11 simple
= [a2
, b3
, a1
, a3
, b2
, b1
],
12 simpleAsc
= [a1
, a2
, a3
, b1
, b2
, b3
],
13 simpleDescasc
= [b1
, b2
, b3
, a1
, a2
, a3
],
16 aaa1
= [ 'A', 'A', 'A', '1' ],
17 aab5
= [ 'A', 'A', 'B', '5' ],
18 abc3
= [ 'A', 'B', 'C', '3' ],
19 bbc2
= [ 'B', 'B', 'C', '2' ],
20 caa4
= [ 'C', 'A', 'A', '4' ],
21 colspanInitial
= [ aab5
, aaa1
, abc3
, bbc2
, caa4
],
24 mercury
= [ 'Mercury', '2439.7' ],
25 venus
= [ 'Venus', '6051.8' ],
26 earth
= [ 'Earth', '6371.0' ],
27 mars
= [ 'Mars', '3390.0' ],
28 jupiter
= [ 'Jupiter', '69911' ],
29 saturn
= [ 'Saturn', '58232' ],
30 planets
= [mercury
, venus
, earth
, mars
, jupiter
, saturn
],
31 planetsAscName
= [earth
, jupiter
, mars
, mercury
, saturn
, venus
],
32 planetsAscRadius
= [mercury
, mars
, venus
, earth
, saturn
, jupiter
],
39 // Some randomly generated fake IPs
50 // Sort order should go octet by octet
114 // Comma's sort after dots
115 // Not intentional but test to detect changes
136 correctDateSorting1
= [
138 ['05 February 2010'],
141 correctDateSortingSorted1
= [
147 correctDateSorting2
= [
149 ['February 05 2010'],
152 correctDateSortingSorted2
= [
158 QUnit
.module( 'jquery.tablesorter', QUnit
.newMwEnvironment( {
160 this.liveMonths
= mw
.language
.months
;
161 mw
.language
.months
= {
163 'names': ['january', 'february', 'march', 'april', 'may_long', 'june',
164 'july', 'august', 'september', 'october', 'november', 'december'],
165 'genitive': ['january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
166 'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen', 'december-gen'],
167 'abbrev': ['jan', 'feb', 'mar', 'apr', 'may', 'jun',
168 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
170 'names': ['January', 'February', 'March', 'April', 'May', 'June',
171 'July', 'August', 'September', 'October', 'November', 'December'],
172 'genitive': ['January', 'February', 'March', 'April', 'May', 'June',
173 'July', 'August', 'September', 'October', 'November', 'December'],
174 'abbrev': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
175 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
178 teardown: function () {
179 mw
.language
.months
= this.liveMonths
;
182 wgDefaultDateFormat
: 'dmy',
183 wgSeparatorTransformTable
: ['', ''],
184 wgDigitTransformTable
: ['', ''],
185 wgContentLanguage
: 'en'
190 * Create an HTML table from an array of row arrays containing text strings.
191 * First row will be header row. No fancy rowspan/colspan stuff.
193 * @param {String[]} header
194 * @param {String[][]} data
197 function tableCreate( header
, data
) {
199 $table
= $( '<table class="sortable"><thead></thead><tbody></tbody></table>' ),
200 $thead
= $table
.find( 'thead' ),
201 $tbody
= $table
.find( 'tbody' ),
204 $.each( header
, function ( i
, str
) {
205 var $th
= $( '<th>' );
206 $th
.text( str
).appendTo( $tr
);
208 $tr
.appendTo( $thead
);
210 for ( i
= 0; i
< data
.length
; i
++ ) {
211 /*jshint loopfunc: true */
213 $.each( data
[i
], function ( j
, str
) {
214 var $td
= $( '<td>' );
215 $td
.text( str
).appendTo( $tr
);
217 $tr
.appendTo( $tbody
);
223 * Extract text from table.
225 * @param {jQuery} $table
228 function tableExtract( $table
) {
231 $table
.find( 'tbody' ).find( 'tr' ).each( function ( i
, tr
) {
233 $( tr
).find( 'td,th' ).each( function ( i
, td
) {
234 row
.push( $( td
).text() );
242 * Run a table test by building a table with the given data,
243 * running some callback on it, then checking the results.
245 * @param {String} msg text to pass on to qunit for the comparison
246 * @param {String[]} header cols to make the table
247 * @param {String[][]} data rows/cols to make the table
248 * @param {String[][]} expected rows/cols to compare against at end
249 * @param {function($table)} callback something to do with the table before we compare
251 function tableTest( msg
, header
, data
, expected
, callback
) {
252 QUnit
.test( msg
, 1, function ( assert
) {
254 $table
= tableCreate( header
, data
);
256 // Give caller a chance to set up sorting and manipulate the table.
259 // Table sorting is done synchronously; if it ever needs to change back
260 // to asynchronous, we'll need a timeout or a callback here.
261 extracted
= tableExtract( $table
);
262 assert
.deepEqual( extracted
, expected
, msg
);
267 * Run a table test by building a table with the given HTML,
268 * running some callback on it, then checking the results.
270 * @param {String} msg text to pass on to qunit for the comparison
271 * @param {String} HTML to make the table
272 * @param {String[][]} expected rows/cols to compare against at end
273 * @param {function($table)} callback something to do with the table before we compare
275 function tableTestHTML( msg
, html
, expected
, callback
) {
276 QUnit
.test( msg
, 1, function ( assert
) {
280 // Give caller a chance to set up sorting and manipulate the table.
284 $table
.tablesorter();
285 $table
.find( '#sortme' ).click();
288 // Table sorting is done synchronously; if it ever needs to change back
289 // to asynchronous, we'll need a timeout or a callback here.
290 extracted
= tableExtract( $table
);
291 assert
.deepEqual( extracted
, expected
, msg
);
295 function reversed( arr
) {
297 var arr2
= arr
.slice( 0 );
304 // Sample data set using planets named and their radius
305 header
= [ 'Planet', 'Radius (km)'];
308 'Basic planet table: sorting initially - ascending by name',
312 function ( $table
) {
313 $table
.tablesorter( { sortList
: [
319 'Basic planet table: sorting initially - descending by radius',
322 reversed( planetsAscRadius
),
323 function ( $table
) {
324 $table
.tablesorter( { sortList
: [
330 'Basic planet table: ascending by name',
334 function ( $table
) {
335 $table
.tablesorter();
336 $table
.find( '.headerSort:eq(0)' ).click();
340 'Basic planet table: ascending by name a second time',
344 function ( $table
) {
345 $table
.tablesorter();
346 $table
.find( '.headerSort:eq(0)' ).click();
350 'Basic planet table: ascending by name (multiple clicks)',
354 function ( $table
) {
355 $table
.tablesorter();
356 $table
.find( '.headerSort:eq(0)' ).click();
357 $table
.find( '.headerSort:eq(1)' ).click();
358 $table
.find( '.headerSort:eq(0)' ).click();
362 'Basic planet table: descending by name',
365 reversed( planetsAscName
),
366 function ( $table
) {
367 $table
.tablesorter();
368 $table
.find( '.headerSort:eq(0)' ).click().click();
372 'Basic planet table: ascending radius',
376 function ( $table
) {
377 $table
.tablesorter();
378 $table
.find( '.headerSort:eq(1)' ).click();
382 'Basic planet table: descending radius',
385 reversed( planetsAscRadius
),
386 function ( $table
) {
387 $table
.tablesorter();
388 $table
.find( '.headerSort:eq(1)' ).click().click();
392 header
= [ 'column1', 'column2' ];
395 'Sorting multiple columns by passing sort list',
399 function ( $table
) {
409 'Sorting multiple columns by programmatically triggering sort()',
413 function ( $table
) {
414 $table
.tablesorter();
415 $table
.data( 'tablesorter' ).sort(
424 'Reset to initial sorting by triggering sort() without any parameters',
428 function ( $table
) {
435 $table
.data( 'tablesorter' ).sort(
441 $table
.data( 'tablesorter' ).sort();
445 'Sort via click event after having initialized the tablesorter with initial sorting',
449 function ( $table
) {
451 { sortList
: [ { 0: 'asc' }, { 1: 'asc' } ] }
453 $table
.find( '.headerSort:eq(0)' ).click();
457 'Multi-sort via click event after having initialized the tablesorter with initial sorting',
461 function ( $table
) {
463 { sortList
: [ { 0: 'desc' }, { 1: 'desc' } ] }
465 $table
.find( '.headerSort:eq(0)' ).click();
467 // Pretend to click while pressing the multi-sort key
468 var event
= $.Event( 'click' );
469 event
[$table
.data( 'tablesorter' ).config
.sortMultiSortKey
] = true;
470 $table
.find( '.headerSort:eq(1)' ).trigger( event
);
473 QUnit
.test( 'Reset sorting making table appear unsorted', 3, function ( assert
) {
474 var $table
= tableCreate( header
, simple
);
481 $table
.data( 'tablesorter' ).sort( [] );
484 $table
.find( 'th.headerSortUp' ).length
+ $table
.find( 'th.headerSortDown' ).length
,
486 'No sort specific sort classes addign to header cells'
490 $table
.find( 'th' ).first().attr( 'title' ),
491 mw
.msg( 'sort-ascending' ),
492 'First header cell has default title'
496 $table
.find( 'th' ).first().attr( 'title' ),
497 $table
.find( 'th' ).last().attr( 'title' ),
498 'Both header cells\' titles match'
502 // Sorting with colspans
503 header
= [ 'column1a', 'column1b', 'column1c', 'column2' ];
505 tableTest( 'Sorting with colspanned headers: spanned column',
508 [ aaa1
, aab5
, abc3
, bbc2
, caa4
],
509 function ( $table
) {
510 // Make colspanned header for test
511 $table
.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
512 $table
.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
514 $table
.tablesorter();
515 $table
.find( '.headerSort:eq(0)' ).click();
518 tableTest( 'Sorting with colspanned headers: sort spanned column twice',
521 [ caa4
, bbc2
, abc3
, aab5
, aaa1
],
522 function ( $table
) {
523 // Make colspanned header for test
524 $table
.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
525 $table
.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
527 $table
.tablesorter();
528 $table
.find( '.headerSort:eq(0)' ).click();
529 $table
.find( '.headerSort:eq(0)' ).click();
532 tableTest( 'Sorting with colspanned headers: subsequent column',
535 [ aaa1
, bbc2
, abc3
, caa4
, aab5
],
536 function ( $table
) {
537 // Make colspanned header for test
538 $table
.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
539 $table
.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
541 $table
.tablesorter();
542 $table
.find( '.headerSort:eq(1)' ).click();
545 tableTest( 'Sorting with colspanned headers: sort subsequent column twice',
548 [ aab5
, caa4
, abc3
, bbc2
, aaa1
],
549 function ( $table
) {
550 // Make colspanned header for test
551 $table
.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
552 $table
.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
554 $table
.tablesorter();
555 $table
.find( '.headerSort:eq(1)' ).click();
556 $table
.find( '.headerSort:eq(1)' ).click();
561 'Basic planet table: one unsortable column',
565 function ( $table
) {
566 $table
.find( 'tr:eq(0) > th:eq(0)' ).addClass( 'unsortable' );
568 $table
.tablesorter();
569 $table
.find( 'tr:eq(0) > th:eq(0)' ).click();
575 'Bug 28775: German-style (dmy) short numeric dates',
578 // German-style dates are day-month-year
586 // Sorted by ascending date
593 function ( $table
) {
594 mw
.config
.set( 'wgDefaultDateFormat', 'dmy' );
595 mw
.config
.set( 'wgContentLanguage', 'de' );
597 $table
.tablesorter();
598 $table
.find( '.headerSort:eq(0)' ).click();
603 'Bug 28775: American-style (mdy) short numeric dates',
606 // American-style dates are month-day-year
614 // Sorted by ascending date
621 function ( $table
) {
622 mw
.config
.set( 'wgDefaultDateFormat', 'mdy' );
624 $table
.tablesorter();
625 $table
.find( '.headerSort:eq(0)' ).click();
630 'Bug 17141: IPv4 address sorting',
634 function ( $table
) {
635 $table
.tablesorter();
636 $table
.find( '.headerSort:eq(0)' ).click();
640 'Bug 17141: IPv4 address sorting (reverse)',
643 reversed( ipv4Sorted
),
644 function ( $table
) {
645 $table
.tablesorter();
646 $table
.find( '.headerSort:eq(0)' ).click().click();
651 'Accented Characters with custom collation',
655 function ( $table
) {
656 mw
.config
.set( 'tableSorterCollation', {
663 $table
.tablesorter();
664 $table
.find( '.headerSort:eq(0)' ).click();
668 QUnit
.test( 'Rowspan not exploded on init', 1, function ( assert
) {
669 var $table
= tableCreate( header
, planets
);
671 // Modify the table to have a multiple-row-spanning cell:
672 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
673 $table
.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
674 // - Set rowspan for 2nd cell of 3rd row to 3.
675 // This covers the removed cell in the 4th and 5th row.
676 $table
.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
678 $table
.tablesorter();
681 $table
.find( 'tr:eq(2) td:eq(1)' ).prop( 'rowSpan' ),
683 'Rowspan not exploded'
688 [ 'Earth', '6051.8' ],
690 [ 'Mars', '6051.8' ],
695 planetsRowspanII
= [ jupiter
, mercury
, saturn
, venus
, [ 'Venus', '6371.0' ], [ 'Venus', '3390.0' ] ];
698 'Basic planet table: same value for multiple rows via rowspan',
702 function ( $table
) {
703 // Modify the table to have a multiple-row-spanning cell:
704 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
705 $table
.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
706 // - Set rowspan for 2nd cell of 3rd row to 3.
707 // This covers the removed cell in the 4th and 5th row.
708 $table
.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
710 $table
.tablesorter();
711 $table
.find( '.headerSort:eq(0)' ).click();
715 'Basic planet table: same value for multiple rows via rowspan (sorting initially)',
719 function ( $table
) {
720 // Modify the table to have a multiple-row-spanning cell:
721 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
722 $table
.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
723 // - Set rowspan for 2nd cell of 3rd row to 3.
724 // This covers the removed cell in the 4th and 5th row.
725 $table
.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
727 $table
.tablesorter( { sortList
: [
733 'Basic planet table: Same value for multiple rows via rowspan II',
737 function ( $table
) {
738 // Modify the table to have a multiple-row-spanning cell:
739 // - Remove 1st cell of 4th row, and, 1st cell or 5th row.
740 $table
.find( 'tr:eq(3) td:eq(0), tr:eq(4) td:eq(0)' ).remove();
741 // - Set rowspan for 1st cell of 3rd row to 3.
742 // This covers the removed cell in the 4th and 5th row.
743 $table
.find( 'tr:eq(2) td:eq(0)' ).attr( 'rowspan', '3' );
745 $table
.tablesorter();
746 $table
.find( '.headerSort:eq(0)' ).click();
751 'Complex date parsing I',
755 function ( $table
) {
756 mw
.config
.set( 'wgDefaultDateFormat', 'mdy' );
758 $table
.tablesorter();
759 $table
.find( '.headerSort:eq(0)' ).click();
764 'Currency parsing I',
768 function ( $table
) {
769 $table
.tablesorter();
770 $table
.find( '.headerSort:eq(0)' ).click();
774 planetsAscNameLegacy
= planetsAscName
.slice( 0 );
775 planetsAscNameLegacy
[4] = planetsAscNameLegacy
[5];
776 planetsAscNameLegacy
.pop();
779 'Legacy compat with .sortbottom',
782 planetsAscNameLegacy
,
783 function ( $table
) {
784 $table
.find( 'tr:last' ).addClass( 'sortbottom' );
785 $table
.tablesorter();
786 $table
.find( '.headerSort:eq(0)' ).click();
790 QUnit
.test( 'Test detection routine', 1, function ( assert
) {
793 '<table class="sortable">' +
794 '<caption>CAPTION</caption>' +
795 '<tr><th>THEAD</th></tr>' +
796 '<tr><td>1</td></tr>' +
797 '<tr class="sortbottom"><td>text</td></tr>' +
800 $table
.tablesorter();
801 $table
.find( '.headerSort:eq(0)' ).click();
804 $table
.data( 'tablesorter' ).config
.parsers
[0].id
,
806 'Correctly detected column content skipping sortbottom'
810 /** FIXME: the diff output is not very readeable. */
811 QUnit
.test( 'bug 32047 - caption must be before thead', 1, function ( assert
) {
814 '<table class="sortable">' +
815 '<caption>CAPTION</caption>' +
816 '<tr><th>THEAD</th></tr>' +
817 '<tr><td>A</td></tr>' +
818 '<tr><td>B</td></tr>' +
819 '<tr class="sortbottom"><td>TFOOT</td></tr>' +
822 $table
.tablesorter();
825 $table
.children().get( 0 ).nodeName
,
827 'First element after <thead> must be <caption> (bug 32047)'
831 QUnit
.test( 'data-sort-value attribute, when available, should override sorting position', 3, function ( assert
) {
834 // Example 1: All cells except one cell without data-sort-value,
835 // which should be sorted at it's text content value.
837 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
839 '<tr><td>Cheetah</td></tr>' +
840 '<tr><td data-sort-value="Apple">Bird</td></tr>' +
841 '<tr><td data-sort-value="Bananna">Ferret</td></tr>' +
842 '<tr><td data-sort-value="Drupe">Elephant</td></tr>' +
843 '<tr><td data-sort-value="Cherry">Dolphin</td></tr>' +
846 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
849 $table
.find( 'tbody > tr' ).each( function ( i
, tr
) {
850 $( tr
).find( 'td' ).each( function ( i
, td
) {
852 data
: $( td
).data( 'sortValue' ),
858 assert
.deepEqual( data
, [
879 ], 'Order matches expected order (based on data-sort-value attribute values)' );
883 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
885 '<tr><td>D</td></tr>' +
886 '<tr><td data-sort-value="E">A</td></tr>' +
887 '<tr><td>B</td></tr>' +
888 '<tr><td>G</td></tr>' +
889 '<tr><td data-sort-value="F">C</td></tr>' +
892 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
895 $table
.find( 'tbody > tr' ).each( function ( i
, tr
) {
896 $( tr
).find( 'td' ).each( function ( i
, td
) {
898 data
: $( td
).data( 'sortValue' ),
904 assert
.deepEqual( data
, [
925 ], 'Order matches expected order (based on data-sort-value attribute values)' );
927 // Example 3: Test that live changes are used from data-sort-value,
928 // even if they change after the tablesorter is constructed (bug 38152).
930 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
932 '<tr><td>D</td></tr>' +
933 '<tr><td data-sort-value="1">A</td></tr>' +
934 '<tr><td>B</td></tr>' +
935 '<tr><td data-sort-value="2">G</td></tr>' +
936 '<tr><td>C</td></tr>' +
939 // initialize table sorter and sort once
942 .find( '.headerSort:eq(0)' ).click();
944 // Change the sortValue data properties (bug 38152)
946 $table
.find( 'td:contains(A)' ).data( 'sortValue', 3 );
948 $table
.find( 'td:contains(B)' ).data( 'sortValue', 1 );
949 // - remove data, bring back attribute: 2
950 $table
.find( 'td:contains(G)' ).removeData( 'sortValue' );
952 // Now sort again (twice, so it is back at Ascending)
953 $table
.find( '.headerSort:eq(0)' ).click();
954 $table
.find( '.headerSort:eq(0)' ).click();
957 $table
.find( 'tbody > tr' ).each( function ( i
, tr
) {
958 $( tr
).find( 'td' ).each( function ( i
, td
) {
960 data
: $( td
).data( 'sortValue' ),
966 assert
.deepEqual( data
, [
987 ], 'Order matches expected order, using the current sortValue in $.data()' );
991 tableTest( 'bug 8115: sort numbers with commas (ascending)',
992 ['Numbers'], numbers
, numbersAsc
,
993 function ( $table
) {
994 $table
.tablesorter();
995 $table
.find( '.headerSort:eq(0)' ).click();
999 tableTest( 'bug 8115: sort numbers with commas (descending)',
1000 ['Numbers'], numbers
, reversed( numbersAsc
),
1001 function ( $table
) {
1002 $table
.tablesorter();
1003 $table
.find( '.headerSort:eq(0)' ).click().click();
1006 // TODO add numbers sorting tests for bug 8115 with a different language
1008 QUnit
.test( 'bug 32888 - Tables inside a tableheader cell', 2, function ( assert
) {
1011 '<table class="sortable" id="mw-bug-32888">' +
1012 '<tr><th>header<table id="mw-bug-32888-2">' +
1013 '<tr><th>1</th><th>2</th></tr>' +
1014 '</table></th></tr>' +
1015 '<tr><td>A</td></tr>' +
1016 '<tr><td>B</td></tr>' +
1019 $table
.tablesorter();
1022 $table
.find( '> thead:eq(0) > tr > th.headerSort' ).length
,
1024 'Child tables inside a headercell should not interfere with sortable headers (bug 32888)'
1027 $( '#mw-bug-32888-2' ).find( 'th.headerSort' ).length
,
1029 'The headers of child tables inside a headercell should not be sortable themselves (bug 32888)'
1034 'Correct date sorting I',
1036 correctDateSorting1
,
1037 correctDateSortingSorted1
,
1038 function ( $table
) {
1039 mw
.config
.set( 'wgDefaultDateFormat', 'mdy' );
1041 $table
.tablesorter();
1042 $table
.find( '.headerSort:eq(0)' ).click();
1047 'Correct date sorting II',
1049 correctDateSorting2
,
1050 correctDateSortingSorted2
,
1051 function ( $table
) {
1052 mw
.config
.set( 'wgDefaultDateFormat', 'dmy' );
1054 $table
.tablesorter();
1055 $table
.find( '.headerSort:eq(0)' ).click();
1059 QUnit
.test( 'Sorting images using alt text', 1, function ( assert
) {
1061 '<table class="sortable">' +
1062 '<tr><th>THEAD</th></tr>' +
1063 '<tr><td><img alt="2"/></td></tr>' +
1064 '<tr><td>1</td></tr>' +
1067 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
1070 $table
.find( 'td' ).first().text(),
1072 'Applied correct sorting order'
1076 QUnit
.test( 'Sorting images using alt text (complex)', 1, function ( assert
) {
1078 '<table class="sortable">' +
1079 '<tr><th>THEAD</th></tr>' +
1080 '<tr><td><img alt="D" />A</td></tr>' +
1081 '<tr><td>CC</td></tr>' +
1082 '<tr><td><a><img alt="A" /></a>F</tr>' +
1083 '<tr><td><img alt="A" /><strong>E</strong></tr>' +
1084 '<tr><td><strong><img alt="A" />D</strong></tr>' +
1085 '<tr><td><img alt="A" />C</tr>' +
1088 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
1091 $table
.find( 'td' ).text(),
1093 'Applied correct sorting order'
1097 QUnit
.test( 'Sorting images using alt text (with format autodetection)', 1, function ( assert
) {
1099 '<table class="sortable">' +
1100 '<tr><th>THEAD</th></tr>' +
1101 '<tr><td><img alt="1" />7</td></tr>' +
1102 '<tr><td>1<img alt="6" /></td></tr>' +
1103 '<tr><td>5</td></tr>' +
1104 '<tr><td>4</td></tr>' +
1107 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
1110 $table
.find( 'td' ).text(),
1112 'Applied correct sorting order'
1116 QUnit
.test( 'bug 38911 - The row with the largest amount of columns should receive the sort indicators', 3, function ( assert
) {
1118 '<table class="sortable">' +
1120 '<tr><th rowspan="2" id="A1">A1</th><th colspan="2">B2a</th></tr>' +
1121 '<tr><th id="B2b">B2b</th><th id="C2b">C2b</th></tr>' +
1123 '<tr><td>A</td><td>Aa</td><td>Ab</td></tr>' +
1124 '<tr><td>B</td><td>Ba</td><td>Bb</td></tr>' +
1127 $table
.tablesorter();
1130 $table
.find( '#A1' ).attr( 'class' ),
1132 'The first column of the first row should be sortable'
1135 $table
.find( '#B2b' ).attr( 'class' ),
1137 'The th element of the 2nd row of the 2nd column should be sortable'
1140 $table
.find( '#C2b' ).attr( 'class' ),
1142 'The th element of the 2nd row of the 3rd column should be sortable'
1146 QUnit
.test( 'rowspans in table headers should prefer the last row when rows are equal in length', 2, function ( assert
) {
1148 '<table class="sortable">' +
1150 '<tr><th rowspan="2" id="A1">A1</th><th>B2a</th></tr>' +
1151 '<tr><th id="B2b">B2b</th></tr>' +
1153 '<tr><td>A</td><td>Aa</td></tr>' +
1154 '<tr><td>B</td><td>Ba</td></tr>' +
1157 $table
.tablesorter();
1160 $table
.find( '#A1' ).attr( 'class' ),
1162 'The first column of the first row should be sortable'
1165 $table
.find( '#B2b' ).attr( 'class' ),
1167 'The th element of the 2nd row of the 2nd column should be sortable'
1171 QUnit
.test( 'holes in the table headers should not throw JS errors', 2, function ( assert
) {
1173 '<table class="sortable">' +
1175 '<tr><th id="A1">A1</th><th>B1</th><th id="C1" rowspan="2">C1</th></tr>' +
1176 '<tr><th id="A2">A2</th></tr>' +
1178 '<tr><td>A</td><td>Aa</td><td>Aaa</td></tr>' +
1179 '<tr><td>B</td><td>Ba</td><td>Bbb</td></tr>' +
1182 $table
.tablesorter();
1183 assert
.equal( $table
.find( '#A2' ).data( 'headerIndex' ),
1185 'A2 should not be a sort header'
1187 assert
.equal( $table
.find( '#C1' ).data( 'headerIndex' ),
1189 'C1 should be a sort header'
1194 QUnit
.test( 'td cells in thead should not be taken into account for longest row calculation', 2, function ( assert
) {
1196 '<table class="sortable">' +
1198 '<tr><th id="A1">A1</th><th>B1</th><td id="C1">C1</td></tr>' +
1199 '<tr><th id="A2">A2</th><th>B2</th><th id="C2">C2</th></tr>' +
1203 $table
.tablesorter();
1204 assert
.equal( $table
.find( '#C2' ).data( 'headerIndex' ),
1206 'C2 should be a sort header'
1208 assert
.equal( $table
.find( '#C1' ).data( 'headerIndex' ),
1210 'C1 should not be a sort header'
1214 // bug 41889 - exploding rowspans in more complex cases
1216 'Rowspan exploding with row headers',
1217 '<table class="sortable">' +
1218 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th></tr></thead>' +
1220 '<tr><td>1</td><th rowspan="2">foo</th><td rowspan="2">bar</td><td>baz</td></tr>' +
1221 '<tr><td>2</td><td>baz</td></tr>' +
1224 [ '1', 'foo', 'bar', 'baz' ],
1225 [ '2', 'foo', 'bar', 'baz' ]
1229 // bug 53211 - exploding rowspans in more complex cases
1231 'Rowspan exploding with row headers and colspans', 1, function ( assert
) {
1232 var $table
= $( '<table class="sortable">' +
1233 '<thead><tr><th rowspan="2">n</th><th colspan="2">foo</th><th rowspan="2">baz</th></tr>' +
1234 '<tr><th>foo</th><th>bar</th></tr></thead>' +
1236 '<tr><td>1</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
1237 '<tr><td>2</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
1238 '</tbody></table>' );
1240 $table
.tablesorter();
1241 assert
.equal( $table
.find( 'tr:eq(1) th:eq(1)').data('headerIndex'),
1243 'Incorrect index of sort header'
1249 'Rowspan exploding with colspanned cells',
1250 '<table class="sortable">' +
1251 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th></tr></thead>' +
1253 '<tr><td>1</td><td>foo</td><td>bar</td><td rowspan="2">baz</td></tr>' +
1254 '<tr><td>2</td><td colspan="2">foobar</td></tr>' +
1257 [ '1', 'foo', 'bar', 'baz' ],
1258 [ '2', 'foobar', 'baz' ]
1263 'Rowspan exploding with colspanned cells (2)',
1264 '<table class="sortable">' +
1265 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th><th>quux</th></tr></thead>' +
1267 '<tr><td>1</td><td>foo</td><td>bar</td><td rowspan="2">baz</td><td>quux</td></tr>' +
1268 '<tr><td>2</td><td colspan="2">foobar</td><td>quux</td></tr>' +
1271 [ '1', 'foo', 'bar', 'baz', 'quux' ],
1272 [ '2', 'foobar', 'baz', 'quux' ]
1277 'Rowspan exploding with rightmost rows spanning most',
1278 '<table class="sortable">' +
1279 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th></tr></thead>' +
1281 '<tr><td>1</td><td rowspan="2">foo</td><td rowspan="4">bar</td></tr>' +
1282 '<tr><td>2</td></tr>' +
1283 '<tr><td>3</td><td rowspan="2">foo</td></tr>' +
1284 '<tr><td>4</td></tr>' +
1287 [ '1', 'foo', 'bar' ],
1288 [ '2', 'foo', 'bar' ],
1289 [ '3', 'foo', 'bar' ],
1290 [ '4', 'foo', 'bar' ]
1295 'Rowspan exploding with rightmost rows spanning most (2)',
1296 '<table class="sortable">' +
1297 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th></tr></thead>' +
1299 '<tr><td>1</td><td rowspan="2">foo</td><td rowspan="4">bar</td><td>baz</td></tr>' +
1300 '<tr><td>2</td><td>baz</td></tr>' +
1301 '<tr><td>3</td><td rowspan="2">foo</td><td>baz</td></tr>' +
1302 '<tr><td>4</td><td>baz</td></tr>' +
1305 [ '1', 'foo', 'bar', 'baz' ],
1306 [ '2', 'foo', 'bar', 'baz' ],
1307 [ '3', 'foo', 'bar', 'baz' ],
1308 [ '4', 'foo', 'bar', 'baz' ]
1313 'Rowspan exploding with row-and-colspanned cells',
1314 '<table class="sortable">' +
1315 '<thead><tr><th id="sortme">n</th><th>foo1</th><th>foo2</th><th>bar</th><th>baz</th></tr></thead>' +
1317 '<tr><td>1</td><td rowspan="2">foo1</td><td rowspan="2">foo2</td><td rowspan="4">bar</td><td>baz</td></tr>' +
1318 '<tr><td>2</td><td>baz</td></tr>' +
1319 '<tr><td>3</td><td colspan="2" rowspan="2">foo</td><td>baz</td></tr>' +
1320 '<tr><td>4</td><td>baz</td></tr>' +
1323 [ '1', 'foo1', 'foo2', 'bar', 'baz' ],
1324 [ '2', 'foo1', 'foo2', 'bar', 'baz' ],
1325 [ '3', 'foo', 'bar', 'baz' ],
1326 [ '4', 'foo', 'bar', 'baz' ]
1331 'Rowspan exploding with uneven rowspan layout',
1332 '<table class="sortable">' +
1333 '<thead><tr><th id="sortme">n</th><th>foo1</th><th>foo2</th><th>foo3</th><th>bar</th><th>baz</th></tr></thead>' +
1335 '<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>' +
1336 '<tr><td>2</td><td rowspan="3">bar</td><td>baz</td></tr>' +
1337 '<tr><td>3</td><td rowspan="2">foo1</td><td rowspan="2">foo2</td><td rowspan="2">foo3</td><td>baz</td></tr>' +
1338 '<tr><td>4</td><td>baz</td></tr>' +
1341 [ '1', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ],
1342 [ '2', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ],
1343 [ '3', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ],
1344 [ '4', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ]
1348 }( jQuery
, mediaWiki
) );