Summary

This article investigates associating a generic form handler to all forms on a web page using ECMAScript. Using a client-side scripting language to check for errors is good for usability, as the script is executed directly on the visitor's machine. This not only saves the visitor having to wait for the form to come back from the server with a list of errors, but also saves bandwidth on the server. That doesn't negate the requirement for server-side validation. This is a progressive enhancement technique, which requires server-side validation to be in place, and used purely to improve the usability of forms.

Author: Gez Lemon

Contents

Form Handling Classes

Update: Please see The DOM And Screen Readers for a far better generic form validation routine that plays well with assistive technology.

A few weeks ago, I wrote an article about developers adding invalid attributes to the DOM to avoid validation concerns. I've received quite a few emails, asking how to write a generic form validation routine that could be attached to any number of forms in the document that doesn't use invalid attributes. The technique I would use is to use the class attribute, with a value indicating the type of validation required. For example, to validate a form field used to get an email address, provide a class attribute with a value of email. As the class attribute can accept multiple class names with a space-separated string, it wouldn't impact on any existing classes (ignoring the fact that some older browsers don't support multiple classes). The following is a segment of a form that uses the class attribute with values of string, number, and email for validation.

<fieldset>
<legend>Personal Details</legend>
<p>
<label for="forename">Forename
<input type="text" class="string" id="forename" name="forename" size="15">
</label>
</p>
<p>
<label for="surname">Surname
<input type="text" class="string" id="surname" name="surname" size="15">
</label>
</p>
<p>
<label for="age">Age
<input type="text" class="number" id="age" name="age" size="5">
</label>
</p>
<p>
<label for="email">Email
<input type="text" class="email" id="email" name="email" size="15">
</label>
</p>
</fieldset>

Event Registration

The first thing we need to do is register our event when the document loads. The correct method of registering an event is to use the addEventListener method, as defined in the DOM Level 2 Events Specification. This method allows you to register as many events handlers as you like to a single event on an element, and add and remove individual handlers as and when they're required. Unfortunately, Internet Explorer uses its proprietary attachEvent method instead of addEventListener. For the purpose of this exercise, I'll use the traditional event registration model, which is supported by all script-enabled browsers. The drawback of this approach is that it only allows one function to be assigned to an event handler, which will overwrite existing functions if they have already been assigned to the event handler. If you require support for more than one function being assigned to the onload event handler, Simon Willison's page load technique is a good workaround for event registration.

// For a more flexible event registration routine, see
// http://simon.incutio.com/archive/2004/05/26/addLoadEvent
window.onload = attachFormHandlers;

Attaching the Validation Function

The function to attach the form handler loops through each form found on the page, and attaches the checkForm function to the onsubmit event handler for the form.

function attachFormHandlers()
{
  // Ensure we're working with a 'relatively' standards 
  // compliant browser
  if (document.getElementsByTagName)
  {
    var objForm = document.getElementsByTagName('form');

    for (var iCounter=0; iCounter<objForm.length; iCounter++)
      objForm[iCounter].onsubmit = function(){return checkForm(this);}
  }
}

Checking Each Form Field

The function to check the form iterates through all of the elements in the form, examining the class attribute. As there may be more than one class name associated with a form field, we need to split the values into an array, and examine each value to check if it's a value that we want to validate. Each value we want to validate is then passed to an appropriate validation routine.

function checkForm(objForm)
{
  var arClass, bValid;
  var objField = objForm.getElementsByTagName('*');

  for (var iFieldCounter=0; iFieldCounter<objField.length; iFieldCounter++)
  {
    // Allow for multiple values being assigned to the class attribute
    arClass = objField[iFieldCounter].className.split(' ');
    for (var iClassCounter=0; iClassCounter<arClass.length; iClassCounter++)
    {
      switch (arClass[iClassCounter])
      {
        case 'string':
           bValid = isString(objField[iFieldCounter].value.replace(/^\s*|\s*$/g, ''));
           break;
        case 'number' :
           bValid = isNumber(objField[iFieldCounter].value);
           break;
        case 'email' :
           bValid = isEmail(objField[iFieldCounter].value);
             break;
        default:
           bValid = true;
      }

      if (bValid == false)
      {
        // If this field is invalid, leave the testing early,
        // and alert the visitor to this error
        alert('Please review the value you provided for ' + objField[iFieldCounter].name);
        objField[iFieldCounter].select();
        objField[iFieldCounter].focus();
        return false;
      }
    }
  }
  return true;
}

