Using a simple counter to iterate a collection works fine, but when I try to change it to use forEach it fails. Can someone point me in the right direction? Here's the code (code in question is commented out...first one works, second one doesn't)
function slideImage(offset = 0) {
let i;
let slides = document.getElementsByClassName("mySlides");
let minCount = 1;
let maxCount = slides.length;
if (typeof index === "undefined") {
index = 0;
}
index += offset;
if (index > maxCount) {
index = minCount;
}
if (index < minCount) {
index = maxCount;
}
**// THIS PIECE OF CODE WORKS FINE (when uncommented obviously)
// for (i = 0; i < maxCount; i++) {
// slides[i].style.display = "none";
// }**
**// WHEN I TRY TO USE FOREACH IT FAILS???
// slides.forEach((c) => {
// c.style.display = "none";
// });**
slides[index - 1].style.display = "block";
}
The slides collection are divs each one containing an img .. here's a sample
<div class="mySlides fade">
<img class="photo-one" src="/images/xxx.webp"/>
</div>
<div class="mySlides fade">
<img class="photo-one" src="/images/xxx.webp"/>
</div>
<div class="mySlides fade">
<img class="photo-one" src="/images/xxx.webp"/>
</div>
getElementsByClassName
returns an HTMLCollection
object, which is an array-like object that you can loop over. However it lacks methods like forEach
to loop over the values in the object.
Use the more powerful querySelectorAll()
function which returns a NodeList
which has the forEach
method.
let slides = document.querySelectorAll(".mySlides");
Alternatively you could turn your HTMLCollection
into an array with the Array.from
function, but I'd recommend learning to use querySelector
and querySelectorAll
for finding elements.
Array.from(slides).forEach(slide => {
slide.style.display = "none";
});
An important difference between a HTMLCollection
and a NodeList
is that the HTMLCollection
is a live collection which means it will change whenever you add or remove elements from the document that have the class you're querying, whereas the NodeList
is a snapshot of the found elements at the time of calling.
let slides = document.querySelectorAll(".mySlides");
slides.forEach(slide => {
console.log(slide.className);
});
<div class="mySlides fade">
<img class="photo-one" src="/images/xxx.webp"/>
</div>
<div class="mySlides pulse">
<img class="photo-one" src="/images/xxx.webp"/>
</div>
<div class="mySlides flyin">
<img class="photo-one" src="/images/xxx.webp"/>
</div>