QuickValidate: Building a jQuery Validation Plugin

by in Tutorials on 9th May 2012 · Comments

Oh forms! For the most part, forms look ugly, old and inconsistent across browsers, but they play one of the most important roles on the web; user input.

User input is everywhere, from contact forms to sign-up forms and from surveys to complex user interfaces. Forms come in many shapes and sizes, colors and styles, but they all have something in common; validation.

QuickValidate: Building a jQuery Validation Plugin


The Validation Process

The validation process can occur in the back-end or in the front-end, using PHP or JavaScript respectively, but most of the time, both the server and the browser will be involved in order to create a robust and secure solution.

HTML5 brings many validation filters to the table and it works pretty well, but only on supported browsers, which means, no IE8 or less. The old fashion way, using PHP exclusively, will offer support for IE, but it's not up to current web standards, where the user expects validation to be processed on the same page, which is also much better in terms of usability. This is where JavaScript comes in handy.

These are some of the most common concepts of input validation in the front-end:

  • Prompt a list of errors when the user submits the form providing a description for each and every field that failed to validate.
  • Display a description next to the field(s) that failed to validate when the user submits the form.
  • Live validation. Validate as the user types or when the field looses focus displaying a description next to the field that fails validation.

The first and second examples are probably the most commonly used patterns to validate forms in the browser. The third option is less popular but it has that extra “feature” that makes it a bit more usable and predictable providing a better experience to the end-user.

Regular Expressions

Regular expressions are essential to the validation process. Each input has to match a set of rules or filters in order to determine if its value is valid or not. We'll be using regular expressions often in this tutorial.

Regular expressions are easier and more powerful than they seem. Think of them as a unique and independent micro-language that it's embedded in almost any other programming language in the world.

The best tutorial you can probably find on how to use regular expressions is regular-expressions.info. It's a language agnostic resource on best practices and common uses of regular expressions that goes into every important detail providing easy to follow examples.

You can also use this quick JavaScript RegExp Reference.

In JavaScript you can create a regular expression in two ways.

  • Literal notation: /regularexpression/
  • As a RegExp object: var regex = new RegExp('regularexpression')

It's important that you understand the basics of regular expressions to follow this tutorial. Feel free to refer to those websites whenever you encounter something that you don't quite understand or that you think needs some more explanation.

What You Need to Get Started

We're going to build a small jQuery validation plugin based on the third concept mentioned in "The validation process".

This tutorial assumes that you have experience in HTML and CSS as well as some knowledge of JavaScript and jQuery.

Before we start, prepare a basic HTML template and load the latest jQuery library, an empty plugin.js, the normalize.css reset and a separate CSS stylesheet.

You can also use jsfiddle as a starting point.

Building the Form

Let's build the basic markup and styles of the form. I'm not going into too much detail since this is a more JavaScript oriented tutorial.

<form id="my-form">
    <p><label>Name <span>*</span>:</label><input type="text" class="required name"/></p>
    <p><label>Password <span>*</span>:</label><input type="password" class="required pass"/></p>
    <p><label>E-Mail:</label><input type="text" class="email"/></p>
    <p><label>Phone:</label><input type="text" class="phone" placeholder="999-999-9999"/></p>
    <!-- Empty label to align button to the rest of elements –->
    <p><label>&nbsp;</label><button type="submit">Submit</button></p>
</form>

We use classes to specify the filters we want to link to each input. You can name these filters whatever you want as long as you're consistent. We'll be using these class names in JavaScript to evaluate each field against a regular expression as we type.

Let's style the form with CSS. If you're using your own project template, make sure to load the normalize.css reset, otherwise it might look different.

#my-form p { 
    float: left; /* so it doesn't span 100% width */
    clear: both; /* so every input is in a new line */
    position: relative; /* to be able to position other elements */
    margin: .5em 0; 
}
#my-form label, 
#my-form input { display: inline-block; }
#my-form label { width: 100px; } /* depends on the length of your labels */
#my-form label span { color: red; } /* required star */
#my-form input { 
    padding: 0 .3em; 
    height: 24px;
    line-height: 24px; /* for IE */
    width: 200px;
    border: 1px solid #ccc;
}

