I'm doing next:
First thing - I'm checking if I already have loaded latitude and longitude data. If I do have, I'm saving that into array named "location".
Second thing - if I don't have any loaded data, I'm trying to get current position. After that, I'm trying to save latitude and longitude for current position.
And, at the end, I'm calling setMap(); function where I check location array and where I'm generating a map.
Problem:
Well, as I said it...inside "getCurrentPosition", I'm trying to set current position into "location" array, and after that I'm trying to take those values inside setMap(); function. Here's the problem, but only when i set "location" values inside "getCurrentPosition". If I set "location" values manually before (from "data" array), everything works fine.
Also, when I call a setMap() function inside "getCurrentPosition", everything works fine...but when I call it from outside, won't work.
Can someone explain me what's going on and what can I do?
Here's my code:
location = new Array();
if (data.lat) {
location['lat'] = data.lat;
location['lng'] = data.lng;
} else {
if (!navigator.geolocation) {
//
} else {
navigator.geolocation.getCurrentPosition(function(position) {
location['lat'] = position.coords.latitude;
location['lng'] = position.coords.longitude;
});
}
}
setMap();
Thank you.
You are setting a different variable inside of getCurrentPosition.
I would suggest researching variable scope.
Check out this question.
--edit--
I did not realize that the function you were using was a part of Javascript, I thought you had written/gotten it from somewhere.
Also, I stand corrected about the scope. Since you are using an array, the scope is fine, you should be able to set it inside the callback function just fine.
I ran your code and got some strange printouts when I did a console.log on location.
I took a guess, and it appears that location is a reserved word. I bet that if you change the name of location to something else, your code should work fine.
--edit--
I should have realized this sooner actually, since location is the same as window.location, which is the browser bar location!
Related
Been trying for 1.5 hours. Can someone please help me out? "your post appears to contain code that is not properly formatted as code" issue.
Please can someone help me format this code?
It works now in this post, but not when making a new one...
Now I cannot make a new post for a day... What the...
FIXED: It appears that the browser output had to be in code layout.
This was my original question:
TITLE: Working with geolocation API - scope question
Hi all
I am working with Mapbox and am trying to update the vars lngreal and latreal (from default Greenwhich coordinates). The function initializeMap() is called during setup, and the idea is that it updates it with user's longlat coordinates if possible. When I run the code below...
function initializeMap() {
mapboxgl.accessToken = 'HIDDEN FOR THIS POST';
var lngreal = 0.0098;
var latreal = 51.4934;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(displayLocationInfo);
}
function displayLocationInfo(position) {
//Why does this not work to update the map zoom?
lngreal = position.coords.longitude;
latreal = position.coords.latitude;
console.log(lngreal);
console.log(latreal);
}
console.log(lngreal);
console.log(latreal);
// This adds the map to your page
var map = new mapboxgl.Map({
// container id specified in the HTML
container: 'map',
// style URL
style: 'mapbox://styles/mapbox/light-v10',
// initial position in [lon, lat] format
center: [lngreal, latreal],
// initial zoom
zoom: 14
});
// More code after this but not related
}
It shows the following in html inspector console:
play-mapboxscripts.js:21 0.0098
play-mapboxscripts.js:22 51.4934
play-mapboxscripts.js:17 4.9212796
play-mapboxscripts.js:18 52.333704999999995
Why does it first show the last console.log lines, instead of the console.log lines in the displayLocationInfo function? Isn't that function called in the navigator.geolocation function, which comes before that?
I cannot get the lngreal and latreal variables updated correctly to match the user's location. They will default back to 0.0098 and 51.4934, and the loaded map (var map) will show the default Greenwhich location. Does this have to do with variable scope of the displayLocationInfo function?
It shows the last two console logs first because displayLocationInfo is the callback to the async method getCurrentPosition and so has to wait until that process has resolved before it can log the new coords.
To recenter the map with the new coords you need to do something like this:
function displayLocationInfo(position) {
const { coords: { latitude, longitude } } = position;
// Get a new lat/lng object
// https://docs.mapbox.com/mapbox-gl-js/api/#lnglatlike
const center = new mapboxgl.LngLat(longitude, latitude);
// Center the map
// https://docs.mapbox.com/mapbox-gl-js/api/#map#setcenter
map.setCenter(center);
}
Thanks Andy and #Chris G. I wasn't aware of asynchronous functions and am happy to have read about them now. Very helpful.
I have a question about callbacks, which relates to this topic. How does a function know that something is a callback; something that needs to be executed once certain I/O has completed. How does it know that it shouldn't execute right away? Is it defined in a function in a (standardized) way?
As far as I know the 'callback' keyword that is often used in an argument is just common practise, but does not automatically let the function interpret the argument as something that should start once certain I/O has completed.
Taking the below example, I have three questions (taken from https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee):
const request = require(‘request’);
function handleResponse(error, response, body){
if(error){
// Handle error.
}
else {
// Successful, do something with the result.
}
}
request('https://www.somepage.com', handleResponse);
What does the structure of the 'require' function look like so that it knows that argument 2 (handleResponse in this case) should be executed once the request has completed? I guess this gets down to the same question that I asked above.
Can functions be asynchronous even without the async keyword in the function? If yes, how does the browser know it's an asynchronous function?
In my code, is it possible to have the browser/script wait with execution of remaining code until the navigator.geolocation.getCurrentPosition has finished executing and therefore updated the lngreal latreal coords?
I am try to use clastering in my aplication but I am get a error addLayer is not defined".
I have no Idea how to resolve this issue.
I just copy and paste this sample function from Here API samples api clusters
And I'm passing lat and lng, to the function but addLayer is undefined.
I have the map object, but the addLayer is undefined.
function startClustering(map, data) {
// First we need to create an array of DataPoint objects,
// for the ClusterProvider
var dataPoints = data.map(function(item) {
return new H.clustering.DataPoint(item.latitude, item.longitude);
});
// Create a clustering provider with custom options for clusterizing the input
var clusteredDataProvider = new H.clustering.Provider(dataPoints, {
clusteringOptions: {
// Maximum radius of the neighbourhood
eps: 32,
// minimum weight of points required to form a cluster
minWeight: 2
}
});
// Create a layer tha will consume objects from our clustering provider
var clusteringLayer = new H.map.layer.ObjectLayer(clusteredDataProvider);
// To make objects from clustering provder visible,
// we need to add our layer to the map
map.addLayer(clusteringLayer);
}
And I'm passing lat and lng, to the function but addLayer is undefined.
I have the map object, bust does not exist addLayer.
I'm embed the script
<script type="text/javascript" src="https://js.api.here.com/v3/3.0/mapsjs-clustering.js"></script>
on my index.
I don't know how to resolve this issue.
If someone knows how to resolve I'm glad to listen
EDIT: Additional code per comment request:
function addMarkerToCameraGroup(map, coordinate, html) { // add and remove markers
document.querySelector(".camera-box").addEventListener("click", function() {
if (document.getElementsByClassName("camera-marker-position")[0] === undefined) {
map.addObject(cameraMarker);
self.startClustering(map, coordinate);
} else {
map.removeAll();
}
});
}
You asked this question a second time as: "Try to create a cluster unsing a sample but addLayer got undefinied" which doesn't include some of the details in this question. Given the additional edit / context you made on this question however, it would seem you are adding an event listener in which map is probably out of scope or not yet defined for visibility inside the anonymous function.
document.querySelector(".camera-box").addEventListener("click", function() {
if (document.getElementsByClassName("camera-marker-position")[0] === undefined) {
map.addObject(cameraMarker);
self.startClustering(map, coordinate);
} else {
map.removeAll();
}
});
You could do a typing check to see if map has been defined when the click event occurs and/or confirm whether it is an H.map. Without seeing the full listing, it may also be the case that you have not made map a global variable but instead declared it somewhere else in the page initialization so is out of scope when the click event is fired.
You can check JavaScript callback scope for details on closures where you could provide the map to the event when declaring the function. For more general information: JavaScript HTML DOM EventListener
I thought I'd finally figured out JavaScript callbacks as I found a use for one, but it is firing out of sequence.
In a Google Maps application I have a function which checks if the map is zoomed to the maximum level before allowing the user to store the (new) location of a marker.
The check function is:
function checkForMaxAccuracy(nextOperation) {
// Check at full zoom and alert if not
maxZoomService.getMaxZoomAtLatLng( newLocationMarker.getPosition(), function(response) {
var levelToZoomTo;
if (response.status != google.maps.MaxZoomStatus.OK) {
alert("Please ensure you are at maximum zoom to ensure most accurate placement possible.");
// continue after this alert as Mao could be fully zoomed but zoom service not reporting correctly
} else {
//alert("The maximum zoom at this location is: " + response.zoom);
if (response.zoom > map.getZoom()) {
alert("You must be zoomed in to the maximum to ensure most accurate placement possible before saving.\n\n Click [ Zoom here ] in theInfo Window to zoom to the maximum.");
// return after this error as Mao is definitely not fully zoomed
return;
}
// Call the update function to do the saving to the database
nextOperation();
}
});
}
Where nextOperation is the callback function.
This is called by two different functions, the first, and simplest (because it's not fully written yet) works perfectly:
function saveNewLocation() {
checkForMaxAccuracy(function () {
alert("save new");
});
}
If not fully zoomed I get the warning message displayed by the check function. If the map IS fully zoomed I get the alert 'save new' message displayed which is a place holder for the code to do the database update.
However, the same check function is also called from a more complete function. This other function is called when the user is updating the location of an existing marker.
This second function actually sets the onclick property of an HTML span object - effectively enabling and disabling the save control depending on what is going on.
In this function I am setting the onclick as follows:
document.getElementById('savePosition'+locationId).onclick = (state)?function(){checkForMaxAccuracy(doUpdate(locationId,"position"));}:null;
In this case, when I click the corresponding span element the doUpdate() function gets fired before the checkForMaxAccuracy() function.
(Apologies for the use of ternary operator.. I know if makes things a little difficult to read, but I'm leaving as is in my code in case I've got the bracketing or syntax slightly wrong here and that's what's causing my problems.)
My guess is I'm getting something fundamentally wrong in my 'understanding' of callback functions.
Can anyone explain what I'm doing wrong?
-FM
checkForMaxAccuracy(
doUpdate(locationId,"position")
);
will pass the returned value of doUpdate as an argument of checkForMaxAccuracy. In other words, you're not passing the callback function itself but its return value.
What you could do is:
checkForMaxAccuracy(
function() {
doUpdate(locationId,"position")
}
);
i am using the following code to access the geolocation of the blackberry device. its working and showing the desire result. but i want to access the window.GlobalVar outside the body of this function. how can i access it? please help.
navigator.geolocation.getCurrentPosition(function(position) {
var gps = (position.coords.latitude+position.coords.longitude);
window.GlobalVar = gps;
alert (window.GlobalVar);
});
Best regards,
window.GlobalVar will be accessible outside of your function.
What's probably going wrong here is that you're trying to access it before it has been set, seeing as it is being set in a callback function.
getCurrentPosition prompts the user for coordinates, but it is not a blocking call, i.e. it does not simply halt all code execution and wait for the user to make a decision.
This means that you do not set window.GlobalVar during page load, you request it during page load, and you set it whenever the user decides to. So no matter where you call getCurrentPosition you cannot be sure that at a given point, window.GlobalVar will be set.
If you want to be sure that window.GlobalVar is set in the script you're running, you need to make sure that you're running the script after the variable has been set.
navigator.geolocation.getCurrentPosition(function(position) {
var gps = (position.coords.latitude+position.coords.longitude);
window.GlobalVar = gps;
continueSomeProcess();
});
function continueSomeProcess() {
// this code will be able to access window.GlobalVar
}
Calling window.gps after setting window.gps = gps should be enough as it has a global scope since you attached it to window. Take care of the fact that JS is asynchronous, ie gps might not be defined when you call it.
I'm trying to do something that should be pretty simple - but it's doing my head in.
I can't seem to get a variable to return from a function
var where;
if (navigator.geolocation) {
where = navigator.geolocation.getCurrentPosition(function (position) {
// okay we have a placement - BUT only show it if the accuracy is lower than 500 mtrs
//if (position.coords.accuracy <= 500 ) {
// put their lat lng into google
var meLatLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var image = "images/map_blue.png";
var myMarker = new google.maps.Marker({
position: meLatLng,
map: map,
title: "Your location, as provided by your browser",
icon: image,
zIndex: 50
});
//} // end 500 mtrs test
return meLatLng;
});
alert("A: "+where);
}
I have a global variable called where, I'm trying to fill it with LatLng information received from the browser using navigator.geolocation - it plots the user on the map - but alert(where) always returns undefined
What am I doing wrong?
Short answer, nothing,
Bit longer answer, well... you see, the problem is that it would appear that your anonymous function returns its value to the getCurrentPosition function, which it seems doesnt return anything at all.
In order to use your returned value you should instead use a callBack or handle the data where it is...
Simply try replacing return meLatLng with customCallBack(meLatLng) and then defined customCallBack somewhere along the line.
Or, since you have already defined where in the global scope you could try and replace return meLatLng with where = meLatLng and then remove where = from where = navigatior.geoloc....
If what I suspect is right, the last method wont work, since I believe getCurrentPosition is asynchronous, meaning that you leave the standard flow of the application as soon as you call it. Which is why you supply a function to it in the first place.