Javascript Google Places Autocomplete - 按 Enter 键选择第一个结果?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14601655/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 17:21:36  来源:igfitidea点击:

Google Places Autocomplete - Pick first result on Enter key?

javascriptgoogle-mapsgoogle-maps-api-3google-places-apigoogle-places

提问by NChase

I'm using a Google Places Autocomplete and I simply want it to select the top item in the results list when the enter key is pressed in the form field and suggestions exist. I know this has been asked before:

我正在使用 Google Places 自动完成功能,我只是希望它在表单字段中按下 Enter 键并且存在建议时选择结果列表中的顶部项目。我知道以前有人问过这个问题:

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

Google 地图 Places API V3 自动完成 - 在输入时选择第一个选项

Google maps Places API V3 autocomplete - select first option on enter (and have it stay that way)

Google 地图 Places API V3 自动完成 - 在输入时选择第一个选项(并保持这种状态)

But the answers in those questions don't seem to actually work, or they address specific added functionality.

但这些问题的答案似乎并没有真正起作用,或者它们解决了特定的附加功能。

It also seems like something like the following should work (but it doesn't):

似乎以下内容也应该起作用(但不起作用):

$("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
    }
  }
});

Any suggestions would be greatly appreciated!

任何建议将不胜感激!

回答by Basj

I've read the many answers of this question, and of the linked questions' answers so many times, before finding that the best answer is this one(Nota: sadly, it's not the accepted answer!).

我已经阅读了这个问题的许多答案以及链接问题的答案很多次,然后才发现最好的答案是这个(注意:遗憾的是,这不是公认的答案!)。

I've modified 2 or 3 lines to turn it into a ready-to-use function that you can copy/paste in your codeand apply to many inputelements if needed. Here it is:

我修改了 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; 
    }
}

Usage:

用法:

selectFirstOnEnter(input1);
selectFirstOnEnter(input2);
...

回答by Klokan Technologies

I am reposting my answer from Google maps Places API V3 autocomplete - select first option on enter:

我正在从Google 地图 Places API V3 自动完成重新发布我的答案- 在输入时选择第一个选项

It seems there is a much better and clean solution: To use google.maps.places.SearchBoxinstead 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.

似乎有一个更好更干净的解决方案:使用google.maps.places.SearchBox代替google.maps.places.Autocomplete. 代码几乎相同,只是从多个地方获取第一个。在按 Enter 时,将返回正确的列表 - 因此它开箱即用,无需进行黑客攻击。

See the example HTML page:

请参阅示例 HTML 页面:

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

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

示例的完整源代码位于:https: //gist.github.com/klokan/8408394

回答by Mangiucugna

In my site to achieve this same functionality I neeeded the jQuery simulate plugin (https://github.com/jquery/jquery-simulate) and then attach the event:

在我的网站中,为了实现相同的功能,我需要 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 });
        }
    });
});

The plugin will simulate the action of press the key DOWN and then ENTER, ENTER itself does not work and I couldn't find another way to select the first option.

该插件将模拟按 DOWN 然后按 ENTER 键的动作,ENTER 本身不起作用,我找不到另一种选择第一个选项的方法。

Hope this helps

希望这可以帮助

回答by Callam

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

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

});

回答by Fillype Farias

This is the easiest way that solved to me:

这是解决我的最简单方法:

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

回答by Fronto

This is what I've done and it works:

这就是我所做的并且它有效:

HTML:

HTML:

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

googleautocompletecustomized.js:

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;

    }
  }

}

回答by saravana va

If you are using the Angular 2,4, 5 & 6, Please find the answer in this below link

如果您使用的是Angular 2,4, 5 & 6,请在下面的链接中找到答案

Angular 6, AGM selects first address in google autocomplete

Angular 6,AGM 在谷歌自动完成中选择第一个地址

Angular AGM autocomplete first address suggestion

Angular AGM 自动完成第一个地址建议

回答by Gustav

Put the input-element outside the form-element. Populate the form with javascript.

将输入元素放在表单元素之外。使用 javascript 填充表单。

document.getElementById("adress").value = place.formatted_address;

回答by Murali

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

我为此做了一些工作,现在我可以使用 angular js 和 angular Autocomplete 模块从 google 地方强制选择第一个选项。
感谢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>

Here is a Plunker
Thank you.

这是一个Plunker
谢谢。