Turn geolcation in city name code doesn't seem to work - javascript

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

Related

How to reverse geocode with maps?

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!");
}

Lime Survey - geolocation response (city, country) params returns in end url

LimeSurvey - click survey url, asks the user to allow or block location
ie. geolocation script run & return the current city & country in the end url.
It is possible or not. Below is my script, how to implement this in lime survey.
Any Suggestions, please
<script type="text/javascript">
var geocoder;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
}
function initMap(){
}
//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 codeLatLng(lat, lng) {
alert("Latitude: "+lat);
alert("Longtude: "+lng);
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({'latLng': 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;
}
if(results[0].address_components[i].types[b] == 'country'){
country = results[0].address_components[i];
break;
}
}
}
//city data
alert(city.short_name + " " + city.long_name)
//country data
alert(country.short_name + " " + country.long_name)
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
} </script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&callback=initMap"
type="text/javascript"></script>
Any help? Thanks in advance.
If your code work (else : review your code first). I spoke only for LimeSurvey part.
Create a multiple text question type :
code GEO
Add 2 sub question code CITY and CONTRY
Add the class (using advanced settings) hidden then the question are not shown.
Deactivate HTML editor and put your script inside a jquery ready (alternate solution use addScriptToQuestion plugin)
Add a space or a line feed after each { you have in your js code (and a space before each } )
replace you last alert (where you have city.data and coutry.data) by
$("#answer{SGQ}CITY").val(city.short_name + " " + city.long_name); for city
$("#answer{SGQ}COUNTRY").val(country.short_name + " " + country.long_name); for country
You can use {GEO_CITY} and {GEO_COUNTRY} in the survey (after this page)
Then you can use it in your url http://example.org/?city={GEO_CITY}&country={GEO_COUNTRY}
Using LimeSurvey 2.50 and up version (else need some javascript to hide the question)
This abbreviated version works for me when placed in the source of a hidden multiple-short-text question as Denis suggests:`
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(){
console.log("Geocoder failed");
}
function codeLatLng(lat, lng) {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({
'latLng': latlng },
function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
for (var i=0; i<results[0].address_components.length; i++) {
for (var b=0;b<results[0].address_components[i].types.length;b++) {
// Find city name
// There are different types that might hold a city
// "locality" works for most of North America
// See here for types - https://developers.google.com/maps/documentation/geocoding/intro
if (results[0].address_components[i].types[b] == "locality") {
//this is the object you are looking for
city= results[0].address_components[i];
break;
}
// Find country name
if(results[0].address_components[i].types[b] == 'country'){
country = results[0].address_components[i];
break;
}
}
}
// City data
//console.log(city.short_name + " " + city.long_name);
$("#answer{SGQ}CITY").val(city.long_name);
// Country data
//console.log(country.short_name + " " + country.long_name);
$("#answer{SGQ}COUNTRY").val(country.long_name);
}
else {
console.log("No results found");
}
} else {
console.log("Geocoder failed due to: " + status);
}
});
}
`

returning variable from javascript function

