[javascript] Google maps Places API V3 autocomplete - select first option on enter

I have successfuly implemented Google Maps Places V3 autocomplete feature on my input box as per http://web.archive.org/web/20120225114154/http://code.google.com:80/intl/sk-SK/apis/maps/documentation/javascript/places.html. It works nicely, however I would love to know how can I make it select the first option from the suggestions when a user presses enter. I guess I would need some JS magic, but I am very much new to JS and don't know where to start.

Thanks in advance!

The answer is


Regarding to all your answers, I have created a solution that works perfectly for me.

_x000D_
_x000D_
/**_x000D_
 * Function that add the google places functionality to the search inputs_x000D_
 * @private_x000D_
 */_x000D_
function _addGooglePlacesInputsAndListeners() {_x000D_
    var self = this;_x000D_
    var input = document.getElementById('searchBox');_x000D_
    var options = {_x000D_
        componentRestrictions: {country: "es"}_x000D_
    };_x000D_
_x000D_
    self.addInputEventListenersToAvoidAutocompleteProblem(input);_x000D_
    var searchBox = new google.maps.places.Autocomplete(input, options);_x000D_
    self.addPlacesChangedListener(searchBox, self.SimulatorMapStorage.map);_x000D_
}_x000D_
_x000D_
/**_x000D_
 * A problem exists with google.maps.places.Autocomplete when the user write an address and doesn't selectany options that autocomplete gives him so we have to add some events to the two inputs that we have to simulate the behavior that it should have. First, we get the keydown 13 (Enter) and if it's not a suggested option, we simulate a keydown 40 (keydownArrow) to select the first option that Autocomplete gives. Then, we dispatch the event to complete the request._x000D_
 * @param input_x000D_
 * @private_x000D_
 */_x000D_
function _addInputEventListenersToAvoidAutocompleteProblem(input) {_x000D_
    input.addEventListener('keydown', function(event) {_x000D_
        if (event.keyCode === 13 && event.which === 13) {_x000D_
            var suggestion_selected = $(".pac-item-selected").length > 0;_x000D_
            if (!suggestion_selected) {_x000D_
                var keyDownArrowEvent = new Event('keydown');_x000D_
                keyDownArrowEvent.keyCode = 40;_x000D_
                keyDownArrowEvent.which = keyDownArrowEvent.keyCode;_x000D_
_x000D_
                input.dispatchEvent(keyDownArrowEvent);_x000D_
            }_x000D_
        }_x000D_
    });_x000D_
}
_x000D_
<input id="searchBox" class="search-input initial-input" type="text" autofocus>
_x000D_
_x000D_
_x000D_

Hope that it can help to someone. Please, feel free to discuss the best way to do.


None of these answers seemed to work for me. They'd get the general location but wouldn't actually pan to the actual place I searched for. Within the .pac-item you can actually get just the address (name of place excluded) by selecting $('.pac-item:first').children()[2].textContent

So here is my solution:

$("#search_field").on("keyup", function(e) {
    if(e.keyCode == 13) {
        searchPlaces();
    }
});

function searchPlaces() {
    var $firstResult = $('.pac-item:first').children();
    var placeName = $firstResult[1].textContent;
    var placeAddress = $firstResult[2].textContent;

    $("#search_field").val(placeName + ", " + placeAddress);

    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({"address":placeAddress }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            var lat = results[0].geometry.location.lat(),
                lng = results[0].geometry.location.lng(),
                placeName = results[0].address_components[0].long_name,
                latlng = new google.maps.LatLng(lat, lng);

            map.panTo(latlng);
        }
    });
}

I know this question was already answered but figured I'd throw in my 2 cents just in case anyone else was having the same problem as me.


A working answer for 2020.

I've combined the best answers on this page and written it in straightforward ES6. No jQuery, 2nd API request, or IIFE needed.

Basically, we simulate a ? (down-arrow) keypress whenever the user hits return inside the autocomplete field.

First, assuming in your HTML you have something like <input id="address-field">, set up the identification of your address field like this:

const field = document.getElementById('address-field') 

const autoComplete = new google.maps.places.Autocomplete(field)

autoComplete.setTypes(['address'])

