Merge "TableSorter: Avoid Sizzle selectors"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 28 Jun 2019 19:20:07 +0000 (19:20 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 28 Jun 2019 19:20:07 +0000 (19:20 +0000)
1  2 
resources/src/jquery.tablesorter/jquery.tablesorter.js
tests/qunit/suites/resources/jquery/jquery.tablesorter.test.js

                                }
                                $thead.append( this );
                        } );
-                       $table.find( ' > tbody:first' ).before( $thead );
+                       $table.find( ' > tbody' ).first().before( $thead );
                }
                if ( !$table.get( 0 ).tFoot ) {
                        $tfoot = $( '<tfoot>' );
                        headerIndex,
                        exploded,
                        $tableHeaders = $( [] ),
-                       $tableRows = $( 'thead:eq(0) > tr', table );
+                       $tableRows = $( table ).find( 'thead' ).eq( 0 ).find( '> tr' );
  
                if ( $tableRows.length <= 1 ) {
                        $tableHeaders = $tableRows.children( 'th' );
        }
  
        function sortText( a, b ) {
 -              return ( ( a < b ) ? -1 : ( ( a > b ) ? 1 : 0 ) );
 +              return ts.collator.compare( a, b );
        }
  
 -      function sortTextDesc( a, b ) {
 -              return ( ( b < a ) ? -1 : ( ( b > a ) ? 1 : 0 ) );
 +      function sortNumeric( a, b ) {
 +              return ( ( a < b ) ? -1 : ( ( a > b ) ? 1 : 0 ) );
        }
  
        function multisort( table, sortList, cache ) {
                var i,
 -                      sortFn = [];
 +                      sortFn = [],
 +                      parsers = $( table ).data( 'tablesorter' ).config.parsers;
  
                for ( i = 0; i < sortList.length; i++ ) {
 -                      sortFn[ i ] = ( sortList[ i ][ 1 ] ) ? sortTextDesc : sortText;
 +                      // Android doesn't support Intl.Collator
 +                      if ( window.Intl && Intl.Collator && parsers[ sortList[ i ][ 0 ] ].type === 'text' ) {
 +                              sortFn[ i ] = sortText;
 +                      } else {
 +                              sortFn[ i ] = sortNumeric;
 +                      }
                }
                cache.normalized.sort( function ( array1, array2 ) {
                        var i, col, ret;
                        for ( i = 0; i < sortList.length; i++ ) {
                                col = sortList[ i ][ 0 ];
 -                              ret = sortFn[ i ].call( this, array1[ col ], array2[ col ] );
 +                              if ( sortList[ i ][ 1 ] ) {
 +                                      // descending
 +                                      ret = sortFn[ i ].call( this, array2[ col ], array1[ col ] );
 +                              } else {
 +                                      // ascending
 +                                      ret = sortFn[ i ].call( this, array1[ col ], array2[ col ] );
 +                              }
                                if ( ret !== 0 ) {
                                        return ret;
                                }
                }
        }
  
 -      function buildCollationTable() {
 +      function buildCollation() {
                var key, keys = [];
                ts.collationTable = mw.config.get( 'tableSorterCollation' );
                ts.collationRegex = null;
                                ts.collationRegex = new RegExp( keys.join( '|' ), 'ig' );
                        }
                }
 +              if ( window.Intl && Intl.Collator ) {
 +                      ts.collator = new Intl.Collator( [
 +                              mw.config.get( 'wgPageContentLanguage' ),
 +                              mw.config.get( 'wgUserLanguage' )
 +                      ], {
 +                              numeric: true
 +                      } );
 +              }
        }
  
        function cacheRegexs() {
                                        // may customize tableSorterCollation but load after $.ready(), other
                                        // scripts may call .tablesorter() before they have done the
                                        // tableSorterCollation customizations.
 -                                      buildCollationTable();
 +                                      buildCollation();
  
                                        // Legacy fix of .sortbottoms
                                        // Wrap them inside a tfoot (because that's what they actually want to be)
                        buildTransformTable();
                        buildDateTable();
                        cacheRegexs();
 -                      buildCollationTable();
 +                      buildCollation();
  
                        return getParserById( id );
                },
                },
                format: function ( s ) {
                        var tsc;
 -                      s = s.toLowerCase().trim();
 +                      s = s.trim();
                        if ( ts.collationRegex ) {
                                tsc = ts.collationTable;
                                s = s.replace( ts.collationRegex, function ( match ) {
 -                                      var r = tsc[ match ] ? tsc[ match ] : tsc[ match.toUpperCase() ];
 -                                      return r.toLowerCase();
 +                                      var r,
 +                                              upper = match.toUpperCase(),
 +                                              lower = match.toLowerCase();
 +                                      if ( upper === match && !lower === match ) {
 +                                              r = tsc[ lower ] ? tsc[ lower ] : tsc[ upper ];
 +                                              r = r.toUpperCase();
 +                                      } else {
 +                                              r = tsc[ match.toLowerCase() ];
 +                                      }
 +                                      return r;
                                } );
                        }
                        return s;
                        [ 'Günther' ],
                        [ 'Peter' ],
                        [ 'Björn' ],
 +                      [ 'ä' ],
 +                      [ 'z' ],
                        [ 'Bjorn' ],
 +                      [ 'BjÖrn' ],
 +                      [ 'apfel' ],
                        [ 'Apfel' ],
                        [ 'Äpfel' ],
                        [ 'Strasse' ],
                        [ 'Sträßschen' ]
                ],
 -              umlautWordsSorted = [
 +              umlautWordsSortedEn = [
 +                      [ 'ä' ],
                        [ 'Äpfel' ],
 +                      [ 'apfel' ],
                        [ 'Apfel' ],
                        [ 'Björn' ],
 +                      [ 'BjÖrn' ],
                        [ 'Bjorn' ],
                        [ 'Günther' ],
                        [ 'Peter' ],
                        [ 'Sträßschen' ],
 -                      [ 'Strasse' ]
 +                      [ 'Strasse' ],
 +                      [ 'z' ]
 +              ],
 +              umlautWordsSortedSv = [
 +                      [ 'apfel' ],
 +                      [ 'Apfel' ],
 +                      [ 'Bjorn' ],
 +                      [ 'Björn' ],
 +                      [ 'BjÖrn' ],
 +                      [ 'Günther' ],
 +                      [ 'Peter' ],
 +                      [ 'Strasse' ],
 +                      [ 'Sträßschen' ],
 +                      [ 'z' ],
 +                      [ 'ä' ], // ä sorts after z in Swedish
 +                      [ 'Äpfel' ]
                ],
  
                // Data set "digraph"
                planetsAscName,
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
        tableTest(
                planetsAscName,
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
        tableTest(
                planetsAscName,
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
-                       $table.find( '.headerSort:eq(1)' ).trigger( 'click' );
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 1 ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
        tableTest(
                reversed( planetsAscName ),
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' ).trigger( 'click' );
                }
        );
        tableTest(
                planetsAscRadius,
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(1)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 1 ).trigger( 'click' );
                }
        );
        tableTest(
                reversed( planetsAscRadius ),
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(1)' ).trigger( 'click' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 1 ).trigger( 'click' ).trigger( 'click' );
                }
        );
        tableTest(
                        $table.tablesorter(
                                { sortList: [ { 0: 'asc' }, { 1: 'asc' } ] }
                        );
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
        tableTest(
                        $table.tablesorter(
                                { sortList: [ { 0: 'desc' }, { 1: 'desc' } ] }
                        );
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                        // Pretend to click while pressing the multi-sort key
                        event = $.Event( 'click' );
                        event[ $table.data( 'tablesorter' ).config.sortMultiSortKey ] = true;
-                       $table.find( '.headerSort:eq(1)' ).trigger( event );
+                       $table.find( '.headerSort' ).eq( 1 ).trigger( event );
                }
        );
        QUnit.test( 'Reset sorting making table appear unsorted', function ( assert ) {
                [ 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)' ).attr( 'colspan', '3' );
+                       $table.find( 'tr th' ).eq( 1 ).remove();
+                       $table.find( 'tr th' ).eq( 1 ).remove();
+                       $table.find( 'tr th' ).eq( 0 ).attr( 'colspan', '3' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
        tableTest( 'Sorting with colspanned headers: sort spanned column twice',
                [ caa4, bbc2, abc3, aab5, aaa1 ],
                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)' ).attr( 'colspan', '3' );
+                       $table.find( 'tr th' ).eq( 1 ).remove();
+                       $table.find( 'tr th' ).eq( 1 ).remove();
+                       $table.find( 'tr' ).eq( 0 ).find( 'th' ).eq( 0 ).attr( 'colspan', '3' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
        tableTest( 'Sorting with colspanned headers: subsequent column',
                [ 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)' ).attr( 'colspan', '3' );
+                       $table.find( 'tr th' ).eq( 1 ).remove();
+                       $table.find( 'tr th' ).eq( 1 ).remove();
+                       $table.find( 'tr th' ).eq( 0 ).attr( 'colspan', '3' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(1)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 1 ).trigger( 'click' );
                }
        );
        tableTest( 'Sorting with colspanned headers: sort subsequent column twice',
                [ aab5, caa4, abc3, bbc2, aaa1 ],
                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)' ).attr( 'colspan', '3' );
+                       $table.find( 'tr th' ).eq( 1 ).remove();
+                       $table.find( 'tr th' ).eq( 1 ).remove();
+                       $table.find( 'tr th' ).eq( 0 ).attr( 'colspan', '3' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(1)' ).trigger( 'click' );
-                       $table.find( '.headerSort:eq(1)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 1 ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 1 ).trigger( 'click' );
                }
        );
  
        QUnit.test( 'Basic planet table: one unsortable column', function ( assert ) {
                var $table = tableCreate( header, planets ),
                        $cell;
-               $table.find( 'tr:eq(0) > th:eq(0)' ).addClass( 'unsortable' );
+               $table.find( 'tr > th' ).eq( 0 ).addClass( 'unsortable' );
  
                $table.tablesorter();
-               $table.find( 'tr:eq(0) > th:eq(0)' ).trigger( 'click' );
+               $table.find( 'tr > th' ).eq( 0 ).trigger( 'click' );
  
                assert.deepEqual(
                        tableExtract( $table ),
                        'table not sorted'
                );
  
-               $cell = $table.find( 'tr:eq(0) > th:eq(0)' );
-               $table.find( 'tr:eq(0) > th:eq(1)' ).trigger( 'click' );
+               $cell = $table.find( 'tr > th' ).eq( 0 );
+               $table.find( 'tr > th' ).eq( 1 ).trigger( 'click' );
  
                assert.strictEqual(
                        $cell.hasClass( 'headerSortUp' ) || $cell.hasClass( 'headerSortDown' ),
                        mw.config.set( 'wgPageContentLanguage', 'de' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                        mw.config.set( 'wgDefaultDateFormat', 'mdy' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                ipv4Sorted,
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
        tableTest(
                reversed( ipv4Sorted ),
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' ).trigger( 'click' );
                }
        );
  
                'Accented Characters with custom collation',
                [ 'Name' ],
                umlautWords,
 -              umlautWordsSorted,
 +              umlautWordsSortedEn,
                function ( $table ) {
                        mw.config.set( 'tableSorterCollation', {
                                ä: 'ae',
                        } );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
 +      tableTest(
 +              'Accented Characters Swedish locale',
 +              [ 'Name' ],
 +              umlautWords,
 +              umlautWordsSortedSv,
 +              function ( $table ) {
 +                      mw.config.set( 'wgPageContentLanguage', 'sv' );
 +
 +                      $table.tablesorter();
 +                      $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
 +              }
 +      );
 +
        tableTest(
                'Digraphs with custom collation',
                [ 'City' ],
                        } );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
  
                // Modify the table to have a multiple-row-spanning cell:
                // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
-               $table.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
+               $table.find( 'tr' ).eq( 3 ).find( 'td' ).eq( 1 ).remove();
+               $table.find( 'tr' ).eq( 4 ).find( 'td' ).eq( 1 ).remove();
                // - Set rowspan for 2nd cell of 3rd row to 3.
                //   This covers the removed cell in the 4th and 5th row.
-               $table.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
+               $table.find( 'tr' ).eq( 2 ).find( 'td' ).eq( 1 ).attr( 'rowspan', '3' );
  
                $table.tablesorter();
  
                assert.strictEqual(
-                       $table.find( 'tr:eq(2) td:eq(1)' ).prop( 'rowSpan' ),
+                       $table.find( 'tr' ).eq( 2 ).find( 'td' ).eq( 1 ).prop( 'rowSpan' ),
                        3,
                        'Rowspan not exploded'
                );
                function ( $table ) {
                        // Modify the table to have a multiple-row-spanning cell:
                        // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
-                       $table.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
+                       $table.find( 'tr' ).eq( 3 ).find( 'td' ).eq( 1 ).remove();
+                       $table.find( 'tr' ).eq( 4 ).find( 'td' ).eq( 1 ).remove();
                        // - Set rowspan for 2nd cell of 3rd row to 3.
                        //   This covers the removed cell in the 4th and 5th row.
-                       $table.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
+                       $table.find( 'tr' ).eq( 2 ).find( 'td' ).eq( 1 ).attr( 'rowspan', '3' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
        tableTest(
                function ( $table ) {
                        // Modify the table to have a multiple-row-spanning cell:
                        // - Remove 2nd cell of 4th row, and, 2nd cell or 5th row.
-                       $table.find( 'tr:eq(3) td:eq(1), tr:eq(4) td:eq(1)' ).remove();
+                       $table.find( 'tr' ).eq( 3 ).find( 'td' ).eq( 1 ).remove();
+                       $table.find( 'tr' ).eq( 4 ).find( 'td' ).eq( 1 ).remove();
                        // - Set rowspan for 2nd cell of 3rd row to 3.
                        //   This covers the removed cell in the 4th and 5th row.
-                       $table.find( 'tr:eq(2) td:eq(1)' ).attr( 'rowspan', '3' );
+                       $table.find( 'tr' ).eq( 2 ).find( 'td' ).eq( 1 ).attr( 'rowspan', '3' );
  
                        $table.tablesorter( { sortList: [
                                { 0: 'asc' }
                function ( $table ) {
                        // Modify the table to have a multiple-row-spanning cell:
                        // - Remove 1st cell of 4th row, and, 1st cell or 5th row.
-                       $table.find( 'tr:eq(3) td:eq(0), tr:eq(4) td:eq(0)' ).remove();
+                       $table.find( 'tr' ).eq( 3 ).find( 'td' ).eq( 0 ).remove();
+                       $table.find( 'tr' ).eq( 4 ).find( 'td' ).eq( 0 ).remove();
                        // - Set rowspan for 1st cell of 3rd row to 3.
                        //   This covers the removed cell in the 4th and 5th row.
-                       $table.find( 'tr:eq(2) td:eq(0)' ).attr( 'rowspan', '3' );
+                       $table.find( 'tr' ).eq( 2 ).find( 'td' ).eq( 0 ).attr( 'rowspan', '3' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                        mw.config.set( 'wgDefaultDateFormat', 'mdy' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                currencySorted,
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                planets,
                planetsAscNameLegacy,
                function ( $table ) {
-                       $table.find( 'tr:last' ).addClass( 'sortbottom' );
+                       $table.find( 'tr' ).last().addClass( 'sortbottom' );
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                                '</table>'
                );
                $table.tablesorter();
-               $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                assert.strictEqual(
                        $table.data( 'tablesorter' ).config.parsers[ 0 ].id,
                                '<tr><td data-sort-value="Cherry">Dolphin</td></tr>' +
                                '</tbody></table>'
                );
-               $table.tablesorter().find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.tablesorter().find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                data = [];
                $table.find( 'tbody > tr' ).each( function ( i, tr ) {
                                '<tr><td><span data-sort-value="D">H</span></td></tr>' +
                                '</tbody></table>'
                );
-               $table.tablesorter().find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.tablesorter().find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                data = [];
                $table.find( 'tbody > tr' ).each( function ( i, tr ) {
                                '</tbody></table>'
                );
                // initialize table sorter and sort once
-               $table
-                       .tablesorter()
-                       .find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.tablesorter().find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                // Change the sortValue data properties (T40152)
                // - change data
                $table.find( 'td:contains(G)' ).removeData( 'sortValue' );
  
                // Now sort again (twice, so it is back at Ascending)
-               $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
-               $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
+               $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                data = [];
                $table.find( 'tbody > tr' ).each( function ( i, tr ) {
                [ 'Numbers' ], numbers, numbersAsc,
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                [ 'Numbers' ], numbers, reversed( numbersAsc ),
                function ( $table ) {
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' ).trigger( 'click' );
                }
        );
        // TODO add numbers sorting tests for T10115 with a different language
                $table.tablesorter();
  
                assert.strictEqual(
-                       $table.find( '> thead:eq(0) > tr > th.headerSort' ).length,
+                       $table.find( '> thead > tr > th.headerSort' ).length,
                        1,
                        'Child tables inside a headercell should not interfere with sortable headers (T34888)'
                );
                        mw.config.set( 'wgDefaultDateFormat', 'mdy' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                        mw.config.set( 'wgDefaultDateFormat', 'dmy' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                        mw.config.set( 'wgDefaultDateFormat', 'dmy' );
  
                        $table.tablesorter();
-                       $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+                       $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                }
        );
  
                                '<tr><td>1</td></tr>' +
                                '</table>'
                );
-               $table.tablesorter().find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.tablesorter().find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                assert.strictEqual(
                        $table.find( 'td' ).first().text(),
                                '<tr><td><img alt="A" />C</tr>' +
                                '</table>'
                );
-               $table.tablesorter().find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.tablesorter().find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                assert.strictEqual(
                        $table.find( 'td' ).text(),
                                '<tr><td>4</td></tr>' +
                                '</table>'
                );
-               $table.tablesorter().find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.tablesorter().find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                assert.strictEqual(
                        $table.find( 'td' ).text(),
                                '</tbody></table>' );
  
                        $table.tablesorter();
-                       assert.strictEqual( $table.find( 'tr:eq(1) th:eq(1)' ).data( 'headerIndex' ),
+                       assert.strictEqual( $table.find( 'tr' ).eq( 1 ).find( 'th' ).eq( 1 ).data( 'headerIndex' ),
                                2,
                                'Incorrect index of sort header'
                        );
                                '</table>'
                );
                $table.tablesorter();
-               $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
                // now the first row have 2 columns
-               $table.find( '.headerSort:eq(1)' ).trigger( 'click' );
+               $table.find( '.headerSort' ).eq( 1 ).trigger( 'click' );
  
                parsers = $table.data( 'tablesorter' ).config.parsers;
  
                );
  
                assert.strictEqual(
-                       parsers[ 1 ].format( $table.find( 'tbody > tr > td:eq(1)' ).text() ),
+                       parsers[ 1 ].format( $table.find( 'tbody > tr > td' ).eq( 1 ).text() ),
                        -Infinity,
                        'empty cell is sorted as number -Infinity'
                );
                                '</table>'
                );
                $table.tablesorter();
-               $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                assert.deepEqual(
                        tableExtract( $table ),
                                '</table>'
                );
                $table.tablesorter();
-               $table.find( '.headerSort:eq(0)' ).trigger( 'click' );
+               $table.find( '.headerSort' ).eq( 0 ).trigger( 'click' );
  
                assert.deepEqual(
                        tableExtract( $table ),