450 lines
14 KiB
JavaScript
450 lines
14 KiB
JavaScript
( function() {
|
|
'use strict';
|
|
var allSubMenus = document.querySelectorAll( '.main-nav .sub-menu, .main-nav .children' );
|
|
|
|
// Add missing aria roles and attributes for accessibility.
|
|
if ( allSubMenus ) {
|
|
allSubMenus.forEach( function( subMenu ) {
|
|
var parentLi = subMenu.closest( 'li' );
|
|
var button = parentLi.querySelector( '.dropdown-menu-toggle[role="button"]' );
|
|
|
|
if ( ! subMenu.id ) {
|
|
var itemId = parentLi.id
|
|
? parentLi.id
|
|
: 'menu-item-' + Math.floor( Math.random() * 100000 ); // Just in case our menu item has no ID.
|
|
|
|
subMenu.id = itemId + '-sub-menu';
|
|
}
|
|
|
|
// Bail if no button to update
|
|
if ( ! button ) {
|
|
button = parentLi.querySelector( 'a[role="button"]' );
|
|
|
|
if ( ! button ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
button.setAttribute( 'aria-controls', subMenu.id );
|
|
} );
|
|
}
|
|
|
|
if ( 'querySelector' in document && 'addEventListener' in window ) {
|
|
/**
|
|
* matches() pollyfil
|
|
*
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Browser_compatibility
|
|
*/
|
|
if ( ! Element.prototype.matches ) {
|
|
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
|
|
}
|
|
|
|
/**
|
|
* closest() pollyfil
|
|
*
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Browser_compatibility
|
|
* @param {Object} s The element to check.
|
|
* @return {Object} The closest object.
|
|
*/
|
|
if ( ! Element.prototype.closest ) {
|
|
Element.prototype.closest = function( s ) {
|
|
var el = this;
|
|
var ancestor = this;
|
|
if ( ! document.documentElement.contains( el ) ) {
|
|
return null;
|
|
}
|
|
do {
|
|
if ( ancestor.matches( s ) ) {
|
|
return ancestor;
|
|
}
|
|
ancestor = ancestor.parentElement;
|
|
} while ( ancestor !== null );
|
|
return null;
|
|
};
|
|
}
|
|
|
|
var getSiblings = function( elem ) {
|
|
return Array.prototype.filter.call( elem.parentNode.children, function( sibling ) {
|
|
return sibling !== elem;
|
|
} );
|
|
};
|
|
|
|
var allNavToggles = document.querySelectorAll( '.menu-toggle' ),
|
|
dropdownToggles = document.querySelectorAll( 'nav .dropdown-menu-toggle' ),
|
|
navLinks = document.querySelectorAll( 'nav .main-nav ul a' ),
|
|
mobileMenuControls = document.querySelector( '.mobile-menu-control-wrapper' ),
|
|
body = document.body,
|
|
htmlEl = document.documentElement,
|
|
i;
|
|
|
|
var enableDropdownArrows = function( nav ) {
|
|
if ( nav && body.classList.contains( 'dropdown-hover' ) ) {
|
|
var dropdownItems = nav.querySelectorAll( 'li.menu-item-has-children' );
|
|
|
|
for ( i = 0; i < dropdownItems.length; i++ ) {
|
|
var toggle = dropdownItems[ i ].querySelector( '.dropdown-menu-toggle' );
|
|
var parentLi = toggle.closest( 'li' );
|
|
var subMenu = parentLi.querySelector( '.sub-menu, .children' );
|
|
|
|
toggle.setAttribute( 'tabindex', '0' );
|
|
toggle.setAttribute( 'role', 'button' );
|
|
toggle.setAttribute( 'aria-expanded', 'false' );
|
|
toggle.setAttribute( 'aria-controls', subMenu.id );
|
|
toggle.setAttribute( 'aria-label', generatepressMenu.openSubMenuLabel );
|
|
}
|
|
}
|
|
};
|
|
|
|
var disableDropdownArrows = function( nav ) {
|
|
if ( nav && body.classList.contains( 'dropdown-hover' ) ) {
|
|
var dropdownItems = nav.querySelectorAll( 'li.menu-item-has-children' );
|
|
|
|
for ( i = 0; i < dropdownItems.length; i++ ) {
|
|
dropdownItems[ i ].querySelector( '.dropdown-menu-toggle' ).removeAttribute( 'tabindex' );
|
|
dropdownItems[ i ].querySelector( '.dropdown-menu-toggle' ).setAttribute( 'role', 'presentation' );
|
|
dropdownItems[ i ].querySelector( '.dropdown-menu-toggle' ).removeAttribute( 'aria-expanded' );
|
|
dropdownItems[ i ].querySelector( '.dropdown-menu-toggle' ).removeAttribute( 'aria-controls' );
|
|
dropdownItems[ i ].querySelector( '.dropdown-menu-toggle' ).removeAttribute( 'aria-label' );
|
|
}
|
|
}
|
|
};
|
|
|
|
var setDropdownArrowAttributes = function( arrow ) {
|
|
if ( 'false' === arrow.getAttribute( 'aria-expanded' ) || ! arrow.getAttribute( 'aria-expanded' ) ) {
|
|
arrow.setAttribute( 'aria-expanded', 'true' );
|
|
arrow.setAttribute( 'aria-label', generatepressMenu.closeSubMenuLabel );
|
|
} else {
|
|
arrow.setAttribute( 'aria-expanded', 'false' );
|
|
arrow.setAttribute( 'aria-label', generatepressMenu.openSubMenuLabel );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Start mobile menu toggle.
|
|
*
|
|
* @param {Object} e The event.
|
|
* @param {Object} _this The clicked item.
|
|
*/
|
|
var toggleNav = function( e, _this ) {
|
|
if ( ! _this ) {
|
|
_this = this;
|
|
}
|
|
|
|
var parentContainer = '';
|
|
|
|
if ( _this.getAttribute( 'data-nav' ) ) {
|
|
parentContainer = document.getElementById( _this.getAttribute( 'data-nav' ) );
|
|
} else {
|
|
parentContainer = document.getElementById( _this.closest( 'nav' ).getAttribute( 'id' ) );
|
|
}
|
|
|
|
if ( ! parentContainer ) {
|
|
return;
|
|
}
|
|
|
|
var isExternalToggle = false;
|
|
|
|
if ( _this.closest( '.mobile-menu-control-wrapper' ) ) {
|
|
isExternalToggle = true;
|
|
}
|
|
|
|
var nav = parentContainer.getElementsByTagName( 'ul' )[ 0 ];
|
|
|
|
if ( parentContainer.classList.contains( 'toggled' ) ) {
|
|
parentContainer.classList.remove( 'toggled' );
|
|
htmlEl.classList.remove( 'mobile-menu-open' );
|
|
|
|
if ( nav ) {
|
|
nav.setAttribute( 'aria-hidden', 'true' );
|
|
}
|
|
|
|
_this.setAttribute( 'aria-expanded', 'false' );
|
|
|
|
if ( isExternalToggle ) {
|
|
mobileMenuControls.classList.remove( 'toggled' );
|
|
} else if ( mobileMenuControls && parentContainer.classList.contains( 'main-navigation' ) ) {
|
|
mobileMenuControls.classList.remove( 'toggled' );
|
|
}
|
|
|
|
disableDropdownArrows( nav );
|
|
} else {
|
|
parentContainer.classList.add( 'toggled' );
|
|
htmlEl.classList.add( 'mobile-menu-open' );
|
|
|
|
if ( nav ) {
|
|
nav.setAttribute( 'aria-hidden', 'false' );
|
|
}
|
|
|
|
_this.setAttribute( 'aria-expanded', 'true' );
|
|
|
|
if ( isExternalToggle ) {
|
|
mobileMenuControls.classList.add( 'toggled' );
|
|
|
|
if ( mobileMenuControls.querySelector( '.search-item' ) ) {
|
|
if ( mobileMenuControls.querySelector( '.search-item' ).classList.contains( 'active' ) ) {
|
|
mobileMenuControls.querySelector( '.search-item' ).click();
|
|
}
|
|
}
|
|
} else if ( mobileMenuControls && parentContainer.classList.contains( 'main-navigation' ) ) {
|
|
mobileMenuControls.classList.add( 'toggled' );
|
|
}
|
|
|
|
enableDropdownArrows( nav );
|
|
}
|
|
};
|
|
|
|
for ( i = 0; i < allNavToggles.length; i++ ) {
|
|
allNavToggles[ i ].addEventListener( 'click', toggleNav, false );
|
|
}
|
|
|
|
/**
|
|
* Open sub-menus
|
|
*
|
|
* @param {Object} e The event.
|
|
* @param {Object} _this The clicked item.
|
|
*/
|
|
var toggleSubNav = function( e, _this ) {
|
|
if ( ! _this ) {
|
|
_this = this;
|
|
}
|
|
|
|
if ( ( _this.closest( 'nav' ).classList.contains( 'toggled' ) || htmlEl.classList.contains( 'slide-opened' ) ) && ! body.classList.contains( 'dropdown-click' ) ) {
|
|
e.preventDefault();
|
|
var closestLi = _this.closest( 'li' );
|
|
|
|
setDropdownArrowAttributes( closestLi.querySelector( '.dropdown-menu-toggle' ) );
|
|
|
|
if ( closestLi.querySelector( '.sub-menu' ) ) {
|
|
var subMenu = closestLi.querySelector( '.sub-menu' );
|
|
} else {
|
|
subMenu = closestLi.querySelector( '.children' );
|
|
}
|
|
|
|
if ( generatepressMenu.toggleOpenedSubMenus ) {
|
|
var siblings = getSiblings( closestLi );
|
|
|
|
for ( i = 0; i < siblings.length; i++ ) {
|
|
if ( siblings[ i ].classList.contains( 'sfHover' ) ) {
|
|
siblings[ i ].classList.remove( 'sfHover' );
|
|
siblings[ i ].querySelector( '.toggled-on' ).classList.remove( 'toggled-on' );
|
|
setDropdownArrowAttributes( siblings[ i ].querySelector( '.dropdown-menu-toggle' ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
closestLi.classList.toggle( 'sfHover' );
|
|
subMenu.classList.toggle( 'toggled-on' );
|
|
}
|
|
|
|
e.stopPropagation();
|
|
};
|
|
|
|
for ( i = 0; i < dropdownToggles.length; i++ ) {
|
|
dropdownToggles[ i ].addEventListener( 'click', toggleSubNav, false );
|
|
dropdownToggles[ i ].addEventListener( 'keypress', function( e ) {
|
|
if ( 'Enter' === e.key || ' ' === e.key ) {
|
|
toggleSubNav( e, this );
|
|
}
|
|
}, false );
|
|
}
|
|
|
|
/**
|
|
* Disable the mobile menu if our toggle isn't visible.
|
|
* Makes it possible to style mobile item with .toggled class.
|
|
*/
|
|
var checkMobile = function() {
|
|
var openedMobileMenus = document.querySelectorAll( '.toggled, .has-active-search' );
|
|
|
|
for ( i = 0; i < openedMobileMenus.length; i++ ) {
|
|
var menuToggle = openedMobileMenus[ i ].querySelector( '.menu-toggle' );
|
|
|
|
if ( mobileMenuControls && ! menuToggle.closest( 'nav' ).classList.contains( 'mobile-menu-control-wrapper' ) ) {
|
|
menuToggle = mobileMenuControls.querySelector( '.menu-toggle' );
|
|
}
|
|
|
|
if ( menuToggle && menuToggle.offsetParent === null ) {
|
|
if ( openedMobileMenus[ i ].classList.contains( 'toggled' ) ) {
|
|
var remoteNav = false;
|
|
|
|
if ( openedMobileMenus[ i ].classList.contains( 'mobile-menu-control-wrapper' ) ) {
|
|
remoteNav = true;
|
|
}
|
|
|
|
if ( ! remoteNav ) {
|
|
// Navigation is toggled, but .menu-toggle isn't visible on the page (display: none).
|
|
var closestNav = openedMobileMenus[ i ].getElementsByTagName( 'ul' )[ 0 ],
|
|
closestNavItems = closestNav ? closestNav.getElementsByTagName( 'li' ) : [],
|
|
closestSubMenus = closestNav ? closestNav.getElementsByTagName( 'ul' ) : [];
|
|
}
|
|
|
|
document.activeElement.blur();
|
|
openedMobileMenus[ i ].classList.remove( 'toggled' );
|
|
|
|
htmlEl.classList.remove( 'mobile-menu-open' );
|
|
menuToggle.setAttribute( 'aria-expanded', 'false' );
|
|
|
|
if ( ! remoteNav ) {
|
|
for ( var li = 0; li < closestNavItems.length; li++ ) {
|
|
closestNavItems[ li ].classList.remove( 'sfHover' );
|
|
}
|
|
|
|
for ( var sm = 0; sm < closestSubMenus.length; sm++ ) {
|
|
closestSubMenus[ sm ].classList.remove( 'toggled-on' );
|
|
}
|
|
|
|
if ( closestNav ) {
|
|
closestNav.removeAttribute( 'aria-hidden' );
|
|
}
|
|
}
|
|
|
|
disableDropdownArrows( openedMobileMenus[ i ] );
|
|
}
|
|
|
|
if ( mobileMenuControls.querySelector( '.search-item' ) ) {
|
|
if ( mobileMenuControls.querySelector( '.search-item' ).classList.contains( 'active' ) ) {
|
|
mobileMenuControls.querySelector( '.search-item' ).click();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
window.addEventListener( 'resize', checkMobile, false );
|
|
window.addEventListener( 'orientationchange', checkMobile, false );
|
|
|
|
if ( body.classList.contains( 'dropdown-hover' ) ) {
|
|
/**
|
|
* Do some essential things when menu items are clicked.
|
|
*/
|
|
for ( i = 0; i < navLinks.length; i++ ) {
|
|
navLinks[ i ].addEventListener( 'click', function( e ) {
|
|
// Remove sfHover class if we're going to another site.
|
|
if ( this.hostname !== window.location.hostname ) {
|
|
document.activeElement.blur();
|
|
}
|
|
|
|
var closestNav = this.closest( 'nav' );
|
|
if ( closestNav.classList.contains( 'toggled' ) || htmlEl.classList.contains( 'slide-opened' ) ) {
|
|
var url = this.getAttribute( 'href' );
|
|
|
|
// Open the sub-menu if the link has no destination
|
|
if ( '#' === url || '' === url ) {
|
|
e.preventDefault();
|
|
var closestLi = this.closest( 'li' );
|
|
closestLi.classList.toggle( 'sfHover' );
|
|
var subMenu = closestLi.querySelector( '.sub-menu' );
|
|
|
|
if ( subMenu ) {
|
|
subMenu.classList.toggle( 'toggled-on' );
|
|
}
|
|
}
|
|
}
|
|
}, false );
|
|
}
|
|
}
|
|
|
|
if ( body.classList.contains( 'dropdown-hover' ) ) {
|
|
var menuBarItems = document.querySelectorAll( '.menu-bar-items .menu-bar-item > a' );
|
|
|
|
/**
|
|
* Make menu items tab accessible when using the hover dropdown type
|
|
*/
|
|
var toggleFocus = function() {
|
|
if ( this.closest( 'nav' ).classList.contains( 'toggled' ) || this.closest( 'nav' ).classList.contains( 'slideout-navigation' ) ) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
|
|
while ( -1 === self.className.indexOf( 'main-nav' ) ) {
|
|
if ( 'li' === self.tagName.toLowerCase() ) {
|
|
self.classList.toggle( 'sfHover' );
|
|
}
|
|
|
|
self = self.parentElement;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Make our menu bar items tab accessible.
|
|
*/
|
|
var toggleMenuBarItemFocus = function() {
|
|
if ( this.closest( 'nav' ).classList.contains( 'toggled' ) || this.closest( 'nav' ).classList.contains( 'slideout-navigation' ) ) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
|
|
while ( -1 === self.className.indexOf( 'menu-bar-items' ) ) {
|
|
if ( self.classList.contains( 'menu-bar-item' ) ) {
|
|
self.classList.toggle( 'sfHover' );
|
|
}
|
|
|
|
self = self.parentElement;
|
|
}
|
|
};
|
|
|
|
for ( i = 0; i < navLinks.length; i++ ) {
|
|
navLinks[ i ].addEventListener( 'focus', toggleFocus );
|
|
navLinks[ i ].addEventListener( 'blur', toggleFocus );
|
|
}
|
|
|
|
for ( i = 0; i < menuBarItems.length; i++ ) {
|
|
menuBarItems[ i ].addEventListener( 'focus', toggleMenuBarItemFocus );
|
|
menuBarItems[ i ].addEventListener( 'blur', toggleMenuBarItemFocus );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Make hover dropdown touch-friendly.
|
|
*/
|
|
if ( 'ontouchend' in document.documentElement && document.body.classList.contains( 'dropdown-hover' ) ) {
|
|
var parentElements = document.querySelectorAll( '.sf-menu .menu-item-has-children' );
|
|
|
|
for ( i = 0; i < parentElements.length; i++ ) {
|
|
parentElements[ i ].addEventListener( 'touchend', function( e ) {
|
|
// Bail on mobile
|
|
if ( this.closest( 'nav' ).classList.contains( 'toggled' ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( e.touches.length === 1 || e.touches.length === 0 ) {
|
|
// Prevent touch events within dropdown bubbling down to document
|
|
e.stopPropagation();
|
|
|
|
// Toggle hover
|
|
if ( ! this.classList.contains( 'sfHover' ) ) {
|
|
// Prevent link on first touch
|
|
if ( e.target === this || e.target.parentNode === this || e.target.parentNode.parentNode ) {
|
|
e.preventDefault();
|
|
}
|
|
|
|
// Close other sub-menus.
|
|
var closestLi = this.closest( 'li' ),
|
|
siblings = getSiblings( closestLi );
|
|
|
|
for ( i = 0; i < siblings.length; i++ ) {
|
|
if ( siblings[ i ].classList.contains( 'sfHover' ) ) {
|
|
siblings[ i ].classList.remove( 'sfHover' );
|
|
}
|
|
}
|
|
|
|
this.classList.add( 'sfHover' );
|
|
|
|
// Hide dropdown on touch outside
|
|
var closeDropdown,
|
|
thisItem = this;
|
|
|
|
document.addEventListener( 'touchend', closeDropdown = function( event ) {
|
|
event.stopPropagation();
|
|
|
|
thisItem.classList.remove( 'sfHover' );
|
|
document.removeEventListener( 'touchend', closeDropdown );
|
|
} );
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
}
|
|
}
|
|
}() );
|