Then add this on the next line:

enableEnterKey(field)

And then elsewhere in your script, to keep this functionality separate in your code if you'd like to, add the function:

  function enableEnterKey(input) {

    /* Store original event listener */
    const _addEventListener = input.addEventListener

    const addEventListenerWrapper = (type, listener) => {
      if (type === 'keydown') {
        /* Store existing listener function */
        const _listener = listener
        listener = (event) => {
          /* Simulate a 'down arrow' keypress if no address has been selected */
          const suggestionSelected = document.getElementsByClassName('pac-item-selected').length
          if (event.key === 'Enter' && !suggestionSelected) {
            const e = new KeyboardEvent('keydown', { 
              key: 'ArrowDown', 
              code: 'ArrowDown', 
              keyCode: 40, 
            })
            _listener.apply(input, [e])
          }
          _listener.apply(input, [event])
        }
      }
      _addEventListener.apply(input, [type, listener])
    }

    input.addEventListener = addEventListenerWrapper
  }

You should be good to go. Essentially, the function captures each keypress in the input field and if it's an enter, simulates instead a down-arrow keypress. It also stores and rebinds listeners and events to maintain all functionality of your Google Maps Autocomplete().

With thanks to earlier answers for much of this code, particular amirnissim and Alexander Schwarzman.


Building on amimissim's answer, I present a slight alternative, utilising Google's API to handle the events in a cross browser way (amimissim's solution doesn't seem to work in IE8).

I also had to change pac-item.pac-selected to pac-item-refresh.pac-selected as it seems the results div class has changed. This makes pressing ENTER on a suggestion work (rather than selecting the next one down).

var input = document.getElementById('MyFormField');
var autocomplete = new google.maps.places.Autocomplete(input);
google.maps.event.addListener(autocomplete, 'keydown', function(event) {
    var suggestion_selected = $(".pac-item-refesh.pac-selected").length > 0;
    if (event.which == 13 && !suggestion_selected) {
        var simulated_downarrow = $.Event("keydown", {
                    keyCode: 40,
                    which: 40
        });
        this.apply(autocomplete, [simulated_downarrow]);
    }
    this.apply(autocomplete, [event]);
});

@Alexander 's solution is the one which I was looking for. But it was causing an error - TypeError: a.stopPropagation is not a function.

So I made the event with KeyboardEvent. Here's the working code and Javascript version is very convenient for React.js projects. I also used this for my React.js project.

(function selectFirst(input) {
  let _addEventListener = input.addEventListener
    ? input.addEventListener
    : input.attachEvent;

  function addEventListenerWrapper(type, listener) {
    if (type === 'keydown') {
      console.log('keydown');

      let orig_listener = listener;
      listener = event => {
        let suggestion_selected =
          document.getElementsByClassName('pac-item-selected').length > 0;

        if (event.keyCode === 13 && !suggestion_selected) {
          let simulated_downarrow = new KeyboardEvent('keydown', {
            bubbles: true,
            cancelable: true,
            keyCode: 40
          });

          orig_listener.apply(input, [simulated_downarrow]);
        }

        orig_listener.apply(input, [event]);
      };
    }

    _addEventListener.apply(input, [type, listener]);
  }

  if (input.addEventListener) input.addEventListener = addEventListenerWrapper;
  else if (input.attachEvent) input.attachEvent = addEventListenerWrapper;
})(addressInput);

this.autocomplete = new window.google.maps.places.Autocomplete(addressInput, options);

Hope this can help someone, :)


For Google Places Autocomplete V3, the best solution for this is two API requests.

Here is the fiddle

The reason why none of the other answers sufficed is because they either used jquery to mimic events (hacky) or used either Geocoder or Google Places Search box which does not always match autocomplete results. Instead, what we will do is is uses Google's Autocomplete Service as detailed here with only javascript (no jquery)

Below is detailed the most cross browser compatible solution using native Google APIs to generate the autocomplete box and then rerun the query to select the first option.

<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places&language=en"></script>

Javascript

// For convenience, although if you are supporting IE8 and below
// bind() is not supported
var $ = document.querySelector.bind(document);

