You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
2.9 KiB
86 lines
2.9 KiB
/** |
|
* @file |
|
* This script watches the desktop version of the primary navigation. If it |
|
* wraps to two lines, it will automatically transition to a mobile navigation |
|
* and remember where it wrapped so it can transition back. |
|
*/ |
|
((Drupal, once) => { |
|
/** |
|
* Handles the transition from mobile navigation to desktop navigation. |
|
* |
|
* @param {Element} navWrapper - The primary navigation's top-level <ul> element. |
|
* @param {Element} navItem - The first item within the primary navigation. |
|
*/ |
|
function transitionToDesktopNavigation(navWrapper, navItem) { |
|
document.body.classList.remove('is-always-mobile-nav'); |
|
|
|
// Double check to see if the navigation is wrapping, and if so, re-enable |
|
// mobile navigation. This solves an edge cases where if the amount of |
|
// navigation items always causes the primary navigation to wrap, and the |
|
// page is loaded at a narrower viewport and then widened, the mobile nav |
|
// may not be enabled. |
|
if (navWrapper.clientHeight > navItem.clientHeight) { |
|
document.body.classList.add('is-always-mobile-nav'); |
|
} |
|
} |
|
|
|
/** |
|
* Callback from Resize Observer. This checks if the primary navigation is |
|
* wrapping, and if so, transitions to the mobile navigation. |
|
* |
|
* @param {ResizeObserverEntry} entries - Object passed from ResizeObserver. |
|
*/ |
|
function checkIfDesktopNavigationWraps(entries) { |
|
const navItem = document.querySelector('.primary-nav__menu-item'); |
|
|
|
if ( |
|
Drupal.olives.isDesktopNav() && |
|
entries[0].contentRect.height > navItem.clientHeight |
|
) { |
|
const navMediaQuery = window.matchMedia( |
|
`(max-width: ${window.innerWidth + 15}px)`, // 5px adds a small buffer before switching back. |
|
); |
|
document.body.classList.add('is-always-mobile-nav'); |
|
|
|
// In the event that the viewport was resized, we remember the viewport |
|
// width with a one-time event listener ,so we can attempt to transition |
|
// from mobile navigation to desktop navigation. |
|
navMediaQuery.addEventListener( |
|
'change', |
|
() => { |
|
transitionToDesktopNavigation(entries[0].target, navItem); |
|
}, |
|
{ once: true }, |
|
); |
|
} |
|
} |
|
|
|
/** |
|
* Set up Resize Observer to listen for changes to the size of the primary |
|
* navigation. |
|
* |
|
* @param {Element} primaryNav - The primary navigation's top-level <ul> element. |
|
*/ |
|
function init(primaryNav) { |
|
const resizeObserver = new ResizeObserver(checkIfDesktopNavigationWraps); |
|
resizeObserver.observe(primaryNav); |
|
} |
|
|
|
/** |
|
* Initialize the automatic navigation transition. |
|
* |
|
* @type {Drupal~behavior} |
|
* |
|
* @prop {Drupal~behaviorAttach} attach |
|
* Attach context and settings for navigation. |
|
*/ |
|
Drupal.behaviors.automaticMobileNav = { |
|
attach(context) { |
|
once( |
|
'olives-automatic-mobile-nav', |
|
'[data-drupal-selector="primary-nav-menu--level-1"]', |
|
context, |
|
).forEach(init); |
|
}, |
|
}; |
|
})(Drupal, once);
|
|
|