Programming Articles - JavaScript, XHTML, CSS, Java
Sunday, 17 August 2008
JavaScript Form Validation
Want to validate user input for an (X)HTML form without embedding a single line of JavaScript, without having to worry about violating semantics, and all the while providing a reactive, user friendly experience?
Introducing GValidator - a powerful, extensible yet easy to implement JavaScript library that provides constant feedback during form completion. To use the library all you need to do is include it.
The aim
The aim of GValidator is to provide the following:
- A user-friendly experience for our visitors
- Semantically clean code
- Standards compliant code
- Cross browser compatibility
- Reusable JavaScript code
- Code flexibility and extensibility
The Code
GValidator now has a Google Code project. To get the latest version, post bugs, comment on or just look about visit: http://code.google.com/p/gvalidator
- Download the entire GValidator library, along with examples and CSS
Actually, for basic forms no extra coding is needed other than to include the JavaScript file and to add appropriate class names to your form fields. Here is an example form:
<form action="/action/" method="post" class="gform" >
<input type="text" name="firstname" class="firstname" maxlength="30"/>
<input type="text" name="lastname" class="lastname" id="lastname" maxlength="30"/>
<input type="text" name="subject" class="text" id="subject" maxlength="30"/>
<input type="text" name="captcha" class="captcha" id="captcha" maxlength="30"/>
<input type="text" name="phone" class="phone" id="phone" maxlength="12"/>
<input id="submit" type="submit"/>
</form>
There are a few things to notice here;
- The form is given a class attribute of "gform". This is what activates the automatic form validator
- The fields for validation are given various class names depending on how we wish to validate them. i.e. class="name", class="phone", class="text" etc.
- There is no embedded JavaScript functions or invalid semantic markup here. Just clean, straightforward XHTML
The Example
Field Types (default XHTML API)
The following are the field types and corresponding class names that are included in the default implementation. They should cover most cases. If you require more than this or customisation, then you can extend the functionality as discussed below.
| Form element | Description | Class name |
| text | Generic text input. Allows any characters except the following - ().;<> and is not mandatory | text |
| text | Generic required text input. Allows any characters except the following - ().;<> and must be completed | genericrequiredtext |
| text | Name field | name |
| text | Phone number field. Allows between 8 - 12 digits only. | phone |
| text | Email field | email |
| text | Captcha field | captcha |
| text | RE-Captcha text field. Displays a context and error message related to the RE-CAPTCHA system | recaptcha |
| textarea | Generic textarea input. Allows any characters except the following - ().;<>. Not require | text |
| select | Generic combo box. Requires the user to select an option with a non-empty value | select |
| radio group | Generic radio group. Requires that the user selects at least one of the options | radio |
| check box | Generic checkbox group. Requires that the user selects at least one of the options | checkbox |
GValidator Library Design
The library was designed with simplicity and extensibility in mind. The basic idea was to create an abstract class hierarchy that could be quickly and easily extended to change the validation function for a new field type. This hierarchy exists in three tiers allowing for the following object types:
- One third (top) level AbstractFormField class, which provides the skeleton that all FormField subclasses inherit from
- A finite number of second level AbstractFormElements which provide the basic implementations for the different form elements (i.e. <input>, <select> etc.)
- An infinite number of first level ConcreteFormElement objects which provide the concrete validation implementations (i.e. validate a phone number field)
Class Hierarchy

