By theassociatedweb


2010-08-03 14:37:40 8 Comments

So I have a pretty simple bit of JS using the navigator.geolocation.getCurrentPosition jammy.

$(document).ready(function(){
  $("#business-locate, #people-locate").click(function() {
    navigator.geolocation.getCurrentPosition(foundLocation, noLocation);
  });

  navigator.geolocation.getCurrentPosition(foundLocation, noLocation);

  function foundLocation(position) {
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
    var userLocation = lat + ', ' + lon;
    $("#business-current-location, #people-current-location").remove();
    $("#Near-Me")
      .watermark("Current Location")
      .after("<input type='hidden' name='business-current-location' id='business-current-location' value='"+userLocation+"' />");
    $("#people-Near-Me")
      .watermark("Current Location")
      .after("<input type='hidden' name='people-current-location' id='people-current-location' value='"+userLocation+"' />");
  }
  function noLocation() {
    $("#Near-Me").watermark("Could not find location");
    $("#people-Near-Me").watermark("Could not find location");
  }
})//end DocReady

Basically what's happening here is we get the current position, if it's obtained, two "watermarks" are placed in two fields that say "Current Position" and two hidden fields are created with the lat-long data as their value (they're removed in the beginning so they don't get duplicated every time). There are also two buttons that have a click function tied to them that do the same thing. Unfortunately, every third time or so, it works. What's the problem here???

21 comments

@1nstinct 2018-03-28 23:42:45

I found, that this way doesn't work

navigator.geolocation.getCurrentPosition(function() {...}, function(err) {...}, {});

But

this way works perfect

function storeCoordinates(position) {
    console.log(position.coords.latitude, position.coords.longitude);
}    

function errorHandler() {...}

navigator.geolocation.getCurrentPosition(storeCoordinates, errorHandler, { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 });

@JoLoCo 2017-08-16 16:13:14

I'll post this here in case it's useful to anyone…

On iOS Safari, calls to navigator.geolocation.getCurrentPosition would timeout if I had an active navigator.geolocation.watchPosition function running.

Starting and stopping the watchPosition properly using clearWatch() as described here, worked: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition

@Andrey E 2017-08-09 20:52:20

It might be a good idea to use an IP address geo location service as a fallback method when getCurrentPosition fails. For example with our api https://ip-api.io

$.getJSON("http://ip-api.io/json/",
    function(result) {
        console.log(result);
    });

@Coderer 2017-06-13 14:02:27

I'm still getting spotty results in 2017, and I have a theory: the API documentation says that the call is now only available "in a secure context", i.e. over HTTPS. I'm having trouble getting a result in my development environment (http on localhost) and I believe this is why.

@thirdender 2016-10-13 18:20:50

The second parameter passed to Geolocation.getCurrentPosition() is the function you want to handle any geolocation errors. The error handler function itself receives a PositionError object with details about why the geolocation attempt failed. I recommend outputting the error to the console if you have any issues:

var positionOptions = { timeout: 10000 };
navigator.geolocation.getCurrentPosition(updateLocation, errorHandler, positionOptions);
function updateLocation(position) {
  // The geolocation succeeded, and the position is available
}
function errorHandler(positionError) {
  if (window.console) {
    console.log(positionError);
  }
}

Doing this in my code revealed the message "Network location provider at 'https://www.googleapis.com/' : Returned error code 400". Turns out Google Chrome uses the Google APIs to get a location on devices that don't have GPS built in (for example, most desktop computers). Google returns an approximate latitude/longitude based on the user's IP address. However, in developer builds of Chrome (such as Chromium on Ubuntu) there is no API access key included in the browser build. This causes the API request to fail silently. See Chromium Issue 179686: Geolocation giving 403 error for details.

@Ben Dowling 2016-09-23 17:43:47

@brennanyoung's answer is great, but if you're wondering what to do in the failure case you could use an IP geolocation API such as https://ipinfo.io (which is my service). Here's an example:

function do_something(coords) {
    // Do something with the coords here
    // eg. show the user on a map, or customize
    // the site contents somehow
}

navigator.geolocation.getCurrentPosition(function(position) { 
    do_something(position.coords);
    },
    function(failure) {
        $.getJSON('https://ipinfo.io/geo', function(response) { 
        var loc = response.loc.split(',');
        var coords = {
            latitude: loc[0],
            longitude: loc[1]
        };
        do_something(coords);
        });  
    };
});

See http://ipinfo.io/developers/replacing-navigator-geolocation-getcurrentposition for more details.

@peater 2017-05-17 16:47:55

