Undefined Variable/Value - javascript

what am I missing here?
I am creating a simple map app and intend to use the lat/lon coords for some ajax/php calls to a couple of api's.
I cant seem access the value of an array (which I will then later use in the ajax call).
I've had similar problem before and resorted to taking the values from the HTML element, which makes no sense.
window.addEventListener('load', () => {
let latlon = []
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
document.getElementById("information").innerHTML = "Geolocation is not supported by this browser.";
}
}
function showPosition(position) {
let lat = position.coords.latitude;
let long = position.coords.longitude;
latlon.push(lat, long)
document.getElementById("information").innerHTML = `lat: ${lat}, long: ${long}`
}
getLocation()
console.log(latlon[0]) // returns undefined
console.log(latlon) // returns array with the 2 coords
//code continues......
in short my question is why does the first console log return undefined and how would I extract the value as string to allow me to insert in to the ajax call.
thanks in advance

Related

Get country and state name from lat and lng in Geocode [duplicate]

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.

Saving Geolocation to an array value returns [object, Object]

I've been trying to search a solution to this one, but I just can't find it.
I am writing a code which saves data to the browsers local storage as jSon. The code works fine but i should add geolocation to every data saved. I can get the coordinates to show in a div, but I am not able to save that same data to jSon -file.
The code goes like this:
$(document).ready(function(){
var selected_index = -1;
var theArray = [];
var operation = "A";
if(localStorage.getItem("ID") != null) {
}
//***********************************************************************
$("#saveButton").click(function(){
if(operation == "A" && $("#input1").val() != ""){
//Now trying to get the geolocation
var x = document.getElementById("DivId"); //works when targeted to a div
alert(x); //This returns [object
HTMLDivElement]
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
x = "Geolocation is not supported by this browser.";
}
}
function showPosition(position) {
x = "Latitude: " + position.coords.latitude +
"<br>Longitude: " + position.coords.longitude;
}
getLocation();
var object = {
value1 : $("#input1").val(),
value2 : $("#input2").val(),
value3 : $("#input3").val(),
value4 : $("#input4").val(),
value5 : $("#input5").val(),
time : Date(),
place: x //This is where the location is saved
//but returns [object, Object]
}
theArray.push(object);
localStorage.setItem("ID",JSON.stringify(TheArray));
}
console.log(x); //for testing, returns: <div id="DivID"
style="display: none;"></div>
$("#input1").val("");
$("#input2").val("");
$("#input3").val("");
$("#input4").val("");
$("#input5").val("");
$("#input1").focus();
});
Clearly, I am trying to save the location data in a wrong form but how is it done correctly? Thank's for the help in advance!!
Your problem is with asynchronous requests.
When you call getPosition(), you are calling getCurrentPosition(showPosition). The problem here is that this function executes asynchronously. Afer calling it, it runs in the background and your code continues executing without delay, so when you define the object variable, showPosition has not been called, and so x contains the initial value you gave it, which is a HTMLDivElement.
To avoid this, you should define the object variable inside the showPosition callback, and save it from there, too, as you don't ever know when that method will be called. For starters, the user must give permission for the page to get their current location. The user can deny this, or ignore it, and in this case the callback function may never get called. I mean, you might know if there has been an error (getCurrentPosition accepts an error callback) but it is possible that you never receive an answer to your request.
Besides, there are other problems with this code, because you are assigning x to a DIV element, and then you assign it to a string. I imagine you really want to add that string as a child node of the DIV, so you should do:
x.appendChild(document.createTextNode('geolocalization is not supported in this browser'));

Centering a map with Geolocation

