Find when google places autocomplete returns zero results
Found a trick,
AutoComplete
triggered by keyup
event of input node, then:
Hide result dropdown list by display: none;
if no result
or
Show result dropdown list by clear display
style if has result
You can get dropdown list by document.getElementsByClassName('pac-container')[0]
(native) or $('.pac-container')
(jQuery)
So just set the display
of dropdown list to 'block' then tracking it to detect the result status.
A simple sample modified from the 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>
I think your scenario may be different than Google returning zero results. One of the assumptions in your question, that the place_changed
event "is fired only when [the] user selects a suggestion from the dropdown list," is not correct. From the google.maps.places.Autocomplete
class Event docs for place_changed
:
This event is fired when a PlaceResult is made available for a Place the user has selected. If the user enters the name of a Place that was not suggested by the control and presses the Enter key, a place_changed event will be fired that contains the user input in the name property, with no other properties defined.
Otherwise, Google should be returning you results, because the user has selected one of the results that was in the Autocomplete's dropdown options. If direct user entry is not what is driving your scenario, shouldn't the check for zero results simply involve checking one, some, or a subset of the google.maps.places.PlaceResult
properties, such as:
- the:
address_components
Array ofgoogle.maps.GeocoderAddressComponent
s id
name
reference
- the
types
Array of strings (e.g., [political
,locality
] or [restaurant
,establishment
])