Saturday, August 23, 2008

[.js] FormValidator v1.0

Hey folks!. I'm glad to announce that I finally finished my own version of a FormValidator for javascript. this is just a simple but well made class which is open to improvements.
the code comes well commented, but in case you have any doubt, please free to post it.

I'll post later some examples I've made using this class. hope you enjoy it. (it's not the most complete FormValidator on the web, but it's very easy to use and very functional.

I'll try to make some improvements to this class in the future so stay tuned for new versions.

By the way, at the moment, it supports simple callbacks after form has been validated. I think this'll help you to implement this code very easy without much changes to your original code.

another thing: this form uses the String.prototype.trim() function implementation posted before. so be sure to copy it and include it before including FormValidator:

<script language="javascript" type="text/javascript" src="trim.js"></script>
<script language="javascript" type="text/javascript" src="FormValidator.js"></script>


/////**** [mk]FORM VALIDATOR v1.0 ****\\\\\\

/////////////////////////////////////////////////
//by MasterKitano kitanosblog.blogspot.com 2008//
/////////////////////////////////////////////////

/*Use var myForm = new FormValidator("form"); to creat a new form validator, where "form" is your form id.
use myForm.addValidation(obj_id,val_type,message) to add a new validation.
obj_id : your object id to validate (your object most be inside the form).
val_type: type of validation-> null: checks if the value is empty
minlen: minimun value length (e.g "minlen=10")
maxlen: maximum value length (e.g "maxlen=10")
selected: (only for selects) checks if a option is selected (e.g. "selected=option_id")
nospaces: checks if value contains spaces (e.g. "nospaces")
alpha: checks if value contains only alphanumeric (letters and digits) (e.g. "alpha")
numbers: checks if value contains only numbers (e.g. "numbers")
mail: checks if value contains @, and a . after @.
message: the message that will be shown on the error messages window.
use myForm.addclearBtn("buton_id"); to automatically set a reset button.
use myForm.addSendBtn("buton_id",callback); to automatically set a send Button. this will perform validation, and if form is valid, then executes a callback to any function
use myForm.form.theElement or use myForm.form["element"] to access to any element in your form.
override myForm.prototype.displayErors() tho show the errors anyway yo want.

//HANDILNG ERROR MESSAGES
use myForm.invalid_form_msg ="error message"; to set default form error message.
use myForm.ERRORS_TAIL array to check all validation error messages.
use myForm.ERRORS_TAIL[index] to acces some specific message. (e.g. myForm.ERRORS_TAIL[0]);



*/
function FormValidator(form){
this.form = document.getElementById(form); //the handled form
this.invalid_form_msg = "data form error";
this.validation = true;
this.validationObjs = Array(); //objects to be validated
this.ERRORS_TAIL = Array(); //contains all error strings
this.addValidation = addValidation; //function to put a new validation on the validations tail
this.doValidation=doValidation; //checks al validations objects and confirms they're valid
this.addSendBtn = addSendBtn; //add send event to a button so we can send data (AJAX is supported) once is confirmed, second parameter defines a callback
this.displayErrors = displayErrors;//display the validation errors
this.clearData = clearData; //clears all the data information and restores it to the default
this.addClearBtn = addClearBtn; // add clear data event to a button so we can clear the form
}

function addValidation(obj_id,val_type,message){
var valid_exist = false;
if(message==null){
message = "unidentified error";
}
//make sure we create only one instance for every input object in the form
if(this[obj_id]==null){
this[obj_id]= new Object();
this[obj_id].elt = this.form[obj_id];
this.validationObjs.push(this[obj_id]); //add the object to the validations tail
this[obj_id].validations = Array(); //tail of validations to be performed to the object
this[obj_id].messages= Array(); //messages to be shown if validations didn't succeded

}
//make sure to have only one instance for every validation to be performed on the object
for(var i =0; i<this[obj_id].validations.length;i++){
var temp_value = this[obj_id].validations[i];
if(temp_value.indexOf("=")>=0){temp_value = temp_value.substr(0,temp_value.indexOf("="))}
var temp_value2 = val_type;
if(temp_value2.indexOf("=")>=0){temp_value2 = temp_value2.substr(0,temp_value2.indexOf("="))}
if(temp_value==temp_value2){
val_found=i;
valid_exist=true;
}
}
//create the validation instance only if it didn't existed before...
if(!valid_exist){
this[obj_id].validations.push(val_type);
this[obj_id].messages.push(message);
//or else, we just change the previos message to the newest (this can also be performed using attribute form.object.messages[validation number] = 'new message';
}else{
this[obj_id].validations[val_found]=val_type;
this[obj_id].messages[val_found]=message;
}
//alert(this[obj_id].validations);
}

function doValidation(){
this.validation = true;
//clear the errors tail;
this.ERRORS_TAIL = Array();
//START THE VALIDATION
for(var i=0; i<this.validationObjs.length;i++){
for(var j=0; j<this.validationObjs[i].validations.length;j++){
show_msg=false;
//CHECK IF INPUT OBJECTS VALUES ARE NULL OR UNCHECKED
if(this.validationObjs[i].validations[j] == "null"){
switch(this.validationObjs[i].elt.type){
case 'checkbox': case 'radio': if(!this.validationObjs[i].elt.checked){show_msg = true;}
break;
case 'password': case 'text': case 'textarea': if(this.validationObjs[i].elt.value==null || this.validationObjs[i].elt.value.trim().length<=0){show_msg = true};
break;
case 'select-one':if(!this.validationObjs[i].elt.value.trim()){show_msg = true};
break;

default :

//RADIO GROUPS
if(!this.validationObjs[i].elt.type && this.validationObjs[i].elt.length){
show_msg = true;
for(var x=0; x<this.validationObjs[i].elt.length;x++){
if(this.validationObjs[i].elt[x].checked){
show_msg=false;
}
}
}
break;
}
}
//CHECK INPUT OBJECTS VALUES MIN LENGTH
if(this.validationObjs[i].validations[j].substr(0,this.validationObjs[i].validations[j].indexOf("=")) == "minlen"){
var minlength = this.validationObjs[i].validations[j].substr(this.validationObjs[i].validations[j].indexOf("=")+1);
if(this.validationObjs[i].elt.value.trim().length<minlength){
show_msg = true;
}
}
//CHECK INPUT OBJECTS VALUES MAX LENGTH
if(this.validationObjs[i].validations[j].substr(0,this.validationObjs[i].validations[j].indexOf("=")) == "maxlen"){
var maxlength = this.validationObjs[i].validations[j].substr(this.validationObjs[i].validations[j].indexOf("=")+1);
if(this.validationObjs[i].elt.value.trim().length>maxlength){
show_msg = true;
}
}
//CHECK OPTION ON SELECT
if(this.validationObjs[i].validations[j].substr(0,this.validationObjs[i].validations[j].indexOf("=")) == "selected"){

var selected = this.validationObjs[i].validations[j].substr(this.validationObjs[i].validations[j].indexOf("=")+1);
if(this.validationObjs[i].elt[this.validationObjs[i].elt.selectedIndex].id==selected){
show_msg = true;
}
}
//CHECK INPUT OBJECTS WHITE SPACES
if(this.validationObjs[i].validations[j]== "nospaces"){
if(this.validationObjs[i].elt.value.trim().indexOf(" ")>=0){
show_msg = true;
}
}
//CHECK INPUT OBJECTS FOR NON ALPHANUMERIC CHARACTERS
if(this.validationObjs[i].validations[j]== "alpha"){
var string = this.validationObjs[i].elt.value.trim();
var regexp = /\W/;
var result = regexp.test(string);
if(result){
show_msg = true;
}
}
//CHECK INPUT OBJECTS FOR NON NUMBERS CHARACTERS
if(this.validationObjs[i].validations[j]== "numbers"){
var string = this.validationObjs[i].elt.value.trim();
var regexp = /\D/;
var result = regexp.test(string);
if(result){
show_msg = true;
}
}
//CHECK E-MAIL
if(this.validationObjs[i].validations[j]== "mail"){
var string = this.validationObjs[i].elt.value.trim();
var at = string.indexOf('@');
var dot = string.indexOf('.',at);
if(at>=0 && dot>at){
}else{
show_msg = true;
}

}
//IF ERROR HAPPENED THEN PUSH THE MESSAGE TO THE ERRORS TAIL
if(show_msg){
this.ERRORS_TAIL.push(this.validationObjs[i].messages[j]);
this.validation = false;
}
}
}
return this.validation;
}

function addSendBtn(btn,callback_function){
var send_button = this.form[btn];
send_button.parentObj = new Object();
send_button.parentObj = this;
send_button.onclick = function(){
var formValidation = this.parentObj.doValidation();
if(formValidation){
callback_function();
}else{
this.parentObj.displayErrors();
}
}
}
function addClearBtn(btn){
var clear_button = this.form[btn];
clear_button.parentObj = new Object();
clear_button.parentObj = this;
clear_button.onclick = function(){
this.parentObj.clearData();
}
}
function clearData(){
for(var i=0; i<this.form.length;i++){
switch(this.form[i].type){
case 'text': case 'password': case 'textarea': this.form[i].value = "";
break;
case 'radio': case 'checkbox': this.form[i].checked = false;
break;
case 'select-one': this.form[i][0].selected = true;
break;
}
}
}
function displayErrors(){
///MODIFY ONLY THIS PORTION OF THE CODE!
///THIS METHOD CAN BE OVERRIDED TO DISPLAY THE ERRORS THE WAY YOU WANT
var errors_msg = this.invalid_form_msg+"\n";
for(var i=0; i<this.ERRORS_TAIL.length;i++){
errors_msg+="\n-"+this.ERRORS_TAIL[i];
}
alert(errors_msg);
}

No comments: