Google Maps javascript API + HTML5 geolocation quirk

I'm having a rather strange issue with the Google Maps javascript API and HTML5 geolocation.

I have the following executed onload:

  var geocoder;
  var map;
  var latlng;
  function initialize() {
 if(navigator.geolocation){
  navigator.geolocation.getCurrentPosition(function(position){
   latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
  });
 }else{
  latlng = new google.maps.LatLng(geoip_latitude(),geoip_longitude());
 }

 geocoder = new google.maps.Geocoder();
 var myOptions = {
   zoom: 8,
   center: latlng,
   streetViewControl: false,
   mapTypeId: google.maps.MapTypeId.HYBRID 
 };
 map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
   google.maps.event.addListener(map, 'click', function(event) {
  placeMarker(event.latLng);
  var latLong = String(event.latLng).replace('(', '');
  latLong = latLong.replace(')', '');
  $('#latlng').attr('value', latLong);
   });

   function placeMarker(location) {
  if(undefined != initialize.marker){
   initialize.marker.setMap(null);
  }
  initialize.marker = new google.maps.Marker({
   position: location, 
   map: map
  });
  initialize.marker.setMap(map);
  map.setCenter(location);
 }
  }

Now, what this should do is if the browser supports geolocation, get the lat+long, create a map, and display the map centered on the lat+long.

It works just fine if I use the geoip_ functions (maxmind), but the geolocation has a strange issue:

If the code is run as is, the google maps display shows up as a gray box with no map and no controls.

If I add an alert(); immediately after

if(navigator.geolocation){
    navigator.geolocation.getCurrentPosition(function(position){
        latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
    });
}else{
    latlng = new google.maps.LatLng(geoip_latitude(),geoip_longitude());
}

the map displays just fine.

What's up with that?

Answers


The W3C Geolocation API is asynchronous; the success callback function you have (which sets the variable latlng) won't be called immediately -- the browser requires some time to actually do the geolocating; in fact, if the user takes some time to read the privacy prompt and decide whether or not to give permission, this process could take many seconds. In the meantime though, your map is loaded immediately.

You're probably finding that it works with an alert after it because the alert gives the browser some time to finish the geolocation process and call the callback before getting to the code that loads the map. (Just waiting a second or two isn't a good solution though: some users and browsers will take much longer than that before revealing location.)

To fix: call the function that creates the map (you'll want to encapsulate practically everything after the geolocation call) and call it both in the success callback for getCurrentPosition and in the geoip else branch. That way you'll only try to load the map after you're guaranteed that the latlng variable has been appropriately filled.


Need Your Help

Simple redirect_to show path is not working

ruby-on-rails ruby-on-rails-3 routing

I am trying to show a resource after it has been created.

Merging XML using SAX parser

java xml

I have looked at the discussion in the link below -