0

I have been playing around with the Google Maps Javascript API v3 and trying to get it to display icons based on a multidimensional array.

Everything is fine until I try and define the icon relative to 'i' from the for loop, I think I'm making a simple mistake.

The code below displays gives the error: Uncaught TypeError: Cannot read property '2' of undefined

function initialize() {
    var map;
    var myOptions = {
        zoom: 14,
        center: new google.maps.LatLng(53.382971,-1.4702737),
        mapTypeId: 'roadmap',
        panControl: false,
        streetViewControl: false,
        mapTypeControl: false,
        zoomControl: false
    };
    map = new google.maps.Map($('#map_canvas')[0], myOptions);

    var addresses = [
     ["S1 4EJ", "Available", "/img/green-marker.png"], 
     ["S1 4QW", "Available", "/img/green-marker.png"],
     ["S1 2HE", "Let Agreed", "/img/red-marker.png"]
    ];

    for (var i = 0; i < addresses.length; i++) {
        console.log(i);
        $.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+addresses[i][0]+'&sensor=false', null, function (data) {
            var p = data.results[0].geometry.location
            var latlng = new google.maps.LatLng(p.lat, p.lng);

            console.log(i);

            new google.maps.Marker({
                position: latlng,
                map: map,
                icon: {
                        url: addresses[i][2],
                        size: new google.maps.Size(50, 50),
                        origin: new google.maps.Point(0,0),
                        anchor: new google.maps.Point(25, 50)
                      }
            });

        });
    }

}; 
google.maps.event.addDomListener(window, "load", initialize);

The second console.log(addresses[i][2]); inside the $.getJSON success function all outputs as '3'.

Moving the addresses[i][2] outside of the $.getJSON function but still inside the for loop outputs them all as the last called iteration of 'i', for example:

...
for (var i = 0; i < addresses.length; i++) {
        console.log(i);

        var image = addresses[i][2];

        $.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+addresses[i][0]+'&sensor=false', null, function (data) {
            var p = data.results[0].geometry.location
            var latlng = new google.maps.LatLng(p.lat, p.lng);

            console.log(i);

            new google.maps.Marker({
                position: latlng,
                map: map,
                icon: {
                        url: image,
                        size: new google.maps.Size(50, 50),
                        origin: new google.maps.Point(0,0),
                        anchor: new google.maps.Point(25, 50)
                      }
            });

        });
    }
...

Am I going about this the wrong way?

frontuk
  • 3
  • 3
  • 1
    `$.ajax` (or `$.getJSON`, etc.) are asynchronous functions. This means your for loop most probably will be completed before you get a return from any of the ajax calls. – MrUpsidown Apr 02 '15 at 12:12

1 Answers1

0

Use function closure to keep the association of i in your loop with the marker created. Similar to how this question: Google Maps JS API v3 - Simple Multiple Marker Example does it for the infowindow content.

for (var i = 0; i < addresses.length; i++) {
    console.log(i);

    var image = addresses[i][2];

    $.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address=' + addresses[i][0] + '&sensor=false', null, (function (i, image) {
        return function (data) {
            var p = data.results[0].geometry.location;
            var latlng = new google.maps.LatLng(p.lat, p.lng);

            console.log(i);

            new google.maps.Marker({
                position: latlng,
                map: map,
                icon: {
                    url: image,
                    size: new google.maps.Size(50, 50),
                    origin: new google.maps.Point(0, 0),
                    anchor: new google.maps.Point(25, 50)
                }
            });

        }
    })(i, image));
}

working fiddle

code snippet:

function initialize() {
    var map;
    var myOptions = {
        zoom: 14,
        center: new google.maps.LatLng(53.382971, -1.4702737),
        mapTypeId: 'roadmap',
        panControl: false,
        streetViewControl: false,
        mapTypeControl: false,
        zoomControl: false
    };
    map = new google.maps.Map($('#map_canvas')[0], myOptions);

    var addresses = [
        ["S1 4EJ", "Available", "http://maps.google.com/mapfiles/ms/icons/green.png"],
        ["S1 4QW", "Available", "http://maps.google.com/mapfiles/ms/icons/green.png"],
        ["S1 2HE", "Let Agreed", "http://maps.google.com/mapfiles/ms/icons/blue.png"]
    ];

    for (var i = 0; i < addresses.length; i++) {
        console.log(i);

        var image = addresses[i][2];

        $.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address=' + addresses[i][0] + '&sensor=false', null, (function (i, image) {
            return function (data) {
                var p = data.results[0].geometry.location;
                var latlng = new google.maps.LatLng(p.lat, p.lng);

                console.log(i);

                new google.maps.Marker({
                    position: latlng,
                    map: map,
                    icon: {
                        url: image,
                        size: new google.maps.Size(50, 50),
                        origin: new google.maps.Point(0, 0),
                        anchor: new google.maps.Point(25, 50)
                    }
                });

            }
        })(i, image));
    }

}
google.maps.event.addDomListener(window, "load", initialize);
html, body, #map_canvas {
    height: 100%;
    width: 100%;
    margin: 0px;
    padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas" style="border: 2px solid #3872ac;"></div>
Community
  • 1
  • 1
geocodezip
  • 158,664
  • 13
  • 220
  • 245