Function after checking for Geolocation doesn't start - javascript

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;
}

Related

Undefined Variable/Value

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

Any way to ensure I get the return value from a sequence of async functions

I'm working with repos and trying to get the pull requests, issues and commits for a repo. I have the following code:
const axios = require('axios');
var gitPullApiLink = "https://api.github.com/repos/alirezadir/Production-Level-Deep-Learning/pulls"
var listOfCommits = [];
var listOfSHAs = [];
var mapOfInfoObjects = new Map();
var mapPullRequestNumberToCommits = new Map();
var mapPRNumbersToCommitObjects = new Map();
var listOfPrObjects = [];
var setOfFileObjects = new Set();
var listOfNumbersOfTargetedIssues = [];
var mapPRnumberToCloseOpenDateObjects = new Map();
class PullRequestParser {
async getListOfPullRequests(pullrequestLink) {
const message = await axios.get(pullrequestLink);
//console.log(message);
listOfPrObjects = message['data'];
}
async getCommitsForEachPullRequestAndPRinformation() {
var listOfPrNumbers = [];
var k;
// this loop will just make a list of Pull Request Numbers
for (k = 0; k < listOfPrObjects.length; k++){
var currPrNumber = listOfPrObjects[k]['number'];
listOfPrNumbers.push(currPrNumber);
}
// I created a separate list just because... I did it this way because on the github API website it seems
// like the pull request has the same number as the issue it affects. I explain how you can see this down below
listOfNumbersOfTargetedIssues = listOfPrNumbers;
// next loop will make objects that contain information about each pull request.
var n;
for (n = 0; n < listOfPrNumbers; n++){
var ApiLinkForEachPullRequest = gitPullApiLink + "/" + listOfPrNumbers[n];
const mes = await axios.get(ApiLinkForEachPullRequest);
var temp = {OpeningDate: mes['data']['created_at'],
ClosingDate: mes['data']['closed_at'],
IssueLink: mes['data']['_links']['issue']['href']};
//mapPRnumberToCloseOpenDateObjects will be a map where the key is the pull request number and the value
// is the object that stores the open date, close date, and issue link for that pull request. The reason
// why I said I think the pull request number is the same as the number of the issue it affects is because
// if you take any object from the map, say you do mapPRnumberToCloseOpenDateObjects.get(10). You'll
// get an object with a pull request number 10. Now if you take this object and look at it's "IssueLink"
// field, the very last part of the link will have the number 10, and if you look at the github API
// it says for a single issue, you do: /repos/:owner/:repo/issues/:issue_number <---- As you can see,
// the IssueLink field will have this structure and in place of the issue_number, the field will be 10
// for our example object.
mapPRnumberToCloseOpenDateObjects.set(listOfPrNumbers[n], temp);
}
//up to this point, we have the pull request numbers. we will now start getting the commits associated with
//each pull request
var j;
for (j = 0; j < listOfPrNumbers.length; j++){
var currentApiLink = gitPullApiLink + "/" + listOfPrNumbers[j] + "/commits";
const res = await axios.get(currentApiLink);
//here we map a single pull request to the information containing the commits. I'll just warn you in
// advance: there's another object called mapPRNumbersToCommitObjects. THIS MAP IS DIFFERENT! I know it's
// subtle, but I hope the language can make the distinction: mapPullRequestNumberToCommits will just
// map a pull request number to some data about the commits it's linked to. In contrast,
// mapPRNumbersToCommitObjects will be the map that actually maps pull request numbers to objects
// containing information about the commits a pull request is associated with!
mapPullRequestNumberToCommits.set(listOfPrNumbers[j], res['data']);
}
// console.log("hewoihoiewa");
}
async createCommitObjects(){
var x;
// the initial loop using x will loop over all pull requests and get the associated commits
for (x = 0; x < listOfPrObjects.length; x++){
//here we will get the commits
var currCommitObjects = mapPullRequestNumberToCommits.get(listOfPrObjects[x]['number']);
//console.log('dhsiu');
// the loop using y will iterate over all commits that we get from a single pull request
var y;
for (y = 0; y < currCommitObjects.length; y++){
var currentSHA = currCommitObjects[y]['sha'];
listOfSHAs.push(currentSHA);
var currApiLink = "https://api.github.com/repos/alirezadir/Production-Level-Deep-Learning/commits/" + currentSHA;
const response = await axios.get(currApiLink);
//console.log("up to here");
// here we start extracting some information from a single commit
var currentAuthorName = response['data']['commit']['committer']['name'];
var currentDate = response['data']['commit']['committer']['date'];
var currentFiles = response['data']['files'];
// this loop will iterate over all changed files for a single commit. Remember, every commit has a list
// of changed files, so this loop will iterate over all those files, get the necessary information
// from those files.
var z;
// we create this temporary list of file objects because for every file, we want to make an object
// that will store the necessary information for that one file. after we store all the objects for
// each file, we will add this list of file objects as a field for our bigger commit object (see down below)
var tempListOfFileObjects = [];
for (z = 0; z < currentFiles.length; z++){
var fileInConsideration = currentFiles[z];
var nameOfFile = fileInConsideration['filename'];
var numberOfAdditions = fileInConsideration['additions'];
var numberOfDeletions = fileInConsideration['deletions'];
var totalNumberOfChangesToFile = fileInConsideration['changes'];
//console.log("with file");
var tempFileObject = {fileName: nameOfFile, totalAdditions: numberOfAdditions,
totalDeletions: numberOfDeletions, numberOfChanges: totalNumberOfChangesToFile};
// we add the same file objects to both a temporary, local list and a global set. Don't be tripped
// up by this; they're doing the same thing!
setOfFileObjects.add(tempFileObject);
tempListOfFileObjects.push(tempFileObject);
}
// here we make an object that stores information for a single commit. sha, authorName, date are single
// values, but files will be a list of file objects and these file objects will store further information
// for each file.
var tempObj = {sha: currentSHA, authorName: currentAuthorName, date: currentDate, files: tempListOfFileObjects};
var currPrNumber = listOfPrObjects[x]['number'];
console.log(currPrNumber);
// here we will make a single pull request number to an object that will contain all the information for
// every single commit associated with that pull request. So for every pull request, it will map to a list
// of objects where each object stores information about a commit associated with the pull request.
mapPRNumbersToCommitObjects.set(currPrNumber, tempObj);
}
}
return mapPRNumbersToCommitObjects;
}
startParsingPullRequests() {
this.getListOfPullRequests(gitPullApiLink + "?state=all").then(() => {
this.getCommitsForEachPullRequestAndPRinformation().then(() => {
this.createCommitObjects().then((response) => {
console.log("functions were successful");
return mapPRNumbersToCommitObjects;
}).catch((error) => {
console.log("printing first error");
console.log(error);
})
}).catch((error2) => {
console.log("printing the second error");
console.log(error2);
})
}).catch((error3) => {
console.log("printing the third error");
console.log(error3);
});
}
//adding some getter methods so they can be used to work with whatever information people may need.
//I start all of them with the this.startParsingPullRequests() method because by calling that method it gets all
// the information for the global variables.
async getSetOfFileObjects(){
var dummyMap = this.startParsingPullRequests();
return setOfFileObjects;
}
async OpenCloseDateObjects(){
var dummyMap = this.startParsingPullRequests();
return mapPRnumberToCloseOpenDateObjects;
}
async getNumbersOfTargetedIssues(){
var dummyMap = this.startParsingPullRequests();
return listOfNumbersOfTargetedIssues;
}
}
I'm trying to make a "dummy map" that gets the return value of calling startParsingPullRequests() in the following way:
var dummy = new PullRequestParser();
var dummyMap = dummy.startParsingPullRequests();
console.log(dummyMap);
But I end up with the following output:
undefined
3
1
functions were successful
I understand dummyMap is undefined because startParsingPullRequests() makes a series of async calls, but I'm wondering how do I go about making sure dummyMap gets its value and then prints. Thanks!
Since you already have code using async/await, why are you changing to .then? When you are using .then/.catch, it can be a lot harder to tell where things are waiting and what they are waiting on.
Here is your function converted to use async/await. With this change, you can await this function (though in that case, you might want to not catch the error and let the caller handle it, otherwise you need to check the return for undefined to "detect" the error). I've also simplified the error handling (but again, unless the code here can "fix" the problem, no reason to handle it here)
async startParsingPullRequests() {
try {
await this.getListOfPullRequests(gitPullApiLink + "?state=all");
await this.getCommitsForEachPullRequestAndPRinformation();
const response = await this.createCommitObjects();
console.log("functions were successful");
return mapPRNumbersToCommitObjects;
} catch (error) {
console.log("printing error");
console.log(error);
}
}

How to retain a JavaScript value on a different page

I have a function that get a value that needs to be accesed across multiple pages (function below).
var currentProperty = '';
function goTo(ele){
var firstLine = ele.getAttribute('value');
var user = firebase.auth().currentUser;
var ref = firebase.database().ref().child("users").child(user.uid).child('rentingAddresses');
ref.orderByChild("firstLine").equalTo(firstLine).once("value", function(snapshot) {
snapshot.forEach(function(child) {
currentProperty = child.key;
console.log(currentProperty);
});
});
}
When the function is fired, it saves the value into the variable but when I access it on another page the value has gone. I've tried using the following method:
window.onload = function() {
var currentProperty = 'nothing'
localStorage.setItem("prop", currentProperty);
}
function goTo(ele){
var firstLine = ele.getAttribute('value');
var user = firebase.auth().currentUser;
var ref = firebase.database().ref().child("users").child(user.uid).child('rentingAddresses');
ref.orderByChild("firstLine").equalTo(firstLine).once("value", function(snapshot) {
snapshot.forEach(function(child) {
currentProperty = child.key;
console.log(currentProperty);
});
});
}
But it doesnt seem to work either. Is there any other way to retain the value once I leave the page containing the function?
TYIA.
There are a few problems in your code:
You're never setting the value that you read from the database into local storage.
You're never reading the value from local storage in the code you provided.
setting the value that you read from the database into local storage
You're only setting the value to local storage once in:
window.onload = function() {
var currentProperty = 'nothing'
localStorage.setItem("prop", currentProperty);
}
This means that every time the page loads you set prop='nothing' in local storage. Nothing else ever happens.
You'll probably also want to write the value that you read from the database into local storage. In that case, you should do so in the callback from your once("value" handler:
ref.orderByChild("firstLine").equalTo(firstLine).once("value", function(snapshot) {
snapshot.forEach(function(child) {
currentProperty = child.key;
localStorage.setItem("prop", currentProperty);
});
});
With this change you'll be updating the local storage to the value that you read from the database.
reading the value from local storage in the next page
You'll need to read the value back from local storage in the next page. Given the code you've already shown, I expect you'll do this with something like:
window.onload = function() {
var currentProperty = localStorage.getItem("prop");
// TODO: do something with currentProperty
}
Note that could also simply re-read the value from the database and using it:
ref.orderByChild("firstLine").equalTo(firstLine).once("value", function(snapshot) {
snapshot.forEach(function(child) {
currentProperty = child.key;
// TODO: do something with currentProperty
});
});

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'));

