html5-geolocation : navigator.geolocation.watchPosition continuous callbacks - html

I am using the HTML5 geolocation API. I recently decided to shift from polling user position to
using the watchPosition method, which is supposed to fire its "success" function, once the device position changes.
But instead, it is filling up my database with the same position over and over again. Relevant code posted below:
updateLocation = navigator.geolocation.watchPosition(success, failed, {enableHighAccuracy:true, maximumAge:30000, timeout:27000});
function success(){
showGPS(position);
}
function showGPS(position) {
var lng = position.coords.longitude;
var lat = position.coords.latitude;
gpsText.innerText = "Latitude: "+ lat +"\nLongitude: "+ lng + "\nAccuracy: "+ position.coords.accuracy + "\nSpeed:" + (position.coords.speed*3.6) + "\nAltitude:" + position.coords.altitude;
getData("http://databaseEntryURL/gpsReceiver.aspx?string=" + gpsText.innerText);
}
The getData gets called about 5 times a second. I'm sure the latlng is not changing. I'm using android 2.2, to load this page. How do i make it call the success function ONLY if the device position changes?

Maybe it's just caused by some bug, so even when the location has no change (or the change is so small) your callback is still triggered.
One way to solve it is storing the last location and using it to compare with the current location. If there's no change (or the change is too small), do nothing in the callback. This will save you bandwidth and database space.
If you need to save battery life for the phone then you need to optimize the options, for example, changing enableHighAccuracy to false.

A more efficient way would be to set the watchPosition as a variable and call clearWatch() on it once you've received the first response:
var watchID = navigator.geolocation.watchPosition(onSuccess, onFailed);
function onSuccess(position) {
navigator.geolocation.clearWatch(watchID);
};

Related

Why is Viewer' getViewerToken getting called infinite times?