I am teaching myself scripting and have learned a lot. I am, however, stuck at this one point. I am wanting to display a weather map and have it center to the users location. Here is what I have in the body of my html so far..
<div id="map-canvas"></div>
<div id="loading">Loading animation layers... <br>
<span id="progress"></span>% done.
</div>
<script type="text/javascript">
var map, radar, satellite;
var animationSync;
// GeoLocation Services
function showLocation(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
}
function errorHandler(err) {
if(err.code == 1) {
alert("Error: Access is denied!");
}
else if( err.code == 2) {
alert("Error: Position is unavailable!");
}
}
function getLocation(){
if(navigator.geolocation){
// timeout at 60000 milliseconds (60 seconds)
var options = {timeout:60000};
navigator.geolocation.getCurrentPosition(showLocation, errorHandler, options);
}
else{
alert("Sorry, browser does not support geolocation!");
}
}
// End GeoLocation Services
map = new aeris.maps.Map('map-canvas', {zoom: 9, center: [36.0462, -96.9942]});
// here is what I am wanting to do instead of the above line..
// map = new aeris.maps.Map('map-canvas', {zoom: 9, center: [latitude +',' + longitude]});
I can display the map perfectly if I hard code the LAT and LON but thats not what I need. I am confident my GeoLocation routine is working as the console in my browser does not show any errors, its only when I try to center the map using LAT and LONG as variables that I have a problem. I am hoping this is just a syntax type issue, but I just don't know enough to figure this out. I have also tried using the map.setCenter command but can't figure where to use it so it works.
Thanks in advance for any help.
Just replace the last line by
map = new aeris.maps.Map('map-canvas', {zoom: 9, center: [latitude, longitude]});
The quotes were not needed and transformed your array with 2 values in an array with a single string value
Current issue
The issue right now is you're performing string concatenation with latitude and longitude. You can just use them as normal inside the array:
map = new aeris.maps.Map('map-canvas', {zoom: 9, center: [latitude, longitude]});
More info that may be of use:
The thing to remember is that both these variables need to be in scope, which they currently aren't. latitude and longitude exist only inside showLocation(), and to further complicate things, it's a callback which means your new aeris.maps.Map() will fail because neither values are set.
If you're just trying to display a map around the position of the current user, this should do it:
var map, radar, satellite;
var animationSync;
// GeoLocation Services
function showLocation(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
map = new aeris.maps.Map("map-canvas", {
zoom: 9,
center: [latitude, longitude]
});
}
function errorHandler(err) {
if (err.code == 1) {
alert("Error: Access is denied!");
} else if (err.code == 2) {
alert("Error: Position is unavailable!");
}
}
function getLocation() {
if (navigator.geolocation) {
// timeout at 60000 milliseconds (60 seconds)
var options = {
timeout: 60000
};
navigator.geolocation.getCurrentPosition(showLocation, errorHandler, options);
} else {
alert("Sorry, browser does not support geolocation!");
}
}
getLocation();
It's a bit tricky since the action happens asynchronously, meaning anything you do with map have to happen after showLocation is called.

Function after checking for Geolocation doesn't start

