我已经按照http://web.archive.org/web/20120225114154/http://code.google.com:80/intl/sk-SK/apis/在我的输入框中成功实现了 Google Maps Places V3 自动完成功能地图/文档/javascript/places.html。它工作得很好,但是我很想知道如何让它在用户按下 Enter 键时从建议中选择第一个选项。我想我需要一些 JS 魔法,但我对 JS 很陌生,不知道从哪里开始。
提前致谢!
我已经按照http://web.archive.org/web/20120225114154/http://code.google.com:80/intl/sk-SK/apis/在我的输入框中成功实现了 Google Maps Places V3 自动完成功能地图/文档/javascript/places.html。它工作得很好,但是我很想知道如何让它在用户按下 Enter 键时从建议中选择第一个选项。我想我需要一些 JS 魔法,但我对 JS 很陌生,不知道从哪里开始。
提前致谢!
这是一个不发出可能返回错误结果的地理编码请求的解决方案:http : //jsfiddle.net/amirnissim/2D6HW/
down-arrow
每当用户return
在自动完成字段内点击时,它都会模拟按键。该↓事件在return事件之前触发,因此它模拟用户使用键盘选择第一个建议。
这是代码(在 Chrome 和 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>
在我最近工作的网站上实现自动完成时,我遇到了同样的问题。这是我想出的解决方案:
$("input").focusin(function () {
$(document).keypress(function (e) {
if (e.which == 13) {
var firstResult = $(".pac-container .pac-item:first").text();
var geocoder = new google.maps.Geocoder();
geocoder.geocode({"address":firstResult }, 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);
$(".pac-container .pac-item:first").addClass("pac-selected");
$(".pac-container").css("display","none");
$("#searchTextField").val(firstResult);
$(".pac-container").css("visibility","hidden");
moveMarker(placeName, latlng);
}
});
} else {
$(".pac-container").css("visibility","visible");
}
});
});
2020 年的有效答案。
我结合了这个页面上的最佳答案,并用简单的 ES6 编写。不需要 jQuery、第二个 API 请求或 IIFE。
基本上,down-arrow
每当用户在自动完成字段内点击返回时,我们都会模拟 ↓ ( ) 按键。
首先,假设在你的 HTML 中你有类似的东西,像这样<input id="address-field">
设置你的地址字段的标识:
const field = document.getElementById('address-field')
const autoComplete = new google.maps.places.Autocomplete(field)
autoComplete.setTypes(['address'])
然后在下一行添加:
enableEnterKey(field)
然后在脚本的其他地方,如果您愿意,要在代码中保持此功能分开,请添加函数:
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
}
你应该很高兴去。本质上,该函数会捕获input
字段中的每个按键,如果是enter
,则模拟down-arrow
按键。它还存储和重新绑定侦听器和事件以维护您的 Google 地图的所有功能Autocomplete()
。
感谢之前对大部分代码的回答,特别是 amirnissim 和 Alexander Schwarzman。
这是一个真实的、非 hacky 的解决方案的例子。它不使用任何浏览器黑客等,只是来自 Google 提供的公共 API 的方法,并在此处记录:Google Maps API
唯一的缺点是,如果用户未从列表中选择项目,则需要向 Google 提出额外请求。好处是结果总是正确的,因为查询的执行方式与 AutoComplete 中的查询相同。第二个好处是,通过只使用公共 API 方法而不依赖于 AutoComplete 小部件的内部 HTML 结构,我们可以确保如果 Google 进行更改,我们的产品不会损坏。
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);
}
});
似乎有一个更好更干净的解决方案:使用google.maps.places.SearchBox
代替google.maps.places.Autocomplete
. 代码几乎相同,只是从多个地方获取第一个。在按 Enter 时,将返回正确的列表 - 因此它开箱即用,不需要黑客攻击。
请参阅示例 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