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
Related
I am not really good at js and trying to use Bing map in our website but it shows the map few times and doesnt show the map most of the time. Below is the code snippet of loading map function, can someone please let me know whats wrong in this function, I am using this from other application:
function loadMap(storeData) {
var coordinates = {};
var map;
var stores = storeData.stores;
if( (typeof stores !== 'undefined') && (typeof stores[0].coordinates !== 'undefined') ) {
coordinates.lat = stores[0].coordinates.lat;
coordinates.lng = stores[0].coordinates.lng;
}else {
coordinates.lat = 33.74831008911133;
coordinates.lng = -84.39111328125;
}
map = new Microsoft.Maps.Map($('#bingMap')[0], {
credentials: 'mykey',
liteMode: true,
enableClickableLogo: false,
center: new Microsoft.Maps.Location(coordinates.lat, coordinates.lng)
});
self.center = new Microsoft.Maps.Location(coordinates.lat, coordinates.lng);
map.setView({zoom: 13});
return map;
}
I have tried below few steps I got from other stackoverflow queries but it didnt help me:-(
setTimeout(this.loadMap(storeData), 2000); Microsoft.Maps.Events.addHandler(map,'resize')
The problem is in your setTimeout call:
You see, setTimeout receives 2 parameters:
A function to execute
Timeout in ms
in your case, you used setTimeout(this.loadMap(storeData), 2000); which doesn't pass the function to the setTimeout but the result of the execution. In addition, this code will also execute this.loadMap immediately and not in 2 seconds.
To solve this, you can just use:
setTimeout(function() { this.loadMap(storeData)}, 2000);
or: (#Sysix's solution)
setTimeout(this.loadMap.bind(this), 2000, storeData);
I an using javascript and am getting an message that I have exceeded my daily request quota for this API. Is there a way to capture this error message in a try catch block so when I go over my quota I can execute another piece of code. I have seen several similar posts, but nothing that has been helpful. Here is my code.
(function (window, google, lat, lng) {
var options = {
center: {
lat: Number(lat),
lng: Number(lng)
},
zoom: 5,
disableDefaultUI: true,
scrollwheel: true,
draggable: false
},
element = document.getElementById('map-canvas')
var map = new google.maps.Map(element, options)
}(window, window.google, result[i]['latitude'], result[i]['longitude']));
Update
As per the documentation:
if you want to programmatically detect an authentication failure (for example to automatically send an beacon) you can prepare a callback function. If the following global function is defined it will be called when the authentication fails. function gm_authFailure() {//code}
Here is a list of errors that the gm_authFaliure function should be able to catch. It also mentions a OverQuotaMapError error.
As per the documentation:
if too many requests are made within a certain time period, the API returns an OVER_QUERY_LIMIT response code.
So you should check the response code. If the Google maps javascript library does not allow to access to the response code then I recommend making a HTTP request to the API to get the response code.
function initMap(window, google, lat, lng) {
var options = {
center: {
lat: Number(lat),
lng: Number(lng)
},
zoom: 5,
disableDefaultUI: true,
scrollwheel: true,
draggable: false
},
element = document.getElementById('map-canvas'),
map = new google.maps.Map(element, options);
};
function googleMapsCustomError(){
alert('Google Maps custom error triggered');
}
// if you want to respond to a specific error, you may hack the
// console to intercept messages.
// check if a message is a Google Map's error message and respond
// accordingly
(function takeOverConsole() { // taken from http://tobyho.com/2012/07/27/taking-over-console-log/
var console = window.console
if (!console) return
function intercept(method) {
var original = console[method]
console[method] = function() {
// check message
if(arguments[0] && arguments[0].indexOf('OverQuotaMapError') !== -1) {
googleMapsCustomError();
}
if (original.apply) {
// Do this for normal browsers
original.apply(console, arguments)
} else {
// Do this for IE
var message = Array.prototype.slice.apply(arguments).join(' ')
original(message)
}
}
}
var methods = ['error']; // only interested in the console.error method
for (var i = 0; i < methods.length; i++)
intercept(methods[i])
}())
<!DOCTYPE html>
<div id="map-canvas"></div>
<script>
// Notice i am defining this within my html file, just to be sure that this function exists before the Google Maps API is loaded.
window.gm_authFailure = function() {
// remove the map div or maybe call another API to load map
// maybe display a useful message to the user
alert('Google maps failed to load!');
}
window.showMap = function() {
var lat = -34.397,
lng = 150.644;
initMap(window, window.google, lat, lng);
};
</script>
<!-- We are passing an invalid API key. Also notice that we have defined 'callback' as 'showMap' which means that when the Google API JavaScript library is finished loading it will call the 'showMap' function. -->
<script src="https://maps.googleapis.com/maps/api/js?key=INVALID_API_KEY&callback=showMap"
async defer></script>
Yes, JavaScript supports try-catch blocks. Here is a sample implementation for your code:
(function (window, google, lat, lng) {
var options = {
center: {
lat: Number(lat),
lng: Number(lng)
},
zoom: 5,
disableDefaultUI: true,
scrollwheel: true,
draggable: false
},
element = document.getElementById('map-canvas')
try {
var map = new google.maps.Map(element, options)
} catch (error) {
// handle error
console.log(error.message);
} finally {
// optional cleanup code
}
}(window, window.google, result[i]['latitude'], result[i]['longitude']));
As per google documentation.
If you exceed the usage limits you will get an OVER_QUERY_LIMIT status
code as a response.
This means that the web service will stop providing normal responses
and switch to returning only status code OVER_QUERY_LIMIT until more
usage is allowed again. This can happen:
Within a few seconds, if the error was received because your application sent too many requests per second.
Within the next 24 hours, if the error was received because your application sent too many requests per day. The daily quotas are
reset at midnight, Pacific Time.
Please refer this link. It would be helpful.
Overall Picture:
I want to add geocoding to my application. I was able to get it working in straight up JavaScript, but the callbacks are not getting triggered after converting to Angular/TypeScript.
Example: if a user enters 1 Microsoft Way, Redmond, WA. The longitude and latitude should be returned: latitude: 47.64006815850735, longitude: -122.12985791265965
Code examples are built off the following resources:
Bing Maps Ajax API - get location from address
https://msdn.microsoft.com/en-us/library/hh868062.aspx
Error Details:
The errors are occurring specifically within the variable name: geocodeRequest. searchModuleLoaded() gets loaded, but my geocodeRequest never triggers geocodeCallback or errCallback. I'm thinking it has something to do with the scope of my methods, but can't seem to isolate what is causing the error. Any ideas on how to get my callbacks to trigger?
Angular/TypeScript (Not Working)
$onInit() {
this.getMap();
}
getMap() {
this.map = new Microsoft.Maps.Map(document.getElementById('myMap'), {credentials: "your key here"});
Microsoft.Maps.loadModule('Microsoft.Maps.Search', { callback: this.searchModuleLoaded });
};
searchModuleLoaded() {
var searchManager = new Microsoft.Maps.Search.SearchManager(this.map);
var geocodeRequest = {
where: "1 Microsoft Way, Redmond, WA",
count: 10,
callback: this.geocodeCallback,
errorCallback: this.errCallback
};
searchManager.geocode(geocodeRequest);
}
geocodeCallback(geocodeResult, userData) {
// this callback never gets triggered
alert("The first geocode result is " + geocodeResult.results[0].location + ".");
}
errCallback(geocodeRequest) {
// this callback never gets triggered
alert("An error occurred.");
}
Working Version (Works, but no Angular/TypeScript)
function GetMap(){
map = new Microsoft.Maps.Map(document.getElementById("mapDiv"), {credentials: "key goes here", center: new Microsoft.Maps.Location(47.5, -122.3), zoom: 9 });
Microsoft.Maps.loadModule('Microsoft.Maps.Search', { callback: searchModuleLoaded });
}
function searchModuleLoaded(){
var searchManager = new Microsoft.Maps.Search.SearchManager(map);
var geocodeRequest = {where:"1 Microsoft Way, Redmond, WA", count:10, callback:geocodeCallback, errorCallback:errCallback};
searchManager.geocode(geocodeRequest);
debugger;
}
function geocodeCallback(geocodeResult, userData){
alert("The first geocode result is " + geocodeResult.results[0].location + ".");
}
function errCallback(geocodeRequest){
alert("An error occurred.");
}
After furthing investigation, I was able to resolve my issue.
What was the problem?
The issue was occurring within the searchModuleLoaded. Both callbacks were undefined. One issue is that it was trying to execute searchModuleLoaded before the module had loaded and another issue was caused because it didn't know the context of this.
To fix the issue, I had to modify the callback while loading Microsoft.Maps.Search. The module's callback is now converted to a lambda function, which calls this.searchModuleLoaded(). Once this gets compiled into JavaScript, it sets the this context appropriatly i.e _this = this. My code looks like this now:
getMap() {
this.map = new Microsoft.Maps.Map(document.getElementById('myMap'), {credentials: "put your key here"});
Microsoft.Maps.loadModule('Microsoft.Maps.Search', {
callback: () => {
this.searchModuleLoaded();
}
});
};
searchModuleLoaded() {
var searchManager = new Microsoft.Maps.Search.SearchManager(this.map);
var geocodeRequest = {
where: "1 Microsoft Way, Redmond, WA",
count: 10,
callback: this.geocodeCallback,
errorCallback: this.errCallback
};
searchManager.geocode(geocodeRequest);
};
geocodeCallback(geocodeResult, userData) {
alert("The first geocode result is " + geocodeResult.results[0].location + ".");
};
errCallback(geocodeRequest) {
alert("An error occurred.");
};
I'm writing an Cordova/Phonegap app and I use a Geolocation plugin...this is my code...
var onSuccess = function(position) {
longitude = position.coords.longitude;
latitude = position.coords.latitude;
console.log("Latitude: "+position.coords.latitude);
console.log("Longitude: "+position.coords.longitude);
};
function onError(error) {
logService.debug("Code: "+error.code);
logService.debug("Message: "+error.message);
};
navigator.geolocation.getCurrentPosition(onSuccess, onError, { maximumAge: 3000, timeout: 15000, enableHighAccuracy: true });
Now, I test it on browser and when I don't the permission I receive Error code 1 (PositionError.PERMISSION_DENIED), when I do the permission it works very well on browser...Now born che question...When I test this on device and the GPS is off I don't receive the Error code 1 (PositionError.PERMISSION_DENIED) but receive always timeout...in this way I don't discern the difference...I set the timeout to 150000 but I receive always code 3 (PositionError.TIMEOUT)...Why? How can use it in the rigth way?
I've found the handling of the geolcation errors to be platform-specific. Since setting enableHighAccuracy: true causes your app to ask the OS retreive a position using the GPS hardware, the effect of turning off GPS on an Android device varies depending on the Android version: either the OS is never able to retreive a high-accuracy position, so the TIMEOUT error occurs (PERMISSION_DENIED will not be received on Android) or a low accuracy position will be retrieved and passed instead using Wifi/cell triangulation.
I'd suggest using watchPosition() instead of getCurrentPosition() to retrieve the location; getCurrentPosition() makes a single request for the device position at that current point in time, so the position timeout may occur before the GPS hardware on the device has had a chance to get a position fix, whereas using watchPosition() you can setup a watcher which will call the success function each time the OS receives a location update from the GPS hardware. If you only want a single location, clear the watcher after receiving a position of sufficient accuracy. If GPS is turned off on the Android device when the watcher is added, it will continue to return a TIMEOUT error; my workaround for this is to clear and re-add the watcher after a number of consequetive errors.
So try something along these lines:
var MAX_POSITION_ERRORS_BEFORE_RESET = 3,
MIN_ACCURACY_IN_METRES = 20,
positionWatchId = null,
watchpositionErrorCount = 0,
options = {
maximumAge: 60000,
timeout: 15000,
enableHighAccuracy: true
};
function addWatch(){
positionWatchId = navigator.geolocation.watchPosition(onWatchPositionSuccess, onWatchPositionError, options);
}
function clearWatch(){
navigator.geolocation.clearWatch(positionWatchId);
}
function onWatchPositionSuccess(position) {
watchpositionErrorCount = 0;
// Reject if accuracy is not sufficient
if(position.coords.accuracy > MIN_ACCURACY_IN_METRES){
return;
}
// If only single position is required, clear watcher
clearWatch();
// Do something with position
var lat = position.coords.latitude,
lon = position.coords.longitude;
}
function onWatchPositionError(err) {
watchpositionErrorCount++;
if (watchpositionErrorCount >= MAX_POSITION_ERRORS_BEFORE_RESET) {
clearWatch();
addWatch();
watchpositionErrorCount = 0;
}
}
addWatch();
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;
}