function autoCallback(predictions, status) {
    // *Callback from async google places call
    if (status != google.maps.places.PlacesServiceStatus.OK) {
        // show that this address is an error
        pacInput.className = 'error';
        return;
    }

    // Show a successful return
    pacInput.className = 'success';
    pacInput.value = predictions[0].description;
}


function queryAutocomplete(input) {
    // *Uses Google's autocomplete service to select an address
    var service = new google.maps.places.AutocompleteService();
    service.getPlacePredictions({
        input: input,
        componentRestrictions: {
            country: 'us'
        }
    }, autoCallback);
}

function handleTabbingOnInput(evt) {
    // *Handles Tab event on delivery-location input
    if (evt.target.id == "pac-input") {
        // Remove active class
        evt.target.className = '';

        // Check if a tab was pressed
        if (evt.which == 9 || evt.keyCode == 9) {
            queryAutocomplete(evt.target.value);
        }
    }
}

// ***** Initializations ***** //
// initialize pac search field //
var pacInput = $('#pac-input');
pacInput.focus();

// Initialize Autocomplete
var options = {
    componentRestrictions: {
        country: 'us'
    }
};
var autocomplete = new google.maps.places.Autocomplete(pacInput, options);
// ***** End Initializations ***** //

// ***** Event Listeners ***** //
google.maps.event.addListener(autocomplete, 'place_changed', function () {
    var result = autocomplete.getPlace();
    if (typeof result.address_components == 'undefined') {
        queryAutocomplete(result.name);
    } else {
        // returns native functionality and place object
        console.log(result.address_components);
    }
});

// Tabbing Event Listener
if (document.addEventListener) {
    document.addEventListener('keydown', handleTabbingOnInput, false);
} else if (document.attachEvent) { // IE8 and below
    document.attachEvent("onsubmit", handleTabbingOnInput);
}

// search form listener
var standardForm = $('#search-shop-form');
if (standardForm.addEventListener) {
    standardForm.addEventListener("submit", preventStandardForm, false);
} else if (standardForm.attachEvent) { // IE8 and below
    standardForm.attachEvent("onsubmit", preventStandardForm);
}
// ***** End Event Listeners ***** //

HTML

<form id="search-shop-form" class="search-form" name="searchShopForm" action="/impl_custom/index/search/" method="post">
    <label for="pac-input">Delivery Location</label>
        <input id="pac-input" type="text" placeholder="Los Angeles, Manhattan, Houston" autocomplete="off" />
        <button class="search-btn btn-success" type="submit">Search</button>
</form>

The only gripe is that the native implementation returns a different data structure although the information is the same. Adjust accordingly.


How about this?

$("input").keypress(function(event) {
  var firstValue = null;
  if (event.keyCode == 13 || event.keyCode == 9) {
    $(event.target).blur();
    if ($(".pac-container .pac-item:first span:eq(3)").text() == "") {
      firstValue = $(".pac-container .pac-item:first .pac-item-query").text();
    } else {
      firstValue = $(".pac-container .pac-item:first .pac-item-query").text() + ", " + $(".pac-container .pac-item:first span:eq(3)").text();
    }
    event.target.value = firstValue;
  } else
    return true;
});

Here is an example of a real, non-hacky, solution. It doesn't use any browser hacks etc, just methods from the public API provided by Google and documented here: Google Maps API

The only downside is that additional requests to Google are required if the user doesn't select an item from the list. The upside is that the result will always be correct as the query is performed identically to the query inside the AutoComplete. Second upside is that by only using public API methods and not relying on the internal HTML structure of the AutoComplete widget, we can be sure that our product won't break if Google makes changes.

var input = /** @type {HTMLInputElement} */(document.getElementById('searchTextField'));
var autocomplete = new google.maps.places.Autocomplete(input);  
// These are my options for the AutoComplete
autocomplete.setTypes(['(cities)']);
autocomplete.setComponentRestrictions({'country': 'es'});

