Thursday, August 13, 2015

navigator.geolocation API strange behaviour on Microsoft Edge - a foolproof location snippet in Javascript

Today we tested a web application in the new Microsoft Edge browser. To our surprize, the site failed where Internet Explorer, Chrome, Firefox and even Safari worked perfectly well. I narrowed the problem to the navigator.geolocation.getCurrentLocation which wasn't working. The site would see navigator.geolocation, ask for the current location, the user would be prompted to allow the site to access location and after that would silently fail. What I mean by that is that neither the success or the error callbacks were called, even if the options object specified one second for the timeout. I don't have access to a lot of Windows 10 machines and I assume that if a lot of people met with this problem they would invade the Internet with angry messages, but so far I've found no one having the same issue.

Bottom line: forced to take into consideration the possibility that the geolocation API would silently fail, I changed the code like this:
if (navigator.geolocation) {
    var timeoutInSeconds=1;
    var geotimeout=setTimeout(function() {
    },timeoutInSeconds*1000+500); //plus 500 ms to allow the API to timeout normally
    navigator.geolocation.getCurrentPosition(function (position) {
        var pos = doSomethingWith(position.coords.latitude, position.coords.longitude);
    }, function () {
        timeout: timeoutInSeconds*1000
} else {

In the handleNoGeolocation function I've accessed the great service FreeGeoIp, that returns vague coordinates based on your IP and fell back to a static latitude, longitude pair if even this call failed.

Note: for the first time the function is called for your site, a browser dialog will appear, requesting permission to share the location. During the display of the dialog the timeout will fire, then, based on the user choice (and browser) a success/error handler will be called or nothing (like in this case), so make sure your code can handle running handleNoGeolocation followed by doSomethingWith.