- •Contents at a Glance
- •Contents
- •Foreword
- •About the Authors
- •About the Technical Reviewer
- •Acknowledgments
- •Introduction
- •Who This Book Is For
- •An Overview of This Book
- •Example Code and Companion Web Site
- •Contacting the Authors
- •Overview of HTML5
- •The Story So Far—The History of HTML5
- •The Myth of 2022 and Why It Doesn’t Matter
- •Who Is Developing HTML5?
- •A New Vision
- •Compatibility and Paving the Cow Paths
- •Utility and the Priority of Constituencies
- •Interoperability Simplification
- •Universal Access
- •A Plugin–Free Paradigm
- •What’s In and What’s Out?
- •What’s New in HTML5?
- •New DOCTYPE and Character Set
- •New and Deprecated Elements
- •Semantic Markup
- •Simplifying Selection Using the Selectors API
- •JavaScript Logging and Debugging
- •window.JSON
- •DOM Level 3
- •Monkeys, Squirrelfish, and Other Speedy Oddities
- •Summary
- •Using the Canvas API
- •Overview of HTML5 Canvas
- •History
- •What Is a Canvas?
- •Canvas Coordinates
- •When Not to Use Canvas
- •Fallback Content
- •CSS and Canvas
- •Browser Support for HTML5 Canvas
- •Using the HTML5 Canvas APIs
- •Checking for Browser Support
- •Adding a Canvas to a Page
- •Applying Transformations to Drawings
- •Working with Paths
- •Working with Stroke Styles
- •Working with Fill Styles
- •Filling Rectangular Content
- •Drawing Curves
- •Inserting Images into a Canvas
- •Using Gradients
- •Using Background Patterns
- •Scaling Canvas Objects
- •Using Canvas Transforms
- •Using Canvas Text
- •Applying Shadows
- •Working with Pixel Data
- •Implementing Canvas Security
- •Building an Application with HTML5 Canvas
- •Practical Extra: Full Page Glass Pane
- •Practical Extra: Timing Your Canvas Animation
- •Summary
- •Working with Scalable Vector Graphics
- •Overview of SVG
- •History
- •Understanding SVG
- •Scalable Graphics
- •Creating 2D Graphics with SVG
- •Adding SVG to a Page
- •Simple Shapes
- •Transforming SVG Elements
- •Reusing Content
- •Patterns and Gradients
- •SVG Paths
- •Using SVG Text
- •Putting the Scene Together
- •Building an Interactive Application with SVG
- •Adding Trees
- •Adding the updateTrees Function
- •Adding the removeTree Function
- •Adding the CSS Styles
- •The Final Code
- •Summary
- •Working with Audio and Video
- •Overview of Audio and Video
- •Video Containers
- •Audio and Video Codecs
- •Audio and Video Restrictions
- •Browser Support for Audio and Video
- •Using the Audio and Video API
- •Checking for Browser Support
- •Accessibility
- •Understanding Media Elements
- •Working with Audio
- •Working with Video
- •Practical Extras
- •Summary
- •Using the Geolocation API
- •About Location Information
- •Latitude and Longitude Coordinates
- •Where Does Location Information Come From?
- •IP Address Geolocation Data
- •GPS Geolocation Data
- •Wi-Fi Geolocation Data
- •Cell Phone Geolocation Data
- •User–Defined Geolocation Data
- •Browser Support for Geolocation
- •Privacy
- •Triggering the Privacy Protection Mechanism
- •Dealing with Location Information
- •Using the Geolocation API
- •Checking for Browser Support
- •Position Requests
- •Building an Application with Geolocation
- •Writing the HTML Display
- •Processing the Geolocation Data
- •The Final Code
- •Practical Extras
- •What’s My Status?
- •Show Me on a Google Map
- •Summary
- •Using the Communication APIs
- •Cross Document Messaging
- •Understanding Origin Security
- •Browser Support for Cross Document Messaging
- •Using the postMessage API
- •Building an Application Using the postMessage API
- •XMLHttpRequest Level 2
- •Cross-Origin XMLHttpRequest
- •Progress Events
- •Browser Support for HTML5 XMLHttpRequest Level 2
- •Using the XMLHttpRequest API
- •Building an Application Using XMLHttpRequest
- •Practical Extras
- •Structured Data
- •Framebusting
- •Summary
- •Using the WebSocket API
- •Overview of WebSocket
- •Real-Time and HTTP
- •Understanding WebSocket
- •Writing a Simple Echo WebSocket Server
- •Using the WebSocket API
- •Checking for Browser Support
- •Basic API Usage
- •Building a WebSocket Application
- •Coding the HTML File
- •Adding the WebSocket Code
- •Adding the Geolocation Code
- •Putting It All Together
- •The Final Code
- •Summary
- •Using the Forms API
- •Overview of HTML5 Forms
- •HTML Forms Versus XForms
- •Functional Forms
- •Browser Support for HTML5 Forms
- •An Input Catalog
- •Using the HTML5 Forms APIs
- •New Form Attributes and Functions
- •Checking Forms with Validation
- •Validation Feedback
- •Building an Application with HTML5 Forms
- •Practical Extras
- •Summary
- •Working with Drag-and-Drop
- •Web Drag-and-Drop: The Story So Far
- •Overview of HTML5 Drag-and-Drop
- •The Big Picture
- •Events to Remember
- •Drag Participation
- •Transfer and Control
- •Building an Application with Drag-and-Drop
- •Getting Into the dropzone
- •Handling Drag-and-Drop for Files
- •Practical Extras
- •Customizing the Drag Display
- •Summary
- •Using the Web Workers API
- •Browser Support for Web Workers
- •Using the Web Workers API
- •Checking for Browser Support
- •Creating Web Workers
- •Loading and Executing Additional JavaScript
- •Communicating with Web Workers
- •Coding the Main Page
- •Handling Errors
- •Stopping Web Workers
- •Using Web Workers within Web Workers
- •Using Timers
- •Example Code
- •Building an Application with Web Workers
- •Coding the blur.js Helper Script
- •Coding the blur.html Application Page
- •Coding the blurWorker.js Web Worker Script
- •Communicating with the Web Workers
- •The Application in Action
- •Example Code
- •Summary
- •Using the Storage APIs
- •Overview of Web Storage
- •Browser Support for Web Storage
- •Using the Web Storage API
- •Checking for Browser Support
- •Setting and Retrieving Values
- •Plugging Data Leaks
- •Local Versus Session Storage
- •Other Web Storage API Attributes and Functions
- •Communicating Web Storage Updates
- •Exploring Web Storage
- •Building an Application with Web Storage
- •The Future of Browser Database Storage
- •The Web SQL Database
- •The Indexed Database API
- •Practical Extras
- •JSON Object Storage
- •A Window into Sharing
- •Summary
- •Overview of HTML5 Offline Web Applications
- •Browser Support for HTML5 Offline Web Applications
- •Using the HTML5 Application Cache API
- •Checking for Browser Support
- •Creating a Simple Offline Application
- •Going Offline
- •Manifest Files
- •The ApplicationCache API
- •Application Cache in Action
- •Building an Application with HTML5 Offline Web Applications
- •Creating a Manifest File for the Application Resources
- •Creating the HTML Structure and CSS for the UI
- •Creating the Offline JavaScript
- •Check for ApplicationCache Support
- •Adding the Update Button Handler
- •Add Geolocation Tracking Code
- •Adding Storage Code
- •Adding Offline Event Handling
- •Summary
- •The Future of HTML5
- •Browser Support for HTML5
- •HTML Evolves
- •WebGL
- •Devices
- •Audio Data API
- •Touchscreen Device Events
- •Peer-to-Peer Networking
- •Ultimate Direction
- •Summary
- •Index
CHAPTER 5 USING THE GEOLOCATION API
Dealing with Location Information
Location data is sensitive information, so when you receive it, you must be careful about handling, storing, and retransmitting the data. Unless users give permission to store data, you should always dispose of the data after the task for which it was required is complete.
Therefore, if you retransmit the location data, it is recommended that you first encrypt the data. Regarding the collection of geolocation data, your application should prominently show the following:
•That you are collecting location data
•Why you are collecting location data
•How long the location data is kept
•How you are securing the data
•How and with whom the location data is shared (if it is)
•How users can check and update their location data
Using the Geolocation API
In this section, we’ll explore the use of the Geolocation API in more detail. For the sake of illustration, we’ve created a simple browser page—geolocation.html. Remember that you can download all the code from the book's page on apress.com or on the companion website http://prohtml5.com.
Checking for Browser Support
Before you call the Geolocation API functions, you will want to make sure that there is support in the browser for what you’re about to do. This way, you can provide some alternate text, prompting the users of your application to dump their dinosaur-like browsers or install a plugin such as Gears, which augments the existing browser functionality. Listing 5-1 shows one way you can use to test for browser support.
Listing 5-1. Checking for Browser Support
function loadDemo() { if(navigator.geolocation) {
document.getElementById("support").innerHTML = "Geolocation supported.";
} else {
document.getElementById("support").innerHTML = "Geolocation is not supported in your browser.";
}
}
In this example, you test for browser support in the loadDemo function, which might be called when the application’s page is loaded. A call to navigator.geolocation (you can also use Modernizr) will return the Geolocation object if it exists, or trigger the failure case if it does not. In this case, the page is updated to reflect whether there is browser support or not by updating a previously defined support element on the page with a suitable message.
114
CHAPTER 5 USING THE GEOLOCATION API
Position Requests
There are two types of position requests:
•One-shot position request
•Repeated position updates
One-Shot Position Requests
In many applications, it will be acceptable to retrieve the user’s location only once, or only by request. For example, if someone is looking for the nearest movie theater showing today’s popular movie in the next hour, the simplest form of the Geolocation API shown in Listing 5-2 can be used.
Listing 5-2. One-Shot Position Request
void getCurrentPosition(in PositionCallback successCallback,
in optional PositionErrorCallback errorCallback, in optional PositionOptions options);
Let’s take a look at this core function call in more detail.
First, this is a function that is available on the navigator.geolocation object, so you will need to have already retrieved this object in your script. As noted previously, make sure that you have a good fallback handler if your browser does not support Geolocation.
The function takes one required parameter, and two optional ones.
•The successCallback function parameter tells the browser which function you want called when the location data is made available. This is important because operations such as fetching location data may take a long time to complete. No user wants the browser to be locked up while the location is retrieved, and no developer wants his program to pause indefinitely—especially because fetching the location data will often be waiting on a user to grant permission. The successCallback is where you will receive the actual location information and act on it.
•However, as in most programming scenarios, it is good to plan for failure cases. It is quite possible that the request for location information may not complete for reasons beyond your control, and for those cases you will want to provide an errorCallback function that can present the user with an explanation, or perhaps make an attempt to try again. While optional, it is recommended that you provide one.
•Finally, an options object can be provided to the Geolocation service to fine-tune the way it gathers data. This is an optional parameter that we will examine later.
Let’s say that you’ve created a JavaScript function on our page named updateLocation() in which you update the contents of the page with the new location data. Similarly, you’ve created a handleLocationError() function to handle the error cases. We’ll examine the details of those functions next, but that means that your core request to access the user’s position would look something like this:
navigator.geolocation.getCurrentPosition(updateLocation, handleLocationError);
115
CHAPTER 5 USING THE GEOLOCATION API
The updateLocation() Function
So, what happens in our updateLocation() call? It’s actually quite simple. As soon as the browser has access to the location information, it will call updateLocation() with a single parameter: a position object. The position will contain coordinates—as the attribute coords—and a timestamp for when the location data was gathered. While you may or may not need the timestamp, the coords attribute contains the crucial values for the location.
The coordinates always have multiple attributes on them, but it is up to the browser and the hardware of the user’s device whether they will have meaningful values. The following are the first three attributes:
•latitude
•longitude
•accuracy
These attributes are guaranteed to have values and are fairly self-explanatory. latitude and longitude will contain the Geolocation service’s best determined value of the user’s location specified in decimal degrees. accuracy will contain a value in meters that specifies how close the latitude and longitude values are to the actual location, with a 95% confidence level. It can therefore be used to display a proximity radius around the location to give people a visual clue about the accuracy. Due to the nature of Geolocation implementations, approximation will be common and coarse. Make sure to check the accuracy of the returned values before you present them with any certainty. Recommending a user to visit a “nearby” shoe store that is actually hours away could have unintended consequences.
The other attributes of the coordinates are not guaranteed to be supported, but they will return a null value if they are not available (for example, if you’re on a desktop computer, you’re unlikely to have access to this information):
•altitude—the height of the user’s location, in meters
•altitudeAccuracy—once again in meters, or null if no altitude is provided
•heading—direction of travel, in degrees relative to true north
•speed—ground speed in meters per second
Unless you are sure that your users have devices with access to such information, it is recommended that you not rely on them as critical to your application. While global positioning devices are likely to provide this level of detail, simple network triangulation will not.
Now let’s take a look at a code implementation of our updateLocation() function that performs some trivial updates with the coordinates (see Listing 5-3).
Listing 5-3. Example of Using the updateLocation() Function
function updateLocation(position) {
var latitude = position.coords.latitude; var longitude = position.coords.longitude; var accuracy = position.coords.accuracy; var timestamp = position.timestamp;
document.getElementById("latitude").innerHTML = latitude; document.getElementById("longitude").innerHTML = longitude;
116
CHAPTER 5 USING THE GEOLOCATION API
document.getElementById(“accuracy”).innerHTML = accuracy document.getElementById("timestamp").innerHTML = timestamp;•
}
In this example, the updateLocation() callback is used to update the text in different elements of our page; we put the value of the longitude attribute in the longitude element, the latitude attribute in the latitude element, and accuracy and timestamp in their corresponding fields.
The handleLocationError() Function
Handling errors is very important for a Geolocation application because there are many moving parts and therefore many possibilities for the location calculation services to go awry. Fortunately, the API defines error codes for all the cases you will need to handle, and it sets them on the error object passed to your error handler as the code attribute. Let’s look at them in turn:
•PERMISSION_DENIED (error code 1)—The user chose not to let the browser have access to the location information.
•POSITION_UNAVAILABLE (error code 2)—The technique used to determine the user’s location was attempted, but failed.
•TIMEOUT (error code 3)—A timeout value was set as an option, and the attempt to determine the location exceeded that limit.
In these cases, you will probably want to let the user know that something went wrong. You may want to retry getting the values in the case of an unavailable or timed-out request.
Listing 5-4 shows an example of an error handler in action.
Listing 5-4. Using an Error Handler
function handleLocationError(error) { switch(error.code){
case 0:
updateStatus("There was an error while retrieving your location: " + error.message);
break; case 1:
updateStatus("The user prevented this page from retrieving a location."); break;
case 2:
updateStatus("The browser was unable to determine your location: " + error.message);
break; case 3:
updateStatus("The browser timed out before retrieving the location."); break;
}
}
The error codes are accessed from the code attribute of the provided error object, while the message attribute will give access to a more detailed description of what went wrong. In all cases, we call our own routine to update the status of the page with the necessary info.
117
CHAPTER 5 USING THE GEOLOCATION API
Optional Geolocation Request Attributes
With both the normal and error cases handled, you should turn your attention to the three optional attributes that you can pass to the Geolocation service in order to fine-tune how it gathers its data. Note that these three attributes can be passed using shorthand object notation, making it trivial to add them to your Geolocation request calls.
•enableHighAccuracy—This is a hint to the browser that, if available, you would like the Geolocation service to use a higher accuracy-detection mode. This defaults to false, but when turned on, it may not cause any difference, or it may cause the machine to take more time or power to determine location. Use with caution.
Note Curiously, the high accuracy setting is only a toggle switch: true or false. The API was not created to allow the accuracy to be set to various values or a numeric range. Perhaps this will be addressed in future versions of the specification.
•timeout—This optional value, provided in milliseconds, tells the browser the maximum amount of time it is allowed to calculate the current location. If the calculation does not complete in this amount of time, the error handler is called instead. This value defaults to Infinity, or no limit.
•maximumAge—This value indicates how old a location value can be before the browser must attempt to recalculate. Again, it is a value in milliseconds. This value defaults to zero, meaning that the browser must attempt to recalculate a value immediately.
Note You might be wondering what the difference is between the timeout and maximumAge options. Although similarly named, they do have distinct uses. The timeout value deals with the duration needed to calculate the location value, while maximumAge refers to the frequency of the location calculation. If any single calculation takes longer than the timeout value, an error is triggered. However, if the browser does not have an up-to-date location value that is younger than maximumAge, it must refetch another value. Special values apply here: setting the maximumAge to “0” requires the value to always be re-fetched, while setting it to Infinity means it should never be refetched.
The Geolocation API does not allow you to tell the browser how often to recalculate the position. This is left entirely up to the browser implementation. All we can do is tell the browser what the maximumAge is of the value it returns. The actual frequency is a detail we cannot control.
Let’s update our location request to include an optional parameter using shorthand notation, as shown in the following example:
navigator.geolocation.getCurrentPosition(updateLocation,handleLocationError,
{timeout:10000});
118
CHAPTER 5 USING THE GEOLOCATION API
This new call ensures that any request for location that takes longer than 10 seconds (10,000 milliseconds) should trigger an error, in which case the handleLocationError function will be called with the TIMEOUT error code. We can combine the Geolocation calls that we discussed so far and display the relevant data on a page as shown in Figure 5-4.
Figure 5-4. Geolocation data displayed on a mobile device
Repeated Position Updates
Sometimes you have to make repeated position requests. Thankfully, the designers of the Geolocation API made it trivial to switch from an application that requests a user location one time to one that requests the location at regular intervals. In fact, it’s largely as trivial as switching the request call, as shown in the following examples:
•One-shot update: navigator.geolocation.getCurrentPosition(updateLocation, handleLocationError);
119