google.maps.event.addListener(autocomplete, 'place_changed', function() {
    result = autocomplete.getPlace();
    if(typeof result.address_components == 'undefined') {
        // The user pressed enter in the input 
        // without selecting a result from the list
        // Let's get the list from the Google API so that
        // we can retrieve the details about the first result
        // and use it (just as if the user had actually selected it)
        autocompleteService = new google.maps.places.AutocompleteService();
        autocompleteService.getPlacePredictions(
            {
                'input': result.name,
                'offset': result.name.length,
                // I repeat the options for my AutoComplete here to get
                // the same results from this query as I got in the 
                // AutoComplete widget
                'componentRestrictions': {'country': 'es'},
                'types': ['(cities)']
            },
            function listentoresult(list, status) {
                if(list == null || list.length == 0) {
                    // There are no suggestions available.
                    // The user saw an empty list and hit enter.
                    console.log("No results");
                } else {
                    // Here's the first result that the user saw
                    // in the list. We can use it and it'll be just
                    // as if the user actually selected it
                    // themselves. But first we need to get its details
                    // to receive the result on the same format as we
                    // do in the AutoComplete.
                    placesService = new google.maps.places.PlacesService(document.getElementById('placesAttribution'));
                    placesService.getDetails(
                        {'reference': list[0].reference},
                        function detailsresult(detailsResult, placesServiceStatus) {
                            // Here's the first result in the AutoComplete with the exact
                            // same data format as you get from the AutoComplete.
                            console.log("We selected the first item from the list automatically because the user didn't select anything");
                            console.log(detailsResult);
                        }
                    );
                }
            }
        );
    } else {
        // The user selected a result from the list, we can 
        // proceed and use it right away
        console.log("User selected an item from the list");
        console.log(result);
    }
});

Working Solution that listens to if the user has started to navigate down the list with the keyboard rather than triggering the false navigation each time

https://codepen.io/callam/pen/RgzxZB

Here are the important bits

// search input
const searchInput = document.getElementById('js-search-input');

// Google Maps autocomplete
const autocomplete = new google.maps.places.Autocomplete(searchInput);

// Has user pressed the down key to navigate autocomplete options?
let hasDownBeenPressed = false;

// Listener outside to stop nested loop returning odd results
searchInput.addEventListener('keydown', (e) => {
    if (e.keyCode === 40) {
        hasDownBeenPressed = true;
    }
});

// GoogleMaps API custom eventlistener method
google.maps.event.addDomListener(searchInput, 'keydown', (e) => {

    // Maps API e.stopPropagation();
    e.cancelBubble = true;

    // If enter key, or tab key
    if (e.keyCode === 13 || e.keyCode === 9) {
        // If user isn't navigating using arrows and this hasn't ran yet
        if (!hasDownBeenPressed && !e.hasRanOnce) {
            google.maps.event.trigger(e.target, 'keydown', {
                keyCode: 40,
                hasRanOnce: true,
            });
        }
    }
});

 // Clear the input on focus, reset hasDownBeenPressed
searchInput.addEventListener('focus', () => {
    hasDownBeenPressed = false;
    searchInput.value = '';
});

// place_changed GoogleMaps listener when we do submit
google.maps.event.addListener(autocomplete, 'place_changed', function() {

    // Get the place info from the autocomplete Api
    const place = autocomplete.getPlace();

    //If we can find the place lets go to it
    if (typeof place.address_components !== 'undefined') {          
        // reset hasDownBeenPressed in case they don't unfocus
        hasDownBeenPressed = false;
    }

});

    /// <reference types="@types/googlemaps" />
import {ChangeDetectorRef, Component, ElementRef, EventEmitter, Inject, Input, NgZone, OnInit, Output, ViewChild} from '@angular/core';
import {MapsAPILoader, MouseEvent} from '@agm/core';
import { Address } from 'src/@core/interfaces/address.model';
import { NotificationService } from 'src/@core/services/notification.service';
// import {} from 'googlemaps';
declare var google: any;

// @ts-ignore

@Component({
  selector: 'app-search-address',
  templateUrl: './search-address.component.html',
  styleUrls: ['./search-address.component.scss']
})
export class SearchAddressComponent implements OnInit {

  @Input('label') label: string;
  @Input('addressObj') addressObj: Address = {};
  zoom: number;
  isSnazzyInfoWindowOpened = false;

  private geoCoder;

