Remy Sharp
THE GEOLOCATION API is one of those APIs that has absolutely nothing to do with the HTML5 specification, and was created by the W3C rather than the WHATWG. In fact, it was never even part of the original Web Applications specification (though it does now reference the HMTL5 specification), but it’s so darn cool that we had to include it in this book. In actuality, it’s a key API when it comes to applications and adding some wicked—yes, wicked—social interaction.
The API is incredibly simple to work with, and you can easily enhance your web apps if they make use of any geo data by plugging this API into the app and saving your visitors from having to finger or scroll all over your map to find themselves.
Currently Firefox 3.5, Chrome 5, Safari 5 and Opera 10.60 all have support for the geolocation API—not a bad state to be in for a bleeding edge technology. In addition, a lot of new mobile phones and mobile browsers are supporting the geolocation API, particularly through the mobile WebKit implementation. Fennec, Mozilla’s mobile browser also supports geolocation which might be used on the Android device for instance. In addition, if you’re using the Open Web technologies to build your applications, PhoneGap, the framework for deploying Open Web mobile apps, provides the geolocation API.
The geolocation API gives us a way to locate the exact position of our visitor. There are already lots of applications that make use of this API, ranging from mapping, as seen on Google Maps in Figure 9.1, to location-based social networks such as Gowalla and Google Buzz.
The geolocation API offers two methods for getting the geo information from your user:
getCurrentPosition
is a one-shot method for grabbing the user’s current location.watchPosition
keeps an eye on their position and keeps polling at regular intervals to see if their location has changed. watchPosition
mirrors getCurrentPosition
’s functionality, but also if the user’s position changes, it will tell your code.Both getCurrentPosition
and watchPosition
work asynchronously to ascertain the user’s location. There is one exception to that rule: if the user is visiting your site for the first time and the browser forces a model dialog asking for permission to share your location. When using either of these methods, most devices will prompt the user and ask whether they want to share their location with the application. If they don’t agree to sharing their location, and you’ve told the geolocation API to pass errors to a specific function, it will be called with the error details.
The specification says:
“User agents must not send location information to websites without the express permission of the user.”
So it’s up to the browser to prompt users to inform them that we’re trying to grab their current position. Different browsers handle this in different ways. Firefox, for example, offers a non-modal, non-blocking alert asking users if they want to share their location (see Figure 9.2). This means your application continues to execute.
Other browsers, such as Mobile Safari, prompt the user with a model dialog, stopping all code execution until the user responds (Figure 9.3).
The geolocation API exists inside the navigator object and contains only three methods:
• getCurrentPosition
• watchPosition
• clearWatch
The watchPosition
and clearWatch
are paired methods. The watch and clear methods work the same way that setInterval
and setTimeout
work. watchPosition
returns a unique identifier that is passed in to clearWatch
to clear that particular watch.
As I mentioned before, both getCurrentPosition
and watchPosition
mirror each other and take the same arguments:
• success handler
• error handler
• geolocation options
Simple usage of the geolocation API would be to pass a success handler to the getCurrentPosition
method:
navigator.geolocation.getCurrentPosition(function (position) {
alert('We found you!'),
// now do something with the position data
});
If the user permits the browser to share his geolocation and there’s no other error, the success handler will be called, which is the first argument to getCurrentPosition
and watchPosition
.
The handler receives a Position
object containing two properties: coords
object (containing coordinate information) and a timestamp
. The coordinates object is where the interesting stuff is sitting. There are really two grades of data in the position object. The first grade is appearing in all the browsers with geolocation support: Chrome 5, Firefox 3.5+, Mobile Safari & Safari 5, and Android 2.0:
• readonly attribute double latitude
• readonly attribute double longitude
• readonly attribute double accuracy
Note that accuracy is the measurement of the latitude and longitude accuracy in meters. You could use this to show a radius of accuracy if you were mapping the user’s position.
The second grade of data inside the coordinates object are supported, but they currently don’t have any values associated. They will be null, 0, or NaN
in all the browsers currently supporting native geolocation:
• readonly attribute double altitude
• readonly attribute double altitudeAccuracy
• readonly attribute double heading
• readonly attribute double speed
Using the coordinate data, you could easily map the user’s current position on something like a Google map:
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function
¬ (position) {
var coords = position.coords;
showMap(coords.latitude, coords.longitude,
¬ coords.accuracy);
});
}
In a lot of applications, it’s likely that the user will be offered a manual way to set his current position. If the geolocation method is available, the site may offer the advanced functionality, progressively enhancing the page or the whole experience.
An example can be seen at http://owlsnearyou.com. Upon visiting the site, if geolocation is available, it reloads the page with your position loaded (see Figure 9.4), showing you where you can go owl hunting, if that’s the activity that gets you going after a day of HTML5 development. If geolocation isn’t available, it simply asks you to enter your location.
The second argument to the getCurrentPosition
and watchPosition
method is the error handler. This is particularly important if you want to provide some alternative method of location (such as manually) or you want to notify the user of any errors in getting her position. The error handler may trigger if the user denies her position, but it could be that the user has given you permission and now you are watching her position on a mobile device and the phone has gone out of reception. This too would cause the error handler to trigger.
The error handler receives a single argument containing a position error object containing two properties:
• readonly attribute unsigned short code
• readonly attribute DOMString message
The code
property will be only one of the following:
• PERMISSION_DENIED
(numeric value 1)
• POSITION_UNAVAILABLE
(numeric value 2)
• TIMEOUT
(numeric value 3)
The message
property is useful for developing and debugging but wouldn’t be appropriate to show the user. The message
property isn’t always available (as it’s not currently in Firefox 3.6+).
For example, if you used the following code and elected to not share the position, the page announces “Permission denied: means we can’t determine your position.”
Finally, the third argument to both getCurrentPosition
and watchPosition
are the geolocation options. All the geolocation options are optional, as you’ve seen, and are made up as follows:
• enableHighAccuracy
(Boolean, default false)
• timeout
(in milliseconds, default infinity/0)
• maximumAge
(in milliseconds, default 0)
For example, to request high accuracy, a two-second timeout, and to never use old geo data, call getCurrentPosition
using the following options (where success
and error
are predefined functions):
navigator.geolocation.getCurrentPosition(success, error, {
enableHighAccuracy: true,
timeout: 2000,
maximumAge: 0
});
The enableHighAccuracy
tells the device to try to get a more accurate reading on the latitude and longitude. On a mobile device, this may be to make use of the GPS on a phone, which could consume more power on the mobile device. Typically, you want the battery to last as long as possible, which is why by default, enableHighAccuracy
is set to false.
The timeout tells the geolocation lookup how long it should wait before giving up and triggering the error handler (but won’t start counting down if it’s waiting for the user to approve the request). If it does timeout, the error code is set to 3 (TIMEOUT
). Setting a zero time out (the current default) tells the browser to never time out.
Finally, maximumAge
can be used to tell the browser whether to use recently cached position data. If there is a request that is within the maximumAge
(in milliseconds), it is returned instead of requesting a new position. maximumAge
can also be Infinity
, which tells the browser to always use a cached position. Setting the maximumAge
to zero (the default value) means the browser must look up a new position on each request.
The geolocation API uses a few different techniques in acquiring your position. Most of it is black magic to most people, including myself, but it’s worth having an idea about what’s under the hood as it will affect the accuracy of the position data.
GPS is one of the obvious methods for getting position data. More computing devices are being fitted out with GPS, ranging from mobile phones to laptops. Assuming there’s a clear enough line to the GPS ground station (which picks up readings from satellites to triangulate your position—yep, more black magic), then you’ll have a very accurate reading on your position. GPS should also be able to give you altitude, which we saw in the second grade of properties in the coordinates object. So far this data isn’t showing up in browsers, but I’d expect this to become available in time as mobile computing evolves quickly.
Another method would be using network information, which would be typical if used via a desktop browser such as Firefox. The network information could use wifi triangulation and IP addresses to make a best guess at your location. The developer makes a call to the browser’s geolocation API, which in turn the browser makes a call to a third-party service such as Skyhook or Google. Although this may not be as accurate as GPS (meterage-wise), it could make for a very good backup as GPS doesn’t work very well indoors or in highrise urban locations.
Overall it’s not terribly important to know what makes geolocation tick, but if you need to get the high accuracy you might want to be wary of using the more power-hungry devices such as GPS and be wary of killing your user’s battery.
All in all, it’s some very cool black magic.
In the UK, when red telephone boxes were still a common sight, inside each of these boxes included a printed note of the current address that you were calling from. This was so that if you had to call the police or an ambulance you knew where you were. Of course, this also helped after a hazy Friday night, calling home for a lift because you didn’t know where you were.
Browsers now come shipped with this feature built in, and it’s one of the simplest APIs available to implement. If your web site needs any location-based information from your user, then you can see it’s easy as pie to progressively enhance your page to support this new API. It’s only a matter of time until someone builds the web site that you open, and it instantly tells you your nearest greasy spoon cafe or curry house all entirely dependent on the current time and your current location.