'Javascript/Google Maps API - "TypeError: undefined is not an object (evaluating 'addresses[x][0]')

I am trying to plot markers on a google map using an array of addresses. The markers are correctly plotting (I used the tips in this post: Multiple markers Google Map API v3 from array of addresses and avoid OVER_QUERY_LIMIT while geocoding on pageLoad) but I am getting this error when I try to add information from the addresses array into the marker and infowindow: "TypeError: undefined is not an object (evaluating 'addresses[x][0]')"

The problem appears to be that within the 'for' loop, x evaluates to the length of the array, 4, every time I loop.

The markers and infowindows are working; they show up when I use a string or I use addresses[0], addresses[1], etc., but everything breaks when I try to do addresses[x] because addresses[4] does not exist. Any pointers at how I can iterate through my addresses array to properly set my marker titles and infowindows?

Note: in case it's relevant, there is a reason the addresses variable is declared inside the calcRoute() function.

This is the code:

var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;

function initialize() {
  directionsDisplay = new google.maps.DirectionsRenderer();
  var chicago = new google.maps.LatLng(41.850033, -87.6500523);
  geocoder = new google.maps.Geocoder(); 
  var mapOptions = {
    zoom:7,
    center: chicago
  };
  map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
  directionsDisplay.setMap(map);
}

function calcRoute() {
  var start = document.getElementById('start').value;
  var end = document.getElementById('end').value;
  var request = {
    origin:start,
    destination:end,
    travelMode: google.maps.TravelMode.DRIVING
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      directionsDisplay.setDirections(response);
      var addresses = [["Beaver Creek Smokehouse","4.5",["601 Main St","Martinez, CA 94553"]],["Lemongrass Bistro","4.5",["501 Main St","Martinez, CA 94553"]],["Picnicky's Sandwich Shop","4.0",["3833 Sonoma Blvd","Vallejo, CA 94590"]],["LV Vietnamese Pho and Sandwiches","4.0",["2621 Springs Rd","Vallejo, CA 94591"]]];
      var infowindow = new google.maps.InfoWindow();
      var marker, x;    

      //This is the problem area:
      for (x = 0; x < addresses.length; x++) {
        jQuery.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+addresses[x][2]+'&sensor=false', null, function (data) {
          console.log(x); // logs the length of array, 4, every time
          var p = data.results[0].geometry.location;
          var latlng = new google.maps.LatLng(p.lat, p.lng);

          marker = new google.maps.Marker({
            position: latlng,
            map: map,
            title: 'this works' // markers don't show when I use addresses[x][0]
          });
          google.maps.event.addListener(marker, 'click', (function(marker, x) {
            return function () {
            infowindow.setContent(addresses[x][0]);
            infowindow.open(map,marker);

            };
          })(marker, x));
        });
      }
    }
  });
}

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


Solution 1:[1]

The geocoder is asynchronous. Inside the callback function, x == addresses.length. You are using function closure to capture its value for the infowindow, you need to do the same for instantiating the marker.

//This is the problem area:
for (x = 0; x < addresses.length; x++) {
    jQuery.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+addresses[x][2]+'&sensor=false', null, function (data) {
        console.log(x); // logs the length of array, 4, every time
        var p = data.results[0].geometry.location;
        var latlng = new google.maps.LatLng(p.lat, p.lng);
        createMarker(latlng, x);
    });
}
function createMarker(latlng, x) {
    marker = new google.maps.Marker({
        position: latlng,
        map: map,
        title: addresses[x][0]
    });
    google.maps.event.addListener(marker, 'click', (function(marker, x) {
        return function () {
          infowindow.setContent(addresses[x][0]);
          infowindow.open(map,marker);

        };
    })(marker, x));
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 geocodezip