Make WordPress Core


Ignore:
Timestamp:
10/16/2017 05:58:07 PM (7 years ago)
Author:
afercia
Message:

Accessibility: Improve the File Editors interstitial warning.

The warning displayed upon first visit on the File Editors introduced in [41774]
needs to be the only perceivable content in the page for users of assistive
technologies. It looks like a modal but it's not exactly an ARIA dialog, not an
ARIA alert either, and needs some special treatment.

  • constrains tabbing within the modal
  • uses wp.a11y.speak() to make screen readers announce the modal message
  • hides all the other page content from assistive technologies using aria-hidden="true"

This way, even if users miss the speak message, the warning is actually the only
perceivable content in the page.

Fixes #42110.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/js/theme-plugin-editor.js

    r41864 r41876  
    5252
    5353        if ( component.warning.length > 0 ) {
    54             $( 'body' ).addClass( 'modal-open' );
    55             component.warning.find( '.file-editor-warning-go-back' ).focus();
    56             component.warning.on( 'click', '.file-editor-warning-dismiss', component.dismissWarning );
     54            component.showWarning();
    5755        }
    5856
     
    7977
    8078    /**
     79     * Set up and display the warning modal.
     80     *
     81     * @since 4.9.0
     82     * @returns {void}
     83     */
     84    component.showWarning = function() {
     85        // Get the text within the modal.
     86        var rawMessage = component.warning.find( '.file-editor-warning-message' ).text();
     87        // Hide all the #wpwrap content from assistive technologies.
     88        $( '#wpwrap' ).attr( 'aria-hidden', 'true' );
     89        // Detach the warning modal from its position and append it to the body.
     90        $( document.body )
     91            .addClass( 'modal-open' )
     92            .append( component.warning.detach() );
     93        // Reveal the modal and set focus on the go back button.
     94        component.warning
     95            .removeClass( 'hidden' )
     96            .find( '.file-editor-warning-go-back' ).focus();
     97        // Get the links and buttons within the modal.
     98        component.warningTabbables = component.warning.find( 'a, button' );
     99        // Attach event handlers.
     100        component.warningTabbables.on( 'keydown', component.constrainTabbing );
     101        component.warning.on( 'click', '.file-editor-warning-dismiss', component.dismissWarning );
     102        // Make screen readers announce the warning message after a short delay (necessary for some screen readers).
     103        setTimeout( function() {
     104            wp.a11y.speak( wp.sanitize.stripTags( rawMessage.replace( /\s+/g, ' ' ) ), 'assertive' );
     105        }, 1000 );
     106    };
     107
     108    /**
     109     * Constrain tabbing within the warning modal.
     110     *
     111     * @since 4.9.0
     112     * @param {object} event jQuery event object.
     113     * @returns {void}
     114     */
     115    component.constrainTabbing = function( event ) {
     116        var firstTabbable, lastTabbable;
     117
     118        if ( 9 !== event.which ) {
     119            return;
     120        }
     121
     122        firstTabbable = component.warningTabbables.first()[0];
     123        lastTabbable = component.warningTabbables.last()[0];
     124
     125        if ( lastTabbable === event.target && ! event.shiftKey ) {
     126            firstTabbable.focus();
     127            event.preventDefault();
     128        } else if ( firstTabbable === event.target && event.shiftKey ) {
     129            lastTabbable.focus();
     130            event.preventDefault();
     131        }
     132    };
     133
     134    /**
    81135     * Dismiss the warning modal.
    82136     *
     
    92146        // Hide modal.
    93147        component.warning.remove();
     148        $( '#wpwrap' ).removeAttr( 'aria-hidden' );
    94149        $( 'body' ).removeClass( 'modal-open' );
    95 
    96         // Return focus - is this a trap?
    97         component.instance.codemirror.focus();
    98150    };
    99151
Note: See TracChangeset for help on using the changeset viewer.