Can't pass event to addEventListener: closure issue

EML picture EML · Jan 3, 2012 · Viewed 19.6k times · Source

This one's driving me crazy... I have a loop which adds an event listener to an SVG object. The object is, for the sake of argument, a small circle, and I have to add mouseover and mouseout events for each of the 10 circles.

My first problem is the standard closure-scope thing - because all the listeners are added in the same loop, they all see the same invalid value of the loop variable. I can fix this, I think, but the second problem is that I have to pass 'event' to the listeners, and I can't find any way to fix both these issues simultaneously.

I've tried various versions of this:

for(month = 0; month < nMonths; month++) {
   ...
   shape.addEventListener(
     "mouseover", 
     (function(event, index) { popup_on(event, foo, index); })(event, month),
     false);
   group.appendChild(shape);
}

This particular version gives me 'event is not defined'. popup_on is the real handler, and must get event and the current value of month. Any idea how I should be doing this? Thanks.

Answer

Adam Rackis picture Adam Rackis · Jan 3, 2012

The event will be passed to your function automatically—just make it the first argument to the function you pass to addEventListener. Also, false is the default value for the capture parameter.

(function() {
    var i = month;
    shape.addEventListener("mouseover", function(e) { popup_on(e, foo, i); });
})();

Also, are you ok with foo being closed over in your event callback? If not, you could do the same thing with it

(function() {
    var i = month;
    var f = foo;
    shape.addEventListener("mouseover", function(e) { popup_on(e, f, i); });
})();

And if all these local variables are getting annoying, you can make them parameters to possibly make things a bit more tidy

(function(i, f) {
    shape.addEventListener("mouseover", function(e) { popup_on(e, f, i); });
})(month, foo);