Make WordPress Core

Ticket #47145: 47145.2.diff

File 47145.2.diff, 7.2 KB (added by afercia, 4 years ago)
  • src/js/media/views/focus-manager.js

     
    1616
    1717        /**
    1818         * Gets all the tabbable elements.
     19         *
     20         * @since 5.3.0
     21         *
     22         * @returns {object} A jQuery collection of tabbable elements.
    1923         */
    2024        getTabbables: function() {
    2125                // Skip the file input added by Plupload.
     
    2428
    2529        /**
    2630         * Moves focus to the modal dialog.
     31         *
     32         * @since 3.5.0
     33         *
     34         * @returns {void}
    2735         */
    2836        focus: function() {
    2937                this.$( '.media-modal' ).focus();
     
    3038        },
    3139
    3240        /**
    33          * @param {Object} event
     41         * Constrains navigation with the Tab key within the media view element.
     42         *
     43         * @since 4.0.0
     44         *
     45         * @param {Object} event A keydown jQuery event.
     46         *
     47         * @returns {void}
    3448         */
    3549        constrainTabbing: function( event ) {
    3650                var tabbables;
     
    5064                        tabbables.last().focus();
    5165                        return false;
    5266                }
    53         }
     67        },
    5468
     69        /**
     70         * Hides from assistive technologies all the body children except the
     71         * provided element and other elements that should not be hidden.
     72         *
     73         * The reason why we use `aria-hidden` is that `aria-modal="true"` is buggy
     74         * in Safari 11.1 and support is spotty in other browsers. In the future we
     75         * should consider to remove this helper function and only use `aria-modal="true"`.
     76         *
     77         * @since 5.3.0
     78         *
     79         * @param {object} visibleElement The jQuery object representing the element that should not be hidden.
     80         *
     81         * @returns {void}
     82         */
     83        setAriaHiddenOnBodyChildren: function( visibleElement ) {
     84                var bodyChildren,
     85                        self = this;
     86
     87                if ( this.isBodyAriaHidden ) {
     88                        return;
     89                }
     90
     91                // Get all the body children.
     92                bodyChildren = document.body.children;
     93
     94                // Loop through the body children and hide the ones that should be hidden.
     95                _.each( bodyChildren, function( element ) {
     96                        // Don't hide the modal element.
     97                        if ( element === visibleElement[0] ) {
     98                                return;
     99                        }
     100
     101                        // Determine the body children to hide.
     102                        if ( self.elementShouldBeHidden( element ) ) {
     103                                element.setAttribute( 'aria-hidden', 'true' );
     104                                // Store the hidden elements.
     105                                self.ariaHiddenElements.push( element );
     106                        }
     107                } );
     108
     109                this.isBodyAriaHidden = true;
     110        },
     111
     112        /**
     113         * Makes visible again to assistive technologies all body children
     114         * previously hidden and stored in this.ariaHiddenElements.
     115         *
     116         * @since 5.3.0
     117         *
     118         * @returns {void}
     119         */
     120        removeAriaHiddenFromBodyChildren: function() {
     121                _.each( this.ariaHiddenElements, function( element ) {
     122                        element.removeAttribute( 'aria-hidden' );
     123                } );
     124
     125                this.ariaHiddenElements = [];
     126                this.isBodyAriaHidden   = false;
     127        },
     128
     129        /**
     130         * Determines if the passed element should not be hidden from assistive technologies.
     131         *
     132         * @since 5.3.0
     133         *
     134         * @param {object} element The DOM element that should be checked.
     135         *
     136         * @returns {boolean} Whether the element should not be hidden from assistive technologies.
     137         */
     138        elementShouldBeHidden: function( element ) {
     139                var role = element.getAttribute( 'role' ),
     140                        liveRegionsRoles = [ 'alert', 'status', 'log', 'marquee', 'timer' ];
     141
     142                /*
     143                 * Don't hide scripts, elements that already have `aria-hidden`, and
     144                 * ARIA live regions.
     145                 */
     146                return ! (
     147                        element.tagName === 'SCRIPT' ||
     148                        element.hasAttribute( 'aria-hidden' ) ||
     149                        element.hasAttribute( 'aria-live' ) ||
     150                        liveRegionsRoles.indexOf( role ) !== -1
     151                );
     152        },
     153
     154        /**
     155         * Whether the body children are hidden from assistive technologies.
     156         *
     157         * @since 5.3.0
     158         */
     159        isBodyAriaHidden: false,
     160
     161        /**
     162         * Stores an array of DOM elements that should be hidden from assistive
     163         * technologies, for example when the media modal dialog opens.
     164         *
     165         * @since 5.3.0
     166         */
     167        ariaHiddenElements: []
    55168});
    56169
    57170module.exports = FocusManager;
  • src/js/media/views/modal.js

     
    117117                // Set initial focus on the content instead of this view element, to avoid page scrolling.
    118118                this.$( '.media-modal' ).focus();
    119119
     120                // Hide the page content from assistive technologies.
     121                this.focusManager.setAriaHiddenOnBodyChildren( $el );
     122
    120123                return this.propagate('open');
    121124        },
    122125
     
    135138                // Hide modal and remove restricted media modal tab focus once it's closed
    136139                this.$el.hide().undelegate( 'keydown' );
    137140
     141                /*
     142                 * Make visible again to assistive technologies all body children that
     143                 * have been made hidden when the modal opened.
     144                 */
     145                this.focusManager.removeAriaHiddenFromBodyChildren();
     146
    138147                // Move focus back in useful location once modal is closed.
    139148                if ( null !== this.clickedOpenerEl ) {
    140149                        // Move focus back to the element that opened the modal.
  • src/wp-includes/css/media-views.css

     
    542542        right: 0;
    543543        bottom: 0;
    544544        margin: 0;
    545         padding: 10px 0;
     545        padding: 50px 0 10px;
    546546        background: #f3f3f3;
    547547        border-right-width: 1px;
    548548        border-right-style: solid;
     
    25302530
    25312531/* Landscape specific header override */
    25322532@media screen and (max-height: 400px) {
    2533         .media-menu {
    2534                 padding: 0;
     2533        .media-menu,
     2534        .media-frame:not(.hide-menu) .media-menu {
     2535                top: 44px;
    25352536        }
    25362537
    25372538        .media-frame-router {
     
    25522553        }
    25532554}
    25542555
     2556@media only screen and (min-width: 901px) and (max-height: 400px) {
     2557        .media-menu,
     2558        .media-frame:not(.hide-menu) .media-menu {
     2559                top: 0;
     2560                padding-top: 44px;
     2561        }
     2562}
     2563
    25552564@media only screen and (max-width: 480px) {
    25562565        .media-modal-close {
    25572566                top: -5px;
     
    25782587        .media-frame-router,
    25792588        .media-frame:not(.hide-menu) .media-menu {
    25802589                top: 40px;
     2590                padding-top: 0;
    25812591        }
    25822592
    25832593        .media-frame-content {
  • src/wp-includes/media-template.php

     
    177177
    178178        <?php // Template for the media frame: used both in the media grid and in the media modal. ?>
    179179        <script type="text/html" id="tmpl-media-frame">
     180                <div class="media-frame-title" id="media-frame-title"></div>
    180181                <div class="media-frame-menu"></div>
    181                 <div class="media-frame-title"></div>
    182182                <div class="media-frame-router"></div>
    183183                <div class="media-frame-content"></div>
    184184                <div class="media-frame-toolbar"></div>
     
    187187
    188188        <?php // Template for the media modal. ?>
    189189        <script type="text/html" id="tmpl-media-modal">
    190                 <div tabindex="0" class="<?php echo $class; ?>">
     190                <div tabindex="0" class="<?php echo $class; ?>" role="dialog" aria-modal="true" aria-labelledby="media-frame-title">
    191191                        <# if ( data.hasCloseButton ) { #>
    192192                                <button type="button" class="media-modal-close"><span class="media-modal-icon"><span class="screen-reader-text"><?php _e( 'Close dialog' ); ?></span></span></button>
    193193                        <# } #>
    194                         <div class="media-modal-content"></div>
     194                        <div class="media-modal-content" role="document"></div>
    195195                </div>
    196196                <div class="media-modal-backdrop"></div>
    197197        </script>