The function getViewerToken is called infinitely since today without any code change. Is this bug on our side or a bug in the forge viewer?
iframe.viewer = new iframe.Autodesk.Viewing.GuiViewer3D(iframe.viewerDiv, { extensions: extensions });
let options = {
// 'env': 'AutodeskProduction',
'env': 'MD20ProdEU', //svf2
'api': 'D3S', //svf2
'getAccessToken': function(onTokenReady) {
...
};
.....
The viewer calls the getAccessToken function whenever the token needs to be refreshed. When you're calling the callback function inside getAccessToken, make sure that the second parameter (expiration time of the new token in seconds) is a positive integer number. Perhaps your code is passing in zero or a negative number, forcing the viewer to repeatedly ask for new tokens.

How to pass data back to webpage?

I am working on a WP8 application, containing the WebBrowser control in which I open a html page, containing javascript. The javascript contains the following function:
function send(data) {
windows.external.notify(data);
var xhr = new XMLHttpRequest();
xhr.open('GET', 'getresponse', false);
xhr.send(null);
var result = xhr.responseText;
if (result) {
return JSON.parse(result);
}
}
Basically this function calls the native C# side of the app, where I run some functions and I need to be able to return some data from the native side to the send function. I wanted to use an XMLHttpRequest for this, where my idea was to "intercept" the request url (in this case 'getresponse') and return the data I want by including it in the response.
Is this please possible on Windows Phone 8 using the WebBrowser control?
Once again, all I need to do is this:
Have a javascript function (in this case called "send") which connects to the native app (using windows.external.notify) and pass data back to this "send" function so that it can return it (and so that other JS function can use it).
Is this please possible? If not using the XMLHttpRequest, maybe using another technique?
Thank you all for your help!
You are looking for InvokeScript.
If you have full control over the page that is displayed inside the WebBrowser (e.g. the server is your's), you can define the JS-function to be called:
webBrowser.InvokeScript("yourJSFunction", "param1", "param2");
If you display a website from a foreign webserver you can inject JS like this (this uses jQuery):
webBrowser.InvokeScript("eval", "window.youInjectedFunction = function() {" +
"window.external.notify('and_notify_back');" +
"}; " +
"window.readyStateCheckInterval = setInterval(function() {" +
"window.external.notify('timer');" +
"if (document.readyState === 'complete') {" +
"clearInterval(window.readyStateCheckInterval);window.yourInjectedFuntion();" +
"}}, 100);" +
"");
I used the timer, as you can not be certain if the InvokeScript is called after the page is completely loaded.
If you can control the source, you should definitely go for option 1.

handling large cookies or using local storage - jquery and jquery cookie plugin

I have the working code which sets and clears cookie (remembers div's style) on click:
var originalAttributes = $('.aaa').attr('style');
$('.aaa').each(function(){
var d = $(this),
id = d.attr('id'),
storedStyle = $.cookie('aaaStyle' + id);
if (storedStyle != undefined){ //style stored
d.attr('style', storedStyle);
}
});
//mouse event functions for class="aaa"
$('#save').click(function () {
$('.aaa').each(function(){
var d = $(this),
id = d.attr('id'),
style = d.attr('style');
if (style != originalAttributes){ //style changed
$.cookie('aaaStyle' + id, style, { expires: 30 });
}
});
});
$('#clear').click(function () {
// unset changes
$('.aaa').attr('style',originalAttributes).each(function(){
var d = $(this),
id = d.attr('id');
$.cookie('aaaStyle' + id, null);
});
});
http://jsfiddle.net/z8KuE/31/
Only problem which occurs with this is when I have to handle a lot of divs of the same class - cookie size can get to 500kb or more. Browsers supports only 4kb per cookie.
So the question is - how can this problem be avoided with this function and with the jquery cookie plugin? - gzip or / and splitting the cookie in small enough parts?
(in either way, it would be good to have some sort of compression in order to speed up the performance (if possible - but if not, doesn't matter))
edit: how this same "save - clear" functionality can be achieved with the local storage?
edit2: solved by user2111737 (http://jsfiddle.net/z8KuE/33/) - uses local storage instead of cookie and works without cookie plugin.
if you don't need to access it on server side or eventually it's possible to manually send this data to server with xmlhttprequest I think you should rather try localStorage, eventually sessionStorage instead of cookies, then you have 20mb (200 in IE but shared with other sites). About compression - you can think about custom format and rebuild html code using stored data in fly - eg. i doubt this class can be absolutely anything - i guess it could be saved as number - or even better - one character. It gives you 255 classes saved as one sign

HTML5 GEOLocation 2nd prompt

Is there a way to prompt user for geolocation again on some trigger, after they denied the location sharing?
navigator.geolocation.getCurrentPosition
fires it once, consecutive calls do not produce the same result. Cant find the answer anywhere/
Take a look at this Code Snippet and this SO Answer: What is the best JQuery plugin that handles HTML5 location?
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
}else{
errorFunction();
}
function successFunction(position) { //uses HTML5 if available
var lat = position.coords.latitude;
var lng = position.coords.longitude;
}
function errorFunction(){ //uses IP if no HTML5
$.getJSON("http://freegeoip.net/json/", function(res){
var lat = res.latitude;
var lng = res.longitude;
});
}
Take a Look at this Fiddle Link also
JQuery Geolocator Plugin
In Geolocation API? No.
If user clicks deny permission it simply means "No, and don't bother me again..."
However user can do it by deleting Location-share-settings, then of course the prompt pops out again.
Or user can just change the settings if browser allows it, however e.g. Chrome manages these settings as exceptions (no matter whether user've allowed or denied permission) so user have to delete the settings, resp. exception anyway.
What now?
Your only option is to catch the error and use e.g. some external API to find the user's location by IP. You can program it by yourself or there are of course existing solutions as #Venkat suggested.
But be aware IP geolocation is a tricky one - sometimes it has an adress-number-accuracy sometimes it's just state-accuracy.
This examle from Mozilla's docs shows a nice example how to handle Geolocation errors:
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
function success(pos) {
var crd = pos.coords;
console.log('Your current position is:');
console.log('Latitude : ' + crd.latitude);
console.log('Longitude: ' + crd.longitude);
console.log('More or less ' + crd.accuracy + ' meters.');
};
function error(err) {
/*
CALL EXTERNAL API HERE
*/
console.warn('ERROR(' + err.code + '): ' + err.message);
};
navigator.geolocation.getCurrentPosition(success, error, options);
The best option for this is to setup a geolocation subdomain, and load it in a iframe.
geo-0.domain.com
geo-1.domain.com
geo-2.domain.com
geo-3.domain.com
geo-4.domain.com
geo-N.domain.com
This will allow you unlimited attempts on every browser, all you need to do is program in your own retry logic.

Google map + browser back with last view location and zoom value

I am trying to return the last marker view and zoom level to the user when he access some other pages and returns to the map page. Right now, I am using cookies to do it. Just want to find out if there's a conventional way of dealing with this, thanks:
When the user clicks on a marker, store them into cookies:
var latLng = map.getCenter();
var currZoom = map.getZoom();
$.cookie("map_center", latLng);
$.cookie("location_id", locationid);
$.cookie("curr_zoom", currZoom);
Retrieving the last viewed marker location and zoom level when he returns to the map page:
var lastViewedActivity = $.cookie('location_id');
var lastViewedMapLocation = $.cookie('map_center');
var lastViewMapZoom = $.cookie('curr_zoom');
This is definitely the way to go; your other options would be:
storing on the server, with session or passing parameters back and forth: not appropriate here as it's more complicated and it adds nothing
html5 local storage: not supported enough, so you'd still need a fallback on cookies