Is there a 'GPS status changed' event for html5 geolocation? - javascript

I'm developing a web app for mobile and using html5's geolocation api.
When the page is loaded I start a watch position:
function enableWatchPosition() {
if (navigator.geolocation) {
watchPositionId = navigator.geolocation.watchPosition(locateByBrowser, handleErrorGettingLocation, {
timeout : 30000,
enableHighAccuracy : true,
maximumAge : 1000
});
}
}
If a user doesn't have his GPS on, handleErrorGettingLocation is triggered and I show him an error message, asking him to turn GPS on.
My Question is:
Suppose the user then turns his GPS on - how can I detect that (so I could retry and call enableWatchPosition() again)? Is there some sort of js event I can listen to?
Thanks!

There is no such event that’s exposed in a way you could see from your Web-application code. Certainly there is no such event defined in the standard Geolocation API spec. And I don’t believe there are any non-standard events that any browsers expose for it. So I don’t think you’re going to be able to automatically re-trigger a call to your enableWatchPosition() function.
I’m sure that’s not the answer you were hoping for, but it is the answer. :-(

Related

Closing Chrome window not sending data with sendBeacon in unload event handler

I am trying to send data when the window closes to prevent 2 people from editing and overwriting each others data. Currently I am using a sendBeacon within a unload event handler.
FireFox:
Refresh: Works
Back button: Works
Close window: Works
Chrome:
Refresh: Works
Back button: Works
Close window: Doesn't work
Here is my code
function sendDataOnClose(edit,trans){
var url = "../../save.php"; //This has a post request handler and works properly with other functions for saving data
const data = JSON.stringify
({
"translations": trans,
"edit": edit
});
navigator.sendBeacon(url, data);
}
function handleClose(){
if(edit){
console.log("sending a false when edit is: "+ edit)
sendDataOnClose(false, translations);
}
}
window.addEventListener('unload', handleClose);
The latest sendBeacon documentation on MDN, states "The navigator.sendBeacon() method asynchronously sends a small amount of data over HTTP to a web server. It’s intended to be used in combination with the visibilitychange event (but not with the unload and beforeunload events)."
To use the visibilitychange event like suggested, you could
document.addEventListener('visibilitychange', function() {
if (document.visibilityState === 'hidden') {
navigator.sendBeacon(handleClose);
}
});
I have experienced similar issues with trying send data on the unload event. Is the user base all on desktop? Mobile devices don't reliably fire the unload event. The Page Lifecycle API provides the visibility change event and the pagehide events which could be used together to get closer to your desired result.
The Page Lifecycle API attempts to solve this problem by:
Introducing and standardizing the concept of lifecycle states on the web.
Defining new, system-initiated states that allow browsers to limit the resources that can be consumed by hidden or inactive tabs.
Creating new APIs and events that allow web developers to respond to transitions to and from these new system-initiated states.
source
The issue you are experiencing is likely more of an issue without how browsers suspend pages or discard them entirely. Unfortunately, browsers are not unified on how they do this, and to add to the complexity there is different behavior on desktop vs. mobile.
There are several threads that dive in deeper to this issue if you are interested. Until browsers standardize on this, I'm not sure there is an easy answer, such as "use x event".
Issue filed on Page Visibility
Issue on MDN's strints about sendBeacon
Thanks to hackers, many other things are removed for security reasons.
I noticed your question had the PHP tag as well; I will give you a, not good idea, but a functional one. Avoid on-close-page handles even JavaScript or frameworks just post with JavaScript a table database where you store time() and an target id then if timeout is maybe more than 30 sec you set then you will remove from table that stuff, and you will know that page isn't still working (translation: use a server "online users" idea (bad but necessary one like anything generates lots of traffic in an app).
Using these in JavaScript in the side client is bad idea and you open gates for bad guys that will exploit your app.

Mock built-in objects with NightmareJS

I am trying use NightmareJS to load a page, click a button, then take a screenshot to test. The click handler on the button requests the geolocation. This is part of what I'm testing for. I want the page to appear a certain way if the user grants the geolocation permission, and another way if they decline.
The problem is that Nightmare doesn't expose a method for me to intercept the permission prompt to accept or decline it. After some research I learned that Electron just hardcodes this permission to 'granted' so there may not even be a way to set it to declined.
What I'd like to do is replace Electron's navigator.geolocation object with a mock that responds to the geolocation request in a certain way.
new Nightmare().goto('https://example.com')
.evaluate(function () {
navigator.geolocation = {
getCurrentPosition(cb) {
cb({coords: latitude: 42, longitude: -42});
}
}
})
.click('#locateMe')
.screenshot()
.end()
.then(diffScreenshot)
However when I try this it seems like the navigator.geolocation object doesn't change. Is there some other way to accomplish this goal?
I think this is possible (or should be) in both projects, you might try changing:
navigator.geolocation
To
window.navigator.geolocation
This is because most evaluate calls are run in a clean context, or so I think. If this doesn't work then Navalia might be able to do it as it's fairly "bare-metal" so-to-speak.
Best of luck!

Firebase Callbacks - what's the underlying trigger?

I understand that in Firebase I can register my page for callbacks with the "on" method.
According to their docs:
on( ) is used to listen for data changes at a particular location.
This is the primary way to read data from Firebase.
firebaseRef.on('value', function(dataSnapshot) {
// code to handle new value.
});
My question is:
How does it work ?
How does it know that something has changed on the serverside ?
(better) How does the server can 'callback' the browser ?
One answer might be that it is "polling". But I have seen no reference about this approach in Firebase documentation or properties to configure polling time ...
Does anybody know ?
Many
Thanks
Firebase uses WebSockets to allow the server to "push" data to the client. Since not all browser versions support WebSockets yet, it also falls back to long polling for those browsers.
The implementation details of how that works on the server are proprietary and sophisticated--enough to write a book about and beyond the scope of a SO question. Logically, works exactly as advertised: The service is designed so that any time a set(), push(), or update() is called (or the REST equivalents), it notifies any listeners of the change.
Regardless of whether the browser uses WebSockets or not, there is no "polling time" as the client is not repeatedly contacting the server. Long polling means waiting for a data change to occur, rather than polling repeatedly to see if a change has occurred. As you can see by trying out the tutorial or any of the real-time examples, data changes are synced to all clients in a matter of milliseconds--nothing to configure.

What is the best way to implement idle time out for web application (auto log off)

I want to implement an idle time-out for the web application that we are building. I had earlier achieved this using AsynchronousSessionAuditor from codeplex, which essentially looks for the formsauthentication and session cookie timeout by constant polling.
But it has a draw back of not respecting the client side events, it will look for only last postback to decide when to log off.
The jquery plug jquery-idle-timeout-plugin from erichynds solves this issue of client side events but suffers from another drawback that is not able to recognise user is active on some other tab.
Is there anyone already fixed the TABBED browsing issue with jquery-idle-timeout-plugin already? Or is there any better approach of application time out for web applications (by the way this web app is build using asp.net f/w)
If I understand your question right, it is not possible, since there are no events triggered in javascript for activity outside of the current window/tab.
Unless you have a addon to go along with your website for each browser, which could monitor all activity in the browser, but that is not really a practical approach.
Well, you'd have to code it by hand, which is not really hard. You can use the onfocus and onblur functions to do something like this:
$(function() {
window.isActive = true;
$(window).focus(function() { this.isActive = true; });
$(window).blur(function() { this.isActive = false; });
showIsActive();
});
function showIsActive()
{
console.log(window.isActive)
window.setTimeout("showIsActive()", 2000);
}
function doWork()
{
if (!window.isActive) { /* Check for idle time */}
}
If you make a little search you can find that varaieties of this question have already been asked and answered, you can probably find a solution you can implement with one of the plugins you mentioned.
Try:
Run setTimeout only when tab is active
or
How to tell if browser/tab is active
EDIT--> ADDED:
Or I'd try a different approach. You could create a cookie with some hash and save that hash in your DB with a timestamp that updates whenever the window is active (you could check every 5 seconds or something, it's not an intensive request)
Then, do another check before(but in the same request) to see how much time has passed since the last timestamp and log them out if necessary.
it won't log them out isntantly when time has passed, but it will when they try to access the site either by opening it again or by focusing on the tab/window.

