0
votes

I have this code to show multiple addresses on a google map.

The problem being is that when the page first loads the map shows blue sea and does not geocode the addresses, I would imagine it is using the lat long of 0,0.

When I reload the page, it finds the addresses and shows them on the map. If then I leave the page and come back to it, it also works, I would imagine, due to caching.

I really need to get this working and am totally stumped.

Any ideas?

function initialize() {

    var addresses = [ '60 Hednesford Road Cannock West Midlands WS11 1DJ','172 High Street Bloxwich West Midlands WS3 3LA',];

    var myOptions = {
        zoom: 10,
        center: new google.maps.LatLng(0, 0),
        mapTypeId: 'roadmap'
    }

    var map = new google.maps.Map($('#map')[0], myOptions);

    var markerBounds = new google.maps.LatLngBounds();

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

    function makeInfoWindowEvent(map, infowindow, marker) {
        google.maps.event.addListener(marker, 'click', function() {
            infowindow.open(map, marker);
        });
    }

    for (var x = 0; x < addresses.length; x++) {
        $.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+addresses[x]+'&sensor=false', null, function (data) {
            var icon = { 
                url: 'http://melbourne.cvsdevelopment.co.uk/wp-content/themes/cvs-main/assets/img/icon-map.png'
            };
            var p = data.results[0].geometry.location;
            var latlng = new google.maps.LatLng(p.lat, p.lng);
            var adress = data.results[0].formatted_address;
            var marker = new google.maps.Marker({
                position: latlng,
                map: map,
                icon: icon
            });
            markerBounds.extend(latlng);
            var infowindow = new google.maps.InfoWindow({
                content: adress
            });
            makeInfoWindowEvent(map, infowindow, marker);

        });
    }

    map.fitBounds(markerBounds);

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

3 Answers

3
votes

I don't have time to test if my statement is correct, but I believe the problem lies in $.getJSON making an asynchronous call to the Google API. Therefore this:

markerBounds.extend(latlng);

happens "long" after this:

map.fitBounds(markerBounds);

I hope it's understandable and that you can now make it work on your own. Look for jQuery promises.

If you need more help, let me know, I might provide it later.

2
votes

To fix your issue, call the map.fitBounds in the callback function to the asynchronous geocode operation.

Working code snippet:

function initialize() {

  var addresses = ['60 Hednesford Road Cannock West Midlands WS11 1DJ', '172 High Street Bloxwich West Midlands WS3 3LA', ];

  var myOptions = {
    zoom: 10,
    center: new google.maps.LatLng(0, 0),
    mapTypeId: 'roadmap'
  }

  var map = new google.maps.Map($('#map')[0], myOptions);

  var markerBounds = new google.maps.LatLngBounds();

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

  function makeInfoWindowEvent(map, infowindow, marker) {
    google.maps.event.addListener(marker, 'click', function() {
      infowindow.open(map, marker);
    });
  }

  for (var x = 0; x < addresses.length; x++) {
    $.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address=' + addresses[x] + '&sensor=false', null, function(data) {
      var icon = {
        url: 'http://melbourne.cvsdevelopment.co.uk/wp-content/themes/cvs-main/assets/img/icon-map.png'
      };
      var p = data.results[0].geometry.location;
      var latlng = new google.maps.LatLng(p.lat, p.lng);
      var adress = data.results[0].formatted_address;
      var marker = new google.maps.Marker({
        position: latlng,
        map: map,
        icon: icon
      });
      markerBounds.extend(latlng);
      var infowindow = new google.maps.InfoWindow({
        content: adress
      });
      makeInfoWindowEvent(map, infowindow, marker);
      map.fitBounds(markerBounds);
    });
  }
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map {
  height: 100%;
  width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3"></script>
<div id="map"></div>
1
votes

The $.getJSON function does an asynchronous call inside your for loop, which means that you'll have several different calls to Google Maps.

The best solution, IMHO, is to set the viewport via fitBounds() in the last loop iteration (which will, in most cases, run last, unless one of the requests lags). It's more efficient to change the viewport once, rather than in each call to Google maps, because users with slow internet connections may see the map going back and forth when you have a lot of geolocation requests.

So, your code could be changed to:

(...)

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

      // Set the viewport in the last call to Google Maps
      if (threadCounter == addresses.length - 1)
        map.fitBounds(markerBounds);

      threadCounter++;
    });
}

Edit: Code corrected as per the comments below