views:

1054

answers:

3

Hi all,

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?

+2  A: 

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));
Greg
That did the trick. Cheers Greg. I had tried something like that earlier but minus the return function() { ... } wrapping the code.
Lee Theobald
I've experienced the same issue, and used the same fix. I really feel this is a bug in Javascript.
TokenMacGuy
I don't think it's a bug, it's just not very intuitive
Greg
+1  A: 

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..

Nael El Shawwa
A: 

My rep isn't high enough yet to mark the response as useful but it helped me out also. Thanks

Edwin