Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Tree: 51f7bf7c82
Fetching contributors…

Cannot retrieve contributors at this time

439 lines (264 sloc) 24.2 KB
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="">
<title><![CDATA[Category: HTML5 | TJ VanToll]]></title>
<link href="" rel="self"/>
<link href=""/>
<name><![CDATA[TJ VanToll]]></name>
<generator uri="">Octopress</generator>
<title type="html"><![CDATA[HTML5 Form Validation - Showing All Error Messages]]></title>
<link href=""/>
<content type="html"><![CDATA[<p><a href="">Browsers that support HTML5 form validation</a> have one thing in common; if a <code>&lt;form&gt;</code> is submitted and has errors on multiple fields, the browser will only display the first error to the user.</p>
<p>Turns out the spec leaves the specific means of handling multiple errors up to the browser itself:</p>
<p><blockquote><p>Report the problems with the constraints of at least one of the elements given in unhandled invalid controls to the user. User agents may focus one of those elements in the process, by running the focusing steps for that element, and may change the scrolling position of the document, or perform some other action that brings the element to the user's attention.</p></p><p><p>User agents may report more than one constraint violation. User agents may coalesce related constraint violation reports if appropriate (e.g. if multiple radio buttons in a group are marked as required, only one error need be reported).</p><footer><strong>HTML5 Specification</strong> <cite><a href=''>;</a></cite></footer></blockquote></p>
<p>The key part here being that user agents (i.e. browsers) <strong>MAY</strong> report more than one constraint violation (i.e. error). Turns out they all decided not to.</p>
<p>You can see this in your browser below (assuming it <a href="">supports HTML5 form validation</a> and is not Safari, more on that later). Both fields are <code>required</code>, but if you submit the form you will only see an error for the first field.</p>
<pre class="codepen" data-type="result" data-href="FBGvu" data-user="tjvantoll" data-host=""><code></code></pre>
<script async src=""></script>
<p>Here's what it looks like on supported browsers if you attempt to submit this empty <code>&lt;form&gt;</code>:</p>
<h5>Chrome 21</h5>
<p><img src="/images/posts/2012-08-05/Chrome.png" title="Chrome" alt="Chrome" /></p>
<h5>Firefox 14</h5>
<p><img src="/images/posts/2012-08-05/Firefox.png" title="Firefox" alt="Firefox" /></p>
<h5>Opera 12</h5>
<p><img src="/images/posts/2012-08-05/Opera.png" title="Opera" alt="Opera" /></p>
<p>As you can see, all three only give an error for the first field. Firefox at least has the decency to put a red border around all fields with invalid data by default.</p>
<p>The one noticeable browser missing from the list above is Safari. Even though Safari supports the constraint validation API, the validation itself is turned off.</p>
<p>From a usability perspective showing the users only the first error message is bad. Imagine how frustrating it would be to continually correct errors just to be presented with the next error in the sequence. If you've ran into a form such as this before you know what I'm talking about.</p>
<p>Luckily, browsers provide a <a href="">constraint validation API</a> that can be used to provide this functionality.</p>
<h3>Using the Validation API</h3>
<p>All dom nodes now possess a <a href="">willValidate</a> property that indicates whether the node is a candidate for form validation.</p>
<p>Nodes in which <code>willValidate</code> is <code>true</code> also have a <code>validity</code> property. The <code>validity</code> property resolves to a <a href="">ValidityState object</a> which contains information about whether the field has validation errors, as well as the error message the browser will display to the user. You can leverage this API to display all error messages whenever a <code>&lt;form&gt;</code> is submitted.</p>
<h3>The Code</h3>
<p>Here's how I accomplished this with a jQuery dependent script.</p>
<p>``` html
<pre><code>&lt;ul id="errorMessages"&gt;&lt;/ul&gt;
&lt;label for="name"&gt;Name:&lt;/label&gt;
&lt;input type="text" required /&gt;
&lt;label for="comments"&gt;Comments:&lt;/label&gt;
&lt;textarea id="comments" required&gt;&lt;/textarea&gt;
&lt;input type="submit" value="Submit" /&gt;
$(function() {
//Keep track of whether there are any errors on the form for Safari.
var formHasErrors = false;
var showAllErrorMessages = function() {
formHasErrors = false;
//Find everything within the form
$('form').find('*').each(function(index, node) {
if (node.willValidate && node.validity && !node.validity.valid) {
formHasErrors = true;
//Find the field's corresponding label
var label = $('label[for=' + + ']');
//Opera incorrectly does not fill the validationMessage property.
var message = node.validationMessage || 'Invalid value.';
.append('<li><span>' + label.html() + '</span> ' + message + '</li>');
$('input[type=submit]').on('click', showAllErrorMessages);
$('input[type=text]').on('keypress', function(event) {
//keyCode 13 is Enter
if (event.keyCode == 13) {
//Handle for Safari not having HTML5 form validation active.
$('form').on('submit', function(event) {
if (formHasErrors) {
<p>You can see the results in your browser below:</p>
<pre class="codepen" data-type="result" data-href="eLvlf" data-user="tjvantoll" data-host=""><code></code></pre>
<p>Here's how it looks in Chrome 21:</p>
<p><img src="/images/posts/2012-08-05/Chrome-full.png" title="Chrome" alt="Chrome" /></p>
<p>A couple things to note:</p>
<p>1) If a user attempts to submit a form and gets validation errors, a <code>submit</code> event is never fired for the <code>&lt;form&gt;</code>. Therefore, instead of listening for <code>submit</code> on the <code>&lt;form&gt;</code>, I instead listen for a <code>click</code> on the <code>&lt;input type="submit"&gt;</code>. Since the user is also able to submit the form pressing enter in text inputs, I attach a <code>keypress</code> listener to them to ensure the same logic runs.</p>
<p>2) In my example I start each error message with the contents of the field's <code>&lt;label&gt;</code>. This is because the messages for each field are often identical. An alternative approach would be to use another constraint validation API method, <a href="">setCustomValidity</a> to set a completely custom message.</p>
<p>3) The <code>node.willValidate &amp;&amp; node.validity</code> check will be <code>false</code> in all browsers that do not support the constraint validation API. Therefore this code will simply do nothing in browsers that do not support HTML5 form validation.</p>
<p>4) Opera incorrectly does not fill the <code>validationMessage</code> property. Therefore the check <code>var message = node.validationMessage || 'Invalid value.'</code> is necessary so a message is displayed for Opera.</p>
<p>5) In order to make Safari display the error messages I manually keep track of whether there are any validation errors in the <code>&lt;form&gt;</code>. If there are I prevent the <code>&lt;form&gt;</code> from submitting in a <code>submit</code> event.</p>
<p>6) I do nothing to style the individual fields based on whether they have valid data. The HTML5 spec provides a number of CSS hooks to do this and I would recommend reading <a href="">CSS Pseudo-Classes and HTML5 Forms</a> from <a href="">html5 Doctor</a> if you're interested in including such styling.</p>
<h3>That's a Lot of Code to Do Something Simple</h3>
<p>Yep. While browser support is getting to be quite good for HTML5 forms the implementations themselves are still a bit buggy. Nevertheless, this approach will work for displaying all validation errors to the end user.</p>
<title type="html"><![CDATA[Native HTML5 Number Picker and jQuery UI's Spinner - Which to Use?]]></title>
<link href=""/>
<content type="html"><![CDATA[<p><a href="">HTML5's native number picker</a> (<code>&lt;input[type=number]</code>) and jQuery UI 1.9's spinner can both be used to create inputs for numeric data. So which makes sense for your application? Let's start with a brief explanation of each.</p>
<p>HTML5 adds several new valid <code>type</code> attributes for <code>&lt;input&gt;</code> elements. One of them, <code>number</code>, can be used to create a number picker.</p>
&lt;input type="number" /&gt;
<p>This will present the user with a number picker in supported browsers, which, as of this writing includes Chrome, Safari, Opera, iOS, Opera Mobile, and Android 4.0+ (<a href="">full support list</a>). Here's what the user will see in supported browsers:</p>
<h5>Chrome 20:</h5>
<p><img src="/images/posts/2012-07-15/Chrome.png" title="Chrome" alt="Chrome" /></p>
<h5>Safari 5.1.7:</h5>
<p><img src="/images/posts/2012-07-15/Safari.png" title="Safari" alt="Safari" /></p>
<h5>Opera 12.00:</h5>
<p><img src="/images/posts/2012-07-15/Opera.png" title="Opera" alt="Opera" /></p>
<h5>Opera Mobile 12:</h5>
<p><img alt="Opera Mobile" title="Opera Mobile" src="" style="height: 250px;" /></p>
<h5>iOS 5:</h5>
<p><img alt="iOS" title="iOS" src="" style="height: 200px;" /></p>
<h5>Android 4.1 (Jelly Bean):</h5>
<p><img alt="Android" title="Android" src="" style="height: 200px;" /></p>
<p>As you can see one of the nicest effects of using <code>[type=number]</code> is that mobile users will automatically be presented with a number pad to aid with entry of numeric data. Unsupported browsers will simply treat the <code>input[type=number]</code> as a normal text input. Firefox has <a href="">recently added a UI-less version</a> of <code>input[type=number]</code> to their nightly builds so hopefully a fully enabled version will be coming soon.</p>
<p>You can see what your browser does below:</p>
<iframe style="width: 100%; height: 120px;" src=",html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<h4>Additional Functionality</h4>
<p>The native number picker supports <code>min</code>, <code>max</code>, and <code>step</code> attributes to allow you to pick the minimum value of the <code>&lt;input&gt;</code>, the maximum value of the <code>&lt;input&gt;</code>, and the amount the value should be incremented / decremented when the user spins through values (the <code>step</code> attribute defaults to <code>1</code> if not specified).</p>
<p>For example, on the <code>&lt;input&gt;</code> below the browser will enforce that the minimum value will be <code>2</code>, the maximum value will be <code>20</code>, and the user will step at increments of <code>2</code>.</p>
&lt;input type="number" min="2" max="20" step="2" /&gt;
<p>You can see how this behaves in your browser below:</p>
<iframe style="width: 100%; height: 120px;" src=",html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<p>Just as a word of warning, Android 4.1 and iOS 5 do not support the <code>min</code>, <code>max</code>, or <code>step</code> attributes.</p>
<p>In addition to the new attributes, supporting browsers also provide 3 JavaScript methods specifically for <code>input[type=number]</code>.</p>
<li><code>stepUp(n)</code> - Increment the <code>value</code> of the <code>&lt;input&gt;</code> by <code>n</code>.</li>
<li><code>stepDown(n)</code> - Decrement the <code>value</code> of the <code>&lt;input&gt;</code> by <code>n</code>.</li>
<li><code>valueAsNumber</code> - Retrieve the <code>value</code> of the <code>input</code> as a JavaScript <code>number</code> variable (by default retrieving the <code>value</code> of an <code>&lt;input&gt;</code> returns a <code>string</code>).</li>
<h3>jQuery UI Spinner</h3>
<p>jQuery UI's <code>spinner</code> is a new plugin due for jQuery UI's 1.9 release (currently in beta). The plugin by default looks and behaves much like the native number picker.</p>
<iframe style="width: 100%; height: 120px;" src=",js,html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<p>It also supports setting minimum, maximum, and step values through options rather than attributes.</p>
<p>``` html jQuery UI Spinner
<input id="spinner" /></p>
$(function() {
min: 2,
max: 20,
step: 2
<iframe style="width: 100%; height: 120px;" src=",js,html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<h3>Above and Beyond</h3>
<p>What really sets jQuery UI's <code>spinner</code> apart from the native picker is that it is extensible, customizable, and it brings a number of extra features. Here are some of the additional things that you can do.</p>
<p><code>spinner</code> takes a <code>page</code> option that allows you to define how much the <code>spinner</code> should step when the page down / page up keys are pressed. The example below shows a <code>spinner</code> with a <code>step</code> value of <code>1</code> and a <code>page</code> value of <code>10</code>.</p>
<iframe style="width: 100%; height: 150px;" src=",js,html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<p>If you want mousewheel support for a <code>spinner</code> all you need to do is include <a href="">Brandon Aaron's mousewheel plugin</a> and you get it automatically! Try it out on any of the <code>spinner</code> demos on this page.</p>
<p>Ever need to accept currency at certain defined increments? This example shows a <code>spinner</code> that spins through currency values at $25 increments, all with the same clean API.</p>
<iframe style="width: 100%; height: 150px;" src=",js,html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<p>The formatting is localized through <a href="">Globalize.js</a>, therefore, if you want to handle different currencies all you need to do is pass in the appropriate <code>culture</code> and include the necessary JavaScript dependencies. Here's an example of an input that takes Euros.</p>
<iframe style="width: 100%; height: 150px;" src=",js,html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<p>If you need to accept time data <code>spinner</code> can be used for that as well.</p>
<iframe style="width: 100%; height: 150px;" src=",js,html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<p>The <code>page</code> option discussed earlier is used nicely here to make the up / down keys control the minutes and the page up / page down keys to controls hours. Try it out on the example above.</p>
<h3>24 Hour Times</h3>
<p>Since the <code>spinner</code> uses Globalize.js, you're free to use a time system different than the United States' nonsensical one.</p>
<iframe style="width: 100%; height: 150px;" src=",js,html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<h3>Time Picker vs. <code>&lt;input type="time"&gt;</code></h3>
<p>HTML5 also provides a native time picker (<code>input[type=time]</code>), but, it has <a href="">nearly no support</a>, does not yet provide localized formatting, and does not provide the stepping/paging functionality that <code>spinner</code> has baked in. In the future it might provide a viable native solution, but for now it's best to stay away.</p>
<h4>Extensible and Customizable</h4>
<p>Because <code>spinner</code> is built on top of <a href="">jQuery UI's widget factory</a>, it is easily extensible. For example, let's say you need to build an input that accepts a year in which the modern summer olympics were held. You could do that with the following:</p>
<p>```javascript Extending spinner
<input /></p>
$.widget( "tj.olympicspicker", $.ui.spinner, {
options: {
min: 1896,
max: 2012,
step: 4
$(function() {
<iframe style="width: 100%; height: 150px;" src=",js,html/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
<p>Now all your olympics pickers in your code base can share the same code!</p>
<h3><code>&lt;input type="number"&gt;</code> vs. <code>spinner</code></h3>
<p>Although jQuery UI's <code>spinner</code> is more advanced and customizable, for most simple applications the native number picker will work just fine. If you simply need a field that accepts numeric data there's no need to bring in <code>spinner</code> as a dependency. However, if you do need the ability to fine tune the behavior and look of the picker, or if you need consistent UI across all browsers, jQuery UI's <code>spinner</code> provides an excellent API to do so.</p>
<p>To summarize the reasons to use the native picker are:</p>
<li>Easy to implement, simply give an <code>&lt;input&gt;</code> a <code>type</code> attribute of <code>number</code>.</li>
<li>There are no dependencies, the number picker is native to the browser.</li>
<li>Mobile browsers that support the native picker will optimize the touch keyboard for number input.</li>
<p>And the reasons to use jQuery UI's <code>spinner</code> are:</p>
<li>Browser support - The <code>spinner</code> will work all the way back to IE6.</li>
<li>Extremely customizable and extensible.</li>
<li>Customizable handling of the page up and page down keys.</li>
<li>Easily integrated mousewheel support.</li>
<li>Built in custom types such as currency and time.</li>
<li>Built in i18n support.</li>
<h3>Using jQuery UI's Spinner to Polyfill <code>input[type=number]</code></h3>
<p>Another option is to use the native HTML number picker when it's available, and fallback to jQuery UI's <code>spinner</code> when it's not.</p>
<p>``` javascript Using jQuery UI to Polyfill input[type=number]
$(function() {</p>
<pre><code>var input = document.createElement('input');
input.setAttribute('type', 'number');
if (input.type == 'text') {
<p>The code to detect <code>input[type=number]</code> support was taken from <a href="">another number picker polyfill by jonstipe</a>. It creates an <code>&lt;input&gt;</code>, changes its <code>type</code> to <code>number</code>, and sees if that change actually took effect to determine whether the browser supports the type. You could also use the <code>Modernizr.inputtypes.number</code> check from <a href="">Modernizr</a> to achieve the same thing.</p>
<p>The <code>spinner</code> plugin is smart enough to look for the <code>step</code>, <code>min</code>, and <code>max</code> attributes on the <code>&lt;input&gt;</code> so you don't have to pass those in explictly (<a href="">thanks @bassistance</a>).</p>
<p>The benefit of this technique is that you get the benefits of the native picker when it's available, and you can count on having a number picker in all browsers. As a further optimization you could even use a conditional script loader such as <a href="">yepnope.js</a> to bring in jQuery UI's required JavaScript and CSS only when you need it.</p>
<h3>Using Spinner and Getting a Number Keyboard on Mobile</h3>
<p>If you want to use a <code>spinner</code> everywhere AND get a number keyboard on mobile things get a little trickier. Mobile browsers look for an <code>&lt;input&gt;</code> to have <code>type=number</code> to provide the number keyboard. So you think this would be as simple as creating a <code>spinner</code> on a <code>&lt;input[type=number]&gt;</code> node. However, that produces the following on supporting desktop browsers.</p>
<h5>Chrome 20:</h5>
<p><img src="/images/posts/2012-07-15/Chrome-Dual.png" title="Chrome" alt="Chrome" /></p>
<h5>Safari 5.1.7:</h5>
<p><img src="/images/posts/2012-07-15/Safari-Dual.png" title="Safari" alt="Safari" /></p>
<h5>Opera 12.00:</h5>
<p><img src="/images/posts/2012-07-15/Opera-Dual.png" title="Opera" alt="Opera" /></p>
<p>Obviously the double arrow UI is less than ideal. So to work around this you simply need to hide or destroy one of the sets or controls... right?</p>
<p>Well it turns out hiding the native arrow controls is difficult because Chrome places the control on the inside of the <code>&lt;input&gt;</code> and Safari and Opera place it on the outside. Therefore, if you try to adjust the <code>margin</code> of the <code>&lt;input&gt;</code> so jQuery UI's controls overlap the native ones it won't work in a cross browser friendly way.</p>
<p>Therefore the best approach I've came up with is to hide the <code>spinner</code>'s arrow controls when the browser creates its own.</p>
<p>``` javascript Number keyboard for a spinner
$(function() {</p>
if (Modernizr.input.step) {
$('.ui-spinner-input').css('marginRight', 0);
<p>What this does is detect whether the browser supports the <code>step</code> attribute, if it does it removes jQuery UI's controls. What does the <code>step</code> attribute have to do with the arrow controls? Nothing, except that it just <em>happens</em> that the browsers that support the <code>step</code> attribute also create a native control to do the stepping. Is this going to change in the future? Quite possibly.</p>
<p>So obviously this is not ideal, and probably shouldn't be used in production code, but it works at the moment. Have a better approach for tackling this problem? Let me know in the comments.</p>
Jump to Line
Something went wrong with that request. Please try again.