Accessible forms using jQuery’s Validation plug-in

There has been a lot of talk on our blog recently regarding forms. We have looked at rules for displaying error messages, creating accessible forms and would you have guessed, I’m now going to talk about implementing accessible form errors! Well, it makes a change from all of those HTML5 and CSS3 posts that are flooding my daily feeds of late.

A screenshot of the demo form page with error messages.

Anyway, this short post looks at how we can begin to deliver a better experience for our users when it comes to displaying form errors. As jQuery is my preferred library of choice and the Validation plug-in provides an excellent starting point, we will use them both to form the basis of this article.

Out of the box the jQuery Validation plug-in provides some reasonable defaults, however because of the vast options available in the plug-in, a developer can use it for great good or great evil. Following these tips, we are able to improve the accessibility of the plugins out-of-the-box defaults, which ultimately provides a better experience for our users.

I will start by making a few assumptions at this point:

  1. You have read Three rules for creating accessible forms and understand how to create accessible forms;
  2. You have a server-side validation method. It ensures there is a fallback for that minority who do not have JavaScript available, and stops hackers who can turn off JavaScript to avoid validation;
  3. You have downloaded the relevant jQuery and jQuery Validation plug-in files.

A simple form

First we need our form mark-up to be clean and tidy. Something like this perhaps:

<form id="formDemo" action="#">
    <fieldset>
    <egend>Your Details</legend>
        <div>
            <label for="f0">First Name</label>
            <input id="f0" name="f0" type="text" class="required">
        </div>
	<div>
            <label for="f1">Last Name</label>
            <input id="f1" name="f1" type="text" class="required">
        </div>
        <div>
            <label for="f2">Telephone Number</label>
            <input id="f2" name="f2" type="text" class="required">
        </div>
        <div>
            <label for="f3">Email Address</label>
            <input id="f3" name="f3" type="text" class="required">
        </div>
    </fieldset>
    <div>
        <input type="submit" value="Submit">
    </div>
</form>

Setup the jQuery validation function

Our next step is to call the jQuery Validation function. There are several ways you can do this, but for the sake of this article I want to keep it clean and simple. Thus I will call the jQuery Validation plug-in from within my own function (accValidate):

