I am using leaflet to display markers on a map, when I click on a marker, I get its lat and lng, then I am sending these to google maps geocoder to retrieve the address name:
var markerCoords = [];
circle.on('click', function (e) {
var curPos = e.target.getLatLng();
markerCoords.push(curPos.lng);
markerCoords.push(curPos.lat);
geocodeLatLng();
});
var geocoder = new google.maps.Geocoder;
function geocodeLatLng(geocoder) {
var latlng = {lat: parseFloat(markerCoords[1]), lng: parseFloat(markerCoords[0])};
geocoder.geocode({'location': latlng}, function(results, status) {
if (status === 'OK') {
if (results[0]) {
console.log(results[0].formatted_address);
} else {
window.alert('No results found');
}
} else {
window.alert('Geocoder failed due to: ' + status);
}
});
}
But it gives me:
Cannot read property 'geocode' of undefined
NOTE
This line is fine
var latlng = {lat: parseFloat(markerCoords[1]), lng: parseFloat(markerCoords[0])};
As if I do console.log I get the correct lat and lng
You have a typo in your code. You aren't passing the reference to the geocoder into the geocodeLatLng function, so it is null inside the function:
var markerCoords = [];
circle.on('click', function (e) {
var curPos = e.target.getLatLng();
markerCoords.push(curPos.lng);
markerCoords.push(curPos.lat);
geocodeLatLng(geocoder); // <============================================== **here**
});
var geocoder = new google.maps.Geocoder;
function geocodeLatLng(geocoder) {
var latlng = {lat: parseFloat(markerCoords[1]), lng: parseFloat(markerCoords[0])};
geocoder.geocode({'location': latlng}, function(results, status) {
// ... code to process the result
});
}
This is probably because google api hasn't loaded yet, you can try loading it before other scripts, to make sure, check console.log("google api object is", geocoder) and check Geocode to verify whether google has loaded before calling the api.
Edit : you don't need geocoder as parameter in geocodeLatLng function,as pointed out by #geocodezip, it will be undefined if you don't pass it. Since parameter will get priority over outer scope when variable names are same.
Following procedure will give you the address of user's current position, you can pass any lat, lng and get its address:-
//getting location address from latitude and longitude with google api
navigator.geolocation.getCurrentPosition(success, error);
function success(position) {
var lat = position.coords.latitude;
var long = position.coords.longitude;
var geocoder = new google.maps.Geocoder;
console.log("google api object is", geocoder)
var latlng = { lat: lat, lng: long };
geocoder.geocode({ 'location': latlng }, function (results, status) {
if (status === 'OK') {
if (results[0]) {
console.log(results[0].formatted_address);// this will be actual full address
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
});
}
function error(err) {
alert("Allow location services!");
}
Related
I'm trying to set a Post Code in order to get Lat and Long Coordinates and place a marker on it. Until now, everything is fine.
The problem comes when I give a postcode input and it ends up making a marker somewhere in another part of the world.
Ex: I type 2975-435 and I get :
https://maps.googleapis.com/maps/api/geocode/json?address=2975-435&key=YOURKEY
"formatted_address" : "Balbey Mahallesi, 435. Sk., 07040 Muratpaşa/Antalya, Turquia",
And I want to make this postcode only be searched in Portugal.
https://maps.googleapis.com/maps/api/geocode/json?address=2975-435+PT
This way I get:
"formatted_address" : "2975 Q.ta do Conde, Portugal",
Exactly what I wanted.
The problem is, how do I make this in JS code?
Here is the code I have till now
function codeAddress () {
var lat = '';
var lng = '';
var address = document.getElementById("cp").value;
geocoder.geocode( { 'address': address},
function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
//Just to keep it stored
positionArray.push(new google.maps.LatLng(lat,lng));
//Make the marker
new google.maps.Marker({
position:new google.maps.LatLng(lat,lng),
map:map
});
}else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
Thank you
To restrict a result to certain country you can apply a component filtering:
https://developers.google.com/maps/documentation/javascript/geocoding#ComponentFiltering
So, your JavaScript code will be
function codeAddress () {
var lat = '';
var lng = '';
var address = document.getElementById("cp").value;
geocoder.geocode( {
'address': address,
componentRestrictions: {
country: 'PT'
}
},
function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
lat = results[0].geometry.location.lat();
lng = results[0].geometry.location.lng();
//Just to keep it stored
positionArray.push(new google.maps.LatLng(lat,lng));
//Make the marker
new google.maps.Marker({
position:new google.maps.LatLng(lat,lng),
map:map
});
}else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
You can see a component filtering in action using the Geocoder tool:
https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/utils/geocoder/#q%3D2975-435%26options%3Dtrue%26in_country%3DPT%26nfw%3D1
Hope it helps!
I have looked up answers on stackoverflow but can't seem to get it to work. This snippet of code does not set the var 'pos' to anything:
var geocoder= new google.maps.Geocoder();
var pos = geocoder.geocode({'address': getCookie('banner-location')}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
return {lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng()};
} else {
return {lat: 0, lng: 0};
}
});
I'm not completely familiar with the Google Maps API but from a quick glance from this Geocoding Service page it seems that you would need to set the pos variable within the geocode response callback function. The response callback function's return will not be geocode's return value. The following may help you out:
var geocoder= new google.maps.Geocoder();
// Create pos beforehand to use in the callback to retrieve the data
var pos = null;
geocoder.geocode({'address': getCookie('banner-location')}, function(results, status) {
// Check the status and set the pos variable here
if (status == google.maps.GeocoderStatus.OK) {
pos = {lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng()};
} else {
pos = {lat: 0, lng: 0};
}
});
Above I'm setting your pos variable within the geocode response callback.
I have the following code to display markers on a google map based upon an array of locations, however I have a mix of postcodes and Lat/longs, I've used the geocoder to convert the postcodes to lat/longs but can't then use them when I try and set a marker.
Thanks for any help!
var geocoder;
var map;
var pos;
var geoLat;
var geoLong;
var markers = [];
var bounds = new google.maps.LatLngBounds();
var locations = [
[null, 'London Eye, London', 51.503454,-0.119562, 4]
,[null, 'Palace of Westminster, London', 51.499633,-0.124755]
,[null, 'The London Dungeon', 'SE1 7PB', , 2] //Value with Postcode
];
function isNumber(o) { return ! isNaN (o-0) && o !== null && o !== "" && o !== false; }
function init() {
geocoder = new google.maps.Geocoder();
var num_markers = locations.length;
map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 10,
center: new google.maps.LatLng(locations[0][2], locations[0][3]),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
for (var i = 0; i < num_markers; i++) {
if (isNumber (locations[i][2]) && isNumber (locations[i][3])){
geoLat = locations[i][2]
geoLng = locations[i][3]
alert(typeof(geoLat) +' '+typeof(geoLng)) //generates a correct number number response
}else{
geocoder.geocode( { 'address': locations[i][2]}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
geoLat = results[0].geometry.location.lat()
geoLng = results[0].geometry.location.lng()
alert(typeof(geoLat) +' '+typeof(geoLng)) //generates a correct number number response
}
});
}
pos = new google.maps.LatLng(geoLat, geoLng); // Doesn't get value if a geocodes postcode added in
bounds.extend(pos);
map.fitBounds(bounds);
markers[i] = new google.maps.Marker({
position: pos,
map: map,
id: i,
title: locations[i][1]
});
}
}
google.maps.event.addDomListener(window, 'load', init);
The Geolocation request is an async call, which means that your script is running through while the API request isn´t finished yet.
Therefore you have two options.
Define the marker directly in the callback function
if (status == google.maps.GeocoderStatus.OK) { }
Or write sth. like a setMarker() function and call it in the callback.
function setMarker(lat, lng){}
In general it is a good practice to also make the Geocoding request a function, like:
doGeocode: function (address, postal_code, callback) {
console.log("TEST: " + address.toString());
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
'address': address,
'componentRestrictions': {
'postalCode': postal_code,
'country': 'de'
}
}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
console.log(results);
callback(results);
} else {
//Error handling
alert('Geocode was not successful for the following reason: ' + status);
}
});
if you want to call it now just do
doGeocode (adress, postal_code, function (response){
//do your stuff
)};
var geocoder;
var map;
var MapCenter, map, x, y, z;
function geocode(address, callback) {
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var city=geoip2.city();
map.setCenter(results[0].geometry.location);
map.fitBounds(results[0].geometry.bounds);
callback();
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
function initialize() {
geocoder = new google.maps.Geocoder();
var city=geoip2.city();
var mapOptions = {
zoom: 1,
}
map = new google.maps.Map(document.getElementById('map'), mapOptions);
geocode(city, function () {
MapCenter = map.getCenter();
x = MapCenter.lat(), y = MapCenter.lng(), window.z = 0;
myLatLng=new google.maps.LatLng(x,y);
}
This is what I have. As you can see the function geocode takes the city as an argument. The only problem is where to declare this city variable. As you can see I have tried doing it in the geocode function definition and the initialize function. both end up with an undefined result. Where am I supposed to declare this so that my geocode function runs without error?
OK upon further investigation, I think I have bigger problems. For some reason even the geoip samples are returning undefined values. for instance, the example on this page: http://dev.maxmind.com/geoip/legacy/javascript/. If you look at www.supercuber.com and click view source you can see I added their example but the javascript isn't working correctly. Im not sure why this is.
I'm trying to get a geolocation and turn that into text. I got code to do that but it gives me an error. How can this error be solved?
The error: TypeError: 'undefined' is not an object (evaluating 'geocoder.geocode')
The code:
var geocoder;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
}
//Get the latitude and the longitude;
function successFunction(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
codeLatLng(lat, lng)
}
function errorFunction(){
alert("Geocoder failed");
}
function initialize() {
geocoder = new google.maps.Geocoder();
}
function codeLatLng(lat, lng) {
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({'location':latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
console.log(results)
if (results[1]) {
//formatted address
alert(results[0].formatted_address)
//find country name
for (var i=0; i<results[0].address_components.length; i++) {
for (var b=0;b<results[0].address_components[i].types.length;b++) {
//there are different types that might hold a city admin_area_lvl_1 usually does in come cases looking for sublocality type will be more appropriate
if (results[0].address_components[i].types[b] == "administrative_area_level_1") {
//this is the object you are looking for
city= results[0].address_components[i];
break;
}
}
}
//city data
alert(city.short_name + " " + city.long_name)
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
To Reverse Geocode, the request structure contains latLng, not location
From the example in the documentation slightly modified (not tested):
function codeLatLng(lat, lng) {
// remove irrelevant code
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
Also, this is not correct, if you are going to use the first result (result[0]), you should check whether that existst (if results[0] ... not if results[1]):
if (results[1]) {
//formatted address
alert(results[0].formatted_address)
Looking at your jsfiddle, you are not loading the API correctly. Please see the documentation on the correct way(s) to load the API