Yet Another Article on Client Side Form Validation

Client-side validation using JavaScript is nothing new, right? But using the HTML DOM and extending the input fields using specialized attributes might be. Read on!

I’ll assume you’ve already read a bunch of articles on form validation, both client-side and server-side, but this one has a new twist on the subject. What I’m going to show here is how to incorporate some object oriented programming into the form validation. So what’s the catch? This tip works with browsers that support JavaScript and W3C’s HTML DOM, such as Internet Explorer 6, Netscape 6 and Opera 6, and to some degree earlier versions. Though I haven’t tested Konqueror, according to specs it should work well.

Fair warning: you’ll need to be relatively proficient with JavaScript to follow this article.

Tags and Objects

Every form has a number of input tags that usually have name and value attributes. Textboxes might also have size and maxsize. In this article I’ve added some more attributes that you usually would not find: pattern and errorMsg. These attributes are nonstandard but that does not disturb the browsers. For the Object Oriented Programming aficionados out there, these attributes act like members of a class, the class in this case being the input tag.

A normal input tag:

<input type="text" name="firstname" size="20" maxsize="20" />

A modified input tag:

<input type="text" name="firstname" size="20" maxsize="20"  
pattern="[^A-Za-z]+" errorMsg="Invalid charcter found in firstname" />

The equivalent class in Java:

public class Input { 
String type = "text";
String name = "firstname";
String size = "20";
String maxsize = "20";  
String pattern = "[^A-Za-z]+";
String errorMsg = "Invalid character found in firstname";
}

Often you need to write functions for every input field you want to validate. But making each input tag ‘aware’ of both its matching pattern and error message makes the validation code much simpler to write. In fact, a generic solution that can be used for any value that can be described with Regular Expressions (RegExps for short) can be used in such a setup. For links on Regular Expressions see the resources at the end of this article.

DOM (Document Object Model)

Most attributes are represented as objects in DHTML but these added attributes are not. So to be able to get the values we need to use the DOM (for links on DOM see the list of resources at the end). The complete HTML page is, as in DHTML, called document. One method available to the document is getElementsByTagName(String). This method is used to find all input tags:

var elements = document.getElementsByTagName('input');

If elements would have been a normal JavaScript object one could guess that it would be an array which holds all input tags. But not in DOM: here it is a NodeList. Unlike an array where an element is reached by myarray[i], NodeLists have an items collection, (e.g. elements.item(i)).

Then we can iterate over all elements using a normal for-loop:

for (var i = 0; i < elements.length; i++) {

But now it’s time for the pattern attribute:

  var pattern = elements.item(i).getAttribute('pattern');

We need to get the pattern for this input field to be able to validate it. In this article just the mandatory elements have a pattern attribute (validation is as always being accomplished with RegExps).

So we take the value from the input field and check if any of the characters don’t match the pattern. In other words, we search for offending characters.

  var value = elements.item(i).value; 
 var offendingChar = value.match(pattern);

And if we find any illegal values we build an error message for the user:

  str += elements.item(i).getAttribute('errorMsg') + "n" + 
        "Found this illegal value: '" + offendingChar + "' n";

To give the user a little extra help, let’s change the background color of the field that contains the invalid input (note that this does not work in Opera, but doesn’t do any harm either).

  elements.item(i).style.background ="red"; 

As the observant reader might have noted, value in elements.item[i].value is represented as an object. But could it have been reached by elements.item(i).getAttribute('value')? No, that just shows the default value (if any) in a tag, not the value entered by the user.

Helper functions

There are two small functions that I’ve not mentioned yet. Firstly, we need to make sure that the browser can handle the script:

function DOMCheck() {  
 if(!document.getElementsByTagName('html')) {  
   alert("Sorry! Your browser does not support the W3C HTML DOM!");  
 }  
}

This simply checks whether there is an html element. Note that if the <html> tags are omitted, Internet Explorer will still render the page as HTML but the return value from the script would be zero, thus giving an incorrect error message. Thus, always be good and include <html> tags in your document.

Secondly, we need to clear out the background color when the user enters a new value in the input tags:

function changeColor(th) {  
 //'resets' the background-color to white  
 th.style.background = "white";  
}

Note that this does not work in Opera. This method is called from the input tag using the event handler 'onfocus'.

Source listing

The complete listing for our validation function looks like this:

function validate() {  
 var str = "";  
 var elements = document.getElementsByTagName('input');  
 
 // loop through all input elements in form  
 for(var i = 0; i < elements.length; i++) {  
 
   // check if element is mandatory; ie has a pattern  
   var pattern = elements.item(i).getAttribute('pattern');  
   if (pattern != null) {  
     var value = elements.item(i).value;  
 
     // validate the value of this element, using its defined pattern  
     var offendingChar = value.match(pattern);  
 
     // if an invalid character is found or the element was left emtpy  
     if(offendingChar != null || value.length == 0) {  
 
       // add up all error messages  
       str += elements.item(i).getAttribute('errorMsg') + "n" +  
              "Found this illegal value: '" + offendingChar + "' n";  
 
       // notify user by changing background color, in this case to red  
       elements.item(i).style.background = "red";  
     }  
   }  
 }  
 
 if (str != "") {  
   // do not submit the form  
   alert("ERROR ALERT!!n" +str);  
   return false;  
 } else {  
   // form values are valid; submit  
   return true;  
 }  
}
Further extensions

This idea of adding attributes can be further extended with attributes such as minimum and maximum values. Let’s say that RegExp isn’t enough, and we need to further qualify a given value:

Age: <input type="text" name="age" maxlength="2" size="2"   
     min_reqs="18" max_reqs="30" errorMsg="Age must be 18-30 years" />

Still using the same idea, generic validation code that can be used for all input tags that uses min/max values by adding some logic (within the validation function) for this input element.

  var min_reqs = elements.item(i).getAttribute('min_reqs');  
 var max_reqs = elements.item(i).getAttribute('max_reqs');  
 
 if (min_reqs != null && max_reqs != null) {  
   var value = elements.item(i).value;  
   if (value < min_reqs || value > max_reqs) {  
     str += elements.item(i).getAttribute('errorMsg') + 'n';  
   }  
 }
Conclusion

Is this the way to go? Maybe not yet but in the very near future, when all or most users use an up-to-date browser. Of course there are other benefits of having a unified object model (DOM) for the browsers, but this little tip will make Web development a bit easier.

Resources

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments

Comments on this post are closed.