【问题标题】:Find when google places autocomplete returns zero results查找谷歌位置自动完成返回零结果的时间
【发布时间】:2012-05-13 21:50:01
【问题描述】:

我使用 google 地方自动完成功能来提供地方建议。现在这就是我想要的:当用户键入不在谷歌数据库中的位置时,即谷歌返回零结果,我需要能够捕获零结果事件,并触发我的客户自动完成。

当谷歌返回零结果时,我如何找到?如果结果为零,autocomplete.getPlace() 将返回一个状态,但这是在 place_changed 事件中,仅当用户从下拉列表中选择建议时才会触发。如何让它在 place_changed 事件之外工作?

这是我使用的代码,请根据此提出建议:

autocomplete = new google.maps.places.Autocomplete(input,options);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
   var place = autocomplete.getPlace();
   document.getElementById('place_name').value = place.name;
   document.getElementById('location_lat').value = place.geometry.location.lat();
   document.getElementById('location_lon').value = place.geometry.location.lng();
   document.getElementById('location_add').value = place.formatted_address;
   $('#locationInput').attr('title', place.formatted_address);
});

【问题讨论】:

    标签: google-maps-api-3 google-places-api


    【解决方案1】:

    发现了一个窍门,

    AutoComplete由输入节点的keyup事件触发,则:

    如果没有结果,则隐藏结果下拉列表display: none;

    如果有结果,则通过清除display 样式显示结果下拉列表

    您可以通过document.getElementsByClassName('pac-container')[0] (native) 或$('.pac-container') (jQuery) 获取下拉列表

    所以只需将下拉列表的display 设置为“阻止”,然后跟踪它以检测结果状态。

    google official sample修改的简单示例:

    <!DOCTYPE html>
    <html>
        <head>
            <title>Google Maps JavaScript API v3 Example: Places Autocomplete</title>
            <script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"
                type="text/javascript"></script>
    
            <style type="text/css">
                body {
                    font-family: sans-serif;
                    font-size: 14px;
                }
                #map_canvas {
                    height: 400px;
                    width: 600px;
                    margin-top: 0.6em;
                }
            </style>
    
            <script type="text/javascript">
                var ns = {}; // a name space
                ns.checktimes = 0; // a couter of check times
                // the check function
                // @param dropdown: the drop-down list of Places.AutoComplete
                // @param msg: the div to show message
                ns._doCheck = function (dropdown, msg) {
                    if (dropdown.style.display == '') {
                        msg.innerHTML = 'has results? true';
                        ns.checkTimer = null;
                    }
                    else if (dropdown.style.display == 'none') {
                        msg.innerHTML = 'has results? false';
                        ns.checkTimer = null;
                    } else if (ns.checktimes < 20) { // check at most 10 seconds
                        ns.checktimes++;
                        ns.checkTimer = setTimeout(function () {
                            ns._doCheck(dropdown, msg);
                        }, 500);
                    }
                }
                function initialize() {
                    var mapOptions = {
                        center: new google.maps.LatLng(-33.8688, 151.2195),
                        zoom: 13,
                        mapTypeId: google.maps.MapTypeId.ROADMAP
                    };
                var map = new google.maps.Map(document.getElementById('map_canvas'),
                    mapOptions);
    
                var input = document.getElementById('searchTextField');
                var autocomplete = new google.maps.places.Autocomplete(input);
    
                autocomplete.bindTo('bounds', map);
    
                var infowindow = new google.maps.InfoWindow();
                var marker = new google.maps.Marker({
                    map: map
                });
    
                google.maps.event.addListener(autocomplete, 'place_changed', function() {
                    infowindow.close();
                    var place = autocomplete.getPlace();
                if (place.geometry.viewport) {
                    map.fitBounds(place.geometry.viewport);
                } else {
                    map.setCenter(place.geometry.location);
                    map.setZoom(17);  // Why 17? Because it looks good.
                }
    
                var image = new google.maps.MarkerImage(
                    place.icon,
                    new google.maps.Size(71, 71),
                    new google.maps.Point(0, 0),
                    new google.maps.Point(17, 34),
                    new google.maps.Size(35, 35));
                marker.setIcon(image);
                marker.setPosition(place.geometry.location);
    
                var address = '';
                if (place.address_components) {
                    address = [(place.address_components[0] &&
                    place.address_components[0].short_name || ''),
                    (place.address_components[1] &&
                    place.address_components[1].short_name || ''),
                    (place.address_components[2] &&
                    place.address_components[2].short_name || '')
                    ].join(' ');
                }
    
                infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
                infowindow.open(map, marker);
                // update stored value
                ns.oldValue = document.getElementById('searchTextField').value;
            });
    
            // Sets a listener on a radio button to change the filter type on Places
            // Autocomplete.
            function setupClickListener(id, types) {
                var radioButton = document.getElementById(id);
                google.maps.event.addDomListener(radioButton, 'click', function() {
                autocomplete.setTypes(types);
                });
            }
    
            setupClickListener('changetype-all', []);
            setupClickListener('changetype-establishment', ['establishment']);
            setupClickListener('changetype-geocode', ['geocode']);
            }
    
            // to check whether responsee and has results
            function startCheck () {
                // the input node
                var inp = document.getElementById('searchTextField'),
                    value = inp.value; // value of input node
                if (value && ns.oldValue != value) { // has value and changed, start check
                    // drop-down list and message div
                    var dropdown = document.getElementsByClassName('pac-container')[0],
                        msg = document.getElementById('msg');
                    // trick! change style to display='block'
                    dropdown.style.display = 'block';
                    // update stored value
                    ns.oldValue = value;
                    // initiate checktimes
                    ns.checktimes = 0;
                    // clear previous timer if exists
                    if (ns.checkTimer)
                        clearTimeout (ns.checkTimer);
                    ns.checkTimer = setTimeout(function () {
                        ns._doCheck(dropdown, msg);
                    }, 500);
                }
            }
            google.maps.event.addDomListener(window, 'load', initialize);
        </script>
        </head>
        <body>
            <div>
                <div id="msg">has results? </div>
                <input id="searchTextField" type="text" size="50" onkeyup="startCheck();">
                <input type="radio" name="type" id="changetype-all" checked="checked">
                <label for="changetype-all">All</label>
    
                <input type="radio" name="type" id="changetype-establishment">
                <label for="changetype-establishment">Establishments</label>
    
                <input type="radio" name="type" id="changetype-geocode">
                <label for="changetype-geocode">Geocodes</lable>
            </div>
            <div id="map_canvas"></div>
        </body>
    </html>
    

    【讨论】:

      【解决方案2】:

      我认为您的情况可能与 Google 返回零结果不同。您的问题中的一个假设是,place_changed 事件“仅在 [the] 用户从下拉列表中选择建议时触发”是不正确的。来自google.maps.places.Autocompleteplace_changedEvent 文档:

      当 PlaceResult 可用于 Place 时会触发此事件 用户已选择。 如果用户输入一个地点的名称, 没有被控制建议并按下 Enter 键,a 将触发包含用户输入的 place_changed 事件 name 属性,没有定义其他属性。

      否则,Google 应该会向您返回结果,因为用户选择了自动完成下拉选项中的结果之一。如果直接用户输入不是驱动您的方案的原因,那么检查零结果是否应该只涉及检查 google.maps.places.PlaceResult 属性的一个、部分或子集,例如:

      • address_componentsgoogle.maps.GeocoderAddressComponents 的数组
      • id
      • name
      • reference
      • types 字符串数组(例如,[politicallocality] 或 [restaurantestablishment])

      【讨论】:

        【解决方案3】:

        您也可以通过这种方式获得结果。预测是谷歌地图返回的数组。

        const displaySuggestions = (predictions, status) => {
              if (status !== google.maps.places.PlacesServiceStatus.OK) {
                if (status === 'ZERO_RESULTS') {
                  alert('zero results found')
                }
                return;
              }
            };
            // you can create autocompleteService as variable outside the function as well
            const autocompleteService = new google.maps.places.AutocompleteService();
            // input is string of what user types 
            autocompleteService.getPlacePredictions({ input: input, types: ['address'] }, displaySuggestions);
        

        【讨论】:

          【解决方案4】:

          您可以通过简单的方式获得零结果(输入 onChange 事件):

          const _handleChange = (event, value) => {
              setTimeout(() => {
                  const dropdownList = document.getElementsByClassName('pac-container')[0];
                  if (dropdownList.childElementCount === 0) {
                      // Zero results
                  } else {
                      // Has results
                  }
                  console.log('child count:', dropdownList.childElementCount);
              }, 100);
          };
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-02-12
            • 2013-03-09
            • 2012-02-20
            • 2018-06-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多