  // @ts-ignore
  @Output() onAddressSelected = new EventEmitter<any>();
  @Input('defaultAddress') defaultAddress = '';
  @ViewChild('search', {static: true})
  public searchElementRef: ElementRef = null;


  constructor(
    private mapsAPILoader: MapsAPILoader,
    private ngZone: NgZone,
    private notify: NotificationService,
    @Inject(ChangeDetectorRef) private changeDetectorRef: ChangeDetectorRef
  ) { }


  ngOnInit() {
    // console.log('addressObj# ', this.addressObj);
    if (this.defaultAddress !== '') {
      this.searchElementRef.nativeElement.value = this.defaultAddress;
    }
    // load Places Autocomplete
    this.mapsAPILoader.load().then(() => {
      if (this.addressObj.address) {
        this.setZoom();
      } else {
        this.setCurrentLocation();
      }
      this.geoCoder = new google.maps.Geocoder;
      const autocomplete = new google.maps.places.Autocomplete(this.searchElementRef.nativeElement, {
        types: ['address']
      });
      autocomplete.setTypes(['(cities)']);
      autocomplete.setComponentRestrictions({'country': 'in'});
      autocomplete.addListener('place_changed', () => {
        this.ngZone.run(() => {
          // get the place result
          const place: google.maps.places.PlaceResult = autocomplete.getPlace();

          // verify result
          if (place.geometry === undefined || place.geometry === null) {
            return;
          }

          // set latitude, longitude and zoom
          this.addressObj.latitude = place.geometry.location.lat();
          this.addressObj.longitude = place.geometry.location.lng();
          this.getAddress(this.addressObj.latitude, this.addressObj.longitude);
          this.zoom = 12;
        });
      });
    });
  }

  setZoom() {
    this.zoom = 8;
  }

  // Get Current Location Coordinates
  private setCurrentLocation() {
    if ('geolocation' in navigator) {
      navigator.geolocation.getCurrentPosition((position) => {
        this.addressObj.latitude = position.coords.latitude;
        this.addressObj.longitude = position.coords.longitude;
        this.zoom = 8;
        this.getAddress(this.addressObj.latitude, this.addressObj.longitude);
      });
    }
  }

  markerDragEnd($event: MouseEvent) {
    this.addressObj.latitude = $event.coords.lat;
    this.addressObj.longitude = $event.coords.lng;
    this.getAddress(this.addressObj.latitude, this.addressObj.longitude);
  }

  getAddress(latitude, longitude) {
    this.addressObj.latitude = latitude;
    this.addressObj.longitude = longitude;
    this.geoCoder.geocode({ location: { lat: latitude, lng: longitude } }, (results, status) => {
      if (status === 'OK') {
        if (results[0]) {
          console.log('results ', results);
          this.zoom = 12;
          this.addressObj.address = results[0].formatted_address;
          this.showSnazzyInfoWindow();
          this.addressObj.placeId = results[0].place_id;

          for(let i = 0; i < results[0].address_components.length; i++) {
            if (results[0].address_components[i].types[0] == 'locality') {
              this.addressObj.city = results[0].address_components[i].long_name;
            }
            if (results[0].address_components[i].types[0] == 'administrative_area_level_1') {
              this.addressObj.region = results[0].address_components[i].long_name;
            }
            if (results[0].address_components[i].types[0] == 'country') {
              this.addressObj.country = results[0].address_components[i].long_name;
            }
            if (results[0].address_components[i].types[0] == 'postal_code') {
              this.addressObj.zip = results[0].address_components[i].long_name;
            }
          }

          this.transmitData();
        } else {
          this.notify.showMessage('No results found', 3000, 'OK');
        }
      } else {
        this.notify.showMessage('Google maps location failed due to: ' + status, 3000, 'OK');
      }

    });
  }


  transmitData() {
   // console.log(this.addressObj);
    this.onAddressSelected.emit(this.addressObj);
  }

  toggleSnazzyInfoWindow() {
    this.isSnazzyInfoWindowOpened = !this.isSnazzyInfoWindowOpened;
  }

  showSnazzyInfoWindow() {
    this.isSnazzyInfoWindowOpened = true;
  }

}




