Lee Theobald
Lee Theobald

Reputation: 8587

Google Maps Trouble: Closures & Passing By Reference

I'm having some Google Maps/Javascript problems. I think I know what the trouble is but just don't know a way round it.

An example of my problem is here. Whatever marker you click on, the second shows up. I'm obviously passing the wrong info into my event listener but I just can't seem to get the code right. Here's a cut down portion of the code:

First, here's a portion of my code:

if (GBrowserIsCompatible() && mapResults != null) {
  // Read in the JSON
  var mapDetailsArray = loadJSON();

  // Create a map
  var map = new google.maps.Map2(document.getElementById(elementId));
  map.setCenter(new google.maps.LatLng(mapDetailsArray[0].getLatitude(),
      mapDetailsArray[0].getLongitude()), 13);
  map.addControl(new google.maps.SmallMapControl());

  // Add the points and center
  var mgr = new google.maps.MarkerManager(map);
  var bounds = new google.maps.LatLngBounds();
  for ( var i = 0; i < mapDetailsArray.length; i++) {
    var mapDetails = mapDetailsArray[i];

    var point = new google.maps.LatLng(mapDetails.getLatitude(), mapDetails
        .getLongitude());
    bounds.extend(point);

    // Create our marker
    var marker = new google.maps.Marker(point);

    // What action do we use to show the hover
    var infoAction = "mouseover";

    marker.value = mapDetails;

    google.maps.Event.addListener(marker, infoAction, function() {
      alert(marker.value);
      map.openInfoWindowHtml(point, getResultInfoContent(marker.value));
    });

    mgr.addMarker(marker, 1);
  }
  mgr.refresh();
}

"marker.value" always ends up set as the last value of what mapDetails was. If anything, I'd expect it to be "undefined" as once the loop has finished, shouldn't that value be gone anyway? I've tried various different values (e.g. marker.value = i+1;) but it will still come up as the same value for both points.

Does anyone have any idea how I can pass the correct values into the event listener?

Upvotes: 5

Views: 4237

Answers (2)

Nael El Shawwa
Nael El Shawwa

Reputation: 348

The above answer is not very intuitive though - as Greg said.

When you add an event to an object, that object is passed down so you can access it by "this" within the closure. If you replaced "marker.value" with "this.value" your problem would have been resolved. If you need to pass down more stuff, you tie it to the object and pass it down:

marker.a = 1
marker.b = 2
marker.c = 3

Within the closure this.a will be 1 and so on..

Upvotes: 3

Greg
Greg

Reputation: 321678

Change this:

google.maps.Event.addListener(marker, infoAction, function() {
      alert(marker.value);
      map.openInfoWindowHtml(point, getResultInfoContent(marker.value));
    });

to this:

google.maps.Event.addListener(marker, infoAction, (function(marker, point, map) { return function() {
      alert(marker.value);
      map.openInfoWindowHtml(point, getResultInfoContent(marker.value));
    }})(marker, point, map));

This will create the closure you want.

Split out for clarity:

var f = function(marker, point, map)
{
    return function()
    {
        alert(marker.value);
        map.openInfoWindowHtml(point, getResultInfoContent(marker.value));
    }
}

google.maps.Event.addListener(marker, infoAction, f(marker, point, map));

Upvotes: 6

Related Questions