I created a carousel slider similar to the one in UIkit slider, I want to use this function to multiple carousel in the same html page but it’s not working as expected because I am using this line of code which query single carousel only:
const carousel = document.querySelector(".c-carousel-inner");
I’ve tried using this but apparently on button press it will trigger the other carousel also
const carousels = document.querySelectorAll(".c-carousel-inner");
carousels.forEach((carousel) => {
// code here
});
I’ve seen some solution which uses constructor, but I’m not sure if that’s the best approach here
Here’s my full javascript code without any applied code from above
const carousel = document.querySelector(".c-carousel-inner");
const carouselLength = carousel.children.length;
const carouselItemWidth = document.querySelector(".c-carousel-inner .c-carousel-item").offsetWidth;
const carouselButtons = document.querySelectorAll(".c-carousel-control");
let startX, scrollSum = 0, mouseIsDown, count = 0, mx, moving=false, lastDirection, prevScroll;
carouselButtons.forEach((button) => {
button.addEventListener("click", function(){
if (button.id == "carousel-right") {
if (prevScroll) {
mouseToLeft();
}
prevScroll = true;
moveToLeftSnap();
} else if (button.id == "carousel-left") {
if (!prevScroll) {
mouseToRight();
}
moveToRightSnap();
prevScroll = false;
}
});
})
function mouseToLeft() {
if (count >= carouselLength) {
count = 0;
}
count++;
for (i=0; i < carouselLength; i++) {
carousel.children[i].style.removeProperty("order");
if (i < count) {
carousel.children[i].style.order = "1";
}
}
}
function mouseToRight() {
if (count <= 0) {
count = carouselLength;
}
count--;
for (i=carouselLength-1; i>=0; i--) {
carousel.children[i].style.removeProperty("order");
if (i >= count) {
carousel.children[i].style.order = "-1";
}
}
}
function moveToRightSnap(value=carouselItemWidth) {
carousel.style.removeProperty("transition");
carousel.style.transform = `translate3d(-${value}px, 0, 0)`;
setTimeout(() => {
carousel.style.transition = `transform 0.342s ease`;
carousel.style.transform = `translate3d(0, 0, 0)`;
}, 1);
}
function moveToLeftSnap(value=0) {
carousel.style.removeProperty("transition");
carousel.style.transform = `translate3d(${value}, 0, 0)`;
setTimeout(() => {
carousel.style.transition = `transform 0.342s ease`;
carousel.style.transform = `translate3d(-${carouselItemWidth}px, 0, 0)`;
}, 1);
}
const startDrag = (e) => {
mouseIsDown = true;
startX = e.pageX;
mx = e.pageX;
carousel.style.removeProperty("transition");
}
const dragging = (e) => {
if (mouseIsDown) {
scrollSum = e.pageX - startX;
console.log(scrollSum);
if (mx < e.pageX) {
lastDirection = "right";
} else if (mx > e.pageX) {
lastDirection = "left"
}
if (scrollSum > 0) {
startX = e.pageX + carouselItemWidth;
scrollSum = scrollSum - carouselItemWidth;
if (!prevScroll) {
mouseToRight();
}
} else if (prevScroll || scrollSum <= -carouselItemWidth) {
scrollSum = 0;
startX = e.pageX;
mouseToLeft();
prevScroll = false;
}
carousel.style.transform = `translate3d(${scrollSum}px,0,0)`;
mx = e.pageX;
}
}
const stopDrag = () => {
mouseIsDown = false;
if (lastDirection == "right") {
moveToRightSnap(scrollSum);
} else if (lastDirection == "left") {
moveToLeftSnap(scrollSum);
prevScroll = true;
}
}
carousel.addEventListener("mousedown", startDrag);
document.addEventListener("mousemove", dragging);
document.addEventListener("mouseup", stopDrag);
HTML code currently only single carousel is added here to make it short
<div class="main-container">
<div class="container">
<div class="c-carousel">
<ul id="" class="c-carousel-inner d-flex">
<% topAiring.forEach((item, index) => { %>
<li class="c-carousel-item item-<%= index + 1 %> col-3 <%= index == 0 ? 'active' : '' %>">
<img src="<%= item.images.jpg['image_url'] %>" draggable="false" class="d-block w-100" alt="...">
</li>
<% }) %>
</ul>
<button id="carousel-left" class="c-carousel-control" type="button">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button id="carousel-right" class="c-carousel-control" type="button">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
</div>
</div>
2
Answers
This code as it is has some fundamental issues. Most noticeably, in the case of multiple carousels you will get duplicated
id
s.id
should be a unique identifier for any element.Instead of
id
, you can usedata
attribute on your buttons. For example:Your function will then become something like:
Get the carousel by their
id
based on the buttonid
. In your handler functions use the specific carousel which you pass in, like:and do the same for other functions.
Don’t forget to
id
your carousels with the same kind of numbering you used for itsbutton
like:To implement dragging handles, get the target carousel from the event and pass it on to the functions as above. Like:
You will need to localise
scrollSum
and other variables that can impact other carousels. I will leave that to youAlternatively, you can make use of event bubbling that will reduce the number of listeners you create to, but that would be a whole different approach than what you currently have.
If you know which carousel is clicked or draged, you can do it easily. right?
-javascript
-html
I hope this answer can help you.
Good luck.
Oh, don’t forget to vote my answer if it works.