Here is the corrected link for this: ipinfo.io/developers/replacing-getcurrentposition

@ekashking 2018-06-14 07:10:32

Terrible. The accuracy is like a 5-7 miles away from the real position when in US and Canada and 100 miles away when somewhere in Russia.

@Ben Dowling 2018-06-14 14:54:14

For a lot of applications that's fine - and a lot better than have no idea what the location is.

@Vasyl Gutnyk 2016-07-13 14:53:30

I have this problem in Mozilla. All time: Error: Unknown error acquiring position.

Now i'm using 47 Mozilla. I have tried everything, but all time this problem. BUT then i open about:config in my addsress bar, go geo.wifi.ui and changed it value to "https://location.services.mozilla.com/v1/geolocate?key=test". works!

If u have Position acquisition timed out error, try to increase timeout value:

var options = {
  enableHighAccuracy: true,
  timeout: 5000,
  maximumAge: 0       
};
navigator.geolocation.getCurrentPosition(success, error, options);

@bendytree 2015-10-28 18:48:44

For anyone working on an iPhone app...

If your code is running in a UIWebView on iOS 9+, then you must set NSLocationWhenInUseUsageDescription within your app's plist.

If you don't set it then getCurrentPosition will never call back and the user will never be prompted.

@user2217751 2015-08-14 18:34:52

Thanks to everyone for their input, this helped me.

In addition to having to use watchPosition() instead of getCurrentPosition(), I also found that I needed to move the call from within document.ready() to the head.

@Niels Steenbeek 2015-08-10 09:59:12

This is already an old question, but all answers didn't solve my problem, so let's add the one I finally found. It smells like a hack (and it is one), but works always in my situation. Hope in your situation too.

//Dummy one, which will result in a working next statement.
navigator.geolocation.getCurrentPosition(function () {}, function () {}, {});
//The working next statement.
navigator.geolocation.getCurrentPosition(function (position) {
    //Your code here
}, function (e) {
    //Your error handling here
}, {
    enableHighAccuracy: true
});

@Brett Gregson 2016-03-14 13:01:03

That is the hackiest of hacks, and I have no idea how you even thought to try that, but it solves my problem. Thank you!

@Nico Westerdale 2016-07-20 14:42:49

I've used this myself in some cases. Second attempt always works better in my experience

@Scott Beeson 2017-10-04 17:03:12

Works for me too.

@th317erd 2018-03-21 23:54:37

This also works for me... strange, but thanks for the hacky find!

@Sarmad Aijaz 2018-04-20 17:40:59

you are the guy ...

@Mike McKay 2014-11-13 09:14:27

This library adds a desiredAccuracy and maxWait option to geolocation calls, which means it will keep trying to get a position until the accuracy is within a specified range.

@surfealokesea 2013-07-09 05:29:10

I finally found a working version for firefox, chrome & default navigator in android (4.2 tested only):

function getGeoLocation() {
        var options = null;
        if (navigator.geolocation) {
            if (browserChrome) //set this var looking for Chrome un user-agent header
                options={enableHighAccuracy: false, maximumAge: 15000, timeout: 30000};
            else
                options={maximumAge:Infinity, timeout:0};
            navigator.geolocation.getCurrentPosition(getGeoLocationCallback,
                    getGeoLocationErrorCallback,
                   options);
        }
    }

@Assimilater 2013-04-22 16:48:34

I noticed this problem recently myself, and I'm not sure how it comes about but it would appear sometimes firefox gets stuck on something loaded in cache. After clearing cache and restarting firefox it appears to function again.

@Drew Calder 2013-01-29 20:07:10

So I was running into the same thing. I tried the timeout solution which worked but not reliably. I found that if you just call it twice the location is refreshed properly

function getLocation(callback)
{   
    if(navigator.geolocation)
    {
        navigator.geolocation.getCurrentPosition(function(position)
        {
            navigator.geolocation.getCurrentPosition(callback, function(){},{maximumAge:0, timeout:10000});
        },function(){}, {maximumAge:0, timeout:10000});
    }
    return true;
}

this of course is a little slower but I have not had it give me the wrong position once. I have had it hit the timeout a few times and not return anything but other then that it works great. I know this is still a little hacky and I am looking forward to someone finding the real solution.

Or if you want to make sure it is going to keep trying until you want to give up you could try something like this.

//example
$(document).ready(function(){
    getLocation(function(position){
        //do something cool with position
        console.log(position);
    });
});


var GPSTimeout = 10; //init global var NOTE: I noticed that 10 gives me the quickest result but play around with this number to your own liking


