The author does not accept responsibility for any effects, adverse or otherwise, that this code may have on you, your computer, your sanity, your dog, and anything else that you can think of. Use it at your own risk. (Deja Vu? I also love the Allegro disclaimer).
Quick and Dirty Tour
So you don't like to read long articles or you don't have time for it, then just download the source files, run the demo HTML files on your preferred browser.
Building cross-browser masks and validating data aren't simple tasks. And there isn't a definitive solution for this topic, but we can, with some assumptions, come up with a feasible solution. Before getting into the code, let's revisit some keywords:
- Max Size: Do not allow infinite data entry on the UI fields.
- Events: The most difficult cross-browser topic. We'll discuss the differences of keyPress x keyDown events on major browsers for masks purposes.
- Masks: Do not allow the user to enter incompatible data into textboxes, like “ABC” in number-only fields.
- Smart Masks: Do not allow the user to enter invalid data into textboxes, like “99:99” in a time field.
- Validation: There are some data types that would be impractical to check as the user types, so the system checks the entire input set for inconsistencies on the forms submit event.
- Cross-Browsing (not breaking on other browsers): The system should run on any major browser seamlessly.
Basics (or Talking is Cheap...)
Let's start with the page that will have some data entry fields ready to be filled. The validationDemo.htm page will look like the image below:
Not much of a beautiful page, but it will help us to test our strategy. Let’s take a look at its HTML code:
F1 number(3)<input ai_name="myNumber" type="text" ai_block="search">
F2 number(3,2) <input id="number3point2" type="text" ai_block="search" />
In the demo, we have two distinct blocks that should be validated separately. The next thing to do is to create an uncoupled way of configuring our pages. For complex systems, we could build an XML file for every page that needs validation, but for our small demo, let's build a single XML file (validationDemo.xml).
<field name="myNumber" block="search|insert" personality="number"
precision="3,0" required="true" />
<field id="number3point2" block="search" personality="number" precision="3,2" />
<field id="date" block="search" personality="date" />
The XML is almost self-explanatory, as it only specifies each field behavior. For instance, the
number3point2 text field should allow 3 digits before the decimal point; and 2 after and the
date field should allow (guess what) only dates. We have two distinct ways of finding elements on pages: by
ID and by
NAME. If you have a single element that does not repeat its behavior through different blocks of the UI, the
ID is your choice. Now take a look at the F1 and F7 fields of our page. They behave the same way and are present in different blocks of the page. In this case, we set its configuration by
NAME, so we do not duplicate the XML tags, we just inform that the element is present on “search” and “insert” blocks. The
NAME attribute does NOT map to the HTML
NAME attribute, for reasons far beyond the scope of this article.
Smart masks, as I conceive, should come in pairs: one real-time filter mask and a post-validation companion function. Our little Framework has some mask ready to use and to serve as an example.
All mask functions can be attached to the
pageValidator dynamically during the setup, without generating errors, even if you need it. We accomplish that by having an array of masks inside the
pageValidator and testing for the existence of a particular mask before using it.
case 'time' :
mask = "TimeMask";
if( mask != null )
if( pageValidator.Masks[mask] != null )
oSrcElement.onkeypress = pageValidator.Masks[mask];
Since it is an advanced feature, let’s keep walking for the last act of our show, the validation of the input.
Validation (or Trust, but Check)
By now, we have only one more step to go: validation of the inputs. This step is performed when the user clicks on the Validate button and it triggers the validation of the block specified as a parameter, as in your test page:
<input type="submit" value="Validate Search" id="Submit2"
onclick="return pageValidator.IsValidForm('frmPage', 'search');" />
You must pass the form to be validated. The section if omitted will be all by default, where the entire form would be validated. Since each page object has its intelligence within, the
IsValidForm function will only check the integrity of those rules, applying an "exception" CSS class to the element with problems.
The "]>" Characters vs. XHTML Validation
A few comments about the
]> characters follows: 'till the present time, no browser is compliant with the custom DTD used in the demo page, despite the fact it is complete valid XHTML page (using the W3C validation). This means that your page will show the
]> characters if you use this approach. Another way to get a valid XHTML page is by creating a custom DTD, by downloading the W3C DTD file and adding your rules. It seems that it should be avoided at all costs, but we have few options these days.
If page validation is no concern for you yet, you may safely remove the custom block from the HTML
DOCTYPE TAG and be happy!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
And that’s it for the simple-but-effective abstraction layer! As you could see, it’s very simple to use, so it can be applied easily on small or mid sized Web systems. Its inner works may not be simple or easy to understand at first because of the complex divergences of major browsers. All the code presented is free of copyrights and may be used freely as long as you maintain the references to its authors.
The best resources you could find:
- 07-27-2006: Original article
- 08-02-2006: Changed function
_GetElementsByAttribute(aName, aValue, tName) in events.js (lines 117-118) file to accommodate some Opera issues related to
null objects. Thanks to cowdart who brought my attention to this issue.
- 11-14-2006: Simplified the article, focused on the use rather than inner works
- 11-16-2006: Added a UML model (jude community software) to help localize methods and classes