Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Googe places autocomplete implementation using Twitter bootstrap typeahead and google's autocomplete and geocoding services
/**
* Author: Richard Willis - badsyntax.co
* Example here: http://demos.badsyntax.co/places-search-bootstrap/example.html
*
* Please note: This is not a reliable method of geocoding the address. Using the
* PlacesService is a much better approach. View the example above for an example
* of using the PlacesService to geocode the address.
*/
var service = new google.maps.places.AutocompleteService();
var geocoder = new google.maps.Geocoder();
$(field).typeahead({
source: function(query, process) {
service.getPlacePredictions({ input: query }, function(predictions, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
process($.map(predictions, function(prediction) {
return prediction.description;
}));
}
});
},
updater: function (item) {
geocoder.geocode({ address: item }, function(results, status) {
if (status != google.maps.GeocoderStatus.OK) {
alert('Cannot find address');
return;
}
map.setCenter(results[0].geometry.location);
map.setZoom(12);
});
return item;
}
});
@alb3rto269
Copy link

alb3rto269 commented Jan 30, 2013

Works great! Thanks for sharing this snippet!

@Err0r404
Copy link

Err0r404 commented Mar 28, 2013

Very usefull !

Someone knows how to restrict results to a specific country ?

@saurabh-agrawal83
Copy link

saurabh-agrawal83 commented Jun 1, 2013

You can specify types, and componentRestrictions using AutocompletionRequest. Here is an example -http://stackoverflow.com/a/16873361/206351

@saurabh-agrawal83
Copy link

saurabh-agrawal83 commented Jun 1, 2013

Works great!..thanks for sharing..

@idrakimuhamad
Copy link

idrakimuhamad commented Jun 7, 2013

Thanks!

@lukashoffmann
Copy link

lukashoffmann commented Jun 24, 2013

works great! thx!

@sivareddy-cc
Copy link

sivareddy-cc commented Jul 1, 2013

Its Working ... ! Thank you very much for the code

@badsyntax
Copy link
Author

badsyntax commented Aug 11, 2013

Glad some people found this handy.

I've created a full working example here: http://demos.badsyntax.co/places-search-bootstrap/example.html

@sjaaksola
Copy link

sjaaksola commented Aug 12, 2013

Great Job Richard!

But this isn't working with bs 3, gives error: "Error: one of local, prefetch, or remote is required"

Can you help? :)

--- EDITED ---

I gave up :) im using now bootstrap 3 rc1 and google api, and some style modifications.. you cant see the difference :P

@ScotterC
Copy link

ScotterC commented Aug 13, 2013

@badsyntax is there a repo for your jquery.places-search ?

@hakanb
Copy link

hakanb commented Aug 25, 2013

Thanks for this, @badsyntax. For anyone else dealing with missing results using this example, I found a small issue where valid results whose names do not contain the query are not displayed. For example, try searching for "mcdonald's nyc" in the demo and you will notice no results are returned, while the same search returns five results on Google's autocomplete example.

To fix this, override Typehead's default matcher function, which hides results whose names do not contain the query, by adding a matcher function to the $.typeahead's call like so:

matcher: function (item) {
    return true;
}

@badsyntax
Copy link
Author

badsyntax commented Aug 27, 2013

@ScotterC I have not created a repo for this code. If you would like to do so, feel free to use my code.

To everyone else, I wanted to create a bootstrap 3 version, but I'm quite disappointed that Bootstrap 3 dropped the typeahead plugin.

I'm really grumpy about this, because the new "fancy" typeahead.js plugin is just another typical bloated jquery plugin and is NOT a drop-in replacement for bootstrap 2.3.0 typeahead.

Seriously, there's no API methods to build up the list of suggestions manually. The plugin expects a data source, and it expects to do all the filtering within a large data set. Whereas with the Google Places API, the API itself does all the filtering and just returns the suggestions. I can't combine the two. I can't manually add the list of suggestions. Such a fancy plugin, so very useless.