//function to be called where you want the location with the callback(position)
function getLocation(callback)
{   
    if(navigator.geolocation)
    {
        var clickedTime = (new Date()).getTime(); //get the current time
        GPSTimeout = 10; //reset the timeout just in case you call it more then once
        ensurePosition(callback, clickedTime); //call recursive function to get position
    }
    return true;
}

//recursive position function
function ensurePosition(callback, timestamp)
{
    if(GPSTimeout < 6000)//set at what point you want to just give up
    {
        //call the geolocation function
        navigator.geolocation.getCurrentPosition(
            function(position) //on success
        {
                //if the timestamp that is returned minus the time that was set when called is greater then 0 the position is up to date
            if(position.timestamp - timestamp >= 0)
                {
                    GPSTimeout = 10; //reset timeout just in case
                    callback(position); //call the callback function you created
                }
                else //the gps that was returned is not current and needs to be refreshed
                {
                    GPSTimeout += GPSTimeout; //increase the timeout by itself n*2
                    ensurePosition(callback, timestamp); //call itself to refresh
                }
            },
            function() //error: gps failed so we will try again
            {
                GPSTimeout += GPSTimeout; //increase the timeout by itself n*2
                ensurePosition(callback, timestamp);//call itself to try again
            },
            {maximumAge:0, timeout:GPSTimeout}
        )
    }       
}

I probably have some typeos and some spelling errors in here but I hope you get the idea. Let me know if anyone has questions or if someone finds something better.

@K'shin Gendron 2012-05-10 19:02:36

This works for me every time:

navigator.geolocation.getCurrentPosition(getCoor, errorCoor, {maximumAge:60000, timeout:5000, enableHighAccuracy:true});

Though it isn't very accurate. The funny thing is that on the same device if I run this it puts me off about 100 meters (every time), but if I go to google's maps it finds my location exactly. So although I think the enableHighAccuracy: true helps it to work consistently, it doesn't seem to make it any more accurate...

@tony 2012-07-02 09:17:17

This has stopped firefox from denying the request and sending back a timeout object.

@K'shin Gendron 2015-02-13 19:26:55

The 100 meters away is the cell tower I'm attached to. So it's returning the location of the cell tower, not my phone. Might be more accurate if I was outside for the gps to kick in.

@Robert Smith 2015-09-16 14:48:37

It keeps putting you off a couple of meters because you have the maximumAge paremeter set to 60 seconds. So its putting your location where you were at 60 seconds ago. Set maximumAge to 10 seconds or less (maximumAge: 10000) and try again.

@Moutono 2018-05-29 16:39:37

I was using this getCurrentPosition within an Angular Resolver that returns an Observable. The Resolver only completed intermittently. Adding these options: {maximumAge:60000, timeout:5000, enableHighAccuracy:true} made it work every time!!!

@jbdemonte 2012-02-10 11:49:28

here is my solution thanks to a closure :

  function geoloc(success, fail){
    var is_echo = false;
    if(navigator && navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        function(pos) {
          if (is_echo){ return; }
          is_echo = true;
          success(pos.coords.latitude,pos.coords.longitude);
        }, 
        function() {
          if (is_echo){ return; }
          is_echo = true;
          fail();
        }
      );
    } else {
      fail();
    }
  }

  function success(lat, lng){
    alert(lat + " , " + lng);
  }
  function fail(){
    alert("failed");
  }

  geoloc(success, fail);

@going 2011-12-01 11:17:16

