Google Maps API v3 Adds InfoWindow to Each Marker

NOTE. I am using the v3 Google Maps API.

I am trying to add an info window to every marker that I put on the map. I am currently doing this with the following code:

for (var i in tracks[racer_id].data.points) { values = tracks[racer_id].data.points[i]; point = new google.maps.LatLng(values.lat, values.lng); if (values.qst) { var marker = new google.maps.Marker({map: map, position: point, clickable: true}); tracks[racer_id].markers[i] = marker; var info = new google.maps.InfoWindow({ content: '<b>Speed:</b> ' + values.inst + ' knots' }); tracks[racer_id].info[i] = info; google.maps.event.addListener(marker, 'click', function() { info.open(map, marker); }); } track_coordinates.push(point); bd.extend(point); } 

The problem is that when I click on the marker, it just displays the info window for the last marker added. Also, to be clear, the info window appears next to the last marker, not the marker. I would suggest that my problem is in the addListener part, but I am not posting. Any ideas?

+44
javascript google-maps google-maps-api-3
Jul 01 '10 at 14:13
source share
11 answers

You have a very common closing problem in a for in loop:

The variables enclosed in the closure have the same common environment, so by the time the click callback is called from addListener loop will work, and the info variable will be pointed to the last object that is created by the last InfoWindow .

In this case, one of the simple ways to solve this problem would be to grow your Marker object using InfoWindow :

 var marker = new google.maps.Marker({map: map, position: point, clickable: true}); marker.info = new google.maps.InfoWindow({ content: '<b>Speed:</b> ' + values.inst + ' knots' }); google.maps.event.addListener(marker, 'click', function() { marker.info.open(map, marker); }); 

This can be a pretty tricky topic if you are not familiar with how closures work. You can view the following Mozilla article for a brief introduction:

Also keep in mind that the v3 API allows multiple InfoWindow on the map. If you intend to have only one InfoWindow visible at a time, you should instead use a single InfoWindow object and then open it and change its contents whenever the marker ( Source ) clicks.

+77
Jul 01 '10 at 3:17
source share

You can use this in the event:

 google.maps.event.addListener(marker, 'click', function() { // this = marker var marker_map = this.getMap(); this.info.open(marker_map); // this.info.open(marker_map, this); // Note: If you call open() without passing a marker, the InfoWindow will use the position specified upon construction through the InfoWindowOptions object literal. }); 
+33
May 18 '13 at 7:21
source share

Add_marker still has a problem with closing because it uses a marker variable outside the scope of google.maps.event.addListener.

Best implementation:

 function add_marker(racer_id, point, note) { var marker = new google.maps.Marker({map: map, position: point, clickable: true}); marker.note = note; google.maps.event.addListener(marker, 'click', function() { info_window.content = this.note; info_window.open(this.getMap(), this); }); return marker; } 

I also used the map from the marker, so you don’t need to pass the google map object, you probably want to use a map in which the marker belongs anyway.

+9
Jul 27 '12 at 9:47
source share
+4
Oct 28 '14 at 6:56
source share

Hello to all. I do not know if this is the best solution, but I decided that I would post it here in order to hope to help people in the future. Please comment if you see something that needs to be changed.

My for loops now:

 for (var i in tracks[racer_id].data.points) { values = tracks[racer_id].data.points[i]; point = new google.maps.LatLng(values.lat, values.lng); if (values.qst) { tracks[racer_id].markers[i] = add_marker(racer_id, point, '<b>Speed:</b> ' + values.inst + ' knots<br /><b>Invalid:</b> <input type="button" value="Yes" /> <input type="button" value="No" />'); } track_coordinates.push(point); bd.extend(point); } 

And add_marker is defined as:

 var info_window = new google.maps.InfoWindow({content: ''}); function add_marker(racer_id, point, note) { var marker = new google.maps.Marker({map: map, position: point, clickable: true}); marker.note = note; google.maps.event.addListener(marker, 'click', function() { info_window.content = marker.note; info_window.open(map, marker); }); return marker; } 

You can use info_window.close () to disable info_window at any time. Hope this helps someone.

+1
Jul 01 '10 at 17:49
source share

for the Earth plugin API, create a balloon outside of your loop and pass your function counter to get unique content for each label!

 function createBalloon(placemark, i, event) { var p = placemark; var j = i; google.earth.addEventListener(p, 'click', function (event) { // prevent the default balloon from popping up event.preventDefault(); var balloon = ge.createHtmlStringBalloon(''); balloon.setFeature(event.getTarget()); balloon.setContentString('iframePath#' + j); ge.setBalloon(balloon); }); } 
+1
Apr 05 '13 at
source share

In my case (using Javascript insidde Razor) This worked fine inside the Foreach loop

 google.maps.event.addListener(marker, 'click', function() { marker.info.open(map, this); }); 
+1
Jun 29 '17 at 2:50
source share

Try the following:

 for (var i in tracks[racer_id].data.points) { values = tracks[racer_id].data.points[i]; point = new google.maps.LatLng(values.lat, values.lng); if (values.qst) { var marker = new google.maps.Marker({map: map, position: point, clickable: true}); tracks[racer_id].markers[i] = marker; var info = new google.maps.InfoWindow({ content: '<b>Speed:</b> ' + values.inst + ' knots' }); tracks[racer_id].info[i] = info; google.maps.event.addListener(tracks[racer_id].markers[i], 'click', function() { tracks[racer_id].info[i].open(map, tracks[racer_id].markers[i]); }); } track_coordinates.push(point); bd.extend(point); } 
0
Jul 01 '10 at 14:24
source share

I had a very similar problem, but in ActionScript 3: Stack Over Flow: dynamic window of the Google Maps API API HTML content issue

I tried to extract unique information in htmlcontent tooltips from the database and found that I was getting information about the last token that I added in each token.

Assuming this is not a specific ActionScript issue, the JochenJung solution will not work. Take a look at the solution that I posted in my problem and see if you can apply it here. This seems like a serious issue with the map APIs.

0
Jul 01 '10 at 14:26
source share

The only way I could get this to work is to create an array in JavaScript. Elements of the array refer to different info windows (one information window is created for each marker on the map). Each element of the array contains unique text for the corresponding map marker. I defined a JavaScript event for each info window based on an array element. And when the event fires, I use the keyword "this" to refer to an array element, to refer to the corresponding value for display.

 var map = new google.maps.Map(document.getElementById('map-div'), mapOptions); zipcircle = []; for (var zip in zipmap) { var circleoptions = { strokeOpacity: 0.8, strokeWeight: 1, fillOpacity: 0.35, map: map, center: zipmap[zip].center, radius: 100 }; zipcircle[zipmap[zip].zipkey] = new google.maps.Circle(circleoptions); zipcircle[zipmap[zip].zipkey].infowindowtext = zipmap[zip].popuptext; zipcircle[zipmap[zip].zipkey].infowindow = new google.maps.InfoWindow(); google.maps.event.addListener(zipcircle[zipmap[zip].zipkey], 'click', function() { this.infowindow.setContent(this.infowindowtext); this.infowindow.open(map, this); }); } 
0
May 29 '14 at 21:44
source share

I had a similar problem. If all you need is some information displayed when you hover over the marker, instead of clicking on it, I found that setting a title on the marker was a good alternative to using the info window. Thus, whenever you hover over a marker, the title is displayed as an ALT tag. 'marker.setTitle (' Marker '+ id);' This eliminates the need to create a listener for the marker too

0
May 22 '15 at 12:26
source share



All Articles