I am using the Leaflet plugin leaflet-control-geocoder found here: https://github.com/perliedman/leaflet-control-geocoder
My aim is to restrict the results by country = UK and city = london.
My current code which works fine but am getting results also from outside UK
var geocoder = L.Control.geocoder({position:'topleft', geocode:'countrycodes=gb'});
geocode.addTo(map);
The geocode uses Nominatim to respond to geocoding queries. Not sure why its not working
The way i have restrict country
var options = {
position: 'topright',
geocoder: new L.Control.Geocoder.nominatim({
geocodingQueryParams: {
"countrycodes": "gb"
}
})
};
var geocoder = L.Control.geocoder(options).addTo(map);
I believe that you need to write L.Control.Geocoder.nominatim({position:'topleft', geocode:'countrycodes=gb'}) to specify that you're using Nominatim.
That is what they do in the demo at this link: https://github.com/perliedman/leaflet-control-geocoder/blob/master/demo/index.html
If you use geocoder without nominatim(), then you can do the country filter as the following. The loops are ugly I know, it could be better solved with mapping to object. It's just for demonstration.
geocoder.query('pass-a-search-string-criteria', showResult);
function showResult(err, data) {
if (!map) {
map = L.mapbox.map('your-map-id', 'mapbox.streets');
}
if (data.lbounds) {
[].slice.call(data.results.features).forEach(function(place){
[].slice.call(place.context).some(function(ccode, i) {
if (i === 3 && ccode.short_code ==='gb') {
console.log(place.place_name);
}
});
});
map.fitBounds(data.lbounds);
} else if (data.latlng) {
map.setView([data.latlng[0], data.latlng[1]], 13);
}
}
Related
This question already has an answer here:
Reverse Geocoder Returning undefined
(1 answer)
Closed 1 year ago.
I am a newbie in web development. Today, I am trying to use Google Map API to get the country name and the state name from longitude and latitude using JavaScript. I read the documentation from the Google Map API and did some research but I was kinda confused about this. I gave it a go and this is what I did:
function getCountryName(latitude, longitude){
var country;
const geocoder = new google.maps.Geocoder();
geocoder.geocode({location: {lat: latitude, lng: longitude}}, (results, status) => {
if(status === "OK"){
if(results[0]){
country = results[0].address_components[0].types[0].country;
}
else{
country = "N/A";
}
}
});
return country;
}
However, I keep getting the "undefine" result. Is there anything wrong with my approach?
Thanks you all in advance!
You seem to be confused about the asynchronous programming happening here.
Basically you have return country; statement at the end of function execution which will always be undefined since the results haven't been fetched by that time.
The 2nd parameter that you are sending to the geocoder.geocode is a callback function that will be called once google has fetched the results which obviously takes a little bit of time.
So your function should be something like this
function getCountryName(latitude, longitude, onSucess){
const geocoder = new google.maps.Geocoder();
geocoder.geocode({location: {lat: latitude, lng: longitude}}, (results, status) => {
if(status === "OK"){
if(results[0]){
onSucess(results[0].address_components[0].types[0].country);
}
else{
onSucess("N/A");
}
}
});
return country;
}
And when you are about to use this function elsewhere, you have to use it like this
getCountryName(1.1111, 2.2222, (country) => {
alert(country);
console.log(country);
// You can do anything here like showing it to ui or using it elsewhere
}
If you want to learn more about callbacks in JS, go through this Article.
I created a function making use of Googles Geocoder API to perform a reverse geolocation. It pulls lat/lon from the browser's native functions and sends them through to Google. The intent of the function is to get the approximate street address of the user (ie. 123 Fake Street). The City/Municipality, Province/State, Country and Post code are not wanted, just the street address.
function geoSuccess(pos) {
Geocoder = new google.maps.Geocoder;
Geocoder.geocode({location: {lat:pos.coords.latitude,lng:pos.coords.longitude}}, function(r, s) {
if (s === 'OK') {
var found = false,
x = 0;
do {
if (r[x].address_components[0].types.indexOf('route') !== -1) {
found = true;
}
x++;
} while(!found && x < r.length);
alert(r[x-1].address_components[0].long_name);
}
});
}
Based on how the function works, it scans through the resulting JSON to find the route. However, there is a discrepancy for mobile devices where the accuracy is different than desktops. Despite searching for route, frequently mobile devices will return either the wrong data (closest highway).
After looking at the comments made (and revising the question), the function was rewritten. Nested loops through the JSON were made to tally up all of the unique data from the query. From their, street address was manually recreated instead of relying on Google to provide the desired result.
function geoSuccess(pos) {
var Geocoder = new google.maps.Geocoder;
Geocoder.geocode({location: {lat:pos.coords.latitude,lng:pos.coords.longitude}}, function(r, s) {
if (s === 'OK') {
var addr = [];
r.each(function(o) {
o.address_components.each(function(a) {
addr[a.types.join('.')] = a.long_name
});
});
alert(addr['street_number']+' '+addr['route']);
}
});
}
So far this stands as the best way I found to get the data I wanted.
I wrote AngularJS application which shows Google, Yandex and Gis maps for specific coordinates, obtained from JSON object. JSON may contains [0...n] objects.
And it is well works with Google Maps API, but not with Yandex/Gis Maps API.
Yandex Maps:
// DOESN'T WORK
$scope.yandexMaps = function (city) {
ymaps.ready(init);
function init() {
$scope.mapContainer = document.createElement('div');
$scope.mapContainer.className = 'mapCon';
$scope.yandexMap = new ymaps.Map($scope.mapContainer, {
center: [city.lat, city.lng],
zoom: 12
});
$scope.placemark = new ymaps.Placemark([city.lat, city.lng]);
$scope.yandexMap.geoObjects.add($scope.placemark);
return $scope.mapContainer; //I NEED TO GET IT !
}
//BUT I NEED TO GET IT THERE !
};
Gis Maps:
// DOESN'T WORK
$scope.gisMaps = function (city) {
DG.then(init);
function init() {
$scope.mapContainer = document.createElement('div');
$scope.mapContainer.className = 'mapCon';
$scope.gisMap = DG.map($scope.mapContainer, {
center: [city.lat, city.lng],
zoom: 13
});
DG.marker([city.lat, city.lng]).addTo($scope.gisMap);
return $scope.mapContainer; //I NEED TO GET IT !
}
//BUT I NEED TO GET IT THERE !
};
The problem is that ymaps.ready(init); and DG.then(init); call init() functions only after they will be checked for ready map state. And I can't return $scope.mapContainer in both cases because they are in nested functions.
I tried to create global variable above init() functions and assign to this $scope.mapContainer, but when I return this global value in parent below init() function it is not visible. It is visible only in nested function.
YOU CAN SEE working JSFiddle here: https://jsfiddle.net/oxpgkLhj/2/
Please, open console to see errors
If you are commenting this part at the end of code:
//adding yandex map to common container
$scope.yandexMap = $scope.yandexMap(value);
$scope.yandexMap.id = "yandexMapContainer" + i;
angular.element($scope.container).append($scope.yandexMap);
and this:
//adding gis map to common container
$scope.gisMap = $scope.gisMaps(value);
$scope.gisMap.id = "gisMapContainer" + i;
angular.element($scope.container).append($scope.gisMap);
you will see perfectly worked Google Maps. I want to see Yandex and Gis Maps exactly the same. Please help...
I'm developing with Nokia Maps (a wonderful option I really love them) but I'm only able to get the location (latitude and longitude) with HTML5 but I can't the name where I am :/, maybe somebody could give an idea, how to do it, thank you very mach for your help.
Maps API for JavaScript 3.x
The current 3.x JavaScript API offers a thin wrapper around the REST Geocoder API. You need to make a ReverseGeocode search, and then extract the data from the Location object(s) found in the result.
A fully working reverse geocoding example can be found here, but the important bit (getting the address) can be see below:
function reverseGeocode(platform) {
var geocoder = platform.getGeocodingService(),
reverseGeocodingParameters = {
prox: '52.5309,13.3847,150', // Location
mode: 'retrieveAddresses',
maxresults: '1',
jsonattributes : 1
};
geocoder.reverseGeocode(
reverseGeocodingParameters,
function (result) {
var locations = result.response.view[0].result;
// ... etc.
},
function (error) {
alert('Ooops!');
}
);
}
Maps API for JavaScript 2.x (deprecated)
With the recently deprecated 2.x JavaScript API, again you need to make a ReverseGeocode search, and then extract the data from the Address object found in the result.
The code is a bit longer, but the important bit (getting the address) can be seen below:
// Function for receiving search results from places search and process them
var processResults = function (data, requestStatus, requestId) {
var i, len, locations, marker;
if (requestStatus == "OK") {
// The function findPlaces() and reverseGeoCode() of return results in slightly different formats
locations = data.results ? data.results.items : [data.location];
// We check that at least one location has been found
if (locations.length > 0) {
for (i = 0, len = locations.length; i < len; i++) {
alert(locations[i].address.street);
alert(locations[i].address.state);
}
} else {
alert("Your search produced no results!");
}
} else {
alert("The search request failed");
}
};
/* We perform a reverse geocode search request: translating a given
* latitude & longitude into an address
*/
var reverseGeoCodeTerm = new nokia.maps.geo.Coordinate(
52.53099,
13.38455
);
nokia.places.search.manager.reverseGeoCode({
latitude: reverseGeoCodeTerm.latitude,
longitude: reverseGeoCodeTerm.longitude,
onComplete: processResults
});
I wonder whether someone may be able to help me please.
This page allows users to filter (via checkboxes), markers which are placed on the map. Clicking on any marker performs a 'reverse geocode' action and in conjunction with selecting the 'Search Locations' button, the user can then see POI's within a given radius of the clicked marker.
For demo purposes, if you select the 'Coin' checkbox, click the green marker, then select the 'Search Locations' button, the marker will bounce and the right hand sidebar will be populated with POI's.
The problem I'm having is that in Internet Explorer everything works fine, but when I try to run this in Chrome, the marker looses the 'bounce' functionality, the 'reverse geocode' doesn't run and in the error console I receive the following error:
Uncaught ReferenceError: reversegeocode is not defined at line 55 of my code which is:
reversegeocode(); I've done some reading on this and other sites and from reading the guidance I've tried changing this part of my code to this:
function geocodePosition(pos) {
var clickListener =
document.getElementById('findosgb36lat').value = this.mylat;
document.getElementById('findosgb36lon').value = this.mylon;
document.getElementById('address').value = this.myaddress;
if(bouncingMarker)
bouncingMarker.setAnimation(null);
if(bouncingMarker != this) {
this.setAnimation(google.maps.Animation.BOUNCE);
bouncingMarker = this;
}
else bouncingMarker = null;
}
geocoder.geocode({latLng: pos }, function(responses) {
if (responses && responses.length > 0) {
updateMarkerAddress(responses[0].formatted_address);
} else {
updateMarkerAddress('Cannot determine address at this location.');
}
});
}
function updateMarkerAddress(str) {
document.getElementById('address').value = str;
}
function getAddress(latlng) {
if (!geocoder) {
geocoder = new google.maps.Geocoder();
}
geocoder.geocode({ 'latLng': latlng }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
// Looping through the result
for (var i = 0; i < results.length; i++) {
if (results[0].formatted_address) {
document.getElementById('address').value =
results[0].formatted_address;
}
}
}
}
)
}
But unfortunately, this doesn't work and actually creates more problems with syntax errors.
I'm relatively new to Javascript, so perhaps I've totally misunderstood,. But I just wondered whether someone could possibly take a look at this please and let me know where I'm going wrong?
Many thanks and kind regards
Code feedback:
What is the second line in your code: var clickListener = meant to do (something is missing)?
Both of your calls to geocoder.geocode pass an object with a property named: latLng; the object passed should match the structure of google.maps.GeocoderRequestapi-doc, which has properties named: address, bounds, location, and region. I suggest you change the name of these properties from: latLng to location.
I'm not sure of the context of the code shown, but the usage of this in this code section looks suspicious:
if(bouncingMarker != this) {
this.setAnimation(google.maps.Animation.BOUNCE);
bouncingMarker = this;
}
It looks like you are within a global function, so it looks like the use of this may not make sense here?
That's all I see after a first pass; hope this helps you -