28 August 2008

The W3C Geolocation API on iPhone with Locatable

I've ported the W3C's draft Geolocation API so it can be used from an iPhone with Locatable installed (my Javascript skills are far from elite, but with enough prodding and old-school alert() debugging, I got there). This means that in addition to the redirect API (which is nice for embedding static links to pages that can take lat/long coordinates), you can now get at location information on demand via Javascript, through what is likely to become the standard API in future browsers.
To use it, just include this in your HEAD:

You can download and install the script locally if you like (but please check back for new versions from time to time).
Then, to use it, just use the standard W3C-prescribed approach via a global object called Locatable, e.g.

The only addition to the W3C API is an isEnabled() method. This will attempt to figure out if the API will work on the current browser. Right now this merely checks if someone is on an iPhoneOS device, but might be more sophisticated in the future.
There's a test page up at http://www.tralfamadore.com/test-w3c.html that demonstrates this functionality.
Some implementation notes:

The same logic applies when sharing location as with the redirector. Depending on user preferences, an alert will ask them to confirm if they want to share their location. If they decline, you'll get an error callback if you provide the second argument to getCurrentPosition.

If the location needs to be refreshed, the app will launch, update the reading, and then return to Safari. This can take some time (in Locatable 0.3, up to 20 seconds, depending on the user accuracy setting). On jailbroken phones with default Locatable settings this is unlikely to occur as the daemon will be updating location in the background, but an AppStore version will not have this advantage, so be mindful of this.

W3C PositionOptions (the accuracy hint) does nothing at the moment.

watchPosition() is "implemented" (that is, the function exists), but you'll only ever get one reading, so it's not entirely useful.

The accuracy reading in the position object is currently the user-set minimum accuracy level (a round number like 10, 100, or 1000 meters), not the device-reported accuracy of the reading itself. This is likely to change in future versions.

Altitude and velocity are not implemented yet and yield null values.

w3c-api.js will attempt to detect if you're running an iPhone or iPod Touch and not install itself otherwise. It also won't overwrite navigator.geolocation if it's already implemented (non-null).

It probably goes without saying, but you should include the w3c-api.js script on every page you want to use it in.

I'd consider this a beta version — I've done some basic testing but haven't tried too many use cases. Let me know how it works for you in the comments.
Update (31 Aug 08): Upon some reflection, I decided it's best not to try to automatically install as the navigator.geolocation global, so the script has been updated to use a global called Locatable (capital L) instead. You're free to assign it to navigator yourself (i.e. navigator.geolocation = Locatable). Also added the isEnabled() method.