Daniel Westman
Daniel Westman

Reputation: 43

Closure issue with Listener and Google Maps markers

I want to add a Listener event to each generated marker, so that when you click a marker you are redirected to the permalink url. With the code below the permalink value is the same for every marker(it get's the last value). I've read about closure problems and that seems to be what I'm having. I don't really get the examples I've looked at though.

Can somebody take a look at my code and point me in the right direction? Any help is greatly appreciated!

downloadUrl("http://localhost/map/generatexml.php", function(data) {
            var xml = parseXml(data);
            var markers = xml.documentElement.getElementsByTagName("marker");
            for (var i = 0; i < markers.length; i++) {
              var permalink = markers[i].getAttribute("permalink");
              var point = new google.maps.LatLng(
                  parseFloat(markers[i].getAttribute("lat")),
                  parseFloat(markers[i].getAttribute("lng")));
              var marker = new google.maps.Marker({map: map,position: point,icon: icon.icon,shadow: icon.shadow,title: name});
              google.maps.event.addListener(marker, 'click', function() {self.location.href = permalink;});
            }

Upvotes: 4

Views: 3286

Answers (3)

Durai Amuthan.H
Durai Amuthan.H

Reputation: 32280

We have to use closures to solve this problem

Use the below code snippet to add info window to marker

function AddInfoWidnow(marker,message)
{
     var infowindow = new google.maps.InfoWindow({ content: message });

     google.maps.event.addListener(marker, 'click', function() {

     infowindow.open(marker.get('map'), marker);

    }); 

}

To see a working sample refer here

Upvotes: 1

Bob
Bob

Reputation: 7961

JavaScript only has function scope, so when you're declaring var's in the middle of the for-loop you're in fact only declaring them once for the entire function. First thing you should do is bring all of the var declarations to the top to make some more sense of what's going on:

downloadUrl("http://localhost/map/generatexml.php", function(data) {
            var xml = parseXml(data);
            var markers = xml.documentElement.getElementsByTagName("marker");
            var i, permalink, point, marker;
            for (i = 0; i < markers.length; i++) {
              permalink = markers[i].getAttribute("permalink");
              point = new google.maps.LatLng(
                  parseFloat(markers[i].getAttribute("lat")),
                  parseFloat(markers[i].getAttribute("lng")));
              marker = new google.maps.Marker({map: map,position: point,icon: icon.icon,shadow: icon.shadow,title: name});
              google.maps.event.addListener(marker, 'click', function() {self.location.href = permalink;});
            }

Your click function will use the final value of permalink for every marker event since permalink gets replaced with a new value every time the for-loop loops.

Edit: So yeah, Pointy beat me to actually solving your problem. But there you have, at least, an explanation of the problem

Upvotes: 2

Pointy
Pointy

Reputation: 413737

Try this:

for (var i = 0; i < markers.length; ++i) {
  // ... like what you have already ...
  (function(permalink) {
    google.maps.event.addListener(marker, 'click', function() {self.location.href = permalink;});
  })(permalink);
}

By making a new lexical scope with a copy of the "permalink" value at each iteration, your handlers should work better.

Upvotes: 13

Related Questions