Make WordPress Core


Ignore:
Timestamp:
06/21/2023 09:45:52 PM (11 months ago)
Author:
joedolson
Message:

Administration: Set accessible state for list table headers.

Implement aria-sort and change icon states to indicate current sort for list tables. Allow screen reader users to get context about the current sort and allow sighted users to know how the table is currently sorted.

Props afercia, rianrietveld, joedolson, alexstine, johnjamesjacoby.
Fixes #32170.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/class-wp-list-table.php

    r55954 r55971  
    11101110     * The format is:
    11111111     * - `'internal-name' => 'orderby'`
     1112     * - `'internal-name' => array( 'orderby', bool, 'abbr', 'orderby-text', 'initially-sorted-column-order' )` -
    11121113     * - `'internal-name' => array( 'orderby', 'asc' )` - The second element sets the initial sorting order.
    11131114     * - `'internal-name' => array( 'orderby', true )`  - The second element makes the initial order descending.
    11141115     *
    1115      * @since 3.1.0
     1116     * In the second format, passing true as second parameter will make the initial
     1117     * sorting order be descending. Following parameters add a short column name to
     1118     * be used as 'abbr' attribute, a translatable string for the current sorting
     1119     * and the initial order for the initial sorted column, 'asc' or 'desc' (default: false).
     1120     *
     1121     * @since 3.1.0
     1122     * @since 6.3.0 Added 'abbr', 'orderby-text' and 'initially-sorted-column-order'.
    11161123     *
    11171124     * @return array
     
    12541261
    12551262            $data = (array) $data;
     1263            // Descending initial sorting.
    12561264            if ( ! isset( $data[1] ) ) {
    12571265                $data[1] = false;
     1266            }
     1267            // Current sorting translatable string.
     1268            if ( ! isset( $data[2] ) ) {
     1269                $data[2] = '';
     1270            }
     1271            // Initial view sorted column and asc/desc order, default: false.
     1272            if ( ! isset( $data[3] ) ) {
     1273                $data[3] = false;
     1274            }
     1275            // Initial order for the initial sorted column, default: false.
     1276            if ( ! isset( $data[4] ) ) {
     1277                $data[4] = false;
    12581278            }
    12591279
     
    12931313        $current_url = remove_query_arg( 'paged', $current_url );
    12941314
     1315        // When users click on a column header to sort by other columns.
    12951316        if ( isset( $_GET['orderby'] ) ) {
    12961317            $current_orderby = $_GET['orderby'];
     1318            // In the initial view there's no orderby parameter.
    12971319        } else {
    12981320            $current_orderby = '';
    12991321        }
    13001322
    1301         if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
     1323        // Not in the initial view and descending order.
     1324        if ( isset( $_GET['order'] ) && 'desc' == $_GET['order'] ) {
    13021325            $current_order = 'desc';
    13031326        } else {
     1327            // The initial view is not always 'asc' we'll take care of this below.
    13041328            $current_order = 'asc';
    13051329        }
     
    13181342
    13191343        foreach ( $columns as $column_key => $column_display_name ) {
    1320             $class = array( 'manage-column', "column-$column_key" );
     1344            $class          = array( 'manage-column', "column-$column_key" );
     1345            $aria_sort_attr = '';
     1346            $abbr_attr      = '';
     1347            $order_text     = '';
    13211348
    13221349            if ( in_array( $column_key, $hidden, true ) ) {
     
    13351362
    13361363            if ( isset( $sortable[ $column_key ] ) ) {
    1337                 list( $orderby, $desc_first ) = $sortable[ $column_key ];
    1338 
     1364                list( $orderby, $desc_first, $abbr, $orderby_text, $initial_order ) = $sortable[ $column_key ];
     1365
     1366                /*
     1367                 * We're in the initial view and there's no $_GET['orderby'] then check if the
     1368                 * initial sorting information is set in the sortable columns and use that.
     1369                 */
     1370                if ( '' === $current_orderby && $initial_order ) {
     1371                    // Use the initially sorted column $orderby as current orderby.
     1372                    $current_orderby = $orderby;
     1373                    // Use the initially sorted column asc/desc order as initial order.
     1374                    $current_order = $initial_order;
     1375                }
     1376
     1377                /*
     1378                 * True in the initial view when an initial orderby is set via get_sortable_columns()
     1379                 * and true in the sorted views when the actual $_GET['orderby'] is equal to $orderby.
     1380                 */
    13391381                if ( $current_orderby === $orderby ) {
    1340                     $order = 'asc' === $current_order ? 'desc' : 'asc';
    1341 
     1382                    // The sorted column. The `aria-sort` attribute must be set only on the sorted column.
     1383                    if ( 'asc' == $current_order ) {
     1384                        $order          = 'desc';
     1385                        $aria_sort_attr = ' aria-sort="ascending"';
     1386                    } else {
     1387                        $order          = 'asc';
     1388                        $aria_sort_attr = ' aria-sort="descending"';
     1389                    }
    13421390                    $class[] = 'sorted';
    13431391                    $class[] = $current_order;
    13441392                } else {
     1393                    // The other sortable columns.
    13451394                    $order = strtolower( $desc_first );
    13461395
     
    13491398                    }
    13501399
    1351                     $class[] = 'sortable';
    1352                     $class[] = 'desc' === $order ? 'asc' : 'desc';
     1400                    $class[]    = 'sortable';
     1401                    $class[]    = 'desc' === $order ? 'asc' : 'desc';
     1402                    $order_text = 'asc' === $order ? __( 'Sort ascending.' ) : __( 'Sort descending.' );
    13531403                }
    1354 
    1355                 $column_display_name = sprintf(
    1356                     '<a href="%s"><span>%s</span><span class="sorting-indicator"></span></a>',
    1357                     esc_url( add_query_arg( compact( 'orderby', 'order' ), $current_url ) ),
    1358                     $column_display_name
    1359                 );
     1404                if ( '' !== $order_text ) {
     1405                    $order_text = ' <span class="screen-reader-text">' . $order_text . '</span>';
     1406                }
     1407
     1408                // Print an 'abbr' attribute if a value is provided via get_sortable_columns().
     1409                $abbr_attr           = $abbr ? ' abbr="' . esc_attr( $abbr ) . '"' : '';
     1410                $column_display_name = '<a href="' . esc_url( add_query_arg( compact( 'orderby', 'order' ), $current_url ) ) . '"><span>' . $column_display_name . '</span><span class="sorting-indicators"><span class="sorting-indicator asc" aria-hidden="true"></span><span class="sorting-indicator desc" aria-hidden="true"></span>' . $order_text . '</a>';
    13601411            }
    13611412
     
    13681419            }
    13691420
    1370             echo "<$tag $scope $id $class>$column_display_name</$tag>";
     1421            echo "<$tag $scope $id $class $aria_sort_attr $abbr_attr>$column_display_name</$tag>";
     1422        }
     1423    }
     1424
     1425    /**
     1426     * Print a table description with information about current sorting and order.
     1427     *
     1428     * For the table initial view, information about initial orderby and order
     1429     * should be provided via get_sortable_columns().
     1430     *
     1431     * @since 4.3.0
     1432     * @access public
     1433     */
     1434    public function print_table_description() {
     1435        list( $columns, $hidden, $sortable ) = $this->get_column_info();
     1436
     1437        if ( empty( $sortable ) ) {
     1438            return;
     1439        }
     1440
     1441        // When users click on a column header to sort by other columns.
     1442        if ( isset( $_GET['orderby'] ) ) {
     1443            $current_orderby = $_GET['orderby'];
     1444            // In the initial view there's no orderby parameter.
     1445        } else {
     1446            $current_orderby = '';
     1447        }
     1448
     1449        // Not in the initial view and descending order.
     1450        if ( isset( $_GET['order'] ) && 'desc' == $_GET['order'] ) {
     1451            $current_order = 'desc';
     1452        } else {
     1453            // The initial view is not always 'asc' we'll take care of this below.
     1454            $current_order = 'asc';
     1455        }
     1456
     1457        foreach ( array_keys( $columns ) as $column_key ) {
     1458
     1459            if ( isset( $sortable[ $column_key ] ) ) {
     1460
     1461                list( $orderby, $desc_first, $abbr, $orderby_text, $initial_order ) = $sortable[ $column_key ];
     1462
     1463                if ( ! is_string( $orderby_text ) || '' === $orderby_text ) {
     1464                    return;
     1465                }
     1466                /*
     1467                 * We're in the initial view and there's no $_GET['orderby'] then check if the
     1468                 * initial sorting information is set in the sortable columns and use that.
     1469                 */
     1470                if ( '' === $current_orderby && $initial_order ) {
     1471                    // Use the initially sorted column $orderby as current orderby.
     1472                    $current_orderby = $orderby;
     1473                    // Use the initially sorted column asc/desc order as initial order.
     1474                    $current_order = $initial_order;
     1475                }
     1476
     1477                /*
     1478                 * True in the initial view when an initial orderby is set via get_sortable_columns()
     1479                 * and true in the sorted views when the actual $_GET['orderby'] is equal to $orderby.
     1480                 */
     1481                if ( $current_orderby == $orderby ) {
     1482                    $order_text = 'asc' === $current_order ? __( 'Ascending.' ) : __( 'Descending.' );
     1483                    echo '<caption  class="screen-reader-text">' . $orderby_text . ' ' . $order_text . '</p>';
     1484
     1485                    return;
     1486                }
     1487            }
    13711488        }
    13721489    }
     
    13851502        ?>
    13861503<table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
     1504        <?php $this->print_table_description(); ?>
    13871505    <thead>
    13881506    <tr>
Note: See TracChangeset for help on using the changeset viewer.