XHTML form validation library
Posted: Sat Aug 19, 2006 4:38 pm
a couple years back I wrote a small little javascript library which validated form elements based on known types and custom regex...
I'll post the source code at the end of this message
Anyways, it was quite clever I thought as it didn't require a lot of Javascript to get the thing going...
Basically, you called a function inside onsubmit() and the function traversed the FORM looking for INPUT's and such...
Each INPUT used custom attributes to actually store the validation information...
For example, if one input was an email, you might (off the top of my head) do somehting like:
The library had some built in types, email being one of them...and the javascript would test the input email against a regex and display an error if the email wasn't formatted correctly...
You could also customize the warning message or do things like, indicate whether "that" field was required or optional by specifing attrbutes such as:
The reason I liked this approach was that it was highly customizable and easy to integrate intop existing forms. Also the big plus for me, was the fact I used it in multiple language applications, so there was no need to provide multiple language packs with the library as that information could be provided by the client programmer...
Anyways, it was has come to my attention lately, that may (probably does) cause validation to fail...which is a bummer as it's IMHO the best approach to client side validation...but I digress...
I've also, noticed a trend and started doing it myself...moving away from client side and server side validation, instead just going with server side possibly using AJAX on the client side to validate before continuing a trip to the server...
At one time I had a neat little popup calendar control and a TEXTAREA which could restrict to certain number of characters, but I seem to have lost those...
Right now I've started development of a cross browser WYSIWYG editor, looking at TinyMCE & FckEditor and a couple commercial ones which I bought...also going on experience I've gained over the years from HtmlArea...
The it stricts me, wouldn't it be neat to have a library which you could use, which hijacked normal controls and turned them into powered-up versions? Date picker, WYSIWYG, restricted TEXTAREA w/ counter, email, etc...
By providing an input mask you could limit the type of characters one would enter, much like advanced Windows textboxes...thus not validating, by forcing a format if browser is cvapable and displying those warning messages on the sever side only if people cheat or have JS turned off...
I'd like to hear you thoughts on the implications of input filtering though...indeed it's not very common in web apps, yet...and I'm not sure it's possible in all browsers...but I think in most you can capture and cancel onkeyup/onkeydown which I think is all you need to implement input masking...
If you have any ideas on how to implement such a library...I'd be interested in hearing them...
I think something like this would be nice addition to a programmers toolkit...especially if someone took it and included it to a CSS powered FORM class which generated valid XHTML forms...
Anyways, here's the code from library I refered to:
I've removed as much comments as possible for the sake of brevity
Don't ask about use, as I don't plan on supporting it, just use it for ideas, etc...
I'll post the source code at the end of this message
Anyways, it was quite clever I thought as it didn't require a lot of Javascript to get the thing going...
Basically, you called a function inside onsubmit() and the function traversed the FORM looking for INPUT's and such...
Each INPUT used custom attributes to actually store the validation information...
For example, if one input was an email, you might (off the top of my head) do somehting like:
Code: Select all
<input type="input" size="30" validateas="email" maxlength="255" />
You could also customize the warning message or do things like, indicate whether "that" field was required or optional by specifing attrbutes such as:
Code: Select all
required="true"
requiredmessage="Email address is a required field"
invalidmessage="Email is not a valid address, please try again"
Anyways, it was has come to my attention lately, that may (probably does) cause validation to fail...which is a bummer as it's IMHO the best approach to client side validation...but I digress...
I've also, noticed a trend and started doing it myself...moving away from client side and server side validation, instead just going with server side possibly using AJAX on the client side to validate before continuing a trip to the server...
At one time I had a neat little popup calendar control and a TEXTAREA which could restrict to certain number of characters, but I seem to have lost those...
Right now I've started development of a cross browser WYSIWYG editor, looking at TinyMCE & FckEditor and a couple commercial ones which I bought...also going on experience I've gained over the years from HtmlArea...
The it stricts me, wouldn't it be neat to have a library which you could use, which hijacked normal controls and turned them into powered-up versions? Date picker, WYSIWYG, restricted TEXTAREA w/ counter, email, etc...
By providing an input mask you could limit the type of characters one would enter, much like advanced Windows textboxes...thus not validating, by forcing a format if browser is cvapable and displying those warning messages on the sever side only if people cheat or have JS turned off...
I'd like to hear you thoughts on the implications of input filtering though...indeed it's not very common in web apps, yet...and I'm not sure it's possible in all browsers...but I think in most you can capture and cancel onkeyup/onkeydown which I think is all you need to implement input masking...
If you have any ideas on how to implement such a library...I'd be interested in hearing them...
I think something like this would be nice addition to a programmers toolkit...especially if someone took it and included it to a CSS powered FORM class which generated valid XHTML forms...
Anyways, here's the code from library I refered to:
I've removed as much comments as possible for the sake of brevity
Code: Select all
var _swift_validator_hash = new Array();
// Built in types
_swift_validator_hash['file'] = /^[\w\-\. ]+$/i;
_swift_validator_hash['folder'] = /^[\w\- ]+$/i;
_swift_validator_hash['alpha'] = "^[a-zA-Z0-9]+";
_swift_validator_hash['email'] = "^[-_a-zA-Z0-9]+@[-_a-zA-Z0-9]+\.(au|jp|org|net|com|ca)";
_swift_validator_hash['postal'] = "^[a-zA-Z][0-9][a-zA-Z] ?[0-9][a-zA-Z][0-9]";
function swift_form_validate(frmObj)
{
if(frmObj.tagName.toLowerCase() != "form") return false;
var el = frmObj.elements;
for(i=0; i<el.length; i++){
var elObj = el[i];
var elTag = elObj.tagName.toLowerCase();
var elType = elObj.type.toLowerCase();
//
// Initialize validation attributes
var strValidateAs = elObj.getAttribute("validateas") || null;
// Client supplied messages
var strRequired = elObj.getAttribute("requiredmessage") || null;
var strInvalid = elObj.getAttribute("invalidmessage") || null;
var strDefault = elObj.getAttribute("default") || null;
var bRequired = elObj.getAttribute("required") || null;
var nMaxCheck = elObj.getAttribute("maxcheck") || null; // SELECT
var nMinCheck = elObj.getAttribute("mincheck") || null;
var nMaxValue = elObj.getAttribute("maxvalue") || null;
var nMinValue = elObj.getAttribute("minvalue") || null;
var nMaxlength = elObj.getAttribute("maxlength") || null;
var nMinLength = elObj.getAttribute("minlength") || null;
// Doesn't work because FILE relies on file extensions, not named hash elements
//if(strValidateAs == null || strValidateAs == "" || strValidateAs.length == 0)
// strValidateAs = elObj.getAttribute("name");
//
// Handle each FORM tag
switch(elTag){
case "input":
switch(elType){
case "password":
case "text":
if(bRequired && elObj.value.length<=0){
elObj.value = (strDefault==null?"":strDefault);
elObj.focus();
elObj.select();
// Display warning about missing field info
if(strRequired!=null)
alert(strRequired);
else
alert(strValidateAs+" - Error Code: 0001");
return false;
}
if(_swift_validator_hash[strValidateAs] == undefined) continue;
var re = new RegExp(_swift_validator_hash[strValidateAs]);
var valid = re.test(elObj.value);
var bLength = _swift_checkLength(elObj.value.length, nMinLength, nMaxlength);
var bValue = _swift_checkLength(elObj.value, nMinValue, nMaxValue);
var bChecked = (bLength && bValue);
if((!valid && elObj.value.length>0) || !bChecked){
elObj.focus();
elObj.select();
if(strInvalid!=null)
alert(strInvalid);
else // Only in DEBUG mode???
alert(strValidateAs+" - Error Code: 0002");
return false; // Prevent FORM from submitting
}
break;
case "checkbox":
var optName = el[i].name;
var count = 0;
while(1){
var optNext = el[i+1].name;
var elTmp = el[i];
if(elTmp.checked) count++;
if(optNext != optName) break;
i = i + 1;
}
if(!_swift_checkLength(count, nMinCheck, nMaxCheck)){
elObj.focus();
if(strRequired!=null)
alert(strRequired);
else
alert(strValidateAs+" - Error Code: 0001");
return false; // Prevent FORM from submitting
}
break;
case "radio":
break;
case "submit": // Fall through
case "reset":
case "hidden":
case "image":
case "button":
break;
case "file":
if(bRequired && elObj.value.length<=0){
elObj.focus();
if(strRequired!=null)
alert(strRequired);
else
alert(strValidateAs+" - Error Code: 0001");
return false; // Prevent FORM from submitting
}
if(strValidateAs==null) continue;
var file_name = elObj.value;
var file_type = ""; // Holds the file type (jpg, bmp, etc...)
var valid_ext = new Array();
valid_ext = strValidateAs.split(',');
file_type = file_name.substr(file_name.lastIndexOf(".")+1, file_name.length);
var bValid = false; // File isn't valid by default
for(k=0; k<valid_ext.length; k++){
// File extension found - it's assumed safe
if(valid_ext[k].toLowerCase() == file_type.toLowerCase()){
bValid = true;
break;
}
}
if(!bValid){
elObj.focus();
elObj.select();
// Display warning about missing field info
if(strInvalid!=null)
alert(strInvalid);
else
alert(strValidateAs+" - Error Code: 0001");
return false; // Prevent FORM from submitting
}
break;
default:
alert(elType+": Not supported!!!");
}
break;
case "select":
if(elType != "select-one"){
var num_options = elObj.options.length;
var count = 0;
for(j=0; j<num_options; j++){
if(elObj.options[j].selected)
count++;
}
if(!_swift_checkLength(count, nMinCheck, nMaxCheck)){
elObj.focus();
// Display warning about missing field info
if(strRequired!=null)
alert(strRequired);
else
alert(strValidateAs+" - Error Code: 0001");
return false; // Prevent FORM from submitting
}
}
else{
if(nMinValue!=null){
if(nMaxValue==null) nMaxValue = 4294967296;
if(!_swift_checkLength(elObj.options[elObj.selectedIndex].value, nMinValue, nMaxValue)){
elObj.focus();
if(strRequired!=null)
alert(strRequired);
else
alert(strValidateAs+" - Error Code: 0001");
return false; // Prevent FORM from submitting
}
}
}
break;
case "textarea":
break;
}
}
return true;
}
function _swift_checkLength(nLength, nMin, nMax)
{
var gt = false; // Length still in boundry by default
var lt = false;
nLength = parseInt(nLength);
nMin = parseInt(nMin);
nMax = parseInt(nMax);
if(nMin != null && nLength < nMin) lt = true;
if(nMax != null && nLength > nMax) gt = true;
return !(lt || gt);
}