0

I am trying to make a website that need a google map on it with some markers I have a problem with reading a javascript 2D array multiple time it gives me error

Cannot read property '0' of undefined

and here its my code

function initialize() {
          var locations = [
          //'City',LatLng,LatLng,Zoom
          ['Egypt', 26.820553, 30.802498, 6], //Center of whole map
          ['Alexandria', 'Egypt'], //pointer
          ['Mansoura', 'Egypt'], //pointer
          ['Assiut', 'Egypt'] //pointer
          ];

          var mapOptions = {
              zoom: locations[0][3],
              center: new google.maps.LatLng(locations[0][1], locations[0][2]),
              mapTypeId: google.maps.MapTypeId.ROADMAP
          };

          var map = new google.maps.Map(document.getElementById('map_canvas'),
          mapOptions);

          var infowindow = new google.maps.InfoWindow();

          var marker, i;
          var geocoder = new google.maps.Geocoder();
          var image = 'flag.png';

          for (i = 1; i < locations.length; i++) {
              geocoder.geocode({ 'address': locations[i][0] + ' ' + locations[i][1] }, function (results, status) {
                  if (status == google.maps.GeocoderStatus.OK) {

                      marker = new google.maps.Marker({
                          animation: google.maps.Animation.DROP,
                          map: map,
                          icon: image,
                          position: results[0].geometry.location,
                          title: locations[i][0]
                      });

                      google.maps.event.addListener(marker, 'click', (function (marker, i) {
                          return function () {
                              infowindow.setContent('<b style="font-size:30px;">' + locations[i][0] + '</b>'
                                  + '<br><b>Starting Date:</b> 11/5/2012'
                                  + '<br><b>Ending Date:</b> 30/5/2012'
                                  + '<br><a href="google.com">Event Website</a>');
                              infowindow.open(map, marker);
                          }
                      })(marker, i));
                  }
              });
          }
      }

      function loadScript() {
          var script = document.createElement('script');
          script.type = 'text/javascript';
          script.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyA6yYH66F1L3NgHAobufuUF6l-jjVCLwfE&sensor=false&' +
          'callback=initialize';
          document.body.appendChild(script);
      }

      window.onload = loadScript;

I got the error in this section when I am trying to read locations[i][0] many times.

for (i = 1; i < locations.length; i++) {
              geocoder.geocode({ 'address': locations[i][0] + ' ' + locations[i][1] }, function (results, status) {
                  if (status == google.maps.GeocoderStatus.OK) {

                      marker = new google.maps.Marker({
                          animation: google.maps.Animation.DROP,
                          map: map,
                          icon: image,
                          position: results[0].geometry.location,
                          title: locations[i][0]
                      });

                      google.maps.event.addListener(marker, 'click', (function (marker, i) {
                          return function () {
                              infowindow.setContent('<b style="font-size:30px;">' + locations[i][0] + '</b>'
                                  + '<br><b>Starting Date:</b> 11/5/2012'
                                  + '<br><b>Ending Date:</b> 30/5/2012'
                                  + '<br><a href="google.com">Event Website</a>');
                              infowindow.open(map, marker);
                          }
                      })(marker, i));
                  }
              });
          }

and if there is anyway that I can handle this code in c# code behind it will be nice

3
  • Don't you mean for (i = 0; i < locations.length; i++)? Starting the iterator at 1 means the last iteration will exceed the length of the array. Commented Nov 25, 2012 at 13:29
  • I mean when I'm trying to read locations[i][0] many times it gives error. and I want loop start from 1 because 0 is the center of my map Commented Nov 25, 2012 at 13:35
  • OK, yeah to be honest that wouldn't cause an error. If the error occurs at locations[i][0] and says "Cannot read property '0' of undefined", it simply means there is no object at position i in the locations array. What is the value of i when the error is thrown? Put a breakpoint on that line in your debugger (Firebug / Chrome dev tools etc). Commented Nov 25, 2012 at 13:49

1 Answer 1

3

[ignore previous comment about results]

The problem is that you're referencing i in the geocode() callback. The geocode() method is asynchronous - i.e. your callback is called after the for-loop has already finished. And at that time, i = 4, meaning locations[i] is undefined.

You should read up on how closures work if that doesn't make sense, but basically the solution is to put the code inside your for-loop into a separate function and pass it the location entry you want to work with, like so:

function geocodeLocation(location) {
  geocoder.geocode({ 'address': location[0] + ' ' + location[1] },
    function (results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        marker = new google.maps.Marker({
          animation: google.maps.Animation.DROP,
          map: map,
          icon: image,
          position: results[0].geometry.location,
          title: location[0]
        });

        google.maps.event.addListener(marker, 'click', (function (marker, i) {
          return function () {
            infowindow.setContent('<b style="font-size:30px;">' + location[0] + '</b>'
              + '<br><b>Starting Date:</b> 11/5/2012'
              + '<br><b>Ending Date:</b> 30/5/2012'
              + '<br><a href="google.com">Event Website</a>');
            infowindow.open(map, marker);
          }
        })(marker, i));
      }
    }
  );
}


for (var i = 1; i < locations.length; i++) {
  geocodeLocation(locations[i]);
}
Sign up to request clarification or add additional context in comments.

5 Comments

updated answer - I was incorrect in thinking it was results. Tested your code and figured out the problem is as noted above.
classic closure in for loop problem
Yes, broofa, you beat me to it, asynch callback of the function causes the variable i to be the lenght of locations when the geocoder.geocode calls the callback.
I though all my code under for-loop. gj your code looks clear :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.