Автозаполнение Google Адресов — выбрать первый результат при нажатии клавиши Enter?

Я использую автозаполнение Google Places и просто хочу, чтобы он выбирал верхний элемент в списке результатов, когда в поле формы нажата клавиша ввода и существуют предложения. Я знаю, что об этом уже спрашивали:

Автозаполнение Google Maps Places API V3 - выберите первый вариант при входе

Автозаполнение Google Maps Places API V3 - выберите первый вариант при входе (и пусть он останется таким)

Но ответы на эти вопросы, похоже, на самом деле не работают или касаются определенных дополнительных функций.

Также кажется, что что-то вроде следующего должно работать (но это не так):

$("input#autocomplete").keydown(function(e) {
  if (e.which == 13) {          
    //if there are suggestions...
    if ($(".pac-container .pac-item").length) {
      //click on the first item in the list or simulate a down arrow key event
      //it does get this far, but I can't find a way to actually select the item
      $(".pac-container .pac-item:first").click();
    } else {
      //there are no suggestions
    }
  }
});

Любые предложения будут ценны!


person NChase    schedule 30.01.2013    source источник
comment
Вам нужно будет использовать класс google.maps.places.AutocompleteService и прочитать AutocompletePrediction вручную: developers.google.com/maps/documentation/javascript/   -  person Marcelo    schedule 30.01.2013
comment
@Mubix принял ответ на второй вопрос, на который вы ссылались, охватывает то, что кажется необходимым, с добавлением некоторых дополнительных функций, которые можно легко удалить. В соответствии с этой демонстрацией я только что сделал ответвление из приведенного выше: jsfiddle.net/Ut2U4/1   -  person Craig Blagg    schedule 30.01.2013
comment
@CraigBlagg Спасибо! Я заставил это работать в конце концов. Не уверен, почему это не сработало с первого раза, но перестроение построчно дало желаемый результат!   -  person NChase    schedule 01.02.2013
comment
Здорово. Странно, это не сработало сразу (кажется, работает здесь). Но рад, что все получилось @NChase   -  person Craig Blagg    schedule 01.02.2013
comment
@CraigBlagg, в вашем образце (jsfiddle.net/Ut2U4/1) необходимо убедиться, что событие «нажатие клавиши» удаляется из документа при запуске «focusout» (строка 14). В противном случае вы прикрепляете его к документу каждый раз, когда ввод получает фокус.   -  person Nik Sumeiko    schedule 25.03.2013


Ответы (9)


Я много раз читал ответы на этот вопрос и ответы на связанные вопросы, прежде чем обнаружил, что лучший ответ - this one (Примечание: к сожалению, это не принятый ответ!).

Я изменил 2 или 3 строки, чтобы превратить ее в готовую к использованию функцию, которую можно скопировать/вставить в свой код и при необходимости применить ко многим input элементам. Вот:

var selectFirstOnEnter = function(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]); // add the modified listener
    }
    if (input.addEventListener) { 
        input.addEventListener = addEventListenerWrapper; 
    } else if (input.attachEvent) { 
        input.attachEvent = addEventListenerWrapper; 
    }
}

Использование:

selectFirstOnEnter(input1);
selectFirstOnEnter(input2);
...
person Basj    schedule 11.05.2016
comment
Это работает как шарм. Для этого требуется jQuery. Если вы используете Angular, как и я, вот небольшое руководство по его установке: medium.com/@swarnakishore/ - person Mladen; 21.06.2018
comment
также убедитесь, что вы вызываете функцию до var autocomplete = new google.maps.places.Autocomplete(input);, иначе она не будет работать - person woodii; 06.08.2018
comment
Хороший ответ, ужасно отформатированный код. Спасибо, в любом случае :) - person Derenir; 20.03.2019
comment
@Derenir исправлено! - person Basj; 29.05.2020

Я повторно публикую свой ответ из Google Maps Places API Автозаполнение V3 — выберите первый вариант при входе:

