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