Onur Demirci
Onur Demirci

Reputation: 35

How to run jQuery function for multiple elements individually?

I can't make my jQuery function work on individual elements. My function is a slider. When I put one slider to my html, it works fine, without problems. But whenever I try to put a second slider, it doesn't work properly. The first slider controls both of them, then the second slider takes the charge if I click right arrow too much etc.

Here is my jQuery code:

$('.right-arrow').click(function () {
    var currentSlide = $('.slide.active');
    var nextSlide = currentSlide.next();

    currentSlide.fadeOut(300).removeClass('active');
    nextSlide.fadeIn(300).addClass('active');

    if (nextSlide.length == 0) {
        $('.slide').first().fadeIn(300).addClass('active');
    }
});

$('.left-arrow').click(function() {
    var currentSlide = $('.slide.active');
    var prevSlide = currentSlide.prev();

    currentSlide.fadeOut(300).removeClass('active');
    prevSlide.fadeIn(300).addClass('active');

    if (prevSlide.length == 0) {
        $('.slide').last().fadeIn(300).addClass('active');
    }
});

And this is where I use it:

<style>
.slide {
    display:none;
}
.slide.active {
    display:block;
}
</style>

<div class="slider-container">
  <div id="slider1">
    <div class="slide active">#1</div>
    <div class="slide">#2</div>
    <div class="slide">#3</div>
  </div>
  <p class="left-arrow"><</p>
  <p class="right-arrow">></p>
</div>

<div class="slider-container">
  <div id="slider2">
    <div class="slide active">#a</div>
    <div class="slide">#b</div>
    <div class="slide">#c</div>
  </div>
  <p class="left-arrow"><</p>
  <p class="right-arrow">></p>
</div>

Like I said previously, when I click the first slider's right arrow, first slider's #2 and second slider's #b shows up.

Upvotes: 0

Views: 67

Answers (2)

Shidersz
Shidersz

Reputation: 17190

As other answers and comments mentioned, you are searching the .slide elements on the whole document. Instead you need to limit the search inside the related .slider-container element. For this purpose, you can use JQuery.closest(). Also, it will be nice to wait the fadeOut animation to finish using the complete callback function before showing the new .slide element. You can take next example as reference of implementation:

$('.right-arrow').click(function()
{
    var container = $(this).closest(".slider-container");
    var currSlide = container.find('.slide.active');
    var nextSlide = currSlide.next(".slide");

    if (nextSlide.length === 0)
        nextSlide = container.find('.slide:first-child');

    currSlide.fadeOut(300, function()
    {
        $(this).removeClass('active');
        nextSlide.fadeIn(300).addClass('active');
    });
});

$('.left-arrow').click(function()
{
    var container = $(this).closest(".slider-container");
    var currSlide = container.find('.slide.active');
    var prevSlide = currSlide.prev(".slide");
    
    if (prevSlide.length === 0)
        prevSlide = container.find('.slide:last-child');

    currSlide.fadeOut(300, function()
    {
        $(this).removeClass('active');
        prevSlide.fadeIn(300).addClass('active');
    });
});
.slide {
    display:none;
}
.slide.active {
    display:block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="slider-container">
  <div id="slider1">
    <div class="slide active">#1</div>
    <div class="slide">#2</div>
    <div class="slide">#3</div>
  </div>
  <p class="left-arrow">&lt;</p>
  <p class="right-arrow">&gt;</p>
</div>

<div class="slider-container">
  <div id="slider2">
    <div class="slide active">#a</div>
    <div class="slide">#b</div>
    <div class="slide">#c</div>
  </div>
  <p class="left-arrow">&lt;</p>
  <p class="right-arrow">&gt;</p>
</div>

Upvotes: 0

phishfordead
phishfordead

Reputation: 387

You are getting this behavior because of the line

var currentSlide = $('.slide.active');

which selects all elements with the classes slide and active. try replacing that line with something like this:

var currentSlide = $(this).parent().find('.slide.active');

What this is doing is selecting the element the event was fired on $(this). Then getting the parent of that element, then finding the active slide within that element.

EDIT Here is an example of your first if statement. Once again, you are getting the parent of the element that caused the event, then searching inside that dom element for all of the elements with a class of 'slide'.

As a side note you might want to make $(this) a variable something like var $this = $(this). Then use $this instead of $(this). It's a performance issue that you may or may not be concerned with.

if (nextSlide.length == 0) {
    $(this).parent().find('.slide').first().fadeIn(300).addClass('active');

}

Upvotes: 1

Related Questions