/**
* Mobile Hamburger Menu
*
* Handles the slide-in mobile navigation drawer with hamburger toggle,
* overlay, sub-menu accordions, and keyboard/focus-trap support.
*
* @package Blog Eye
*/
(function () {
'use strict';
const hamburgerBtn = document.getElementById('mmenu-btn');
const closeBtn = document.getElementById('mmenu-close');
const drawer = document.getElementById('mobile-navigation');
const overlay = document.getElementById('mobile-menu-overlay');
if (!hamburgerBtn || !drawer) {
return;
}
// ── Open / Close helpers ──────────────────────────────────
function openMenu() {
drawer.classList.add('is-open');
overlay.classList.add('is-visible');
hamburgerBtn.classList.add('is-active');
hamburgerBtn.setAttribute('aria-expanded', 'true');
document.body.classList.add('mobile-menu-open');
// focus first link inside drawer
const firstLink = drawer.querySelector('a');
if (firstLink) {
firstLink.focus();
}
}
function closeMenu() {
drawer.classList.remove('is-open');
overlay.classList.remove('is-visible');
hamburgerBtn.classList.remove('is-active');
hamburgerBtn.setAttribute('aria-expanded', 'false');
document.body.classList.remove('mobile-menu-open');
hamburgerBtn.focus();
}
// ── Event listeners ───────────────────────────────────────
hamburgerBtn.addEventListener('click', function (e) {
e.stopPropagation();
if (drawer.classList.contains('is-open')) {
closeMenu();
} else {
openMenu();
}
});
if (closeBtn) {
closeBtn.addEventListener('click', closeMenu);
}
if (overlay) {
overlay.addEventListener('click', closeMenu);
}
// Close on Escape key
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && drawer.classList.contains('is-open')) {
closeMenu();
}
});
// ── Sub-menu accordion toggles ────────────────────────────
const subMenuParents = drawer.querySelectorAll(
'.menu-item-has-children, .page_item_has_children'
);
subMenuParents.forEach(function (item) {
// Create toggle button
const toggleBtn = document.createElement('button');
toggleBtn.className = 'sub-menu-toggle';
toggleBtn.setAttribute('aria-expanded', 'false');
toggleBtn.setAttribute('aria-label', 'Toggle submenu');
toggleBtn.innerHTML =
'';
// Insert toggle after the link
const link = item.querySelector(':scope > a');
if (link) {
link.after(toggleBtn);
}
toggleBtn.addEventListener('click', function () {
const isOpen = item.classList.toggle('sub-open');
toggleBtn.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
});
});
// ── Focus trap inside drawer ──────────────────────────────
const focusableSelector =
'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])';
document.addEventListener('keydown', function (e) {
if (e.key !== 'Tab' || !drawer.classList.contains('is-open')) {
return;
}
const focusable = drawer.querySelectorAll(focusableSelector);
if (!focusable.length) {
return;
}
const first = focusable[0];
const last = focusable[focusable.length - 1];
if (e.shiftKey) {
if (document.activeElement === first) {
e.preventDefault();
last.focus();
}
} else {
if (document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
});
})();