This is the hacky way that I am getting around this, at least it works in all current browsers (on Windows, I don't own a Mac):

if (navigator.geolocation) {
    var location_timeout = setTimeout("geolocFail()", 10000);

    navigator.geolocation.getCurrentPosition(function(position) {
        clearTimeout(location_timeout);

        var lat = position.coords.latitude;
        var lng = position.coords.longitude;

        geocodeLatLng(lat, lng);
    }, function(error) {
        clearTimeout(location_timeout);
        geolocFail();
    });
} else {
    // Fallback for no geolocation
    geolocFail();
}

This will also work if someone clicks the close or chooses no or chooses the Never Share option on Firefox.

Clunky, but it works.

@kaiser 2012-08-02 15:10:33

+1 But you're missing the geolocFail(); error handler and the getcodeLatLng(); geo coder.

@Lance Cleveland 2012-10-23 02:54:29

Sweet - the timer works beautifully if someone chooses not to share a location. Some browsers do not play well when users do this. This timer workaround worked great on my Store Locator Plus WP Plugin!

@sajith 2012-11-07 07:17:27

but this is also not working in firefox

@going 2012-11-07 21:55:34

@sajith - Not sure if this solution is now outdated with recent FF browsers. It worked at the time I provided the solution because I needed it for a site I was working on. Have you tested?

@sajith 2012-11-08 06:39:12

sorry,it worked.But i cant find what makes it work.After closing and reopen the FF its working........thanx for your solution....

@atilkan 2017-08-23 16:45:22

You should not use function inside string. Evil eval works there unnessesarrily. setTimeout("geolocFail()", 10000);

@Steve Danner 2017-11-03 16:27:10

This may seem hacky, but it works like a champ! Sad part about this is that you posted this in 2011...it's now 2017 and the same clunky solution is still required even for the latest FireFox.

@brewster 2011-11-18 20:17:41

I have been having similar issues, and have been looking into the possibility that browsers have limits on how often getCurrentPosition can be called. It seems I can often get a location, but if i refresh the page right away it will time out. If I wait for a bit, I can usually get a location again. This usually happens with FF. In Chrome and Safari, I have not yet noticed getCurrentPosition timing out. Just a thought...

Although I cannot find any documentation to support this, it was a conclusion I came to after much testing. Perhaps someone else has has some info about that?

@Jamie 2011-12-18 20:12:15

That's a good point. My timeouts/fails seem to happen mostly when I'm testing and am repeatedly querying geolocation data. I'm anxious to know if this is the result of a bug or, as you suggest, possibly by design.

@Nico Westerdale 2016-07-20 14:44:09

I've not seen any case where the browser limits the amount of calls to the location services. How often are you querying?

@Mark Baijens 2010-12-10 01:33:15

You don't get an error message because it has no timeout by default (At least i think). I have had the same problem with firefox only for me firefox always gives an timeout. You can set a timeout yourself like this.

I have set the maximum age to Infinity to make sure that is not problem. My function works great in chrome but i get a timeout everytime in firefox.

    navigator.geolocation.getCurrentPosition(
        function(position) {
            //do succes handling
        },
        function errorCallback(error) {
            //do error handling
        },
        {
            maximumAge:Infinity,
            timeout:5000
        }
    );

I recommend to watch your errors carefully. Be expected for everything. Have a backup plan for everything. I use some default values or values from my database myself in case both google geolocations and navigator geolocations fails.

@Porco 2013-10-15 16:53:53

just an FYI, maximumAge refers to the age of the location data in cache, setting it to infinity guarantees you'll get a cached version. Setting it to 0 forces the device to retrieve the position.

@brennanyoung 2010-10-07 19:26:25

I have been having exactly the same problem, and finding almost no information online about it. Nothing at all in the books. Finally I found this sober query on stackoverflow and (ha!) it was the final impetus I needed to set up an account here.

And I have a partial answer, but alas not a complete one.

First of all, realise that the default timeout for getCurrentPosition is infinite(!). That means that your error handler will never be called if getCurrentPosition hangs somewhere on the back end.

To ensure that you get a timeout, add the optional third parameter to your call to getCurrentPosition, for example, if you want the user to wait no more than 10 seconds before giving them a clue what is happening, use:

navigator.geolocation.getCurrentPosition(successCallback,errorCallback,{timeout:10000});

Secondly, I have experienced quite different reliability in different contexts. Here at home, I get a callback within a second or two, although the accuracy is poor.

At work however, I experience quite bizarre variations in behavior: Geolocation works on some computers all the time (IE excepted, of course), others only work in chrome and safari but not firefox (gecko issue?), others work once, then subsequently fail - and the pattern changes from hour to hour, from day to day. Sometimes you have a 'lucky' computer, sometimes not. Perhaps slaughtering goats at full moon would help?

I have not been able to fathom this, but I suspect that the back end infrastructure is more uneven than advertised in the various gung-ho books and websites that are pushing this feature. I really wish that they would be a bit more straight about how flakey this feature is, and how important that timeout setting is, if you want your error handler to work properly.

I have been trying to teach this stuff to students today, and had the embarassing situation where my own computer (on the projector and several large screens) was failing silently, whereas about 80% of the students were getting a result almost instantly (using the exact same wireless network). It's very difficult to resolve these issues when my students are also making typos and other gaffes, and when my own pc is also failing.

Anyway, I hope this helps some of you guys. Thanks for the sanity check!

@Felipe Lima 2010-12-29 22:36:13

Good detailed info, thanks! I'm seeing the same problems, but only on Firefox 3.6.13. Chrome seems to be quite reliable.

@Richard 2011-10-28 13:00:38

Same here, and the maximumAge parameter seems to be unreliable too. Thanks for the post.

@mlo55 2013-08-06 07:45:25

Nice one, I had the same issue (on a Samsung Galaxy Tab, 10.1, running Android 4.0.3), once I used the timeout param above, I was able to handle the issue.

@George Filippakos 2013-10-31 13:58:47

On Win8: Google Chrome v30 - works for the first time and then always fails. IE10/11 works every time. Firefox v24 always fails.

@TheCarver 2013-12-06 21:17:31

I find that if I close my browser down and relaunch, my position is returned rather quickly. If I then refresh the browser and try again, it fails. I try again later and it works! Thanks for the timeout suggestion - this will help tremendously. Very unreliable feature. It's shame because it's a very important one for various projects of mine.

@TheCarver 2013-12-06 22:17:10

Another tip: if like me you don't need 100% precise location, just an area, you can set enableHighAccuracy:false and the whole process can be a lot quicker. Setting it to false has hardly affected anything - it's still pretty accurate. I'm not showing a marker on the map when the position is found, I just want the map's view to be in the right area to start with.

@François 2014-09-24 13:52:37

It's important to understand what the timeout option in getCurrentPosition() is actually timing. It does not time the user to allow or deny the geolocation request, but how long the network is allowed to take to return a location once permission is granted. If the user does not answer the geolocation request, the error handler will never be called. Thus, you need a second timeout like in @xiaohouzi79 answer.

@d1jhoni1b 2014-10-07 23:23:15

In case of having an hybrid app (cordova based with nested WebView instead of browser) going to Location Services and enabling ALL options (GPS and Wi-fi) will fix odd issues, i just had this using Cordova 3.X and KitKat all working just fine

@Asim K T 2016-05-12 08:32:51

slaughtering goats at full moon would help? LOL

@AlexRebula 2017-10-17 02:22:53

Thanks buddy! Great info and great explanation! Helped me too.

@mvilrokx 2010-09-11 06:26:37

Same here people, this works perfect btw in Chrome (stable, dev and canary) just not in FF and Safari. It also works perfect on my iPhone and iPad (Safari!). This might be due to the relative newness of this feature (i.e. it is a bug). I spend almost a week on this now and I just cannot get it to work on those browsers

Here's what I found:

The first time you call getCurrentPosition it works perfect. Any subsequent call never returns, i.e. it does not fire the successCallback or the errorCallback functions. I added a few position options to my call to prove my point:

 navigator.geolocation.getCurrentPosition(successCallback, errorCallback,  {timeout: 10000});

and it times out every time (after the first successful call). I thought I could fix it with maximumAge, but that doesn't seem to be working as it is suppose to work either:

navigator.geolocation.getCurrentPosition(successCallback, errorCallback,  {maximumAge:60000, timeout: 2000});

this should prevent actually calling the getCurrentPosition function if you call it within 60 seconds, but it ignores this (however, this could be due because I actually refresh my page to trigger the second call, not sure if this is persistent accross calls)

btw, even google's examples fail on these browsers which leads me to believe that this are indeed browser bugs, try it, load it twice in Safari and it won't work the second time.

If anybody finds a solution for this, PLEASE let me know :-)

