//Form validator
//by oechai, oechai@gmail.com


//CLASS :: formValidator :: a form object class
var formValidator = function (oFormName){
	//to get form object
	this.oForm = document.forms[oFormName];
	//to ensure the form object is assigned
	if ( !this.oForm ){
		alert("Could not get form object : "+oFormName);
	}
	
	this.oForm.onsubmit = formSubmitHandler; 	//to submit form handler.
	this.addValidate = formAddValidate; 		//to add input to the setting memory.
	this.oForm.onreset = formClrValidate; 		//to retreive the input from the setting memory.
	//this.setXtraValidate = formSetXtraValidate; //to add extra validation function.
}

//submit form handler.
function formSubmitHandler(){
	//alert(this.elements[4].setValidate)
	//alert(this.elements[4].setValidate.validate())
	for ( itm=0; itm < this.elements.length; itm++ ){
		//alert(this.elements[itm].length)
		//alert(	"itm : "+itm+ ", " + this.elements[itm].setValidate.validate() );
		//is object.elements[itr].validateSetting available or null ?
		//is object.elements[itr].validateSetting.validate return true or false ?
		
		if ( this.elements[itm].setValidate && 
			!this.elements[itm].setValidate.validate() )
		{	
			
			return false;
		}
	}
	return true;
}
//add the form validation at here
function formAddValidate(itemName, command, errmsg){
	//ensure the Form and form elements status
	if (!this.oForm) alert("Could not get form object.");
	//form's items assigned
	var oItem = this.oForm[itemName];
	if (!oItem){
		alert("Could not find item named : "+ itemName);
		return; //force to end this function;
	}
	//assigned input storage to oItem
	if (!oItem.setValidate){
		oItem.setValidate = new formSetValidate(oItem);
	}
	//add the commands and value into the settings
	oItem.setValidate.add(command, errmsg);
	//----alert(a+":"+oItem.name+':'+oItem.setValidate.validSet.length);
}
//clear the form validation
function formClrValidate(){
	for ( itm=0; itm< this.oForm.elements.length; itm ++ ){
		//temporary only
		this.oForm.elements[itm].setValidate = null;
	}
}

