From: MatmaRex Date: Fri, 9 Nov 2012 16:47:29 +0000 (+0100) Subject: (bug 41886) make $.tablesorter support headers with colspan X-Git-Tag: 1.31.0-rc.0~21524^2 X-Git-Url: http://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/exercices/?a=commitdiff_plain;h=99a53dd8e40e7ea416427ba585bcdbcaada955a4;p=lhc%2Fweb%2Fwiklou.git (bug 41886) make $.tablesorter support headers with colspan Previously, if a header had colspan set, all headers after it would sort wrong columns (shifted by the cumulating colspans). This fixes the issue, from now on every header sorts on all columns it spans over (using the multi-column sorting funcitonality already present in $.tablesorter). Change-Id: I89766c9640b83ca38f41d698d1ef052a9e3f68d3 --- diff --git a/resources/jquery/jquery.tablesorter.js b/resources/jquery/jquery.tablesorter.js index 7a1bd279ad..6297f9a745 100644 --- a/resources/jquery/jquery.tablesorter.js +++ b/resources/jquery/jquery.tablesorter.js @@ -325,20 +325,14 @@ return false; } - function setHeadersCss( table, $headers, list, css, msg ) { + function setHeadersCss( table, $headers, list, css, msg, columnToHeader ) { // Remove all header information and reset titles to default message $headers.removeClass( css[0] ).removeClass( css[1] ).attr( 'title', msg[1] ); - var h = []; - $headers.each( function () { - if ( !this.sortDisabled ) { - h[this.column] = $( this ); - } - } ); - - var l = list.length; - for ( var i = 0; i < l; i++ ) { - h[ list[i][0] ].addClass( css[ list[i][1] ] ).attr( 'title', msg[ list[i][1] ] ); + for ( var i = 0; i < list.length; i++ ) { + $headers.eq( columnToHeader[ list[i][0] ] ) + .addClass( css[ list[i][1] ] ) + .attr( 'title', msg[ list[i][1] ] ); } } @@ -545,6 +539,7 @@ return $tables.each( function ( i, table ) { // Declare and cache. var $headers, cache, config, + headerToColumns, columnToHeader, colspanOffset, $table = $( table ), firstTime = true; @@ -612,6 +607,22 @@ table.config.parsers = buildParserCache( table, $headers ); } + // as each header can span over multiple columns (using colspan=N), + // we have to bidirectionally map headers to their columns and columns to their headers + headerToColumns = []; + columnToHeader = []; + colspanOffset = 0; + $headers.each( function ( headerIndex ) { + var columns = []; + for ( var i = 0; i < this.colSpan; i++ ) { + columnToHeader[ colspanOffset + i ] = headerIndex; + columns.push( colspanOffset + i ); + } + + headerToColumns[ headerIndex ] = columns; + colspanOffset += this.colSpan; + } ); + // Apply event handling to headers // this is too big, perhaps break it out? $headers.filter( ':not(.unsortable)' ).click( function ( e ) { @@ -635,43 +646,48 @@ var totalRows = ( $table[0].tBodies[0] && $table[0].tBodies[0].rows.length ) || 0; if ( !table.sortDisabled && totalRows > 0 ) { - - // Get current column index - var i = this.column; - // Get current column sort order this.order = this.count % 2; this.count++; - // User only wants to sort on one column - if ( !e[config.sortMultiSortKey] ) { - // Flush the sort list - config.sortList = []; - // Add column to sort list - config.sortList.push( [i, this.order] ); + var cell = this; + // Get current column index + var columns = headerToColumns[this.column]; + var newSortList = $.map( columns, function (c) { + // jQuery "helpfully" flattens the arrays... + return [[c, cell.order]]; + }); + // Index of first column belonging to this header + var i = columns[0]; - // Multi column sorting + if ( !e[config.sortMultiSortKey] ) { + // User only wants to sort on one column set + // Flush the sort list and add new columns + config.sortList = newSortList; } else { - // The user has clicked on an already sorted column. + // Multi column sorting + // It is not possible for one column to belong to multiple headers, + // so this is okay - we don't need to check for every value in the columns array if ( isValueInArray( i, config.sortList ) ) { + // The user has clicked on an already sorted column. // Reverse the sorting direction for all tables. for ( var j = 0; j < config.sortList.length; j++ ) { var s = config.sortList[j], o = config.headerList[s[0]]; - if ( s[0] === i ) { + if ( isValueInArray( s[0], newSortList ) ) { o.count = s[1]; o.count++; s[1] = o.count % 2; } } } else { - // Add column to sort list array - config.sortList.push( [i, this.order] ); + // Add columns to sort list array + config.sortList = config.sortList.concat( newSortList ); } } // Set CSS for headers - setHeadersCss( $table[0], $headers, config.sortList, sortCSS, sortMsg ); + setHeadersCss( $table[0], $headers, config.sortList, sortCSS, sortMsg, columnToHeader ); appendToTable( $table[0], multisort( $table[0], config.sortList, cache ) ); @@ -714,7 +730,7 @@ cache = buildCache( table ); // set css for headers - setHeadersCss( table, $headers, sortList, sortCSS, sortMsg ); + setHeadersCss( table, $headers, sortList, sortCSS, sortMsg, columnToHeader ); // sort the table and append it to the dom appendToTable( table, multisort( table, sortList, cache ) ); diff --git a/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js b/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js index ef71dd0eb4..0000f0c34f 100644 --- a/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js +++ b/tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js @@ -255,6 +255,43 @@ ); } ); + // Sorting with colspans + header = [ 'column1a' , 'column1b', 'column1c', 'column2' ]; + var + aaa1 = [ 'A', 'A', 'A', '1' ], + aab5 = [ 'A', 'A', 'B', '5' ], + abc3 = [ 'A', 'B', 'C', '3' ], + bbc2 = [ 'B', 'B', 'C', '2' ], + caa4 = [ 'C', 'A', 'A', '4' ]; + // initial is already declared above + initial = [ aab5, aaa1, abc3, bbc2, caa4 ]; + tableTest( 'Sorting with colspanned headers: spanned column', + header, + initial, + [ aaa1, aab5, abc3, bbc2, caa4 ], + function ( $table ) { + // Make colspanned header for test + $table.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove(); + $table.find( 'tr:eq(0) th:eq(0)' ).prop( 'colspan', '3' ); + + $table.tablesorter(); + $table.find( '.headerSort:eq(0)' ).click(); + } + ); + tableTest( 'Sorting with colspanned headers: subsequent column', + header, + initial, + [ aaa1, bbc2, abc3, caa4, aab5 ], + function ( $table ) { + // Make colspanned header for test + $table.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove(); + $table.find( 'tr:eq(0) th:eq(0)' ).prop( 'colspan', '3' ); + + $table.tablesorter(); + $table.find( '.headerSort:eq(1)' ).click(); + } + ); + // Regression tests! tableTest( 'Bug 28775: German-style (dmy) short numeric dates',