$(document).ready(function() {
    /*Initialise the validation function */
    $('#formDemo').accValidate();
});
jQuery.fn.accValidate = function(){
 
    var form = this;
 
    //The jQuery validation plug-in in action
    $(form).validate({
 
    //Optional, but for demo purpose we only want to validate on submitting the form
    onfocusout: false,
    onkeyup: false,
    onclick: false,
 
    //We are going to focus on the first link in the error list so i have disabled
    //the input error focus option in jQuery Validation
focusInvalid: false,

The excellent jQuery Validation plug-in allows us to configure how and when the validation script is run. For the purpose of our demo, we will disable the onfocus, onkeyup and onclick validation options. We only want it to validate on submission of the form.

Next the plug-in allows us to define the element to use for the error messages and their location:

//Set the element which will wraps the inline error messages
errorElement: "strong",
 
    //Location for the inline error messages
    //In this case we will place them in the associated label element
    errorPlacement: function(error, element) {
    error.appendTo($('label[for="' + $(element).attr('id') + '"]', form));
    },

We will display a simple inline error message for each input as part of the associated label. Why here you ask? Well it will depend on the situation and the input type in question (there are always some exceptions), but in this case it works well for screen readers that typically read out the associated label text (and therefore the error message) when the input field receives focus.

Creating the error summary

So far our jQuery Validation plug-in has done an excellent job! But now we are going to head off the beaten track slightly and create the error summary with the help of some of the functionality available within the plug-in:

//Create our error summary that will appear before the form
    showErrors: function(errorMap, errorList) {
    if (submitted &amp;&amp; errorList) {
 
        var $errorFormId = 'errors-' + form.attr('id')
 
        //Reset and remove error messages if the form
        //has been validated once already
        summary = "";
        $('label .error', form).remove();
 
        //Create our container if one doesnt already exits
        //better than an empty div being in the HTML source
        if($('#' + $errorFormId).length == 0) {
            $('&lt;div id="' + $errorFormId + '"/&gt;').insertBefore(form);
        }
 
        //Generate our error summary list
        for (error in errorList) {
            //get associated label text to be used for the error summary
            var $errorLabel = $('label[for="' + $(errorList[error].element).attr('id') + '"]').text();
            summary += '&lt;li&gt;&lt;a href="#' + errorList[error].element.id + '"&gt;' + $errorLabel + ': ' + errorList[error].message + '&lt;/a&gt;&lt;/li&gt;';
            }
 
            //Output our error summary and place it in the error container
            $('#' + $errorFormId).html('&lt;h2&gt;Errors found in the form&lt;/h2&gt;&lt;p&gt;&lt;em&gt;Whoops!&lt;/em&gt; - There is a problem with the form, please check and correct the following:&lt;/p&gt;&lt;ul&gt;' + summary + '&lt;/ul&gt;');
 
            //Focus on first error link in the error container
            //Alternatively, you might want to use the Validation default option (focusInvalid)
            $('#' + $errorFormId + ' a:eq(0)').focus();
 
            //Move the focus to the associated input when error message link is triggered
            //a simple href anchor link doesnt seem to place focus inside the input
            $('#' + $errorFormId + ' a').click(function() {
            $($(this).attr('href')).focus();
            return false;
        });
    }
    this.defaultShowErrors();
    submitted = false;
    },
    invalidHandler: function(form, validator){
        submitted = true;
    }

This creates our error summary, based on the errors found in the form, and inserts it before the form being validated. It clearly lists all errors and, as an added bit of functionality, provides anchor links allowing the user to easily skip to input fields that have an error.

You might also notice that we place the focus on the first link in the error summary when the form is submitted. This approach has undergone a fair amount of discussion and testing, the result of which lead us to believe that this approach worked well for users addressing errors in the form.

There we have it. You can checkout the demo here to see the form validation in action.

The jQuery Validation plug-in offers many useful features, for example we haven’t even looked at custom error messages or checkbox validation. But this should give you an idea of how we can start to deliver accessible error messages using a plug-in like jQuery Validation.

Have a different plug-in or library of choice for validating forms? Why not share it here…

Share this post

About the Author

Matt is a Web Developer at Nomensa, where he works on a range of front end development projects. When he's not cropping pixels and closing tags, Matt can usually be found taking part in a variety of outdoor pursuits, which often result in him being covered head to toe in mud.

16 comments

  1. Julia says:

    You’ve got the form validating on submission. I’m wondering about users of older screen readers whose buffer may not refresh with the changes to the DOM. I’ve always thought that JavaScript validation should be an enhancement, but that the form should still submit and return via a screen refresh with the error messages in situ.

    Have enough screen reader users upgraded to versions that will handle this type of JavaScript that we don’t need to worry about this any more?

  2. Alastair Campbell says:

    Hi Julia,

    Screen readers will generally update when you submit a form (i.e. press enter or space).

    Also, Matt did mention that he was assuming that:

    You have a server-side validation method. It ensures there is a fallback for that minority who do not have JavaScript available, and stops hackers who can turn off JavaScript to avoid validation;

  3. Julia says:

    Hey Alastair,

    Thanks for your response. :)

    I’ve come across issues in the past where the user has tried to submit the form (but has made an error, which has been flagged up using JavaScript). Because there was an error, the form would not submit (thus the server side validation can’t kick in), but the user couldn’t ‘see’ the error because their buffer hadn’t updated.

    So they’re left wondering why the form hasn’t submitted and not being able to understand why.

    This was a few years ago though, so I’m wondering if Screen Readers have indeed moved on enough that this is such an edge case we don’t need to worry about it any more.

    If you’re saying that screen readers will update the buffer when you submit a form, then it could well be that it they have!

    cheers
    Julia

  4. Alastair Campbell says:

    Hi Julia,

    It might have been an issue if they used onclick or something, but if it’s a standard submit button that shouldn’t be a problem.

    There is a script from Juicy Studio to force an update for when using AJAX (or other within-page updates without using a link or submit):
    http://juicystudio.com/article/improving-ajax-applications-for-jaws-users.php#theupdatefunction

    From the article:

    In JAWS 7.1 and later, dynamic updates that result from the user activating a link with the keyboard will automatically update the virtual buffer so that it is synchronized with the content on the screen.

    I believe that the same thing applies to submit buttons as well, assuming they are activated with space or enter.

    I think we’re upto JAWs 11 or 12 now?

    -Alastair

  5. Julia says:

    Oh – that’s really cool!

    Thanks for the updates Alastair, really appreciated.

    cheers
    Julia

  6. Lucica says:

    Hi, I think the web form can be improved with ARIA, maybe using aria-required=”true” for inputs and a live region for the error message returned when some field was missed. What do you think?

  7. Alastair Campbell says:

    Hi Lucica,

    Yes, ARIA attributes can improve forms, but this article was about using the jQuery plugin for validation.

    I would advise reading Derek Featherstone’s article before you jump in though, there are some gotchas:
    http://www.alistapart.com/articles/aria-and-progressive-enhancement/

  8. OK. I was thinking, Alert box is a best method for screen reader users.

  9. Hi,

    I have implemented this method successfully in one of my aspx forms. I faced a few issues though. When I tried to implement the validation using rules: {…my rules here…} syntax, the invalidHandler wouldn’t get called. This left “submitted” variable undefined. I wanted to do it this way as I wanted to have freedom to have my custom error messages. Any idea how could I achieve this?

  10. Brad Barwick says:

    The link to example form routes back to this page.
    http://www.nomensa.com/blog/demos/accessible-forms/

  11. Alastair Campbell says:

    Hi Brad,

    Ah, looks like that got left behind in an update, we’ll try and get that back in place again.

    Thanks

  12. Ben Roberts says:

    That link to the demo is still redirecting back to this page. It would be great if you could fix it, thanks

  13. Michael says:

    Great article…but where’s the demo page Alastair?

  14. Janey Lee says:

    Hi, the demo link is broken~

  15. Informative article.
    The demo link does not work and is broken.
    It would be nice if you guys fix it.
    Thanks

  16. Hi Janey and Ehsan,

    Sorry about that, we’ve re-established that link now. It got left behind in a WordPress update, we’re going to find a better place for demos.

Add a comment

Fields marked with an asterisk (*) are mandatory.

Comment details