Working with HTML5 Web Forms: Handling Dates and Other Input Types
Let the browser do the work of supporting rich data entry in web applications
December 4, 2012
RELATED: "HTML5 Tutorial: Build a Chart with JavaScript and the HTML5 Canvas" and "HTML5 Is in Style: Working with CSS3 and HTML5"
For web developers, HTML5 is a quantum leap in terms of programmability, in part because of the new input types it provides. The downside of using these new input types is browsers' inconsistent support for them: The latest browsers do not support the input types in a uniform manner, and older browsers don't support the HTML5 input types at all. Thus, working with HTML5 forces developers to confront the pesky issue of accommodating diverse browser versions in web applications.
Here we will take a closer look at the input types that HTML5 introduces as well as how to deal with the issue of cross-browser support in your applications. I'll demonstrate how to use the popular JavaScript Modernizr library to check a user's browser capabilities and adjust markup and styles, so that you can ensure that the same core behavior is maintained on non-HTML5–compliant browsers as well as browsers that fully support HTML5.
HTML5 to the Rescue
Many types of data that users enter in an HTML form can be expressed as plain text strings; but they aren't actually plain strings. An architect following good software design principles will look skeptically upon any class members defined through a primitive type, whether string, number, or Boolean. More often than not, a primitive type leads to a loss of information or to performing work with specific data using inappropriate tools.
Prior to version 5, HTML only offered one input field that could accept only plain text:
<input type="text" />
In a perfect world, this input field would be used to accept limited types of plain text -- for example, a comment or a description. Using the field to contain the input of a person's or city's name introduces noise; even more noise is introduced when using the text input field to accept a URL, an email address or, worst of all, a date. URLs, email addresses, and dates are specific types of their own and deserve at minimum ad hoc input widgets and validation tools.
Before the HTML5 bandwagon arrived, the jQuery UI library was the de facto standard for date pickers. It provides a JavaScript-based visual component that pops up and lets the user select a date by navigating in a calendar. Using the jQuery UI date picker requires a bit of script code for each and every occurrence of the input field. This task isn't a big deal, but it is extra work all the same.
The HTML5 standard pushes the idea that it's the browser -- not the developer -- that takes care of specialized input fields. And the HTML5 standard recognizes several new input types and suggests browsers to provide an ad hoc widget for it. If your page could fully leverage the power of new HTML5 input types, then in a single shot your page would become far slimmer and easier to read and manage. At the same time, the page remains as friendly to users as it is when cool jQuery UI widgets are employed.
New HTML5 input types cover most common scenarios, such as entering dates or times, numbers, numbers in a range, URL and email addresses, phone numbers, and more. The best way to experience the power of HTML input types is by constructing a relatively rich HTML form. Let's take a look at this sample form, shown in Figure 1.
Figure 1: A Relatively Rich Input Form as Displayed in Chrome 22
Creating an Input Form
Listing 1 shows the markup of the input form in Figure 1. As you can see, the form needs to collect dates, numbers in a range, numeric input, dates, and even a phone number. In addition, all fields would benefit from having placeholder text, and many of them are required and cannot be left blank.
Listing 1: An ASP.NET MVC Input Form Written Using HTML5 Elements
<fieldset> <legend>New tournament</legend> <table id="inputForm"> <tr> <td class="label">Name</td> <td class="content"> @Html.DropDownList("circuit", new SelectList(Enum.GetNames(typeof(TournamentCircuit)))) <input required id="city" name="city" type="text" placeholder="City" title="Enter the city where the tournament will be played." /> <input required id="country" name="country" type="text" placeholder="Country" value="@Model.Country" /> </td> </tr> <tr> <td class="label">Contact</td> <td class="content"> <input required id="phone" name="phone" type="tel" placeholder="Phone number" title="Phone number for contact" /> </td> </tr> <tr> <td class="label">Logo</td> <td class="content"> <input id="logo" name="logo" type="file" value="@Model.Logo" /> </td> </tr> <tr> <td class="label">Date</td> <td class="content"> <input required id="startDate" name="startDate" type="date" value="@Model.StartDate.ToString("yyyy-MM-dd")" /> thru <input required id="endDate" name="endDate" type="date" value="@Model.EndDate.ToString("yyyy-MM-dd")" /> file as <input required id="year" name="year" type="number" min="2011" max="2013" value="@Model.Year" /> </td> </tr> <tr> <td class="label">Prize money</td> <td class="content"> @Html.DropDownList("currency", new SelectList(Enum.GetNames(typeof(Currency)))) <input id="prize" name="prize" type="number" value="@Model.PrizeMoney" /> <label for="hospitality">Hospitality</label> <input id="hospitality" name="hospitality" type="checkbox" value="@Model.Hospitality" /> </td> </tr> <tr> <td class="label">Website</td> <td class="content"> <input id="website" name="website" type="url" placeholder="Web site" value="@Model.Website" /> </td> </tr> <tr> <td class="label">Appearance</td> <td class="content"> Primary color: <input id="baseColor" name="baseColor" type="color" value="@Model.PrimaryColor" /> </td> </tr> </table> <input type="submit" value="Save" /> </fieldset>
At the time of this writing, Google Chrome 22 and Opera 12 are the browsers that offer the best experience with HTML5 input controls. The form contains the new input types date, number, color, tel, and url as well as the classic checkbox, file, and text fields.
The browser automatically displays a down arrow where a date is expected and spin boxes where a number is expected. You also have a special color box where a color should be entered. No special clues exist for tel and url fields. As discussed in several of my previous HTML5 articles, placeholder text is used wherever applicable, and custom style makes it more noticeable to users. (See the end of this article for a list of relevant HTML5 articles.)
Entering Dates
As Figure 1 shows, the date picker is native and doesn't require any extra effort on your own beyond setting the input field as a date field. Let's focus a bit more on the date fields that indicate the start and end of the tournament.
<input required id="startDate" name="startDate" type="date" value="@Model.StartDate.ToString("yyyy-MM-dd")" />
<input required id="endDate" name="endDate" type="date" value="@Model.EndDate.ToString("yyyy-MM-dd")" />
At the markup level, you can set a default value by using the value attribute set to a yyyy-mm-dd formatted string. Note that this international format is mandated by the HTML5 standard.
You can also achieve the same programmatically using the valueAsDate read/write property that is also described in the HTML5 standard. For example, the domain logic for the sample page suggests that once the start date is set, we automatically adjust the end date to the next Sunday. How can you do that? You need a bit of JavaScript and specifically a handler for the new HTML5 input event. Listing 2 shows how to use set a handler using jQuery. Note that jQuery doesn't offer a helper method, so our only alternative is to use the general-purpose event binder.
Listing 2: Adjusting Dates Programmatically
<script type="text/javascript"> var Sunday = 0, Saturday = 6; $(document).ready(function () { $('#startDate').bind('input', function () { var startDate = $(this)[0].valueAsDate; var increment = 0; var day = startDate.getDay(); switch (day) { case Sunday: increment = 7; break; case Saturday: increment = 8; break; default: increment = 7 - day; break; } var endDate = new Date(startDate).setDate(startDate.getDate() + increment); $('#endDate')[0].valueAsDate = endDate; }); });</script>
The key thing to notice in the code in Listing 2 is the use of the valueAsDate Document Object Model (DOM) property. Because the property is not natively supported by jQuery (at least as of v1.7.2), you need to grab a direct DOM reference to the input element. You can do so using plain-vanilla JavaScript or via the indexer, as follows:
var startDate = $("#startDate")[0].valueAsDate;
var startDate = document.getElementById("startDate").valueAsDate;
The property gives you a valid JavaScript Date object that you can freely manipulate for your purposes. To update the end-date field you have two options: formatting the date as yyyy-mm-dd and assigning it to the value property or passing a Date object to the valueAsDate property.
In regard to the display format of the date in the date picker, the HTML5 standard offers no recommendations. Chrome, for example, shows selected dates using the browser's locale settings.
Numeric Input
Thankfully HTML5 saves us from having to attach JavaScript code to ensure that numbers are entered instead of text. The HTML5 standard offers two variations: number and range. The former lets you type a number and provides tools to set min/max boundaries. Most browsers show a spin box and let you indicate a step for users to quickly progress to the desired value. For programmatic access to the field, you use the valueAsNumber property and stepUp and stepDown methods to move the spin box. The second option is range, which browsers typically render through a slider.
A Word About Other HTML5 Input Fields
Numbers and dates are today widely and reasonably supported across browsers. The same can't be said for other types of input fields. A color picker has been added only recently to Chrome, which now joins Opera in supporting it. Picking colors from forms is probably not as common a task as picking dates or numbers, but having a nice UI may save a lot of work when picking colors is necessary.
URLs and email addresses are treated like plain text fields except that browsers validate the content before submitting the form against an internal set of text patterns. Some browsers also clear up the typed text a bit by completing it with http:// or detecting illegal characters. In terms of UI, there's no difference with plain text fields.
The tel field is a curious mystery. Browsers claim they support it, but there's no visually discernible difference between the tel field and a plain text field. Moreover, the HTML5 standard doesn't mention how one could express the pattern for a valid phone number. It turns out that you're better off using the pattern attribute on a plain text field if you need to accept a phone number in a valid format.
On the other hand, the tel, url, and email fields are very well supported by mobile browsers -- in particular Safari Mobile. When the focus moves to one of these fields, Safari Mobile pops up a specific keyboard with characters that match expected input. So, especially in mobile pages, you might want to use extensively the tel, email, and url fields.
A Date Picker for Every Browser
Now try displaying the same form generated by the code in Listing 1 in Internet Explorer 9 (IE9) or even old versions of Chrome and Firefox. You get none of the wonders that an HTML5-compliant browser can offer. If you want date pickers, you need to resort to using jQuery UI. As a developer, what should you do? Should you do the work twice?
As harsh as it might sound, the answer is yes: You should do the work twice and with no significant benefit for the user. The user will still get a nice form with prompt validation regardless of whether or not you use HTML5.
This begs another question: Should you really use HTML5? If you can force your audience to use latest versions of Chrome, Opera, and to a lesser extent IE10, Safari, and Firefox, then by all means go for HTML5. Otherwise, you can probably just ignore it for another couple of years. But perhaps there's a middle ground between using HTML5 and ignoring it.
The Modernizr library provides that middle ground. Modernizr greatly minimizes the amount of work required to make your web application UIs HTML5 compliant. Modernizr transparently checks the browser capabilities and offers an infrastructure for you to "declare" rather than "code" alternative behaviors. Let's see what it takes to extend the previous HTML5 form to use jQuery UI date pickers on IE9, as shown in the code in Listing 3.
Listing 3: Using jQuery UI Date Pickers in an HTML5 Form in IE9
<script src="@Url.Content("~/Content/Scripts/modernizr.js")" type="text/javascript"></script> <script type="text/javascript"> Modernizr.load({ test: Modernizr.inputtypes.date, nope: ['http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js', '/content/styles/jquery-ui.css'], complete: function () { $('input[type=date]').datepicker({ dateFormat: 'yy-mm-dd' }); } }); </script>
You place the script at the top of the page or, better yet, at the top of the layout or master page. The library checks whether date fields are supported, and if not, it downloads jQuery UI and Cascading Style Sheets (CSS) and sets up the page date fields, as Figure 2 shows. The source is HTML5 based, and the behavior is consistent across nearly all browsers.
Figure 2: An HTML5 Form in IE9
Modernizr doesn't force browsers to support HTML5 input fields (and more). However, Modernizr does make it easier and more convenient for developers to become familiar with HTML5, enabling them to write forms using higher-level tools with a small chunk of extra work.
Learn More About HTML5
Dino Esposito is a trainer and consultant specializing in web, social, and mobile integrated architecture and effective code design principles and practices. He's the author of Programming Microsoft ASP.NET 4 and Programming Microsoft ASP.NET MVC3 (Microsoft Press).
Twitter: @despos
About the Author
You May Also Like