Merge "tablesorter: Keyboard accessibility for sort headers."
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 23 Jul 2013 13:21:58 +0000 (13:21 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 23 Jul 2013 13:21:58 +0000 (13:21 +0000)
1  2 
resources/jquery/jquery.tablesorter.js

  
        function buildHeaders( table, msg ) {
                var maxSeen = 0,
 +                      colspanOffset = 0,
                        longest,
 -                      realCellIndex = 0,
 +                      columns,
 +                      i,
                        $tableHeaders = $( [] ),
                        $tableRows = $( 'thead:eq(0) > tr', table );
                if ( $tableRows.length <= 1 ) {
                } else {
                        // We need to find the cells of the row containing the most columns
                        var rowspan,
 -                              i,
                                headersIndex = [];
                        $tableRows.each( function ( rowIndex ) {
                                $.each( this.cells, function( index2, cell ) {
                        } );
                        $tableHeaders = headersIndex[longest];
                }
 -              $tableHeaders.each( function ( index ) {
 -                      this.column = realCellIndex;
  
 -                      var colspan = this.colspan;
 -                      colspan = colspan ? parseInt( colspan, 10 ) : 1;
 -                      realCellIndex += colspan;
 +              // as each header can span over multiple columns (using colspan=N),
 +              // we have to bidirectionally map headers to their columns and columns to their headers
 +              table.headerToColumns = [];
 +              table.columnToHeader = [];
  
 +              $tableHeaders.each( function ( headerIndex ) {
 +                      columns = [];
 +                      for ( i = 0; i < this.colSpan; i++ ) {
 +                              table.columnToHeader[ colspanOffset + i ] = headerIndex;
 +                              columns.push( colspanOffset + i );
 +                      }
 +
 +                      table.headerToColumns[ headerIndex ] = columns;
 +                      colspanOffset += this.colSpan;
 +
 +                      this.headerIndex = headerIndex;
                        this.order = 0;
                        this.count = 0;
  
                        }
  
                        if ( !this.sortDisabled ) {
-                               $( this ).addClass( table.config.cssHeader ).attr( 'title', msg[1] );
+                               $( this )
+                                       .addClass( table.config.cssHeader )
+                                       .attr( 'title', msg[1] )
+                                       .prop( 'tabIndex', 0 ).attr( 'role', 'button' );
                        }
  
                        // add cell to headerList
 -                      table.config.headerList[index] = this;
 +                      table.config.headerList[headerIndex] = this;
                } );
  
                return $tableHeaders;
                                return $tables.each( function ( i, table ) {
                                        // Declare and cache.
                                        var $headers, cache, config,
 -                                              headerToColumns, columnToHeader, colspanOffset,
                                                $table = $( table ),
                                                firstTime = true;
  
                                                table.config.parsers = buildParserCache( table, $headers );
                                        }
  
 -                                      // as each header can span over multiple columns (using colspan=N),
 -                                      // we have to bidirectionally map headers to their columns and columns to their headers
 -                                      headerToColumns = [];
 -                                      columnToHeader = [];
 -                                      colspanOffset = 0;
 -                                      $headers.each( function ( headerIndex ) {
 -                                              var columns = [];
 -                                              for ( var i = 0; i < this.colSpan; i++ ) {
 -                                                      columnToHeader[ colspanOffset + i ] = headerIndex;
 -                                                      columns.push( colspanOffset + i );
 -                                              }
 -
 -                                              headerToColumns[ headerIndex ] = columns;
 -                                              colspanOffset += this.colSpan;
 -                                      } );
 -
                                        // Apply event handling to headers
                                        // this is too big, perhaps break it out?
-                                       $headers.filter( ':not(.unsortable)' ).click( function ( e ) {
-                                               if ( e.target.nodeName.toLowerCase() === 'a' ) {
-                                                       // The user clicked on a link inside a table header
-                                                       // Do nothing and let the default link click action continue
+                                       $headers.filter( ':not(.unsortable)' ).on( 'keypress click', function ( e ) {
+                                               if ( e.type === 'click' && e.target.nodeName.toLowerCase() === 'a' ) {
+                                                       // The user clicked on a link inside a table header.
+                                                       // Do nothing and let the default link click action continue.
+                                                       return true;
+                                               }
+                                               if ( e.type === 'keypress' && e.which !== 13 ) {
+                                                       // Only handle keypresses on the "Enter" key.
                                                        return true;
                                                }
  
  
                                                        var cell = this;
                                                        // Get current column index
 -                                                      var columns = headerToColumns[this.column];
 +                                                      var columns = table.headerToColumns[ this.headerIndex ];
                                                        var newSortList = $.map( columns, function (c) {
                                                                // jQuery "helpfully" flattens the arrays...
                                                                return [[c, cell.order]];
                                                        }
  
                                                        // Reset order/counts of cells not affected by sorting
 -                                                      setHeadersOrder( $headers, config.sortList, headerToColumns );
 +                                                      setHeadersOrder( $headers, config.sortList, table.headerToColumns );
  
                                                        // Set CSS for headers
 -                                                      setHeadersCss( $table[0], $headers, config.sortList, sortCSS, sortMsg, columnToHeader );
 +                                                      setHeadersCss( $table[0], $headers, config.sortList, sortCSS, sortMsg, table.columnToHeader );
                                                        appendToTable(
                                                                $table[0], multisort( $table[0], config.sortList, cache )
                                                        );
  
                                                // Set each column's sort count to be able to determine the correct sort
                                                // order when clicking on a header cell the next time
 -                                              setHeadersOrder( $headers, sortList, headerToColumns );
 +                                              setHeadersOrder( $headers, sortList, table.headerToColumns );
  
                                                // re-build the cache for the tbody cells
                                                cache = buildCache( table );
  
                                                // set css for headers
 -                                              setHeadersCss( table, $headers, sortList, sortCSS, sortMsg, columnToHeader );
 +                                              setHeadersCss( table, $headers, sortList, sortCSS, sortMsg, table.columnToHeader );
  
                                                // sort the table and append it to the dom
                                                appendToTable( table, multisort( table, sortList, cache ) );