Javascript GeoLocation Caching

I'm using the following to successfully capture user's location (mobile browser):
<script>
if ( navigator.geolocation ) {
navigator.geolocation.getCurrentPosition(handlePosition);
}
function handlePosition(pos) {
//this passes lat/long to additional code
}
</script>
This works, but often times the browser will seemingly cache the location data. The page that calls this geolocation code shows information relative to the user's location, so what happens is the user can move (change location), the page is reloaded, but the previous location data is used (showing incorrect data). Sometimes the page will have to be refreshed once or even twice for the page to use new location data.
Does anyone know of any means to force the code to get and use "up to date" location data each time script is executed?
FWIW, I'm experiencing problem in iOS Safari (6.1). Have not been able to test in Android yet.
Thanks for reading and for any help.
Edit: As Oleksiy has written in his answer, the Geolocation API now supports this. You can add {maximumAge: 0} as the third option parameter of getCurrentPosition. There is also a timeout and a high accuracy option available in the PositionOptions as noted in the specification.
Your navigator call would change to the following:
navigator.geolocation.getCurrentPosition(
handlePosition,
(error)=>{},
{maximumAge:0}
);
No can't be done. You don't have any control over the browser geolocation other than the code in your example. The html5 geo location api is very, very limited and that is a pain. I also had a question whether I could ask it if permission for the domain had already been granted and the answer was also no.
The problem is that the api is implemented in the browser itself and that are just no endpoints for these kind of functions.
What you could do is make an array in js to store previous locations and before you update your view test against that array to see if you got a stale location.
You do have this ability now.
getCurrentPosition takes three parameters: success, failure and options
Try this:
<script>
if ( navigator.geolocation ) {
navigator.geolocation.getCurrentPosition(handlePosition, (error)=>{}, {maximumAge:0});
}
function handlePosition(pos) {
//this passes lat/long to additional code
}
</script>

Categories

Resources