Customising GValidator
To create your own basic validation functions, you need to do the following things:
- Create a class at the first level, overriding the AbstractFormElement of your choice. i.e. To create a UsernameFormField class you would subclass the AbstractTextField class
- Set isRequired to true or false and override any other instance variables if necessary
- Override the validation function (and any other functions necessary) to do the custom form field validation
- Override the getNewInstance method which returns a instance of the new class. This is used by FormFieldFactory to automatically assign your class to a form field.
- Register the new class with FormFieldFactory
Customisation example
Lets say we would like to create a new field type username for validating usernames. The requirements are as follows:
- It must be between 8-10 alpha-numeric characters
- It must not already exist in the database
- It is a required field
Step 1: Subclass AbstractFormElement
Create a new class ONEGEEK.forms.GenericTextField and subclass AbstractTextField.
ONEGEEK.forms.UsernameTextField = function(field) {}
ONEGEEK.forms.UsernameTextField.prototype = new ONEGEEK.forms.AbstractTextField;
Step 2: Override existing instance variables
In this case, we need to make the field required and we want to validate the field using a regular expression. We can override the instance variables in AbstractTextField to achieve this. Override the following instance variables like so:
this.field = field;
this.name = 'username';
this.isRequired = true;
this.regex = /([a-zA-Z0-9-\'\s]{8,10})/g
this.cleanRegex = /[^0-9a-zA-Z-\'\s]/g
this.isRequired = true;
this.errorMessage = 'Your username must be between 8 and 10 characters';
this.contextMessage = 'You will use this to login. It must be between 8 and 10 characters';
Step 3: Override the validation function
The validation function is where most of the action happens. This function is responsible for checking whether the data has been modified and is valid, and setting the appropriate state of the field (INFO, OK, ERROR). This is where your custom AJAX code would go.
Assuming that an AJAX function called checkUsername(name, field) exists, which takes a username and a ConcreteFormElement object, this is how you would implement the validation function:
this.validate = function() {
this.clean();
this.pattern = new RegExp(this.regex);
var validated = this.pattern.test(this.field.value);
if(validated) {
// Regex validated, now use AJAX to check if username exists
// On successfull AJAX validation set state to OK - formField.setState(FIELD_STATUS_OK);
// On failure of AJAX validation set state to ERROR - formField.setState(FIELD_STATUS_ERROR);
checkUsername(this.field.value, formField);
} else {
if(this.modified == false) {
this.setState(FIELD_STATUS_INFO);
} else {
this.setState(FIELD_STATUS_ERROR);
}
}
return true;
}
Step 4: Override getNewInstance()
This function is simple yet vital, as it is called automatically by FormFieldFactory and assigns the object returned to be the handler for a particular form field. This assigned is done by matching a class name attribute from a form to a registered class name which we do in step 6.
this.getNewInstance = function(field) {
return new ONEGEEK.forms.UsernameTextField(field);
}
Step 5: Register the class with FormFieldFactory
Your custom validation function wil never be used unless you register with FormFieldFactory and tell it which classes you want it to automatically handle. Let's say that you want to use the class "username" with this function as in the example form element below:
<input type="text" name="username" class="username"/>
To get your new function to handle this, you simply do the following:
formFieldFactory.registerFormField('username', new ONEGEEK.forms.UsernameTextField());
Now when you load the page your new function will handle the validation!
Full customisation code
Here is the entire code listing for the customisation:
ONEGEEK.forms.UsernameTextField = function(field) {
this.field = field;
this.name = 'username';
this.isRequired = true;
this.regex = /([a-zA-Z0-9-\'\s]{8,10})/g
this.cleanRegex = /[^0-9a-zA-Z-\'\s]/g
this.isRequired = true;
this.errorMessage = 'Your username must be between 8 and 10 characters';
this.contextMessage = 'You will use this to login. It must be between 8 and 10 characters';
this.getNewInstance = function(field) {
return new ONEGEEK.forms.GenericTextField(field);
}
this.validate = function() {
this.clean();
this.pattern = new RegExp(this.regex);
var validated = this.pattern.test(this.field.value);
if(validated) {
// Regex validated, but use AJAX to check if username exists
// On successfull AJAX validation set state to OK - this.setState(FIELD_STATUS_OK);
// On failure of AJAX validation set state to ERROR - this.setState(FIELD_STATUS_ERROR);
checkUsername(this.field.value, this);
} else {
if(this.modified == false) {
this.setState(FIELD_STATUS_INFO);
} else {
this.setState(FIELD_STATUS_ERROR);
}
}
return true;
}
}
// Subclass Abstract FormField class
ONEGEEK.forms.UsernameTextField.prototype = new ONEGEEK.forms.AbstractTextField;
// Register the field types with FormFieldFactory
formFieldFactory.registerFormField('username', new ONEGEEK.forms.UsernameTextField());
GValidator Browser Support
The library has been tested successfully on the following browsers:
- Internet Explorer 6.0
- Internet Explorer 7.0
- Mozilla Firefox 1.0.6
- Mozilla Firefox 2.0.0.7
- Safari 3 Beta
- Opera 9.25
- Netscape Navigator8.0
- Netscape Navigator 9.0.0.1
| Next > |
|---|


