I am running into trouble with this script below, as I take a collection based on a class name and then modify the class names of each member of the collection respectively the programs triggers that the very items of the collection are undefined.
I assume this has to do with the collection falling apart as I remove what made the elements belong to the collection? Could you give me a hint to how I could implement smth like this?
<script>
var toggle1 = document.getElementById("toggle1");
toggle1.addEventListener("click", Colortoggle);
function Colortoggle() {
if (toggle1.className === " white") {
var collection = document.getElementsByClassName("white");
for (let i = 0; i < collection.length; i ) {
collection[i].className -= "white";
collection[i].className = "black";
}
} else {
var collection = document.getElementsByClassName("black");
for (let i = 0; i < collection.length; i ) {
collection[i].className -= "black";
collection[i].className = "white";
}
}
console.log("colortoggle was finished");
}
</script>
These are the classes in the beginning:
This is the change in classes:
CodePudding user response:
The main logic for below code is
toggle1.classList.contains("white")
this statement return true if toggle has classwhite
else return false.WIth DOM elements you can use this
classList
methodsclassList.add()
,classList.remove()
.classList.add()
=> this will add class to selected DOM element.classList.remove()
=> this will remove class to selected DOM element.for more information abslout classList method please visit this.
var toggle1 = document.querySelector("#toggle1");
toggle1.addEventListener("click", Colortoggle);
function Colortoggle() {
if (toggle1.classList.contains("white")) {
var collection = document.querySelectorAll(".white");
collection.forEach(element => {
element.classList.add("black");
element.classList.remove("white");
})
} else {
var collection = document.querySelectorAll(".black");
collection.forEach(element => {
element.classList.add("white");
element.classList.remove("black");
})
}
console.log("colortoggle was finished");
}
.main div {
display: inline-block;
height: 100px;
width: 100px;
}
.white {
background-color: #f0f0f0;
color: black;
}
.black {
background-color: #000000;
color: white;
}
<div >
<div id="toggle1" >toggle1 click here</div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
</div>
CodePudding user response:
In JavaScript, the subtraction operator (-) does not work with non-numbers; that is why it yields NaN
. If you want to edit the class name of an element, please use methods like add(), remove(). For more information, please see here.
CodePudding user response:
As a sidenote: getElementsByClassName()
returns a live HTMLCollection, which means you should never iterate over it using a for-loop while also modifying elements such as that they get removed from the collection.
Lets picture this:
Let this be the collection getElementsByClassName('foo')
, with ->
displaying the current iteration of the loop.
// list before iterating
0: <div >0</div>
1: <div >1</div>
2: <div >2</div>
// first iteration i=0
-> 0: <div >0</div> // in this iteration, remove .foo
1: <div >1</div>
2: <div >2</div>
// still first iteration, but now collection[0] is actually what was collection[1] before
-> 0: <div >1</div>
1: <div >2</div>
// second iteration i=1
0: <div >1</div> // we never touch this one!!
-> 1: <div >2</div>
You will not have this problem if instead of getElementsByClassName('foo')
you work with querySelectorAll('.foo')
.
Second sidenote: No, this cannot be fixed using for (const div of divs)
instead, as it internally seems to work with indexes as well.