How do I return a longitude and latitude from Google Maps JavaScript geocoder?

manraj82 picture manraj82 · Mar 9, 2011 · Viewed 58.8k times · Source

When I use the code below its alerting a blank value? why is that?

HTML

<body onload="initialize()">
 <div id="map_canvas" style="width: 320px; height: 480px;"></div>
  <div>
    <input id="address" type="textbox" value="Sydney, NSW">
    <input type="button" value="Encode" onclick="display()">
  </div>
</body>

JavaScript

var geocoder;
var map;


  function initialize() {
    geocoder = new google.maps.Geocoder();
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {
      zoom: 8,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  }

  function codeAddress() {
    var address = document.getElementById("address").value;
    var loc=[];

    geocoder.geocode( { 'address': address}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        loc[0]=results[0].geometry.location.lat();
        loc[1]=results[0].geometry.location.lng();

      } else {
        alert("Geocode was not successful for the following reason: " + status);
      }
    });

    return loc;
  }

  function display(){
     var long_lat=codeAddress();
    alert(long_lat);
  }

Answer

Maxym picture Maxym · Mar 9, 2011

because your function codeAddress is executed, assigning empty array to loc, executing asynchronous request to google geocoder and returns loc, which is empty, because its real value is assigned when response from google comes. In other words, allert should be inside response handler:

var geocoder;
var map;


  function initialize() {
    geocoder = new google.maps.Geocoder();
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {
      zoom: 8,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  }

  function codeAddress() {
    var address = document.getElementById("address").value;
    var loc=[];

    // next line creates asynchronous request
    geocoder.geocode( { 'address': address}, function(results, status) {
      // and this is function which processes response
      if (status == google.maps.GeocoderStatus.OK) {
        loc[0]=results[0].geometry.location.lat();
        loc[1]=results[0].geometry.location.lng();

        alert( loc ); // the place where loc contains geocoded coordinates

      } else {
        alert("Geocode was not successful for the following reason: " + status);
      }
    });

    // pretty meaningless, because it always will be []
    // this line is executed right after creating AJAX request, but not after its response comes
    return loc;
  }

  function display(){
     codeAddress();
  }

this is how AJAX works... process results in callback handlers.


if you want to separate geocoding and 'dispalying' you can execute display function inside handler:

  function codeAddress() {
    var address = document.getElementById("address").value;

    geocoder.geocode( { 'address': address}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
        var loc=[]; // no need to define it in outer function now
        loc[0]=results[0].geometry.location.lat();
        loc[1]=results[0].geometry.location.lng();

        display( loc ); 

      } else {
        alert("Geocode was not successful for the following reason: " + status);
      }
    });

  }

  function display( long_lat ){
     alert(long_lat);
  }

html:

<input type="button" value="Encode" onclick="codeAddress()">


you can make it even more generic, if you will geocode not only to display. Then you can define callback as parameter to codeAddress function:

function codeAddress( callback ) {
...
 geocoder.geocode( { 'address': address}, function(results, status) {
   ...
   callback( loc ); // instead of dispaly( loc );
   ...
 }
...
}

codeAddress( display ); // to execute geocoding