c01gat3 c01gat3 - 6 months ago 5
Javascript Question

jQuery - repeating each() for each() element but resetting between loops

I want to perform an action on the first 4 elements of each group.

The problem I have is that it doesn't seem to reset the count when it iterates through the next group.

With this example, the first four items of each group should be red, but it only works on the first group, not the second... please help :)

html

<div class="group">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
</div>
<div class="group">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
</div>


jQuery

var itemLimit = 4;
$('.group').each(function(){
$('.item').each(function(index, value){
if(index < itemLimit){
$(value).addClass('red')
}
});
});


css

.red{
color: red;
}


here is a fiddle: https://jsfiddle.net/a4zja9th/

Answer

Your .item index refers to the index of all those .item together1.

A simpler variant would be using .find() and the :lt() selector

var itemLimit = 4;

$(".group").find(".item:lt("+itemLimit+")").addClass("red");
.group{
  padding: 10px;
}
.red{
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="group">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
</div>
<div class="group">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
  <div class="item">Item 6</div>
  <div class="item">Item 7</div>
</div>

Want to do more stuff than just an .addClass() ? Use .each() on your already filtered elements collection:

$(".group").find(".item:lt("+itemLimit+")").each(function() {
   // addClass
   // or whatever you want
});

1) The above is how I'd do it... Now let's explain your issue:

// DON'T USE!! JUST FOR EXPLANATION:
$('.group').each(function() {
  $('.item').each(function(index, value) { // You're taking all .item from the DOM

    console.log($(this).index(), index);  // See the difference in console!

    if($(this).index() < itemLimit) {     // Using $(this).index();
      $(value).addClass('red')
    }
  });
});

...cause index is the index of every .item in the collection of all .item.
instead $(this).index() is the actual index of an .item within it's parent .group.

[jsFiddle using .index() instead of .each(index][1]

To correctly refer .item child of (this) .group you could use instead $('.item', this).each( or $(this).find(".item").each(

var itemLimit = 4;

$('.group').each(function() {
  $('.item', this).each(function(index, value) {
    if(index < itemLimit) {
      $(value).addClass('red')
    }
  });
});

jsFiddle Fixed child reference

Comments