I often need to add events to an element inside a JavaScript loop. If you’ve ever done this before, you know that it wont work unless you change the syntax properly, the event will always fire on the last item in the loop. In this article I will show you the simple concept of using a closure around the event to make it work properly.
The proper way to handle this code only involves 2 words, some parenthesis, and some brackets. Personally, I always forget the way it’s supposed to look, so I am forever storing it for reference in this article!
The Wrong Way
Below is an example of code that won’t work. It’s the same code that would get most people to this article in search of help. It doesn’t work because you overwrite the event with each iteration of the loop.
// the WRONG way for(var i=1; i<10; i++){ someElement.onclick = function(a1,a2){ myNewFunction(a1,a2); } } |
The Right Way
Below is the correct example. It simply creates an anonymous function that can exist on its own and won’t be overwritten. This is a 2 step process. The first step is to wrap return function(){ ... }
around your events action. The second step is simply calling the event handler function using parenthesis ()
. Your original arguments go in between those parenthesis.
Notice how I named my original arguments ‘arg1’ and ‘arg2.’ Our event handler function can call the arguments anything it wants, which I called ‘a1’ and ‘a2.’
for(var i=1; i<10; i++){ someElement.onclick = function(a1,a2){ return function(){ myNewFunction(a1,a2); } }(arg1,arg2); } |
This usage of closures will allow your events to fire properly with the correct parameters. If this tip helped you out, leave a comment!
Life saver!!! Thanks a lot for this one!!
glad to help!
Funny thing… Looks like it doesn’t work in IE 9.
I can say that my code is OK since it works like a charm in FF 4.0
Could you have a look please?
Thank you in advance
Just checked it out in IE9, works fine. I used the following test:
<input type="button" id="btn1" value="btn1" />
<input type="button" id="btn2" value="btn2" />
<script type="text/javascript">
for(var i=1; i<3; i++){
var el = document.getElementById("btn"+i);
el.onclick = function(a1){
return function(){ myNewFunction(a1); }
}(el.value);
}
function myNewFunction(a1){ alert("A1 = "+a1); }
</script>
Hi, thank you for such a fast reply
this is what I do
var el;
for (var i = 0; i < somelength; i++)
{
el = document.createElement("img");
el.src = 'someimagesource';
el.id = 'img' + i;
// here I append 'el' to a container.
el = document.getElementById('img'+i);
el.onclick = function(sender)
{
return function(){ somefunction(sender); }
}(el);
}
and for some reason it doesn't work in IE9 (can't check on previous IE versions), but it works in FF 4.
I tried to detach all javascript files without any luck.
I've solved it for now by doing this
el.setAttribute('onclick','somefunction(event)');
and then I extract sender from event target or srcElement.
it works but it looks really lame.. (((
I'll get tomorrow to a computer at office and will check this issue on it to ensure it's only me, not the whole concept… (((
Your code works fine in IE9. Tested it here.
Also, you say you can’t check previous versions- yes you can. IE9 includes IE8 and IE7. You press F12 and select “Browser Mode.”
then I just don’t get why doesn’t it work for me…
Thank you any way..
I’ll try to rewrite the whole thing to find out what ‘causing this behaviour… errhh…
Thanks a lot for sharing. i had been trying to solve this problem for past 2 days. Found the solution here… Many thanks!!! Indeed a wonderful post!!!
LifeSaver. Thanks.