You need to generate an anonymous function during the current iteration, the following should fix it:
// note these are actual addresses in the real page
var addresses = new Array( "addr 1", "addr 2", "addr 3", "addr 4" );
for (var i = 0; i < addresses.length; i++) {
geocoder.getLatLng(addresses[i], function (current) {
return function(point) {
if (point) {
var marker = new GMarker(point);
map.addOverlay(marker);
map.setCenter(point, 13);
GEvent.addListener(marker, "click", function() {
// here, i=4
marker.openInfoWindowHtml("Address: <b>" + addresses[current] + "</b>");
});
}
}
}(i));
}
B// note these are actual addresses in the real page
var addresses = new Array( "addr 1", "addr 2", "addr 3", "addr 4" );
for (var i = 0; i < addresses.length; i++) {
geocoder.getLatLng(addresses[i], function(point) {
if (point) {
var marker = new GMarker(point);
map.addOverlay(marker);
map.setCenter(point, 13);
GEvent.addListener(marker, "click", function() {
// here, i=4
marker.openInfoWindowHtml("Address: <b>" + addresses[i] + "</b>");
});
}
});
}
Further Clarification
The getLatLng
method provided by Google uses an ajax call to get the lat and long for a specific address. Since this is an asynchronous call and is not part of the current thread, a callback function is required which is called on completion of the ajax request. This is the anonymous function you specify as the second parameter of the function.
Now, whilst the ajax requests are being made, your code continues to run, increasing the value of i
each time the loop iterates over the array. By the time your first ajax call returns, the loop has already increased to the length of the addresses array (4), so when the your callback function runs you're retrieving the in-scope variable i
after it has been increased by the loop.
With the fix I wrote, you're creating an anonymous function that takes a single argument - current
- and returns the previous anonymous function with the i
variable replaced with the current
variable. This function is invoked right away, before the next iteration of the loop, with the i
variable as it's first parameter. This creates a closure for which the current value of i
is stored in the current
variable at the time the function is called. When we refer to the current
variable later, we're getting the stored value of i
.
I'm not really very good at explaining these sort of things, probably because my understanding of it isn't quite as good as the js Gods. Better to read some more info on javascript closures.