Created
January 2, 2023 16:29
-
-
Save ckrina/225ec50b5b2e0fb163e9ef3a38173f8e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file | |
* Main navigation script. | |
*/ | |
export default (Drupal, once) => { | |
let nav; | |
let dropdowns; | |
let navButton; | |
let desktopMenu; | |
let desktopOnlyMenu; | |
let desktop2XLMenu; | |
let tabletMenu; | |
let submenuToggle; | |
function expandMenu(element) { | |
// Relies on the "button.main-navigation__submenu-toggle". | |
let expanded = element.getAttribute('aria-expanded') === 'true' || false; | |
submenuToggle = element.querySelector('.main-navigation__submenu-toggle'); | |
element.setAttribute('aria-expanded', !expanded); | |
let submenu = element.nextElementSibling; | |
// If it has submenu. | |
if (typeof submenu !== 'undefined' && submenu !== null) { | |
dropdowns.forEach(function (dropdown) { | |
// Close everything if it is not the item being opened. | |
if (dropdown !== element) { | |
dropdown.parentNode.classList.remove('opened'); | |
dropdown.setAttribute('aria-expanded', false); | |
submenu.classList.remove('opened'); | |
submenuToggle.setAttribute('aria-expanded', false); | |
} | |
}); | |
// Opening. | |
if (!expanded) { | |
element.parentNode.classList.add('opened'); | |
submenu.classList.add('opened'); | |
submenuToggle.setAttribute('aria-expanded', true); | |
// Submenu placement. | |
let submenuX = submenu.getBoundingClientRect().x; | |
let submenuRight = submenu.getBoundingClientRect().right; | |
let elementX = element.getBoundingClientRect().x; | |
let elementRight = element.getBoundingClientRect().right; | |
// Tablet. | |
if (tabletMenu.matches) { | |
// Further right position a small element can take on Tablet. | |
let maxRight = window.innerWidth - submenuRight; | |
// Check if the submenu is misaligned with the Main menu item: if the | |
// submenu left is further in the left than the Menu item and if the right | |
// point is more in the left than parent it's outside, so align. | |
if ((submenuX < elementX) && (submenuRight < elementRight)) { | |
// If submenuRight falls outside the window edge use the maxRight. | |
if (elementX > maxRight) { | |
submenu.style.left = `${maxRight}px`; | |
} else { | |
// Use the left item value minus 16px per design. | |
let leftPlacement = elementX - 16; | |
submenu.style.left = `${leftPlacement}px`; | |
} | |
} | |
} | |
// From LG / Desktop. | |
if (desktopOnlyMenu.matches && submenuX > elementX) { | |
// Use the left item value minus 16px per design. | |
let leftPlacement = elementX - 16; | |
submenu.style.left = `${leftPlacement}px`; | |
} | |
// From LG / Desktop. | |
if (desktop2XLMenu.matches && submenuX > elementX) { | |
// Use the left item value minus 16px per design. | |
submenu.style.left = `-1rem`; | |
} | |
// Closing. | |
} else { | |
element.parentNode.classList.remove('opened'); | |
submenuToggle.setAttribute('aria-expanded', false); | |
element.setAttribute('aria-expanded', false); | |
submenu.classList.remove('opened'); | |
} | |
} | |
} | |
function init(el) { | |
nav = el; | |
dropdowns = document.querySelectorAll('.main-navigation__level-0-content'); | |
navButton = document.querySelector('button.main-navigation__control'); | |
desktopMenu = window.matchMedia('(min-width: 48rem)'); | |
desktopOnlyMenu = window.matchMedia('(min-width: 60rem)'); | |
desktop2XLMenu = window.matchMedia('(min-width: 87.5rem)'); | |
tabletMenu = window.matchMedia('(min-width:48rem) and (max-width: 59.99rem)'); | |
submenuToggle = el.querySelector('.main-navigation__submenu-toggle'); | |
// Resets. | |
if (typeof navButton !== 'undefined' && navButton !== null) { | |
// Reset all menus when click happens outside the menu. | |
navButton.addEventListener('click', function() { | |
dropdowns.forEach(function(dropdown) { | |
// Remove the .open class from all list wrappers. | |
dropdown.parentNode.classList.remove('opened'); | |
// Remove the aria-expanded=true from all dropdowns. | |
dropdown.setAttribute('aria-expanded', false); | |
// Remove the .open class from all submenus. | |
dropdown.nextElementSibling.classList.remove('opened'); | |
// Remove the aria-expanded=true from all toggles. | |
submenuToggle.setAttribute('aria-expanded', false); | |
}); | |
}); | |
if (typeof nav !== 'undefined' && nav !== null && typeof ResizeObserver === 'function') { | |
// Reset all menus when navigation closes or the window is resized to desktop. | |
let resizeObserver = new ResizeObserver(function () { | |
if ((navButton.offsetParent !== null && nav.classList.contains('main-navigation--closed')) || desktopMenu.matches) { | |
dropdowns.forEach(function(dropdown) { | |
// Remove the .open class from all list wrappers. | |
dropdown.parentNode.classList.remove('opened'); | |
// Remove the aria-expanded=true from all dropdowns. | |
dropdown.setAttribute('aria-expanded', false); | |
if (typeof dropdown.nextElementSibling !== 'undefined' && dropdown.nextElementSibling !== null) { | |
// Remove the aria-expanded=true from all toggles. | |
submenuToggle.setAttribute('aria-expanded', false); | |
// Remove the .open class from all submenus. | |
dropdown.nextElementSibling.classList.remove('opened'); | |
} | |
}); | |
} | |
}); | |
resizeObserver.observe(nav); | |
} | |
} | |
dropdowns.forEach(function(dropdown) { | |
dropdown.addEventListener('click', function(event) { | |
if (desktopMenu.matches) { | |
if (typeof nav !== 'undefined' && nav !== null && nav.classList.contains('main-navigation--closed')) { | |
expandMenu(dropdown); | |
} | |
} | |
else { | |
if (typeof nav !== 'undefined' && nav !== null && !nav.classList.contains('main-navigation--closed')) { | |
expandMenu(dropdown); | |
} | |
} | |
}); | |
dropdown.parentNode.addEventListener('mouseenter', function(o) { | |
if (typeof nav !== 'undefined' && nav !== null && nav.classList.contains('main-navigation--closed')) { | |
expandMenu(dropdown); | |
} | |
}); | |
dropdown.parentNode.addEventListener('mouseleave', function(event) { | |
if (typeof nav !== 'undefined' && nav !== null && nav.classList.contains('main-navigation--closed')) { | |
expandMenu(dropdown); | |
} | |
}); | |
}); | |
} | |
Drupal.behaviors.mainNavigation = { | |
attach(context) { | |
once("mainNavigation", ".main-navigation", context).forEach(init); | |
}, | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment