Wednesday, 18 September 2013

Why, when I add a bunch of event listeners in a loop, does every element trigger the last listener added?

Why, when I add a bunch of event listeners in a loop, does every element
trigger the last listener added?

On a page, I have an SVG map of the US and Canada, and an HTML list of
provinces and states. Hovering over any province, either its name in the
list OR its depiction on the map, should make Arkansas on both list AND
map turn a different color. All the names and paths have logical
IDs/classes on them already.
Here's a fiddle with my code. (It's a horrible procedural mess at the
moment, so please forgive me.)
jQuery's event functions don't work on SVG, and though I know there's a
jQuery plugin that supposedly helps, I thought this would be a good
opportunity to use a larger proportion of vanilla Javascript than I'm used
to.
The most relevant part of the code is the makeMapInteractive function on
lines 46 through 69 of the Javascript:
function makeMapInteractive(provinces) {
for(var province in provinces) { // Iterate over every state/province
code
var $HTMLtargets = $('ul.provinces li.' + province);
var $SVGtargets = $('path#{0}, g#{0} path'.format(province));
var $allTargets = $HTMLtargets.add($SVGtargets);
// I tried it first with $().each(); when that didn't work,
// I commented it out and tried without it. Neither one works.
/* $allTargets.each(function() {
this.addEventListener('mouseover', function(e) {
console.log(e);
$HTMLtargets.css('color', '#990000');
$SVGtargets.attr('fill', '#990000');
}, false)
}); */
for(var i = 0; i < $allTargets.length; i++) {
$allTargets.get(i).addEventListener('mouseover', function(e) {
$HTMLtargets.css('color', '#990000');
$SVGtargets.attr('fill', '#990000');
}, false);
}
}
}
What I'm trying to tell it to do is to add a mouseover listener to every
element, that triggers a change on all elements involved in that element's
province.
What actually happens is that hovering over anything on the whole page
triggers the very last event listener added, the one for Wyoming. It's
like when I change the $allTargets variable, it changes all the
previously-added listeners to the elements contained in its new value. But
I can't see how that's happening, since I'm applying the event listeners
to the DOM elements inside that variable, not the jQuery object itself.
Can someone explain exactly what is going on here? I know I'm using jQuery
a bit here, but I'd like the answer to use no more than I'm already using;
it's my vanilla Javascript skill that needs increasing.

No comments:

Post a Comment