Niraj paul
Niraj paul

Reputation: 15

For loop not working on a Jquery selector

Struggling on a for loop.. I cant seem to make it work..Trying to add a for loop to the (".circle" + (i+1)) Selector but not hiding and fading in one circle(i). Is this possible or some similar approach?

Any help would be appreciate it!

<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<ul class="menu">
  <li class="first"><a href="#btn1">btn1</a></li>
  <li class="second"><a href="#btn2">btn2</a></li>
  <li class="third"><a href="#btn3">btn3</a></li>
  <li class="forth"><a href="#btn4">btn4</a></li>
</ul>

<div class="circle1 circle">1</div>
<div class="circle1 circle">2</div>
<div class="circle1 circle">3</div>
<div class="circle4 circle">4</div>

<script>
for(i=0;i<$(".menu li").length;i++){
    $(".menu li").eq(i).on('click',function(){
      $(".circle").hide();
      $('.circle'+(i+1)).stop().fadeIn('300');
      return false;
    });
  }
</script>
</body>
</html>

Upvotes: 0

Views: 1347

Answers (2)

Paul Richter
Paul Richter

Reputation: 11072

Matt Burland's answer is correct and very thorough. This is merely an alternate suggestion to avoid using the for loop (if you prefer):

// Use the jQuery's already-available `.each` method
$(".menu li").each(function(index, list_element){

    (function(list_index){ // as per Matt's answer
        list_element.on('click',function(){
            $(".circle").hide();
            $('.circle'+(list_index+1)).stop().fadeIn('300');
            return false;
        }
    })(index);

});

The effect is the same, and there is no performance difference (so far as I know); I find it slightly cleaner.

Upvotes: 0

Matt Burland
Matt Burland

Reputation: 45135

Your problem is with the way variables are scoped. i will always have the value that it had at the end of the loop in your click handler. You can fix it like this:

for(i=0;i<$(".menu li").length;i++){
    (function(j) {
        $(".menu li").eq(j).on('click',function(){
            $(".circle").hide();
            $('.circle'+(j+1)).stop().fadeIn('300');
            return false;
        });
    })(i);
}

What the above does is create a closure by using an Immediately Invoked Function Expression (IIFE) that creates a new scope and copies the value of i during the loop.

It would also be assign $(".menu li").length to a variable before the loop so that jQuery isn't recreating the collection every time it loops.

To understand what's going on, compare this:

for(i=0;i<5;i++){
    setTimeout(function() {
        console.log(i);
    },100);
}

// outputs: 5 5 5 5 5

To this:

for(i=0;i<5;i++){
    (function(i) {
        setTimeout(function() {
            console.log(i);
        },100);
    })(i);
}

// outputs: 0 1 2 3 4

http://jsfiddle.net/PLsUN/

Upvotes: 4

Related Questions