i want to implement radius on my gmaps Autocomplete place search,so i can get search hint from that radius first.
my code
var options = {
types: [],
componentRestrictions: {
'country': 'IN'
},
location : { lat: 17.3850, lng: 78.4867 },
radius : 5000
};
let inputPick = document.getElementById('pick');
const autocompletePick = new google.maps.places.Autocomplete(inputPick, options);
google.maps.event.addListener(autocompletePick, 'place_changed', () => {
let place =autocompletePick.getPlace();
// console.log(place.name)
// document.getElementById('pick').value = place.name;
this.setState({pickAddress:place.name})
let lat = place.geometry.location.lat(),
lng = place.geometry.location.lng();
//putting place in pick field
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
// console.log(results[0].formatted_address)
document.getElementById('pick').value = results[0].formatted_address;
}
})
but right now i'm getting all over country place.
i search on google but didn't get proper solution.can anyone help me,i''m stuck ):
If you check the Google Maps JavaScript API reference documentation, you will see that AutocompleteOptions object doesn't have location and radius fields
https://developers.google.com/maps/documentation/javascript/reference/3/#AutocompleteOptions
Instead it has bounds field to define an area where you would like to search and strictBounds field to restrict results to this area only.
You should rewrite your code with bounds and strictBounds autocomplete options. Something like
var options = {
bounds: cityBounds,
strictBounds: true,
types: ['geocode'],
componentRestrictions: { country: "IN" }
};
Have a look at bounds documentation for more details
https://developers.google.com/maps/documentation/javascript/reference/3/#LatLngBounds
https://developers.google.com/maps/documentation/javascript/reference/3/#LatLngBoundsLiteral
I hope this helps!
Related
Probably simple answer for someone that knows JavaScript, I don't know it very well. I'm getting JSON data back and applying markers to a map. However it's generating markers for those that have null which really messes things up. So what I need to do is create a conditional variable based on data being present. I have the following in the code:
let mapElement = document.getElementById('map-banner');
let pointMarkers = mapElement.getAttribute('data-location');
let marked = JSON.parse(pointMarkers);
let bounds = new google.maps.LatLngBounds();
console.log(pointMarkers);
marked.forEach(marked => {
if (marked.lat > 0 && marked.lat !== null) {
let lat = marked.lat;
}
let lng = marked.lng;
const marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
map: map,
icon: '/marker.png',
title: marked.name
});
bounds.extend(marker.position);
});
map.fitBounds(bounds);
};
Specifically I'm working with the variables lat and lng. I've also tried:
let lat = marked.lat;
if (lat > 0 && lat !== null) {
const lat = marked.lat;
}
In this case it presents all the data and it doesn't appear to be applying the condition.
You are conditionally declaring the variable, which for javascript is optional.
What you want is to skip that iteration in your loop with a guard clause:
marked.forEach(marked => {
if (marked.lat == null)
return;
const marker = new google.maps.Marker({
position: new google.maps.LatLng(marked.lat, marked.lng),
map: map,
icon: '/marker.png',
title: marked.name
});
bounds.extend(marker.position);
});
I think a filter is what you're looking for. Filtering can remove entries from arrays which you don't want to use.
Docs (by MDN) -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Also, const/let are used to achieve block scope in JavaScript.
consts are used for variables that do not change in value and are (preferably) immutable, see Docs -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
lets are used for values that do change in value, and have different values in different block scopes, see Docs -> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
const mapElement = document.getElementById('map-banner');
const pointMarkers = mapElement.getAttribute('data-location');
// catch any error from JSON.parse
try {
const coords = JSON.parse(pointMarkers);
const bounds = new google.maps.LatLngBounds();
// filter out incorrect coords
const markers = coords.filter(coord => {
return (marked.lat > 0 && marked.lat !== null)
});
// create markers, extend bounds
markers.forEach(({ lat, lng }) => {
const marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
map,
icon: '/marker.png',
title: marked.name
});
bounds.extend(marker.position);
});
// fit bounds
map.fitBounds(bounds);
} catch (error) {
// handle error to keep users happy
}
Maybe just show the marker if it exists?:
if(marked.lat && marked.lat > 0) {
const marker = new google.maps.Marker({
position: new google.maps.LatLng(lat, lng),
map: map,
icon: '/marker.png',
title: marked.name
});
}
I'm using Google Maps API example called 'Retrieving Autocomplete Predictions'. And I can't figure out how to filter it so it only returns places in the USA. I see how I could do it with the other examples...
var input = document.getElementById('searchTextField');
var options = {
types: ['(cities)'],
componentRestrictions: {country: 'us'}
};
autocomplete = new google.maps.places.Autocomplete(input, options);
But I can't seem to figure out how to apply it to my example. Here is my code...
function GetAddressPredictions(Search) {
var displaySuggestions = function (predictions, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
return;
}
predictions.forEach(function (prediction) {
PredictionArray.push(prediction);
});
};
var service = new google.maps.places.AutocompleteService();
service.getQueryPredictions({input: Search}, displaySuggestions);
}
I tried this but it didn't work.
function GetAddressPredictions(Search) {
var displaySuggestions = function (predictions, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
return;
}
predictions.forEach(function (prediction) {
PredictionArray.push(prediction);
});
};
var options = {
types: ['(cities)'],
componentRestrictions: {country: 'us'}
};
var service = new google.maps.places.AutocompleteService();
service.getQueryPredictions({input: Search, options}, displaySuggestions);
}
Any Ideas? Thanks.
You are so very close but unfortunately to get this specific behavior you need to use getPlacePredictions() instead of getQueryPredictions(). This allows you to use AutocompletionRequest which has componentRestrictions however QueryAutocompletionRequest does not support componetRestictions and you must fall back to either using bounds to limit the scope of the search to a box or location to bias the search to prefer locations near a point.
Here is the solution with getPlacePredictions():
var service = new google.maps.places.AutocompleteService();
var options = {
input: Search,
types: ['(cities)'],
componentRestrictions: {country: 'us'}
};
service.getPlacePredictions(options , displaySuggestions);
You can add location or bounds as keys to the options object if you must do this with getQueryPredictions()
The function getQueryPredictions takes a QueryAutocompletionRequest object as its parameter, and QueryAutocompletionRequest doesn't have a property to restrict it to a specific country.
That said, you can simply append ' United States' or ' usa' to the query before sending:
service.getQueryPredictions({
input: 'pizza near Syd' + ' usa'
}, displaySuggestions);
If you don't want the ", USA" to show within the returned results, you can remove it with JavaScript's replace function:
predictions.forEach(function(prediction) {
var li = document.createElement('li');
li.appendChild(document.createTextNode(prediction.description.replace(', USA', '')));
document.getElementById('results').appendChild(li);
});
Demo: https://jsfiddle.net/sdz4yssL/2/
Also note that if there is a risk of the search terms already including USA or a variation thereof, then you will need to remove any occurrences from the search terms first (typically using regex to ignore case sensitivity), otherwise searching for something like "pizza usa usa" will return no results:
input: (' ' + 'pizza near us Syd usa United States US' + ' ').replace(/ usa /ig,' ').replace(/ US /ig,' ').replace(/ united states /ig,' ') + ' usa'
(I've added a space before and after the query so that the replace functions will still match at the beginning and the very end)
With a bit of searching it was possible to find the solution.
The request was approved and released of earlier this year: Google Request
The documentation of such information can be read from here: Google Documentation
Implementation:
HTML :
<div id="text">
Search Place:
</div>
<div id="locationField">
<input id="autocomplete" placeholder="Enter text" type="text" />
</div>
<div id="map"></div>
Restrict to which country using a global variable, UK for uk, US for Americas etc...
var countryRestrict = {
'country': 'uk'
};
var autocomplete;
Auto complete is then constructed using the following:
autocomplete = new google.maps.places.Autocomplete(
(
document.getElementById('autocomplete')), {
componentRestrictions: countryRestrict
});
places = new google.maps.places.PlacesService(map);
autocomplete.addListener('place_changed', onPlaceChanged);
When the text changes we call the onPlacesChanged function:
function onPlaceChanged() {
var place = autocomplete.getPlace();
if (place.geometry) {
map.panTo(place.geometry.location);
map.setZoom(5);
var marker = new google.maps.Marker({
position: place.geometry.location,
map: map,
});
} else {
document.getElementById('autocomplete').placeholder = 'Enter a Value';
}
}
This calls the get place function and adds a marker to the value you clicked on.
JSFIDDLE: https://jsfiddle.net/hn8091fk/
Have you tried something like this:
function GetAddressPredictions(Search) {
var displaySuggestions = function(predictions, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
return;
}
predictions.forEach(function(prediction) {
PredictionArray.push(prediction);
});
};
var service = new google.maps.places.AutocompleteService();
service.getQueryPredictions({
input: Search,
types: ['(cities)'],
componentRestrictions: {country: 'us'}
}, displaySuggestions);
}
Contrary to above, AutocompleteService takes EITHER QueryAutocompletionRequest OR AutocompletionRequest so I think the way you are passing your options is wrong. Is it not simply:
var options = {
input: Search,
types: ['(cities)'],
componentRestrictions: {country: 'us'}
};
var service = new google.maps.places.AutocompleteService();
service.getQueryPredictions(options, displaySuggestions);
Please also keep in mind that this is all for prediction biasing you cannot ask PAC to exclude results, only bias.
So what I am trying to do is implement Google Maps with a search box. Currently, the search box retrieves 20 of the top places based on the search result.
What I noticed is there is no pagination with this. Such as if I type in “pizza”, it will give me the top 20 results in the current location bounds. But when I use the google.maps.places.PlacesService(map) textSearch function to obtain a list of pizza searches, I get more than 20 results with pagination.
Is there a way to get pagination on your searchBox or use the textSearch function to provide pagination after you used searchBox?
What I have here is a snippet:
var canvas = element.find('div')[0];
var mapOptions = {
zoom: 5,
minZoom: 2,
};
var searchBox = new google.maps.places.SearchBox('pizza');
var placeService = new google.maps.places.PlacesService(map);
google.maps.event.addListener(searchBox, 'places_changed', locationChange);
function locationChange() {
var places = searchBox.getPlaces();
//Determine if there are additional places not provided by searchbox. Using text
var request = {
query: input.value,
};
var textSearchPlaces = placeService.textSearch(request, callback);
function callback(results, status, pagination) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
var hi = places;
for (var i = 0; i < results.length; i++) {
var place = results[i];
}
}
}
if (places.length === 0) {
return;
}
};
As you can see this is not the most ideal solution to looking using a pagination as I would have to filter through the textSearchPlaces to see if those places are not duplicates of the searchBox results.
I also thought about just removing the searchBox and just going with the textSearch function but I realized I wouldn’t have the autoComplete function that provides suggestions that searchBox provides.
Most likely you are getting OVER_QUERY_LIMIT.
if (status == google.maps.places.PlacesServiceStatus.OK) {
Try queuing the details requests for after you have all the list completed, adding the same timeout logic to check for google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT on this line.
if (pagination.hasNextPage) {
//add all places to the list
setTimeout('pagination.nextPage()',2000);
} else {
createMarkers(placesList);
}
You should use google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT when using Places.
Able to successfully set the mapbox viewpoint dynamically by passing the geocoder a street address stored in my database.
But rather than just setting the map view to the address, I want to draw a marker at the address' location.
Template.vendorPage.rendered = function(){
//get address from database by ID
address = function(){
pathname =location.pathname.split("/");
thisId = pathname[2];
return Vendors.findOne({_id: thisId}).address
}
//set variable to the address function
thisAddress = address();
//draw the mapbox
L.mapbox.accessToken = '<My Token Here>';
var geocoder = L.mapbox.geocoder('mapbox.places-v1'),
map = L.mapbox.map('map', 'alexnetsch.j786e624');
geocoder.query(thisAddress, showMap);
function showMap(err, data) {
// The geocoder can return an area, like a city, or a
// point, like an address. Here we handle both cases,
// by fitting the map bounds to an area or zooming to a point.
if (data.lbounds) {
map.fitBounds(data.lbounds);
} else if (data.latlng) {
map.setView([data.latlng[0], data.latlng[1]], 16);
}
}
}
Played around with the documentation for hours and can't figure it out. I'd like to simply pass the marker function 'thisAddress'
Seems like rather than setting the viewport, I could set the map to be zoomedin and centered around my marker.
Here is the example from the documentation but without Geocoding the location.
L.mapbox.accessToken = 'pk.eyJ1IjoiYWxleG5ldHNjaCIsImEiOiJsX0V6Wl9NIn0.i14NX5hv3bkVIi075nOM2g';
var map = L.mapbox.map('map', 'examples.map-20v6611k')
.setView([38.91338, -77.03236], 16);
L.mapbox.featureLayer({
// this feature is in the GeoJSON format: see geojson.org
// for the full specification
type: 'Feature',
geometry: {
type: 'Point',
// coordinates here are in longitude, latitude order because
// x, y is the standard for GeoJSON and many formats
coordinates: [
-77.03221142292,
38.913371603574
]
},
properties: {
title: 'Peregrine Espresso',
description: '1718 14th St NW, Washington, DC',
// one can customize markers by adding simplestyle properties
// https://www.mapbox.com/foundations/an-open-platform/#simplestyle
'marker-size': 'large',
'marker-color': '#BE9A6B',
'marker-symbol': 'cafe'
}
}).addTo(map);
Figured it out finally.
Template.vendorPage.rendered = function(){
address = function(){
pathname =location.pathname.split("/");
thisId = pathname[2];
return Vendors.findOne({_id: thisId}).address
}
thisAddress = address();
//draw the mapbox
L.mapbox.accessToken = 'pk.eyJ1IjoiYWxleG5ldHNjaCIsImEiOiJsX0V6Wl9NIn0.i14NX5hv3bkVIi075nOM2g';
var geocoder = L.mapbox.geocoder('mapbox.places-v1'),
map = L.mapbox.map('map', 'alexnetsch.j786e624');
geocoder.query(thisAddress, showMap);
function showMap(err, data) {
// The geocoder can return an area, like a city, or a
// point, like an address. Here we handle both cases,
// by fitting the map bounds to an area or zooming to a point.
if (data.lbounds) {
map.fitBounds(data.lbounds);
} else if (data.latlng) {
map.setView([data.latlng[0], data.latlng[1]], 16);
}
}
var addMarker;
addMarker = function(geocoder, map, placeName) {
return geocoder.query(placeName, function(error, result) {
var marker;
marker = L.marker(result.latlng);
return marker.addTo(map);
});
};
addMarker(geocoder, map, thisAddress);
I'm using Google Places API to get location details using javascript.
var request = {
input: request.term,
componentRestrictions: {country: 'us'},
types: ['geocode']};
service.getPlacePredictions(request, function (predictions, status) {
if (status != 'OK') {
return;
}
response($.map(predictions, function (prediction, i) {
var cty_st = '';
var pred_terms_lnt = prediction.terms.length;
if(pred_terms_lnt >= 3){
cty_st = prediction.terms[pred_terms_lnt - 3].value+', '+prediction.terms[pred_terms_lnt - 2].value;
}
else if(pred_terms_lnt >= 2){
cty_st = prediction.terms[pred_terms_lnt - 2].value;
}
else{
cty_st = prediction.description.replace(", United States", "");
}
return {
label: cty_st,
value: cty_st,
ref: prediction.reference,
id: prediction.id
}
}));
});
I want to show only city and state code from the results fetched and when I search for a location I'm getting duplicate city, state coder in the results. I want to remove these duplicates from the results. How to do that?
From the above results you can see last two results have same city and state code. I want to show only once.
Instead of types: ['geocode'] use types: ['(cities)']