Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery Event Handler created in loop

Tags:

So I have a group of events like this:

$('#slider-1').click(function(event){   
        switchBanners(1, true);
});
$('#slider-2').click(function(event){   
        switchBanners(2, true);
});
$('#slider-3').click(function(event){   
        switchBanners(3, true);
});
$('#slider-4').click(function(event){   
        switchBanners(4, true);
});
$('#slider-5').click(function(event){   
        switchBanners(5, true);
});

And I wanted to run them through a loop I am already running something like this:

for(i = 1; i <= totalBanners; i++){
    $('#slider-' + i).click(function(event){    
            switchBanners(i, true);
    });
}   

In theory that should work, but it doesnt seem to once I load the document... It doesnt respond to any specific div id like it should when clicked... it progresses through each div regardless of which one I click. There are more event listeners I want to dynamically create on the fly but I need these first...

What am I missing?

like image 266
Ryan Erb Avatar asked Oct 14 '11 23:10

Ryan Erb


2 Answers

This is a very common issue people encounter.

JavaScript doesn't have block scope, just function scope. So each function you create in the loop is being created in the same variable environment, and as such they're all referencing the same i variable.

To scope a variable in a new variable environment, you need to invoke a function that has a variable (or function parameter) that references the value you want to retain.

In the code below, we reference it with the function parameter j.

   // Invoke generate_handler() during the loop. It will return a function that
   //                                          has access to its vars/params. 
function generate_handler( j ) {
    return function(event) { 
        switchBanners(j, true);
    };
}
for(var i = 1; i <= totalBanners; i++){
   $('#slider-' + i).click( generate_handler( i ) );
}

Here we invoked the generate_handler() function, passed in i, and had generate_handler() return a function that references the local variable (named j in the function, though you could name it i as well).

The variable environment of the returned function will exist as long as the function exists, so it will continue to have reference to any variables that existed in the environment when/where it was created.


UPDATE: Added var before i to be sure it is declared properly.

like image 156
user113716 Avatar answered Nov 22 '22 07:11

user113716


Instead of doing something this .. emm .. reckless, you should attach a single event listener and catch events us they bubble up. Its called "event delegation".

Some links:

  • http://davidwalsh.name/event-delegate
  • http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-event-delegation-in-4-minutes/
  • http://www.sitepoint.com/javascript-event-delegation-is-easier-than-you-think/
  • http://lab.distilldesign.com/event-delegation/

Study this. It is a quite important thing to learn about event management in javascript.

like image 24
tereško Avatar answered Nov 22 '22 05:11

tereško