/*proven js patterns
Name: pattern=/^([a-zA-Z\.\'\,\s\-]+)$/;
Numeric/CC Number: pattern=/^\d{16}$/;
U.S. Zip: pattern=/^\d{5}([\-]\d{4})?$/;
*/
function FormValidator(frm,/*optional object*/params)  {
	//INITIALIZE THE BASIC REQUIRED VARIABLES
	this.arr_errors=new Array();
	this.arr_passwords=new Array();
	this.requiredFields=new Array();
	this.regExFields=new Array();
	this.arrCounter=0;
	this.temp="";
	this.pattern="";
	this.error=false;
	this.formEl=null;
	this.useLabels=false;
	this.labelPrefix="lbl_";
	this.labelColor="#FF0000";
	this.originalLabelColor="#000000";
	_this=this;
	if (!params || typeof(params)!="object"){
		this.form=frm;
		document.getElementById(this.form).onsubmit="return this.validate;";
		this.validateClass="required";
		this.divEl="displayDiv";
		this.hiddenRequired="requiredFields";
		this.hiddenClass="required";
		this.returnClassNames=true;
		this.hiddenAttribute="attributeInput";
		this.attribute="format";
		this.returnAttNames=true;
		this.nameField="name";
		this.submitDisplay="";
		this.submitDisplayMessage="";
	}
	else if(params && typeof(params)=="object"){
		this.form=frm;
		document.getElementById(this.form).onsubmit="return this.validate;";
		this.validateClass=params.validateClass || "required";
		this.divEl=params.divEl || "displayDiv";
		this.hiddenRequired=params.hiddenRequired || "requiredFields";
		this.hiddenClass=params.hiddenClass || "required";
		this.returnClassNames=params.returnClassNames || false;
		this.hiddenAttribute=params.hiddenAttribute || "attributeInput";
		this.attribute=params.attribute || "validate";
		this.returnAttNames=params.returnAttNames || true;
		this.nameField=params.nameField || "name";
		this.useLabels=params.useLabels || false;
		this.labelPrefix=params.labelPrefix || "lbl_";
		this.labelColor=params.labelColor || "#FF0000";
		this.originalLabelColor=params.originalLabelColor || "#000000";
		this.submitDisplay=params.submitButton || "";
		this.submitDisplayMessage=params.submitButtonMessage || "";
	}
	else{
		throw new Error("FormValidator class cannot be instantiated with the information supplied");
		this.error=true;
	}
	
	if (!document.forms[this.form]){
		throw new Error("Form with id of " + this.form + " not found in document.");
		this.error=true;
		return false;
	}
	if(document.forms[this.form].elements.length==0){
		throw new Error("Form with id of " + this.form + " appears to have no elements to validate.");
		this.error=true;
		return false;
	}
	
	if(!this.error){
		this.formEl=document.forms[this.form];
		for(var i=0; i<this.formEl.elements.length; i++){
			if(this.formEl.elements[i].getAttribute(this.validateClass)){
				this.requiredFields.push(this.formEl.elements[i]);
			}
			if(this.formEl.elements[i].getAttribute(this.attribute)){
				this.regExFields.push(this.formEl.elements[i]);
			}
		}
	}
	//IF EVERYTHING IS OK, FILL THE 2 HIDDEN FIELDS && add validate to the form onsubmit
	//formInit(this.hiddenRequired,this.hiddenClass,this.returnClassNames,this.hiddenAttribute,this.attribute,this.returnAttNames);
	this.formEl.onsubmit = function(){ return _this.validate(); };


	this.validate=function(){
		formInit(this.hiddenRequired,this.hiddenClass,this.returnClassNames,this.hiddenAttribute,this.attribute,this.returnAttNames);
		//grab all the form elements	
		for(var i=0; i<this.formEl.elements.length; i++){
			if(this.formEl.elements[i].value!="" && this.formEl.elements[i].type=="text" || this.formEl.elements[i].type=="textarea" || this.formEl.elements[i].type=="password"){
				this.formEl.elements[i].value=this.formEl.elements[i].value.trim();
			}
			//check for blank text boxes and textareas
			if ((this.formEl.elements[i].type=="text" || this.formEl.elements[i].type=="textarea") && this.formEl.elements[i].getAttribute(this.validateClass)){
				if (this.formEl.elements[i].value=="") {
					if(this.useLabels==true){
						document.getElementById(this.labelPrefix+this.formEl.elements[i].id).style.color=this.labelColor;
						document.getElementById(this.labelPrefix+this.formEl.elements[i].id).style.fontWeight="bold";
						this.arr_errors[this.arrCounter++]=this.formEl.elements[i];
					}
					else{
						this.temp=this.formEl.elements[i].id;
						while(this.temp.indexOf("_")!=-1){
							this.temp=this.temp.replace("_", " ");
						}
						this.arr_errors[this.arrCounter++]=this.temp.toProperCase();
					}
				}
				else if(this.useLabels==true){
					if(rgbToHex(document.getElementById(this.labelPrefix+this.formEl.elements[i].id).style.color).toString()==this.labelColor){
						document.getElementById(this.labelPrefix+this.formEl.elements[i].id).style.color="";
						document.getElementById(this.labelPrefix+this.formEl.elements[i].id).style.fontWeight="";
					}
				}
			}
			//check for blank select boxes
			else if(this.formEl.elements[i].type=="select-one" && this.formEl.elements[i].getAttribute(this.validateClass)){
				if(this.formEl.elements[i].selectedIndex==0){
					temp=this.formEl.elements[i].id;
					while(temp.indexOf("_")!=-1){
						temp=temp.replace("_", " ");
					}
					this.arr_errors[this.arrCounter++]=temp.toProperCase();
				}
			}
			//check for blank or non-matching password fields
			else if (this.formEl.elements[i].type=="password" && this.formEl.elements[i].getAttribute(this.validateClass)){
				if(this.arr_passwords.length==1){
					if(this.formEl.elements[i].value==""){
						this.temp=this.formEl.elements[i].id;
						while(this.temp.indexOf("_")!=-1){
							this.temp=this.temp.replace("_", " ");
						}
						this.arr_errors[this.arrCounter++]=this.temp.toProperCase();
						this.arr_errors[this.arrCounter++]="Passwords do not match";
					}
					else if(this.arr_passwords[0]!=this.formEl.elements[i].value){
						this.arr_errors[this.arrCounter++]="Passwords do not match";
					}
				}
				else{
					if(this.formEl.elements[i].value==""){
						this.temp=this.formEl.elements[i].id;
						while(this.temp.indexOf("_")!=-1){
							this.temp=this.temp.replace("_", " ");
						}
						this.arr_errors[this.arrCounter++]=this.temp.toProperCase();
					}
					else{
						this.arr_passwords[0]=this.formEl.elements[i].value;
					}
				}
			}
		}
		//SEND THE FORM OVER TO SERVER SCRIPT, OR REPORT ERRORS
		if (this.arr_errors.length==0){
			return true;
		}
		else{
			if(this.useLabels==false){
				document.location.href="#errs";
				displayError(this.arr_errors, this.divEl);
				this.arr_errors=new Array();
				this.arr_passwords=new Array();
				this.requiredFields=new Array();
				this.regExFields=new Array();
				this.arrCounter=0;
				this.temp="";
				this.pattern="";
				this.error=false;
				return false;
			}
			else{
				document.location.href="#errs";
				document.getElementById(this.divEl).innerHTML="Fields marked in red were either blank or contained invalid data.<br />Please fix and re-submit";
			}
			if(this.submitButton!="" && this.submitButtonMessage!=""){
				document.getElementById(this.submitDisplay).appendChild(document.createTextNode(this.submitDisplayMessage));
			}
			this.arr_errors=new Array();
			this.arr_passwords=new Array();
			this.requiredFields=new Array();
			this.regExFields=new Array();
			this.arrCounter=0;
			this.temp="";
			this.pattern="";
			this.error=false;
			return false;
		}
		
		function displayError(/*array of missing fields*/ arr, /*element to write to*/ el){
			msg="These required fields were left blank or invalid. Please fix and re-submit.<br />\n";
			msg+="<ul>";
			for(var i=0; i<arr.length; i++){
				msg +="<li>" + arr[i] + "</li>\n";  
			}
			msg+="</ul>\n";
			document.getElementById(el).innerHTML=msg;
		}	
	}

	function formInit(hrf,rfn,rcn,haf,att,ran){
		if(document.getElementById(hrf) && document.getElementById(haf) && document.getElementsByAttribute){
			document.getElementById(hrf).value=document.getElementsByAttribute(rfn,rcn);
			document.getElementById(haf).value=document.getElementsByAttribute(att,ran);
		}
		else{
			throw new Error("Missing required input fields.");
		}
	}
	
	function rgbToHex(value) {
		if (typeof value !== "string") {
			return false;
		}
		var result = value.match(/^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*/);
		if (result == null) { 
			return value; 
		}
		// Use unary operator to force type conversion of result from string to digit.
		var rgb = +result[1] << 16 | +result[2] << 8 | +result[3];
		var hex = "";
		// Convert digits to hex value.
		var digits = "0123456789ABCDEF";
		while (rgb != 0) { 
			hex = digits.charAt(rgb&0xf) + hex; 
			rgb >>>= 4; 
		} 
		while (hex.length < 6) { 
			hex = '0' + hex; 
		}
		// Don't forget to add this to the front of the value!
		return "#" + hex;
	}

	String.prototype.replaceAll=function(haystack, needle, replacement){
		while(haystack.indexOf(needle)!=-1){
			haystack=haystack.replace(needle, " ");
		}
		return haystack;
	}	

}