Google Maps v3 Multiple Markers and Infowindows in a Loop

My lack of javascript knowledge is really becoming a pain in the ass. I was trying to add multiple markers and infowindows via Google Maps v3 API, and whichever marker I clicked on, it would always open the infowindow of the last marker. Here is the code I was using: //photoMarkers is a JavaScript array of objects that PHP spits out to the page, and the script below is from an external javascript file and is contained within a function for (var i = 0; i < photoMarkers.length; i++) { var p = photoMarkers[i]; var marker = new google.maps.Marker({position: new google.maps.LatLng(p.latitude, p.longitude), title: p.alt, map: map, draggable: true}); var infowindow = new google.maps.InfoWindow({content: p.content}); google.maps.event.addListener(marker, 'click', function() { infowindow.open(map, marker); }); } I was baffled as to why this didn't work. I am creating new variables on every loop and then passing the marker to the infowindow via a closure. After some searching, I found a solution which worked. But it still didn't explain why this wasn't working. Surely the Google code must be doing something strange in the addListener function, making my life difficult? Some more searching resulted inthis article, explaining why you can't have closures in loops. The closure is using the scope of the function it was created in and not the loop.Therefore each closure is "sharing" the variables, and when the closure is executed, it has a reference to the last marker and infowindow. Shows how little I know about JavaScript. Another way of dealing with this is to return an anonymous function that acts as a closure from within another function. Now the closure, e.g. the inner function, takes the environment of the outer function on each loop, and it doesn't "share" the scope/environment with the other closures. E.g. function infoCallback(infowindow, marker) { return function() { infowindow.open(map, marker); }; } for (var i = 0; i < photoMarkers.length; i++) { var p = photoMarkers[i]; var marker = new google.maps.Marker({position: new google.maps.LatLng(p.latitude, p.longitude), title: p.alt, map: map, draggable: true}); var infowindow = new google.maps.InfoWindow({content: p.content}); google.maps.event.addListener(marker, 'click', infoCallback(infowindow, marker)); }

Posted In: JavaScript

Commentary

[...] RobertBolton.com » Google Maps v3 Multiple Markers and Infowindows in a Loop [...]

Paul Synnott 2010-09-26 22:10:41

Hey Robert, Many thanks for this! This was doing my head in for about an hour before I came across this post. Only problem I'm having now is when I click on another marker when an infowindow is still open, I get two infowindows displaying on the map. I'm pretty sure it's a simple fix though.

Anonymous 2010-10-28 13:31:11

Thank you mate!, "My lack of javascript knowledge is really becoming a pain in the ass." lol, I feel the same way about my knowledge of javascript.

Anonymous 2011-05-11 17:10:09

@Paul If this still matters (I doubt it), just make just to do infowindow.close() whenever you open one :)

Juan Carlos Rodriguez Cruz 2011-05-24 21:05:33

Thank you mate! I was losing control... You have saved my job!! =D

Hiren Prajapati 2011-07-19 12:35:43

Hey Robert, Thanks for providing this info. But still i am unable to apply this concept. Its been really very long time i am trying this. but i cant get out of this. Please check below are my code. and i always get the last loop value in the bubble. can you please look at it. for(var h = 0; h < (ptDt1.length)-1; h ) { ptDt2 = ptDt1[h].split(","); points[h] = new GLatLng(parseFloat(ptDt2[0]),parseFloat(ptDt2[1])); // New code starts here inc_counter[h] = ptDt2[2]; currenttime[h] = ptDt2[3]; address[h] = ptDt2[4]; } //alert(points); //map.clearOverlays(); var poly= new GPolyline(points, "#110581", 2, 1); map.addOverlay(poly); var length = points.length; //alert(inc_counter); //var tot = points.split() for (var i = 0; i< length; i ) { if(inc_counter[i]==0) { marker = new GMarker(points[i]); map.addOverlay(marker); // Ends here.. html5[i] ="" " Location: " address[i] "" "Time:

Pat 2011-10-25 17:15:16

Thank you very much for sharing this code. It was the solution I was looking for.

Sudeep Talati 2011-10-26 12:31:57

You are Star How Could we make it to close existing window if i click other

Anonymous 2011-11-20 10:47:09

Thanks for sharing!