Search code examples
javascriptjquerygoogle-mapsgoogle-maps-api-3google-geocoder

Google map (geocoder.geocode) breaks the markers list while using address instead of LatLng


Chaps, Please Have a look at my google map from. It works while I am using LatLng for showing the location. the problem is using Geocode to convert address to LatLng.

although the marker shows up for only the first address , the Infowindow wont get attached to it. Also after the first address is reached in the loop it breaks and no more location or addresses are being shown. It shows all the location with latLng but miss behaves when reaches addresses ( using geocode)

Link to the complete code is on : http://jsfiddle.net/6cs2uLrL/8/

  var clients_details;
  var infowindow =[];
  var content =[
                 'QLD marker','SA marker','WA marker','VIC marker','random marker'
                  ];
  var geocoder;
  var map;
  var clients_details =
       [
         {location:"-26.6719304,153.0889225,17z",address: null},
         {location:"-34.927883,138.610688,17",address: null},                                             
         {location: null ,address:"Perth, WA"},
         {location: null ,address:"Melbourne, VIC"},
         {location:"-39.927883,150.610688,17",address: null}
       ];



   /**
   *
   * Draw google map with markers
   */
  function initialize()
  {

    geocoder = new google.maps.Geocoder();
    // Sydney
    var defaultLatlng = new google.maps.LatLng(-34.397, 150.644);

    var mapOptions =
    {
      center: defaultLatlng ,
      //disableDefaultUI:true,
      mapTypeControl: false,
      zoomControl: true,
      zoomControlOptions: {
      style: google.maps.ZoomControlStyle.SMALL
      },
      zoom: 3
    };

    map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

    // Makes sure clients_details is populated
   if (clients_details != null)
      showMarkers(clients_details);
 } // initialize
 /**
  * Asigning info to the  markers on the map
  * @param {list} clients_details
  *
  */
 function showMarkers(clients_details)
 {

   var marker = [];
   for (var i = 0; i < clients_details.length; i++)
   {

       infowindow[i] = new google.maps.InfoWindow({ content: content[i] });           
       var client_location='';
       if (clients_details[i]['location'] !== null)
       {
       // Geting Lat and Lng from the database string
       LatLng = clients_details[i]['location'].split(',');
       // Making number from string
       Lat = Number (LatLng[0]);
       Lng = Number(LatLng[1]);
       client_location = new google.maps.LatLng (Lat,Lng);
       marker[i] = new google.maps.Marker({
         position: client_location,
         map: map,
         title:  'LatLng'
           });

       }
       else
       {

         client_address = clients_details[i]['address'];
         geocoder.geocode(
           { 'address': client_address},
           function(results, status)
           {
             debugger;
             if (status == google.maps.GeocoderStatus.OK)
             {
               client_location = results[0].geometry.location;
               marker[i] = new google.maps.Marker({
                 position: client_location,
                 map: map,
                 title: 'address' 
               });
             }
             else
               alert('Geocode was not successful for the following\n\
                      reason: ' + clients_details[i]['name']+'\n' + status);
           });
       }
       // Add 'click' event listener to the marker
       addListenerMarkerList(infowindow[i], map, marker[i]);
   }// for
 }// function

 /*
  * Adds a click listner to the marker object
  *
  *   */
 function addListenerMarkerList(infowindow, map, marker )
 {       
   google.maps.event.addListener(marker, 'click', function() {
     infowindow.open(map,marker);
      });
 }     

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

Solution

  • There are two problems with your code.

    First, at the end of the for loop you're calling addListenerMarkerList(infowindow[i], map, marker[i]);. However, if you're geocoding the location, marker[i] will only be created after the geocoder has returned (in your function(results, status) callback). To resolve this, you need to call addListenerMarkerList in the if branch as well as in the geocoding callback.

    Second, in your geocoding callback function(results, status), you're accessing the loop variable i. A for loop does, however, not create a new scope. That means that the value of i is not wrapped with your callback. When the callback is executed, the for loop will have finished and, hence, i will be equal to clients_details.length. The workaround is to use a function closure.

    Conceptually, the fixed code looks like this (JSFiddle).

    for (var i = 0; i < clients_details.length; i++) {
        ...
        if (clients_details[i]['location'] !== null) {
            ...
            marker[i] = new google.maps.Marker(...);
            addListenerMarkerList(infowindow[i], map, marker[i]);
        } else {
            ....
            geocoder.geocode(..., (function(i) {
                return function(results, status) {
                    ...
                    marker[i] = new google.maps.Marker(...);
                    addListenerMarkerList(infowindow[i], map, marker[i]);
                }
            })(i));
        }
    
        //addListenerMarkerList(infowindow[i], map, marker[i]); // Will not work
    }