Understanding HTML5 intelligent forms â&#x20AC;&#x201C; Part 1: New input elements Forms are everywhere on the web. They're essential for gathering information through surveys, feedback pages, blog comments, and shopping carts. Thanks to HTML5, online forms are about to get a whole lot better. HTML5 form features fall into two categories: dedicated input elements for data such as email addresses and numbers, and new attributes that allow you to specify whether an item is required, minimum and maximum values, and so on. The latest versions of browsers have already begun implementing many of these features. Once they're fully implemented, they'll eliminate the need to use JavaScript for client-side form validation (although you should still validate user input on the server for security reasons). And the good news is that you can start implementing these features right away, because they have been designed to be backwards compatible with HTML 4.01 and XHTML 1.0. Older browsers that don't recognize the new input elements simply treat them as ordinary text input fields. So, with one minor exception (therange input type), you can use HTML5 form features safely in all browsers. In this first part of a two-part tutorial, I'll describe the new input elements and the <datalist> element, which allows you to suggest options for a text input field. In Part 2, you'll learn about the HTML5 form attributes.
Specialized text input elements Figure 1 shows a simple online form that contains a text field, check box, radio (or option) buttons, file upload field, and a Submit button.
Figure 1. The HTML <input> tag has a wide range of uses.
The underlying HTML markup for this form looks like this (see also html4_input.html in the example files that accompany this tutorial): <form method="post" enctype="multipart/form-data" name="form1"> <p> <label for="name">Name:</label> <input type="text" name="name" id="name"> </p> <p>
<input type="checkbox" name="terms" id="terms"> <label for="terms">I have read the terms and conditions</label> </p> <p> <label> <input type="radio" name="gender" value="f" id="gender_0">
Female</label>
<br> <label> <input type="radio" name="gender" value="m" id="gender_1">Male</label> </p> <p> <label for="file">Upload file:</label> <input type="file" name="file" id="file"> </p> <p> <input type="submit" name="send" id="send" value="Submit"> </p> </form> The notable feature of this form is that every element uses the <input> tag. What changes the look and behavior of each element is its type attribute. So, instead of having a dedicated tag for check boxes, for example, and another for radio buttons, the same HTML tag is used for a variety of purposes. Of course, other tags, such as <select> and<textarea> are also used in forms, but the <input> tag is the most versatile. What's more, the default value of thetype attribute is text . So, if the attribute is missingâ&#x20AC;&#x201D;or the browser doesn't recognize itâ&#x20AC;&#x201D;the form displays a simple text field. HTML5 takes advantage of this default behavior to define no fewer than 13 new form elements by expanding the range of accepted values for the type attribute. Browsers that understand the new values handle form input according to the HTML5 specification. Older browsers simply display standard text fields. It's a win-win situation, meaning that you can start incorporating the new input types in your forms right now. Table 1 lists the specialized text input types, of which there are six. I'll deal later with the remaining types, which are dedicated to dates and time, and a number slider. Table 1. HTML5 specialized text input types
Type
Description
search
Search field
tel
Single-line text field for phone number
url
Single-line text field for URL
Single-line text field for one or more email addresses
number
Single-line text field or number stepper
color
Color picker
To add one of these new input types to a form, you simply create a text input field and change its type attribute in the HTML markup. Code hints in Dreamweaver CS5.5 support all HTML5 input types (see Figure 2).
Figure 2. Dreamweaver code hints support the HTML5 input types.
You can also change the type attribute by highlighting the <input> tag, and selecting the appropriate value from the pop-up menu in the General category of the Tag Inspector panel (Window > Tag Inspector), as shown in Figure 3.
Figure 3. The Dreamweaver Tag Inspector panel also supports the HTML5 input types.
A sample of each new input type listed in Table 1 is in html5_input.html in the example files that accompany this tutorial. The following sections describe each one briefly. Creating a search field Setting the type attribute of an <input> tag to search is mainly of cosmetic value. It doesn't automatically create a search field. As with all form elements, you still need to code the server-side logic yourself or use a third-party script. Most browsers simply display a search field as a normal text field. However, Safari and Chrome on Mac OS X automatically add rounded corners to match the operating system's standard look (see Figure 4).
Figure 4. WebKit browsers automatically style search fields on Mac OS X.
Creating a dedicated field for phone numbers There's no internationally agreed format for telephone numbers, so setting the type attribute to tel doesn't appear all that usefulâ&#x20AC;&#x201D;until you test it on a smartphone or tablet, that is. As Figure 5 shows, tapping a tel input field on an iPod touch, iPhone, or similar device brings up the phone keypad. This not only makes it a lot easier to enter the phone number, but it also prevents invalid characters from being entered on a mobile device.
Figure 5. Using a dedicated phone field is more user-friendly on a mobile device.
Desktop browsers currently don't treat tel input fields differently from ordinary text fields. However, if you want to enforce a particular format for a telephone number, you can use the pattern attribute, which you'll learn about in Part 2 of this two-part tutorial. Creating a URL input field Setting the type attribute to url also brings up the appropriate keypad on modern mobile devices. The most recent versions of desktop browsers, apart from Internet Explorer (IE) 9 and Safari 5.1, automatically validate the user input when the form is submitted. However, in Firefox 5, Chrome 13, and IE 10 Preview 2 the validation is stricter than you might expect. As Figure 6 shows, "www.adobe.com" is rejected as not being a valid URL.
Figure 6. Chrome 13 rejects a URL without the leading http://.
Firefox 5, Chrome 13, and IE 10 Preview 2 all insist on a fully qualified URL beginning with http://. On the other hand, Opera 11.50 automatically inserts the http:// for you if it has been omitted. However, Opera doesn't
perform any other validation. For example, if you enter "adobe" in the field, it simply converts it to "http://adobe" and submits it, even though it's not the correct format for a URL. Clearly, there's some way to go before browsers handle URL fields in a consistent, user-friendly way. Creating an email input field Support for the email input type is similar to that for URLs. If you set the type attribute to email, mobile devices display the appropriate keypad when the user taps the field. On a desktop computer, Firefox 5, Chrome 13, IE 10 Preview 2, and Opera 11.50 prevent the form from being submitted if the input contains illegal characters or doesn't include an @mark. A really useful feature of the email input type is that it prevents users from attempting to stuff the field with multiple email addresses. Only a single address is permitted unless you also set the multiple attribute on the <input> tag like this: <input type="email" name="email" id="email" multiple> Creating a number field Setting the type attribute to number creates a field intended for numerical input. On iOS, tapping the field displays a numeric keypad, but you can also switch to alphabetic input. On Android, however, the keypad permits only numbers and a limited range of punctuation characters. The latest versions of all mainstream desktop browsers, except IE and Firefox 5, display a number spin box similar to Figure 7. Clicking the up arrow to the right of the box increases the number in the field. Clicking the down arrow reduces the number.
Figure 7. Number spin boxes make it easier to enter numeric values.
Currently, browsers don't check whether the submitted value is actually a number, so a user could type "ten" in the field, and the form would be submitted without problem. However, you can enforce the use of a number with the patternattribute (see Part 2). Adding a color picker Currently, the only browser that supports the color type is Opera. It displays a color box, which expands to display a set of common color swatches (see Figure 8).
Figure 8. Opera displays a color picker when type is set to color.
Clicking the Other button below the swatches opens a full color picker that lets you select and store custom colors. The selected color is transmitted as a hexadecimal color value when the form is submitted. What happens in older browsers As mentioned earlier, the new HTML5 input elements have been designed to be backward compatible. So, if an olderâ&#x20AC;&#x201D;or even relatively modernâ&#x20AC;&#x201D;browser doesn't recognize the new type attributes, it simply displays an ordinary text field. Figure 9 shows html5_input.html in IE 9.
Figure 9. IE 9 displays the new input types as ordinary text fields.
The form remains perfectly usable in IE 9 and older browsers even though they have no support for HTML5 form elements.
Date- and time-related input Six of the new input types are dedicated to date- and time-related values. Support for these input fields is still patchy. Currently, iOS, Android, Firefox 5, and IE 10 Preview 2 display ordinary text input fields. Chrome and Safari treat them like number spin boxes, increasing and decreasing the value depending on whether you click the up or down arrow. Opera and BlackBerry offer the most user-friendly support with calendar pop-ups. Figure 10 shows what happens when you put the focus in a date field in Opera 11.50. It displays a navigable calendar that defaults to the current date.
Figure 10. Opera makes it easy to insert dates from a pop-up calendar.
The latest versions of BlackBerry devices offer a similar experience. Figure 11 shows what happens when you tap a date field in a BlackBerry PlayBook.
Figure 11. The BlackBerry PlayBook displays a set of rolling barrels to choose the date.
In spite of their user-friendly date pickers, what comes as a surprise is the format of the date they enter into the form field. The date shown in Figure 11 is inserted as 2011-08-03â&#x20AC;&#x201D;in other words, in the order year, month, and date. This is not an arbitrary decision, but is the format mandated by the World Wide Web Commission (W3C), which is responsible for drawing up the HTML5 specification. The YYYY-MM-DD format has been chosen because it's the way the International Organization for Standardization (ISO) recommends that dates should be presented. Table 2 shows all date- and time-related input types in the HTML5 specification together with the required format. Table 2. HTML5 date- and time-related input types
Type
Format
Description
date
YYYY-MM-DD
Year (4 digits), month (2 digits), and date (2 digits), each value separated by hyphens.
datetime
YYYY-MM-DDTHH:MMZ YYYY-MM-DDTHH:MM-07:00
UTC (Universal Coordinated Time) date and time. The date is expressed in the same format as date , followed by the letter T and the time in the 24-hour clock, optionally with the local offset from UTC. A zero offset is represented by the letter Z. The second example on the left shows the offset for Pacific Daylight Time (7 hours behind UTC).
datetimelocal
YYYY-MM-DDTHH:MM
The date and local time expressed in the same format as datetime , but without a UTC offset.
month
YYYY-MM
The year (4 digits) and month (2 digits separated by a hyphen.
week
YYYY-W00
The year (4 digits) followed by a hyphen, the letter W, and the week number (2 digits).
time
HH:MM orHH:MM:SS.0000
Time expressed in the 24-hour clock with optional seconds and milliseconds. Hours, minutes, and seconds are separated by colons.
The W3C's choice of formats is intended to solve the vexed problem of differing date formats around the world. They work fine in a technical environment, butâ&#x20AC;&#x201D;with the exception of the time input typeâ&#x20AC;&#x201D;are likely to confuse nontechnical users. Figure 12 shows actual examples of the official formats as rendered by Chrome 13.
Figure 12. The official date formats are likely to confuse many people.
Local customs regarding date formats are so deeply ingrained that I think the HTML5 date-related input types will find little practical application unless the specification is amended to permit alternative formats. Another possibility is that browsers could offer the option to display the date in a local format, but use the official format when the form is submitted. In the meantime, I think the best approach is to provide separate text input fields or <select> menus for the month, date, and year. Alternatively, use a single text input field with a configurable JavaScript widget, such as the jQuery UI Datepicker. In Part 2 of this tutorial, I'll also show you how to use the pattern attribute with a text input field to enforce a specific date format in HTML5-compliant browsers.
Creating a slider input The final new type attribute for the <input> tag is range , which creates a slider that allows the user to select a numeric value. Currently, this input type is supported by iOS, Safari, Chrome, and Opera. With the exception of Android, other browsers display an ordinary text input field. Unfortunately, in my experiments, Android completely ignores therange type, severely limiting its usefulness. However, it's an interesting input type, so I'll describe it in full.
According to the specification, the range input type is intended to be used when the exact value is not important. The reason for this becomes clear when you see a default slider in an HTML5-compliant browser. Figure 13 shows a slider in Opera (you can test it yourself in slider.html in the example files).
Figure 13. The range input type is normally displayed as a slider.
Although Opera displays a scale below the slider, other browsers don't, and there's no indication of the selected value. By default, the range type allows the user to select a value between 0 and 100, and is initially set to the halfway pointâ&#x20AC;&#x201D;in other words, 50. Moving the slider in either direction increases or decreases the selected value in steps of 1. On its own, the range input type is a very crude tool. However, with a little extra code, it becomes much more versatile. By setting the min, max, and step attributes, you can change the default range and incremental value (only whole numbers can be used). For example, the following HTML markup sets a range of 0â&#x20AC;&#x201C;25 in steps of 5 (0, 5, 10, and so on): <input type="range" name="rating" id="rating" min="0" max="25" step="5"> To set the initial value to zero, just add the value attribute like this: <input type="range" name="rating" id="rating" min="0" max="25" step="5" value="0"> As Figure 14 shows, the slider is automatically set to the far left of the track, and Opera adjusts the scale to indicate the new range of selectable values (the code is in slider2.html in the example files).
Figure 14. Explicitly setting the value changes the initial position of the slider.
Even though Chrome and Safari don't display a scale, if you test slider2.html in either of those browsers, you'll see that the slider stops only at positions roughly equivalent to 0, 5, 10, and so on. Still, it would be much better to show users what value they have selected. You can do so with the HTML5 <output> tag and some very simple JavaScript, as described in the next section. Displaying the slider's value The following instructions show how to display the value selected by an HTML5 range input element. 1. Open slider2.html in the example files. The HTML markup for the form looks like this: <form method="post" name="form1"> <p> <label for="rating">Rating:</label> <input type="range" name="rating" id="rating" min="0" max="25" step="5" value="0"> </p> </form>
2. In Code view, position the insertion point immediately after the <input> tag and add an opening and closing pair of<output> tags like this (if you're using Dreamweaver CS5.5, code hints will autocomplete the tags): <input type="range" name="rating" id="rating" min="0" max="25" step="5" value="0"><output></output> 3. In the opening <output> tag, give the element a unique name, such as display_rate: <output name="display_rate"></output> 4. Link the <output> and <input> elements using the for attribute and setting its value to the <input>element's ID like this: <output name="display_rate" for="rating"></output> 5. To display the value selected by the slider, you need to add an onchange handler to the slider. Add the following code inside the <input> tag: onchange="display_rate.value=this.value" In JavaScript, this represents the target of the current event. So, whenever the slider is moved, this.value contains the slider's selected value. Because the name of the <output> element is display_rate, this code sets the value of the <output> element to the same value as the slider. The complete code for the <input> and <output> elements should now look like this (the code is also in slider_output.html in the example files): <input type="range" name="rating" id="rating" min="0" max="25" step="5" value="0" onchange="display_rate.value=this.value"><output name="display_rate" for="rating"></output> 6. Save the page, and load it into a browser that supports the range input type (currently Chrome, Safari, or Opera). The <output> element doesn't have an initial value, so the slider should look the same as Figure 14. 7. Move the slider. The selected value should appear alongside, as shown in Figure 15.
Figure 15. The value of the <output> element updates when the slider is moved.
Note: According to the HTML5 specification, the default value of an <output> element must initially be an empty stringâ&#x20AC;&#x201D;in other words, nothing. To change the default, you need to use JavaScript to set the element's defaultValueproperty when the page loads. This is currently supported only by Chrome and Safari. In practice, current browsers allow you to set the initial value by inserting a number between the opening and closing <output> tags. The number updates automatically when the slider is moved. However, this has the unfortunate side effect of displaying an unchanging value alongside the text field of the range input element.
Using a datalist to display options for text input A really useful addition to HTML5 forms is the <datalist> element, which is currently supported only by Opera. It associates a set of predefined options with a text input field, allowing you to create an editable <select> menu. Figure 16 shows a simple example of a datalist in Opera.
Figure 16. A datalist offers suggestions for a text input field.
When the focus is in the text field, the datalist displays a set of options for the user to choose from. If one is selected, it's entered in the field. However, the user is free to enter a completely different value. For example, Princess Leia could type "Princess" in the Title field rather than settling for plain Ms. The HTML markup for a datalist is very simple. The example shown in Figure 16 looks like this (it's also in datalist.html in the example files): <input type="text" name="title" id="title" list="titlelist"> <datalist id="titlelist"> <option value="Mr."> <option value="Mrs."> <option value="Ms."> </datalist> You associate a text input field with a datalist by adding the list attribute to the <input> tag and setting its value to the ID of the <datalist> elementâ&#x20AC;&#x201D;in this case, titlelist. The <datalist> element serves as a wrapper for a set of <option> tags, which you probably recognize from<select> menus. An important difference is that a datalist requires the value attribute to be present in the<option> tag. Unlike a <select> menu, <datalist> won't display values nested between opening and closing tags. For example, the following won't work in a <datalist>: <option>Mr.</option> It must be like this: <option value="Mr."> Although the <datalist> element isn't yet widely supported, you can safely use it in existing forms. Browsers that don't recognize it simply display the ordinary text input field. But as soon as browser support catches up, visitors to your sites benefit from the list of suggested options.
Understanding HTML5 intelligent forms â&#x20AC;&#x201C; Part 2: New form attributes Validating user input in online forms needs to be done in two placesâ&#x20AC;&#x201D;in the browser to prevent the form from being submitted with insufficient or invalid data, and on the server to filter out potential attacks. You'll still need to write your own server-side processing script or use a third-party one, but HTML5 is assuming most of the burden of validating user input before submitting it to the server. In Part 1 of this two-part tutorial series, I described the specialized input types for such values such as phone numbers, email addresses, and dates. In this second part, you'll learn about new form attributes that allow you to specify required fields, minimum and maximum values, and so on. You'll also learn how to ensure that ZIP codes, phone numbers, and similar values conform to a set format.
Using the example files To demonstrate how various HTML5 attributes work, the files in html5_forms_pt2.zip contain simple forms, such as this one in on-off_01.html: <form method="post" name="form1"> <p> <label for="name">Name:</label> <input type="text" name="name" id="name"> </p> <p> <label for="website">Website:</label> <input type="url" name="website" id="website"> </p> <p> <label for="email">Email:</label> <input type="email" name="email" id="email"> </p> <p> <input type="submit" name="send" id="send" value="Submit"> </p> </form> The type attribute of the first <input> tag uses the default text value, which creates an ordinary text input field. The second and third fields use the new url and email types. Figure 1 shows what the form looks like in a browser.
Figure 1. The form contains three text input fields.
As explained in Part 1, older browsers that don't understand HTML5 form elements treat them as ordinary text input fields. Modern HTML5-compliant browsers check that the data matches the specified type before allowing the form to be submitted. Use the example files in a variety of browsers to see the level of support they offer. The forms don't send the data anywhere. Processing form data is a huge subject beyond the scope of this tutorial, but clicking the submit button simulates what happens when a form is submitted. If the input fields clear, it indicates that the data was submitted successfully. If the data is invalid, modern browsers display an error message, preventing the form from being submitted until the error is corrected.
Attributes that turn features on/off HTML5 defines several Boolean attributes—ones that represent true or false—for forms, namely: autofocus required multiple formnovalidate novalidate Adding one of these attributes to a tag turns the feature on. Leaving it out (or removing it programmatically) turns the feature off. Closely related to these Boolean attributes is autocomplete , which is on by default. To turn it off, you need to add it to a tag and explicitly set its value. • • • • •
Automatically setting the focus in a field As a courtesy to the user, it's a good idea to set the focus in the first field for many forms. Previously, the only way to do this has been with JavaScript. With HTML5, just add the autofocus attribute to the <input> tag like this (on-off_02.html): <input type="text" name="name" id="name" autofocus> If you load the page into a modern browser, the cursor is automatically inserted in the field. Most browsers also highlight the field to draw the user's attention, as shown in Figure 2.
Figure 2. Autofocus automatically puts the cursor in the field when the page loads.
Only one field can have focus at any given time, so you should use autofocus only once in a form. It works well for login forms and pages that are solely dedicated to filling in a form. But you probably shouldn't use it for a search field that's incidental to the main content. Note: If you're using XHTML-style markup, you need to set the value of autofocus and other Boolean attributes to the same value as the attribute name like this: autofocus="autofocus" . Making fields required Making fields required is just as easy. Simply add the required attribute to the <input> tag like this: <input type="text" name="name" id="name" autofocus required> If you attempt to submit the form without entering a value into the field, browsers that recognize the required attribute will prevent you from doing so, as Figure 3 shows (you can test it in on-off_03.html).
Figure 3. Chrome prevents the form from being submitted when a required field is empty.
input[required] { background-color: #E5F5EF; } In on-off_04.html, the required attribute has been added to the name and email fields producing the result shown in Figure 4.
Figure 4. Using a CSS attribute selector for required fields provides an extra visual clue.
All browsers except Internet Explorer (IE) 6 support attribute selectors. If you still need to support IE 6, you can hide the paragraph at the top of the form in IE 6 using a class and an IE conditional comment setting the class's display property to none like this: <!--[if IE 6]> <style> .notie6 { display: none; } </style> <![endif]--> Load on-off_04.html into different browsers, and try submitting the form without entering a value. Among modern browsers, IE 9 and Safari 5.1 are the only ones that submit the required fields without validation. Chrome and Opera check only the first invalid field. However, Firefox 5 and IE 10 Preview 2 not only display an error message for the first field, but also outline both invalid fields in red (see Figure 5).
Figure 5. Firefox also outlines other invalid fields in red.
Allowing multiple values The multiple attribute isn't new to HTML5, but its role has been expanded. Previously, its use was restricted to<select> elements, allowing you to convert a drop-down menu into a multiple-selection list. In HTML5, you can use it with other form fields to permit the submission of multiple values where normally only one would be accepted. In practice, this means with file upload and email fields. The multiple attribute on file upload fields has been supported since Firefox 3.6, Safari 4, Chrome 4, and Opera 10. It's also supported by IE 10 Preview 2. Testing support for file upload fields requires a server-side technology, such as PHP or ColdFusion, which is beyond the scope of this tutorial. However, you can easily test email fields. 1. Load on-off_05.html into the latest version of Firefox, Chrome, or Opera. (Safari 5.1 and IE 9 don't support the emailinput type). 2. Enter two email addresses separated by a comma in the Email field, and click Submit. You should see an error message similar to Figure 6. The error message would be more helpful if it explained that multiple addresses are not permitted, but the form won't be submitted until you enter only a single address.
Figure 6. Browsers the support the email input type reject multiple addresses.
3. Edit the HTML markup to add the multiple attribute to the <input> tag like this (or use on-off_06.html): <input type="email" name="email" id="email" autofocus multiple> 4. Save the page and reload it in your browser. Then enter two email addresses separated by a comma. 5. When you click submit, what happens depends on the browser and the exact format that you used. If there was no space between the comma and the addresses, all three browsers should accept the addresses. If there was a space between the comma and the addresses, Firefox and Opera accept the addresses, but Chrome 13 displays the error message shown in Figure 7.
Figure 7. Chrome displays a confusing error message if there's a space after the comma.
This is likely to confuse many users because it fails to explain that the problem is the space after the comma. 6. Remove the space after the comma, and Chrome should now accept the multiple addresses. 7. Try using a semicolon between the email addresses. This time the Chrome error message makes sense, because it tells you about the need to use a comma as the separator. The error messages in Firefox and Opera are less helpful, because they simply tell you to enter a (valid) email address. IE 10 Preview 2 behaves the same way as Firefox and Opera in that it accepts a space after the comma and rejects any other separator without explaining why. Although the error messages with multiple email fields can be confusing, the main advantage of the HTML5 email input type is the way it rejects the submission of multiple addresses unless you specifically add the multiple attribute to the<input> tag. This is a safeguard against casual spammers. Unfortunately, it's very easy for the determined spammer to get around this restriction, so you still need to validate user data on the server. Turning off autocompletion Most browsers try to help users by suggesting values that have previously been entered in the same form or in fields with common names, such as address or email. For example, Safari displays a list of recent values entered in an email field, (see as Figure 8) shows.
Figure 8. Autocompletion helps speed up filling out a form.
Most of the time, this behavior is welcome, but allowing the browser to autocomplete certain fields, such as username, password, or credit card number can be insecure. HTML5 gives you control with the autocomplete attribute, which can be applied to a whole form or to individual input elements. By default, autocomplete is turned on, so you don't need to do anything if you're happy for the browser to make suggestions. To turn off autocompletion for an entire form, add autocomplete="off" to the opening <form> tag. To turn off autocompletion for an individual element, add autocomplete="off" to the element's tag. For example, the email field in on-off_07.html looks like this:
<input type="email" name="email" id="email" autofocus autocomplete="off"> This turns off autocompletion for the email field, but leaves the default behavior for other fields. Note: In my experiments, adding autocomplete="off" to an opening form tag is one ring to rule them all. You cannot override it for an individual element by adding autocomplete="on" to the element's tag. Turning off automatic validation Validating user input is important, so why would you want to turn off HTML5's automatic validation? There are several reasons: •
Many of your site's visitors still use old browsers, and you want to apply your own custom validation to everyone.
•
You want to provide an option for users to save a draft before submitting the form.
•
You want to test your server-side validation without the browser validation preventing the form from being submitted.
Whatever your reason for wanting to turn off automatic validation, there are two ways to do so: Add the novalidate attribute to the opening <form> tag. Add the formnovalidate attribute to the submit button's tag. Why two different attributes? Using novalidate in the opening <form> tag is basically a catch-all way of preventing the form from being validated when it's submitted. The formnovalidate attribute gives you a finer degree of control because it applies only when that particular button is clicked. For example, you could have separate buttons to save a draft and to submit the data like this: <input type="submit" name="draft" id="draft" value="Save Draft" formnovalidate> • •
<input type="submit" name="send" id="send" value="Submit"> You can test this in on-off_08.html. Leave one of the required fields empty, and click the Save Draft button. The other fields clear, because automatic validation is skipped (it's a dummy form, so no data is actually saved). Try it again with the Submit button. This time, the browser does the normal validation checks and reports that the required field needs to be filled in.
Setting min and max values In HTML 4.01 and XHTML 1.0, the maxlength attribute sets the maximum number of characters permitted in a text or password field. HTML5 extends its use to the following new input types: • search • tel • email • url Setting the maximum number of characters in a text area More significantly, perhaps, you can now also use maxlength to limit the number of characters in a <textarea>element. Currently, this is supported by the latest versions of Firefox, Chrome, and Safari. Once the limit is reached, the browser stops any further characters from being entered. You can test this in textareamaxlength.html, which limits the number of permitted characters to 50 like this: <textarea name="comments" id="comments" maxlength="50"></textarea> Note also that the <textarea> tag no longer requires the rows and columns attributes. Use CSS to set the text area's width and height.
Setting minimum and maximum values for numeric fields When using the HTML5 number and range input types, you can specify the minimum and maximum acceptable values with the min and max attributes. You can also specify the size of the increment between values using the step attribute. The values for min , max , and step must be numbers (integers or floating-point). The markup in min-max_01.html sets the permitted range of values to 1â&#x20AC;&#x201C;4 like this: <input type="number" name="tickets" id="tickets" min="1" max="4"> The step attribute is omitted, so the default value of 1 is used. If you load the page into a browser that supports thenumber type (currently Safari, Chrome, or Opera), clicking the up and down arrows on the right of the input field displays only whole numbers between 1 and 4. You can type an out-of-range number directly into the field, but you get an error message as shown in Figure 9 when you click the submit button.
Figure 9. The browser prevents an out-of-range number from being submitted.
You need to be careful when using a floating-point number for step because of rounding errors caused by floating-point values. Opera automatically adjusts the value to the same number of decimal places as step , but Safari and Chrome use the raw number generated by the computer. To demonstrate the difference, minmax_02.html contains two sliders designed to generate a value between 0 and 1 in increments of 0.1. The HTML markup looks like this: like this: <p> <label for="opacity">Opacity:</label> <input type="range" name="opacity" id="opacity" min="0" max="1" step="0.1" value="0" onchange="display_rate.value=this.value"> <output name="display_rate" for="opacity"></output> </p> <p> <label for="opacity2">Opacity (rounded):</label> <input type="range" name="opacity2" id="opacity2" min="0" max="1" step="0.1" value="0" onchange="display_rate2.value=parseFloat(this.value).toFixed(1)"> <output name="display_rate2" for="opacity2"></output> </p> Figure 10 shows what happens when both sliders are set to 0.3 in Safari.
Figure 10. Safari and Chrome don't fix rounding errors with a floating-point increment.
Strictly speaking, the rounding error is not a problem because the HTML5 specification says the range input type is intended for situations where a precise value is not important. However, if you need to display the value onscreen, you need to use the JavaScript parseFloat() method to convert it to a number, and then set the number of decimal places with toFixed() . The onchange handler in the second slider rounds the selected value like this: display_rate2.value=parseFloat(this.value).toFixed(1) Note: See Part 1 of this tutorial series for an explanation of the code used to display the output of an HTML5 slider. Setting minimum and maximum ranges for dates and times The min , max , and step attributes can also be used to set a permitted range of dates or times. However, the HTML5 date- and time-related input types accept only values that conform to formats that are more suited to a technical environment (see Table 2 in Part 1 of this tutorial). The code in min-max_03.html limits the range of dates to between January 1, 2011 and December 31, 2015 like this: <input type="date" name="date" id="date" min="2011-01-01" max="2015-12-31" step="10"> The value of step has been set to 10, which further limits the choice of dates to every tenth day. In Safari and Chrome, clicking the up arrow inserts tomorrow's date (or the upper limit if the range has been exceeded). Clicking the down arrow inserts the date from 10 days ago. If you keep clicking, the date increases in steps of 10 days until you reach the end of the range. In Opera, the calendar opens with dates in 10-day increments calculated from tomorrow's date highlighted in bold type. You can use the calendar's navigation arrows to move to different months or years within the specified range, but only highlighted dates can be selected (see Figure 11).
Figure 11. Only dates at the specified interval can be selected.
The value of step affects only the smallest unit. In the case of date , the increment is calculated in days. You cannot setdate to increment one month at a time. When used with time-related input elements, specifiying a value for step forces the field to display seconds as well as hours and minutes. The step attribute can also be set to the case-insensitive keyword any . In Safari and Chrome, usingstep="any" in a time input element sets the current time to the closest millisecond. Figure 12 shows the output in Chrome of the following time input elements after clicking the down arrow of each field in turn (the code is in min-max_04.html): <p> <label for="time">Time:</label> <input type="time" name="time" id="time"> </p> <p> <label for="time10">Step="10":</label> <input type="time" name="time10" id="time10" step="10"> </p> <p> <label for="any">Step="any":</label> <input type="time" name="any" id="any" step="any"> </p>
Figure 12. The step attribute controls the precision of time input elements.
The first time element doesn't use step , so it displays only hours and minutes. Clicking the up or down arrow increases or decreases the value one minute at a time. In the second one, step is set to 10, so it displays hours, minutes, and seconds, which can be adjusted in increments of ten seconds. The final field uses step="any" , which inserts the current time to the closest millisecond. Clicking the up or down arrow has no effect. The value is fixed. Instead of inserting the current time, Opera defaults to 12:00. Setting step to a numeric value displays seconds in the same way as Safari and Chrome, but step="any" has no effect; Opera displays only hours and minutes.
Displaying hints to the user Many online forms help users by displaying hints inside text fields, usually in light gray. When the field has focus, the hint disappears. Previously, you needed to code everything in JavaScript. Not any more. With HTML5, you just add theplaceholder attribute to the <input> tag and set its value to whatever you want to appear as the hint. Figure 13 shows the output of the following code in placeholder.html: <p> <label for="zip">Zip Code:</label> <input type="text" name="zip" id="zip" placeholder="5 digits"> </p> <p> <label for="arrival">Arrival Date:</label> <input type="text" name="arrival" id="arrival" placeholder="MM/DD/YYYY"> </p>
Figure 13. The placeholder attribute displays hints in text fields.
All browsers except IE support placeholderâ&#x20AC;&#x201D;and it's coming in IE 10.
Specifying custom formats Displaying hints is all very fine, but it's not much use unless you can check whether the user has entered the data in the correct format. Thanks to the pattern attribute, you can. The only snag is that the pattern needs to be a regular expression (regex). Building regular expressions isn't easy, but it's a vital skill for working with many web-related languages. You can learn more about regexes in my two-part tutorial Using regular expressions. There are also online repositories, such as the one at http://regexlib.com, where you can find regular expressions that have been tried and tested by others. When using the pattern attribute, the following restrictions apply: •
The input must match the regex completely. Partial matches are not allowed.
•
The ^ and $ anchors for the beginning and end of the pattern are automatically implied.
•
The regex should not be enclosed in delimiters, such as forward slashes.
You cannot use modifiers, such as i to perform a case-insensitive match. The HTML5 specification also recommends including a description of the regex in the title attribute. Browsers use this as part of the error message if the input fails validation. The code in pattern.html includes regular expressions for a five-digit zip code and a date formatted as MM/DD/YYYY : <p> •
<label for="zip">Zip Code:</label> <input type="text" name="zip" id="zip" placeholder="5 digits" pattern="\d{5}" title="The zip code should consist of five numbers only"> </p> <p> <label for="arrival">Arrival Date:</label> <input type="text" name="arrival" id="arrival" placeholder="MM/DD/YYYY" pattern="(0[1-9]|1[0-2])\/(0[19]|[12][0-9]|3[01])\/\d{4}" title="The date should be in the format MM/DD/YYYY with leading zeros where necessary"> </p> Figure 14 shows what happens when Santa Claus enters his arrival date using the European DD/MM/YYYY format (after all, he comes from Lappland).
Figure 14. The title is used by the browser as part of the error message.
Note: A regex only matches a pattern. It doesn't check whether a date is valid. Nor can it distinguish between American- and European-style dates when both month and date are less than 12. For example, 07/04/2011 could mean either July 4 to an American or 7 April to a European, but it would still be accepted by the regex. The regex for DD/MM/YYYY looks like this: (0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4} The pattern attribute is supported by the latest versions of all browsers, except Safari 5.1 and IE 9 (but it's supported by IE 10 Preview 2).
Overriding a form's default behavior Earlier, I demonstrated the use of formnovalidate to turn off automatic validation when a particular Submit button is clicked. Closely related to this attribute are four others, which override the form's defaults: • formaction overrides the action attribute • formenctype overrides the enctype attribute • formmethod overrides the method attribute • formtarget overrides the target attribute Adding these attributes to a submit button causes the button to override the value of the equivalent attribute in the opening <form> tag—or the default value if it's not defined in the opening tag. For example, if the method attribute in the opening <form> tag is set to post , you can use formmethod="get" to override it when a specific button is clicked. To demonstrate how this works, the form in overrides.html looks like this: <form action="submit.html" method="post" name="form1"> <!-- input fields omitted --> <p> <input type="submit" name="draft" id="draft" value="Save Draft" formnovalidate formaction="draft.html"> <input type="submit" name="send" id="send" value="Submit" formmethod="get"> </p> </form> The default settings in the opening <form> tag send the data to submit.html by the post method for processing. However, the form has two submit buttons. • If you click Save Draft, the formnovalidate attribute turns off validation and the formaction attribute diverts the data to draft.html for processing. The <input> tag contains no other overrides, so the form is submitted by thepost method, as specified in the opening <form> tag. • On the other hand, the second button uses the formmethod attribute to override the post method and resets it toget . The <input> tag contains no other overrides, so the form is validated before being sent to the default submit.html for processing. You can see the principle behind how this works by loading overrides.html into the latest version of Chrome, Firefox, Opera, or Safari. Clicking the buttons shows the different ways the form reacts by taking you to dummy processing pages. 1. Click Save Draft without entering any values into the text input fields. You should be taken directly to draft.html. 2. Check the URL in the address bar. There's no query string attached to it. The form data has been sent by the postmethod. (Even when all fields are empty, the form still submits their names and name of the submit button.) 3. Click the browser Back button to return to overrides.html.
4. This time, click Submit without entering any values. The form is not submitted and you're warned about the required fields. 5. Enter values in the Name and Email fields, and click Submit. This time you're taken to submit.html. 6. Check the browser address bar. The data you entered in the form has been submitted by the get method, and is attached to the URL as a query string (see Figure 15).
Figure 15. The form redirects to the default page, but the data is attached to the URL.
The ability to override the default form behaviors is an extremely powerful addition to HTML5. Unfortunately, it's not supported by Internet Explorer until IE 10. This means, in effect, that you won't be able to use these overrides for many years unless you're designing a form for an intranet where you know that everyone will be using a compliant browser. Shame, really.
Anything else? In HTML 4.01 and XHTML 1.0, all form elements must be nested inside the opening and closing <form> tags. However, in HTML5 you can put a form element anywhere you like and associate it with a form using the new form attribute and setting it to the form's ID. For example, this is perfectly legitimate in HTML5: <form action="submit.html" method="post" name="form1"> <!-- input fields omitted --> <p> <input type="submit" name="draft" id="draft" value="Save Draft" formnovalidate formaction="draft.html"> <input type="submit" name="send" id="send" value="Submit" formmethod="get"> </p> </form> The problem, as always, is lack of support. Until the form attribute is supported by all browsers in current use, you need to keep all form elements nested within the <form> tags. Another important HTML5 form attribute is list , which associates a <datalist> element with an <input> field. This was described in Part 1 of this tutorial series. One minor change is that you can now use the height and width attributes on an <input> element that uses an image as a button ( type="image" ).
Where to go from here If you have managed to survive this far, you'll realize that HTML5 introduces many new features designed to make online forms more intelligent. Unfortunately, the date- and time-related input elements aren't very userfriendly. Neverthless, the prospect of creating self-validating forms is appealing. The big question is when can you start using these new features. My personal view is that you canâ&#x20AC;&#x201D;and shouldâ&#x20AC;&#x201D;start using them now, with the exception of the form , formaction ,formenctype , formmethod , and formtarget attributes. The only proviso is that you should turn off JavaScript validation. Of course, this means older browsers won't validate your forms before submitting them to the server; but validation still needs to be done on the server to stop spam and other attacks, as well as to eliminate user error. So, any problems will still be caught there. Adopting the HTML5 features will provide a better user experience for visitors using newer browsers without affecting the form's functionality in older ones.