function formChecker(form){
	this._form = $(form);
	this._rules = new Array();
	this._logicRules = new Array();
	this._errorMsgs = new Array();
	this._show1Error = true;
	this._validatorFunctions = new Object();
	this._validatorFunctions["zipcode"] = isValidZipCode;
	this._validatorFunctions["email"] = isValidEmail;
	this._logicFunctions = new Object();
	this._logicFunctions["onlyone"] = oneOnlyLogic; 
	this._logicFunctions["oneandonlyone"] = oneAndOnlyOneLogic;
	this._postValidationFunctions = new Array();
	this._preValidationFunctions = new Array();
	// "***" will be replaced with fieldName;
	this._fieldErrorMsg = "The *** field is not valid.";
	this._fieldReqMsg = "The *** field is required.";
	
	Event.observe(this._form,'submit',
				  function(e){if(!this.validate())Event.stop(e)}.bindAsEventListener(this) );
}

formChecker.prototype.setFieldErrorMsg = function(msg){
	this._fieldErrorMsg = msg;
};
formChecker.prototype.setFieldReqMsg = function(msg){
	this._fieldReqMsg = msg;
};
formChecker.prototype.addPostFunction = function(valFunction){
	this._postValidationFunctions[this._postValidationFunctions.length] = valFunction;
};
formChecker.prototype.addPreFunction = function(valFunction){
	this._preValidationFunctions[this._preValidationFunctions.length] = valFunction;
};
//set extra validatory functions - functions show take a string value and return a boolean
//error alerts message are not needed
formChecker.prototype.setValidatorFunction4Type = function(typeName,vFunction){
	this._validatorFunctions[typeName]= vFunction;
};
//set extra Logic validator functions - functions will take a array of arguments
//arg[0] will logic type, arg[2] will be error message 
formChecker.prototype.setLogicFunction4Rule = function(ruleType,vFunction){
	this._logicFunctions[typeName]= vFunction;
};
formChecker.prototype.addValidationRule = function(fieldname,vType,required,showName,CustomError){
	var newRule = this._rules.length;
	this._rules[newRule] = new Object();
	this._rules[newRule].fieldname = fieldname;
	this._rules[newRule].valType = vType;
	this._rules[newRule].required = required;
	//for now will not work with out name
	if (typeof showName == "undefined") {
		this._rules[newRule].useName = false;
		this._rules[newRule].useMsg = false;
	}else{
		this._rules[newRule].useName = true;
		this._rules[newRule].useMsg = false;
		this._rules[newRule].name = showName;
		if(!(typeof CustomError == "undefined") ){
			this._rules[newRule].useMsg = true;
			this._rules[newRule].msg = CustomError;   
  		}
   }
   
	
};
formChecker.prototype.setShow1Error = function(tf){
	this._show1Error = tf;
};
//add extra logic rule
//arg[0] string , logic rule type
//arg[2] string , error message
//remaining arguments will depend on function that validates logic rules
formChecker.prototype.addLogicRule = function(){
	this._logicRules.push(arguments);
};
formChecker.prototype.validate = function(){
	var value;
	var isValid;
	this._errorMsgs = new Array();
	for(var r = 0;r<this._rules.length;r++){
		isValid = this.isValid(this._rules[r]);
		if(this._show1Error && !isValid){
			this.showErrorMsg();
			return false;
		}
	}
	if(this._errorMsgs.length != 0){
		this.showErrorMsg();
		return false;
	}	
	if(!this.logicRulesOk()){
		return false;
	}
	if(!this.callValidateFunctions(this._postValidationFunctions)){
		return false;
	}
	return true;
	
};
formChecker.prototype.callValidateFunctions = function(funcArray){
	//calls a series of functions
	//returns false when the first one returns false
	//or returns true if all return true
	for(var f=0;f<funcArray.length;f++){
		if(!funcArray[f]()){
			return false;
		}
	}
	return true;
};
formChecker.prototype.logicRulesOk = function(){
	var ruleType = 0;
	var ruleMsg = 1;
	var ruleElements = 2;
	for(var l = 0;l<this._logicRules.length;l++){
		if(!this._logicFunctions[this._logicRules[l][ruleType]](this._logicRules[l])){
			alert(this._logicRules[l][ruleMsg]);
			return false;
		}
	}
	return true;
};
formChecker.prototype.showErrorMsg = function(){
		var errorMsg = "";
		for(var e = 0;e<this._errorMsgs.length;e++){
			if(e>0){
				errorMsg += ", ";
			}
			errorMsg += this._errorMsgs[e];
		}
		alert(errorMsg);
};
formChecker.prototype.isValid = function(rule){
	
	if(isEmptyField(rule.fieldname)){
		if(!rule.required){
			return true;
		}else{
			this._errorMsgs[this._errorMsgs.length] = this._fieldReqMsg.replace("***",rule.name);
			return false;
		}
	}
	
	if(rule.valType == "any"){
		return true;
	}
	var value = $F(rule.fieldname);
	if(!this._validatorFunctions[rule.valType](value)){
		if(rule.useMsg){
			this._errorMsgs[this._errorMsgs.length] = rule.msg;
		}else{
			this._errorMsgs[this._errorMsgs.length] = this._fieldErrorMsg.replace("***",rule.name);
		}
		return false;
	}
	return true;
	
}
function oneOnlyLogic(rule,needOne){
	var ruleMsg = 1;
	var ruleElements = 2;
	var found1 = false;
	for(var e = 0;e<rule[ruleElements].length;e++){
		if(!isEmptyField(rule[ruleElements][e])){
			if(found1){
				return false;
			}
			found1 = true;
		}
	}
	if(needOne == true && !found1){
		return false;
	}
	return true;
}
function oneAndOnlyOneLogic(rule){
	return oneOnlyLogic(rule,true);
	
}
function isEmptyField(fieldName){
	if($F(fieldName).empty())
		return true;
	if($(fieldName).type == "select-one"){
		if($(fieldName).selectedIndex == 0 && ["Any","Choose"].indexOf($(fieldName).options[$(fieldName).selectedIndex].text) != -1){
			return true;
		}
	}
	return false;
};
function isValidZipCode(string){
	return (string.search(/(^\d{5}$)|(^\d{5}-\d{4}$)/) == 0);
}
function isValidEmail(str) {
			
	var at="@"
	var dot="."
	var lat=str.indexOf(at)
	var lstr=str.length
	var ldot=str.indexOf(dot)
	if (str.indexOf(at)==-1){
		  return false;
	}

	if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){
	   return false;
	}

	if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){
		return false;
	}

	 if (str.indexOf(at,(lat+1))!=-1){
		return false;
	 }

	 if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){
		return false;
	 }

	 if (str.indexOf(dot,(lat+2))==-1){
		return false;
	 }
	
	 if (str.indexOf(" ")!=-1){
		return false;
	 }

	 return true;					
}
