- •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 8 USING THE FORMS API
Once again, the choice here is yours. The HTML5 Forms API provides you with the flexibility to achieve a customized API or to fall back to default browser behavior.
Turning Off Validation
In spite of the power behind the validation API, there are… (ahem) valid reasons why you might want to turn off validation on a control or an entire form. The most common reason is that you might choose to submit the temporary contents of a form to be saved or retrieved for later, even if the contents aren’t quite valid yet.
Imagine the case of a user who is entering a complex order entry form, but needs to run an errand midway through the process. Ideally, you might present the user with a “save” button which stores the values of the form by submitting them to the server. However, if the form was only partially completed, validation rules might prevent the content from being submitted. The user would be very displeased if she had to complete or abandon the form due to an unexpected interruption.
To handle this, a form itself can be programmatically set with the attribute noValidate, which will cause it to forego any validation logic otherwise present and simply submit the form. Naturally, this attribute can be set either via script or original markup.
A more useful way to turn off validation is to set a formNoValidate attribute on a control such as a form submit button. Take the following submit button, set up as a “save” button, for example:
<input type="submit" formnovalidate name="save" value="Save current progress"> <input type="submit" name="process" value="Process order">
This snippet will create a two normal looking submit buttons. The second will submit the form, as usual. However, the first button is marked with the noValidate attribute, causing all validation to be bypassed when it is used. This allows the data to be submitted to the server without checking for correctness. Of course, your server will need to be set up to handle unvalidated data, but best practices dictate that this should be the case at all times.
Building an Application with HTML5 Forms
Now, let’s use the tools we’ve described in this chapter to create a simple signup page which showcases new features in HTML5 Forms. Turning back to our familiar Happy Trails Running Club, we’ll create a page for race registration that incorporates new form elements and validation.
As always, the source code for the demo files we show here is available in the code/forms folder. Therefore, we’ll spend less attention on the CSS and peripheral markup, and more on the core of the page itself. That being said, let’s start with a look at the finished page shown in Figure 8-4, then break it down into sections to tackle one-by-one.
209
CHAPTER 8 USING THE FORMS API
Figure 8-4. Example page with race signup form
This signup page demonstrates many of the elements and APIs we’ve explored in this chapter, including validation. Although the actual display may look somewhat different on your browser, it should degrade gracefully even if the browser does not support a particular feature.
On to the code!
The header, navigation, and footer have all been seen before on our previous examples. The page now contains a <form> element.
<form name="register">
<p><label for="runnername">Runner:</label>
<input id="runnername" name="runnername" type="text" placeholder="First and last name" required></p>
<p><label for="phone">Tel #:</label>
<input id="phone" name="phone" type="tel" placeholder="(xxx) xxx-xxx"></p>
<p><label for="emailaddress">E-mail:</label>
<input id="emailaddress" name="emailaddress" type="email" placeholder="For confirmation only"></p>
<p><label for="dob">DOB:</label>
<input id="dob" name="dob" type="date" placeholder="MM/DD/YYYY"></p>
210
CHAPTER 8 USING THE FORMS API
In this first section, we see the markup for the four primary inputs: name, phone, email, and birthday. For each, we’ve set a <label> with descriptive text and tied it to the actual control using the for attribute. We’ve also set placeholder text to show a description to the user of just what type of content belongs there.
For the runner name text field, we’ve made it a required value by setting the required attribute. This will cause form validation to kick in with a valueMissing constraint if nothing is entered. On the phone input, we’ve declared it to be of type tel. Your browser may or may not display this field differently or provide optimized keyboards.
Similarly, the e-mail field has been marked of type e-mail. Any specific handling is up to the browser. Some browsers will throw a typeMismatch constraint if they detect that the entered value is not a valid email.
Finally, the date-of-birth field is declared as type date. Not many browsers support this yet, but when they do, they will automatically render a date picking control on this input.
<fieldset>
<legend>T-shirt Size: </legend>
<p><input id="small" type="radio" name="tshirt" value="small"> <label for="small">Small</label></p>
<p><input id="medium" type="radio" name="tshirt" value="medium"> <label for="medium">Medium</label></p>
<p><input id="large" type="radio" name="tshirt" value="large"> <label for="large">Large</label></p>
<p><label for="style">Shirt style:</label>
<input id="style" name="style" type="text" list="stylelist" title="Years of participation"></p>
<datalist id="stylelist">
<option value="White" label="1st Year"> <option value="Gray" label="2nd - 4th Year">
<option value="Navy" label="Veteran (5+ Years)"> </datalist>
</fieldset>
In our next section, we set out the controls to be used to T-shirt selection. The first few controls are a standard set of radio buttons for selecting a shirt size.
The next section is more interesting. Here, we exercise the list attribute and its corresponding <datalist> element. In the <datalist>, we declare a set of types that should be displayed for this list with distinct values and labels, representing the types of T-shirts available based on veteran status.
Although this list is quite simple, the same technique can be used for lengthy lists of dynamic elements.
<fieldset>
<legend>Expectations:</legend>
<p>
<label for="confidence">Confidence:</label> <input id="confidence" name="level" type="range"
onchange="confidenceDisplay.value=(value +'%')" min="0" max="100" step="5" value="0">
<output id="confidenceDisplay">0%</output></p> <p><label for="notes">Notes:</label>
<textarea id="notes" name="notes" maxLength="140"></textarea></p> </fieldset>
In our final section of controls, we create a slider for the user to express his or her confidence in completing the race. For this, we use an input of type range. Since our confidence is measured in
211
CHAPTER 8 USING THE FORMS API
percentages, we set a minimum, a maximum, and step value on the input. These force a constraint within normal percentage ranges. Additionally, we constrain the movement of the value to 5% step increments, which you will be able to observe if your browser supports a range slider interface control. Although it should not be possible to trigger them through simple control interactions, there are possible validation constraints on this control for rangeUnderflow, rangeOverflow, and stepMismatch.
Because a range control does not show a textual representation of its value by default, we will add an <output> to our application for that purpose. The confidenceDisplay will be manipulated through the onchange handler of the range control, but we’ll see that in action in just a minute.
Finally, we add a <textarea> to contain any extra notes from the registrant. By setting a maxLength constraint on the notes control, we allow it to achieve a tooLong constraint, perhaps if a lengthy value is pasted into the field.
<p><input type="submit" name="register" value="Register"></p> </form>
We finish off our control section with a submit button that will send in our form registration. In this default example, the registration is not actually being sent to any server.
There are a few scripts we still need to describe: how we will override the browser’s built-in form validation feedback and how we will listen for events. Although you might find the browser’s default handling of form errors to be acceptable, it is always good to know your options.
<script type="text/javascript">
function invalidHandler(evt) {
// find the label for this form control
var label = evt.srcElement.parentElement.getElementsByTagName("label")[0];
//set the label's text color to red label.style.color = 'red';
//stop the event from propagating higher evt.stopPropagation();
//stop the browser's default handling of the validation error evt.preventDefault();
}
function loadDemo() {
//register an event handler on the form to
//handle all invalid control notifications document.register.addEventListener("invalid", invalidHandler, true);
}
window.addEventListener("load", loadDemo, false);
</script>
This script shows how we override the handling of validation errors. We start by registering event listeners for the special event type invalid. In order to capture invalid events on all form controls, we register the handler on the form itself, making sure to register for event capture so that events will arrive at our handler.
// register an event handler on the form to
212