I would like to create an image carousel using plain JavaScript and HTML. I have been able to move to the next slide with the logic I have but having trouble with the previous slide functionality. When going through the next slide the slideshow at the end restarts at the first picture. I would also like to have this behaviour with the previous slide functionality going to the last picture instead of receiving a Uncaught TypeError.
How can I achieve this ?
const container = document.querySelector(".div-container")
const nextBtn = document.querySelector(".next")
const prevBtn = document.querySelector(".previous")
let currentIndex = 0;
const nextSlide = () => {
const slides = document.getElementsByClassName("slide")
for (let i = 0; i < slides.length; i++) {
slides[i].style.display = "none"
}
currentIndex++
if (currentIndex > slides.length) {
currentIndex = 1
}
slides[currentIndex - 1].style.display = "block"
}
nextSlide()
const prevSlide = () => {
const slides = document.getElementsByClassName("slide")
for (let i = 0; i < slides.length; i++) {
slides[i].style.display = "none"
}
currentIndex--
slides[currentIndex - 1].style.display = "block"
}
nextBtn.addEventListener("click", () => {
nextSlide()
})
prevBtn.addEventListener("click", () => {
prevSlide()
})
.div-container {
display: flex;
justify-content: center;
max-width: 1000px;
}
.slide {
display: none;
}
.image {
width: 300px;
}
<body>
<div class="div-container">
<button class="previous">Previous</button>
<div class="slide fade">
<img src="https://i.redd.it/z7myrlhfhxr31.jpg" alt="windows xp autumn" class="image">
</div>
<div class="slide fade">
<img src="https://www.newegg.com/insider/wp-content/uploads/windows_xp_bliss-wide.jpg" alt="windows xp bliss" class="image">
</div>
<div class="slide fade">
<img src="https://i0.wp.com/tjkelly.com/wp-content/uploads/windows-xp-desktop-background-wallpaper-follow-800x600.jpg?ssl=1" alt="windows xp fishy" class="image">
</div>
<button class="next">Next</button>
</div>
</body>
>Solution :
I fixed your code with as little changes as possible. Instead of two separate functions I am now using just one for stepping forward and backward:
const container = document.querySelector(".div-container")
const nextBtn = document.querySelector(".next")
const prevBtn = document.querySelector(".previous")
let currentIndex = 0;
const nextSlide = (inc) => {
const slides = document.getElementsByClassName("slide")
for (let i = 0; i < slides.length; i++) {
slides[i].style.display = "none"
}
currentIndex=(currentIndex+slides.length+inc)%slides.length;
slides[currentIndex].style.display = "block"
}
nextSlide(0)
nextBtn.addEventListener("click", () => {
nextSlide(1)
})
prevBtn.addEventListener("click", () => {
nextSlide(-1)
})
.div-container {
display: flex;
justify-content: center;
max-width: 1000px;
}
.slide {
display: none;
}
.image {
width: 300px;
}
<body>
<div class="div-container">
<button class="previous">Previous</button>
<div class="slide fade">
<img src="https://i.redd.it/z7myrlhfhxr31.jpg" alt="windows xp autumn" class="image">
</div>
<div class="slide fade">
<img src="https://www.newegg.com/insider/wp-content/uploads/windows_xp_bliss-wide.jpg" alt="windows xp bliss" class="image">
</div>
<div class="slide fade">
<img src="https://i0.wp.com/tjkelly.com/wp-content/uploads/windows-xp-desktop-background-wallpaper-follow-800x600.jpg?ssl=1" alt="windows xp fishy" class="image">
</div>
<button class="next">Next</button>
</div>
</body>
The central part of the operation is the expression
currentIndex=(currentIndex+slides.length+inc)%slides.length
It calculates a new currentIndex by adding inc to the current value. inc can be -1, 0 or 1 and the resulting value will always be between 0 and slides.length-1.
There is scope for further improvements (code simplification and reduction of global variables), but that is a separate issue.