Кажется, есть гораздо лучшее и чистое решение: использовать google.maps.places.SearchBox вместо google.maps.places.Autocomplete. Код почти такой же, только получение первого из нескольких мест. При нажатии Enter возвращается правильный список - так что он работает из коробки и нет необходимости в хаках.

См. пример HTML-страницы:

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

Соответствующий фрагмент кода:

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);
  }
});

Полный исходный код примера находится по адресу: https://gist.github.com/klokan/8408394< /а>

person Klokan Technologies    schedule 13.01.2014
comment
SeachBox не позволяет фильтровать по (региону) или (городу) или любому типу, если уж на то пошло. - person metsfan; 28.05.2014
comment
Я проверил это, и это не работает, как ожидалось. SearchBox выполняет запрос автозаполнения при вводе, но когда вы нажимаете клавишу ввода, он выполняет запрос по адресу maps.googleapis.com/maps/api/js/PlaceService.QueryPlaces, используя введенную вами строку. Это может или не может вернуть фактические результаты. Например, при вводе naxo список автозаполнения возвращает в качестве первого результата Naxos ke Mikres Kyklades (может быть, это зависит от локали?). Нажатие ввода без выбора элемента списка возвращает 0 результатов. - person pkExec; 21.11.2014
comment
Поле поиска такое удобное. Я действительно хотел бы, чтобы это позволило мне ограничить результаты геокодированием или адресами. - person Adam Starrh; 14.09.2015
comment
но окно поиска отличается от автозаполнения. это больше для таких вещей, как кофе в Нью-Йорке - person user151496; 26.02.2016
comment
Я использую автозаполнение уже около года, и после прочтения этого и перехода на SearchBox все стало намного лучше. У меня была специальная функция getPlaceFromAutocompleteList в качестве обходного пути, но она исправляет несколько разочаровывающих ошибок в крайних случаях. Спасибо! - person Andy Mercer; 23.05.2017
comment
Больше не работает. Есть ли новый способ сделать это? - person theBugger; 16.04.2018
comment
Я настоятельно рекомендую вам выбрать виджет AutocompleteService вместо SearchBox. Особенно, если для вас важна цена. См. эту статью в блоге, чтобы понять различия: blog .woosmap.com/ - person Gael; 05.11.2019

Рабочее решение, которое прослушивает, начал ли пользователь перемещаться по списку с помощью клавиатуры, а не каждый раз запускает ложную навигацию.

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

Вот важные биты

// 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;
    }

});
person Callam    schedule 19.07.2017

На моем сайте для достижения той же функциональности мне понадобился подключаемый модуль имитации jQuery (https://github.com/jquery/jquery-simulate), а затем прикрепите событие:

$("input#autocomplete").focusin(function () {
    $(document).keypress(function (e) {
        if (e.which == 13) {
            $("input#autocomplete").trigger('focus');
            $("input#autocomplete").simulate('keydown', { keyCode: $.ui.keyCode.DOWN } ).simulate('keydown', { keyCode: $.ui.keyCode.ENTER });
        }
    });
});

Плагин имитирует действие нажатия клавиши DOWN, а затем ENTER, сам ENTER не работает, и я не нашел другого способа выбрать первый вариант.

Надеюсь это поможет

person Mangiucugna    schedule 26.07.2013
comment
Это не работает в ситуациях, когда вы перемещаетесь с помощью клавиш со стрелками и выбираете его, нажимая клавишу ввода. - person dnlmzw; 26.02.2015
comment
@dnlmzw, если вы перемещаетесь с помощью клавиш со стрелками и выбираете его с помощью ввода, вы запускаете place_change ... - person user151496; 26.02.2016
comment
@user151496 user151496 это правда, но это не сработает, если ваше поле является полем <form>, тогда вы должны сделать e.preventDefault(); при вводе (13/$.ui.keyCode.ENTER)keydown, если вы этого не сделаете, ответ на запрос, вероятно, не вернется вовремя :) - person jave.web; 20.06.2016
comment
Это отлично сработало для меня после нескольких часов поиска и попыток взломать подобные решения. - person Antony D'Andrea; 24.07.2018

