0

I am using Bing Maps to implement putting multiple pins on a map. Whenever a pin is pressed I have an infobox popup and within the info box i have an edit button. When the edit button is pressed i want it to display the title associated for the pin (testing purposes). However, whenever I add a handler in my for loop for each pin only the last handler is used... For example if I add three pins with the titles: [hello, foo, bar], bar is displayed no matter what pin I click on... Here is what I am doing:

for ( var pos = 0; pos < locationsSize; pos++) {

            var locationFromIndex = locations[pos];
            var bingLocation = new Microsoft.Maps.Location(
                    locationFromIndex.latitude, locationFromIndex.longitude);

            // Create/add the pin
            var pin = new Microsoft.Maps.Pushpin(bingLocation, {
                width : 25,
                height : 39,
                anchor : mAnchor
            });
            pins.push(pin);

            // Create/add the pin info box
            var pinInfobox = new Microsoft.Maps.Infobox(pin.getLocation(), {
                title : locationFromIndex.type,
                visible : false,
                height : 75,
                zIndex : i,
                width : 150,
                offset : mOffset,
            })
            pinInfobox.setOptions({
                actions : [ {
                    label : "Edit",
                    eventHandler : function(mouseEvent) {
                        alert(pinInfobox.getTitle()); // Only the last eventHandler added is being used...
                    }
                } ]
            });
            map.entities.push(pinInfobox);
        }
1

2 Answers 2

1

The simplest solution to your problem is a closure:

for ( var pos = 0; pos < locationsSize; pos++) {
  (function(locationFromIndex) {
        var bingLocation = new Microsoft.Maps.Location(
                locationFromIndex.latitude, locationFromIndex.longitude);

        // Create/add the pin
        var pin = new Microsoft.Maps.Pushpin(bingLocation, {
            width : 25,
            height : 39,
            anchor : mAnchor
        });
        pins.push(pin);

        // Create/add the pin info box
        var pinInfobox = new Microsoft.Maps.Infobox(pin.getLocation(), {
            title : locationFromIndex.type,
            visible : false,
            height : 75,
            zIndex : i,
            width : 150,
            offset : mOffset,
        })
        pinInfobox.setOptions({
            actions : [ {
                label : "Edit",
                eventHandler : function(mouseEvent) {
                    alert(inInfobox.getTitle()); // Only the last eventHandler added is being used...
                }
            } ]
        });
        map.entities.push(pinInfobox);
    }
 })(locations[pos]);

The closure closes over its containing scope, but will have a specific reference to your locations[pos] in each call to it. This allows you to not have the loop issue.

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

8 Comments

This creates unnecessary functions (objective) and is hard to read (subjective). Still, the objective issue is unlikely to cause anyone any real trouble...
"The simplest solution to your problem is a closure" The OP's function is already a closure. That's why he/she is having trouble in the first palce.
@T.J.Crowder: All I did was to provide a way to scope pin in order for his/her events to actually bind to the correct pin instead of always referencing the last one. Also, the OP's declaration of pin is NOT in one.
@T.J.Crowder: Finally, while I am open to criticism, all I have done is to fix the problem. Refactoring his/her code is none of my business - I merely provided a reason for the problem she has (pin is hoisted) and a solution.
@unknown MDN has a good explanation on the issue.
|
1
pinInfobox.setOptions({
    actions: [{
        label: "Edit",
        eventHandler: (function (infoBox) {
            return (function (mouseEvent) {
                alert(infoBox.getTitle());
            })
        })(pinInfobox)
    }]
});

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.