Files
advancedmegamenu/views/js/megamenu.js
T
tiamak 8e6b6d0cdd
Build / Build & Release draft (push) Failing after 0s
PHP tests / PHP Syntax check 5.6 => 8.1 (push) Failing after 33s
PHP tests / PHPStan (1.7.1.2) (push) Has been cancelled
PHP tests / PHPStan (1.7.2.5) (push) Has been cancelled
PHP tests / PHPStan (1.7.3.4) (push) Has been cancelled
PHP tests / PHPStan (1.7.4.4) (push) Has been cancelled
PHP tests / PHPStan (1.7.5.1) (push) Has been cancelled
PHP tests / PHPStan (1.7.6) (push) Has been cancelled
PHP tests / PHPStan (1.7.7) (push) Has been cancelled
PHP tests / PHPStan (1.7.8) (push) Has been cancelled
PHP tests / PHPStan (latest) (push) Has been cancelled
PHP tests / PHP-CS-Fixer (push) Has been cancelled
Build advanced mega menu module
2026-04-09 13:29:59 +00:00

358 lines
9.5 KiB
JavaScript

(function () {
var menuRoot = document.querySelector('.adv-megamenu');
if (!menuRoot) {
return;
}
var hoverDelay = 120;
var clickDelay = 220;
var hoverTimers = new WeakMap();
var clickTimers = new WeakMap();
function isDesktop() {
return window.matchMedia('(min-width: 992px)').matches;
}
function navigateToLink(link) {
var href = link.getAttribute('href');
if (!href || href === '#') {
return;
}
if (link.getAttribute('target') === '_blank') {
window.open(href, '_blank', 'noopener');
return;
}
window.location.href = href;
}
function closeUnlockedPanels(exceptItem) {
menuRoot.querySelectorAll('.adv-megamenu__root-item.is-open').forEach(function (item) {
if (item === exceptItem || item.classList.contains('is-click-open')) {
return;
}
item.classList.remove('is-open');
});
}
function closeAllPanels(exceptItem) {
menuRoot.querySelectorAll('.adv-megamenu__root-item.is-open, .adv-megamenu__root-item.is-click-open').forEach(function (item) {
if (item === exceptItem) {
return;
}
item.classList.remove('is-open', 'is-click-open');
});
}
function getPageContainer() {
return document.querySelector('.header-bottom__container') || document.querySelector('.container-md') || document.querySelector('.container');
}
function positionDesktopPanels() {
if (!isDesktop()) {
return;
}
var container = getPageContainer();
if (!container) {
return;
}
var containerRect = container.getBoundingClientRect();
var desktopRect = menuRoot.querySelector('.adv-megamenu__desktop').getBoundingClientRect();
var viewportWidth = window.innerWidth || document.documentElement.clientWidth;
var panelWidth = Math.min(1440, viewportWidth - 32, containerRect.width);
var left = containerRect.left - desktopRect.left;
menuRoot.style.setProperty('--adv-panel-left', left + 'px');
menuRoot.style.setProperty('--adv-panel-width', panelWidth + 'px');
}
function positionBridgeForItem(item) {
if (!isDesktop()) {
return;
}
var desktop = menuRoot.querySelector('.adv-megamenu__desktop');
var link = item.querySelector(':scope > .adv-megamenu__root-link');
if (!desktop || !link) {
return;
}
var panelLeft = parseFloat(getComputedStyle(menuRoot).getPropertyValue('--adv-panel-left')) || 0;
var desktopRect = desktop.getBoundingClientRect();
var linkRect = link.getBoundingClientRect();
var preferredWidth = Math.max(40, linkRect.width - 24);
var bridgeLeft = linkRect.left - desktopRect.left - panelLeft + ((linkRect.width - preferredWidth) / 2);
item.style.setProperty('--adv-bridge-left', bridgeLeft + 'px');
item.style.setProperty('--adv-bridge-width', preferredWidth + 'px');
}
function activateSubmenuPane(item) {
if (!item) {
return;
}
var panel = item.closest('.adv-megamenu__panel');
var key = item.getAttribute('data-submenu-key');
if (!panel || !key) {
return;
}
panel.querySelectorAll('.adv-megamenu__manual-tree li.is-active').forEach(function (entry) {
entry.classList.remove('is-active');
});
panel.querySelectorAll('.adv-megamenu__submenu-pane.is-active').forEach(function (pane) {
pane.classList.remove('is-active');
});
item.classList.add('is-active');
var targetPane = panel.querySelector('[data-submenu-pane="' + key + '"]');
if (targetPane) {
targetPane.classList.add('is-active');
}
}
function activateFirstSubmenuPane(rootItem) {
if (!rootItem) {
return;
}
var firstItem = rootItem.querySelector('.adv-megamenu__manual-tree li.has-submenu');
if (firstItem) {
activateSubmenuPane(firstItem);
}
}
function bindDesktopClickIntent(link, onSingleClick) {
link.addEventListener('click', function (event) {
if (!isDesktop()) {
return;
}
event.preventDefault();
var existingTimer = clickTimers.get(link);
if (existingTimer) {
window.clearTimeout(existingTimer);
clickTimers.delete(link);
navigateToLink(link);
return;
}
var timer = window.setTimeout(function () {
clickTimers.delete(link);
onSingleClick();
}, clickDelay);
clickTimers.set(link, timer);
});
}
menuRoot.querySelectorAll('.adv-megamenu__root-item.has-panel').forEach(function (item) {
var link = item.querySelector(':scope > .adv-megamenu__root-link');
item.addEventListener('mouseenter', function () {
if (!isDesktop()) {
return;
}
window.clearTimeout(hoverTimers.get(item));
var timer = window.setTimeout(function () {
closeUnlockedPanels(item);
positionBridgeForItem(item);
activateFirstSubmenuPane(item);
item.classList.add('is-open');
}, hoverDelay);
hoverTimers.set(item, timer);
});
item.addEventListener('mouseleave', function () {
if (!isDesktop()) {
return;
}
window.clearTimeout(hoverTimers.get(item));
var timer = window.setTimeout(function () {
if (!item.classList.contains('is-click-open')) {
item.classList.remove('is-open');
}
}, hoverDelay);
hoverTimers.set(item, timer);
});
if (!link) {
return;
}
bindDesktopClickIntent(link, function () {
var isOpen = item.classList.contains('is-open');
var isPinned = item.classList.contains('is-click-open');
if (!isOpen) {
closeAllPanels(item);
positionBridgeForItem(item);
activateFirstSubmenuPane(item);
item.classList.add('is-open', 'is-click-open');
return;
}
if (!isPinned) {
closeAllPanels(item);
positionBridgeForItem(item);
activateFirstSubmenuPane(item);
item.classList.add('is-click-open');
return;
}
item.classList.remove('is-click-open', 'is-open');
});
});
menuRoot.querySelectorAll('.adv-megamenu__manual-tree li.has-submenu').forEach(function (item) {
var link = item.querySelector(':scope > .adv-megamenu__submenu-trigger');
if (!link) {
return;
}
item.addEventListener('mouseenter', function () {
if (!isDesktop()) {
return;
}
activateSubmenuPane(item);
});
bindDesktopClickIntent(link, function () {
activateSubmenuPane(item);
});
});
menuRoot.querySelectorAll('.adv-megamenu__manual-tree li, .adv-megamenu__category-tree li').forEach(function (item) {
var directLink = item.querySelector(':scope > a');
var directSubtree = item.querySelector(':scope > ul');
if (!directLink || !directSubtree) {
return;
}
item.classList.add('has-children');
bindDesktopClickIntent(directLink, function () {
item.classList.toggle('is-expanded');
});
});
var overlay = menuRoot.querySelector('.js-adv-overlay');
var openButton = menuRoot.querySelector('.js-adv-menu-toggle');
var closeButton = menuRoot.querySelector('.js-adv-menu-close');
var panelStack = ['root'];
function setActivePanel(panelId) {
var panels = menuRoot.querySelectorAll('.adv-megamenu__mobile-panel');
panels.forEach(function (panel) {
var currentId = panel.getAttribute('data-panel-id');
panel.classList.remove('is-active', 'is-left');
var currentIndex = panelStack.indexOf(currentId);
if (currentIndex === -1) {
return;
}
if (currentId === panelId) {
panel.classList.add('is-active');
} else if (currentIndex < panelStack.length - 1) {
panel.classList.add('is-left');
}
});
}
function openDrawer() {
if (!overlay) {
return;
}
overlay.classList.add('is-open');
if (openButton) {
openButton.setAttribute('aria-expanded', 'true');
}
panelStack = ['root'];
setActivePanel('root');
}
function closeDrawer() {
if (!overlay) {
return;
}
overlay.classList.remove('is-open');
if (openButton) {
openButton.setAttribute('aria-expanded', 'false');
}
}
if (openButton) {
openButton.addEventListener('click', openDrawer);
}
if (closeButton) {
closeButton.addEventListener('click', closeDrawer);
}
if (overlay) {
overlay.addEventListener('click', function (event) {
if (event.target === overlay) {
closeDrawer();
}
});
}
document.addEventListener('click', function (event) {
if (!isDesktop()) {
return;
}
if (menuRoot.contains(event.target)) {
return;
}
closeAllPanels();
menuRoot.querySelectorAll('.adv-megamenu__manual-tree li.is-expanded, .adv-megamenu__category-tree li.is-expanded').forEach(function (item) {
item.classList.remove('is-expanded');
});
});
menuRoot.querySelectorAll('.js-adv-open-panel').forEach(function (button) {
button.addEventListener('click', function () {
var target = button.getAttribute('data-target');
if (!target) {
return;
}
panelStack.push(target);
setActivePanel(target);
});
});
menuRoot.querySelectorAll('.js-adv-back').forEach(function (button) {
button.addEventListener('click', function () {
if (panelStack.length <= 1) {
return;
}
panelStack.pop();
setActivePanel(panelStack[panelStack.length - 1]);
});
});
positionDesktopPanels();
window.addEventListener('resize', function () {
positionDesktopPanels();
menuRoot.querySelectorAll('.adv-megamenu__root-item.is-open').forEach(positionBridgeForItem);
});
})();