2 var header
= [ 'Planet', 'Radius (km)' ],
5 mercury
= [ 'Mercury', '2439.7' ],
6 venus
= [ 'Venus', '6051.8' ],
7 earth
= [ 'Earth', '6371.0' ],
8 mars
= [ 'Mars', '3390.0' ],
9 jupiter
= [ 'Jupiter', '69911' ],
10 saturn
= [ 'Saturn', '58232' ],
11 planets
= [ mercury
, venus
, earth
, mars
, jupiter
, saturn
],
12 planetsAscName
= [ earth
, jupiter
, mars
, mercury
, saturn
, venus
],
13 planetsAscRadius
= [ mercury
, mars
, venus
, earth
, saturn
, jupiter
],
25 simple
= [ a2
, b3
, a1
, a3
, b2
, b1
],
26 simpleAsc
= [ a1
, a2
, a3
, b1
, b2
, b3
],
27 simpleDescasc
= [ b1
, b2
, b3
, a1
, a2
, a3
],
30 header4
= [ 'column1a', 'column1b', 'column1c', 'column2' ],
31 aaa1
= [ 'A', 'A', 'A', '1' ],
32 aab5
= [ 'A', 'A', 'B', '5' ],
33 abc3
= [ 'A', 'B', 'C', '3' ],
34 bbc2
= [ 'B', 'B', 'C', '2' ],
35 caa4
= [ 'C', 'A', 'A', '4' ],
36 colspanInitial
= [ aab5
, aaa1
, abc3
, bbc2
, caa4
],
40 // Some randomly generated fake IPs
44 [ '204.204.132.158' ],
51 // Sort order should go octet by octet
58 [ '204.204.132.158' ],
93 digraphWordsSorted
= [
103 [ 'January, 19 2010' ],
107 [ 'December 12 \'10' ]
113 [ 'January, 19 2010' ],
114 [ 'December 12 \'10' ]
133 // Comma's sort after dots
134 // Not intentional but test to detect changes
155 correctDateSorting1
= [
156 [ '01 January 2010' ],
157 [ '05 February 2010' ],
158 [ '16 January 2010' ]
160 correctDateSortingSorted1
= [
161 [ '01 January 2010' ],
162 [ '16 January 2010' ],
163 [ '05 February 2010' ]
166 correctDateSorting2
= [
167 [ 'January 01 2010' ],
168 [ 'February 05 2010' ],
169 [ 'January 16 2010' ]
171 correctDateSortingSorted2
= [
172 [ 'January 01 2010' ],
173 [ 'January 16 2010' ],
174 [ 'February 05 2010' ]
178 [ '2009-12-25T12:30:45.001Z' ],
181 [ '2009-12-25T12:30:45' ],
182 [ '2009-12-25T12:30:45.111' ],
183 [ '2009-12-25T12:30:45+01:00' ]
185 isoDateSortingSorted
= [
187 [ '2009-12-25T12:30:45' ],
188 [ '2009-12-25T12:30:45+01:00' ],
189 [ '2009-12-25T12:30:45.001Z' ],
190 [ '2009-12-25T12:30:45.111' ],
195 QUnit
.module( 'jquery.tablesorter', QUnit
.newMwEnvironment( {
197 this.liveMonths
= mw
.language
.months
;
198 mw
.language
.months
= {
200 names
: [ 'january', 'february', 'march', 'april', 'may_long', 'june',
201 'july', 'august', 'september', 'october', 'november', 'december' ],
202 genitive
: [ 'january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
203 'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen', 'december-gen' ],
204 abbrev
: [ 'jan', 'feb', 'mar', 'apr', 'may', 'jun',
205 'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ]
207 names
: [ 'January', 'February', 'March', 'April', 'May', 'June',
208 'July', 'August', 'September', 'October', 'November', 'December' ],
209 genitive
: [ 'January', 'February', 'March', 'April', 'May', 'June',
210 'July', 'August', 'September', 'October', 'November', 'December' ],
211 abbrev
: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
212 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
215 teardown: function () {
216 mw
.language
.months
= this.liveMonths
;
219 wgDefaultDateFormat
: 'dmy',
220 wgSeparatorTransformTable
: [ '', '' ],
221 wgDigitTransformTable
: [ '', '' ],
222 wgPageContentLanguage
: 'en'
227 * Create an HTML table from an array of row arrays containing text strings.
228 * First row will be header row. No fancy rowspan/colspan stuff.
230 * @param {string[]} header
231 * @param {string[][]} data
234 function tableCreate( header
, data
) {
236 $table
= $( '<table class="sortable"><thead></thead><tbody></tbody></table>' ),
237 $thead
= $table
.find( 'thead' ),
238 $tbody
= $table
.find( 'tbody' ),
241 $.each( header
, function ( i
, str
) {
242 var $th
= $( '<th>' );
243 $th
.text( str
).appendTo( $tr
);
245 $tr
.appendTo( $thead
);
247 for ( i
= 0; i
< data
.length
; i
++ ) {
249 $.each( data
[ i
], function ( j
, str
) {
250 var $td
= $( '<td>' );
251 $td
.text( str
).appendTo( $tr
);
253 $tr
.appendTo( $tbody
);
259 * Extract text from table.
261 * @param {jQuery} $table
262 * @return {string[][]}
264 function tableExtract( $table
) {
267 $table
.find( 'tbody' ).find( 'tr' ).each( function ( i
, tr
) {
269 $( tr
).find( 'td,th' ).each( function ( i
, td
) {
270 row
.push( $( td
).text() );
278 * Run a table test by building a table with the given data,
279 * running some callback on it, then checking the results.
281 * @param {string} msg text to pass on to qunit for the comparison
282 * @param {string[]} header cols to make the table
283 * @param {string[][]} data rows/cols to make the table
284 * @param {string[][]} expected rows/cols to compare against at end
285 * @param {function($table)} callback something to do with the table before we compare
287 function tableTest( msg
, header
, data
, expected
, callback
) {
288 QUnit
.test( msg
, 1, function ( assert
) {
290 $table
= tableCreate( header
, data
);
292 // Give caller a chance to set up sorting and manipulate the table.
295 // Table sorting is done synchronously; if it ever needs to change back
296 // to asynchronous, we'll need a timeout or a callback here.
297 extracted
= tableExtract( $table
);
298 assert
.deepEqual( extracted
, expected
, msg
);
303 * Run a table test by building a table with the given HTML,
304 * running some callback on it, then checking the results.
306 * @param {string} msg text to pass on to qunit for the comparison
307 * @param {string} html HTML to make the table
308 * @param {string[][]} expected Rows/cols to compare against at end
309 * @param {function($table)} callback Something to do with the table before we compare
311 function tableTestHTML( msg
, html
, expected
, callback
) {
312 QUnit
.test( msg
, 1, function ( assert
) {
316 // Give caller a chance to set up sorting and manipulate the table.
320 $table
.tablesorter();
321 $table
.find( '#sortme' ).click();
324 // Table sorting is done synchronously; if it ever needs to change back
325 // to asynchronous, we'll need a timeout or a callback here.
326 extracted
= tableExtract( $table
);
327 assert
.deepEqual( extracted
, expected
, msg
);
331 function reversed( arr
) {
333 var arr2
= arr
.slice( 0 );
340 // Sample data set using planets named and their radius
343 'Basic planet table: sorting initially - ascending by name',
347 function ( $table
) {
348 $table
.tablesorter( { sortList
: [
354 'Basic planet table: sorting initially - descending by radius',
357 reversed( planetsAscRadius
),
358 function ( $table
) {
359 $table
.tablesorter( { sortList
: [
365 'Basic planet table: ascending by name',
369 function ( $table
) {
370 $table
.tablesorter();
371 $table
.find( '.headerSort:eq(0)' ).click();
375 'Basic planet table: ascending by name a second time',
379 function ( $table
) {
380 $table
.tablesorter();
381 $table
.find( '.headerSort:eq(0)' ).click();
385 'Basic planet table: ascending by name (multiple clicks)',
389 function ( $table
) {
390 $table
.tablesorter();
391 $table
.find( '.headerSort:eq(0)' ).click();
392 $table
.find( '.headerSort:eq(1)' ).click();
393 $table
.find( '.headerSort:eq(0)' ).click();
397 'Basic planet table: descending by name',
400 reversed( planetsAscName
),
401 function ( $table
) {
402 $table
.tablesorter();
403 $table
.find( '.headerSort:eq(0)' ).click().click();
407 'Basic planet table: ascending radius',
411 function ( $table
) {
412 $table
.tablesorter();
413 $table
.find( '.headerSort:eq(1)' ).click();
417 'Basic planet table: descending radius',
420 reversed( planetsAscRadius
),
421 function ( $table
) {
422 $table
.tablesorter();
423 $table
.find( '.headerSort:eq(1)' ).click().click();
427 'Sorting multiple columns by passing sort list',
431 function ( $table
) {
441 'Sorting multiple columns by programmatically triggering sort()',
445 function ( $table
) {
446 $table
.tablesorter();
447 $table
.data( 'tablesorter' ).sort(
456 'Reset to initial sorting by triggering sort() without any parameters',
460 function ( $table
) {
467 $table
.data( 'tablesorter' ).sort(
473 $table
.data( 'tablesorter' ).sort();
477 'Sort via click event after having initialized the tablesorter with initial sorting',
481 function ( $table
) {
483 { sortList
: [ { 0: 'asc' }, { 1: 'asc' } ] }
485 $table
.find( '.headerSort:eq(0)' ).click();
489 'Multi-sort via click event after having initialized the tablesorter with initial sorting',
493 function ( $table
) {
495 { sortList
: [ { 0: 'desc' }, { 1: 'desc' } ] }
497 $table
.find( '.headerSort:eq(0)' ).click();
499 // Pretend to click while pressing the multi-sort key
500 var event
= $.Event( 'click' );
501 event
[ $table
.data( 'tablesorter' ).config
.sortMultiSortKey
] = true;
502 $table
.find( '.headerSort:eq(1)' ).trigger( event
);
505 QUnit
.test( 'Reset sorting making table appear unsorted', function ( assert
) {
506 var $table
= tableCreate( header
, simple
);
513 $table
.data( 'tablesorter' ).sort( [] );
516 $table
.find( 'th.headerSortUp' ).length
+ $table
.find( 'th.headerSortDown' ).length
,
518 'No sort specific sort classes addign to header cells'
522 $table
.find( 'th' ).first().attr( 'title' ),
523 mw
.msg( 'sort-ascending' ),
524 'First header cell has default title'
528 $table
.find( 'th' ).first().attr( 'title' ),
529 $table
.find( 'th' ).last().attr( 'title' ),
530 'Both header cells\' titles match'
534 // Sorting with colspans
536 tableTest( 'Sorting with colspanned headers: spanned column',
539 [ aaa1
, aab5
, abc3
, bbc2
, caa4
],
540 function ( $table
) {
541 // Make colspanned header for test
542 $table
.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
543 $table
.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
545 $table
.tablesorter();
546 $table
.find( '.headerSort:eq(0)' ).click();
549 tableTest( 'Sorting with colspanned headers: sort spanned column twice',
552 [ caa4
, bbc2
, abc3
, aab5
, aaa1
],
553 function ( $table
) {
554 // Make colspanned header for test
555 $table
.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
556 $table
.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
558 $table
.tablesorter();
559 $table
.find( '.headerSort:eq(0)' ).click();
560 $table
.find( '.headerSort:eq(0)' ).click();
563 tableTest( 'Sorting with colspanned headers: subsequent column',
566 [ aaa1
, bbc2
, abc3
, caa4
, aab5
],
567 function ( $table
) {
568 // Make colspanned header for test
569 $table
.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
570 $table
.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
572 $table
.tablesorter();
573 $table
.find( '.headerSort:eq(1)' ).click();
576 tableTest( 'Sorting with colspanned headers: sort subsequent column twice',
579 [ aab5
, caa4
, abc3
, bbc2
, aaa1
],
580 function ( $table
) {
581 // Make colspanned header for test
582 $table
.find( 'tr:eq(0) th:eq(1), tr:eq(0) th:eq(2)' ).remove();
583 $table
.find( 'tr:eq(0) th:eq(0)' ).attr( 'colspan', '3' );
585 $table
.tablesorter();
586 $table
.find( '.headerSort:eq(1)' ).click();
587 $table
.find( '.headerSort:eq(1)' ).click();
591 QUnit
.test( 'Basic planet table: one unsortable column', function ( assert
) {
592 var $table
= tableCreate( header
, planets
),
594 $table
.find( 'tr:eq(0) > th:eq(0)' ).addClass( 'unsortable' );
596 $table
.tablesorter();
597 $table
.find( 'tr:eq(0) > th:eq(0)' ).click();
600 tableExtract( $table
),
605 $cell
= $table
.find( 'tr:eq(0) > th:eq(0)' );
606 $table
.find( 'tr:eq(0) > th:eq(1)' ).click();
609 $cell
.hasClass( 'headerSortUp' ) || $cell
.hasClass( 'headerSortDown' ),
611 'after sort: no class headerSortUp or headerSortDown'
615 $cell
.attr( 'title' ),
617 'after sort: no title tag added'
624 'T30775: German-style (dmy) short numeric dates',
627 // German-style dates are day-month-year
635 // Sorted by ascending date
642 function ( $table
) {
643 mw
.config
.set( 'wgDefaultDateFormat', 'dmy' );
644 mw
.config
.set( 'wgPageContentLanguage', 'de' );
646 $table
.tablesorter();
647 $table
.find( '.headerSort:eq(0)' ).click();
652 'T30775: American-style (mdy) short numeric dates',
655 // American-style dates are month-day-year
663 // Sorted by ascending date
670 function ( $table
) {
671 mw
.config
.set( 'wgDefaultDateFormat', 'mdy' );
673 $table
.tablesorter();
674 $table
.find( '.headerSort:eq(0)' ).click();
679 'T19141: IPv4 address sorting',
683 function ( $table
) {
684 $table
.tablesorter();
685 $table
.find( '.headerSort:eq(0)' ).click();
689 'T19141: IPv4 address sorting (reverse)',
692 reversed( ipv4Sorted
),
693 function ( $table
) {
694 $table
.tablesorter();
695 $table
.find( '.headerSort:eq(0)' ).click().click();
700 'Accented Characters with custom collation',
704 function ( $table
) {
705 mw
.config
.set( 'tableSorterCollation', {
712 $table
.tablesorter();
713 $table
.find( '.headerSort:eq(0)' ).click();
718 'Digraphs with custom collation',
722 function ( $table
) {
723 mw
.config
.set( 'tableSorterCollation', {
728 $table
.tablesorter();
729 $table
.find( '.headerSort:eq(0)' ).click();
733 QUnit
.test( 'Rowspan not exploded on init', function ( assert
) {
734 var $table
= tableCreate( header
, planets
);
736 // Modify the table to have a multiple-row-spanning cell:
737 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
738 $table
.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
739 // - Set rowspan for 2nd cell of 3rd row to 3.
740 // This covers the removed cell in the 4th and 5th row.
741 $table
.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
743 $table
.tablesorter();
746 $table
.find( 'tr:eq(2) td:eq(1)' ).prop( 'rowSpan' ),
748 'Rowspan not exploded'
753 [ 'Earth', '6051.8' ],
755 [ 'Mars', '6051.8' ],
760 planetsRowspanII
= [ jupiter
, mercury
, saturn
, venus
, [ 'Venus', '6371.0' ], [ 'Venus', '3390.0' ] ];
763 'Basic planet table: same value for multiple rows via rowspan',
767 function ( $table
) {
768 // Modify the table to have a multiple-row-spanning cell:
769 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
770 $table
.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
771 // - Set rowspan for 2nd cell of 3rd row to 3.
772 // This covers the removed cell in the 4th and 5th row.
773 $table
.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
775 $table
.tablesorter();
776 $table
.find( '.headerSort:eq(0)' ).click();
780 'Basic planet table: same value for multiple rows via rowspan (sorting initially)',
784 function ( $table
) {
785 // Modify the table to have a multiple-row-spanning cell:
786 // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
787 $table
.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
788 // - Set rowspan for 2nd cell of 3rd row to 3.
789 // This covers the removed cell in the 4th and 5th row.
790 $table
.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
792 $table
.tablesorter( { sortList
: [
798 'Basic planet table: Same value for multiple rows via rowspan II',
802 function ( $table
) {
803 // Modify the table to have a multiple-row-spanning cell:
804 // - Remove 1st cell of 4th row, and, 1st cell or 5th row.
805 $table
.find( 'tr:eq(3) td:eq(0), tr:eq(4) td:eq(0)' ).remove();
806 // - Set rowspan for 1st cell of 3rd row to 3.
807 // This covers the removed cell in the 4th and 5th row.
808 $table
.find( 'tr:eq(2) td:eq(0)' ).attr( 'rowspan', '3' );
810 $table
.tablesorter();
811 $table
.find( '.headerSort:eq(0)' ).click();
816 'Complex date parsing I',
820 function ( $table
) {
821 mw
.config
.set( 'wgDefaultDateFormat', 'mdy' );
823 $table
.tablesorter();
824 $table
.find( '.headerSort:eq(0)' ).click();
829 'Currency parsing I',
833 function ( $table
) {
834 $table
.tablesorter();
835 $table
.find( '.headerSort:eq(0)' ).click();
839 planetsAscNameLegacy
= planetsAscName
.slice( 0 );
840 planetsAscNameLegacy
[ 4 ] = planetsAscNameLegacy
[ 5 ];
841 planetsAscNameLegacy
.pop();
844 'Legacy compat with .sortbottom',
847 planetsAscNameLegacy
,
848 function ( $table
) {
849 $table
.find( 'tr:last' ).addClass( 'sortbottom' );
850 $table
.tablesorter();
851 $table
.find( '.headerSort:eq(0)' ).click();
855 QUnit
.test( 'Test detection routine', function ( assert
) {
858 '<table class="sortable">' +
859 '<caption>CAPTION</caption>' +
860 '<tr><th>THEAD</th></tr>' +
861 '<tr><td>1</td></tr>' +
862 '<tr class="sortbottom"><td>text</td></tr>' +
865 $table
.tablesorter();
866 $table
.find( '.headerSort:eq(0)' ).click();
869 $table
.data( 'tablesorter' ).config
.parsers
[ 0 ].id
,
871 'Correctly detected column content skipping sortbottom'
875 /** FIXME: the diff output is not very readeable. */
876 QUnit
.test( 'T34047 - caption must be before thead', function ( assert
) {
879 '<table class="sortable">' +
880 '<caption>CAPTION</caption>' +
881 '<tr><th>THEAD</th></tr>' +
882 '<tr><td>A</td></tr>' +
883 '<tr><td>B</td></tr>' +
884 '<tr class="sortbottom"><td>TFOOT</td></tr>' +
887 $table
.tablesorter();
890 $table
.children().get( 0 ).nodeName
,
892 'First element after <thead> must be <caption> (T34047)'
896 QUnit
.test( 'data-sort-value attribute, when available, should override sorting position', function ( assert
) {
899 // Example 1: All cells except one cell without data-sort-value,
900 // which should be sorted at it's text content value.
902 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
904 '<tr><td>Cheetah</td></tr>' +
905 '<tr><td data-sort-value="Apple">Bird</td></tr>' +
906 '<tr><td data-sort-value="Bananna">Ferret</td></tr>' +
907 '<tr><td data-sort-value="Drupe">Elephant</td></tr>' +
908 '<tr><td data-sort-value="Cherry">Dolphin</td></tr>' +
911 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
914 $table
.find( 'tbody > tr' ).each( function ( i
, tr
) {
915 $( tr
).find( 'td' ).each( function ( i
, td
) {
917 data
: $( td
).data( 'sortValue' ),
923 assert
.deepEqual( data
, [
944 ], 'Order matches expected order (based on data-sort-value attribute values)' );
948 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
950 '<tr><td>D</td></tr>' +
951 '<tr><td data-sort-value="E">A</td></tr>' +
952 '<tr><td>B</td></tr>' +
953 '<tr><td>G</td></tr>' +
954 '<tr><td data-sort-value="F">C</td></tr>' +
957 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
960 $table
.find( 'tbody > tr' ).each( function ( i
, tr
) {
961 $( tr
).find( 'td' ).each( function ( i
, td
) {
963 data
: $( td
).data( 'sortValue' ),
969 assert
.deepEqual( data
, [
990 ], 'Order matches expected order (based on data-sort-value attribute values)' );
992 // Example 3: Test that live changes are used from data-sort-value,
993 // even if they change after the tablesorter is constructed (T40152).
995 '<table class="sortable"><thead><tr><th>Data</th></tr></thead>' +
997 '<tr><td>D</td></tr>' +
998 '<tr><td data-sort-value="1">A</td></tr>' +
999 '<tr><td>B</td></tr>' +
1000 '<tr><td data-sort-value="2">G</td></tr>' +
1001 '<tr><td>C</td></tr>' +
1004 // initialize table sorter and sort once
1007 .find( '.headerSort:eq(0)' ).click();
1009 // Change the sortValue data properties (T40152)
1011 $table
.find( 'td:contains(A)' ).data( 'sortValue', 3 );
1013 $table
.find( 'td:contains(B)' ).data( 'sortValue', 1 );
1014 // - remove data, bring back attribute: 2
1015 $table
.find( 'td:contains(G)' ).removeData( 'sortValue' );
1017 // Now sort again (twice, so it is back at Ascending)
1018 $table
.find( '.headerSort:eq(0)' ).click();
1019 $table
.find( '.headerSort:eq(0)' ).click();
1022 $table
.find( 'tbody > tr' ).each( function ( i
, tr
) {
1023 $( tr
).find( 'td' ).each( function ( i
, td
) {
1025 data
: $( td
).data( 'sortValue' ),
1026 text
: $( td
).text()
1031 assert
.deepEqual( data
, [
1052 ], 'Order matches expected order, using the current sortValue in $.data()' );
1056 tableTest( 'T10115: sort numbers with commas (ascending)',
1057 [ 'Numbers' ], numbers
, numbersAsc
,
1058 function ( $table
) {
1059 $table
.tablesorter();
1060 $table
.find( '.headerSort:eq(0)' ).click();
1064 tableTest( 'T10115: sort numbers with commas (descending)',
1065 [ 'Numbers' ], numbers
, reversed( numbersAsc
),
1066 function ( $table
) {
1067 $table
.tablesorter();
1068 $table
.find( '.headerSort:eq(0)' ).click().click();
1071 // TODO add numbers sorting tests for T10115 with a different language
1073 QUnit
.test( 'T34888 - Tables inside a tableheader cell', function ( assert
) {
1076 '<table class="sortable" id="mw-bug-32888">' +
1077 '<tr><th>header<table id="mw-bug-32888-2">' +
1078 '<tr><th>1</th><th>2</th></tr>' +
1079 '</table></th></tr>' +
1080 '<tr><td>A</td></tr>' +
1081 '<tr><td>B</td></tr>' +
1084 $table
.tablesorter();
1087 $table
.find( '> thead:eq(0) > tr > th.headerSort' ).length
,
1089 'Child tables inside a headercell should not interfere with sortable headers (T34888)'
1092 $( '#mw-bug-32888-2' ).find( 'th.headerSort' ).length
,
1094 'The headers of child tables inside a headercell should not be sortable themselves (T34888)'
1099 'Correct date sorting I',
1101 correctDateSorting1
,
1102 correctDateSortingSorted1
,
1103 function ( $table
) {
1104 mw
.config
.set( 'wgDefaultDateFormat', 'mdy' );
1106 $table
.tablesorter();
1107 $table
.find( '.headerSort:eq(0)' ).click();
1112 'Correct date sorting II',
1114 correctDateSorting2
,
1115 correctDateSortingSorted2
,
1116 function ( $table
) {
1117 mw
.config
.set( 'wgDefaultDateFormat', 'dmy' );
1119 $table
.tablesorter();
1120 $table
.find( '.headerSort:eq(0)' ).click();
1128 isoDateSortingSorted
,
1129 function ( $table
) {
1130 mw
.config
.set( 'wgDefaultDateFormat', 'dmy' );
1132 $table
.tablesorter();
1133 $table
.find( '.headerSort:eq(0)' ).click();
1137 QUnit
.test( 'Sorting images using alt text', function ( assert
) {
1139 '<table class="sortable">' +
1140 '<tr><th>THEAD</th></tr>' +
1141 '<tr><td><img alt="2"/></td></tr>' +
1142 '<tr><td>1</td></tr>' +
1145 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
1148 $table
.find( 'td' ).first().text(),
1150 'Applied correct sorting order'
1154 QUnit
.test( 'Sorting images using alt text (complex)', function ( assert
) {
1156 '<table class="sortable">' +
1157 '<tr><th>THEAD</th></tr>' +
1158 '<tr><td><img alt="D" />A</td></tr>' +
1159 '<tr><td>CC</td></tr>' +
1160 '<tr><td><a><img alt="A" /></a>F</tr>' +
1161 '<tr><td><img alt="A" /><strong>E</strong></tr>' +
1162 '<tr><td><strong><img alt="A" />D</strong></tr>' +
1163 '<tr><td><img alt="A" />C</tr>' +
1166 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
1169 $table
.find( 'td' ).text(),
1171 'Applied correct sorting order'
1175 QUnit
.test( 'Sorting images using alt text (with format autodetection)', function ( assert
) {
1177 '<table class="sortable">' +
1178 '<tr><th>THEAD</th></tr>' +
1179 '<tr><td><img alt="1" />7</td></tr>' +
1180 '<tr><td>1<img alt="6" /></td></tr>' +
1181 '<tr><td>5</td></tr>' +
1182 '<tr><td>4</td></tr>' +
1185 $table
.tablesorter().find( '.headerSort:eq(0)' ).click();
1188 $table
.find( 'td' ).text(),
1190 'Applied correct sorting order'
1194 QUnit
.test( 'T40911 - The row with the largest amount of columns should receive the sort indicators', function ( assert
) {
1196 '<table class="sortable">' +
1198 '<tr><th rowspan="2" id="A1">A1</th><th colspan="2">B2a</th></tr>' +
1199 '<tr><th id="B2b">B2b</th><th id="C2b">C2b</th></tr>' +
1201 '<tr><td>A</td><td>Aa</td><td>Ab</td></tr>' +
1202 '<tr><td>B</td><td>Ba</td><td>Bb</td></tr>' +
1205 $table
.tablesorter();
1208 $table
.find( '#A1' ).attr( 'class' ),
1210 'The first column of the first row should be sortable'
1213 $table
.find( '#B2b' ).attr( 'class' ),
1215 'The th element of the 2nd row of the 2nd column should be sortable'
1218 $table
.find( '#C2b' ).attr( 'class' ),
1220 'The th element of the 2nd row of the 3rd column should be sortable'
1224 QUnit
.test( 'rowspans in table headers should prefer the last row when rows are equal in length', function ( assert
) {
1226 '<table class="sortable">' +
1228 '<tr><th rowspan="2" id="A1">A1</th><th>B2a</th></tr>' +
1229 '<tr><th id="B2b">B2b</th></tr>' +
1231 '<tr><td>A</td><td>Aa</td></tr>' +
1232 '<tr><td>B</td><td>Ba</td></tr>' +
1235 $table
.tablesorter();
1238 $table
.find( '#A1' ).attr( 'class' ),
1240 'The first column of the first row should be sortable'
1243 $table
.find( '#B2b' ).attr( 'class' ),
1245 'The th element of the 2nd row of the 2nd column should be sortable'
1249 QUnit
.test( 'holes in the table headers should not throw JS errors', function ( assert
) {
1251 '<table class="sortable">' +
1253 '<tr><th id="A1">A1</th><th>B1</th><th id="C1" rowspan="2">C1</th></tr>' +
1254 '<tr><th id="A2">A2</th></tr>' +
1256 '<tr><td>A</td><td>Aa</td><td>Aaa</td></tr>' +
1257 '<tr><td>B</td><td>Ba</td><td>Bbb</td></tr>' +
1260 $table
.tablesorter();
1261 assert
.equal( $table
.find( '#A2' ).data( 'headerIndex' ),
1263 'A2 should not be a sort header'
1265 assert
.equal( $table
.find( '#C1' ).data( 'headerIndex' ),
1267 'C1 should be a sort header'
1272 QUnit
.test( 'td cells in thead should not be taken into account for longest row calculation', function ( assert
) {
1274 '<table class="sortable">' +
1276 '<tr><th id="A1">A1</th><th>B1</th><td id="C1">C1</td></tr>' +
1277 '<tr><th id="A2">A2</th><th>B2</th><th id="C2">C2</th></tr>' +
1281 $table
.tablesorter();
1282 assert
.equal( $table
.find( '#C2' ).data( 'headerIndex' ),
1284 'C2 should be a sort header'
1286 assert
.equal( $table
.find( '#C1' ).data( 'headerIndex' ),
1288 'C1 should not be a sort header'
1292 // T43889 - exploding rowspans in more complex cases
1294 'Rowspan exploding with row headers',
1295 '<table class="sortable">' +
1296 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th></tr></thead>' +
1298 '<tr><td>1</td><th rowspan="2">foo</th><td rowspan="2">bar</td><td>baz</td></tr>' +
1299 '<tr><td>2</td><td>baz</td></tr>' +
1302 [ '1', 'foo', 'bar', 'baz' ],
1303 [ '2', 'foo', 'bar', 'baz' ]
1307 // T55211 - exploding rowspans in more complex cases
1309 'Rowspan exploding with row headers and colspans', function ( assert
) {
1310 var $table
= $( '<table class="sortable">' +
1311 '<thead><tr><th rowspan="2">n</th><th colspan="2">foo</th><th rowspan="2">baz</th></tr>' +
1312 '<tr><th>foo</th><th>bar</th></tr></thead>' +
1314 '<tr><td>1</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
1315 '<tr><td>2</td><td>foo</td><td>bar</td><td>baz</td></tr>' +
1316 '</tbody></table>' );
1318 $table
.tablesorter();
1319 assert
.equal( $table
.find( 'tr:eq(1) th:eq(1)' ).data( 'headerIndex' ),
1321 'Incorrect index of sort header'
1327 'Rowspan exploding with colspanned cells',
1328 '<table class="sortable">' +
1329 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th></tr></thead>' +
1331 '<tr><td>1</td><td>foo</td><td>bar</td><td rowspan="2">baz</td></tr>' +
1332 '<tr><td>2</td><td colspan="2">foobar</td></tr>' +
1335 [ '1', 'foo', 'bar', 'baz' ],
1336 [ '2', 'foobar', 'baz' ]
1341 'Rowspan exploding with colspanned cells (2)',
1342 '<table class="sortable">' +
1343 '<thead><tr><th>n</th><th>foo</th><th>bar</th><th>baz</th><th id="sortme">n2</th></tr></thead>' +
1345 '<tr><td>1</td><td>foo</td><td>bar</td><td rowspan="2">baz</td><td>2</td></tr>' +
1346 '<tr><td>2</td><td colspan="2">foobar</td><td>1</td></tr>' +
1349 [ '2', 'foobar', 'baz', '1' ],
1350 [ '1', 'foo', 'bar', 'baz', '2' ]
1355 'Rowspan exploding with rightmost rows spanning most',
1356 '<table class="sortable">' +
1357 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th></tr></thead>' +
1359 '<tr><td>1</td><td rowspan="2">foo</td><td rowspan="4">bar</td></tr>' +
1360 '<tr><td>2</td></tr>' +
1361 '<tr><td>3</td><td rowspan="2">foo</td></tr>' +
1362 '<tr><td>4</td></tr>' +
1365 [ '1', 'foo', 'bar' ],
1366 [ '2', 'foo', 'bar' ],
1367 [ '3', 'foo', 'bar' ],
1368 [ '4', 'foo', 'bar' ]
1373 'Rowspan exploding with rightmost rows spanning most (2)',
1374 '<table class="sortable">' +
1375 '<thead><tr><th id="sortme">n</th><th>foo</th><th>bar</th><th>baz</th></tr></thead>' +
1377 '<tr><td>1</td><td rowspan="2">foo</td><td rowspan="4">bar</td><td>baz</td></tr>' +
1378 '<tr><td>2</td><td>baz</td></tr>' +
1379 '<tr><td>3</td><td rowspan="2">foo</td><td>baz</td></tr>' +
1380 '<tr><td>4</td><td>baz</td></tr>' +
1383 [ '1', 'foo', 'bar', 'baz' ],
1384 [ '2', 'foo', 'bar', 'baz' ],
1385 [ '3', 'foo', 'bar', 'baz' ],
1386 [ '4', 'foo', 'bar', 'baz' ]
1391 'Rowspan exploding with row-and-colspanned cells',
1392 '<table class="sortable">' +
1393 '<thead><tr><th id="sortme">n</th><th>foo1</th><th>foo2</th><th>bar</th><th>baz</th></tr></thead>' +
1395 '<tr><td>1</td><td rowspan="2">foo1</td><td rowspan="2">foo2</td><td rowspan="4">bar</td><td>baz</td></tr>' +
1396 '<tr><td>2</td><td>baz</td></tr>' +
1397 '<tr><td>3</td><td colspan="2" rowspan="2">foo</td><td>baz</td></tr>' +
1398 '<tr><td>4</td><td>baz</td></tr>' +
1401 [ '1', 'foo1', 'foo2', 'bar', 'baz' ],
1402 [ '2', 'foo1', 'foo2', 'bar', 'baz' ],
1403 [ '3', 'foo', 'bar', 'baz' ],
1404 [ '4', 'foo', 'bar', 'baz' ]
1409 'Rowspan exploding with uneven rowspan layout',
1410 '<table class="sortable">' +
1411 '<thead><tr><th id="sortme">n</th><th>foo1</th><th>foo2</th><th>foo3</th><th>bar</th><th>baz</th></tr></thead>' +
1413 '<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>' +
1414 '<tr><td>2</td><td rowspan="3">bar</td><td>baz</td></tr>' +
1415 '<tr><td>3</td><td rowspan="2">foo1</td><td rowspan="2">foo2</td><td rowspan="2">foo3</td><td>baz</td></tr>' +
1416 '<tr><td>4</td><td>baz</td></tr>' +
1419 [ '1', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ],
1420 [ '2', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ],
1421 [ '3', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ],
1422 [ '4', 'foo1', 'foo2', 'foo3', 'bar', 'baz' ]
1426 QUnit
.test( 'T105731 - incomplete rows in table body', function ( assert
) {
1427 var $table
, parsers
;
1429 '<table class="sortable">' +
1430 '<tr><th>A</th><th>B</th></tr>' +
1431 '<tr><td>3</td></tr>' +
1432 '<tr><td>1</td><td>2</td></tr>' +
1435 $table
.tablesorter();
1436 $table
.find( '.headerSort:eq(0)' ).click();
1437 // now the first row have 2 columns
1438 $table
.find( '.headerSort:eq(1)' ).click();
1440 parsers
= $table
.data( 'tablesorter' ).config
.parsers
;
1445 'detectParserForColumn() detect 2 parsers'
1451 'detectParserForColumn() detect parser.id "number" for second column'
1455 parsers
[ 1 ].format( $table
.find( 'tbody > tr > td:eq(1)' ).text() ),
1457 'empty cell is sorted as number -Infinity'
1461 QUnit
.test( 'bug T114721 - use of expand-child class', function ( assert
) {
1462 var $table
, parsers
;
1464 '<table class="sortable">' +
1465 '<tr><th>A</th><th>B</th></tr>' +
1466 '<tr><td>b</td><td>4</td></tr>' +
1467 '<tr class="expand-child"><td colspan="2">some text follow b</td></tr>' +
1468 '<tr><td>a</td><td>2</td></tr>' +
1469 '<tr class="expand-child"><td colspan="2">some text follow a</td></tr>' +
1470 '<tr class="expand-child"><td colspan="2">more text</td></tr>' +
1473 $table
.tablesorter();
1474 $table
.find( '.headerSort:eq(0)' ).click();
1477 tableExtract( $table
),
1480 [ 'some text follow a' ],
1483 [ 'some text follow b' ]
1485 'row with expand-child class follow above row'
1488 parsers
= $table
.data( 'tablesorter' ).config
.parsers
;
1492 'detectParserForColumn() detect parser.id "number" for second column'
1496 }( jQuery
, mediaWiki
) );