Hi,
I am currently learning Google Maps API V3.
I want to display an infowindow for each marker on a map and I have written two codes snippets doing the same thing, yet producing completely different results.
Version A: Successfully displays an infowindow for each marker.
I tried to do it another way but
Version B: Displays infowindow for only last marker in Array

Please, I spend the last 6 hours trying to understand what I did wrong. Can you help me please?


The is Version A

infowindow = new google.maps.InfoWindow({
		content: content
		});

    var lastIndex = myJSONobject.geolocation.length - 1;
    for(i=0;i<myJSONobject.geolocation.length;i++) { 
		if (i == lastIndex) {
			placeIcons(myJSONobject.geolocation[i]);
		} else {
			addMarker(myJSONobject.geolocation[i]);
		}
    }
	
    function addMarker(data) {
		var marker = new google.maps.Marker({
			position: new google.maps.LatLng(data.lat, data.lon),
			map: map,
			title: data.time_inserted
			});
		google.maps.event.addListener(marker, "click", function() {
			openInfoWindow(marker);
			});
    }

This is Version B and should do the same thing as above.
But it only displays an infowindow for the last marker.

var lastIndex = myJSONobject.geolocation.length - 1;
for(i=0;i<myJSONobject.geolocation.length;i++) { 
	
	if (i == lastIndex) {
		placeIcons(myJSONobject.geolocation[i]);
	} else {
		//addMarker(myJSONobject.geolocation[i]);
			
	var marker = new google.maps.Marker({
		position: new google.maps.LatLng(myJSONobject.geolocation[i].lat, myJSONobject.geolocation[i].lon),
		map: map,
		title: myJSONobject.geolocation[i].time_inserted
			});
		google.maps.event.addListener(marker, "click", function() {
			openInfoWindow(marker);
			});
	}
}

Evan..,

To understand what is going on here, you must first understand the tricky topic of closures.

In version A, each time it is called, function addMarker() forms a closure containing its own marker .

In version B, there is only one closure formed by the outer scope (also a function I assume). The inner "click" function picks up marker by reference to that single variable. At the time a click occurs, marker is the marker for the last item in the array - giving precisely the behaviour you describe.

The simplest solution is to use version A. Another possible solution is to form a separate closure for each iteration of the loop by calling an anonymous inner function that accepts marker as an argument and returns a function!. However, this solution is not particularly easy to understand.

google.maps.event.addListener(marker, "click", (function(m){
		return function() { openInfoWindow(m); };
	})(marker));

Although it is far from obvious, the nett effect is actually very similar to version A.

I would need to test my code to be 100% confident that it would work. It's very easy to make mistakes in this type of thing.

Airshow

Post Script: There's no shame in having struggled for 6 hours without success. I wrote javascript for over a decade before starting to learn how to exploit closures ... and I'm still learning.

Airshow

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.