'Responsive accessible navigation dropdown issue
I have a responive navigation which has a dropdown that cases me headaches.
Currenlty the navigatio has a event listener mouse over for desktop and on devices has a click event that adds a .is-active class.
For some reason the events aren't working. I get this error. Uncaught ReferenceError: j is not defined.
I can't figure it out. I leave the code below. hopefully you gus can help me out to find the issue.
const navBlocks = document.querySelectorAll(".nav-container");
const mediaQuery = window.matchMedia("(min-width: 900px)");
const navBp = "(min-width: 900px)";
let isMenuOpen = false;
for (var i = 0; i < navBlocks.length; i++) {
const menu = navBlocks[i].querySelector(".sliding-nav .nav-wrap");
const nav = navBlocks[i].querySelector(".sliding-nav");
let btn = navBlocks[i].querySelector(".nav-cta");
let navLinks = navBlocks[i].querySelectorAll(".sliding-nav .nav-items > li");
//let isSubNavLink = navBlocks[i].querySelector(".has-nav-panel");
btn.onclick = function (e) {
e.preventDefault();
isMenuOpen = !isMenuOpen;
btn.setAttribute("aria-expanded", String(isMenuOpen));
menu.hidden = !isMenuOpen;
if (isMenuOpen) {
nav.classList.add("is-open");
document.body.classList.add("is-no-scroll", "is-fixed");
//console.log(isMenuOpen);
} else {
nav.classList.remove("is-open");
document.body.classList.remove("is-no-scroll", "is-fixed");
//console.log(!isMenuOpen);
}
};
Array.prototype.forEach.call(navLinks, function (el, i) {
var currentNavLink = navLinks[i];
currentNavLink.addEventListener("click", function () {
megaNavClickAndTouchHandler(navLinks, currentNavLink);
});
currentNavLink.addEventListener("mouseover", function () {
megaNavMouseOverHandler(navLinks, currentNavLink, navBp);
});
currentNavLink.addEventListener("mouseleave", function () {
megaNavMouseLeaveHandler(navLinks, currentNavLink, navBp);
});
megaNavResetOnBreakPoint(navLinks, currentNavLink, mediaQuery);
});
function megaNavResetOnBreakPoint(elements, currentElement, mqNav) {
if (matchMedia) {
var navigationBar = currentElement.closest(".header");
var navigationItems = currentElement.closest(".sliding-nav");
mqNav.addListener(function () {
if (mqNav.matches) {
document.querySelectorAll("body")[0].classList.remove("is-no-scroll");
navigationBar.classList.remove("is-active");
navigationItems.classList.remove("is-active");
navigationBar
.querySelectorAll(".burger")[0]
.classList.remove("is-active");
megaNavClosePanels(elements);
} else {
megaNavClosePanels(elements);
}
});
}
}
function megaNavClickAndTouchHandler(elements, currentElement) {
var isSubNavLink = currentElement.classList.contains("has-nav-panel");
var isSubNavLinkActive = currentElement.classList.contains("is-active");
var navBarContainer = currentElement.closest(".header");
if (!isSubNavLink) {
window.location = currentElement.firstElementChild.getAttribute("href");
} else if (isSubNavLink && !isSubNavLinkActive) {
megaNavClosePanels(elements);
currentElement.classList.add("is-active");
} else {
megaNavClosePanels(elements);
}
}
function megaNavClosePanels(elements) {
for (j = 0; j < elements.length; j++) {
if (elements[j].classList.contains("has-nav-panel")) {
elements[j].classList.remove("is-active");
}
}
}
function megaNavMouseOverHandler(elements, currentElement, breakPoint) {
if (window.innerWidth >= breakPoint) {
var isSubNavLink = currentElement.classList.contains("has-nav-panel");
megaNavClosePanels(elements);
currentElement.classList.add("is-active");
}
}
function megaNavMouseLeaveHandler(elements, currentElement, breakPoint) {
if (window.innerWidth >= breakPoint) {
currentElement.classList.remove("is-active");
}
}
function handleTabletChange(e) {
// Check if the media query is true
if (e.matches) {
console.log("desktop");
btn.setAttribute("aria-expanded", false);
menu.removeAttribute("hidden");
nav.classList.remove("is-open");
document.body.classList.remove("is-no-scroll", "is-fixed");
} else {
console.log("mobile");
btn.setAttribute("aria-expanded", false);
}
}
// Register event listener
mediaQuery.addListener(handleTabletChange);
// Initial check
handleTabletChange(mediaQuery);
// TRAP TAB INSIDE NAV WHEN OPEN
nav.addEventListener("keydown", (e) => {
// abort if menu isn't open or modifier keys are pressed
if (!isMenuOpen || e.ctrlKey || e.metaKey || e.altKey) {
return;
}
// listen for tab press and move focus
// if we're on either end of the navigation
const menuLinks = menu.querySelectorAll(".nav-link");
if (e.keyCode === 9) {
if (e.shiftKey) {
if (document.activeElement === menuLinks[0]) {
menuToggle.focus();
e.preventDefault();
}
} else if (document.activeElement === menuToggle) {
menuLinks[0].focus();
e.preventDefault();
}
}
});
}
Solution 1:[1]
Change:
function megaNavClosePanels(elements) {
for (j = 0; j < elements.length; j++) {
if (elements[j].classList.contains("has-nav-panel")) {
elements[j].classList.remove("is-active");
}
}
}
to:
function megaNavClosePanels(elements) {
for (let j = 0; j < elements.length; j++) {
if (elements[j].classList.contains("has-nav-panel")) {
elements[j].classList.remove("is-active");
}
}
}
You are getting that error because the running variable, j in this case, has not been declared and you are using strict directive somewhere (which prevents the use of undeclared variables).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Syed Ali Irtaza Kazmi |
