0

This is undoubtedly due to my ignorance of JavaScript. I have two equisized arrays of objects and I loop through both of them simultaneously adding an action handler so that when the n:th object in the first array is hovered over, some magic occurs to the n:th object in the second array.

That's my intention.

In reality, the computer "forgets" the previous assignments and only executes the last magic declared, independently of which of the invoking objects gets hovered over. I know what the problem is but I can't think of a good way to solve it. There might be an answer to this already (seems like a common gotcha to me) but since I, obviously, can't word the problem correctly I get nada.

The code is like this.

for (index in pushpins) {
  map.entities.push(pushpins[index]);
  map.entities.push(infoboxes[index]);

  Microsoft.Maps.Events.addHandler(pushpins[index], "mouseover", function (d) {
    infoboxes[index].setOptions({ visible: true });
  });

Please note that the problem most likely isn't specific to Microsoft.Maps but to the fact that JavaScript has a different scoping rules for variables. When I statically add a few instances and call them some1, some2 etc., I get the behavior intended. I believe it's index that somehow retains its value.

1
  • i don't now javascript, but maybe the function attached contains index in it's closure, so that all attached functions use infoboxes[index]? Commented Dec 27, 2013 at 14:36

2 Answers 2

2

The best solution here is move

Microsoft.Maps.Events.addHandler(pushpins[index], "mouseover", function (d) {
    infoboxes[index].setOptions({ visible: true });
  });

to the other function like:

function addEvent(element, i) {
   Microsoft.Maps.Events.addHandler(element[i], "mouseover", function (d) {
      element[i].setOptions({ visible: true });
   });
}

See: Javascript scope problem or What is the scope of variables in JavaScript?

Sign up to request clarification or add additional context in comments.

5 Comments

Just to be a bit nit-picky here. In my specific case the signature should be function addEvent(e1, e2, i) and not var (e1, i), right (since I'm bounding to the first element's event something happening to the second element)? The var in your example can be substituted for function, correct?
Yup, I've just fixed the typo. If you wanted to declare this function by var you can declare this like: var addEvent = function(...) {}; Also in my example pushpins reffers to the infoboxes. This is just simple expample.
It would be helpful to explain why this change solves the original problem.
@JameyHicks What are you referring to exactly? Did you note the comment #1 that I made explaining why my specific question needed three parameters to be passed? Perhaps you meant something totally different?
I was suggesting to @shpyo to describe why the suggested change solves the problem. There is a hint in user3125280's comment on the question.
1

index is not bound to each item. Your loop will attach a handler to each item, but they all refer to the same index which end up as n after your loop. Thus they all trigger with n indexes.

A common solution is to use an IIFE for each iteration which creates a local scope per iteration. That way, the handler will refer to that local index rather than the index outside the loop. Not optimal (JSHint screams "Don't create functions in loops"), but does the job.

for (index in pushpins) {
  (function(index){
    map.entities.push(pushpins[index]);
    map.entities.push(infoboxes[index]);

    Microsoft.Maps.Events.addHandler(pushpins[index], "mouseover", function (d) {
      infoboxes[index].setOptions({ visible: true });
    });
  }(index));
}

5 Comments

As I suspected - index is the villain here. How to kill it? Or, to use your nomenclature - how do I bind index to each thingy?
so index is bound to the index in it's static closure? (i don't speak javascript)
Dude... That's some scary syntax... It's Christmas, not Halloween, haha. Would it be less controversial to use the syntax provided in the answer by @shpyo?
@KonradViltersten It's not rocket science, just 2 lines of magic. :D And yes, shpyo's answer is better.
@JosephtheDreamer Hahaha - precisely. Just 2 lines of magic. And getting a golden medal in sprint is just about running faster than a single guy - the runner-up, right? :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.