Issue
I tried to add the for loop to go through each carousel, but when I do that, now non of them works. Before I added the for-loop, only the first one worked.
initially it was :
querySelector('.carousel')
Then I changed it to :
querySelectorAll('.carousel')
var carousel = document.querySelectorAll('.carousel'), i;
for (i = 0; i < carousel.length; ++i) {
firstImg = carousel[i].querySelectorAll("img")[0];
arrowIcons = document.querySelectorAll(".wrapper i");
let isDragStart = false, isDragging = false, prevPageX, prevScrollLeft, positionDiff;
carousel[i].addEventListener("mousedown", dragStart);
carousel[i].addEventListener("touchstart", dragStart);
document.addEventListener("mousemove", dragging);
carousel[i].addEventListener("touchmove", dragging);
document.addEventListener("mouseup", dragStop);
carousel[i].addEventListener("touchend", dragStop);
}
const showHideIcons = () => {
// showing and hiding prev/next icon according to carousel scroll left value
let scrollWidth = carousel.scrollWidth - carousel.clientWidth; // getting max scrollable width
arrowIcons[0].style.display = carousel.scrollLeft == 0 ? "none" : "block";
arrowIcons[1].style.display = carousel.scrollLeft == scrollWidth ? "none" : "block";
}
arrowIcons.forEach(icon => {
icon.addEventListener("click", () => {
let firstImgWidth = firstImg.clientWidth + 14; // getting first img width & adding 14 margin value
// if clicked icon is left, reduce width value from the carousel scroll left else add to it
carousel.scrollLeft += icon.id == "left" ? -firstImgWidth : firstImgWidth;
setTimeout(() => showHideIcons(), 60); // calling showHideIcons after 60ms
});
});
const autoSlide = () => {
// if there is no image left to scroll then return from here
if(carousel.scrollLeft - (carousel.scrollWidth - carousel.clientWidth) > -1 || carousel.scrollLeft <= 0) return;
positionDiff = Math.abs(positionDiff); // making positionDiff value to positive
let firstImgWidth = firstImg.clientWidth + 14;
// getting difference value that needs to add or reduce from carousel left to take middle img center
let valDifference = firstImgWidth - positionDiff;
if(carousel.scrollLeft > prevScrollLeft) { // if user is scrolling to the right
return carousel.scrollLeft += positionDiff > firstImgWidth / 3 ? valDifference : -positionDiff;
}
// if user is scrolling to the left
carousel.scrollLeft -= positionDiff > firstImgWidth / 3 ? valDifference : -positionDiff;
}
const dragStart = (e) => {
// updatating global variables value on mouse down event
isDragStart = true;
prevPageX = e.pageX || e.touches[0].pageX;
prevScrollLeft = carousel.scrollLeft;
}
const dragging = (e) => {
// scrolling images/carousel to left according to mouse pointer
if(!isDragStart) return;
e.preventDefault();
isDragging = true;
carousel.classList.add("dragging");
positionDiff = (e.pageX || e.touches[0].pageX) - prevPageX;
carousel.scrollLeft = prevScrollLeft - positionDiff;
showHideIcons();
}
const dragStop = () => {
isDragStart = false;
carousel.classList.remove("dragging");
if(!isDragging) return;
isDragging = false;
autoSlide();
}
/* Import Google font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body{
//display: flex;
padding: 0 35px;
min-height: 100vh;
align-items: center;
justify-content: center;
background: #343F4F;
}
.wrapper{
display: flex;
max-width: 1200px;
position: relative;
}
.wrapper i{
top: 50%;
height: 44px;
width: 44px;
color: #343F4F;
cursor: pointer;
font-size: 1.15rem;
position: absolute;
text-align: center;
line-height: 44px;
background: #fff;
border-radius: 50%;
transform: translateY(-50%);
transition: transform 0.1s linear;
}
.wrapper i:active{
transform: translateY(-50%) scale(0.9);
}
.wrapper i:hover{
background: #f2f2f2;
}
.wrapper i:first-child{
left: -22px;
display: none;
}
.wrapper i:last-child{
right: -22px;
}
.wrapper .carousel{
font-size: 0px;
cursor: pointer;
overflow: hidden;
white-space: nowrap;
scroll-behavior: smooth;
}
.carousel.dragging{
cursor: grab;
scroll-behavior: auto;
}
.carousel.dragging img{
pointer-events: none;
}
.carousel img{
height: 340px;
object-fit: cover;
user-select: none;
margin-left: 14px;
width: calc(100% / 3);
}
.carousel img:first-child{
margin-left: 0px;
}
@media screen and (max-width: 900px) {
.carousel img{
width: calc(100% / 2);
}
}
@media screen and (max-width: 550px) {
.carousel img{
width: 100%;
}
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Draggable Image Slider | CodingNepal</title>
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
</head>
<body>
<div>
<div class="wrapper">
<i id="left" class="fa-solid fa-angle-left"></i>
<div class="carousel">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back04.jpg" alt="img" draggable="false">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back02.jpg" alt="img" draggable="false">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back01.jpg" alt="img" draggable="false">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back05.jpg" alt="img" draggable="false">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back07.jpg" alt="img" draggable="false">
</div>
<i id="right" class="fa-solid fa-angle-right"></i>
</div>
</div>
<p>
hihifdd
</p>
<div class="wrapper">
<i id="left" class="fa-solid fa-angle-left"></i>
<div class="carousel">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back04.jpg" alt="img" draggable="false">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back02.jpg" alt="img" draggable="false">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back01.jpg" alt="img" draggable="false">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back05.jpg" alt="img" draggable="false">
<img src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back07.jpg" alt="img" draggable="false">
</div>
<i id="right" class="fa-solid fa-angle-right"></i>
</div>
</body>
</html>
Solution
You'd want to bring the rest of the functions into the for
loop, and adjust the code so that the functions reference properties from the curent carousel element being iterated upon:
var carousel = document.querySelectorAll(".carousel"),
i;
for (i = 0; i < carousel.length; ++i) {
const thisCourusel = carousel[i];
const firstImg = thisCourusel.querySelectorAll("img")[0];
const arrowIcons = thisCourusel.closest(".wrapper").querySelectorAll("i");
let isDragStart = false,
isDragging = false,
prevPageX,
prevScrollLeft,
positionDiff;
const dragStart = (e) => {
// updatating global variables value on mouse down event
isDragStart = true;
prevPageX = e.pageX || e.touches[0].pageX;
prevScrollLeft = thisCourusel.scrollLeft;
};
const dragging = (e) => {
// scrolling images/carousel to left according to mouse pointer
if (!isDragStart) return;
e.preventDefault();
isDragging = true;
thisCourusel.classList.add("dragging");
positionDiff = (e.pageX || e.touches[0].pageX) - prevPageX;
thisCourusel.scrollLeft = prevScrollLeft - positionDiff;
showHideIcons();
};
const dragStop = () => {
isDragStart = false;
thisCourusel.classList.remove("dragging");
if (!isDragging) return;
isDragging = false;
autoSlide();
};
thisCourusel.addEventListener("mousedown", dragStart);
thisCourusel.addEventListener("touchstart", dragStart);
document.addEventListener("mousemove", dragging);
thisCourusel.addEventListener("touchmove", dragging);
document.addEventListener("mouseup", dragStop);
thisCourusel.addEventListener("touchend", dragStop);
const showHideIcons = () => {
// showing and hiding prev/next icon according to carousel scroll left value
let scrollWidth = thisCourusel.scrollWidth - thisCourusel.clientWidth; // getting max scrollable width
arrowIcons[0].style.display =
thisCourusel.scrollLeft == 0 ? "none" : "block";
arrowIcons[1].style.display =
thisCourusel.scrollLeft == scrollWidth ? "none" : "block";
};
arrowIcons.forEach((icon) => {
icon.addEventListener("click", () => {
let firstImgWidth = firstImg.clientWidth + 14; // getting first img width & adding 14 margin value
// if clicked icon is left, reduce width value from the carousel scroll left else add to it
thisCourusel.scrollLeft +=
icon.id == "left" ? -firstImgWidth : firstImgWidth;
setTimeout(() => showHideIcons(), 60); // calling showHideIcons after 60ms
});
});
const autoSlide = () => {
// if there is no image left to scroll then return from here
if (
thisCourusel.scrollLeft -
(thisCourusel.scrollWidth - thisCourusel.clientWidth) >
-1 ||
thisCourusel.scrollLeft <= 0
)
return;
positionDiff = Math.abs(positionDiff); // making positionDiff value to positive
let firstImgWidth = firstImg.clientWidth + 14;
// getting difference value that needs to add or reduce from carousel left to take middle img center
let valDifference = firstImgWidth - positionDiff;
if (carousel.scrollLeft > prevScrollLeft) {
// if user is scrolling to the right
return (thisCourusel.scrollLeft +=
positionDiff > firstImgWidth / 3 ? valDifference : -positionDiff);
}
// if user is scrolling to the left
thisCourusel.scrollLeft -=
positionDiff > firstImgWidth / 3 ? valDifference : -positionDiff;
};
}
/* Import Google font - Poppins */
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
//display: flex;
padding: 0 35px;
min-height: 100vh;
align-items: center;
justify-content: center;
background: #343f4f;
}
.wrapper {
display: flex;
max-width: 1200px;
position: relative;
}
.wrapper i {
top: 50%;
height: 44px;
width: 44px;
color: #343f4f;
cursor: pointer;
font-size: 1.15rem;
position: absolute;
text-align: center;
line-height: 44px;
background: #fff;
border-radius: 50%;
transform: translateY(-50%);
transition: transform 0.1s linear;
}
.wrapper i:active {
transform: translateY(-50%) scale(0.9);
}
.wrapper i:hover {
background: #f2f2f2;
}
.wrapper i:first-child {
left: -22px;
display: none;
}
.wrapper i:last-child {
right: -22px;
}
.wrapper .carousel {
font-size: 0px;
cursor: pointer;
overflow: hidden;
white-space: nowrap;
scroll-behavior: smooth;
}
.carousel.dragging {
cursor: grab;
scroll-behavior: auto;
}
.carousel.dragging img {
pointer-events: none;
}
.carousel img {
height: 340px;
object-fit: cover;
user-select: none;
margin-left: 14px;
width: calc(100% / 3);
}
.carousel img:first-child {
margin-left: 0px;
}
@media screen and (max-width: 900px) {
.carousel img {
width: calc(100% / 2);
}
}
@media screen and (max-width: 550px) {
.carousel img {
width: 100%;
}
}
<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<title>Draggable Image Slider | CodingNepal</title>
<link rel="stylesheet" href="style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
/>
</head>
<body>
<div>
<div class="wrapper">
<i id="left" class="fa-solid fa-angle-left"></i>
<div class="carousel">
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back04.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back02.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back01.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back05.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back07.jpg"
alt="img"
draggable="false"
/>
</div>
<i id="right" class="fa-solid fa-angle-right"></i>
</div>
</div>
<p>hihifdd</p>
<div class="wrapper">
<i id="left" class="fa-solid fa-angle-left"></i>
<div class="carousel">
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back04.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back02.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back01.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back05.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back07.jpg"
alt="img"
draggable="false"
/>
</div>
<i id="right" class="fa-solid fa-angle-right"></i>
</div>
</body>
</html>
It may behove you to use a forEach()
loop to make the code more clear, like:
document.querySelectorAll(".carousel").forEach((carousel) => {
const firstImg = carousel.querySelectorAll("img")[0];
const arrowIcons = carousel.closest(".wrapper").querySelectorAll("i");
let isDragStart = false,
isDragging = false,
prevPageX,
prevScrollLeft,
positionDiff;
const dragStart = (e) => {
// updatating global variables value on mouse down event
isDragStart = true;
prevPageX = e.pageX || e.touches[0].pageX;
prevScrollLeft = carousel.scrollLeft;
};
const dragging = (e) => {
// scrolling images/carousel to left according to mouse pointer
if (!isDragStart) return;
e.preventDefault();
isDragging = true;
carousel.classList.add("dragging");
positionDiff = (e.pageX || e.touches[0].pageX) - prevPageX;
carousel.scrollLeft = prevScrollLeft - positionDiff;
showHideIcons();
};
const dragStop = () => {
isDragStart = false;
carousel.classList.remove("dragging");
if (!isDragging) return;
isDragging = false;
autoSlide();
};
carousel.addEventListener("mousedown", dragStart);
carousel.addEventListener("touchstart", dragStart);
document.addEventListener("mousemove", dragging);
carousel.addEventListener("touchmove", dragging);
document.addEventListener("mouseup", dragStop);
carousel.addEventListener("touchend", dragStop);
const showHideIcons = () => {
// showing and hiding prev/next icon according to carousel scroll left value
let scrollWidth = carousel.scrollWidth - carousel.clientWidth; // getting max scrollable width
arrowIcons[0].style.display = carousel.scrollLeft == 0 ? "none" : "block";
arrowIcons[1].style.display =
carousel.scrollLeft == scrollWidth ? "none" : "block";
};
arrowIcons.forEach((icon) => {
icon.addEventListener("click", () => {
let firstImgWidth = firstImg.clientWidth + 14; // getting first img width & adding 14 margin value
// if clicked icon is left, reduce width value from the carousel scroll left else add to it
carousel.scrollLeft += icon.id == "left" ? -firstImgWidth : firstImgWidth;
setTimeout(() => showHideIcons(), 60); // calling showHideIcons after 60ms
});
});
const autoSlide = () => {
// if there is no image left to scroll then return from here
if (
carousel.scrollLeft - (carousel.scrollWidth - carousel.clientWidth) >
-1 ||
carousel.scrollLeft <= 0
)
return;
positionDiff = Math.abs(positionDiff); // making positionDiff value to positive
let firstImgWidth = firstImg.clientWidth + 14;
// getting difference value that needs to add or reduce from carousel left to take middle img center
let valDifference = firstImgWidth - positionDiff;
if (carousel.scrollLeft > prevScrollLeft) {
// if user is scrolling to the right
return (carousel.scrollLeft +=
positionDiff > firstImgWidth / 3 ? valDifference : -positionDiff);
}
// if user is scrolling to the left
carousel.scrollLeft -=
positionDiff > firstImgWidth / 3 ? valDifference : -positionDiff;
};
});
/* Import Google font - Poppins */
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
//display: flex;
padding: 0 35px;
min-height: 100vh;
align-items: center;
justify-content: center;
background: #343f4f;
}
.wrapper {
display: flex;
max-width: 1200px;
position: relative;
}
.wrapper i {
top: 50%;
height: 44px;
width: 44px;
color: #343f4f;
cursor: pointer;
font-size: 1.15rem;
position: absolute;
text-align: center;
line-height: 44px;
background: #fff;
border-radius: 50%;
transform: translateY(-50%);
transition: transform 0.1s linear;
}
.wrapper i:active {
transform: translateY(-50%) scale(0.9);
}
.wrapper i:hover {
background: #f2f2f2;
}
.wrapper i:first-child {
left: -22px;
display: none;
}
.wrapper i:last-child {
right: -22px;
}
.wrapper .carousel {
font-size: 0px;
cursor: pointer;
overflow: hidden;
white-space: nowrap;
scroll-behavior: smooth;
}
.carousel.dragging {
cursor: grab;
scroll-behavior: auto;
}
.carousel.dragging img {
pointer-events: none;
}
.carousel img {
height: 340px;
object-fit: cover;
user-select: none;
margin-left: 14px;
width: calc(100% / 3);
}
.carousel img:first-child {
margin-left: 0px;
}
@media screen and (max-width: 900px) {
.carousel img {
width: calc(100% / 2);
}
}
@media screen and (max-width: 550px) {
.carousel img {
width: 100%;
}
}
<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<title>Draggable Image Slider | CodingNepal</title>
<link rel="stylesheet" href="style.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
/>
</head>
<body>
<div>
<div class="wrapper">
<i id="left" class="fa-solid fa-angle-left"></i>
<div class="carousel">
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back04.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back02.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back01.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back05.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back07.jpg"
alt="img"
draggable="false"
/>
</div>
<i id="right" class="fa-solid fa-angle-right"></i>
</div>
</div>
<p>hihifdd</p>
<div class="wrapper">
<i id="left" class="fa-solid fa-angle-left"></i>
<div class="carousel">
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back04.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back02.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back01.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back05.jpg"
alt="img"
draggable="false"
/>
<img
src="https://codeskulptor-demos.commondatastorage.googleapis.com/GalaxyInvaders/back07.jpg"
alt="img"
draggable="false"
/>
</div>
<i id="right" class="fa-solid fa-angle-right"></i>
</div>
</body>
</html>
The benefit here is that you don't get the dissonance between the naming of the carousel
variable – where I expect it to be plural for a collection carousels.
Answered By - Wongjn
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.