I'm building a small web app that takes a form input (name) + the geolocation of the user and puts this in localstorage arrays. I'm new to JS, but I've already got the part that takes care of the name complete. I'm now trying to expand it to the point where the Latitude + Longitude get stored in a localstorage array at the moment when a user presses submit, but somehow the function that does this won't start/set through.
window.onload = function() {
// Read value from storage, or empty array
var names = JSON.parse(localStorage.getItem('locname') || "[]");
var lat = JSON.parse(localStorage.getItem('latitude') || "[]");
var long = JSON.parse(localStorage.getItem('longitude') || "[]");
function initCoords() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(saveData);
console.log('This works');
} else {
showError("Your browser does not support Geolocation!");
}
}
function saveData(data){
console.log('But does it get here?');
//Push Users Input value
var data = document.getElementById("locationName").value;
names.push(data);
localStorage.setItem('locname', JSON.stringify(names));
//Push Latitude
var latitude = position.coords.latitude;
lat.push(latitude);
localStorage.setItem('latitude', JSON.stringify(latitude));
//Push Longitude
var longitude = position.coords.longitude;
long.push(longitude);
localStorage.setItem('longitude', JSON.stringify(longitude));
}
document.querySelector('#saveData').onclick = initCoords;
}
I have a button with the id saveData. My earlier version of this script without geolocation worked perfectly, there I started the saveData function by clicking the button. In this case I first wanted to check if the user had geolocation available, therefor i created the initCoords function.
I tried to use console log to see where my function ends, it somehow doesnt get to the 'But does it get here' in saveData.
I think your issue is this
I have a button with the id saveData
you also have a function with that name
function saveData(data){ ....
If the function is in the global scope, it will be set as window.saveData, and then when the element with that ID comes after the function, the browser stores elements as ID's on the window object, so it stores window.saveData as the element and overwrites the function.
The solution is to change either the name of the function or the ID of the element.
EDIT:
Here are a few more issues:
You're not declaring position anywhere, you have data as an argument to the callback
function saveData(data){
var data = document.getElementById("locationName").value;
....
That doesn't make any sense, you probably meant
function saveData(position){
var data = document.getElementById("locationName").value;
....
Then there's the fact that you're storing the numbers from the position object in localStorage, not the arrays:
var latitude = position.coords.latitude;
lat.push(latitude);
localStorage.setItem('latitude', JSON.stringify(latitude));
See how you're pushing data to lat, but you're saving latitude, the number, not the array, so the next time around you're trying to push to a number not an array and you get an error, it should be
var latitude = position.coords.latitude;
lat.push(latitude);
localStorage.setItem('latitude', JSON.stringify(lat));
but now you've already stored the numbers in localStorage so you'll get an error before that you get that far in the script, you have to clear your localStorage as well, it can be done in the browser console or like this
localStorage.removeItem('locname');
localStorage.removeItem('latitude');
localStorage.removeItem('longitude');
and you have to to this once to clear it before you start trying the working code, which should look like this
window.onload = function () {
localStorage.removeItem('locname');
localStorage.removeItem('latitude');
localStorage.removeItem('longitude');
// Read value from storage, or empty array
var names = JSON.parse(localStorage.getItem('locname') || "[]");
var lat = JSON.parse(localStorage.getItem('latitude') || "[]");
var long = JSON.parse(localStorage.getItem('longitude') || "[]");
function initCoords() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(saveData);
console.log('This works');
} else {
showError("Your browser does not support Geolocation!");
}
}
function saveData(position) {
var data = document.getElementById("locationName").value;
names.push(data);
localStorage.setItem('locname', JSON.stringify(names));
var latitude = position.coords.latitude;
lat.push(latitude);
localStorage.setItem('latitude', JSON.stringify(lat));
var longitude = position.coords.longitude;
long.push(longitude);
localStorage.setItem('longitude', JSON.stringify(long));
}
document.getElementById('saveData').onclick = initCoords;
}

Passing HTML5 geolocation data to a variable

I'm really new to Javascript, and I'm trying to jump into it.
I want to have a script get geolocation data and pass it to a variable, and then have the information displayed in an alert.
I have a jsFiddle here: http://jsfiddle.net/yJrtR/
When I run it, I get an "undefined" in the alert box. Can someone help me with this?
Here is my code:
function lat() {
navigator.geolocation.getCurrentPosition(function (position) {
var lat = position.coords.latitude;
var lon = position.coords.longitude;
}, function (error) {
console.log("Something went wrong: ", error);
});
}
function alert() {
var lat="";
var lon="";
lat();
alert("lat + lon");
}
There are several weird things in your code. Your fiddle is set to run onLoad, which means the functions you defined in your JavaScript won't be available globally - they'll be defined in the window.onload handler...which doesn't code outside of that to access them (especially inline event handlers). This is a perfect example of why not to use inline event handlers (even though the problem is really because of the jsFiddle settings).
So that means, when you call alert(); in your button's inline click handler, it calls the native window.alert() function, which brings up a dialog window. Since you pass nothing to it, it shows undefined. It's not actually calling your created alert function.
Also, since the getCurrentPosition method seems to be asynchronous, you should pass a callback function to lat, so that you can call it when it gets position.
Try this:
function lat(callback) {
navigator.geolocation.getCurrentPosition(function (position) {
var lat = position.coords.latitude;
var lon = position.coords.longitude;
callback.call(null, lat, lon);
}, function (error) {
console.log("Something went wrong: ", error);
});
}
function getPosition() {
lat(function (latitude, longitude) {
alert("lat: " + latitude + ", lon: " + longitude);
});
}
http://jsfiddle.net/yJrtR/1/
UPDATE:
Per your comment, if you'd like it to be shown "live", you can use something like this:
window.onload = function () {
var latElement = document.getElementById("lat"),
lonElement = document.getElementById("lon"),
lastUpdatedElement = document.getElementById("last_updated"),
getPositionOptions = {
enableHighAccuracy: false,
timeout: 10000,
maximumAge: 0
},
getPos = function () {
console.log("getPos function called");
navigator.geolocation.getCurrentPosition(function (position) {
console.log("Successfully retrieved position: ", position);
var coords = position.coords;
latElement.innerHTML = coords.latitude;
lonElement.innerHTML = coords.longitude;
lastUpdatedElement.innerHTML = new Date(position.timestamp);
setTimeout(getPos, 5000);
}, function (error) {
console.log("Something went wrong retrieving position: ", error);
setTimeout(getPos, 5000);
}, getPositionOptions);
};
getPos();
};
with the following HTML (just to "simulate" the dialog you speak of):
<div id="dialog">
<div>Your latitude is: <span id="lat"></span></div>
<div>Your longitude is: <span id="lon"></span></div>
<div>Last Updated: <small id="last_updated"></small></div>
</div>
DEMO: http://jsfiddle.net/yJrtR/12/
So what this code does is from the time the window has loaded, it continually re-gets the geo position. There are special options you can pass to the getCurrentPosition, that I declared in getPositionOptions.
As I said before, the getCurrentPosition is asynchronous, so the position could be retrieved at any time after calling getCurrentPosition is called...that's what the callbacks are for. In the options object, I set a timeout - 10000 - that says "don't take any longer than 10 seconds to retrieve the position", and if it does, it will call the error callback. The maximumAge option makes sure it always tries to grab the current location (instead of using a cached version, within a certain period of time.
So when either callback is called (could be 1 second later, could be 20 seconds later...although we set a timeout of 10 seconds), it will update the HTML with the details, and then do it all again 5 seconds later - that's what the setTimeout is for. This is because if we continually tried to get the position (without any kind of delay), the page would be very busy getting the position. 5 second delays, or even up to 15, should be fine.
Reference:
https://developer.mozilla.org/en-US/docs/DOM/window.navigator.geolocation.getCurrentPosition
UPDATE:
There is a specific method for the geolocation feature that lets you watch the position, called watchPosition, doing exactly what I was trying to emulate, but more efficiently. You could try this:
window.onload = function () {
var latElement = document.getElementById("lat"),
lonElement = document.getElementById("lon"),
lastUpdatedElement = document.getElementById("last_updated"),
watchPositionOptions = {
enableHighAccuracy: false,
timeout: 10000,
maximumAge: 0
};
navigator.geolocation.watchPosition(function (position) {
console.log("Successfully retrieved position: ", position);
var coords = position.coords;
latElement.innerHTML = coords.latitude;
lonElement.innerHTML = coords.longitude;
lastUpdatedElement.innerHTML = new Date(position.timestamp);
}, function (error) {
console.log("Something went wrong retrieving position: ", error);
}, watchPositionOptions);
};
DEMO: http://jsfiddle.net/yJrtR/14/
Reference:
https://developer.mozilla.org/en-US/docs/DOM/window.navigator.geolocation.watchPosition?redirect=no

Categories

Resources