first commit
This commit is contained in:
209
wp-content/themes/storefront/assets/js/navigation.js
Normal file
209
wp-content/themes/storefront/assets/js/navigation.js
Normal file
@@ -0,0 +1,209 @@
|
||||
/* global storefrontScreenReaderText */
|
||||
|
||||
/**
|
||||
* navigation.js
|
||||
*
|
||||
* Handles toggling the navigation menu for small screens.
|
||||
* Also adds a focus class to parent li's for accessibility.
|
||||
*/
|
||||
( function () {
|
||||
// eslint-disable-next-line @wordpress/no-global-event-listener
|
||||
document.addEventListener( 'DOMContentLoaded', function () {
|
||||
const container = document.getElementById( 'site-navigation' );
|
||||
if ( ! container ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = container.querySelector( 'button' );
|
||||
|
||||
if ( ! button ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const menu = container.querySelector( 'ul' );
|
||||
|
||||
// Hide menu toggle button if menu is empty and return early.
|
||||
if ( ! menu ) {
|
||||
button.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
button.setAttribute( 'aria-expanded', 'false' );
|
||||
menu.setAttribute( 'aria-expanded', 'false' );
|
||||
menu.classList.add( 'nav-menu' );
|
||||
|
||||
button.addEventListener( 'click', function () {
|
||||
container.classList.toggle( 'toggled' );
|
||||
const expanded = container.classList.contains( 'toggled' )
|
||||
? 'true'
|
||||
: 'false';
|
||||
button.setAttribute( 'aria-expanded', expanded );
|
||||
menu.setAttribute( 'aria-expanded', expanded );
|
||||
} );
|
||||
|
||||
// Add dropdown toggle that displays child menu items.
|
||||
const handheld = document.getElementsByClassName(
|
||||
'handheld-navigation'
|
||||
);
|
||||
|
||||
if ( handheld.length > 0 ) {
|
||||
[].forEach.call(
|
||||
handheld[ 0 ].querySelectorAll(
|
||||
'.menu-item-has-children > a, .page_item_has_children > a'
|
||||
),
|
||||
function ( anchor ) {
|
||||
// Add dropdown toggle that displays child menu items
|
||||
const btn = document.createElement( 'button' );
|
||||
btn.setAttribute( 'aria-expanded', 'false' );
|
||||
btn.classList.add( 'dropdown-toggle' );
|
||||
|
||||
const btnSpan = document.createElement( 'span' );
|
||||
btnSpan.classList.add( 'screen-reader-text' );
|
||||
btnSpan.appendChild(
|
||||
document.createTextNode(
|
||||
storefrontScreenReaderText.expand
|
||||
)
|
||||
);
|
||||
|
||||
btn.appendChild( btnSpan );
|
||||
|
||||
anchor.parentNode.insertBefore( btn, anchor.nextSibling );
|
||||
|
||||
// Set the active submenu dropdown toggle button initial state
|
||||
if (
|
||||
anchor.parentNode.classList.contains(
|
||||
'current-menu-ancestor'
|
||||
)
|
||||
) {
|
||||
btn.setAttribute( 'aria-expanded', 'true' );
|
||||
btn.classList.add( 'toggled-on' );
|
||||
btn.nextElementSibling.classList.add( 'toggled-on' );
|
||||
}
|
||||
|
||||
// Add event listener
|
||||
btn.addEventListener( 'click', function () {
|
||||
btn.classList.toggle( 'toggled-on' );
|
||||
|
||||
// Remove text inside span
|
||||
while ( btnSpan.firstChild ) {
|
||||
btnSpan.removeChild( btnSpan.firstChild );
|
||||
}
|
||||
|
||||
const expanded = btn.classList.contains( 'toggled-on' );
|
||||
|
||||
btn.setAttribute( 'aria-expanded', expanded );
|
||||
btnSpan.appendChild(
|
||||
document.createTextNode(
|
||||
expanded
|
||||
? storefrontScreenReaderText.collapse
|
||||
: storefrontScreenReaderText.expand
|
||||
)
|
||||
);
|
||||
btn.nextElementSibling.classList.toggle( 'toggled-on' );
|
||||
} );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Add focus class to parents of sub-menu anchors.
|
||||
[].forEach.call(
|
||||
document.querySelectorAll(
|
||||
'.site-header .menu-item > a, .site-header .page_item > a, .site-header-cart a'
|
||||
),
|
||||
function ( anchor ) {
|
||||
anchor.addEventListener( 'focus', function () {
|
||||
// Remove focus class from other sub-menus previously open.
|
||||
const elems = document.querySelectorAll( '.focus' );
|
||||
|
||||
[].forEach.call( elems, function ( el ) {
|
||||
if ( ! el.contains( anchor ) ) {
|
||||
el.classList.remove( 'focus' );
|
||||
|
||||
// Remove blocked class, if it exists.
|
||||
if ( el.firstChild && el.firstChild.classList ) {
|
||||
el.firstChild.classList.remove( 'blocked' );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// Add focus class.
|
||||
const li = anchor.parentNode;
|
||||
|
||||
li.classList.add( 'focus' );
|
||||
} );
|
||||
}
|
||||
);
|
||||
|
||||
// Ensure the dropdowns close when user taps outside the site header
|
||||
[].forEach.call(
|
||||
document.querySelectorAll( 'body #page > :not( .site-header )' ),
|
||||
function ( element ) {
|
||||
element.addEventListener( 'click', function () {
|
||||
[].forEach.call(
|
||||
document.querySelectorAll( '.focus, .blocked' ),
|
||||
function ( el ) {
|
||||
el.classList.remove( 'focus' );
|
||||
el.classList.remove( 'blocked' );
|
||||
}
|
||||
);
|
||||
} );
|
||||
}
|
||||
);
|
||||
|
||||
// Add an identifying class to dropdowns when on a touch device
|
||||
// This is required to switch the dropdown hiding method from a negative `left` value to `display: none`.
|
||||
if (
|
||||
( 'ontouchstart' in window || window.navigator.maxTouchPoints ) &&
|
||||
window.innerWidth > 767
|
||||
) {
|
||||
[].forEach.call(
|
||||
document.querySelectorAll(
|
||||
'.site-header ul ul, .site-header-cart .widget_shopping_cart'
|
||||
),
|
||||
function ( element ) {
|
||||
element.classList.add( 'sub-menu--is-touch-device' );
|
||||
}
|
||||
);
|
||||
|
||||
// Add blocked class to links that open sub-menus, and prevent from navigating away on first touch.
|
||||
let acceptClick = false;
|
||||
|
||||
[].forEach.call(
|
||||
document.querySelectorAll(
|
||||
'.site-header .menu-item > a, .site-header .page_item > a, .site-header-cart a'
|
||||
),
|
||||
function ( anchor ) {
|
||||
anchor.addEventListener( 'click', function ( event ) {
|
||||
if (
|
||||
anchor.classList.contains( 'blocked' ) &&
|
||||
acceptClick === false
|
||||
) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
acceptClick = false;
|
||||
} );
|
||||
|
||||
anchor.addEventListener( 'pointerup', function ( event ) {
|
||||
if (
|
||||
anchor.classList.contains( 'blocked' ) ||
|
||||
event.pointerType === 'mouse'
|
||||
) {
|
||||
acceptClick = true;
|
||||
} else if (
|
||||
( anchor.className === 'cart-contents' &&
|
||||
anchor.parentNode.nextElementSibling &&
|
||||
anchor.parentNode.nextElementSibling.textContent.trim() !==
|
||||
'' ) ||
|
||||
anchor.nextElementSibling
|
||||
) {
|
||||
anchor.classList.add( 'blocked' );
|
||||
} else {
|
||||
acceptClick = true;
|
||||
}
|
||||
} );
|
||||
}
|
||||
);
|
||||
}
|
||||
} );
|
||||
} )();
|
||||
Reference in New Issue
Block a user