How to remove class from multiple elements in reverse order?

I have a toggle-like interaction that adds a class to a list of items, then removes the class from all items upon second click. I am doing if else to achieve this, but am failing trying to get the class removal to occur in the reverse order.

I’ve been working with .reverse().each and get().reverse().each but can’t seem to include it properly. Can that be done with the if else or does it need to be done differently?

To clarify, the class is added to each item .row with a delay starting with the first item. I want it to start with the last item when the class is removed.

$('button').click(function() {
  var interval = 0;
  $.each($('.row'), function() {
    // Check if .row is active 
    if ($('.row').hasClass('active')) {
      // Remove class at interval
      var item = $(this);
      setTimeout(function() {
        item.removeClass('active')
      }, interval);
      interval += 80;
      // If not...
    } else {
      // Add class at interval
      var item = $(this);
      setTimeout(function() {
        item.addClass('active')
      }, interval);
      interval += 80;
    }
  });
});
.row {
  background: #ccc;
  width: 100px;
  height: 20px;
  margin-bottom: 5px;
  transition: all 0.4s;
}

.active {
  background: green;
  width: 200px;
  transition: all 0.4s;
}

button {
  margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<button>Click to run</button>

Fiddle

Answer

Assuming that by ‘running the effect in reverse’ you mean that you want the green bars to animate out from bottom to top, then you can use reverse() to reorder the collection before you run the loop.

In addition you can simplify the logic slightly by using toggleClass() instead of having the if determine state. Try this:

let $rows = $('.row');

$('button').click(function() {
  var interval = 0;
  let $btn = $(this).toggleClass('foo');

  let $orderedRows = $btn.hasClass('foo') ? $rows : $($rows.get().reverse());
  $orderedRows.each(function() {
    var item = $(this);
    setTimeout(function() {
      item.toggleClass('active')
    }, interval);
    interval += 80;
  });
});
.row {
  background: #ccc;
  width: 100px;
  height: 20px;
  margin-bottom: 5px;
  transition: all 0.4s;
}

.active {
  background: green;
  width: 200px;
  transition: all 0.4s;
}

button {
  margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<button>Click to run</button>

Leave a Reply

Your email address will not be published. Required fields are marked *