Geolocation Redux and a JS Library
After the excellent feedback I got on my last geolocation blog post, I’ve updated the proposed geolocation API. More importantly, I’ve also created a pure Javascript library which you can use to start playing around with geolocation before we actually get it into the browser. This library provides exactly the same API as would be provided by the browser. Although it can’t offer GPS-quality data, it does provide a decent city-level geolocation based on your IP. You can get the library here, and there’s also a no-frills demo.
For quick hacking you can just include the following in your head tag.
<script src="http://azarask.in/projects/geolocation/MockGeolocation.js"><script>
The best way to get a feel for the API is to see some examples:
var g = new navigator.GeolocationRequest();
g.request( function(geolocation){
alert( geolocation.longitude + ", " + geolocation.latitude );
})
This is the same example as we saw last time; it alerts the user’s current location. What’s new is that I’ve spec’ed out the object passed to the callback (I’ve borrowed some of the great work done for the GoogleGears Location API):
interface Geolocation {
readonly double latitude; // in degrees
readonly double longitude; // in degrees
readonly double altitude; // in meters, or null if no data.
readonly double accuracy; // in meters
readonly double altitudeAccuracy; // in meters, or null if no data
int timestamp; // time of the location read, in seconds since
// the epoch
}
Everything here should be self-explanatory. As a commenter mentioned last time, it’s important to know when the last location reading occurred. Without it, for example, it would be impossible to reliably calculate the current speed of the browsing device. (Knowing such data gives developers all sorts of fun—we could have an onDrunkDriving DOM event for when the browser detects your moving at 60MPH and weaving!).
Let’s move on to something a bit more complicated.
var g = new navigator.GeolocationRequest();
g.request({
error: function(e){ alert( e.message ); },
success: function(location){
alert( location.altitude + "+/-" + location.altitudeAccuracy );
},
desiredAccuracy: g.defaultAccuracy
})
Here’s the new stuff:
error takes a callback whose argument is an object. The only attribute the object must have is message, a human readable explanation of the error. The error object may have other attributes, as dictated by the particulars of the location-giving device.
desiredAccuracy is a string which can take one of three values: “exact”, “neighbourhood”, and “city”. In order, “exact” means to return a geolocation as precisely as possible, “neighbourhood” means to return a geolocation good to 1km, and “city” means to return a geolocation good to 10km. It’s unnecessary to include a “country” option because there are more accurate ways of knowing what country a user is browsing from than with a highly fuzzed lat/long (e.g., IP-based geolocation).
defaultAccuracy is a read only property of the GeolocationRequest object that contains the user’s globally-set preference for yielding location to content providers. If the user has opted to give all websites city-level access to their location, then a website requesting city-level information won’t cause the browser to prompt for permission. In the above example, the request is asking for the highest accuracy location that won’t prompt the user for permission. defaultAccuracy is null if the user has opted out of providing geolocation information.
That about wraps it up for the API. Full interface documentation is available.
Why not on window.navigator?
It’s tempting to attach the GeolocationRequest object to window, but it makes more semantic sense to place it on the navigator object (and, unfortunately, not just for the pun). The navigator object contains meta information about the browsing agent—browser version, os, language, etc—and geolocation information is just that. Looking at it from the other side, the window object should contain information that is tied to the current tab/window. Geolocation is independent of what tab/window you are looking at (unless, of course, you have an extremely large screen), and so should not be attached directly to window.
Geocoding API
I’m somewhat on the fence about whether to include geocoding as part of the fundamental GeolocationRequest API. The information is useful to web developers, and it is a boon to not require an extra Ajax call to perform geocoding. However, it’s going beyond the scope of the fundamental language of geolocation. To quote Arun Ranganathan, our standards hero here at Mozilla:
That aside, we don’t really have to choose. By designing the API right, we can upgrade to include geocoding at a later date, without breaking any code. Let’s see it in action:
var g = new navigator.GeolocationRequest();
g.request({
error: function(e){ /* Handle error. */ ); },
success: function(location){ alert( location.address.city ); },
desiredAccuracy: "neighborhood",
requestAddress: true,
addressLanguage: "en-US"
})
You can get the library for the address-enabled API here. The address object interface is:
interface Address {
// Any of the below can be null, if not known.
readonly string streetNumber; // street number
readonly string street; // street address
readonly string premises; // premises, e.g. building name
readonly string city; // city name
readonly string county; // county name
readonly string region; // region, e.g. a state in the US
readonly string country; // country
readonly string countryCode; // country code (ISO 3166-1)
readonly string postalCode; // postal code
}
The full specification is available, if you are interested in such sundry documentation.
Interface
Based on a number of good suggestions from the last post, this is how I’m thinking the security UI should look:

16 Comments
Jump to comment form | comments rss [?] | trackback uri [?]