I'm using the following code to do an "intelligent" autocomplete via Geosearch using Google Places API:
var input = 'field_18';
google.maps.event.addDomListener(document.getElementById(input), 'keydown', function(event) {
if (event.keyCode === 13) {
event.preventDefault();
}
});
var ppx_autocomplete = new google.maps.places.Autocomplete((document.getElementById(input)), { types: ['geocode'] });
ppx_autocomplete.setFields(['geometry', 'formatted_address']);
google.maps.event.addListener(ppx_autocomplete, 'place_changed', function () {
var place = ppx_autocomplete.getPlace();
document.getElementById(input).value = place.formatted_address;
var lat = place.geometry.location.lat();
var lng = place.geometry.location.lng();
document.getElementById('pp_18_geocode').value = latlng;
});
Pretty common and straight forward.
The downside is: The autocompletion starts right away with the first 2 or 3 letters typed, resulting in a LOT of requests to Google, hence to my API key consumption.
Is there any way to restrict the number of requests, e.g. by sending requests only after 5 typed letters AND maybe after some delay time, e.g. not sending requests when the user still types...
What you are looking for can be done, but you'll need to use the Autocomplete Service [1] instead of the Autocomplete widget [2]. Here is an example that waits until the fifth character is entered to make a request, and then makes one after each 2 additional characters. The number of characters can be edited at the line "edit params here". You need to insert your own API key. A similar example is at https://codepen.io/ecglover8/pen/ExPqdNd that does every 3 characters.
Since you won't be using the Autocomplete widget, you'll need to handle session tokens [3] yourself (not shown). From a price standpoint, whether you'll need tokens or not depends on exactly how you plan to use the predictions [4]. This example actually makes a geocoding API request using the Place ID from the prediction and displays the lat/long.
[2] https://developers.google.com/maps/documentation/javascript/places-autocomplete#add-autocomplete
[3] https://developers.google.com/maps/documentation/javascript/places-autocomplete#session_tokens
[4] https://developers.google.com/maps/documentation/places/web-service/usage-and-billing#ac-per-request
//declare constants
const ac = document.getElementById("ac");
const g = document.getElementById("geocoded");
const results = document.getElementById("results");
//listen for typing into input box
ac.addEventListener("input", ACRequest);
//show resulting predictions
const displayPredictions = function(predictions, status) {
results.innerHTML = "";
g.innerHTML = "";
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
predictions.forEach(prediction => {
let li = document.createElement("li");
li.appendChild(document.createTextNode(prediction.description));
li.dataset.placeid = prediction.place_id;
li.addEventListener("click", Geo)
results.appendChild(li);
});
let img = document.createElement("img");
img.setAttribute("src", "https://developers.google.com/maps/documentation/images/powered_by_google_on_white.png");
results.appendChild(img);
};
//make autocomplete request if input value length divisible by 3
function ACRequest() {
//edit params here
if ((ac.value.length > 4) && (ac.value.length % 2 == 1)) {
const service = new google.maps.places.AutocompleteService();
service.getPlacePredictions(
{
//here is where you can add bounds, componentrestrictions, types, etc
input: ac.value
}, displayPredictions
)
};
};
function Geo() {
console.log(this.getAttribute("data-placeid"));
const geocoder = new google.maps.Geocoder();
geocoder.geocode(
{
"placeId": this.getAttribute("data-placeid")
}, function(address, status) {
if (status == "OK") {
g.innerHTML = address[0].geometry.location
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
li {
border: 2px solid blue;
list-style: none;
margin: 2px;
padding: 2px;
}
li:hover {
border: 2px solid red;
}
.pac-card {
border-radius: 2px 0 0 2px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
box-sizing: border-box;
font-family: Roboto;
margin: 10px 10px 0 0;
outline: none;
}
.title {
background-color: #4D90FE;
color: #FFFFFF;
font-size: 25px;
font-weight: 500;
margin: 10px 0px;
padding: 6px 12px;
}
<div class="pac-card">
<div class="title">Autocomplete Makes Requests Every Three Characters</div>
<input id="ac" size="10" type="text" />
<ul id="results"></ul>
<p id="geocoded"></p>
</div>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&libraries=places&v=weekly" async defer></script>