WordPress.org

Make WordPress Core

Ticket #48894: 48894.6.diff

File 48894.6.diff, 6.3 KB (added by isabel_brison, 17 months ago)

Add close on click outside and fix scroll.

  • src/js/_enqueues/lib/admin-bar.js

    diff --git a/src/js/_enqueues/lib/admin-bar.js b/src/js/_enqueues/lib/admin-bar.js
    index ea69ae7efe..e2802304ae 100644
    a b  
    1616        document.addEventListener( 'DOMContentLoaded', function() {
    1717                var adminBar = document.getElementById( 'wpadminbar' ),
    1818                        topMenuItems,
     19                        toggleMenuItems,
    1920                        allMenuItems,
    2021                        adminBarLogout,
    2122                        adminBarSearchForm,
     
    3031                }
    3132
    3233                topMenuItems = adminBar.querySelectorAll( 'li.menupop' );
     34                toggleMenuItems = adminBar.querySelectorAll( 'li.menupop > .ab-item' );
    3335                allMenuItems = adminBar.querySelectorAll( '.ab-item' );
    3436                adminBarLogout = document.getElementById( 'wp-admin-bar-logout' );
    3537                adminBarSearchForm = document.getElementById( 'adminbarsearch' );
     
    5658                                }
    5759
    5860                                adminBar.removeEventListener( 'touchstart', bindMobileEvents );
     61                                for ( i = 0; i < toggleMenuItems.length; i++ ) {
     62                                        // Remove click and keyboard event handlers that interfere with mobile behaviour.
     63                                        toggleMenuItems[i].removeEventListener( 'keydown', handleKeyDown );
     64                                        toggleMenuItems[i].removeEventListener( 'keyup', handleKeyUp );
     65                                        toggleMenuItems[i].removeEventListener( 'click', handleClick );
     66                                }
     67
    5968                        } );
    6069                }
    6170
     71                document.addEventListener('click', closeOpenMenus);
     72                document.addEventListener('keydown', closeOpenMenus);
     73
    6274                // Scroll page to top when clicking on the admin bar.
    6375                adminBar.addEventListener( 'click', scrollToTop );
    6476
    65                 for ( i = 0; i < topMenuItems.length; i++ ) {
    66                         // Adds or removes the hover class based on the hover intent.
    67                         window.hoverintent(
    68                                 topMenuItems[i],
    69                                 addClass.bind( null, topMenuItems[i], 'hover' ),
    70                                 removeClass.bind( null, topMenuItems[i], 'hover' )
    71                         ).options( {
    72                                 timeout: 180
    73                         } );
    74 
    75                         // Toggle hover class if the enter key is pressed.
    76                         topMenuItems[i].addEventListener( 'keydown', toggleHoverIfEnter );
    77                 }
    78 
    7977                // Remove hover class if the escape key is pressed.
    8078                for ( i = 0; i < allMenuItems.length; i++ ) {
    8179                        allMenuItems[i].addEventListener( 'keydown', removeHoverIfEscape );
    8280                }
     81               
     82                for ( i = 0; i < toggleMenuItems.length; i++ ) {
     83                        // Make the menu dropdown toggles be perceived and behave as buttons.
     84                        toggleMenuItems[i].setAttribute( 'role', 'button' );
     85                        toggleMenuItems[i].setAttribute( 'aria-expanded', 'false' );
     86
     87                        // Handle opening/closing menus with Enter.
     88                        toggleMenuItems[i].addEventListener( 'keydown', handleKeyDown );
     89                        // Handle opening/closing menus with Space.
     90                        toggleMenuItems[i].addEventListener( 'keyup', handleKeyUp );
     91                        // Handle opening/closing menus with click.
     92                        toggleMenuItems[i].addEventListener( 'click', handleClick );
     93                }
    8394
    8495                if ( adminBarSearchForm ) {
    8596                        adminBarSearchInput = document.getElementById( 'adminbar-search' );
     
    113124                if ( adminBarLogout ) {
    114125                        adminBarLogout.addEventListener( 'click', emptySessionStorage );
    115126                }
     127
     128        /**
     129         * Closes all open menus.
     130         *
     131         * @since 5.5.0
     132         *
     133         * @param {Event} event The captured event.
     134         */
     135        function closeOpenMenus( event ) {
     136                for ( i = 0; i < toggleMenuItems.length; i++ ) {
     137                        var wrapper = getClosest( toggleMenuItems[i], '.menupop' );
     138                        if ( wrapper.contains( event.target )  ) {
     139                                continue;
     140                        }
     141                        if ( wrapper.classList.contains( 'hover' ) ) {
     142                                wrapper.classList.remove( 'hover' );
     143                        }
     144                        if ( toggleMenuItems[i].getAttribute('aria-expanded') === 'true' ) {
     145                                toggleMenuItems[i].setAttribute( 'aria-expanded', 'false' );
     146                        }
     147                }
     148        }
     149
    116150        } );
    117151
     152        /**
     153         * Updates the My Account menu aria-expanded attribute.
     154         *
     155         * @since 5.5.0
     156         *
     157         * @param {HTMLElement} element The element to toggle aria-expanded on.
     158         */
     159        function toggleAriaExpanded( element ) {
     160                if ( element.getAttribute('aria-expanded') === 'true' ) {
     161                        element.setAttribute( 'aria-expanded', 'false' );
     162                } else {
     163                        element.setAttribute( 'aria-expanded', 'true' );
     164                }
     165        }
     166
    118167        /**
    119168         * Remove hover class for top level menu item when escape is pressed.
    120169         *
     
    123172         * @param {Event} event The keydown event.
    124173         */
    125174        function removeHoverIfEscape( event ) {
    126                 var wrapper;
     175                var wrapper,
     176                toggle;
    127177
    128178                if ( event.which !== 27 ) {
    129179                        return;
    130180                }
    131181
    132182                wrapper = getClosest( event.target, '.menupop' );
    133 
     183                toggle = wrapper.querySelector( '.menupop > .ab-item' );
    134184                if ( ! wrapper ) {
    135185                        return;
    136186                }
    137187
    138                 wrapper.querySelector( '.menupop > .ab-item' ).focus();
     188                toggle.focus();
     189                toggleAriaExpanded( toggle );
    139190                removeClass( wrapper, 'hover' );
    140191        }
    141192
    142193        /**
    143          * Toggle hover class for top level menu item when enter is pressed.
     194         * Handles the click event on dropdown toggles.
    144195         *
    145          * @since 5.3.1
     196         * @since 5.5.0
    146197         *
    147          * @param {Event} event The keydown event.
     198         * @param {Event} event The click event.
    148199         */
    149         function toggleHoverIfEnter( event ) {
    150                 var wrapper;
     200        function handleClick( event ) {
     201                event.preventDefault();
     202                var wrapper = getClosest( event.target, '.menupop' );
     203                wrapper.classList.toggle( 'hover' );
     204                toggleAriaExpanded( getClosest( event.target, '.ab-item' ) );
     205        }
    151206
    152                 if ( event.which !== 13 ) {
    153                         return;
    154                 }
     207        /**
     208         * Handles keyboard events on dropdown toggles.
     209         *
     210         * @since 5.5
     211         *
     212         * @param {Event} event The keyboard event.
     213         */
     214        function keyboardEventHandler( event ) {
     215                var wrapper = getClosest( event.target, '.menupop' );
    155216
    156                 if ( !! getClosest( event.target, '.ab-sub-wrapper' ) ) {
     217                if (
     218                        ! wrapper ||
     219                        !! getClosest( event.target, '.ab-sub-wrapper' )
     220                ) {
    157221                        return;
    158222                }
    159223
    160                 wrapper = getClosest( event.target, '.menupop' );
     224                event.preventDefault();
    161225
    162                 if ( ! wrapper ) {
     226                wrapper.classList.toggle( 'hover' );
     227                toggleAriaExpanded( event.target );
     228        }
     229
     230        /**
     231         * Handles the keydown event on dropdown toggles.
     232         *
     233         * @since 5.5
     234         *
     235         * @param {Event} event The keydown event.
     236         */
     237        function handleKeyDown( event ) {
     238                if ( event.which === 32 ) {
     239                        event.preventDefault;
     240                }
     241                if ( event.which !== 13 ) {
    163242                        return;
    164243                }
     244                keyboardEventHandler( event );
     245        }
    165246
    166                 event.preventDefault();
    167 
    168                 if ( hasClass( wrapper, 'hover' ) ) {
    169                         removeClass( wrapper, 'hover' );
    170                 } else {
    171                         addClass( wrapper, 'hover' );
     247        /**
     248         * Handles the keyup event on dropdown toggles.
     249         *
     250         * @since 5.5
     251         *
     252         * @param {Event} event The keyup event.
     253         */
     254        function handleKeyUp( event ) {
     255                if ( event.which !== 32 ) {
     256                        return;
    172257                }
     258                keyboardEventHandler( event );
    173259        }
    174260
    175261        /**