At this stage, the form should look like this:

Building the Form

Building the Plugin

It's important to think about how do we want to use this plugin, or how will the user make use of it. The most obvious way is to be able to call the plugin like this:

$('#my-form').quickValidate();

With that in mind we can begin building our plugin using a common jQuery plugin template as a base.

Open your plugin.js if you're working locally. If you're working with jsfiddle use the JavaScript panel and make sure the latest jQuery is loaded in the framework dropdown menu.

(function($){
    $.fn.quickValidate = function () {
    
        // Cache variables
        var $form = this;

        // Only text and password fields will be processed
        var $inputs = $form.find('input:text, input:password');
        
        // Plugin code here
        
        // Allow jQuery to chain stuff to our plugin
        return this;
    };    
})(jQuery);

The plugin will be divided in four parts so it's easier to follow and understand how it works:

  • Filters
  • Validation
  • Error handling
  • Events

We'll be putting everything that follows within the "Plugin code here" area.

Filters

We need to create a reference and store all the filters that we previously set as classes in our HTML. The most organized way of doing this is by using an object literal. We'll use the class name as the filter name or key, and each key will contain a regular expression and an error message linked to it.

The required filter is the only one that doesn't belong here. It's a really simple filter that doesn't need a regular expression. We'll go into more detail later on.

var filters = {
    name : {
        regex : /^[A-Za-z]{3,}$/,
        error : 'Must be at least 3 characters long, and must only contain letters.'
    },
    pass : {
        regex : /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/,
        error : 'Must be at least 6 characters long, and contain at least one number, one uppercase and one lowercase letter.'
    },
    email : {
        regex : /^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/,
        error : 'Must be a valid e-mail address (user@gmail.com)'
    },
    phone : {
        regex : /^[2-9]\d{2}-\d{3}-\d{4}$/,
        error : 'Must be a valid US phone number (999-999-9999)'
    }
};

Using a structure like this is future proof. Adding new filters is as easy and fast as it can get. Now, take a moment to analyze the regular expressions you just wrote. Let's take the very first regex as a simple example and break it down:

^[A-Za-z]{3,}$
  • ^: matches a string that starts with
  • [A-Za-z]: an uppercase or lowercase letter
  • {3,}: at least 3 or more times
  • $: and ends. (not allowing any other characters but letters)

You can find most common regular expressions on Google, like e-mail, telephone, password, etc, but it's crucial to understand how they work. You can use the resources from "Regular expressions" to guide you.

Validation

This is the core of our plugin. The validate() function or method will evaluate all classes of a given input and it will test its value against the filter that matches the class. It's important to note that an input can have many classes, not only the ones related to our plugin but our plugin will only read two main classes; the required class and one of the filters from the filter object.

The validate() method takes two arguments, klass and value. The class will be a string containing all the classes of the given input, and the value, well, it's the value of the input which we'll test against the matching filter.

To build this function we're going to use the popular JavaScript module pattern. Let's break it down and comment out the important parts:

var validate = function (klass, value) {
    
    // Initial values of the public variables
    var isValid = true,
        error = '';
        
    // If the field is empty 
    // and it has the `required` filter...
    if (!value && /required/.test(klass)) {
        error = 'This field is required';
        isValid = false;
        
    // If the field is not empty...    
    } else {

        // Loop through all filters
        for (var f in filters) {

            // Create a new regex with the filter name
            var regex = new RegExp(f);

            // If the the current filter
            // in this iteration matches
            // a class...
            if (regex.test(klass)) {

                // If the value doesn't match the
                // regex of the current filter
                if (value && !filters[f].regex.test(value)) {
                    error = filters[f].error;
                    isValid = false;
                }

                // Exit the loop as soon as we find
                // a filter that matches a class
                break;
            }
        }
    }
    
    // Return public variables
    return {
        isValid : isValid,
        error : error
    }
};

Error Handling

When we run the validate() method with some parameters, it will return the isValid variable as well as an error if the value failed to validate. The error is just a string assigned to a variable, but we want to create an HTML tag so we can style it with CSS and integrate it in our form.

