Search code examples
javascripthtmljquerycss.net

Carousel linked roll to the side independently


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>

My carousel view

I have included the HTML


Solution

  • 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');
        }
      })
    });