JavaScript query does not work correctly within a function, no results are shown

UPDATE.
I've now added a screen shot of the parse data browser showing a row using customer number 21.
UPDATE.
Based on the comments below and the suggested answer I have updated my code. It functions without error but does not appear to have the desired result.
I see two issues.
Once, I don't see anything being stored in the cname or cnumber variables, they appear undefined.
Secondly, I wanted the result of the user typing in a number (searchnumber) into the input box that matches that stored (cnumber) in parse to then return this parse object to the user.
Whats wrong with this code? it runs in the browser without errors in Chrome dev tools, but does not appear to return the "CustomerObject" If I run it outside of the function and without the search button it will work, be it only return an empty object.
Is there a problem with my code structure?
HTML
<input type="text" name="searchnumber" id="searchnumber" value="" placeholder="Customer Number"/>
<button type="submit" onclick = "search()" >Find</button>
JS
function search() {
var CustomerObject = Parse.Object.extend("CustomerObject");
var retrieve = new Parse.Query(CustomerObject);
retrieve.equalTo("customernumber", $('#searchnumber').val());
retrieve.first({
success: function(retrieveResults)
{
}
});
var cname = retrieve.get("customername");
var cnumber = retrieve.get("customernumber");
};
Inside the success function, do this:
var cname = retrieveResults.get("customername");
var cnumber = retrieveResults.get("customernumber");
You should rename retrieveResults to object or customerObject or something.
You're trying to get customername and number from the query, not the retrieved object.
Full code:
function search() {
var CustomerObject = Parse.Object.extend("CustomerObject");
var retrieve = new Parse.Query(CustomerObject);
retrieve.equalTo("customernumber", $('#searchnumber').val());
retrieve.first({
success: function(customerObject) {
var cname = customerObject.get("customername");
var cnumber = customerObject.get("customernumber");
...
}
});
};

Categories

Resources