Dan*_*ezo 68 javascript google-maps autocomplete google-maps-api-3
根据http://code.google.com/intl/sk-SK/apis/maps/documentation/javascript/places.html#places_autocomplete,我已成功在输入框中实施了Google Maps Places V3自动填充功能.它工作得很好,但我很想知道如何在用户按下回车时从建议中选择第一个选项.我想我需要一些JS魔法,但我对JS很新,不知道从哪里开始.
提前致谢!
ami*_*sim 163
这是一个解决方案,不会产生可能返回错误结果的地理编码请求: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>
Run Code Online (Sandbox Code Playgroud)
小智 44
在我最近工作的网站上实现自动完成时,我遇到了同样的问题.这是我提出的解决方案:
$("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");
}
});
});
Run Code Online (Sandbox Code Playgroud)
http://jsfiddle.net/dodger/pbbhH/
小智 21
这是一个真实的,非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);
}
});
Run Code Online (Sandbox Code Playgroud)
Ton*_*nas 20
这是2018年的工作答案.
这结合了这个页面上的最佳答案,只使用纯JS,并用简单的ES6编写.不需要jQuery,第二个API请求或IIFE.
首先,假设您已经设置了类似的内容来识别您的地址字段:
const field = document.getElementById('address-field')
const autoComplete = new google.maps.places.Autocomplete(field)
autoComplete.setTypes(['address'])
Run Code Online (Sandbox Code Playgroud)
然后在下一行添加:
enableEnterKey(field)
Run Code Online (Sandbox Code Playgroud)
然后在您的脚本中的其他地方,为了保持此功能在代码中保持良好且独立,请添加以下内容:
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 = JSON.parse(JSON.stringify(event))
e.key = 'ArrowDown'
e.code = 'ArrowDown'
_listener.apply(input, [e])
}
_listener.apply(input, [event])
}
}
_addEventListener.apply(input, [type, listener])
}
input.addEventListener = addEventListenerWrapper
}
Run Code Online (Sandbox Code Playgroud)
你应该好好去.本质上,该down-arrow功能捕获input字段中的每个返回/输入按键,并模拟向下箭头按键.它还存储和重新绑定侦听器和事件,以维护您的Google地图的所有功能enter.
明显感谢大多数代码的早期答案,特别是amirnissim和Alexander Schwarzman.
Klo*_*ies 12
似乎有一个更好,更干净的解决方案:使用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);
}
});
Run Code Online (Sandbox Code Playgroud)
该示例的完整源代码位于:https://gist.github.com/klokan/8408394
对于Google Places Autocomplete V3,最佳解决方案是两个API请求.
这是小提琴
之所以没有其他答案足够的原因是因为他们要么使用jquery来模仿事件(hacky),要么使用Geocoder或Google Places Search框,它们并不总是匹配自动完成结果.相反,我们要做的是使用谷歌的自动完成服务,这里只详细说明javascript(没有jquery)
下面详细介绍了使用本机Google API生成自动填充框的最交叉浏览器兼容解决方案,然后重新运行查询以选择第一个选项.
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places&language=en"></script>
Run Code Online (Sandbox Code Playgroud)
使用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 ***** //
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
唯一的抱怨是本机实现返回不同的数据结构,尽管信息是相同的.相应调整.