2 /*jshint onevar: false */
5 wgMonthNames: ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
6 wgMonthNamesShort: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
7 wgDefaultDateFormat: 'dmy',
8 wgSeparatorTransformTable: ['', ''],
9 wgDigitTransformTable: ['', ''],
10 wgContentLanguage: 'en'
13 QUnit.module( 'jquery.tablesorter', QUnit.newMwEnvironment( { config: config } ) );
16 * Create an HTML table from an array of row arrays containing text strings.
17 * First row will be header row. No fancy rowspan/colspan stuff.
19 * @param {String[]} header
20 * @param {String[][]} data
23 function tableCreate( header, data ) {
25 $table = $( '<table class="sortable"><thead></thead><tbody></tbody></table>' ),
26 $thead = $table.find( 'thead' ),
27 $tbody = $table.find( 'tbody' ),
30 $.each( header, function ( i, str ) {
31 var $th = $( '<th>' );
32 $th.text( str ).appendTo( $tr );
34 $tr.appendTo( $thead );
36 for ( i = 0; i < data.length; i++ ) {
37 /*jshint loopfunc: true */
39 $.each( data[i], function ( j, str ) {
40 var $td = $( '<td>' );
41 $td.text( str ).appendTo( $tr );
43 $tr.appendTo( $tbody );
49 * Extract text from table.
51 * @param {jQuery} $table
54 function tableExtract( $table ) {
57 $table.find( 'tbody' ).find( 'tr' ).each( function ( i, tr ) {
59 $( tr ).find( 'td,th' ).each( function ( i, td ) {
60 row.push( $( td ).text() );
68 * Run a table test by building a table with the given data,
69 * running some callback on it, then checking the results.
71 * @param {String} msg text to pass on to qunit for the comparison
72 * @param {String[]} header cols to make the table
73 * @param {String[][]} data rows/cols to make the table
74 * @param {String[][]} expected rows/cols to compare against at end
75 * @param {function($table)} callback something to do with the table before we compare
77 function tableTest( msg, header, data, expected, callback ) {
78 QUnit.test( msg, 1, function ( assert ) {
79 var $table = tableCreate( header, data );
81 // Give caller a chance to set up sorting and manipulate the table.
84 // Table sorting is done synchronously; if it ever needs to change back
85 // to asynchronous, we'll need a timeout or a callback here.
86 var extracted = tableExtract( $table );
87 assert.deepEqual( extracted, expected, msg );
92 * Run a table test by building a table with the given HTML,
93 * running some callback on it, then checking the results.
95 * @param {String} msg text to pass on to qunit for the comparison
96 * @param {String} HTML to make the table
97 * @param {String[][]} expected rows/cols to compare against at end
98 * @param {function($table)} callback something to do with the table before we compare
100 function tableTestHTML( msg, html, expected, callback ) {
101 QUnit.test( msg, 1, function ( assert ) {
102 var $table = $( html );
104 // Give caller a chance to set up sorting and manipulate the table.
108 $table.tablesorter();
109 $table.find( '#sortme' ).click();
112 // Table sorting is done synchronously; if it ever needs to change back
113 // to asynchronous, we'll need a timeout or a callback here.
114 var extracted = tableExtract( $table );
115 assert.deepEqual( extracted, expected, msg );
119 function reversed( arr ) {
121 var arr2 = arr.slice( 0 );
128 // Sample data set using planets named and their radius
129 var header = [ 'Planet' , 'Radius (km)'],
130 mercury = [ 'Mercury', '2439.7' ],
131 venus = [ 'Venus' , '6051.8' ],
132 earth = [ 'Earth' , '6371.0' ],
133 mars = [ 'Mars' , '3390.0' ],
134 jupiter = [ 'Jupiter', '69911' ],
135 saturn = [ 'Saturn' , '58232' ];
138 var planets = [mercury, venus, earth, mars, jupiter, saturn];
139 var ascendingName = [earth, jupiter, mars, mercury, saturn, venus];
140 var ascendingRadius = [mercury, mars, venus, earth, saturn, jupiter];
143 'Basic planet table: sorting initially - ascending by name',
147 function ( $table ) {
148 $table.tablesorter( { sortList: [
154 'Basic planet table: sorting initially - descending by radius',
157 reversed( ascendingRadius ),
158 function ( $table ) {
159 $table.tablesorter( { sortList: [
165 'Basic planet table: ascending by name',
169 function ( $table ) {
170 $table.tablesorter();
171 $table.find( '.headerSort:eq(0)' ).click();
175 'Basic planet table: ascending by name a second time',
179 function ( $table ) {
180 $table.tablesorter();
181 $table.find( '.headerSort:eq(0)' ).click();
185 'Basic planet table: ascending by name (multiple clicks)',
189 function ( $table ) {
190 $table.tablesorter();
191 $table.find( '.headerSort:eq(0)' ).click();
192 $table.find( '.headerSort:eq(1)' ).click();
193 $table.find( '.headerSort:eq(0)' ).click();
197 'Basic planet table: descending by name',
200 reversed( ascendingName ),
201 function ( $table ) {
202 $table.tablesorter();
203 $table.find( '.headerSort:eq(0)' ).click().click();
207 'Basic planet table: ascending radius',
211 function ( $table ) {
212 $table.tablesorter();
213 $table.find( '.headerSort:eq(1)' ).click();
217 'Basic planet table: descending radius',
220 reversed( ascendingRadius ),
221 function ( $table ) {
222 $table.tablesorter();
223 $table.find( '.headerSort:eq(1)' ).click().click();
227 // Sample data set to test multiple column sorting
228 header = [ 'column1' , 'column2'];
236 var initial = [a2, b3, a1, a3, b2, b1];
237 var asc = [a1, a2, a3, b1, b2, b3];
238 var descasc = [b1, b2, b3, a1, a2, a3];
241 'Sorting multiple columns by passing sort list',
245 function ( $table ) {
255 'Sorting multiple columns by programmatically triggering sort()',
259 function ( $table ) {
260 $table.tablesorter();
261 $table.data( 'tablesorter' ).sort(
270 'Reset to initial sorting by triggering sort() without any parameters',
274 function ( $table ) {
281 $table.data( 'tablesorter' ).sort(
287 $table.data( 'tablesorter' ).sort();
291 'Sort via click event after having initialized the tablesorter with initial sorting',
295 function ( $table ) {
297 { sortList: [ { 0: 'asc' }, { 1: 'asc' } ] }
299 $table.find( '.headerSort:eq(0)' ).click();
303 'Multi-sort via click event after having initialized the tablesorter with initial sorting',
307 function ( $table ) {
309 { sortList: [ { 0: 'desc' }, { 1: 'desc' } ] }
311 $table.find( '.headerSort:eq(0)' ).click();
313 // Pretend to click while pressing the multi-sort key
314 var event = $.Event( 'click' );
315 event[$table.data( 'tablesorter' ).config.sortMultiSortKey] = true;
316 $table.find( '.headerSort:eq(1)' ).trigger( event );
319 QUnit.test( 'Reset sorting making table appear unsorted', 3, function ( assert ) {
320 var $table = tableCreate( header, initial );
327 $table.data( 'tablesorter' ).sort( [] );
330 $table.find( 'th.headerSortUp' ).length + $table.find( 'th.headerSortDown' ).length,
332 'No sort specific sort classes addign to header cells'
336 $table.find( 'th' ).first().attr( 'title' ),
337 mw.msg( 'sort-ascending' ),
338 'First header cell has default title'
342 $table.find( 'th' ).first().attr( 'title' ),
343 $table.find( 'th' ).last().attr( 'title' ),
344 'Both header cells\' titles match'
348 // Sorting with colspans
349 header = [ 'column1a' , 'column1b', 'column1c', 'column2' ];
351 aaa1 = [ 'A', 'A', 'A', '1' ],
352 aab5 = [ 'A', 'A', 'B', '5' ],
353 abc3 = [ 'A', 'B', 'C', '3' ],
354 bbc2 = [ 'B', 'B', 'C', '2' ],
355 caa4 = [ 'C', 'A', 'A', '4' ];
356 // initial is already declared above
357 initial = [ aab5, aaa1, abc3, bbc2, caa4 ];
358 tableTest( 'Sorting with colspanned headers: spanned column',
361 [ aaa1, aab5, abc3, bbc2, caa4 ],
362 function ( $table ) {
363 // Make colspanned header for test
364 $table.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
365 $table.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
367 $table.tablesorter();
368 $table.find( '.headerSort:eq(0)' ).click();
371 tableTest( 'Sorting with colspanned headers: sort spanned column twice',
374 [ caa4, bbc2, abc3, aab5, aaa1 ],
375 function ( $table ) {
376 // Make colspanned header for test
377 $table.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
378 $table.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
380 $table.tablesorter();
381 $table.find( '.headerSort:eq(0)' ).click();
382 $table.find( '.headerSort:eq(0)' ).click();
385 tableTest( 'Sorting with colspanned headers: subsequent column',
388 [ aaa1, bbc2, abc3, caa4, aab5 ],
389 function ( $table ) {
390 // Make colspanned header for test
391 $table.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
392 $table.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
394 $table.tablesorter();
395 $table.find( '.headerSort:eq(1)' ).click();
398 tableTest( 'Sorting with colspanned headers: sort subsequent column twice',
401 [ aab5, caa4, abc3, bbc2, aaa1 ],
402 function ( $table ) {
403 // Make colspanned header for test
404 $table.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
405 $table.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
407 $table.tablesorter();
408 $table.find( '.headerSort:eq(1)' ).click();
409 $table.find( '.headerSort:eq(1)' ).click();
416 'Bug 28775: German-style (dmy) short numeric dates',
419 // German-style dates are day-month-year
427 // Sorted by ascending date
434 function ( $table ) {
435 mw.config.set( 'wgDefaultDateFormat', 'dmy' );
436 mw.config.set( 'wgContentLanguage', 'de' );
438 $table.tablesorter();
439 $table.find( '.headerSort:eq(0)' ).click();
444 'Bug 28775: American-style (mdy) short numeric dates',
447 // American-style dates are month-day-year
455 // Sorted by ascending date
462 function ( $table ) {
463 mw.config.set( 'wgDefaultDateFormat', 'mdy' );
465 $table.tablesorter();
466 $table.find( '.headerSort:eq(0)' ).click();
471 // Some randomly generated fake IPs
482 // Sort order should go octet by octet
494 'Bug 17141: IPv4 address sorting',
498 function ( $table ) {
499 $table.tablesorter();
500 $table.find( '.headerSort:eq(0)' ).click();
504 'Bug 17141: IPv4 address sorting (reverse)',
507 reversed( ipv4Sorted ),
508 function ( $table ) {
509 $table.tablesorter();
510 $table.find( '.headerSort:eq(0)' ).click().click();
515 // Some words with Umlauts
526 var umlautWordsSorted = [
527 // Some words with Umlauts
539 'Accented Characters with custom collation',
543 function ( $table ) {
544 mw.config.set( 'tableSorterCollation', {
551 $table.tablesorter();
552 $table.find( '.headerSort:eq(0)' ).click();
556 QUnit.test( 'Rowspan not exploded on init', 1, function ( assert ) {
557 var $table = tableCreate( header, planets );
559 // Modify the table to have a multiple-row-spanning cell:
560 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
561 $table.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
562 // - Set rowspan for 2nd cell of 3rd row to 3.
563 // This covers the removed cell in the 4th and 5th row.
564 $table.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
566 $table.tablesorter();
569 $table.find( 'tr:eq(2) td:eq(1)' ).prop( 'rowSpan' ),
571 'Rowspan not exploded'
575 var planetsRowspan = [
576 [ 'Earth', '6051.8' ],
578 [ 'Mars', '6051.8' ],
583 var planetsRowspanII = [ jupiter, mercury, saturn, venus, [ 'Venus', '6371.0' ], [ 'Venus', '3390.0' ] ];
586 'Basic planet table: same value for multiple rows via rowspan',
590 function ( $table ) {
591 // Modify the table to have a multiple-row-spanning cell:
592 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
593 $table.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
594 // - Set rowspan for 2nd cell of 3rd row to 3.
595 // This covers the removed cell in the 4th and 5th row.
596 $table.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
598 $table.tablesorter();
599 $table.find( '.headerSort:eq(0)' ).click();
603 'Basic planet table: same value for multiple rows via rowspan (sorting initially)',
607 function ( $table ) {
608 // Modify the table to have a multiple-row-spanning cell:
609 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
610 $table.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
611 // - Set rowspan for 2nd cell of 3rd row to 3.
612 // This covers the removed cell in the 4th and 5th row.
613 $table.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
615 $table.tablesorter( { sortList: [
621 'Basic planet table: Same value for multiple rows via rowspan II',
625 function ( $table ) {
626 // Modify the table to have a multiple-row-spanning cell:
627 // - Remove 1st cell of 4th row, and, 1st cell or 5th row.
628 $table.find( 'tr:eq(3) td:eq(0), tr:eq(4) td:eq(0)' ).remove();
629 // - Set rowspan for 1st cell of 3rd row to 3.
630 // This covers the removed cell in the 4th and 5th row.
631 $table.find( 'tr:eq(2) td:eq(0)' ).attr( 'rowspan', '3' );
633 $table.tablesorter();
634 $table.find( '.headerSort:eq(0)' ).click();
638 var complexMDYDates = [
639 // Some words with Umlauts
640 ['January, 19 2010'],
647 var complexMDYSorted = [
651 ['January, 19 2010'],
656 'Complex date parsing I',
660 function ( $table ) {
661 mw.config.set( 'wgDefaultDateFormat', 'mdy' );
663 $table.tablesorter();
664 $table.find( '.headerSort:eq(0)' ).click();
668 var currencyUnsorted = [
678 var currencySorted = [
685 // Comma's sort after dots
686 // Not intentional but test to detect changes
691 'Currency parsing I',
695 function ( $table ) {
696 $table.tablesorter();
697 $table.find( '.headerSort:eq(0)' ).click();
701 var ascendingNameLegacy = ascendingName.slice( 0 );
702 ascendingNameLegacy[4] = ascendingNameLegacy[5];
703 ascendingNameLegacy.pop();
706 'Legacy compat with .sortbottom',
710 function ( $table ) {
711 $table.find( 'tr:last' ).addClass( 'sortbottom' );
712 $table.tablesorter();
713 $table.find( '.headerSort:eq(0)' ).click();
717 QUnit.test( 'Test detection routine', 1, function ( assert ) {
720 '<table class="sortable">' +
721 '<caption>CAPTION</caption>' +
722 '<tr><th>THEAD</th></tr>' +
723 '<tr><td>1</td></tr>' +
724 '<tr class="sortbottom"><td>text</td></tr>' +
727 $table.tablesorter();
728 $table.find( '.headerSort:eq(0)' ).click();
731 $table.data( 'tablesorter' ).config.parsers[0].id,
733 'Correctly detected column content skipping sortbottom'
737 /** FIXME: the diff output is not very readeable. */
738 QUnit.test( 'bug 32047 - caption must be before thead', 1, function ( assert ) {
741 '<table class="sortable">' +
742 '<caption>CAPTION</caption>' +
743 '<tr><th>THEAD</th></tr>' +
744 '<tr><td>A</td></tr>' +
745 '<tr><td>B</td></tr>' +
746 '<tr class="sortbottom"><td>TFOOT</td></tr>' +
749 $table.tablesorter();
752 $table.children().get( 0 ).nodeName,
754 'First element after <thead> must be <caption> (bug 32047)'
758 QUnit.test( 'data-sort-value attribute, when available, should override sorting position', 3, function ( assert ) {
761 // Example 1: All cells except one cell without data-sort-value,
762 // which should be sorted at it's text content value.
764 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
766 '<tr><td>Cheetah</td></tr>' +
767 '<tr><td data-sort-value="Apple">Bird</td></tr>' +
768 '<tr><td data-sort-value="Bananna">Ferret</td></tr>' +
769 '<tr><td data-sort-value="Drupe">Elephant</td></tr>' +
770 '<tr><td data-sort-value="Cherry">Dolphin</td></tr>' +
773 $table.tablesorter().find( '.headerSort:eq(0)' ).click();
776 $table.find( 'tbody > tr' ).each( function ( i, tr ) {
777 $( tr ).find( 'td' ).each( function ( i, td ) {
779 data: $( td ).data( 'sortValue' ),
785 assert.deepEqual( data, [
806 ], 'Order matches expected order (based on data-sort-value attribute values)' );
810 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
812 '<tr><td>D</td></tr>' +
813 '<tr><td data-sort-value="E">A</td></tr>' +
814 '<tr><td>B</td></tr>' +
815 '<tr><td>G</td></tr>' +
816 '<tr><td data-sort-value="F">C</td></tr>' +
819 $table.tablesorter().find( '.headerSort:eq(0)' ).click();
822 $table.find( 'tbody > tr' ).each( function ( i, tr ) {
823 $( tr ).find( 'td' ).each( function ( i, td ) {
825 data: $( td ).data( 'sortValue' ),
831 assert.deepEqual( data, [
852 ], 'Order matches expected order (based on data-sort-value attribute values)' );
854 // Example 3: Test that live changes are used from data-sort-value,
855 // even if they change after the tablesorter is constructed (bug 38152).
857 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
859 '<tr><td>D</td></tr>' +
860 '<tr><td data-sort-value="1">A</td></tr>' +
861 '<tr><td>B</td></tr>' +
862 '<tr><td data-sort-value="2">G</td></tr>' +
863 '<tr><td>C</td></tr>' +
866 // initialize table sorter and sort once
869 .find( '.headerSort:eq(0)' ).click();
871 // Change the sortValue data properties (bug 38152)
873 $table.find( 'td:contains(A)' ).data( 'sortValue', 3 );
875 $table.find( 'td:contains(B)' ).data( 'sortValue', 1 );
876 // - remove data, bring back attribute: 2
877 $table.find( 'td:contains(G)' ).removeData( 'sortValue' );
879 // Now sort again (twice, so it is back at Ascending)
880 $table.find( '.headerSort:eq(0)' ).click();
881 $table.find( '.headerSort:eq(0)' ).click();
884 $table.find( 'tbody > tr' ).each( function ( i, tr ) {
885 $( tr ).find( 'td' ).each( function ( i, td ) {
887 data: $( td ).data( 'sortValue' ),
893 assert.deepEqual( data, [
914 ], 'Order matches expected order, using the current sortValue in $.data()' );
935 tableTest( 'bug 8115: sort numbers with commas (ascending)',
936 ['Numbers'], numbers, numbersAsc,
937 function ( $table ) {
938 $table.tablesorter();
939 $table.find( '.headerSort:eq(0)' ).click();
943 tableTest( 'bug 8115: sort numbers with commas (descending)',
944 ['Numbers'], numbers, reversed( numbersAsc ),
945 function ( $table ) {
946 $table.tablesorter();
947 $table.find( '.headerSort:eq(0)' ).click().click();
950 // TODO add numbers sorting tests for bug 8115 with a different language
952 QUnit.test( 'bug 32888 - Tables inside a tableheader cell', 2, function ( assert ) {
955 '<table class="sortable" id="mw-bug-32888">' +
956 '<tr><th>header<table id="mw-bug-32888-2">' +
957 '<tr><th>1</th><th>2</th></tr>' +
958 '</table></th></tr>' +
959 '<tr><td>A</td></tr>' +
960 '<tr><td>B</td></tr>' +
963 $table.tablesorter();
966 $table.find( '> thead:eq(0) > tr > th.headerSort' ).length,
968 'Child tables inside a headercell should not interfere with sortable headers (bug 32888)'
971 $( '#mw-bug-32888-2' ).find( 'th.headerSort' ).length,
973 'The headers of child tables inside a headercell should not be sortable themselves (bug 32888)'
978 var correctDateSorting1 = [
980 ['05 February 2010'],
984 var correctDateSortingSorted1 = [
991 'Correct date sorting I',
994 correctDateSortingSorted1,
995 function ( $table ) {
996 mw.config.set( 'wgDefaultDateFormat', 'mdy' );
998 $table.tablesorter();
999 $table.find( '.headerSort:eq(0)' ).click();
1003 var correctDateSorting2 = [
1004 ['January 01 2010'],
1005 ['February 05 2010'],
1009 var correctDateSortingSorted2 = [
1010 ['January 01 2010'],
1011 ['January 16 2010'],
1012 ['February 05 2010']
1016 'Correct date sorting II',
1018 correctDateSorting2,
1019 correctDateSortingSorted2,
1020 function ( $table ) {
1021 mw.config.set( 'wgDefaultDateFormat', 'dmy' );
1023 $table.tablesorter();
1024 $table.find( '.headerSort:eq(0)' ).click();
1028 QUnit.test( 'Sorting images using alt text', 1, function ( assert ) {
1030 '<table class="sortable">' +
1031 '<tr><th>THEAD</th></tr>' +
1032 '<tr><td><img alt="2"/></td></tr>' +
1033 '<tr><td>1</td></tr>' +
1036 $table.tablesorter().find( '.headerSort:eq(0)' ).click();
1039 $table.find( 'td' ).first().text(),
1041 'Applied correct sorting order'
1045 QUnit.test( 'Sorting images using alt text (complex)', 1, function ( assert ) {
1047 '<table class="sortable">' +
1048 '<tr><th>THEAD</th></tr>' +
1049 '<tr><td><img alt="D" />A</td></tr>' +
1050 '<tr><td>CC</td></tr>' +
1051 '<tr><td><a><img alt="A" /></a>F</tr>' +
1052 '<tr><td><img alt="A" /><strong>E</strong></tr>' +
1053 '<tr><td><strong><img alt="A" />D</strong></tr>' +
1054 '<tr><td><img alt="A" />C</tr>' +
1057 $table.tablesorter().find( '.headerSort:eq(0)' ).click();
1060 $table.find( 'td' ).text(),
1062 'Applied correct sorting order'
1066 QUnit.test( 'Sorting images using alt text (with format autodetection)', 1, function ( assert ) {
1068 '<table class="sortable">' +
1069 '<tr><th>THEAD</th></tr>' +
1070 '<tr><td><img alt="1" />7</td></tr>' +
1071 '<tr><td>1<img alt="6" /></td></tr>' +
1072 '<tr><td>5</td></tr>' +
1073 '<tr><td>4</td></tr>' +
1076 $table.tablesorter().find( '.headerSort:eq(0)' ).click();
1079 $table.find( 'td' ).text(),
1081 'Applied correct sorting order'
1085 QUnit.test( 'bug 38911 - The row with the largest amount of columns should receive the sort indicators', 3, function ( assert ) {
1087 '<table class="sortable">' +
1089 '<tr><th rowspan="2" id="A1">A1</th><th colspan="2">B2a</th></tr>' +
1090 '<tr><th id="B2b">B2b</th><th id="C2b">C2b</th></tr>' +
1092 '<tr><td>A</td><td>Aa</td><td>Ab</td></tr>' +
1093 '<tr><td>B</td><td>Ba</td><td>Bb</td></tr>' +
1096 $table.tablesorter();
1099 $table.find( '#A1' ).attr( 'class' ),
1101 'The first column of the first row should be sortable'
1104 $table.find( '#B2b' ).attr( 'class' ),
1106 'The th element of the 2nd row of the 2nd column should be sortable'
1109 $table.find( '#C2b' ).attr( 'class' ),
1111 'The th element of the 2nd row of the 3rd column should be sortable'
1115 QUnit.test( 'rowspans in table headers should prefer the last row when rows are equal in length', 2, function ( assert ) {
1117 '<table class="sortable">' +
1119 '<tr><th rowspan="2" id="A1">A1</th><th>B2a</th></tr>' +
1120 '<tr><th id="B2b">B2b</th></tr>' +
1122 '<tr><td>A</td><td>Aa</td></tr>' +
1123 '<tr><td>B</td><td>Ba</td></tr>' +
1126 $table.tablesorter();
1129 $table.find( '#A1' ).attr( 'class' ),
1131 'The first column of the first row should be sortable'
1134 $table.find( '#B2b' ).attr( 'class' ),
1136 'The th element of the 2nd row of the 2nd column should be sortable'
1140 // bug 41889 - exploding rowspans in more complex cases
1142 'Rowspan exploding with row headers',
1143 '<table class="sortable">' +
1144 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th></tr></thead>' +
1146 '<tr><td>1</td><th rowspan="2">foo</th><td rowspan="2">bar</td><td>baz</td></tr>' +
1147 '<tr><td>2</td><td>baz</td></tr>' +
1150 [ '1', 'foo', 'bar', 'baz' ],
1151 [ '2', 'foo', 'bar', 'baz' ]
1156 'Rowspan exploding with colspanned cells',
1157 '<table class="sortable">' +
1158 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th></tr></thead>' +
1160 '<tr><td>1</td><td>foo</td><td>bar</td><td rowspan="2">baz</td></tr>' +
1161 '<tr><td>2</td><td colspan="2">foobar</td></tr>' +
1164 [ '1', 'foo', 'bar', 'baz' ],
1165 [ '2', 'foobar', 'baz' ]
1170 'Rowspan exploding with colspanned cells (2)',
1171 '<table class="sortable">' +
1172 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th><th>quux</th></tr></thead>' +
1174 '<tr><td>1</td><td>foo</td><td>bar</td><td rowspan="2">baz</td><td>quux</td></tr>' +
1175 '<tr><td>2</td><td colspan="2">foobar</td><td>quux</td></tr>' +
1178 [ '1', 'foo', 'bar', 'baz', 'quux' ],
1179 [ '2', 'foobar', 'baz', 'quux' ]
1184 'Rowspan exploding with rightmost rows spanning most',
1185 '<table class="sortable">' +
1186 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th></tr></thead>' +
1188 '<tr><td>1</td><td rowspan="2">foo</td><td rowspan="4">bar</td></tr>' +
1189 '<tr><td>2</td></tr>' +
1190 '<tr><td>3</td><td rowspan="2">foo</td></tr>' +
1191 '<tr><td>4</td></tr>' +
1194 [ '1', 'foo', 'bar' ],
1195 [ '2', 'foo', 'bar' ],
1196 [ '3', 'foo', 'bar' ],
1197 [ '4', 'foo', 'bar' ]
1202 'Rowspan exploding with rightmost rows spanning most (2)',
1203 '<table class="sortable">' +
1204 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th></tr></thead>' +
1206 '<tr><td>1</td><td rowspan="2">foo</td><td rowspan="4">bar</td><td>baz</td></tr>' +
1207 '<tr><td>2</td><td>baz</td></tr>' +
1208 '<tr><td>3</td><td rowspan="2">foo</td><td>baz</td></tr>' +
1209 '<tr><td>4</td><td>baz</td></tr>' +
1212 [ '1', 'foo', 'bar', 'baz' ],
1213 [ '2', 'foo', 'bar', 'baz' ],
1214 [ '3', 'foo', 'bar', 'baz' ],
1215 [ '4', 'foo', 'bar', 'baz' ]
1220 'Rowspan exploding with row-and-colspanned cells',
1221 '<table class="sortable">' +
1222 '<thead><tr><th id="sortme">n</th><th>foo1</th><th>foo2</th><th>bar</th><th>baz</th></tr></thead>' +
1224 '<tr><td>1</td><td rowspan="2">foo1</td><td rowspan="2">foo2</td><td rowspan="4">bar</td><td>baz</td></tr>' +
1225 '<tr><td>2</td><td>baz</td></tr>' +
1226 '<tr><td>3</td><td colspan="2" rowspan="2">foo</td><td>baz</td></tr>' +
1227 '<tr><td>4</td><td>baz</td></tr>' +
1230 [ '1', 'foo1', 'foo2', 'bar', 'baz' ],
1231 [ '2', 'foo1', 'foo2', 'bar', 'baz' ],
1232 [ '3', 'foo', 'bar', 'baz' ],
1233 [ '4', 'foo', 'bar', 'baz' ]
1238 'Rowspan exploding with uneven rowspan layout',
1239 '<table class="sortable">' +
1240 '<thead><tr><th id="sortme">n</th><th>foo1</th><th>foo2</th><th>foo3</th><th>bar</th><th>baz</th></tr></thead>' +
1242 '<tr><td>1</td><td rowspan="2">foo1</td><td rowspan="2">foo2</td><td rowspan="2">foo3</td><td>bar</td><td>baz</td></tr>' +
1243 '<tr><td>2</td><td rowspan="3">bar</td><td>baz</td></tr>' +
1244 '<tr><td>3</td><td rowspan="2">foo1</td><td rowspan="2">foo2</td><td rowspan="2">foo3</td><td>baz</td></tr>' +
1245 '<tr><td>4</td><td>baz</td></tr>' +
1248 [ '1', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ],
1249 [ '2', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ],
1250 [ '3', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ],
1251 [ '4', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ]
1255 }( jQuery, mediaWiki ) );