Google Maps set a text field value when address is selected - google-maps

I'm trying to work out how to set the value of a text field called rehabGroup when I do an search for an address.
The autocomplete form I'm using consists of 2 maps.
I need to take the value from the locality returned result and use it to search through a list of names to return the result to a text field.
I can do it with an autocomplete search but I really need it to do it automatically when the result from the search is selected.
This is a snippet of the HTML
<div id="map2"></div>
<div class="form-group">
<label class="control-label" for="autocomplete2">Search for Encounter Address</label>
<i class="h5 fas fa-map-pin"></i>
<div class="input-group">
<input id="autocomplete2" />
</div>
</div>
<div class="form-group">
<label class="control-label" for="locality">Town/Suburb</label>
<i class="h5 far fa-map"></i>
<div class="input-group">
<input type="text" class=" form-control rounded" id="locality2" name="locality2" placeholder="Town of the rescue" data-toggle="tooltip" title="Town of rescue" />
</div>
</div>
<div class="form-group">
<label class="control-label" for="rehabGroup">Rehab Group</label>
<i class="h5 fas fa-map-pin"></i>
<div class="input-group">
<input type="text" id="rehabGroup" name="rehabGroup" value="" />
</div>
</div>
This is the code i've been using
<script>
$(function() {
$('#locality2').autocomplete({
source: 'ajax.php',
minLength: 3,
change: function (event, ui) {
if (!ui.item) {
$(this).val('');
$(this).focus();
}
},
select: function(event, ui) {
$('#rehabGroup').val(ui.item.rehabGroup);
}
});
});
let placeSearch, autocomplete, autocomplete2;
let componentForm = {
subpremise: 'long_name',
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
administrative_area_level_2: 'long_name',
country: 'long_name',
postal_code: 'short_name',
latitude: 'long_name',
longitude: 'short_name'
};
let defaultBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(-32.889049, 151.600815),
new google.maps.LatLng(-32.506633, 152.340289)
);
let map1 = new google.maps.Map(document.getElementById('map1'), {
center: {
lat: -32.732140,
lng: 152.039616
},
zoom: 11
});
let map2 = new google.maps.Map(document.getElementById('map2'), {
center: {
lat: -32.732140,
lng: 152.039616
},
zoom: 11
});
let marker1 = new google.maps.Marker({
map: map1,
draggable: true
});
let marker2 = new google.maps.Marker({
map: map2,
draggable: true
});
google.maps.event.addListener(marker1, 'dragend',
function(marker1) {
let latLng1 = marker1.latLng;
currentLatitude1 = latLng1.lat();
currentLongitude1 = latLng1.lng();
$('#lat').val((currentLatitude1).toFixed(6));
$('#lng').val((currentLongitude1).toFixed(6));
}
);
google.maps.event.addListener(marker2, 'dragend',
function(marker2) {
let latLng2 = marker2.latLng;
currentLatitude2 = latLng2.lat();
currentLongitude2 = latLng2.lng();
$('#lat2').val((currentLatitude2).toFixed(6));
$('#lng2').val((currentLongitude2).toFixed(6));
}
);
function initAutocomplete() {
// Create the autocomplete object, restricting the search to geographical
// location types.
autocomplete = new google.maps.places.Autocomplete(
/** #type {!HTMLInputElement} */
(document.getElementById('autocomplete')), {
bounds: defaultBounds,
types: [
'geocode'
],
strictBounds: true,
componentRestrictions: {
country: 'au'
}
});
// When the user selects an address from the dropdown, populate the address
// fields in the form.
autocomplete.addListener('place_changed', function() {
fillInAddress(autocomplete, '');
});
autocomplete2 = new google.maps.places.Autocomplete(
/** #type {!HTMLInputElement} */
(document.getElementById('autocomplete2')), {
bounds: defaultBounds,
types: [
'geocode'
],
strictBounds: true,
componentRestrictions: {
country: 'au'
}
});
autocomplete2.addListener('place_changed', function() {
fillInAddress(autocomplete2, '2');
});
}
function fillInAddress(autocomplete, unique) {
// Get the place details from the autocomplete object.
let place = autocomplete.getPlace();
if (unique === '2'){
if (place.geometry.viewport) {
map2.fitBounds(place.geometry.viewport);
} else {
map2.setCenter(place.geometry.location);
map2.setZoom(14);
}
marker2.setPosition(place.geometry.location);
marker2.setVisible(true);
}else{
if (place.geometry.viewport) {
map1.fitBounds(place.geometry.viewport);
} else {
map1.setCenter(place.geometry.location);
map1.setZoom(14);
}
marker1.setPosition(place.geometry.location);
marker1.setVisible(true);
}
for (let component in componentForm) {
if (!!document.getElementById(component + unique)) {
document.getElementById(component + unique).value = '';
document.getElementById(component + unique).disabled = false;
}
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (let i = 0; i < place.address_components.length; i++) {
let addy = '';
let addressTypes = place.address_components[i].types;
for (let j = 0; j < addressTypes.length; j++) {
let addressType = addressTypes[j];
if (componentForm[addressType] && document.getElementById(addressType + unique)) {
addy = place.address_components[i][componentForm[addressType]];
document.getElementById(addressType + unique).value = addy;
}
}
}
document.getElementById('lat' + unique).value = place.geometry.location.lat().toFixed(6);
document.getElementById('lng' + unique).value = place.geometry.location.lng().toFixed(6);
}
google.maps.event.addDomListener(window, 'load', initAutocomplete);
</script>
TIA

Looks like you're able to populate an address form successfully once an address is selected from the Autocomplete dropdown. You just need to add another step to the to fillInAddress() when you find the locality component of the address to call your custom function that searches for your group names and populates the text field.
function fillInAddress(autocomplete, unique) {
// Get the place details from the autocomplete object.
let place = autocomplete.getPlace();
if (unique === '2'){
if (place.geometry.viewport) {
map2.fitBounds(place.geometry.viewport);
} else {
map2.setCenter(place.geometry.location);
map2.setZoom(14);
}
marker2.setPosition(place.geometry.location);
marker2.setVisible(true);
}else{
if (place.geometry.viewport) {
map1.fitBounds(place.geometry.viewport);
} else {
map1.setCenter(place.geometry.location);
map1.setZoom(14);
}
marker1.setPosition(place.geometry.location);
marker1.setVisible(true);
}
for (let component in componentForm) {
if (!!document.getElementById(component + unique)) {
document.getElementById(component + unique).value = '';
document.getElementById(component + unique).disabled = false;
}
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (let i = 0; i < place.address_components.length; i++) {
let addy = '';
let addressTypes = place.address_components[i].types;
for (let j = 0; j < addressTypes.length; j++) {
let addressType = addressTypes[j];
if (componentForm[addressType] && document.getElementById(addressType + unique)) {
addy = place.address_components[i][componentForm[addressType]];
document.getElementById(addressType + unique).value = addy;
}
if (addressType == 'locality') {
// Perform your custom search on this locality and populate the result in text field rehabGroup
let locality = place.address_components[i]['long_name'];
let result = yourCustomSearch(locality);
document.getElementbyId('rehabGroup').value = result;
}
}
}
document.getElementById('lat' + unique).value = place.geometry.location.lat().toFixed(6);
document.getElementById('lng' + unique).value = place.geometry.location.lng().toFixed(6);
}

Thank's, I've gotten it to work but it happens on both the locality and locality2 fields . I'll try and sort it out from there.
if (addressType === 'locality') {
// Perform your custom search on this locality and populate the result in text field rehabGroup
let locality2 = place.address_components[i]['long_name'];
//Carry out a GET Ajax request using JQuery
$.ajax({
//The URL of the PHP file that searches MySQL.
type: 'GET',
url: 'ajax.php',
data: {
locality2: locality2
},
success: function(data){
let obj = data;
alert(cut);
document.getElementById('rehabGroup').value = cut;
}
});
}

Related

Call markers based on radio button value

I am trying to call markers to a google map based on a value (year as a string). I thought by putting an on click event to listen for when the radio class is clicked, that I could initialize the $.getJSON and set the value for the year.
How can initialize the $.getJSON call when the radio button is clicked and base the variable yearValue on which radio button is checked?
Also, if I wanted to reset the markers each time a new radio button is clicked, would I need to put all of the markers in an array, set them to the map, then clear the array when a new radio button value is checked (say I choose 2014 instead of 2015?). How can I clear the markers when a new radio button is checked so that I don't see both years at the same time?
var map;
var mapProp;
var url = 'https://data.montgomerycountymd.gov/resource/5pue-gfbe.json?$limit=50000';
var count;
var marker;
var manyCategory = [];
var category = [];
var yearValue;
function initMap() {
mapProp = {
center: new google.maps.LatLng(39.154743, -77.240515),
zoom: 10
};
map = new google.maps.Map(document.getElementById('map'), mapProp);
}
function addInfoWindow(marker, message) {
var infoWindow = new google.maps.InfoWindow({
content: message
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.open(map, marker);
});
}
$(document).ready(function() {
if ($('input:radio[name="year"]').is("checked")) {
yearValue = $(this).val();
}
initMap();
$('.radioClass').on('click', function() {
$.getJSON(url, function(data) {
count = 0;
for (var i = 0; i < data.length; i++) {
var newDate = data[i].inspectiondate;
if (data[i].violation22 === "Out of Compliance" && newDate.slice(0, 4) === yearValue) {
if (data[i].hasOwnProperty('latitude')) {
count++;
var message = "<div>" + data[i].organization + "<br>" + (data[i].inspectiondate).slice(0, 10) + "</div>";
var uniqueIcon;
if (data[i].category === "Private School" || data[i].category === "Public School- Elementary" || data[i].category === "Public School- High" || data[i].category === "Public School- Middle") {
uniqueIcon = "https://maps.gstatic.com/mapfiles/ms2/micons/blue.png";
} else if (data[i].category === "Market" || data[i].category === "Carry Out" || data[i].category === "Snack Bar" || data[i].category === "Caterer" || data[i].category === "Restaurant") {
uniqueIcon = "https://maps.gstatic.com/mapfiles/ms2/micons/purple.png"
} else if (data[i].category === "Nursing Home" || data[i].category === "Hospital" || data[i].category === "Assisted Living") {
uniqueIcon = "https://maps.gstatic.com/mapfiles/ms2/micons/red.png"
} else {
uniqueIcon = "https://maps.gstatic.com/mapfiles/ms2/micons/yellow.png";
}
marker = new google.maps.Marker({
position: new google.maps.LatLng(data[i].location.latitude, data[i].location.longitude),
title: "Hello, world. I received a food violation in 2015",
animation: google.maps.Animation.DROP,
icon: uniqueIcon,
});
marker.setMap(map);
//console.log(data[i].inspectionresults);
addInfoWindow(marker, message);
manyCategory.push(data[i].category);
}
}
}
//;
$.each(manyCategory, function(i, el) {
if ($.inArray(el, category) === -1) category.push(el);
})
//console.log(count);
//console.log(manyCategory);
//console.log(category);
});
});
});
h1,
#icons,
#radioDiv {
text-align: center;
}
#map {
margin: 0 auto;
width: 700px;
height: 400px;
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<h1>Rodent Violations</h1>
<div id="radioDiv">
<input type="radio" name="year" value="2015" class="radioClass">2015
<input type="radio" name="year" value="2014" class="radioClass">2014
</div>
<div id="icons">
<img src="https://maps.gstatic.com/mapfiles/ms2/micons/blue.png">School
<img src="https://maps.gstatic.com/mapfiles/ms2/micons/purple.png">Restaurant
<img src="https://maps.gstatic.com/mapfiles/ms2/micons/red.png">Healthcare
<img src="https://maps.gstatic.com/mapfiles/ms2/micons/yellow.png">All other
</div>
<div id="map"></div>
You need an array fo markers globally visibile that hold all the markers you create for let you clean them before you show the new markers.
var myMarkers
add the begin of the callback function clear the markers setting maps to null
$.getJSON(url, function(data) {
count = 0;
for (var i = 0; i < myMarkers.length; i++) {
myMarkers[i].setMap(null);
}
myMarkers = []; // empty the array
.......
popluate the myMArkers Array with all the marker you create
marker.setMap(map);
addInfoWindow(marker, message);
myMarkers.push(marker);

Manipulate google maps autocomplete results on dynamically loaded text fields

I have a page with an unknown number of ".city-name" text fields (generated dynamically).
I'm having issues working with the auto-complete results for these fields after they are generated. I think I'm not doing the right things with my loop.
http://jsfiddle.net/w0dwxg4a/
function getPlace_dynamic() {
var options = {types: ['(cities)']};
var inputs = document.getElementsByClassName('city-name');
for (i = 0; i < inputs.length; i++) {
var places = new google.maps.places.Autocomplete(inputs[i], options);
google.maps.event.addDomListener(inputs[i], 'keydown', function (e) {
if (e.keyCode == 13) {
e.preventDefault();
}
});
google.maps.event.addListener(places, 'place_changed', function () {
var results = places.getPlace();
var address_components = results.address_components;
var components = {};
jQuery.each(address_components, function (k, v1) {
jQuery.each(v1.types, function (k2, v2) {
components[v2] = v1.long_name;
});
});
$(inputs).val(components.locality + ", " + components.country);
$(inputs).closest("form").submit();
});
}
}
The desired behaviour for each".city-name" can be seen in the "#txtPlaces" JsFiddle. I need the box value to convert to "City, Country", and then submit once selected.
I have disabled the enter key because that was submitting the autocomplete without switching it over to "City, Country".
I got it using jQuery $.each: Seems to work.
var options = {
types: ['(cities)']
};
var input = document.getElementsByClassName('city-name');
$.each(input, function(i, x){
var this_id = input[i].id;
var this_input = document.getElementById(this_id);
var places = new google.maps.places.Autocomplete(input[i], options);
google.maps.event.addListener(places, 'place_changed', function () {
var results = places.getPlace();
var address_components = results.address_components;
var components = {};
jQuery.each(address_components, function (k, v1) {
jQuery.each(v1.types, function (k2, v2) {
components[v2] = v1.long_name;
});
});
$(this_input).val(components.locality + ", " + components.country);
$(this_input).closest("form").submit();
});
google.maps.event.addDomListener(input[i], 'keydown', function (e) {
if (e.keyCode == 13) {
e.preventDefault();
}
});
})
}

Validate credit card expiration with angular?

I can not validate my date field.
The idea is that when the user enter the date validate if the card is expired. I made this directive but I am a little lost with the directives of angular.
checkOut.directive('cardDateExpiration', function() {
return {
require: 'ngModel',
link: function(date) {
var currentDate = new Date();
var m, y, d;
if (/^\d{2}\/\d{2}$/.test(date)) {
m = date.substring(0, 2) - 1;
y = 20 + date.slice(-2);
d = new Date(y, m);
} else if (/^\d{2}\/\d{4}$/.test(date)) {
m = date.substring(0, 2) - 1;
y = date.slice(-4);
d = new Date(y, m);
} else if (/^\d{4}$/.test(date)) {
m = date.substring(0, 2) - 1;
y = 20 + date.slice(-2);
d = new Date(y, m);
}
return currentDate > d;
}
}
});
<div class="large-6 columns sd-items-form">
<label>
<input id="expiry_date" maxlength="5" name="datacard" card-date-expiration ng-disabled="" class="sd-field sd-txt-center p-l-0" ng-model="form.data.datacard" type="text" type placeholder="MM / YY" required></input>
</label>
<div class="error" ng-if="checkoutPayment.$submitted || checkoutPayment.datacard.$touched" ng-messages="checkoutPayment.datacard.$error">
<p class="text-msg" ng-message="required">Not valid date credit card</p>
</div>
</div>
I have this example of how to do custom validation of input fields in angular here: http://jsfiddle.net/fortesl/2uv6xmjL/6/
I am using momentjs to validate a date, which I recommend, but you can also parse the input string if you like (I do not recommend it). Code is shown below:
app.directive('dateFieldValidator', [function () {
var validateDate = function (date, format) {
if (!date.length) {
return true;
}
return moment(date, format.toUpperCase(), true).isValid();
};
return {
restrict: 'A',
require: 'ngModel',
scope: {
dateFormat: '#'
},
link: function (scope, elem, attrs, ngModelCtrl) {
//For DOM -> model validation
ngModelCtrl.$parsers.unshift(function (value) {
var valid = validateDate(value, scope.dateFormat);
ngModelCtrl.$setValidity('validDate', valid);
return valid ? value : undefined;
});
//For Model Update --> DOM
ngModelCtrl.$formatters.unshift(function (value) {
var valid = validateDate(value, scope.dateFormat);
ngModelCtrl.$setValidity('validDate', valid);
return value;
});
}
};
}]);
and here is a sample html which uses the directive:
<div ng-app="dateApp">
<div ng-controller="DateController as dateCtrl">
<form name="dateForm" novalidate
ng-submit="dateCtrl.setDate(dateForm.dateInput.$valid); dateForm.dateInput.$setPristine();">
Enter date:
<input name="dateInput" ng-model="dateCtrl.date" date-format="{{dateCtrl.format}}"
date-field-validator placeholder="{{dateCtrl.format}}">
<button ng-disabled="dateForm.dateInput.$pristine">Submit</button>
</form>
</div>
A sample controller:
var app = angular.module('dateApp', []);
app.controller('DateController', function () {
var self = this;
self.format = 'MM/DD/YYYY';
self.date = '';
self.setDate = function (valid) {
if (valid) {
window.alert('You entered a valid Date: ' + self.date);
} else {
window.alert('!!!!!!!!!! WARNING: INVALID DATE !!!!!!!!!');
}
self.date = '';
}
})

Google places api not returning postal code for some places

I have a form which would collect location information from the user. I'm using Google places api to autocomplete the location information. It works great. Everything got filled out nicely however there are some places (e.g. my workplace which is a building), Google does not return a postal code for it.
I followed this example from Google address autocomplete. It also doesn't return postal code for my workplace. So I'm not entire sure what I did wrong.
Below is my code:
HTML
<div id="location-autocomplete" style="display: none;">
<div class="half-formfield">
#Html.LabelFor(x => x.Address)
#Html.TextBoxFor(x => x.Address, new { #class = "two-third-field", id = "street_number", required = "required" })
</div>
<div>
#Html.LabelFor(x => x.UnitNumber, new { value = "Unit Number" })
#Html.TextBoxFor(x => x.UnitNumber, new { #class = "one-third-field" })
</div>
<div class="half-formfield">
#Html.LabelFor(x => x.City)
#Html.TextBoxFor(x => x.City, new { #class = "half-field", required = "required", id = "locality" })
</div>
<div>
#Html.LabelFor(x => x.ProvinceOrState)
#Html.TextBoxFor(x => x.ProvinceOrState, new { #class = "half-field", required = "required", id = "administrative_area_level_1" })
</div>
<div class="half-formfield">
#Html.LabelFor(x => x.ZipOrPostalCode)
#Html.TextBoxFor(x => x.ZipOrPostalCode, new { #class = "half-field", required = "required", id = "postal_code" })
</div>
<div>
#Html.LabelFor(x => x.Country)
#Html.TextBoxFor(x => x.Country, new { #class = "half-field", required = "required", id = "country" })
</div>
<input type="button" value="Clear Address" onclick="clearAddress()" id="clear-btn" class="service-form-btn"/>
JS
var placeSearch, autocomplete;
var componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
function initialize() {
// Create the autocomplete object, restricting the search
// to geographical location types.
autocomplete = new google.maps.places.Autocomplete(
/** #type {HTMLInputElement} */(document.getElementById('autocomplete')),
{ types: ['geocode'] });
// When the user selects an address from the dropdown,
// populate the address fields in the form.
google.maps.event.addListener(autocomplete, 'place_changed', function () {
fillInAddress();
showAddressComponent();
setTimeout(hideAddressSearch, 800);
});
}
function fillInAddress() {
// Get the place details from the autocomplete object.
var place = autocomplete.getPlace();
for (var component in componentForm) {
if (component != "route") {
document.getElementById(component).value = '';
document.getElementById(component).disabled = false;
}
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var val = place.address_components[i][componentForm[addressType]];
console.log(val);
if (addressType != "route") document.getElementById(addressType).value = val;
else if (addressType == "route") document.getElementById("street_number").value = document.getElementById("street_number").value + " " + val;
}
}
}
// Bias the autocomplete object to the user's geographical location,
// as supplied by the browser's 'navigator.geolocation' object.
function geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
var geolocation = new google.maps.LatLng(
position.coords.latitude, position.coords.longitude);
autocomplete.setBounds(new google.maps.LatLngBounds(geolocation,
geolocation));
});
}
}
Screenshot
I wonder if this is a bug or simply Google doesn't know the postal code of the building. In that case, is there simply any work around this?
Thanks in advance.
There is a postal code for this address, but only a part (I guess it's called FSA-code).
The function didn't recognize this part, because for this address the returned types-array is:
["postal_code_prefix", "postal_code"]
...but the function only checks the first item of the types-array.
possible fix:
function fillInAddress() {
// Get the place details from the autocomplete object.
var place = autocomplete.getPlace();
for (var component in componentForm) {
document.getElementById(component).value = '';
document.getElementById(component).disabled = false;
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i++) {
var addressTypes = place.address_components[i].types,addressType,val;
for(var j=0;j<addressTypes.length;++j){
addressType=addressTypes[j];
if (componentForm[addressType]) {
val = place.address_components[i][componentForm[addressType]];
document.getElementById(addressType).value = val;
break;
}
}
}
}
Hope this will explore more ideas.
function initDefaultAutoCompleteFunction() {
var objAddress = document.getElementsByClassName('autocomplete-address');
$(objAddress).each(function (index, address) {
if (typeof (address) != 'undefined' && address != null) {
let options = {
types: ['address'],
Fields: ['address_component', 'formatted_address'],
componentRestrictions: { country: ['us', 'ca'] }
};
let autocomplete = new google.maps.places.Autocomplete(address, options);
autocomplete.addListener('place_changed', function () {
debugger;
let place = autocomplete.getPlace();
if (place) {
let zipOrPostalCode = null; // or set empty etc.
$.each(place.address_components, function (index, value) {
let addressType = value.types[0];
if (addressType == 'street_number') {
// value.short_name; //this is your street number
}
if (addressType == 'route') {
// value.short_name; //this is your route
}
if (addressType == 'postal_code' || addressType == "postal_code_prefix") {
// value.short_name; //this is your postal_code
}
});
}
});
}
});
}
var location = place.geometry.location;
var lat = location.lat();
var lng = location.lng();
var latlng = {lat: lat, lng: lng};
geocoder.geocode({'location': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
for (var i = 0; i < results[0].address_components.length; i++) {
var types = results[0].address_components[i].types;
for (var typeIdx = 0; typeIdx < types.length; typeIdx++) {
if (types[typeIdx] == 'postal_code') {
//console.log(results[0].address_components[i].long_name);
var pincode = results[0].address_components[i].short_name;
alert('pin'+pincode);
}
}
}
$('#pac-input2').val(results[0].formatted_address);
infowindow.setContent(results[0].formatted_address);
//infowindow.open(map, marker);
}
}
});