//CLASS :: input settings memory 
var formSetValidate = function (oItem){
	this.validSet = new Array();		//storing the setting into array according to name;
	this.add = addingCmdValidate;		//add command or setting function
	this.validate = settingValidate; 	//validate the settings
	this.oItem = oItem;					//input form OBJECT
	
	//params' value obtain from this.add as input by user.
	function addingCmdValidate(cmd, error){
		//storing the setting in array.
		//in which ...
		//----alert('1 : '+this.oItem.name+' : '+this.validSet.length);
		this.validSet[this.validSet.length] = new cmdValidate(this.oItem, cmd, error);
		//alert(this.validSet.length+' -  '+this.oItem.name + ": adding command - \'"+cmd+"\', "+ error);
	}
	//validate function for formSetValidate Class
	function settingValidate(){
		for ( vset=0; vset<this.validSet.length; vset++ ){
			//if (this.validSet[vset].validate()==true){ abc=true; }
			//if (this.validSet[vset].validate()==false){ abc=false; }
			//----alert('2 : '+ this.oItem.name + ', '+ vset  +', this.validSet.length : '+this.validSet.length);
			if(!this.validSet[vset].validate()){
				return false;
			}
		}
		return true;
	}
	
	//CLASS :: commands validation : obtain passed input to
	//validate
	var cmdValidate = function (inputItem, cmd, error){
		this.command = cmd;					//the command / setting
		this.error = error;					//the error message
		this.oInputItem = inputItem;		//pass the form object
		this.validate = validateCmd; 		//function to pass setting or command to core validator.
		//function to pass input to core validator.
		function validateCmd(){
			if ( !dataValidate(this.oInputItem, this.command,this.error) ){
				this.oInputItem.focus();
				return false;
			}
			return true;
		}
	}
}
//main core for input validation
function dataValidate(oItem, cmd, errmsg){
	var equalsign_position = cmd.search('=');
	var command = '';
	var command_init = '';
	if (equalsign_position >=0){
		command = cmd.substring(0,equalsign_position);
		command_init = cmd.substring(equalsign_position+1);
	}else command = cmd;
	var command_str = new Array();
	command_str[0] = "required";
	command_str[1] = "maxlength";
	command_str[2] = "minlength";
	command_str[3] = "alphabetic";
	command_str[4] = "numberic";
	command_str[5] = "alphanumberic";
	command_str[6] = "alphanumhyphen";
	command_str[7] = "email";
	command_str[8] = "lessthan"; //lt
	command_str[9] = "greaterthan"; //gt
	command_str[10] = "regexp"; //invalid character
	command_str[11] = "dontselect";
	
	var command_respon = new Array();
	command_respon[0] = respon_req;
	command_respon[1] = respon_maxlen;
	command_respon[2] = respon_minlen;
	command_respon[3] = respon_alphabet;
	command_respon[4] = respon_number;
	command_respon[5] = respon_alphenum;
	command_respon[6] = respon_alphenumhyphen;
	command_respon[7] = respon_email;
	command_respon[8] = respon_lt;
	command_respon[9] = respon_gt;
	command_respon[10] = respon_regexp;
	command_respon[11] = respon_dunselect;
	
	//default error message;
	var command_respon_error = new Array();
	command_respon_error[0] = oItem.name + " : required to fill.";
	command_respon_error[1] = oItem.name + " : maximum character(s) allowed : " +command_init;
	command_respon_error[2] = oItem.name + " : minimum character(s) allowed : " +command_init;
	command_respon_error[3] = oItem.name + " : only [ a-z, A-Z ] character(s) allowed";
	command_respon_error[4] = oItem.name + " : only [ 0-9 ] character(s) allowed";
	command_respon_error[5] = oItem.name + " : only [ a-z, A-Z, 0-9 ] character(s) allowed";
	command_respon_error[6] = oItem.name + " : only [ a-z, A-Z, 0-9, -, _ ] character(s) allowed";
	command_respon_error[7] = oItem.name + " : contained error(s)";
	command_respon_error[8] = oItem.name + " : value should be less than " +command_init;
	command_respon_error[9] = oItem.name + " : value should be greater than " +command_init;
	command_respon_error[10] = oItem.name + " : invalid character(s) found";
	command_respon_error[11] = oItem.name + " : Please select one option";
	
	
//	alert(command_respon[0]());
	function respon_req(){
		//using length of the value's length return by OBJECT as condition
		//alert("in respon_req");
		if (!oItem.value || oItem.value.length == 0){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[0];
			}
			alert (errmsg);
			return false;
		}
	}//respon_req - [0]
	function respon_maxlen(){
		// more than maxtlength
		if (oItem.value.length > eval(command_init)){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[1];
			}
			alert (errmsg);
			return false;
		}
	}//respon_maxlen - [1]
	function respon_minlen(){
		// less than minlength
		if (oItem.value.length < eval(command_init)){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[2];
			}
			alert (errmsg);
			return false;
		}
	}//respon_minlen - [2]
	function respon_alphabet(){
		//search for exclusion == error input position
		var searchCharPos = oItem.value.search("[^a-zA-Z/ ]");
		if (!oItem.value) {
			alert(oItem.name+ " : value not set");
			return false;
		}
		if (oItem.value.length > 0 && searchCharPos >= 0){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[3];
			}
			alert(errmsg+ "\n [Error found at "  +eval(searchCharPos+1)+ " ]");
			return false;
		}
	}//respon_alphabet - [3]
	function  respon_number(){
		//alert("in respon_number...")
		// [\d] == [^0-9]
		var searchCharPos = oItem.value.search("[^0-9]");
		if (oItem.value.length > 0 && searchCharPos >= 0){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[4];
			}
			alert(errmsg+ "\n [Error found at "  +eval(searchCharPos+1)+ " ]"); 
			
			return false;
		}
	}//respon_number - [4]
	function respon_alphenum(){
		//alert("in respon_alphenum");
		var searchCharPos = oItem.value.search("[^a-zA-Z0-9]");
		if (oItem.value.length > 0 && searchCharPos >= 0){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[5];
			}
			alert(errmsg+ "\n [Error found at "  +eval(searchCharPos+1)+ " ]"); 
			return false;
		}
	}//respon_alphenum - [5]
	function respon_alphenumhyphen(){
		//alert("in respon_alphenumhyphen");
		var searchCharPos = oItem.value.search("[^a-zA-Z0-9\-\_]");
		if (oItem.value.length > 0 && searchCharPos >= 0){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[6];
			}
			alert(errmsg+ "\n [Error found at "  +eval(searchCharPos+1)+ " ]"); 
			return false;
		}
	}//respon_alphenumhyphen - [6]
	function respon_email(){
		if (!emailValidate(oItem.value)){
			return false;
		}
	}//respon_email - [7]
	function respon_lt(){
		if (isNaN(oItem.value)){
			alert(oItem.name +": should be a number");
		}
		if (eval(oItem.value) >= eval(command_init)){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[8];
			}
			alert(errmsg);
			return false;
		}
	}//respon_lt - [8]
	function respon_gt(){
		if (isNaN(oItem.value)){
			alert(oItem.name +": should be a numer");
		}
		if (eval(oItem.value) <= eval(command_init)){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[9];
			}
			alert(errmsg);
			return false;
		}
	}//respon_gt - [9]
	function respon_regexp(){
		if (oItem.value.length > 0){
			if (!oItem.value.match(command_init)){
				if (!errmsg || errmsg.length == 0){
					errmsg = command_respon_error[10];
				}
				alert(errmsg);
				return false;
			}
		}
	}//respon_regexp - [10]
	function respon_dunselect(){
		//alert("in respon_dunselect");
		if (oItem.selectedIndex == null){
			alert ("dontselect for non-select item");
			return false;
		}
		if (oItem.selectedIndex == command_init){
			if (!errmsg || errmsg.length == 0){
				errmsg = command_respon_error[11];
			}
			alert(errmsg);
			return false;
		}
	}//respon_dunselct - [11]
	
	//for (oo=0; oo<oItem[oItem.name].elements.length; oo++){
	//	alert(oItem.value)
	//}
	for ( ss=0; ss<command_str.length; ss++ ){
		if (command_str[ss] == command){
			if(command_respon[ss]()==false){
				return false;
			}else{ return true; }
		}
	}
}


