I have a page with multiple carousel rows, but whenever I click on the button "next" or "prev" to show the other items of the carousel it impacts all carousels, not only the clicked one.
I have tried separating them in partial views so each js is executed only in its context, but it is still the same problem.
I want to be able to see the next item and the previous independently from another
If possible I wanted the js to get only items inside the partial view, but if there's other solution I am open to hear
js:
$(document).ready(function () {
const multipleItemCarousel = document.querySelector('#carouselExample')
if (window.matchMedia('(min-width: 576px)').matches) {
const carousel = new bootstrap.Carousel(multipleItemCarousel, {
interval: false
})
var carouselWidth = $('.carousel-inner')[0].scrollWidth;
var cardWidth = $('.carousel-item').width();
var scrollPosition = 0;
$('.carousel-control-next').click(function () {
if (scrollPosition < carouselWidth - (cardWidth * 4)) {
scrollPosition += cardWidth;
$('.carousel-inner').animate(
{ scrollLeft: scrollPosition },
600
);
}
});
$('.carousel-control-prev').click(function () {
if (scrollPosition > 0) {
scrollPosition -= cardWidth;
$('.carousel-inner').animate(
{ scrollLeft: scrollPosition },
600
);
}
});
}
else {
$(multipleItemCarousel).addClass('slide');
}
});
HTML:
<div id="carouselExample" class="carousel">
<div class="carousel-inner">
<div class="carousel-item active">
<div class="card">
@{
var firstCourse = Model.First();
<img src="@firstCourse.Image" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">@firstCourse.Title</h5>
<h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
<p class="card-text">@firstCourse.Description</p>
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
}
</div>
</div>
@foreach (var course in Model.Skip(1))
{
<div class="carousel-item">
<div class="card">
<img src="@course.Image" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">@course.Title</h5>
<h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
<p class="card-text">@course.Description</p>
<a href="#" class="card-link">Card link</a>
<a href="#" class="card-link">Another link</a>
</div>
</div>
</div>
}
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExample" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExample" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
I have included the HTML
Each of the carousels should live in its own scope. Notice the use of $.find
which finds elements that are children of the carousel.
$(document).ready(function() {
// i'm assuming #carouselExample is the id of all your carousels
const multipleItemCarousels = document.querySelectorAll('#carouselExample')
multipleItemCarousels.forEach(function(multipleItemCarousel) {
if (window.matchMedia('(min-width: 576px)').matches) {
const carousel = new bootstrap.Carousel(multipleItemCarousel, {
interval: false
})
var carouselWidth = $(multipleItemCarousel).find('.carousel-inner')[0].scrollWidth;
var cardWidth = $(multipleItemCarousel).find('.carousel-item').width();
var scrollPosition = 0;
$(multipleItemCarousel).find('.carousel-control-next').click(function() {
if (scrollPosition < carouselWidth - (cardWidth * 4)) {
scrollPosition += cardWidth;
$(multipleItemCarousel).find('.carousel-inner').animate({
scrollLeft: scrollPosition
},
600
);
}
});
$(multipleItemCarousel).find('.carousel-control-prev').click(function() {
if (scrollPosition > 0) {
scrollPosition -= cardWidth;
$(multipleItemCarousel).find('.carousel-inner').animate({
scrollLeft: scrollPosition
},
600
);
}
});
} else {
$(multipleItemCarousel).addClass('slide');
}
})
});