Cheers.

@going 2011-12-01 11:19:51

See my workaround below and let me know what you think.

@Adriano Rizzo 2012-12-12 12:57:17

I have the exact problem as yours, it works for the first call but never the next ones, if anyone find a solution i would be very intersted... @xiaohouzi79 your solution ends every time(except for the frist one) in geolocFail()

Related Questions

Sponsored Content

88 Answered Questions

[SOLVED] How do JavaScript closures work?

17 Answered Questions

[SOLVED] Why is setTimeout(fn, 0) sometimes useful?

20 Answered Questions

[SOLVED] How does the "this" keyword work?

  • 2010-06-27 13:12:56
  • Maxim Gershkovich
  • 350160 View
  • 1092 Score
  • 20 Answer
  • Tags:   javascript this

23 Answered Questions

[SOLVED] How does JavaScript .prototype work?

14 Answered Questions

[SOLVED] How does data binding work in AngularJS?

2 Answered Questions

[SOLVED] GeoLocation Google Maps not working

1 Answered Questions

[SOLVED] Updating values in async await

2 Answered Questions

[SOLVED] Get the value from the function

  • 2017-01-07 01:47:12
  • Justin
  • 42 View
  • 0 Score
  • 2 Answer
  • Tags:   javascript

2 Answered Questions

0 Answered Questions

Uncaught Type Error: Can not read property latitude

Sponsored Content