Javascript addEventListener – peculiarity or bug?
Yesterday I was writing some javascript code to dynamically produce a list and add an event listener for when an item in the list was clicked on. When I then tested it out, for some reason the last event listener seems to have overridden all the others in the list. I’m not sure if the is a Javascript ‘feature’ or bug, but it occurs in both Firefox (v2) and IE (v6).
This is the code I tested:
function init(){
var myUl = document.getElementById("test");
for(var i=0; i<10; i++){
var myLi = document.createElement("li");
mySpan = document.createElement("span");
mySpan.setAttribute("id","myspan"+i);
myLi.appendChild(mySpan);
myUl.appendChild(myLi);
mySpan.appendChild(document.createTextNode(i));
if(mySpan.addEventListener){ // Mozilla, Netscape, Firefox
mySpan.addEventListener('click', function(){test(i);}, false);
} else { // IE
mySpan.attachEvent('onclick', function(){test(i);});
}
}
}
function test(myNum){
alert(myNum);
}
This produces an unordered list of 10 items – (0-9), but when you click on any of the numbers the alert returns ’10′, rather than the expected 0-9 depending on which on you click. I could understand if it returned ’9′ for every item in the list – but why 10?? I spent ages fiddling with this, but never did find what was actually causing this to occur – it seems like a bug to me – unless I’m just misunderstanding how the addEventListeners work? Maybe something to do with the fact I’m using anonymous functions?
If anyone has an explanation (or can point me to an explanation) as to what I’ve done wrong it would be much appreciated.
For info I managed to get around the problem by using the code below instead, though I’d still like to know what was wrong with my original code!
function init(){
var myUl = document.getElementById("test");
for(var i=0; i<10; i++){
var myLi = document.createElement("li");
mySpan = document.createElement("span");
mySpan.setAttribute("id",i);
myLi.appendChild(mySpan);
myUl.appendChild(myLi);
mySpan.appendChild(document.createTextNode(i));
if(mySpan.addEventListener){ // Mozilla, Netscape, Firefox
mySpan.addEventListener('click', eventHandler, false);
} else { // IE
mySpan.attachEvent('onclick', eventHandler);
}
}
}
function eventHandler(e){
var e=e? e : window.event;
var el=e.target? e.target : e.srcElement;
alert(el.id);
}

I don’t know anything about JavaScript but…
won’t 10 be the value that i has at the end of the loop?
I think your script is setting up the elements with the function ‘test(i)’ not e.g. ‘test(1)’ or ‘test(2)’ or whatever.
Hi, Cheers, yes it does look like it’s doing something like that, was just a bit of an unexpected result to me!
I just ran across this post while searching for something else.
What you’re seeing in the first example is that you’re referencing the loop variable i from your anonymous function. Once the function is executed (*after* termination of the loop), the value is 10. So whenever the event listener is triggered, it gets the value of i existing at that time, and passes it to test().
Java or other strongly-typed language would complain about referencing a local variable in an anonymous context.
[...] das Objekt zu schauen der den Event ausgelöst hat, gelang nicht auf den ersten Blick. Bis ich folgende Lösung im Netz gefunden habe, es lohnt sich sehr oft eine Nacht über dem Problem schalfen zu gehen. for (var [...]