Validation Routines

The only thing left to do is define the validation routines. Obviously, you could add further validation routines such as isCreditCardNumber, isFristonCapacitor, or any other business rules your particular forms require.

function isString(strValue)
{
  return (typeof strValue == 'string' && strValue != '' && isNaN(strValue));
}

function isNumber(strValue)
{
  return (!isNaN(strValue) && strValue != '');
}

function isEmail(strValue)
{
  var objRE = /^[\w-\.\']{1,}\@([\da-zA-Z-]{1,}\.){1,}[\da-zA-Z-]{2,}$/;

  return (strValue != '' && objRE.test(strValue));
}

Complete Script

The following is the complete script for attaching the generic form handler to all forms in a document.

// For a more flexible event registration routine, see
// http://simon.incutio.com/archive/2004/05/26/addLoadEvent
window.onload = attachFormHandlers;

function attachFormHandlers()
{
  // Ensure we're working with a 'relatively' standards 
  // compliant browser
  if (document.getElementsByTagName)
  {
    var objForm = document.getElementsByTagName('form');

    for (var iCounter=0; iCounter<objForm.length; iCounter++)
      objForm[iCounter].onsubmit = function(){return checkForm(this);}
  }
}

function checkForm(objForm)
{
  var arClass, bValid;
  var objField = objForm.getElementsByTagName('*');

  for (var iFieldCounter=0; iFieldCounter<objField.length; iFieldCounter++)
  {
    // Allow for multiple values being assigned to the class attribute
    arClass = objField[iFieldCounter].className.split(' ');
    for (var iClassCounter=0; iClassCounter<arClass.length; iClassCounter++)
    {
      switch (arClass[iClassCounter])
      {
        case 'string':
           bValid = isString(objField[iFieldCounter].value.replace(/^\s*|\s*$/g, ''));
           break;
        case 'number' :
           bValid = isNumber(objField[iFieldCounter].value);
           break;
        case 'email' :
           bValid = isEmail(objField[iFieldCounter].value);
             break;
        default:
           bValid = true;
      }

      if (bValid == false)
      {
        // If this field is invalid, leave the testing early,
        // and alert the visitor to this error
        alert('Please review the value you provided for ' + objField[iFieldCounter].name);
        objField[iFieldCounter].select();
        objField[iFieldCounter].focus();
        return false;
      }
    }
  }
  return true;
}

function isString(strValue)
{
  return (typeof strValue == 'string' && strValue != '' && isNaN(strValue));
}

function isNumber(strValue)
{
  return (!isNaN(strValue) && strValue != '');
}

function isEmail(strValue)
{
  var objRE = /^[\w-\.\']{1,}\@([\da-zA-Z-]{1,}\.){1,}[\da-zA-Z-]{2,}$/;

  return (strValue != '' && objRE.test(strValue));
}

Category: Scripting.

Comments

  1. [generic-form-validation.php#comment1]

    Another great article *smile*

    I've been using this technique for a couple of years now (coupled with a PHP back-end form generator to automatically produce the form mark-up)

    My form engine adds multiple classes such as 'date required'. It's a shame you can't specify additional parameters such as 'integer min=100 max=200'.

    Another advantage is that once you identify the data type of field using a class, you can add visual clues using CSS.

    You can also attach other events and behaviours with a bit more DOM magic. How about a date data type field that turns into a drop down calendar if the user has Javascript enabled, a textarea that automatically turns into a rich text input...

    My current thinking is to tie the individual validation routines (isString, isDate etc.) into the back-end validation routines that you always have to write (in case the user agent doesnt have javascript) using an Ajax or JSPAN type mechanism so your not repeating the same code twice.

    Posted by Richard@Home on

  2. [generic-form-validation.php#comment2]

    Hi Richard,

    That's a great list of enhancements, thank you.

    My form engine adds multiple classes such as 'date required'.

    I wish I'd thought of using a required class, that is a really good idea. It makes sense that a field wouldn't necessarily be required, but if one's provided, it should be validated.

    It's a shame you can't specify additional parameters such as 'integer min=100 max=200'.

    Yes, it would be good if there was a standards compliant method of adding additional parameters. It's not an ideal solution, but something similar could be set up using hidden input fields:

    
    <input type="text" name="x" id="x" size="4" class="integer"/>
    <input type="hidden" name="xmin" id="xmin" value="100"/>
    <input type="hidden" name="xmax" id="xmax" value="200"/>
    

    Then use getElementById with a value of the name appended with min and max to retrieve the values if they exist. It's a lot of extra markup though, and really quite an ugly hack. I may give it some thought to see if I can come up with a better suggestion, as that would be a really useful feature.

    You can also attach other events and behaviours with a bit more DOM magic. How about a date data type field that turns into a drop down calendar if the user has Javascript enabled, a textarea that automatically turns into a rich text input...

    My current thinking is to tie the individual validation routines (isString, isDate etc.) into the back-end validation routines that you always have to write (in case the user agent doesnt have javascript) using an Ajax or JSPAN type mechanism so your not repeating the same code twice.

    Again, they're really good ideas. If the validation routines were implemented as a generic web service, the more likely they are to be kept up to date. I only recently discovered that it's quite valid for an email address to contain an apostrophe. Quite a lot of validation routines don't allow email addresses to have apostrophes. With this suggestion, you update one function and all pages using your web service are automatically up-to-date.

    Thanks again for some great suggestions, Richard *smile*

    Posted by Gez on

  3. [generic-form-validation.php#comment3]

    I still cringe Gez, when I see regular expressions used to match "valid" email addresses. This, as you probably are well aware, is a long-standing topic/debate in the programming community. The only really effective way of determining if an address is valid is to send something to the box and see if it bounces. Of course if you're just checking to see if someone is doing the old:

    sdfsdgsgsd

    thing, well...

    I'm also a little picker when it comes to checking textareas, the user could enter space characters, newlines, etc. and still not submit any sort of text. I would add a few other comments, but the topic here is generic validators, not custom ones.

    Nice work, as usual! ~d

    Posted by Douglas Clifton on

  4. [generic-form-validation.php#comment4]

    Hi Douglas,

    The only really effective way of determining if an address is valid is to send something to the box and see if it bounces.

    Of course; it's a case of something is better than nothing.

    I'm also a little picker when it comes to checking textareas, the user could enter space characters, newlines, etc. and still not submit any sort of text.

    The regular expression would catch that, as whitespace characters are stripped before it's sent to the isString function. Of course, it couldn't verify that someone hadn't put in gobbledeygook.

    I would add a few other comments, but the topic here is generic validators, not custom ones.

    I'd be interested in hearing them anyway. If it's off-topic, you're welcome to email me *smile*

    Best regards,

    Posted by Gez on

  5. [generic-form-validation.php#comment5]

    So, what happens when I have more than one error on the form? I get lots of alerts in a row?

    I'll give you the fact that *how* to display the error message is obviously left to the developer, but why not go through the extra effort to show the proper way to write out error messages?

    I'm actually working on something similar, but not generic like this. Javascript alerts are about the worst possible choice for displaying error messages. It's annoying and once you click OK you have no clue what the error was. Say you have 5 errors to fix. By the time you fix the first one are you going to remember what the other 4 error message were that popped up? I doubt it.

    Just one more little rant, attaching onload events. It should be done via the DOM not via the old school window.onload=... method.

    Something like this will work across all browsers (except IE/Mac):

    
    function prepform(){
    	// this is where you would do something cool to the form
    }
    function addEvent(obj,evType,fn,useCapture){
    	var ret=false;
    	if(obj!=null){
    		if(obj.addEventListener){
    			obj.addEventListener(evType,fn,useCapture);
    			ret=true;
    		}
    		else if(obj.attachEvent){
    			obj.attachEvent('on'+evType,fn);
    			ret=true;
    		}
    	}
    	return ret;
    }
    
    addEvent(window,'load',prepform);
    

    The bigger picture though, is that a generic validation routine would be very nice. Adding non-valid attributes through DOM manipulation is a pretty nifty idea. Great work.

    Posted by Justin Perkins on

  6. [generic-form-validation.php#comment6]

    It's annoying and once you click OK you have no clue what the error was. Say you have 5 errors to fix. By the time you fix the first one are you going to remember what the other 4 error message were that popped up? I doubt it.

    It doesn't work anything like you describe. If you look at the code properly, you'll notice that it gives up after it finds the first error, gives an appropriate message, and highlights and gives focus to the appropriate field. The reason I would do it that way is so as not to overface people with error messages, and help show which field, given that the validation is generic.

    Just one more little rant, attaching onload events. It should be done via the DOM not via the old school window.onload=... method.

    Something like this will work across all browsers (except IE/Mac):

    I acknowledge that point at the start where I suggest Simon Willison's page load method. There are also much better event registration routines than the one you suggest, that do include every script capable browser.

    Adding non-valid attributes through DOM manipulation is a pretty nifty idea. Great work.

    Great work? Where have I suggested that developers add non-valid attributes? I'm very much against developers adding invalid attributes through the DOM. See http://juicystudio.com/article/scripting-away-validation.php

    By the way, one of those lines got a little jumbled up. Those should be literal quotes, not the encoded quote.

    Sorry about that; fixed *smile*

    Posted by Gez on

  7. [generic-form-validation.php#comment7]

    Wow this is great. I wonder if it would very difficult to find the label associated with the field you're checking so that you can display a "nice" description of the field?

    As for adding more functionality why not add that to the class name? The class name could be "integer_min_100_max_200". If the code was changed to look at the text to the left of the underscore character some simple validation could be added.

    Do you have a greater list of validation types available?

    Posted by Tanny O'Haley on

  8. [generic-form-validation.php#comment8]

    Hmm, I admit I glossed over the intro paragraph and obviously missed that you were saying that you're against non-valid attributes. I thought you were suggesting using the DOM to add validation attributes (data types, default values, regular expressions, etc..) to individual input elements. That seems like an interesting idea and a neat way to add those values you need so you can retrieve them later when validating the form.

    I don't want to get into a discussion over the semantics of such a practice, I just thought that's what you were suggesting. This code snipped seemed like an "add-on" to some existing strucure you've already written.

    Simon's method still uses the window.onload technique. Why use custom functions written for a single document object (the window) when you can use a more generic method that can be used to attach multiple listeners to the same event on the same element? I've never seen a custom function just for attaching events to an input box, so why treat the window object any differently?

    You got a better event registering routine that actually works in IE/Mac? I don't see the advantage to keeping it a secret, why condone and further propagate the usage of window.onload when you yourself use a better method for attaching events? That's like knowing how to create CSS-based layouts but writing tutorials that show table based layouts, just because it's *easier*.

    I hope you can appreciate the nature of my questions/concerns, they are surely not meant to degrade the work you've done *smile*

    Posted by Justin Perkins on

  9. [generic-form-validation.php#comment9]

    Hi Tanny,

    Wow this is great. I wonder if it would very difficult to find the label associated with the field you're checking so that you can display a "nice" description of the field?

    That's a good idea. You could get the collection of label elements in the form, and use the 'for' attribute for each element to find the matching id for current form field.

    As for adding more functionality why not add that to the class name? The class name could be "integer_min_100_max_200". If the code was changed to look at the text to the left of the underscore character some simple validation could be added.

    Something like that would be workable. It's quite verbose, but would be easy to extract the validation constraints.

    Do you have a greater list of validation types available?

    Sorry, I don't have a list anywhere on this website.

    Posted by Gez on

  10. [generic-form-validation.php#comment10]

    Hi Justin,

    I don't want to get into a discussion over the semantics of such a practice, I just thought that's what you were suggesting. This code snipped seemed like an "add-on" to some existing structure you've already written.

    Adding invalid attributes would make constraints for the validation, such as min and max, a lot easier. I firmly believe in standards, and am trying to investigate standard compliant means of doing the same thing. I don't have elegant solutions for issues such as these. The comments often add more valuable information than the actual article, so I'm kind of hoping that someone with more experience of scripting would come up with workable solutions.

    Simon's method still uses the window.onload technique. Why use custom functions written for a single document object (the window) when you can use a more generic method that can be used to attach multiple listeners to the same event on the same element?

    I agree that it's bad to advocate the traditional event registration model, but it's the most flexible means all the time that IE is still the most popular Windows browser, and a major browser still widely used on the Mac. If IE didn't support CSS at all, no one would be using it. It's one of those areas that I think people should be aware of, but I personally think Simon's solution is a good solution at this moment in time that could easily be amended to use addEventListener when IE finally supports it.

    You got a better event registering routine that actually works in IE/Mac? I don't see the advantage to keeping it a secret, why condone and further propagate the usage of window.onload when you yourself use a better method for attaching events?

    I use Simon's method, but I've seen suggestions (I think it was Peter-Paul Koch, but it could have been brothercake) that essentially use your technique, but uses further object detection to degrade back to the traditional event registration model. I'm just on way out to work, so don't have time to search and find out where I've seen it.

    I hope you can appreciate the nature of my questions/concerns, they are surely not meant to degrade the work you've done *smile*

    Thank you; I do appreciate your comments *smile*

    Posted by Gez on

  11. [generic-form-validation.php#comment11]

    A technique I have recently used at work is based on the very old form-mail technique of having a single extra field which holds all of your validation information. This allows my forms to have complex validation rules such as regular expressions.

    All the ECMAScript has to do is check each field against a matching rule in this validation field. If the validation input or rule does not exist, you have to assume the field is valid.

    The icing on the cake is that the validation field is automatically generated by server-side code.

    Posted by David Carrington on

  12. [generic-form-validation.php#comment12]

    I've seen suggestions (I think it was Peter-Paul Koch, but it could have been brothercake) that essentially use your technique, but uses further object detection to degrade back to the traditional event registration model.

    I think this may be the script you're referring to - http://www.brothercake.com/site/resources/scripts/onload

    The browser notes mentions how it needs to be implemented for Mac/IE5 support. I don't see the point in supporting Mac/IE.

    Posted by Ste on

  13. [generic-form-validation.php#comment13]

    It's annoying and once you click OK you have no clue what the error was. Say you have 5 errors to fix. By the time you fix the first one are you going to remember what the other 4 error message were that popped up? I doubt it.

    I just wonder if error messages popping up one after another can get annoying? Obviously this would only be a problem with large forms. And assuming the visitor is a serious dumb***.

    You could use CSS to markup the fields that had errors. For instance, if you have

    div
    label ...
    input ...
    /div

    change the background color of the div if the field contained an error.

    Of course this doesn't really help people with screen readers now that I think about it. Its an idea anyhow.

    Posted by john on

  14. [generic-form-validation.php#comment14]

    Thanks for the tip to brothercake, I'm going to look into that because I've got a definite need to get the onload registration working in IE/Mac.

    As for displaying error message, I've found it best to dynamically insert an error message area that contains a <UL> of form errors.

    I also use the Fade Anything Technique ( http://www.axentric.com/posts/default/7 ) combined with some DOM scripting to apply a FAT class to the input elements that have errors. That way the visitor sees not only an error message area listing the error items, but there attention is drawn to the items in question via the FAT.

    It's really pretty neat, but still under development, otherwise I'd post an example up here.

    Posted by Justin Perkins on

  15. [generic-form-validation.php#comment15]

    Hi David,

    A technique I have recently used at work is based on the very old form-mail technique of having a single extra field which holds all of your validation information. This allows my forms to have complex validation rules such as regular expressions.

    That's an interesting technique; I may experiment with that to see what the possibilities are.

    Hi ste,

    I think this may be the script you're referring to - http://www.brothercake.com/site/resources/scripts/onload[/quote]Thanks, Ste. That doesn't look familiar, but looks like it does a good job of event registration.

    Hi John,

    I just wonder if error messages popping up one after another can get annoying? Obviously this would only be a problem with large forms. And assuming the visitor is a serious dumb***.

    I must be one of those dumbasses, as that would piss me off *smile*

    change the background color of the div if the field contained an error.

    Of course this doesn't really help people with screen readers now that I think about it. Its an idea anyhow.

    Anything like that helps, but couldn't be relied on for drawing attention to the field. As well as the screen reader issue, there is colour blindness and monochrome monitors to consider. The use of colour would be complimentary to a technique that does draw attention to the field.

    Hi Justin,

    As for displaying error message, I've found it best to dynamically insert an error message area that contains a <UL> of form errors.

    I use that technique for server-side validation. I basically build up a list of errors, then present them at the top of the form. I think it's important to review all of the fields if it's being sent to the server, as it's less time consuming for the visitor, and less strain on the server. For client-side scripting, I prefer to deal with the errors one at a time. It allows you to highlight and give focus to the field in question, and can also be beneficial to people with cognitive problems that would benefit from an error at a time, rather than being over-faced with a load of issues that they need to address. I do think there's scope for DOM manipulation to help indicate the field, and maybe provide more clues on the type of data required.

    I also use the Fade Anything Technique

    That's cool! Again, I don't think it could be relied on alone, but it's a nice complimentary method. [quote]It's really pretty neat, but still under development, otherwise I'd post an example up here.

    I'd be interested in seeing it in use. When you have it ready, I'd appreciate it if you could drop me a line so I could take a peek at it in action. I've included my email with this post, if you feel so inclined, of course *smile*

    Cheers,

    Posted by Gez on

  16. [generic-form-validation.php#comment16]

    I actually do something similiar, but I don't use the class attribute, because it cannot be reused by the server-side validation. Instead I use the name attribute. An example:

    <input id="email" name="Email:EmailRegExpValidator:1" />

    The : is the separator. In my backend I split these three values:

    1) Email, is the string that is used to describe the field. That way I can say "You're {fieldname} is wrong. Please correct". It can also be used as a translatable string.
    2) EmailRegExpValidator: Is the name of my PHP class that validates emails. I haven't done this, yet, but it would be easy to do the same thing for JavaScript and only send everything to the server when the JavaScript validation passes.
    3) 1 or 0, means required or not required.

    It validates and can be made to work on both sides. If you need parameters you could extend the syntax.

    <input id="age" name="Age:RangeValidator_min-13_max-99:1" />

    Posted by Saša Ebach on

  17. [generic-form-validation.php#comment18]

    Great work!

    Just one little addition/idea:
    Using a regular expression for checking the classes in checkForm() would save you (your browser *wink* ) from running through the second for()-loop for each field that should be validated.

    Instead of:

    
    // Allow for multiple values being assigned to the class attribute
    arClass = objField[iFieldCounter].className.split(' ');
    for (var iClassCounter=0; ...) {
      ...
      if (bValid == false) {
        ...
      }
    }
    

    Try:

    
    // Allow for multiple values being assigned to the class attribute
    strClass = objField[iFieldCounter].className;
    strValue = objField[iFieldCounter].value;
    if (strClass.match(/\Wstring\W/) {
      bValid = isString(strValue.replace(/^\s*|\s*$/g, ''));
    }
    else if (strClass.match(/\Wnumber\W/) {
      bValid = isNumber(strValue);
    }
    else if (strClass.match(/\Wemail\W/) {
      bValid = isEmail(strValue);
    }
    else {
      bValid = true;
    }
    
    if (bValid == false) {
      ...
    }
    
    

    Sascha

    Posted by Sascha Drews on

  18. [generic-form-validation.php#comment19]

    Hi Sascha

    Using a regular expression for checking the classes in checkForm() would save you (your browser *wink* ) from running through the second for()-loop for each field that should be validated.

    That's a great idea. You have missing closing parentheses on your conditions, and \b would be more appropriate to check for the boundary in the regular expression:

    
    strClass = objField[iFieldCounter].className;
    strValue = objField[iFieldCounter].value;
    
    if (strClass.match(/\bstring\b/))
      bValid = isString(strValue.replace(/^\s*|\s*$/g, ''));
    else if (strClass.match(/\bnumber\b/))
      bValid = isNumber(strValue);
    else if (strClass.match(/\bemail\b/))
      bValid = isEmail(strValue);
    else 
      bValid = true;
    

    Thank you for the suggestion, it is a good idea *smile*

    Posted by Gez on

  19. [generic-form-validation.php#comment20]

    Hi folks,

    My logic goes like this:

    If javascript is required in order to actually run the validation routine, why add invalid attributes or classnames to the html at all; It should be possible to use javascript for the passing of validation parameters, for example:

    validator.addRule("email", /some reg exp/);
    

    This is the process used within my form validator script (which validates fields using user-defined regular expressions).

    As with everything web, theres pros and cons to each method.

    On an aside I never thought of using the name attribute to store data on both the client and the server.. interesting Sasa, very interesting..

    Posted by frequency decoder on

  20. [generic-form-validation.php#comment22]

    If javascript is required in order to actually run the validation routine, why add invalid attributes or classnames to the html at all; It should be possible to use javascript for the passing of validation parameters

    Just to reiterate, I'm totally against adding invalid attributes to the DOM, period. Adding a class name to the markup means that the validation routines can be added unobtrusively, and remain generic. Requiring a script to add invalid attributes to the DOM is not only bad practice; it's also not generic, as each form requires its own script to add the invalid attributes. I'm also against methods such as innerHTML, particularly with XHTML, but that's another issue. Not working with standards does afford more flexible scripts, but I only want to investigate standard compliant methods.

    Posted by Gez on

  21. [generic-form-validation.php#comment23]

    Hi Gez,

    I'm totally against adding invalid attributes to the DOM

    And I'm 100% in agreement. To stop this, I encapsulated/referenced the HTML element within a javascript object and added the attributes to the object.

    
    var someobj = new Object();
    someobj.element = document.getElementById(formelem);
    someobj.regexp = /some reg exp/
    

    My biggest 'javascript dislike' has to be having to use the traditional event model; as you pointed out, it can (and often does) cause problems, especially with window.onload.

    As I say, theres a million ways to skin a cat (or something like that!). Including the validation terms within the classnames has no adverse side effects but means the classnames themselves are used for a non-intended purpose.

    The big drawback with my javascript initialisation is that each form requires a unique block of javascript in order to validate but personally, I don't think that it's any more work to initiate the rules within javascript than to add classnames to the XHTML - although it does mean the script isn't generic per se which was the crux of the article!

    It's a nice comment thread - it's good to see people chipping in with ideas and suggestions.

    Posted by frequency-decoder on

  22. [generic-form-validation.php#comment24]

    I'm working on some OO generic form validation classes in javascript. I've also been researching the various options and despite being timid at first I have to admit that the most elegant and extensible solution is to add custom attributes/properties to the DOM.

    Take a look at this procedural example:
    http://phrogz.net/tmp/FormAutoValidate/

    I guess this approach does violate encapsulation as it applies to OO concepts but I guess that's not the real concern...

    I agree - adopting a standard's based approach is important, however; I don't think adding custom attributes/properties to the DOM poses a huge threat to the future of the WWW. In fact, I hope that future standards will allow for custom attributes and events and ultimately the definition of custom tags that can be defined in linked files in well-formed and standard compliant XHTML/XML.

    I guess the WWW is still a very young and dynamic medium and as such we will continue to see innovative solutions to complex problems - even if they don't validate against a strict or even transitional DTD!

    Posted by Immy on

  23. [generic-form-validation.php#comment25]

    Wow - great idea and a great resource.
    I've run with the idea of using the field label to give a more helpful notice to the user. I'm no DOM master, but this is what I've knocked up:

    
    // get the label for the field that's got a problem
    // objLabels is a collection of all the labels in the form
    for (var iLabelIDX=0; iLabelIDX < objLabels.length; iLabelIDX++) {
      if (objLabels[iLabelIDX].getAttribute("for") == objFrmItemID) {
        objLabels[iLabelIDX].className = "error"; // give the label the "error" class - highlights it red
        lblError = objLabels[iLabelIDX].innerHTML
        break;
      }
      else
      lblError = ""
    }
    // then use the lblError variable in your error message. When the user submits the form again, reset all labels to their normal class.
    

    Posted by craig on

  24. [generic-form-validation.php#comment26]

    I've implemented something similar although I've used a standard naming convention for labels - <targetElementId> + "Label" - i don't like the idea of traversing through the DOM element hierarchy searching for the relevant label for each and every form element to be validated...

    here is another resource which formats errors very nicely with standards compliant CSS:
    http://jeffhowden.com/code/css/forms/

    Posted by Immy on

  25. [generic-form-validation.php#comment27]

    Very nice technique, I just read about it..
    But - as I am not a very ecma/js techy - what you css-style your forms and want to add the css styling to a form object with class="formXinput" etc?

    As the class-tag is now used for the formvalidation etc.

    Or am I overlooking something here?
    For instance, is it possble to style a whole form with css at once with stuff like:

    
    .formX input {
      background-color: pink;
      width: auto;
    }
    .formX button {
      border: 2px dotted black;
    }
    
    .formY input {
      background-color: green;
    }
    

    and then style the whole form in one go in the <form ..>-tag?

    Thanks for any input. Feel free to mail me.

    Rolf

    Posted by Rolf on

  26. [generic-form-validation.php#comment28]

    Very nice technique, I just read about it..

    Thank you

    But - as I am not a very ecma/js techy - what you css-style your forms and want to add the css styling to a form object with class="formXinput" etc?

    As the class-tag is now used for the formvalidation etc.

    The class attribute allows for more than one class to be specified, as a space separated list. The following example uses two classes; one for the validation, and the other for styling.

    
    <input type="text" class="string order" ...
    

    You could add the style information directly to string if you wanted all form controls with a class of string to look similar. If not, you could just use whatever class you would normally associate with the form control.

    For instance, is it possble to style a whole form with css at once

    It is possible to style the whole form at once, but you also have the option of using classes, and the form's position on the page to help style the form. For more information about choosing appropriate selectors, see the div mania article.

    Posted by Gez on

  27. [generic-form-validation.php#comment29]

    Hi Gez,

    Thanks for the reply.

    I read about the space seperated multiple classes option, but as I never saw examples of it really I wasn't sure how it works.

    I couldn't find how it would select the appropriate style. But it seems that it just looks at every class in the list and then tries matching it with the styles specified in the css doc. Is that true?

    E.g.

    
    <style>
    input {
      width: auto;
      background-color: #ccc;
      border: 1px solid black;
    }
    .rolf {
      background-color: pink;
    }
    </style>
    
    <form>
      <input type="text" name="firstname" />
      <input type="text" name="email" class="email rolf" />
    </form>
    

    the first class "email" is used by the validator and the background of the input field is styled by the class .rolf making it pink.
    As far as I could test, this works. Is this how it's supposed to be used (it almost looks too easy, you know what I mean?).

    I'm looking at what appropriate selector to use (regarding the div mania article), there are more ways to go as usual. But so far the space seperated class styles suits my code best, as I have a generic right lining div I use a couple of times on the page with multiple forms.

    Btw- feel free to delete this comment from the general page and reply via e-mail, as this might go in too much detail about the use of styling..

    Thanks (again),
    Rolf

    Posted by Rolf on

  28. [generic-form-validation.php#comment31]

    This script is perfect. But, i am programmer- beginner in JS, and i need define and custom all values outside HTML like this:

    mainItems['address'] = new Array('string', "Bad Adrress!");
    mainItems['creditcard'] = new Array('number', "Bad CC number!");

    Is it possible? How? Thanks.
    Juraj

    Posted by Juraj on

  29. [generic-form-validation.php#comment32]

    Hi Juraj,

    It is possible, and you do it exactly as you have shown (although it's better to be consistent with the type of quotes you use for readability).

    Posted by Gez on

  30. [generic-form-validation.php#comment33]

    Hello all,

    really green with this javascript stuff, but how can i add select validation routine to the original script??? tried but have not been able to think it through..any help would be appreciated...

    Skiz

    Posted by Skizzly on

  31. [generic-form-validation.php#comment34]

    how can i add select validation routine to the original script

    I'm not sure what you're asking, but will assume you mean validate the select element. As the select element only has values that you provide, it shouldn't really need validating.

    If you use options such as "Please choose", you could either provide a default valid value for that option, so that people who can't be arsed to select the right option will at least be able to post the form. If that's not appropriate solution, and you want an invalid default option, you could validate that the user has selected a valid option with this script.

    To validate it with this script, set the class to the data type of your options, and set an inappropriate value for the default option. For example, if valid values are all strings, you could use:

    
    <select name="g" id="g" class="string">
    <option value="0">Please choose</option>
    <option value="A">Proper Option</option>
    ...
    </select>
    

    Posted by Gez on

  32. [generic-form-validation.php#comment35]

    Thanks Gez for coming back to me. One last thing I have found with the script is that; after it goes through the form page element and checking validation when it comes to the select element, the form submits without allowing user to amend select element...here is the script:

    [edit: script removed]

    Please advise as to what I am doing wrong!....

    Thanks in anticipation

    Skiz

    Posted by Skizzly on

  33. [generic-form-validation.php#comment36]

    Why not using another tag than the "class" tag, eg the "title" tag? Also I've just realised that you could use your own tags as in

    <input type=text mytag="email" id="myelement">

    and then refer to it in Javascript with

    document.getElementById("myelement").mytag

    That would avoid potential clashes with CSS and keep the class tag for display things only.

    Cheers,
    V.

    Posted by Valere on

  34. [generic-form-validation.php#comment37]

    One last thing I have found with the script is that; after it goes through the form page element and checking validation when it comes to the select element, the form submits without allowing user to amend select element

    When the script encounters an error, it calls the select method which isn't available to the select element. I should have mentioned this when I responded to your last question, sorry. Put a condition in front of the select method that checks the form field is an input element:

    if (objField[iFieldCounter].nodeName.toLowerCase() == 'input')
      objField[iFieldCounter].select();

    Posted by Gez on

  35. [generic-form-validation.php#comment38]

    Why not using another tag than the "class" tag, eg the "title" tag?

    They're attributes, not tags. The purpose of the class attribute is for styling and scripting. It's semantically the correct attribute to use.

    Also I've just realised that you could use your own tags

    That's not a good idea. Please see: http://juicystudio.com/article/scripting-away-validation.php

    That would avoid potential clashes with CSS and keep the class tag for display things only.

    Scripting and CSS don't clash; they're different technologies for different purposes that are merely using a hook in the markup. Creating invalid elements, or using the wrong attributes won't help, as there isn't a problem to solve.

    Posted by Gez on

Comments are closed for this entry.