Google商家信息自动填充强制选择

时间:2013-02-01 18:13:17

标签: javascript ajax google-places-api

我使用的是Google自动填充API v3。它工作正常,但我想知道是否有办法强制从自动完成选择,即输入不接受任何自由格式文本。我查看了文档并没有看到这样的选项,但我想我会要求安全。我确信我可以通过一些JavaScript来解决这个问题,但是如果可用的话,我更愿意使用已经构建的方法。谢谢!

14 个答案:

答案 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&amp;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()事件来强制最后选择的地址。

我们添加了一个超时,以防止blurplace_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)

WTF,人们?!?!? Google通常没有正确的信息。不要使用自动完成API进行强制选择!这就是为什么大量的网站不允许我使用他们的服务:我住在谷歌搞砸地址的地方。而且我并不孤单。

如果必须,请使用USPS地址验证 - 至少它们是最新的。理想情况下允许自动完成但允许手动覆盖;停止懒惰,让我们这么多人生活困难!