Javascript – Multiple markers in Google Maps API v3 that link to different pages when clicked


I have a map with multiple markers, which I populate via an array. Each marker is clickable and should take the user to a different url per marker.

The problem is that all the markers, while displaying the correct title, all use the url of the last entry in the array.

Here is my code:

var myOptions = { zoom: 9, center: new google.maps.LatLng(40.81940575,-73.95647955), mapTypeId: google.maps.MapTypeId.TERRAIN }
var map = new google.maps.Map(document.getElementById("bigmap"), myOptions);
setMarkers(map, properties);

var properties = [
['106 Ft Washington Avenue',40.8388485,-73.9436015,'Mjg4'],
['213 Bennett Avenue',40.8574384,-73.9333426,'Mjkz'],
['50 Overlook Terrace',40.8543752,-73.9362542,'Mjky'],
['850 West 176 Street',40.8476012,-73.9417571,'OTM='],
['915 West End Avenue',40.8007478,-73.9692155,'Mjkx']];

function setMarkers(map, buildings) {
    var image = new google.maps.MarkerImage('map_marker.png', new google.maps.Size(19,32), new google.maps.Point(0,0), new google.maps.Point(10,32));
    var shadow = new google.maps.MarkerImage('map_marker_shadow.png', new google.maps.Size(28,32), new google.maps.Point(0,0), new google.maps.Point(10,32));
    var bounds = new google.maps.LatLngBounds;
    for (var i in buildings) {
        var myLatLng = new google.maps.LatLng(buildings[i][1], buildings[i][2]);
        var marker = new google.maps.Marker({ position: myLatLng, map: map, shadow: shadow, icon: image, title: buildings[i][0] });
        google.maps.event.addListener(marker, 'click', function() { window.location = ('detail?b=' + buildings[i][3]); });

Using this code, clicking any marker take the user to 'detail?b=Mjkx'

What am I doing wrong?

Best Solution

The problem is that your click handler is using the i variable from the outer function.

Executing a loop doesn't make a separate copy of the variable in each iteration, so your callback function is using the same value of i for all of the callbacks.

To fix it, write a separate function to generate the callback.

For example:

function buildClickHandler(i) {
    return function() { window.location = ('detail?b=' + buildings[i][3]); };

for(var i = 0; i < buildings.length; i++) {
    google.maps.event.addListener(marker, 'click', buildClickHandler(i));

(You'll need to define buildClickHandler inside setMarkers so it can use the buildings parameter)

By the way, when looping through an array, you shouldn't use a for in loop, because it will also iterate over any additional members on the array object.

Related Question