From ea5c242f040b1efebc14456dbfcdd30afc319593 Mon Sep 17 00:00:00 2001 From: Rob Garrison Date: Mon, 18 Sep 2017 21:48:00 -0500 Subject: [PATCH] Core: Target header cells for data-column. Fixes #1459 --- js/jquery.tablesorter.js | 58 +++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/js/jquery.tablesorter.js b/js/jquery.tablesorter.js index e47c3ede..b2c2538d 100644 --- a/js/jquery.tablesorter.js +++ b/js/jquery.tablesorter.js @@ -461,9 +461,9 @@ downTarget = null; if ( core !== true ) { $headers.addClass( namespace.slice( 1 ) + '_extra_headers' ); - tmp = $.fn.closest ? $headers.closest( 'table' )[ 0 ] : $headers.parents( 'table' )[ 0 ]; - if ( tmp && tmp.nodeName === 'TABLE' && tmp !== table ) { - $( tmp ).addClass( namespace.slice( 1 ) + '_extra_table' ); + tmp = ts.getClosest( $headers, 'table' ); + if ( tmp.length && tmp[ 0 ].nodeName === 'TABLE' && tmp[ 0 ] !== table ) { + $( tmp[ 0 ] ).addClass( namespace.slice( 1 ) + '_extra_table' ); } } tmp = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' ) @@ -515,8 +515,7 @@ ts.buildCache( c ); } // jQuery v1.2.6 doesn't have closest() - $cell = $.fn.closest ? $( this ).closest( 'th, td' ) : - /TH|TD/.test( this.nodeName ) ? $( this ) : $( this ).parents( 'th, td' ); + $cell = ts.getHeaderCell( $( this ) ); // reference original table headers and find the same cell // don't use $headers or IE8 throws an error - see #987 temp = $headers.index( $cell ); @@ -556,7 +555,7 @@ ''; // 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, + var configHeaders, header, column, template, tmp, $th, $elem = $( elem ); // ignore cell (don't add it to c.$headers) if row has ignoreRow class if ( $elem.parent().hasClass( c.cssIgnoreRow ) ) { return; } @@ -582,7 +581,9 @@ if ( c.onRenderHeader ) { c.onRenderHeader.apply( $elem, [ index, c, c.$table ] ); } - column = parseInt( $elem.attr( 'data-column' ), 10 ); + // data-column stored on th or td only + $th = ts.getHeaderCell( $elem ); + column = parseInt( $th.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 @@ -600,10 +601,9 @@ } // add cell to headerList c.headerList[ index ] = elem; + $elem.addClass( ts.css.header + ' ' + c.cssHeader ); // add to parent in case there are multiple rows - $elem - .addClass( ts.css.header + ' ' + c.cssHeader ) - .parent() + ts.getClosest( $elem, 'tr' ) .addClass( ts.css.headerRow + ' ' + c.cssHeaderRow ) .attr( 'role', 'row' ); // allow keyboard cursor to focus on element @@ -1161,10 +1161,29 @@ } }, + // 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 /TH|TD/.test( $el[0].nodeName ) ? + $el : + $el.parents( 'th, td' ).filter( ':first' ); + }, + // nextSort (optional), lets you disable next sort text setColumnAriaLabel : function( c, $header, nextSort ) { if ( $header.length ) { - var column = parseInt( $header.attr( 'data-column' ), 10 ), + var $th = ts.getHeaderCell( $header ), + // data-column always stored on the th/td + column = parseInt( $th.attr( 'data-column' ), 10 ), vars = c.sortVars[ column ], tmp = $header.hasClass( ts.css.sortAsc ) ? 'sortAsc' : @@ -1322,10 +1341,9 @@ $cell = $( cell ), // update cache - format: function( s, table, cell, cellIndex ) // no closest in jQuery v1.2.6 - tbodyIndex = $tbodies - .index( $.fn.closest ? $cell.closest( 'tbody' ) : $cell.parents( 'tbody' ).filter( ':first' ) ), + tbodyIndex = $tbodies.index( ts.getClosest( $cell, 'tbody' ) ), tbcache = c.cache[ tbodyIndex ], - $row = $.fn.closest ? $cell.closest( 'tr' ) : $cell.parents( 'tr' ).filter( ':first' ); + $row = ts.getClosest( $cell, 'tr' ); cell = $cell[ 0 ]; // in case cell is a jQuery object // tbody may not exist if update is initialized while tbody is removed for processing if ( $tbodies.length && tbodyIndex >= 0 ) { @@ -1380,11 +1398,13 @@ if ( valid ) { $row = $( $row ); c.$tbodies.append( $row ); - } else if ( !$row || + } else if ( + !$row || // row is a jQuery object? !( $row instanceof jQuery ) || // row contained in the table? - ( $.fn.closest ? $row.closest( 'table' )[ 0 ] : $row.parents( 'table' )[ 0 ] ) !== c.table ) { + ( ts.getClosest( $row, 'table' )[ 0 ] !== c.table ) + ) { if ( c.debug ) { console.error( 'addRows method requires (1) a jQuery selector reference to rows that have already ' + 'been added to the table, or (2) row HTML string to be added to a table with only one tbody' ); @@ -1531,10 +1551,10 @@ notMultiSort = !event[ c.sortMultiSortKey ], table = c.table, len = c.$headers.length, - // get current column index - col = parseInt( $( cell ).attr( 'data-column' ), 10 ), + // get current column index; *always* stored on th/td + $th = ts.getHeaderCell( $( cell ) ), + col = parseInt( $th.attr( 'data-column' ), 10 ), order = c.sortVars[ col ].order; - // Only call sortStart if sorting is enabled c.$table.triggerHandler( 'sortStart', table ); // get current column sort order