我使用的是Google自动填充API v3。它工作正常,但我想知道是否有办法强制从自动完成选择,即输入不接受任何自由格式文本。我查看了文档并没有看到这样的选项,但我想我会要求安全。我确信我可以通过一些JavaScript来解决这个问题,但是如果可用的话,我更愿意使用已经构建的方法。谢谢!
答案 0 :(得分:13)
实际上,我们做了以下几点:
- 每次从“自动完成”列表中选择一个位置时,我们会填充一些隐藏字段,其中一些字段来自JSON响应(城市名称,国家/地区名称,经度和纬度)
- 提交表单时,我们检查这些字段是否有值,如果不是,则表示用户不是从列表中选择位置,而是自己输入值。
它不能以JS的方式解决问题,但是,它仍然可以解决问题!
答案 1 :(得分:8)
Google Places API目前不支持此功能。如果您认为这是一项有用的功能,请提交Places API - Feature Request。
答案 2 :(得分:6)
<script src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"
type="text/javascript"></script>
<script>
var IsplaceChange = false;
$(document).ready(function () {
var input = document.getElementById('txtlocation');
var autocomplete = new google.maps.places.Autocomplete(input, { types: ['(cities)'] });
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var place = autocomplete.getPlace();
IsplaceChange = true;
});
$("#txtlocation").keydown(function () {
IsplaceChange = false;
});
$("#btnsubmit").click(function () {
if (IsplaceChange == false) {
$("#txtlocation").val('');
alert("please Enter valid location");
}
else {
alert($("#txtlocation").val());
}
});
});
</script>
答案 3 :(得分:1)
以下解决方案为我(用jQuery)解决了问题。想法是一旦输入失去焦点,就使用blur()
事件来强制最后选择的地址。
我们添加了一个超时,以防止blur
和place_changed
事件之间发生冲突。
考虑以下html:
<input type="text" placeholder="Your address" id="autocomplete">
以及以下javascript:
var autocomplete = new google.maps.places.Autocomplete(
(document.getElementById('autocomplete')),
{types: ['geocode']});
autocomplete.addListener('place_changed', fillInAddress);
var currentAddress = {
line_1: "",
line_2: "",
zipcode: "",
city: "",
country: "",
lat: "",
lng: "",
one_liner: ""
};
function fillInAddress() {
var place = this.autocomplete.getPlace();
// reset the address
currentAddress = {
line_1: "",
line_2: "",
zipcode: "",
city: "",
country: "",
lat: "",
lng: "",
one_liner: place.formatted_address
};
// store relevant info in currentAddress
var results = place.address_components.reduce(function(prev, current) {
prev[current.types[0]] = current['long_name'];
return prev;
}, {})
if (results.hasOwnProperty('route')) {
currentAddress.line_1 = results.route;
}
if (results.hasOwnProperty('street_number')) {
currentAddress.line_1 = results.street_number + " " + currentAddress.line_1;
}
if (results.hasOwnProperty('postal_code')) {
currentAddress.zipcode = results.postal_code;
}
if (results.hasOwnProperty('locality')) {
currentAddress.city = results.locality;
}
if (results.hasOwnProperty('country')) {
currentAddress.country = results.country;
}
currentAddress.lat = Number(place.geometry.location.lat()).toFixed(6);
currentAddress.lng = Number(place.geometry.location.lng()).toFixed(6);
}
$('#autocomplete').blur(function() {
var address = $('#autocomplete').val();
// we set a timeout to prevent conflicts between blur and place_changed events
var timeout = setTimeout(function() {
// release timeout
clearTimeout(timeout);
if (address !== currentAddress.one_liner) {
$('#autocomplete').val(currentAddress.one_liner);
}
}, 500);
});
我希望这会有所帮助。
答案 4 :(得分:0)
我遇到了同样的问题,下面是一个我想出来的功能。这可以与诸如onchange或onkeyup之类的事件结合使用。希望它有所帮助!
//Arguments:
address - string containing the place that you want to validate
address_success_div - div object specifically used for displaying validation
function is_location_valid(address, address_success_div)
{
var geocoder = new google.maps.Geocoder();
geocoder.geocode( {"address": address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK)
{
address_success_div.innerHTML = "SUCCESS";
}
else
{
address_success_div.innerHTML = "FAILURE";
}
});
}
答案 5 :(得分:0)
var options = {
language: 'en',
types: ['(cities)'],
};
var input = document.getElementById('city');
var autocomplete = new google.maps.places.Autocomplete(input, options);
input.addEventListener("change", function(){
input.value = "";
});
在输入更改时退出值对我有用。它会强制使用Google地方信息。
答案 6 :(得分:0)
我使用发现的here
代码解决了我的问题
<asp:TextBox runat="server" ID="TextBox1" />
<input type="button" id="btnSubmit" name="name" value="Validate" />
<div id="dvMap">
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places&key=AIzaSyBE1J5Pe_GZXBR_x9TXOv6TU5vtCSmEPW4"></script>
<script type="text/javascript">
var isPlaceChanged = false;
google.maps.event.addDomListener(window, 'load', function () {
var places = new google.maps.places.Autocomplete(document.getElementById('<%= TextBox1.ClientID %>'));
google.maps.event.addListener(places, 'place_changed', function () {
isPlaceChanged = true;
var geocoder = new google.maps.Geocoder();
var place = places.getPlace();
var address = place.formatted_address;
geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
var mapOptions = { center: new google.maps.LatLng(latitude, longitude), zoom: 15, mapTypeId: google.maps.MapTypeId.ROADMAP };
var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
var marker = new google.maps.Marker({ position: new google.maps.LatLng(latitude, longitude), map: map });
} else {
alert("Request failed.")
}
});
});
});
$(function () {
$("#TextBox1").keydown(function () {
isPlaceChanged = false;
});
$("#btnSubmit").click(function () {
if (!isPlaceChanged) {
$("#TextBox1").val('');
alert("Please Enter valid location");
}
else {
alert($("#TextBox1").val());
}
});
});
</script>
答案 7 :(得分:0)
您可以使用输入模式标记,强制用户根据Google Autocomplete API选择一个预定值。
输入:
<form>
<input type="text" onkeyup="changePatterns()" onchange="changePatterns()" id="autocomplete" required pattern="">
<input type="submit">
</form>
JS文件:
function changePatterns() {
let input = document.getElementById('autocomplete').value;
let regExp = new RegExp(' ', 'g');
input = input.replace(regExp, '%20');
let mapsURL = 'https://maps.googleapis.com/maps/api/place/autocomplete/json'
mapsURL += '?types=geocode';
mapsURL += '&key=YOUR-KEY-HERE';
mapsURL += `&input=${input}`;
const endpoint = 'middle.php';
let formData = new FormData();
formData.append('url', mapsURL);
fetch(endpoint, {
method: 'post',
body: formData
})
.then(blob => blob.json())
.then(response => {
const predictions = response.predictions;
let {length} = predictions;
let pattern = '';
for(let i = 0; i < length; i++){
pattern += i == 0 ? '' : '|';
pattern += predictions[i].description
}
const input = document.getElementById('autocomplete');
input.setAttribute('pattern', pattern);
});
}
由于CORS政策存在问题,我不得不使用php中间件:
<?php
header('Content-Type: application/json');
$url = $_POST['url'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //remove on upload
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, false);
curl_setopt($ch, CURLOPT_REFERER, "https://www.notmydomain.com");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$result = curl_exec($ch);
echo curl_error($ch);
curl_close($ch);
echo $result;
答案 8 :(得分:0)
就像他们提到的那样, Google Autocomplete API 不支持该功能。 我找到了一种方法,可以通过创建一个隐藏元素来存储选定位置,然后检查它是否等于自动完成输入,来使其工作。
/*----------------------------------------------------*/
/* check if it's valid address
/*----------------------------------------------------*/
function checkAddress(location, validLocation) {
if (location.val() == validLocation.val()) {
return true;
}
return false;
}
/*----------------------------------------------------*/
/* initialize auto complete address
/*----------------------------------------------------*/
function initialize() {
let input = document.getElementById('autocomplete-input');
let inputHidden = document.getElementById('autocomplete-input-hidden');
let options = {
types: ['(regions)'],
componentRestrictions: {country: "tn"}
};
let autocomplete =new google.maps.places.Autocomplete(input, options);
autocomplete.setFields(['formatted_address']);
autocomplete.addListener('place_changed', function () {
inputHidden.value= autocomplete.getPlace().formatted_address;
});
}
调用主函数。
let location = $('#autocomplete-input');
let validLocation = $('#autocomplete-input-hidden');
checkAddress(location,validLocation);
并在您的html中:
<input id="autocomplete-input" type="text">
<input id="autocomplete-input-hidden" type="hidden" >
答案 9 :(得分:0)
我找到了一个使用jquery验证插件实现的更简单的解决方案,但这不是必须的。我只是使用一个类名作为标志来显示该字段是有效的(即用户从Google进行选择)还是无效的(即他们键入了自己的东西)。 我创建了两个函数,一个添加了“ err”类,另一个删除了它。
function invalidate(element_id){
$('#' + element_id).addClass('err');
}
function makeValid(element_id){
if ($('#' + element_id).hasClass('err')){
$('#' + element_id).removeClass('err');
}
$('#' + element_id).valid(); //this is a method from jquery validation plugin to check validity of a field
}
然后,在onkeydown上,我调用了“ invalidate”函数来标记输入元素已经输入。
document.getElementById("element_id").setAttribute('onkeydown', "invalidate('element_id')");
在Google Autocomplete API的末尾(我在fillInAddress方法的末尾做到了这一点),我调用了“ makeValid”来删除该标志,因为用户刚刚从下拉菜单中选择了一个选项。
makeValid(userElementId);
最后,我验证了当用户键入而不选择选项时用作标志的“ err”类不存在。在这里,我使用了jQuery验证插件,但是如果需要,您可以使用其他东西。
jQuery.validator.addMethod("hasClassErr", function(value, element) {
return this.optional( element ) || !element.classList.contains("err");
}, jQuery.validator.format("Please choose an option from the dropdown menu."));
FORM_RULES = {
element_name: {required: true, 'hasClassErr': true}
};
$('#form_id').validate({
rules: FORM_RULES
});
答案 10 :(得分:-1)
我从Google地方信息示例中修改了一些代码。
<input type="text" id="address" onchange="check();" required>
function check() {
console.log("check");
try {
var place = autocomplete.getPlace();
console.log(place);
if (!place.geometry) {
// User entered the name of a Place that was not suggested and
// pressed the Enter key, or the Place Details request failed.
window.alert("Please enter address suggested by google");
return;
}
} catch (err) {
window.alert("Please enter address suggested by google");
}
}
答案 11 :(得分:-2)
Hia的 我设法通过每次用户对输入字段进行聚焦时创建自动完成对象,并在每次用户模糊时检查它的值:
var autocompleteField;
var input = document.getElementById('YOUR_INPUT');
$('#YOUR_INPUT').focus(function(e){
if(autocompleteField){
autocompleteField=null;
}
autocompleteField = new google.maps.places.Autocomplete(input);
});
$('#YOUR_INPUT').blur(function(e){
var results = autocompleteField.getPlace();
if(!results){
$(this).attr('value','');
}
});
答案 12 :(得分:-2)
我解决了从这里结合几个不同答案的建议的问题。用户输入地址的我的文本字段称为txtPlaces。这是我的代码:
var pac_input = document.getElementById('txtPlaces');
(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 || event.which == 9) && !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);
$('#txtPlaces').blur(function(e){
selectFirstAddress(pac_input);
});
////Ensuring that only Google Maps adresses are inputted
function selectFirstAddress (input) {
google.maps.event.trigger(input, 'keydown', {keyCode:40});
google.maps.event.trigger(input, 'keydown', {keyCode:13});
}
这将对Enter键或Tab键以及用户选择其他字段时做出正确反应。希望这有帮助!
答案 13 :(得分:-6)
如果必须,请使用USPS地址验证 - 至少它们是最新的。理想情况下允许自动完成但允许手动覆盖;停止懒惰,让我们这么多人生活困难!