Это самый простой способ, который решил для меня:

autocomplete.addListener('place_changed', function() {
  if(event.keyCode == 13 || event.keyCode == 9) { // detect the enter key
    var firstValue = $(".pac-container .pac-item:first").text(); // assign to this variable the first string from the autocomplete dropdown
     }
    $('#search-address').val(firstValue); // add this string to input
    console.log(firstValue); // display the string on your browser console to check what it is
   //(...) add the rest of your code here
  });
}
person Fillype Farias    schedule 22.02.2018
comment
Я изменил вышеуказанную функцию, и она работает для меня как шарм. // листнер, чтобы сделать kepdown равным true и выбрать первый результат поиска this.searchElementRef.nativeElement.addEventListener('keydown', (e) =› { if (e.keyCode === 13 || e.keyCode === 9) { var firstValue = $('.pac-container .pac-item:first').text(); // Если пользователь не использует стрелки и это еще не запущено this.txtValue = firstValue; google.maps .event.trigger(e.target, 'keydown', {keyCode: 40, hasRanOnce: true, }); } }); - person Uttam; 26.10.2020

Это то, что я сделал, и это работает:

HTML:

<input name="location" id="autocomplete" autocomplete="off" type="text" class="textbx" placeholder="Enter Destination" required>

googleautocompletecustomized.js:

        function initialize() {
      // Create the autocomplete object, restricting the search
      // to geographical location types.
      if($('#autocomplete').length){
          autocomplete = new google.maps.places.Autocomplete(
              (document.getElementById('autocomplete')),
              {
                types: ['(regions)'],
                componentRestrictions: {country: "in"}
              });
          google.maps.event.addListener(autocomplete, 'place_changed', function() {
            $('#autocomplete').closest('form').data('changed', true);
            fillInAddress();
          });         
      }

    //select first result
        $('#autocomplete').keydown(function (e) {
            if (e.keyCode == 13 || e.keyCode == 9) {
                $(e.target).blur();
                if($(".pac-container .pac-item:first span:eq(3)").text() == "")
                    var firstResult = $(".pac-container .pac-item:first .pac-item-query").text();
                else
                    var firstResult = $(".pac-container .pac-item:first .pac-item-query").text() + ", " + $(".pac-container .pac-item:first span:eq(3)").text();

                var geocoder = new google.maps.Geocoder();
                geocoder.geocode({"address":firstResult }, function(results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        placeName = results[0];
                        e.target.value = firstResult;
                        fillInAddress(placeName);
                        $('#datetimepicker1 .input-group-addon').click();
                    }
                });
            }

        });
    }

// [START region_fillform]
function fillInAddress(place) {
  // Get the place details from the autocomplete object.
  if(!place)
    var place = autocomplete.getPlace();

  for (var component in componentForm) {
    document.getElementById(component).value = '';
    document.getElementById(component).disabled = false;
  }

  // Get each component of the address from the place details
  // and fill the corresponding field on the form.
  for (var i = 0; i < place.address_components.length; i++) {
    var addressType = place.address_components[i].types[0];
    if (componentForm[addressType]) {
      var val = place.address_components[i][componentForm[addressType]];
      document.getElementById(addressType).value = val;

    }
  }

}
person Fronto    schedule 07.03.2016

Если вы используете Angular 2,4, 5 и 6, найдите ответ по этой ссылке ниже.

Angular 6, AGM выбирает первый адрес в автозаполнении Google< /а>

Предложение автозаполнения Angular AGM по первому адресу

person saravana va    schedule 09.08.2018

Поместите элемент ввода вне элемента формы. Заполните форму javascript.

document.getElementById("adress").value = place.formatted_address;
person Gustav    schedule 03.12.2013

Я немного поработал над этим, и теперь я могу принудительно выбрать 1-й вариант из Google Places, используя angular js и угловой модуль автозаполнения.
Благодаря kuhnza
мой код

<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>

Вот Plunker
Спасибо.

person Murali    schedule 26.07.2015