 <h1>Updated</h1> <p>Google has released <a href="https://developers.google.com/maps/documentation/javascript/places-autocomplete" rel="nofollow">Google Places Autocomplete</a> which resolves exactly this problem.</p> <p>At the bottom of a page throw this in there:</p> <pre><code>&lt;script defer async src="//maps.googleapis.com/maps/api/js?libraries=places&amp;key=(key)&amp;sensor=false&amp;callback=googPlacesInit"&gt;&lt;/script&gt; </code></pre> <p>Where <code>(key)</code> is your API key.</p> <p>We've set our code up so you mark some fields to handle typeahead and get filled in by that typeahead, like:</p> <pre><code>&lt;input name=Address placeholder=Address /&gt; &lt;input name=Zip placeholder=Zip /&gt; </code></pre> <p>etc</p> <p>Then you initialize it (before the Google Places API has loaded typically, since that's going to land async) with:</p> <pre><code>GoogleAddress.init('#billing input', '#shipping input'); </code></pre> <p>Or whatever. In this case it's tying the address typeahead to whatever input has name=Address in the #billing tag and #shipping tag, and it will fill in the related fields inside those tags for City, State, Zip etc when an address is chosen.</p> <p>Setup the class:</p> <pre><code>var GoogleAddress = { AddressFields: [], //ZipFields: [], // Not in use and the support code is commented out, for now OnSelect: [], /** * @param {String} field Pass as many arguments as you like, each a selector to a set of inputs that should use Google * Address Typeahead via the Google Places API. * * Mark the inputs with name=Address, name=City, name=State, name=Zip, name=Country * All fields are optional; you can for example leave Country out and everything else will still work. * * The Address field will be used as the typeahead field. When an address is picked, the 5 fields will be filled in. */ init: function (field) { var args = $.makeArray(arguments); GoogleAddress.AddressFields = $.map(args, function (selector) { return $(selector); }); } }; </code></pre> <p>The script snippet above is going to async call into a function named <code>googPlacesInit</code>, so everything else is wrapped in a function by that name:</p> <pre><code>function googPlacesInit() { var fields = GoogleAddress.AddressFields; if ( // If Google Places fails to load, we need to skip running these or the whole script file will fail typeof (google) == 'undefined' || // If there's no input there's no typeahead so don't bother initializing fields.length == 0 || fields[0].length == 0 ) return; </code></pre> <p>Setup the autocomplete event, and deal with the fact that we always use multiple address fields, but Google wants to dump the entire address into a single input. There's surely a way to prevent this properly, but I'm yet to find it.</p> <pre><code>$.each(fields, function (i, inputs) { var jqInput = inputs.filter('[name=Address]'); var addressLookup = new google.maps.places.Autocomplete(jqInput[0], { types: ['address'] }); google.maps.event.addListener(addressLookup, 'place_changed', function () { var place = addressLookup.getPlace(); // Sometimes getPlace() freaks out and fails - if so do nothing but blank out everything after comma here. if (!place || !place.address_components) { setTimeout(function () { jqInput.val(/^([^,]+),/.exec(jqInput.val())[1]); }, 1); return; } var a = parsePlacesResult(place); // HACK! Not sure how to tell Google Places not to set the typeahead field's value, so, we just wait it out // then overwrite it setTimeout(function () { jqInput.val(a.address); }, 1); // For the rest, assign by lookup inputs.each(function (i, input) { var val = getAddressPart(input, a); if (val) input.value = val; }); onGoogPlacesSelected(); }); // Deal with Places API blur replacing value we set with theirs var removeGoogBlur = function () { var googBlur = jqInput.data('googBlur'); if (googBlur) { jqInput.off('blur', googBlur).removeData('googBlur'); } }; removeGoogBlur(); var googBlur = jqInput.blur(function () { removeGoogBlur(); var val = this.value; var _this = this; setTimeout(function () { _this.value = val; }, 1); }); jqInput.data('googBlur', googBlur); }); // Global goog address selected event handling function onGoogPlacesSelected() { $.each(GoogleAddress.OnSelect, function (i, fn) { fn(); }); } </code></pre> <p>Parsing a result into the canonical street1, street2, city, state/province, zip/postal code is not trivial. Google differentiates these localities with varying tags depending on where in the world you are, and as a warning, there are places for example in Africa that meet none of your expectations of what an address looks like. You can break addresses in the world into 3 categories:</p> <ul> <li><p>US-identical - the entire US and several countries that use a similar addressing system</p></li> <li><p>Formal addresses - UK, Australia, China, basically developed countries - but the way their address parts are tags has a fair amount of variance</p></li> <li><p>No formal addresses - in undeveloped areas there are no street names let alone street numbers, sometimes not even a town/city name, and certainly no zip. In these locations what you really want is a GPS location, which is not handled by this code.</p></li> </ul> <p>This code only attempts to deal with the first 2 cases.</p> <pre><code>function parsePlacesResult(place) { var a = place.address_components; var p = {}; var d = {}; for (var i = 0; i &lt; a.length; i++) { var ai = a[i]; switch (ai.types[0]) { case 'street_number': p.num = ai.long_name; break; case 'route': p.rd = ai.long_name; break; case 'locality': case 'sublocality_level_1': case 'sublocality': d.city = ai.long_name; break; case 'administrative_area_level_1': d.state = ai.short_name; break; case 'country': d.country = ai.short_name; break; case 'postal_code': d.zip = ai.long_name; } } var addr = []; if (p.num) addr.push(p.num); if (p.rd) addr.push(p.rd); d.address = addr.join(' '); return d; } /** * @param input An Input tag, the DOM element not a jQuery object * @paran a A Google Places Address object, with props like .city, .state, .country... */ var getAddressPart = function(input, a) { switch(input.name) { case 'City': return a.city; case 'State': return a.state; case 'Zip': return a.zip; case 'Country': return a.country; } return null; } </code></pre> <h1>Old Answer</h1> <p>ArcGis/ESRI has a limited typeahead solution that's functional but returns limited results only after quite a bit of input. There's a demo here:</p> <p><a href="http://www.esri.com/services/disaster-response/wildlandfire/latest-news-map.html" rel="nofollow">http://www.esri.com/services/disaster-response/wildlandfire/latest-news-map.html</a></p> <p>For example you might type 1600 Pennsylvania Ave hoping to get the white house by the time you type "1600 Penn", but have to get as far as "1600 pennsylvania ave, washington dc" before it responds with that address. Still, it could have a small benefit to users in time savings.</p>