The code works just as expected but if I use for (let line in hamburgerLines) {...} I get the following error: "Uncaught TypeError: Cannot read properties of undefined (reading ‘toggle’) at HTMLDivElement.addClass".
I used this alert function alert("Here: " + line + " "+ hamburgerLines[line] + " " + hamburgerLines.length); to find out what’s happening. It iterates normally three times and hamburgerLines.length does return 3 but then pops up another time putting out: "Here: entries function entries() { [native code] } 3" which I assume causes the error.
I already fixed this by changing it to for (let line = 0; line < hamburgerLines.length; line++) {...} but would like to know why it iterates once more through the for loop.
let hamburgerButton = document.getElementById('hamburger-button');
hamburgerButton.addEventListener('click', addClass);
function addClass() {
let hamburgerLines = document.querySelectorAll('.hamburger-line');
for (let line in hamburgerLines) {
hamburgerLines[line].classList.toggle('open-test');
}
}
header #hamburger-button {
position: absolute;
width: 50px;
height: 40px;
top: 30px;
right: 50px;
cursor: pointer;
}
/* ---- Untoggled Hamburger Button ---- */
header .hamburger-line:nth-child(1) {
width: 1px;
height: 30px;
background-color: #000;
position: absolute;
right: 0px;
-webkit-transition: .5s ease-in-out;
}
header .hamburger-line:nth-child(2) {
width: 1px;
height: 20px;
background-color: #000;
position: absolute;
right: 10px;
-webkit-transition: .5s ease-in-out;
}
header .hamburger-line:nth-child(3) {
width: 1px;
height: 14px;
background-color: #000;
position: absolute;
right: 20px;
-webkit-transition: .5s ease-in-out;
}
/* ---- Toggled Hamburger Button ---- */
header .hamburger-line.open-test:nth-child(1) {
width: 1px;
height: 30px;
background-color: #F00;
position: absolute;
right: 10px;
-webkit-transition: .5s ease-in-out;
transform: rotate(45deg);
}
header .hamburger-line.open-test:nth-child(2) {
width: 1px;
height: 20px;
background-color: #FFF;
position: absolute;
transform: translateY(20px);
-webkit-transition: .5s ease-in-out;
opacity: 0;
}
header .hamburger-line.open-test:nth-child(3) {
width: 1px;
height: 30px;
background-color: #F00;
position: absolute;
right: 10px;
-webkit-transition: .5s ease-in-out;
transform: rotate(-45deg);
}
<header>
<div id="hamburger-button">
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
</div>
</header>
>Solution :
document.querySelectorAll() returns a NodeList object, check NodeList documentation
Don’t use for…in to enumerate the items in NodeLists, since they
will also enumerate its length and item properties and cause errors if
your script assumes it only has to deal with element objects. Also,
for..in is not guaranteed to visit the properties in any particular
order.for…of loops will loop over NodeList objects correctly:
Recent browsers also support iterator methods (forEach()) as well as
entries(), values(), and keys().