/**
* @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
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.olivera.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 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(
'olivera-automatic-mobile-nav',
'[data-drupal-selector="primary-nav-menu--level-1"]',
context,
).forEach(init);
},
};
})(Drupal, once);