Search code examples
javascriptjquerygoogle-mapsdynamic-data

Initialize a dynamically added Google Map


I've written a form which includes a Google Map and uses 'places autocomplete'. On the same page I have a button to add another location, so I'm adding another map-canvas div and trying to initialize another copy of the map.

I've modified the Google Map javascript as follows to be able to pass a variable to the function to attach to a different element:

<script>
function initialize(mapid) {
  var mapOptions = {
    center: new google.maps.LatLng(51.5112139, -0.1198244),
    zoom: 9,
    disableDefaultUI: true,
    mapTypeControl: false,
    scaleControl: true,
    zoomControl: true,
    zoomControlOptions: {
      style: google.maps.ZoomControlStyle.SMALL 
    },
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  var map = new google.maps.Map(document.getElementById('map-canvas' + mapid),
    mapOptions);

  var input = (document.getElementById('input' + mapid));
  var autocomplete = new google.maps.places.Autocomplete(input);
  autocomplete.bindTo('bounds', map);
  var infowindow = new google.maps.InfoWindow();
  var marker = new google.maps.Marker({
    map: map
  });
  google.maps.event.addListener(autocomplete, 'place_changed', function() {
    infowindow.close();
    marker.setVisible(false);
    var place = autocomplete.getPlace();
    if (!place.geometry) {
      return;
    }
    if (place.geometry.viewport) {
      map.fitBounds(place.geometry.viewport);
    } else {
      map.setCenter(place.geometry.location);
      map.setZoom(17); 
    }
    marker.setIcon(({
      url: place.icon,
      size: new google.maps.Size(71, 71),
      origin: new google.maps.Point(0, 0),
      anchor: new google.maps.Point(17, 34),
      scaledSize: new google.maps.Size(35, 35)
    }));
    marker.setPosition(place.geometry.location);
    marker.setVisible(true);
    var address = '';
    if (place.address_components) {
      address = [
        (place.address_components[0] && place.address_components[0].short_name || ''),
        (place.address_components[1] && place.address_components[1].short_name || ''),
        (place.address_components[2] && place.address_components[2].short_name || '')
      ].join(' ');
    }
    infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
    infowindow.open(map, marker);
  });
}

//google.maps.event.addDomListener(window, 'load', initialize);
$( document ).ready(function() {
    initialize(1);
});
</script>

Note that I commented out the standard Google way of initialising the map and replaced it with a JQuery method as the Google way didn't like the parameter.

The above works on loading the page for the first map, but when I try to add a second using the following on('click'), the call to initialize breaks the script.

$(function() {
    var mapdiv = $('.parentclass');
    var m = $('.parentclass div.well').size() + 1;
    $('#addMap').on('click', function() {
        $('<div class="well"><div id="map-canvas'+m+'" class="map-canvas"></div></div>').appendTo(mapdiv).hide().fadeIn('60');
        initialize(m);
        m++;
        return false;
    });
});;

If I comment out the initialize(m) call, it creates the empty well, so I know it's something that call is doing to break it. I've confirmed that the m variable, which counts the number of .well divs already there is correctly calculating the right number. So why, when loading the document does initialize(1) work, but on the 'on('Click')` function, it breaks there?


Solution

  • In this case it was a lack of an input field for the newly created map to bind the autocomplete to, but thanks to twil for suggesting the jsfiddle which allowed me to spot the problem a lot easier than starring at the mess of code I'd been playing with locally.