diff -r 3d4e9c994f10 -r a86126ab1dd4 wp/wp-includes/js/admin-bar.js --- a/wp/wp-includes/js/admin-bar.js Tue Oct 22 16:11:46 2019 +0200 +++ b/wp/wp-includes/js/admin-bar.js Tue Dec 15 13:49:49 2020 +0100 @@ -1,550 +1,453 @@ /** * @output wp-includes/js/admin-bar.js */ - -/* jshint loopfunc: true */ -// use jQuery and hoverIntent if loaded -if ( typeof(jQuery) != 'undefined' ) { - if ( typeof(jQuery.fn.hoverIntent) == 'undefined' ) { - /* jshint ignore:start */ - // hoverIntent v1.8.1 - Copy of wp-includes/js/hoverIntent.min.js - !function(a){a.fn.hoverIntent=function(b,c,d){var e={interval:100,sensitivity:6,timeout:0};e="object"==typeof b?a.extend(e,b):a.isFunction(c)?a.extend(e,{over:b,out:c,selector:d}):a.extend(e,{over:b,out:b,selector:c});var f,g,h,i,j=function(a){f=a.pageX,g=a.pageY},k=function(b,c){return c.hoverIntent_t=clearTimeout(c.hoverIntent_t),Math.sqrt((h-f)*(h-f)+(i-g)*(i-g)) .ab-item' ).focus(); + removeClass( wrapper, 'hover' ); + } + + /** + * Toggle hover class for top level menu item when enter is pressed. + * + * @since 5.3.1 + * + * @param {Event} event The keydown event. + */ + function toggleHoverIfEnter( event ) { + var wrapper; - adminbar.removeClass('nojq').removeClass('nojs'); + if ( event.which !== 13 ) { + return; + } + + if ( !! getClosest( event.target, '.ab-sub-wrapper' ) ) { + return; + } + + wrapper = getClosest( event.target, '.menupop' ); + + if ( ! wrapper ) { + return; + } + + event.preventDefault(); - // If clicked on the adminbar add the hoverclass, if clicked outside it remove - // it. - if ( 'ontouchstart' in window ) { - adminbar.on('touchstart', function(){ - touchOpen(true); - disableHoverIntent = true; - }); - touchClose(); - } else if ( /IEMobile\/[1-9]/.test(navigator.userAgent) ) { - touchOpen(); - touchClose(); + if ( hasClass( wrapper, 'hover' ) ) { + removeClass( wrapper, 'hover' ); + } else { + addClass( wrapper, 'hover' ); + } + } + + /** + * Focus the target of skip link after pressing Enter. + * + * @since 5.3.1 + * + * @param {Event} event The keydown event. + */ + function focusTargetAfterEnter( event ) { + var id, userAgent; + + if ( event.which !== 13 ) { + return; } - // Adds or removes the hover class based on the hover intent. - adminbar.find('li.menupop').hoverIntent({ - over: function() { - if ( disableHoverIntent ) - return; + id = event.target.getAttribute( 'href' ); + userAgent = navigator.userAgent.toLowerCase(); + + if ( userAgent.indexOf( 'applewebkit' ) > -1 && id && id.charAt( 0 ) === '#' ) { + setTimeout( function() { + var target = document.getElementById( id.replace( '#', '' ) ); + + if ( target ) { + target.setAttribute( 'tabIndex', '0' ); + target.focus(); + } + }, 100 ); + } + } - $(this).addClass('hover'); - }, - out: function() { - if ( disableHoverIntent ) - return; + /** + * Toogle hover class for mobile devices. + * + * @since 5.3.1 + * + * @param {NodeList} topMenuItems All menu items. + * @param {Event} event The click event. + */ + function mobileHover( topMenuItems, event ) { + var wrapper; + + if ( !! getClosest( event.target, '.ab-sub-wrapper' ) ) { + return; + } + + event.preventDefault(); + + wrapper = getClosest( event.target, '.menupop' ); - $(this).removeClass('hover'); - }, - timeout: 180, - sensitivity: 7, - interval: 100 - }); + if ( ! wrapper ) { + return; + } + + if ( hasClass( wrapper, 'hover' ) ) { + removeClass( wrapper, 'hover' ); + } else { + removeAllHoverClass( topMenuItems ); + addClass( wrapper, 'hover' ); + } + } - // Prevents the toolbar from covering up content when a hash is present in the - // URL. - if ( window.location.hash ) - window.scrollBy( 0, -32 ); + /** + * Handles the click on the Shortlink link in the adminbar. + * + * @since 3.1.0 + * @since 5.3.1 Use querySelector to clean up the function. + * + * @param {Event} event The click event. + * @return {boolean} Returns false to prevent default click behavior. + */ + function clickShortlink( event ) { + var wrapper = event.target.parentNode, + input; + + if ( wrapper ) { + input = wrapper.querySelector( '.shortlink-input' ); + } + + if ( ! input ) { + return; + } + + // (Old) IE doesn't support preventDefault, and does support returnValue. + if ( event.preventDefault ) { + event.preventDefault(); + } - /** - * Handles the selected state of the Shortlink link. - * - * When the input is visible the link should be selected, when the input is - * unfocused the link should be unselected. - * - * @param {Object} e The click event. - * - * @return {void} - **/ - $('#wp-admin-bar-get-shortlink').click(function(e){ - e.preventDefault(); - $(this).addClass('selected').children('.shortlink-input').blur(function(){ - $(this).parents('#wp-admin-bar-get-shortlink').removeClass('selected'); - }).focus().select(); - }); + event.returnValue = false; + + addClass( wrapper, 'selected' ); + + input.focus(); + input.select(); + input.onblur = function() { + removeClass( wrapper, 'selected' ); + }; + + return false; + } + + /** + * Clear sessionStorage on logging out. + * + * @since 5.3.1 + */ + function emptySessionStorage() { + if ( 'sessionStorage' in window ) { + try { + for ( var key in sessionStorage ) { + if ( key.indexOf( 'wp-autosave-' ) > -1 ) { + sessionStorage.removeItem( key ); + } + } + } catch ( er ) {} + } + } - /** - * Removes the hoverclass if the enter key is pressed. - * - * Makes sure the tab index is refreshed by refreshing each ab-item - * and its children. - * - * @param {Object} e The keydown event. - * - * @return {void} - */ - $('#wpadminbar li.menupop > .ab-item').bind('keydown.adminbar', function(e){ - // Key code 13 is the enter key. - if ( e.which != 13 ) - return; + /** + * Check if element has class. + * + * @since 5.3.1 + * + * @param {HTMLElement} element The HTML element. + * @param {string} className The class name. + * @return {boolean} Whether the element has the className. + */ + function hasClass( element, className ) { + var classNames; + + if ( ! element ) { + return false; + } - var target = $(e.target), - wrap = target.closest('.ab-sub-wrapper'), - parentHasHover = target.parent().hasClass('hover'); + if ( element.classList && element.classList.contains ) { + return element.classList.contains( className ); + } else if ( element.className ) { + classNames = element.className.split( ' ' ); + return classNames.indexOf( className ) > -1; + } - e.stopPropagation(); - e.preventDefault(); + return false; + } - if ( !wrap.length ) - wrap = $('#wpadminbar .quicklinks'); + /** + * Add class to an element. + * + * @since 5.3.1 + * + * @param {HTMLElement} element The HTML element. + * @param {string} className The class name. + */ + function addClass( element, className ) { + if ( ! element ) { + return; + } - wrap.find('.menupop').removeClass('hover'); - - if ( ! parentHasHover ) { - target.parent().toggleClass('hover'); + if ( element.classList && element.classList.add ) { + element.classList.add( className ); + } else if ( ! hasClass( element, className ) ) { + if ( element.className ) { + element.className += ' '; } - target.siblings('.ab-sub-wrapper').find('.ab-item').each(refresh); - }).each(refresh); - - /** - * Removes the hover class when the escape key is pressed. - * - * Makes sure the tab index is refreshed by refreshing each ab-item - * and its children. - * - * @param {Object} e The keydown event. - * - * @return {void} - */ - $('#wpadminbar .ab-item').bind('keydown.adminbar', function(e){ - // Key code 27 is the escape key. - if ( e.which != 27 ) - return; + element.className += className; + } + } - var target = $(e.target); - - e.stopPropagation(); - e.preventDefault(); - - target.closest('.hover').removeClass('hover').children('.ab-item').focus(); - target.siblings('.ab-sub-wrapper').find('.ab-item').each(refresh); - }); + /** + * Remove class from an element. + * + * @since 5.3.1 + * + * @param {HTMLElement} element The HTML element. + * @param {string} className The class name. + */ + function removeClass( element, className ) { + var testName, + classes; - /** - * Scrolls to top of page by clicking the adminbar. - * - * @param {Object} e The click event. - * - * @return {void} - */ - adminbar.click( function(e) { - if ( e.target.id != 'wpadminbar' && e.target.id != 'wp-admin-bar-top-secondary' ) { - return; + if ( ! element || ! hasClass( element, className ) ) { + return; + } + + if ( element.classList && element.classList.remove ) { + element.classList.remove( className ); + } else { + testName = ' ' + className + ' '; + classes = ' ' + element.className + ' '; + + while ( classes.indexOf( testName ) > -1 ) { + classes = classes.replace( testName, '' ); } - adminbar.find( 'li.menupop.hover' ).removeClass( 'hover' ); - $( 'html, body' ).animate( { scrollTop: 0 }, 'fast' ); - e.preventDefault(); - }); - - /** - * Sets the focus on an element with a href attribute. - * - * The timeout is used to fix a focus bug in WebKit. - * - * @param {Object} e The keydown event. - * - * @return {void} - */ - $('.screen-reader-shortcut').keydown( function(e) { - var id, ua; - - if ( 13 != e.which ) - return; - - id = $( this ).attr( 'href' ); - - ua = navigator.userAgent.toLowerCase(); - - if ( ua.indexOf('applewebkit') != -1 && id && id.charAt(0) == '#' ) { - setTimeout(function () { - $(id).focus(); - }, 100); - } - }); + element.className = classes.replace( /^[\s]+|[\s]+$/g, '' ); + } + } - $( '#adminbar-search' ).on({ - /** - * Adds the adminbar-focused class on focus. - * - * @return {void} - */ - focus: function() { - $( '#adminbarsearch' ).addClass( 'adminbar-focused' ); - /** - * Removes the adminbar-focused class on blur. - * - * @return {void} - */ - }, blur: function() { - $( '#adminbarsearch' ).removeClass( 'adminbar-focused' ); + /** + * Remove hover class for all menu items. + * + * @since 5.3.1 + * + * @param {NodeList} topMenuItems All menu items. + */ + function removeAllHoverClass( topMenuItems ) { + if ( topMenuItems && topMenuItems.length ) { + for ( var i = 0; i < topMenuItems.length; i++ ) { + removeClass( topMenuItems[i], 'hover' ); } - } ); + } + } - if ( 'sessionStorage' in window ) { - /** - * Empties sessionStorage on logging out. - * - * @return {void} - */ - $('#wp-admin-bar-logout a').click( function() { - try { - for ( var key in sessionStorage ) { - if ( key.indexOf('wp-autosave-') != -1 ) - sessionStorage.removeItem(key); - } - } catch(e) {} - }); - } - - if ( navigator.userAgent && document.body.className.indexOf( 'no-font-face' ) === -1 && - /Android (1.0|1.1|1.5|1.6|2.0|2.1)|Nokia|Opera Mini|w(eb)?OSBrowser|webOS|UCWEB|Windows Phone OS 7|XBLWP7|ZuneWP7|MSIE 7/.test( navigator.userAgent ) ) { - - document.body.className += ' no-font-face'; - } - }); -} else { /** - * Wrapper function for the adminbar that's used if jQuery isn't available. + * Scrolls to the top of the page. * - * @param {Object} d The document object. - * @param {Object} w The window object. + * @since 3.4.0 + * + * @param {Event} event The Click event. * * @return {void} */ - (function(d, w) { - /** - * Adds an event listener to an object. - * - * @since 3.1.0 - * - * @param {Object} obj The object to add the event listener to. - * @param {string} type The type of event. - * @param {function} fn The function to bind to the event listener. - * - * @return {void} - */ - var addEvent = function( obj, type, fn ) { - if ( obj && typeof obj.addEventListener === 'function' ) { - obj.addEventListener( type, fn, false ); - } else if ( obj && typeof obj.attachEvent === 'function' ) { - obj.attachEvent( 'on' + type, function() { - return fn.call( obj, window.event ); - } ); - } - }, - - aB, hc = new RegExp('\\bhover\\b', 'g'), q = [], - rselected = new RegExp('\\bselected\\b', 'g'), - - /** - * Gets the timeout ID of the given element. - * - * @since 3.1.0 - * - * @param {HTMLElement} el The HTML element. - * - * @return {number|boolean} The ID value of the timer that is set or false. - */ - getTOID = function(el) { - var i = q.length; - while ( i-- ) { - if ( q[i] && el == q[i][1] ) - return q[i][0]; - } - return false; - }, - - /** - * Adds the hoverclass to menu items. - * - * @since 3.1.0 - * - * @param {HTMLElement} t The HTML element. - * - * @return {void} - */ - addHoverClass = function(t) { - var i, id, inA, hovering, ul, li, - ancestors = [], - ancestorLength = 0; + function scrollToTop( event ) { + // Only scroll when clicking on the wpadminbar, not on menus or submenus. + if ( + event.target && + event.target.id !== 'wpadminbar' && + event.target.id !== 'wp-admin-bar-top-secondary' + ) { + return; + } - // aB is adminbar. d is document. - while ( t && t != aB && t != d ) { - if ( 'LI' == t.nodeName.toUpperCase() ) { - ancestors[ ancestors.length ] = t; - id = getTOID(t); - if ( id ) - clearTimeout( id ); - t.className = t.className ? ( t.className.replace(hc, '') + ' hover' ) : 'hover'; - hovering = t; - } - t = t.parentNode; - } - - // Removes any selected classes. - if ( hovering && hovering.parentNode ) { - ul = hovering.parentNode; - if ( ul && 'UL' == ul.nodeName.toUpperCase() ) { - i = ul.childNodes.length; - while ( i-- ) { - li = ul.childNodes[i]; - if ( li != hovering ) - li.className = li.className ? li.className.replace( rselected, '' ) : ''; - } - } - } - - // Removes the hover class for any objects not in the immediate element's ancestry. - i = q.length; - while ( i-- ) { - inA = false; - ancestorLength = ancestors.length; - while( ancestorLength-- ) { - if ( ancestors[ ancestorLength ] == q[i][1] ) - inA = true; - } - - if ( ! inA ) - q[i][1].className = q[i][1].className ? q[i][1].className.replace(hc, '') : ''; - } - }, - - /** - * Removes the hoverclass from menu items. - * - * @since 3.1.0 - * - * @param {HTMLElement} t The HTML element. - * - * @return {void} - */ - removeHoverClass = function(t) { - while ( t && t != aB && t != d ) { - if ( 'LI' == t.nodeName.toUpperCase() ) { - (function(t) { - var to = setTimeout(function() { - t.className = t.className ? t.className.replace(hc, '') : ''; - }, 500); - q[q.length] = [to, t]; - })(t); - } - t = t.parentNode; - } - }, + try { + window.scrollTo( { + top: -32, + left: 0, + behavior: 'smooth' + } ); + } catch ( er ) { + window.scrollTo( 0, -32 ); + } + } - /** - * Handles the click on the Shortlink link in the adminbar. - * - * @since 3.1.0 - * - * @param {Object} e The click event. - * - * @return {boolean} Returns false to prevent default click behavior. - */ - clickShortlink = function(e) { - var i, l, node, - t = e.target || e.srcElement; - - // Make t the shortlink menu item, or return. - while ( true ) { - // Check if we've gone past the shortlink node, - // or if the user is clicking on the input. - if ( ! t || t == d || t == aB ) - return; - // Check if we've found the shortlink node. - if ( t.id && t.id == 'wp-admin-bar-get-shortlink' ) - break; - t = t.parentNode; - } - - // IE doesn't support preventDefault, and does support returnValue - if ( e.preventDefault ) - e.preventDefault(); - e.returnValue = false; - - if ( -1 == t.className.indexOf('selected') ) - t.className += ' selected'; - - for ( i = 0, l = t.childNodes.length; i < l; i++ ) { - node = t.childNodes[i]; - if ( node.className && -1 != node.className.indexOf('shortlink-input') ) { - node.focus(); - node.select(); - node.onblur = function() { - t.className = t.className ? t.className.replace( rselected, '' ) : ''; - }; - break; - } - } - return false; - }, - - /** - * Scrolls to the top of the page. - * - * @since 3.4.0 - * - * @param {HTMLElement} t The HTML element. - * - * @return {void} - */ - scrollToTop = function(t) { - var distance, speed, step, steps, timer, speed_step; - - // Ensure that the #wpadminbar was the target of the click. - if ( t.id != 'wpadminbar' && t.id != 'wp-admin-bar-top-secondary' ) - return; - - distance = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; - - if ( distance < 1 ) - return; + /** + * Get closest Element. + * + * @since 5.3.1 + * + * @param {HTMLElement} el Element to get parent. + * @param {string} selector CSS selector to match. + */ + function getClosest( el, selector ) { + if ( ! window.Element.prototype.matches ) { + // Polyfill from https://developer.mozilla.org/en-US/docs/Web/API/Element/matches. + window.Element.prototype.matches = + window.Element.prototype.matchesSelector || + window.Element.prototype.mozMatchesSelector || + window.Element.prototype.msMatchesSelector || + window.Element.prototype.oMatchesSelector || + window.Element.prototype.webkitMatchesSelector || + function( s ) { + var matches = ( this.document || this.ownerDocument ).querySelectorAll( s ), + i = matches.length; - speed_step = distance > 800 ? 130 : 100; - speed = Math.min( 12, Math.round( distance / speed_step ) ); - step = distance > 800 ? Math.round( distance / 30 ) : Math.round( distance / 20 ); - steps = []; - timer = 0; - - // Animate scrolling to the top of the page by generating steps to - // the top of the page and shifting to each step at a set interval. - while ( distance ) { - distance -= step; - if ( distance < 0 ) - distance = 0; - steps.push( distance ); + while ( --i >= 0 && matches.item( i ) !== this ) { } - setTimeout( function() { - window.scrollTo( 0, steps.shift() ); - }, timer * speed ); - - timer++; - } - }; - - addEvent(w, 'load', function() { - aB = d.getElementById('wpadminbar'); - - if ( d.body && aB ) { - d.body.appendChild( aB ); - - if ( aB.className ) - aB.className = aB.className.replace(/nojs/, ''); - - addEvent(aB, 'mouseover', function(e) { - addHoverClass( e.target || e.srcElement ); - }); + return i > -1; + }; + } - addEvent(aB, 'mouseout', function(e) { - removeHoverClass( e.target || e.srcElement ); - }); - - addEvent(aB, 'click', clickShortlink ); - - addEvent(aB, 'click', function(e) { - scrollToTop( e.target || e.srcElement ); - }); + // Get the closest matching elent. + for ( ; el && el !== document; el = el.parentNode ) { + if ( el.matches( selector ) ) { + return el; + } + } - addEvent( document.getElementById('wp-admin-bar-logout'), 'click', function() { - if ( 'sessionStorage' in window ) { - try { - for ( var key in sessionStorage ) { - if ( key.indexOf('wp-autosave-') != -1 ) - sessionStorage.removeItem(key); - } - } catch(e) {} - } - }); - } + return null; + } - if ( w.location.hash ) - w.scrollBy(0,-32); - - if ( navigator.userAgent && document.body.className.indexOf( 'no-font-face' ) === -1 && - /Android (1.0|1.1|1.5|1.6|2.0|2.1)|Nokia|Opera Mini|w(eb)?OSBrowser|webOS|UCWEB|Windows Phone OS 7|XBLWP7|ZuneWP7|MSIE 7/.test( navigator.userAgent ) ) { - - document.body.className += ' no-font-face'; - } - }); - })(document, window); - -} +} )( document, window, navigator );