<mat-form-field class="full-width pt-2 flex-auto w-full">
  <input matInput [(ngModel)]="addressObj.address" type="text" (keydown.enter)="$event.preventDefault()" placeholder="{{label ? label : 'Location'}}" autocorrect="off" autocapitalize="off" spellcheck="off" type="text" #search>
</mat-form-field>

<agm-map
  [latitude]="addressObj.latitude"
  [longitude]="addressObj.longitude"
  [zoom]="zoom">
  <agm-marker
    [latitude]="addressObj.latitude"
    [longitude]="addressObj.longitude"
    [markerDraggable]="true"
    (dragEnd)="markerDragEnd($event)">
  </agm-marker>

</agm-map>

I did some work around this and now I can force select 1st option from google placces using angular js and angular Autocomplete module.
Thanks to kuhnza
my code

<form method="get" ng-app="StarterApp"  ng-controller="AppCtrl" action="searchresults.html" id="target" autocomplete="off">
   <br/>
    <div class="row">
    <div class="col-md-4"><input class="form-control" tabindex="1" autofocus g-places-autocomplete force-selection="true"  ng-model="user.fromPlace" placeholder="From Place" autocomplete="off"   required>
    </div>
        <div class="col-md-4"><input class="form-control" tabindex="2"  g-places-autocomplete force-selection="true"  placeholder="To Place" autocomplete="off" ng-model="user.toPlace" required>
    </div>
    <div class="col-md-4"> <input class="btn btn-primary"  type="submit" value="submit"></div></div><br /><br/>
    <input class="form-control"  style="width:40%" type="text" name="sourceAddressLat" placeholder="From Place Lat" id="fromLat">
    <input class="form-control"  style="width:40%"type="text" name="sourceAddressLang" placeholder="From Place Long" id="fromLong">
    <input class="form-control"  style="width:40%"type="text" name="sourceAddress" placeholder="From Place City" id="fromCity">
    <input class="form-control"  style="width:40%"type="text" name="destinationAddressLat" placeholder="To Place Lat" id="toLat">
    <input class="form-control"  style="width:40%"type="text" name="destinationAddressLang" placeholder="To Place Long"id="toLong">
    <input class="form-control"  style="width:40%"type="text" name="destinationAddress"placeholder="To Place City" id="toCity">
</form>

Here is a Plunker
Thank you.


I just want to write an small enhancement for the answer of amirnissim
The script posted doesn't support IE8, because "event.which" seems to be always empty in IE8.
To solve this problem you just need to additionally check for "event.keyCode":

listener = function (event) {
  if (event.which == 13 || event.keyCode == 13) {
    var suggestion_selected = $(".pac-item.pac-selected").length > 0;
    if(!suggestion_selected){
      var simulated_downarrow = $.Event("keydown", {keyCode:40, which:40})
      orig_listener.apply(input, [simulated_downarrow]);
    }
  }
  orig_listener.apply(input, [event]);
};

JS-Fiddle: http://jsfiddle.net/QW59W/107/


@benregn @amirnissim I think the selection error comes from:

var suggestion_selected = $(".pac-item.pac-selected").length > 0;

The class pac-selected should be pac-item-selected, which explains why !suggestion_selected always evaluate to true, causing the incorrect location to be selected when the enter key is pressed after using 'keyup' or 'keydown' to highlight the desired location.


Here is a solution that does not make a geocoding request that may return an incorrect result: http://jsfiddle.net/amirnissim/2D6HW/

It simulates a down-arrow keypress whenever the user hits return inside the autocomplete field. The ? event is triggered before the return event so it simulates the user selecting the first suggestion using the keyboard.

Here is the code (tested on Chrome and Firefox) :

