Search code examples
jqueryarraysloopsinitvariable-length-array

Bug in jQuery array (i), when adding a +1 to a negative value


I guess I'm fighting a bug. I build a small carousel in jquery. It's more some boxs stacked on each other, that will change their z-index (jquery.css) when my user clicks the next and prev arrows. So far so good, the carousel is connected with owl-carousel, but it's independent. Each box has a class that I store in an array and I loop through with jquery. The problem is the following:

Jquery:

$(document).ready(function () {

    var carousel = $('.covercarousel');
    var carouselnum = carousel.length;
    var i = 0;

    $('.owl-next').click(function () {
        i++;

        $(carousel).css('zIndex', '0');
        $(carousel[i]).css('zIndex', '2');
        if (i == (carouselnum-1)) {
            $(carousel).css('zIndex', '2');
            i = -1;
        }
    });

    $('.owl-prev').click(function () {
        i--;
        $(carousel).css('zIndex', '0');
        $(carousel[i]).css('zIndex', '2');
        if (i < 0) {

            i = carouselnum-1;
            $(carousel[5]).css('z-index', '2');
            $(carousel).css('zIndex', '0');
        }
    });
});

HTML:

<div class="covercarouselbox">
    <div class="covercarousel">
        <div>
            a
        </div>
    </div>
    <div class="covercarousel">
        <div>
            b
        </div>
    </div>
    <div class="covercarousel">
        <div>
            c
        </div>
    </div>
    <div class="covercarousel">
        <div>
            d
        </div>
    </div>
    <div class="covercarousel">
        <div>
            e
        </div>
    </div>
    <div class="covercarousel">
        <div>
            f
        </div>
    </div>
</div>

The carousel works fine when you scroll to the next div. If you console log the (i), you can notice that the count works fine from 0 to 4 (there are 6 elements in the array, I gave to the first one a z-index 2 with css => covercarousel:nth-child(1) {z-index=2} ), so when you reach the fifth element in the array, the value assigned to the i is -1, so the count comes back to 0 (i++).

But when you do the opposite it brakes: The first value is 0, so when you add the -1 to the array pressing the prev arrow, and then you try to scroll to the next slide inside adding a +1 to the i for some reason, if you console log the value of the (i), the result will be 5 and then it will keep growing. Is there any way to prevent this behavior?


Solution

  • You were trying to modify the DOM both before and after modifying i, which was leading to a lot of bugs depending on where exactly the user was in the sequence when clicking next or previous. There was also one place where you inadvertently hardcoded the length of the carousel, which would have caused additional problems if that didn't match the DOM. Deliberately setting -1 when the "next" button loops around to the beginning assumes the user is going to click "next" again; that, too, would break if the user didn't behave exactly as you planned.

    I've simplified all that here: figure out what i should be first, and then modify the DOM based on that:

    $(document).ready(function() {
    
      var carousel = $('.covercarousel');
      var carouselnum = carousel.length - 1;
      var i = 0;
    
      $('.owl-next').click(function() {
        i++;
        if (i>carouselnum) {i=0}
        // console.log(i);
        $(carousel).css('backgroundColor', '#FFF');
        $(carousel[i]).css('backgroundColor', '#FFC');
      });
    
      $('.owl-prev').click(function() {
        i--;
        if (i<0) {i = carouselnum}
        // console.log(i);
        $(carousel).css('backgroundColor', '#FFF');
        $(carousel[i]).css('backgroundColor', '#FFC');    
      });
    });
    .covercarousel {display:inline-block; padding: 0.5em}
    .owl-next, .owl-prev {cursor: pointer}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="covercarouselbox">
      <div class="covercarousel"><div>a</div></div>
      <div class="covercarousel"><div>b</div></div>
      <div class="covercarousel"><div>c</div></div>
      <div class="covercarousel"><div>d</div></div>
      <div class="covercarousel"><div>e</div></div>
      <div class="covercarousel"><div>f</div></div>
    </div>
    <div class="owl-next">Next</div>
    <div class="owl-prev">Prev</div>

    (This sets the backgroundColor instead of the zIndex so you can see what it's doing, but otherwise it's the same idea.)