Gerger Blog

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 parameter, 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 ( @azizunsall )

  • Craig

    Hi this is great – we have been looking long and far for a solution like this – Please can i ask if we are able to use this code on our websites?

  • http://www.gerger.co Yalim K. Gerger

    Hi Craig,

    Of course you can. Happy to help.

  • Craig

    Hi Yalim – many many thanks.

  • http://www.gerger.co Yalim K. Gerger

    You are very welcome Craig.

  • Yunusyenigor

    Merhaba Hocam;

    benim elimde javascript çoklu yer olan google map kodu var orada location ları kendi içinde javascript dosyasında ama ben bunları XML den çekmek istiyorum
    var locations = [
    ['Bondi Beach', -33.890542, 151.274856, 4],
    ['Coogee Beach', -33.923036, 151.259052, 5],
    ['Cronulla Beach', -34.028249, 151.157507, 3],
    ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
    ['Maroubra Beach', -33.950198, 151.259302, 1]
    ];

    nasıl yapabilirim acaba ? şimdiden teşekkürler…

  • http://azizunsal.com Aziz Ünsal

    Soruyu biraz açabilir misiniz; tam olarak ne yapmak istiyorsunuz ?

  • Yunusyenigor

    demek istediğim ben bir yerden sitelerimize google map kodları buldum bu kodlarda birden fazla nokta işaretlenebiliyor javascript kodu içinden fakat ben bu locationları XML dosyasından javascriptine içine çekmek istiyorum ?

    bunun gibi;

    var locations = [ restaurants.xml ];

  • http://azizunsal.com Aziz Ünsal

    Doğru anlamışsam eğer şöyle bir şeye ihtiyacınız var;

    İçinde location bilgilerinin olduğu buna benzer bir XML fileınız olduğunu/olacağını varsayıyorum:

    ….

    Ve bunları JS içerisinde almak istiyorsunuz, bunun için şöyle bir fonksiyon yazabiliriz:

    function getLocations(locationsXml){
    var locations = [];

    $(locationsXml).find(“marker”).each(function){
    var markerNode = $(this);
    var location = new google.map.LatLng(markerNode.attr(‘lat’), markerNode.attr(‘lng’));
    locations.push(location)
    }
    }

    Artık elinizde istanbul ve ankara’nın latitude ve longitude bilgisi olan bir “locations” array ı var. Bunu Google Maps API ile dilediğiniz gibi kullanabilirsiniz.

    Umarım yardımcı olabilmişimdir.

  • Ignetius Mashile

    It’s really, really cool.

    How do I filter to show only my country?

  • Liuyajms

    Thank you very much!

  • Olas Navigator

    First, Thank You very much for Mr. Aziz Unsal.

    i manage to filter by specific country, it’s not a good solution but it’s worked. I hope someone can make it more prettier.

    geocoder.geocode( {‘address’: request.term + ” Indonesia”, ‘region’: “id” }, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {

    //find the latest word from formatted address
    var myCountry = results[0].formatted_address.split(/[, ]+/).pop();

    if(myCountry == “Indonesia”){
    var searchLoc = results[0].geometry.location;
    ……………………….
    }
    }
    });

  • Clayton Miller

    how can I change it to a specific location and search for anything nearby?

  • Jipin Nakarmi

    i have used fusion table to show the mobile coverage of a telecom company…..i have the map with the coverage aswell but i am not being able to figure out how would i use the map built using fusion table with this code. Since it used this one… ….i have to replace this map with my map built with fusion table.

  • Chaitenyay

    awesome work bro…

  • Justaquickone

    Love it. Thank you. Also added a marker on selection by amending these two bits:

    …….

    return {
    label: loc.formatted_address,
    value: loc.formatted_address,
    bounds: loc.geometry.bounds,
    latitude: loc.geometry.location.lat(),
    longitude: loc.geometry.location.
    }

    &

    …..

    if (bounds) {
    map.fitBounds(bounds);
    }
    var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
    var marker = new google.maps.Marker({
    position: location,
    map: map,
    draggable: false
    });

  • Nicolas Cabrera

    Hi! good Job, I did some cache improvements to your script

    ADDING LOCAL CACHE:
    1. Add a variable called “cache” before the $(“#searchbox”).autocomplete:
    var cache = {};

    2. Then after the second geocoding call changed the code to this:

    if (status1 == google.maps.GeocoderStatus.OK) {
    if (results1[1]) {
    //Translate all items in an array or object to new array of items
    var data = $.map(results1, function(loc) {
    return {
    // jquery IU defaults
    id : loc.formatted_address,
    label : loc.formatted_address,
    value : loc.formatted_address,
    // adding new properties
    bounds : loc.geometry.bounds,
    latlng : new google.maps.LatLng(loc.geometry.location.lat(), loc.geometry.location.lng()),
    formatted_address : loc.formatted_address,
    lat : loc.geometry.location.lat(),
    lng : loc.geometry.location.lng(),
    location : loc.geometry.location
    };
    });
    // add to cache
    cache[ term ] = data;
    response(data);
    }
    }

    This adds some local caching to improve performance, now every time the user looks for the same term you will save one http call (geocode call).
    I took the idea from http://jqueryui.com/demos/autocomplete/remote-with-cache.html.
    Thanks!

  • nana

    hi! this is brilliant..

    is it possible to source addresses from a database?

  • Kizildagcenk

    Hocam,

    Jquery maps ile location search yapmak istiyorum.Ara sonucunda maps üzerinde marker koymak ve marker’a tıklayınca da modal pop up açıp birşeyler göstermek istiyorum. Bu konu ile ilgili yardımcı olabilir misiniz?

    Teşekkür ederim.

  • powers

    Its nice BUT it doesnt really give you the same kind of pull down as Google Maps since its converting to lat/lng and then looking up by that instead of the original query. Things like landmarks, that work well in maps proper, dont come back well in this (e.g. Big Basin gets you a list of parks in CA but if you do that in this form you get an odd list of addresses nearby). Anyone have a variation that might get closer to Google Maps’ list?

  • powers

    Looks like Google Maps offers its own autocomplete now that can do addresses or places or both!
    http://code.google.com/apis/maps/documentation/javascript/places.html#places_autocomplete

  • Ashok Mandial

    This is what i was looking from last two days. you just make my day. Many thanks..

  • http://www.gerger.co Yalim K. Gerger

    You are welcome Ashok. :-)

  • Aziz Saidakhmedov

    i have one problem. I have local markers (custom geocoders for my city) in my database. How can I merge google result and my local result in one autocomplate? Can I send a request in server side to fetch google geo coders?

  • Anonymous

    Awesome Post. Thanks alot sir :)

  • Ramya

    Hi, first of all I should appreciate you for the nice work done.

    Your piece of code is working fine in Chrome but not in IE 9 and Firefox 16.0.1.
    The problem that I am facing is that the auto-complete dropdown is playing hide and seek i.e, appearing and disappearing as I start typing a place.

    Please let me know the fix for this ASAP.

    Thanks in advance.

  • Afaq

    Great code, just what I had been looking for. Can this code be modified to select the specific marker that is being entered. Example, I enter “Mamji Hospital” and among other choices auto complete does not specifically list “Mamji Hospital”. I am working on a Blood donation website and need specific coordinates of the hospitals.

    Would appreciate any help in this regard.

  • Idhar

    Great tutorial :D thanks for share

  • Youyouk

    Thank you, it was very usefull :)

  • http://www.thatsitguys.com/ Meleniumshane90

    When I tried your code, the map no longer loaded.

  • Sudarshana

    please send improved final demo code

  • alexis

    is there a way to enter location directly
    from search box without picking from the dropdown list?

  • http://www.facebook.com/shreshtt.bhatt Shreshtt Bhatt

    thanks for this wonderful tutorial.. it works like a charm

  • Catalin Deaconescu

    great example … works great and is exactly what i was looking for … thanks a lot

  • Prasad

    Hi,

    Code is working fine.But a small problem is coming that is the custom search results and Google Map serach results are different and I want marker on Map.Could you pls help me.

  • Abhishek

    thx