<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<script>
    var pac_input = document.getElementById('searchTextField');

    (function pacSelectFirst(input) {
        // store the original event binding function
        var _addEventListener = (input.addEventListener) ? input.addEventListener : input.attachEvent;

        function addEventListenerWrapper(type, listener) {
            // Simulate a 'down arrow' keypress on hitting 'return' when no pac suggestion is selected,
            // and then trigger the original listener.
            if (type == "keydown") {
                var orig_listener = listener;
                listener = function(event) {
                    var suggestion_selected = $(".pac-item-selected").length > 0;
                    if (event.which == 13 && !suggestion_selected) {
                        var simulated_downarrow = $.Event("keydown", {
                            keyCode: 40,
                            which: 40
                        });
                        orig_listener.apply(input, [simulated_downarrow]);
                    }

                    orig_listener.apply(input, [event]);
                };
            }

            _addEventListener.apply(input, [type, listener]);
        }

        input.addEventListener = addEventListenerWrapper;
        input.attachEvent = addEventListenerWrapper;

        var autocomplete = new google.maps.places.Autocomplete(input);

    })(pac_input);
</script>

It seems there is a much better and clean solution: To use google.maps.places.SearchBox instead of google.maps.places.Autocomplete. A code is almost the same, just getting the first from multiple places. On pressing the Enter the the correct list is returned - so it runs out of the box and there is no need for hacks.

See the example HTML page:

http://rawgithub.com/klokan/8408394/raw/5ab795fb36c67ad73c215269f61c7648633ae53e/places-enter-first-item.html

The relevant code snippet is:

var searchBox = new google.maps.places.SearchBox(document.getElementById('searchinput'));

google.maps.event.addListener(searchBox, 'places_changed', function() {
  var place = searchBox.getPlaces()[0];

  if (!place.geometry) return;

  if (place.geometry.viewport) {
    map.fitBounds(place.geometry.viewport);
  } else {
    map.setCenter(place.geometry.location);
    map.setZoom(16);
  }
});

The complete source code of the example is at: https://gist.github.com/klokan/8408394


I investigated this a bit since I have the same Issue. What I did not like about the previous solutions was, that the autocomplete already fired the AutocompleteService to show the predictions. Therefore, the predictions should be somewhere and should not be loaded again.

I found out that the predictions of place inkl. place_id is stored in

Autocomplete.gm_accessors_.place.Kc.l

and you will be able to get a lot of data from the records [0].data. Imho, it's faster and better to get the location by using the place_id instead of address data. This very strange object selection appears not very good to me, tho.

Do you know, if there is a better way to retrieve the first prediction from the autocomplete?


Just a pure javascript version (without jquery) of the great amirnissim's solution:

listener = function(event) {
      var suggestion_selected = document.getElementsByClassName('.pac-item-selected').length > 0;
      if (event.which === 13 && !suggestion_selected) {
        var e = JSON.parse(JSON.stringify(event));
        e.which = 40;
        e.keyCode = 40;
        orig_listener.apply(input, [e]);
      }
      orig_listener.apply(input, [event]);
    };

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to google-maps

GoogleMaps API KEY for testing Google Maps shows "For development purposes only" java.lang.NoClassDefFoundError:failed resolution of :Lorg/apache/http/ProtocolVersion How to import JSON File into a TypeScript file? Googlemaps API Key for Localhost Getting "Cannot call a class as a function" in my React Project ERROR: Google Maps API error: MissingKeyMapError This page didn't load Google Maps correctly. See the JavaScript console for technical details Google Maps API warning: NoApiKeys ApiNotActivatedMapError for simple html page using google-places-api

Examples related to autocomplete

twitter bootstrap 3.0 typeahead ajax example How do I stop Notepad++ from showing autocomplete for all words in the file how to get value of selected item in autocomplete .autocomplete is not a function Error Angularjs autocomplete from $http autocomplete ='off' is not working when the input type is password and make the input field above it to enable autocomplete Disabling Chrome Autofill How to add Google Maps Autocomplete search box? Google Maps API - how to get latitude and longitude from Autocomplete without showing the map? twitter bootstrap autocomplete dropdown / combobox with Knockoutjs

Examples related to google-maps-api-3

Google Maps shows "For development purposes only" Googlemaps API Key for Localhost ERROR: Google Maps API error: MissingKeyMapError Google Maps API warning: NoApiKeys Google Maps JavaScript API RefererNotAllowedMapError This API project is not authorized to use this API. Please ensure that this API is activated in the APIs Console TypeError: window.initMap is not a function Google maps Marker Label with multiple characters Google Maps how to Show city or an Area outline How to use SVG markers in Google Maps API v3