Search code examples
jquerysequenceinfinite-loop

toogle class of list of elements sequentially infinitely


I have a series of div elements that I want to show and hide sequentially using toggleClass. My code works like a charm.

I would now like to go back to the first div when the last div is active, and so on infinitely. I can't figure out how to do this.

var timeout = 2000
setTimeout(function() {
  $(".text-sequence .text").each(function(i, el) {
    var $this = $(this);
    setTimeout(function() {
      $this.toggleClass('active')
      $(".text-sequence .text").not($this).removeClass('active')
    }, i * timeout)
  })
}, timeout)
.text {
  opacity: 0
}

.text.active {
  opacity: 1
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="text-sequence">
  <div class="text">Text 1</div>
  <div class="text">Text 2</div>
  <div class="text">Text 3</div>
  <div class="text">Text 4</div>
  <div class="text">Text 5</div>
  <div class="text">Text 6</div>
</div>


Solution

  • Your code is a bit more complex than necessary. You don't need to wrap an interval in a timeout, and you don't need the loop within that timeout.

    To do what you require simply target the current .active element and use next() to get the next element. You can determine if there is no next element and then go back to the first() again.

    Note in the following example that I shortened the interval to make the effect more obvious.

    let timeout = 500;
    let $text = $('.text-sequence .text');
    let updateActiveText = () => {
      let $current = $text.filter('.active').removeClass('active');
      let $next = $current.next();
      if ($next.length == 0)
        $next = $text.first();    
      $next.addClass('active');
    }
    
    updateActiveText(); // on load
    setInterval(updateActiveText, timeout) // every n iterval;
    .text {
      opacity: 0
    }
    
    .text.active {
      opacity: 1
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="text-sequence">
      <div class="text">Text 1</div>
      <div class="text">Text 2</div>
      <div class="text">Text 3</div>
      <div class="text">Text 4</div>
      <div class="text">Text 5</div>
      <div class="text">Text 6</div>
    </div>