I'm trying to return longitude and latitude from this function, I can console.log both of them, but when I try to return one of them, I get undefined.
How can I return latitude, longitude?
function latLong(location) {
var geocoder = new google.maps.Geocoder();
var address = location;
var longitude;
var latitude;
geocoder.geocode({
'address': address
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
latitude = results[0].geometry.location.lat();
longitude = results[0].geometry.location.lng();
} else {
alert("Geocode was not successful for the following reason: " + status);
}
console.log(longitude);
});
}
The geocoder is asynchronous, and you can't return data from an asynchronous function, you could however use a callback
function latLong(location, callback) {
var geocoder = new google.maps.Geocoder();
var address = location;
var longitude;
var latitude;
geocoder.geocode({
'address': address
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
latitude = results[0].geometry.location.lat();
longitude = results[0].geometry.location.lng();
callback(latitude, longitude);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
and to use it do
latLong(location, function(lat, lon) {
// inside this callback you can use lat and lon
});
You don't.
The generally used technique is to pass a callback to latLong function as a parameter, and run this function when you receive the result.
Something like:
function latLong(location, callback) {
var geocoder = new google.maps.Geocoder();
var address = location;
var longitude;
var latitude;
geocoder.geocode({
'address': address
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
latitude = results[0].geometry.location.lat();
longitude = results[0].geometry.location.lng();
callback(latitude, longitude);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
console.log(longitude);
});
}

Why is this variable undefined or not returned?

I have the following code:
/*
* converts a string to geolocation and returns it
*/
function stringToLatLng(string){
if(typeof string == "string"){
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': string}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
console.log("LatLng: "+results[0].geometry.location);
return results[0].geometry.location;
} else {
console.log("Geocode was not successful for the following reason: " + status);
}
});
}
}
the LatLng prints the correct location to the console, but when I write this:
var pos = stringToLatLng('New York');
console.log(pos);
I get undefined back. Why is that? thanks
Something like this:
function stringToLatLng(strloc, callback){
if(typeof string == "string"){
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': strloc}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
callback.call({}, results[0].geometry.location);
} else {
console.log("Geocode was not successful for the following reason: " + status);
}
});
}
}
stringToLatLng('New York', function(pos){
console.log(pos);
});
In your code, when you return, you are actually returning from the function(results, status){..} function, not the stringToLatLng function, as said in the comments its an asynchronous call, so you must use a callback.
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
ref:
Javascript geocoding from address to latitude and longitude numbers not working

How do I return a variable from Google Maps JavaScript geocoder callback?

I am working with the google maps API and whenever I return the variable to the initialize function from the codeLatLng function it claims undefined. If I print the variable from the codeLatLng it shows up fine.
var geocoder;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(40.730885,-73.997383);
var addr = codeLatLng();
document.write(addr);
}
function codeLatLng() {
var latlng = new google.maps.LatLng(40.730885,-73.997383);
if (geocoder) {
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
return results[1].formatted_address;
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
}
prints out undefined
If I do:
var geocoder;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(40.730885,-73.997383);
codeLatLng();
}
function codeLatLng() {
var latlng = new google.maps.LatLng(40.730885,-73.997383);
if (geocoder) {
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
document.write(results[1].formatted_address);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
}
prints out New York, NY 10012, USA
You can't return the value from the function, the value doesn't exist yet when the function returns.
The geocode method makes an asynchonous call and uses a callback to handle the result, so you have to do the same in the codeLatLng function:
var geocoder;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(40.730885,-73.997383);
codeLatLng(function(addr){
alert(addr);
});
}
function codeLatLng(callback) {
var latlng = new google.maps.LatLng(40.730885,-73.997383);
if (geocoder) {
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
callback(results[1].formatted_address);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
}
You're making an asynchronous request, your codeLatLng() function has finished and returned long before the geocoder is done.
If you need the geocoder data to continue, you'll have to chain your functions together:
function initialize() {
geocoder = new google.maps.Geocoder();
codeLatLng();
}
function codeLatLng() {
var latlng = new google.maps.LatLng(40.730885,-73.997383);
if (geocoder) {
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
initContinued(results[1].formatted_address);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
}
function initContinued(addr) {
alert(addr);
}
You can get value using localstorage.
geocoder.geocode({
'address': address,
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
}
localStorage.setItem("endlat", latitude);
localStorage.setItem("endlng", longitude);
});
var end_lat = localStorage.getItem("endlat");
var end_lng = localStorage.getItem("endlng");
But it returns previous value.. Returns current value when we click twice...
pass geocoder as a parameter to the codeLatLng() function.
function codeLatLng(geocoder) {
call it like so in your initialize function:
var addr = codeLatLng(geocoder);
That return is not returning from codeLatLng; it's returning from the anonymous function being passed to geocoder.geocode.
I think you'll need to pass the data using another mechanism e.g. a global variable

Categories

Resources