If you want to use the typeahead with google's autocomplete with Bootstrap 3, you will have to use Bootstrap 2.3.0 typeahead.

I willl update this gist if/when typeahead.js provides a simple API method for building the list of suggestions manually.

@toolsmith
Copy link

toolsmith commented Sep 1, 2013

I completely agree...I've been trying to migrate my old bootstrap code using autocomplete and typeahead to 3.0 but it has been a nightmare! Has anyone else had any luck in doing so?

@svub
Copy link

svub commented Oct 7, 2013

Found a hack fpr the new typeahead so that suggestions can be provided using a callback method again.
It goes something like this:

(t = $("field")).typeahead({ local: [] });
t.data("ttView").datasets[0].getSuggestions = function(query, callback) {
  var suggestions = ... gather your suggestions here ...
  var data = [];
  for (suggestion in suggestions) { data.push(this._transformDatum(suggestion)); }
  callback(data)
}

More details at http://svenbuschbeck.net/wordpress/2013/10/callback-method-for-twitters-typeahead/
Guess this should allow you to use autocomplete again easily.

@ficshelf
Copy link

ficshelf commented Jan 9, 2014

this is great. many thanks!

I am however wrecking my brain trying to port your example to the latest twitter typeahead.js instead of the bootstrap 2 version. help?

@badsyntax
Copy link
Author

badsyntax commented Jan 23, 2014

@ficshelf read the comments in this thread, it's not possible without hacks.

Copy link

ghost commented Apr 27, 2014

@svub Where do i need to put your code so that autocomplete would work again ? Can't find place where to put it.

@Azaret
Copy link

Azaret commented Dec 31, 2014

Just in case anyone get to this page in the future, as it's like second when googling typeahead with gmaps.

It's totally possible to make typeahead works with google maps easily without hacks :

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

$('.typeahead').typeahead({
    autoselect: true,
    sections: [{
        name: 'google',
        minLength: 4,
        templates: {
            header: '<h5 class="typeahead-header">Google Results</h5>'
        },
        source: function (q, value) {
            geocoder.geocode({ address: q }, function (results, status) {

                value($.map(results, function (result) {
                    retval = [];
                    retval.push({ value: result.formatted_address });
                    return retval;
                }));
            });
        }
  }]
});

source : twitter/typeahead.js#220 (comment)

@ronnyandre
Copy link

ronnyandre commented Sep 25, 2015

Couldn't get that to work @Azaret .. No errors, typeahead is initialized, but no dropdown with results.

@vinicius33
Copy link

vinicius33 commented Feb 25, 2016

thx for sharing! :)

@tomhalley
Copy link

tomhalley commented Apr 24, 2017

@badsyntax You created a project for it on google developer console and assigned the demo an API key.... then you deleted the project. Probably best just not to have given it an API key in the first place

@safakz
Copy link

safakz commented Oct 24, 2017

I think it will be a little late to answer @ronnyandre :) But this would be better. And moreover if any map on page it would be fit bounds to selected suggestions geometry

var geocoder = new google.maps.Geocoder();
$('.typeahead').typeahead({
                                            autoselect: true,
                                                minLength: 4,
                                              },{
                                                name: 'google',
                                                displayKey: 'address',
                                                templates: {
                                                    header: '<h5 class="typeahead-header">Google Results</h5>'
                                                },
                                                source: function (q, sync, async){
                                                    geocoder.geocode({ address: q }, function (results, status) {
                                                      for (var i = results.length - 1; i >= 0; i--) {
                                                        async([{address:results[i].formatted_address, geometry:results[i].geometry}]);
                                                      }
                                                    });
                                                }
                                          }
                                        ).on('typeahead:selected', function (obj, datum) {
                                            if(datum)
                                            {
                                              var geometry = datum.geometry;
                                               map.fitBounds(geometry.bounds? geometry.bounds : geometry.viewport);
                                            }
                                        });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment