Google Maps Api v3 Location Search with jQuery Autocomplete Plugin

When I needed Google Maps style auto complete in my application, I looked into a lot of JavaScript libraries but I couldn’t find a useful solution. Since I’m new to JQuery, at first I couldn’t realize how it simple all this was.
With JQuery auto complete plug-in we can pull data from local or remote sources. In this example , I used google.maps.Geocoder as the remote data source.

For those who are not familiar with the term, geocoding is the process of converting addresses like ("1600 Amphitheatre Parkway, Mountain View, CA”) into geographic coordinates (latitude and longitude values).

There are two different geocode requests in this example:

1. I used first geocoding request to convert user address into latitude and longitude values,
2. The second request is the Reverse Geocoding, to convert search results into human readable format.
Reverse Geocoding often returns more than one result. I think it is best to fetch all these results and serve all of them to the user instead of showing only one result.

After getting search results for a given keyword, the map’s viewport is adjusted to the selected search result using map.fitBounds(bounds).

Let’s examine the script;

First initialize the map with basic options;


var mapOptions = {
  zoom : 10,
  mapTypeId: google.maps.MapTypeId.ROADMAP,
  center: new google.maps.LatLng(41.06000,28.98700)
};

var map = new google.maps.Map(document.getElementById("map"),mapOptions);


Then create a google Geocoder object;
var geocoder = new google.maps.Geocoder();

Bind the auto complete event to the search input box,
$(function() { $("#searchbox").autocomplete({ source: function(request, response) {
In source event I created a callback function that process the geocoder results;

geocoder.geocode( {'address': request.term }, function(results, status) { if (status == google.maps.GeocoderStatus.OK) {


My first geocoder request takes address as a paramete, and the callback functions processes the returning result object if geocoder status is OK. Then using the returning location which usually has one string, I prepare a Google Maps LatLng object to get a list of search results with reverse geocoding;

var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
var latlng = new google.maps.LatLng(lat, lng);



This is the second and the last request to google geocoder with latlng;

geocoder.geocode({'latLng': latlng}, function(results1, status1) {

This request also have a callback function that generates label, value and bounds

if (status1 == google.maps.GeocoderStatus.OK) {
if (results1[1]) {
             response($.map(results1, function(loc) {
        return {
         label: loc.formatted_address,
         value: loc.formatted_address,
         bounds: loc.geometry.bounds
}
               }));
          }
    }
 });

Finally, when the user selects an option from search results, to navigate the map to that place, I wrote the following code in the auto complete select event;

select: function(event,ui){
var bounds = ui.item.bounds;
  map.fitBounds(bounds);
 } 

Here is the full demonstration of my auto complete example;

<!DOCTYPE PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script> 
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script> 
  <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
  <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>  
 </head>
 <body>
  <h1>Google Maps Autocomplete Search Sample</h1>
  <div align="left">
   <input type="text" value="" id="searchbox" style=" width:800px;height:30px; font-size:15px;">
  </div>
  <div align="left" id="map" style="width:800px; height: 600px; margin-top: 10px;">
   
  </div>
  
 </body>
</html>
<script type="text/javascript">
 $(document).ready(function(){

  var mapOptions = {
       zoom: 10,
       mapTypeId: google.maps.MapTypeId.ROADMAP,
       center: new google.maps.LatLng(41.06000,28.98700)
     };

  var map = new google.maps.Map(document.getElementById("map"),mapOptions);

  var geocoder = new google.maps.Geocoder();  

     $(function() {
         $("#searchbox").autocomplete({
          
           source: function(request, response) {

          if (geocoder == null){
           geocoder = new google.maps.Geocoder();
          } 
             geocoder.geocode( {'address': request.term }, function(results, status) {
               if (status == google.maps.GeocoderStatus.OK) {

                  var searchLoc = results[0].geometry.location;
               var lat = results[0].geometry.location.lat();
                  var lng = results[0].geometry.location.lng();
                  var latlng = new google.maps.LatLng(lat, lng);
                  var bounds = results[0].geometry.bounds;

                  geocoder.geocode({'latLng': latlng}, function(results1, status1) {
                      if (status1 == google.maps.GeocoderStatus.OK) {
                        if (results1[1]) {
                         response($.map(results1, function(loc) {
                        return {
                            label  : loc.formatted_address,
                            value  : loc.formatted_address,
                            bounds   : loc.geometry.bounds
                          }
                        }));
                        }
                      }
                    });
            }
              });
           },
           select: function(event,ui){
      var pos = ui.item.position;
      var lct = ui.item.locType;
      var bounds = ui.item.bounds;

      if (bounds){
       map.fitBounds(bounds);
      }
           }
         });
     });   
 });
</script>




Aziz Ünsal


Comments

Anonymous said…
First of all, great work! I wish there was a jQuery plugin to do this.

I am not sure if this code is working 100% Ok yet. I have my Lat, Long set to point to CN Tower and I have my zoom set to 14 as default, With this setup if I go and type an address from Toronto (with in that map region) it is picking things from California, some cases from Iran :)

What do you think I need to change to make it work with in the displayed map. Your help/work is much appreciated.

Thanks.

Nikke (thenike@hotmail.com).
Anonymous said…
570Awesome work... it works 4 me,
Thank you 4 sharing this

Popular posts from this blog

Monitoring Oracle Database with Zabbix

Powerful Free Webinar Network for Oracle Developers