fill google maps autocomplete with prediction results

What I have at the moment is a place autocomplete which displays results for one country.
What I want to do is make it display results for more countries (limited to 2 or 3).
As I understand it, this is not possible with the current version of the autocomplete ( https://code.google.com/p/gmaps-api-issues/issues/detail?id=4233)
So what I'm going to do is get two lists of predictions and display those instead of the autocomplete result.
Is there any way to trigger the dropdown part of the autocomplete and populate it with the predictionslist?
triggered code in the onChange of the input:
var inputData = this.value;
var options = {
componentRestrictions: { country: "be" }
};
service = new google.maps.places.AutocompleteService();
var request = {
input: inputData,
componentRestrictions: {country: 'be'},
};
var secondaryRequest = {
input: inputData,
componentRestrictions: {country: 'lu'},
};
service.getPlacePredictions(request, callback);
service.getPlacePredictions(secondaryRequest, callback);
callback function:
function callback(predictions, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
//here I need to display that dropdown if it isn't already
// and then add the results of the current predictions.
}
UPDATE
Multiple countries filter in place autocomplete was introduced in version 3.27 of Maps JavaScript API in January 2017:
You can now restrict Autocomplete predictions to only surface from multiple countries. You can do this by specifying up to 5 countries in the componentRestrictions field of the AutocompleteOptions.
source: https://developers.google.com/maps/documentation/javascript/releases#327
Here's my demo solution. As mentioned in the comment. it uses several calls to get predictions and build up the result list with them. When a result is selected the address is geocoded.
This means 3 calls instead of 1 with the autocomplete, but so far I haven't found a way around it.
<!DOCTYPE html>
<html>
<head>
<title>Retrieving Autocomplete Predictions</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places&v=3.exp"></script>
<script>
function initialize() {
$("#place").live("keyup", function (evt) {
// Clear any previously set timer before setting a new one
window.clearTimeout($(this).data("timeout"));
$(this).data("timeout", setTimeout(function () {
//whe the timeout has expired get the predictions
var inputData = $("#place").val();
service = new google.maps.places.AutocompleteService();
var request = {
input: inputData,
componentRestrictions: {country: 'be'},
};
var secondaryRequest = {
input: inputData,
componentRestrictions: {country: 'lu'},
};
$('#resultWindow').empty();
service.getPlacePredictions(request, callback);
service.getPlacePredictions(secondaryRequest, callback);
}, 1000));
});
function callback(predictions, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
console.log(status);
return;
}
var resultHTML = '';
for (var i = 0, prediction; prediction = predictions[i]; i++) {
resultHTML += '<div>' + prediction.description + '</div>';
}
if($('#resultWindow').html() != undefined && $('#resultWindow').html() != ''){
resultHTML = $('#resultWindow').html()+ resultHTML;
}
if(resultHTML != undefined && resultHTML != ''){
$('#resultWindow').html(resultHTML).show();
}
//add the "powered by google" image at the bottom -> required!!
if($('#resultWindow').html() != undefined){
$('#resultWindow #googleImage').remove();
var imageHtml = $('#resultWindow').html() + '<img id="googleImage" src="powered-by-google-on-white2.png"/>';
$('#resultWindow').html(imageHtml);
}
}
function geocodeAddress(address) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': address}, function (results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
$('#latitude').val(results[0].geometry.location.lat());
$('#longitude').val(results[0].geometry.location.lng());
}
else {
console.log("Error: " + google.maps.GeocoderStatus);
}
});
}
$('#resultWindow div').live('click',function(){
//get the coördinates for the selected (clicked) address
$('#resultWindow').hide();
var address = $(this).text();
var addressParts = address.split(',');
$('#country').val(addressParts[2]);
$('#city').val(addressParts[1]);
$('#place').val(addressParts[0]);
if(address != ''){
geocodeAddress(address);
}
});
/*end custom autocomplete stuff*/
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<style type="text/css">
#resultWindow{
position: fixed;
/* top: 0;
left: 0;
width: 100%;
height: 100%;*/
background-color: #fff;
filter:alpha(opacity=50);
-moz-opacity:0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
z-index: 10000;
border: 1px solid black;
color:black;
display:none;
}
</style>
</head>
<body>
<div id="placeholder">
<input type="text" id="place" style="width:200px;"/>
<label for="latitude">Latitude</label>
<input type="text" id="latitude"/>
<label for="longitude">Longitude</label>
<input type="text" id="longitude"/>
<label for="city">city</label>
<input type="text" id="city"/>
<label for="country">selected country</label>
<input type="text" id="country"/>
<div id="resultWindow"></div>
</div>
</body>
</html>