When the value of an input doesn't validate we want to highlight the field and show and icon that indicates something is wrong. When the user hovers over the information icon, an error popup will appear next to it with a brief description on what's going on and/or how to fix it.

Error Handling

Now, let's go back to our HTML and add some temporary markup to just the first field. This markup will be dynamically generated for every field with jQuery in the error handling function so we use this merely as a template for now, so we can style it with CSS.

<p><label>Name <span>*</span>:</label><input type="text" class="required name invalid"/><i class="error-icon"></i><span class=”error”>This is an error</span></p>

We've just added an invalid class to the input, an icon < i class="error-icon" > and a < span class="error" > which will contain the error message. Again, this will be added dynamically with jQuery.

Let's style those new elements in CSS to look like the image above:

/* Error highlight */
#my-form input.invalid {
    background: #FFFAC4;
}

#my-form .error-icon {
    position: absolute;
    top: 0;
    right: -32px;
    height: 24px;
    width: 24px;
    background: url(http://i43.tinypic.com/dbsh3m.png) no-repeat;
    cursor: pointer;
}

/* Error description */
#my-form .error {
    display: none;
    position: absolute;
    top: 10px;
    right: -195px;
    z-index: 999;
    padding: 10px;
    width: 120px;
    font-size: 12px;
    background: #222;
    color: white;
}

/* Popup arrow */
#my-form .error:after {
    content: "";
    position: absolute;
    top: 0;
    left: -20px;
    border-style: solid;
    border-width: 0 10px 10px 10px;
    border-color: transparent #222 transparent transparent;
}

The icon used in this tutorial can be downloaded for free at Iconfinder.

Now that the styles are all set, you can remove that markup from the HTML and revert to the original code. Next, we have to create that markup with jQuery.

The printError() method takes an $input jQuery object as parameter and creates the necessary HTML markup. It uses the validate() method to test if the given input validates or not. Then it prints the error and icon accordingly.

var printError = function($input) {
    // Cache variables
    var klass = $input.attr('class'),
        value = $input.val(),

        // Run the `validate()` method and store
        // it's returned values in a variable `test`
        test = validate(klass, value),

        // Create markup for the error and icon
        $error = $('<span class="error">' + test.error + '</span>'),
        $icon = $('<i class="error-icon"></i>');
        
    // Reset: 
    // Remove the current markup 
    // and `invalid` class if found
    $input.removeClass('invalid').siblings('.error, .error-icon').remove();
    
    // If the input fails to validate...
    if (!test.isValid) {
        $input.addClass('invalid');

        // Insert error and icon
        $error.add($icon).insertAfter($input);

        // Show the error when hovering the icon
        $icon.hover(function() {
            $(this).siblings('.error').toggle();
        });
    } 
};

Events

We need to make sure that the required fields are invalid when the plugin loads. Then we'll bind the events to our inputs and form.

// Initialize: 
// Go through every input and
// check if it has a required class
// If it does, run the `printError()`
// method on that input
$inputs.each(function() {
    if ($(this).is('.required')) {
        printError($(this));
    }
});

// Run the `printError()` method
// everytime we press a key in an input
$inputs.keyup(function() {
    printError($(this));
});

// Make sure that no invalid inputs
// are found when we submit the form
// Otherwise stop the form from submitting
// and prompt an error
$form.submit(function(e) {
    if ($form.find('input.invalid').length) {
        e.preventDefault();

        // The `alert()` is the simplest example
        // but you can really do whatever you want
        alert('The form does not validate! Check again...');
    }
});

The Final Step

Finally, call the plugin on your form:

$('#my-form').quickValidate();

Conclusion

QuickValidate brings easy to use validation in an unobtrusive small plugin with improved usability and very easy extensibility.

This plugin is GPL licensed and it's been tested in IE8+, Webkit and Firefox.

Download QuickValidate at github.

Check out the final result an fiddle with it at jsfiddle.net.

Cedric Ruiz is a freelance graphic and web designer/developer with a passion for computers and technology. He actually studied 3D animation but took a totally different path. He needs to learn something new everyday and he loves challenges and teaching people new skills.