From b5dc8f2a3e382beb882fc70e587e6bbcd7a950c9 Mon Sep 17 00:00:00 2001 From: Rob Garrison Date: Wed, 18 Oct 2017 06:41:21 -0500 Subject: [PATCH] Core: Fix non-typical use of selectorHeaders. See #1459 --- js/jquery.tablesorter.js | 52 ++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/js/jquery.tablesorter.js b/js/jquery.tablesorter.js index e530077f..ef611620 100644 --- a/js/jquery.tablesorter.js +++ b/js/jquery.tablesorter.js @@ -514,8 +514,7 @@ if ( c.delayInit && ts.isEmptyObject( c.cache ) ) { ts.buildCache( c ); } - // jQuery v1.2.6 doesn't have closest() - $cell = ts.getHeaderCell( $( this ) ); + $cell = ts.getClosest( $( this ), '.' + ts.css.header ); // reference original table headers and find the same cell // don't use $headers or IE8 throws an error - see #987 temp = $headers.index( $cell ); @@ -555,10 +554,15 @@ ''; // redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683 c.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) { - var configHeaders, header, column, template, tmp, $th, + var configHeaders, header, column, template, tmp, $elem = $( elem ); // ignore cell (don't add it to c.$headers) if row has ignoreRow class - if ( $elem.parent().hasClass( c.cssIgnoreRow ) ) { return; } + if ( ts.getClosest( $elem, 'tr' ).hasClass( c.cssIgnoreRow ) ) { return; } + // transfer data-column to element if not th/td - #1459 + if ( !/(th|td)/i.test( elem.nodeName ) ) { + tmp = ts.getClosest( $elem, 'th, td' ); + $elem.attr( 'data-column', tmp.attr( 'data-column' ) ); + } // make sure to get header cell & not column indexed cell configHeaders = ts.getColumnData( c.table, c.headers, index, true ); // save original header content @@ -581,9 +585,7 @@ if ( c.onRenderHeader ) { c.onRenderHeader.apply( $elem, [ index, c, c.$table ] ); } - // data-column stored on th or td only - $th = ts.getHeaderCell( $elem ); - column = parseInt( $th.attr( 'data-column' ), 10 ); + column = parseInt( $elem.attr( 'data-column' ), 10 ); elem.column = column; tmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder ); // this may get updated numerous times if there are multiple rows @@ -619,6 +621,7 @@ if ( ts.isEmptyObject( c.sortVars[ indx ] ) ) { c.sortVars[ indx ] = {}; } + // Use c.$headers.parent() in case selectorHeaders doesn't point to the th/td $temp = c.$headers.filter( '[data-column="' + indx + '"]' ); // target sortable column cells, unless there are none, then use non-sortable cells // .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6 @@ -1120,7 +1123,7 @@ var include = true, $el = c.$headers.eq( i ), col = parseInt( $el.attr( 'data-column' ), 10 ), - end = col + c.$headers[ i ].colSpan; + end = col + ts.getClosest( $el, 'th, td' )[0].colSpan; for ( ; col < end; col++ ) { include = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false; } @@ -1161,29 +1164,20 @@ } }, - // This function does NOT return closest if the $el matches the selector getClosest : function( $el, selector ) { - return $.fn.closest ? - $el.closest( selector ) : - $el.parents( selector ).filter( ':first' ); - }, - - getHeaderCell : function( $el ) { // jQuery v1.2.6 doesn't have closest() if ( $.fn.closest ) { - return $el.closest( 'th, td' ); + return $el.closest( selector ); } - return /TH|TD/.test( $el[0].nodeName ) ? + return $el.is( selector ) ? $el : - $el.parents( 'th, td' ).filter( ':first' ); + $el.parents( selector ).filter( ':first' ); }, // nextSort (optional), lets you disable next sort text setColumnAriaLabel : function( c, $header, nextSort ) { if ( $header.length ) { - var $th = ts.getHeaderCell( $header ), - // data-column always stored on the th/td - column = parseInt( $th.attr( 'data-column' ), 10 ), + var column = parseInt( $header.attr( 'data-column' ), 10 ), vars = c.sortVars[ column ], tmp = $header.hasClass( ts.css.sortAsc ) ? 'sortAsc' : @@ -1551,10 +1545,10 @@ notMultiSort = !event[ c.sortMultiSortKey ], table = c.table, len = c.$headers.length, - // get current column index; *always* stored on th/td - $th = ts.getHeaderCell( $( cell ) ), - col = parseInt( $th.attr( 'data-column' ), 10 ), + th = ts.getClosest( $( cell ), 'th, td' ), + col = parseInt( th.attr( 'data-column' ), 10 ), order = c.sortVars[ col ].order; + th = th[0]; // Only call sortStart if sorting is enabled c.$table.triggerHandler( 'sortStart', table ); // get current column sort order @@ -1589,8 +1583,8 @@ if ( dir < 2 ) { c.sortList[ c.sortList.length ] = [ col, dir ]; // add other columns if header spans across multiple - if ( cell.colSpan > 1 ) { - for ( indx = 1; indx < cell.colSpan; indx++ ) { + if ( th.colSpan > 1 ) { + for ( indx = 1; indx < th.colSpan; indx++ ) { c.sortList[ c.sortList.length ] = [ col + indx, dir ]; // update count on columns in colSpan c.sortVars[ col + indx ].count = $.inArray( dir, order ); @@ -1622,8 +1616,8 @@ if ( dir < 2 ) { c.sortList[ c.sortList.length ] = [ col, dir ]; // add other columns if header spans across multiple - if ( cell.colSpan > 1 ) { - for ( indx = 1; indx < cell.colSpan; indx++ ) { + if ( th.colSpan > 1 ) { + for ( indx = 1; indx < th.colSpan; indx++ ) { c.sortList[ c.sortList.length ] = [ col + indx, dir ]; // update count on columns in colSpan c.sortVars[ col + indx ].count = $.inArray( dir, order ); @@ -2392,7 +2386,7 @@ $cells = ( $headers || c.$headers ), // c.$headerIndexed is not defined initially $cell = c.$headerIndexed && c.$headerIndexed[ indx ] || - $cells.filter( '[data-column="' + indx + '"]:last' ); + $cells.find( '[data-column="' + indx + '"]:last' ); if ( typeof obj[ indx ] !== 'undefined' ) { return getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ]; }