function emailValidate(emailAdd){
	var emailAddress = emailAdd;
	if(emailAddress.length <= 0){
		alert("Please enter your email.");
		return false;
	}
	var charMatch = emailAddress.match("^(.+)@(.+)$");
	if(charMatch == null){
		alert("Invalid email address found.");
		return false;
	}
	
	username = charMatch[1];
	domain = charMatch[2];
	
	var invalid_username_regexp = /^\"?[\w-_\.]*\"?$/;
	var invalid_domain_regexp = /^[\w-\.]*\.[A-Za-z]{2,4}$/;
	var ip_regexp = /^\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]$/
	if(username!=null){
		if(username.match(invalid_username_regexp)==null) return false;
	}
	
	if(domain!=null){
		if(domain.match(invalid_username_regexp)==null){
			if(domain.match(ip_regexp)==null) return false;
		}
		return true;
	}
}

/*//////////////////////////////////////////////
\n		- new line
\t		- tab
\(char) - A literal (character), eg. \* represents *

[abc]		- a,b,c
[abc/*] 	- a,b,c,*
[a-zA-Z] 	- a-z, A-Z

[^abc] 		- exclude a,b,c

\w		= [a-zA-Z0-9]
\W		= [^\w]
\d		= [0-9]
\D		= [^\d]

{n,m}	= match between n&m times
{n,}	= match at least n times
{n}		= match exactly n times

^	- match with start of text
$	- match with end of text

*///////////////////////////////////////////////
