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();
}
}
});
}
demo in codepen, please fork it to modify
CodePudding user response:
The code should be modified:
let j
breakPoint
is not anumber
const navBlocks = document.querySelectorAll(".nav-container");
const BREAKPOINT = 900
const mediaQuery = window.matchMedia(`(min-width: ${BREAKPOINT}px)`);
const navBp = `(min-width: ${BREAKPOINT}px)`;
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, BREAKPOINT);
});
currentNavLink.addEventListener("mouseleave", function() {
megaNavMouseLeaveHandler(navLinks, currentNavLink, BREAKPOINT);
});
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 (let 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) {
console.log('here', 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();
}
}
});
}
CodePudding user response:
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).