var form = function(OlOs){
	this.OlOs = OlOs;

	/* clone some methods that could belong here */
		this.appendOnSubmit	= this.OlOs.events.appendOnSubmit;
	/* end */

	if( typeof(this.OlOs.validate) == 'undefined' ){
		alert('"OlOs.validate" is missing, and is required for form validation functionality.\n\nPlease load validate.js');
	}

	return this;
};

/* !!! VIRGINDATA CUSTOM FORM VALIDATOR !!! */
	/* Have all forms monitored by just calling the function below as is */
		form.prototype.validateAll_onSubmit = function(){
			/* TODO: need to create unique array container to reference properly */
				if( window.attachEvent ){
					window.attachEvent( 'onload' , function(){ OlOs.form.attachValidationToAllForms() } );
				}else if( window.addEventListener ){
					window.addEventListener( 'load' , function(){OlOs.form.attachValidationToAllForms()} , false );
				}
				this.attachValidationToAllForms();
			/* end */
		}
	/* end */
	
	/* monitor all forms at time of call, forms loaded after call are not monitored */
		form.prototype.attachValidationToAllForms = function(){
			var documentForms = document.getElementsByTagName('FORM');
			for( var x=0; x < documentForms.length; ++x ){
				if( documentForms[x].getAttribute("monitoredByVirginData") == null ){
					this.attachValidation( targetForm=documentForms[x] );
				}
			}
		}
	/* end */
	
	form.prototype.attachValidation = function( targetForm ){
		/* attach the onsubmit validation */
			/* remove current actions */
				if( typeof( targetForm.onsubmit ) != 'undefined' ){
					targetForm.setAttribute( "onSubmitSub" , targetForm.getAttribute("onsubmit") );
				}

				/* NON IE Browsers */
					if( typeof(targetForm.getAttribute( "onSubmitSub" )) != typeof(function(){}) ){
						targetForm.onSubmitSub = targetForm.onsubmit;
					}
				/* end */


			/* end */
			targetForm.onsubmit = function(event){ return OlOs.form.attachValidateEvent( this , event ) }
		/* end */
		targetForm.setAttribute("monitoredByVirginData","true");
	}

	form.prototype.getAllowedAttributeArray = function(){
		return new Array(
			"required",
			"invalidMessage",
			"exception",
			"validateJavaScript",
			"invalidIf",
			"validateRegX",
			"validCondition",
			"validateType",
			"onInvalid",
			"atleastOneHasValue",
			"validateErrorMessage"
		);
	}

	/* Main validator in all its glory */
		form.prototype.attachValidateEvent = function( targetForm , event ){
			var inputTypeArray = new Array("TEXTAREA","INPUT","SELECT");
			this.alerter = "";
			this.afterAlertFunctionsArray = new Array();			

			/* loops form targets by element type */
				for( var inputs in inputTypeArray ){
					inputTypeTarget = inputTypeArray[inputs];
					/* Loop form targets */
						for( var inputTarget = 0; inputTarget < targetForm.getElementsByTagName(inputTypeTarget).length; ++inputTarget ){
							this.validate( target=targetForm.getElementsByTagName(inputTypeTarget)[inputTarget] );
						}
					/* end */
				}
			/* end */
			
			if( this.alerter.length ){ alert("The following error(s) occuried:\n"+this.alerter); }

			/* Fire onInvalid functions */
				if( this.afterAlertFunctionsArray.length ){
					for( x = 0; x < this.afterAlertFunctionsArray.length; ++x ){
						this.afterAlertFunctionsArray[x].onInvalidFunction();
					}
				}
			/* end */
			
			if( this.alerter.length ){
				return false;
			}else if( targetForm.getAttribute("onSubmitSub") != null ){
				/* Fire Sub actions */
					return targetForm.onSubmitSub(event);
				/* end */
			}else{
				return true;
			}
		}
	/* end main validator */
	
	form.prototype.validate = function( target ){
		var acceptableAttributesArray = this.getAllowedAttributeArray();
		/* set and reset initial values per node */
			for( x=0; x < acceptableAttributesArray.length; ++x ){
				eval( 'var ' + acceptableAttributesArray[x] + ' = null ');
			}
			var required = false;
			var currentValue = "";
			/* the ending absolute check to determine if input is valid or invalid */
				var valid = true;
			/* end */
		/* end */
		
		/* FIND and DEFINE VALIDATION ATTRIBUTES */
			for( x=0; x < acceptableAttributesArray.length; ++x ){
				if( target.getAttribute( acceptableAttributesArray[x] ) != null ){
					eval( acceptableAttributesArray[x] +' = target.getAttribute(acceptableAttributesArray[x]) ');
				}
			}
		/* END */

		/* invalidIf logic */
			if( invalidIf != null){
				if( target.getAttribute("invalidIfFunction") == null ){
					eval('target.invalidIfFunction = function(){ if('+ invalidIf +'){return false}else{return true} }');
				}
				valid = target.invalidIfFunction();
			}
		/* end */
		
		/* onInvalid preliminary logic */
			if(
				onInvalid != null
			&&
				target.getAttribute("onInvalidFunction") == null
			){
				eval('target.onInvalidFunction = function(){'+ onInvalid +'}');
			}
		/* end */

		/* Process found actions */
			if(
				(
					inputTypeTarget == "INPUT"
				&&
					target.type != 'checkbox'
				)
			||
				inputTypeTarget == "TEXTAREA"
			){
				currentValue = target.value;
			}else if(
				inputTypeTarget == "SELECT"
			&&
				target.selectedIndex >= 0
			){
				currentValue = target.options[target.selectedIndex].value;
				/* for multi select any select option is ok, and so let's add a character if the value is null */
					if(
						!currentValue.length 
					&&
						(
							target.multiple
						||
							target.size > 1
						)
					){
						currentValue = "-";
					}
				/* end */
			}else if(
				inputTypeTarget == "INPUT"
			&&
				target.type == 'checkbox'
			){
				if( target.checked == false ){
					currentValue = "";
				}else{
					currentValue = 1;
				}
			}

			/* validate Length */
				/* trim the value */
					if( isNaN(currentValue) ){
						currentValue = currentValue.replace(/(^(\s|\t|\r|\n)+|(\s|\t|\r|\n)+$)/,'');
					}
				/* end */
				if(
					(
						required == "yes"
					||
						eval(required)
					)
				&&
					currentValue.length == 0
				){
					valid = false;
				}
			/* end */

			/* Regular Expression Validation **/
				if( validCondition != null ){
					var validCondition_if = validCondition.replace( 'this' , 'target' );
					if( eval(validCondition_if) ){
						valid=true;
					}else{
						valid=false
					}
				}else if(
					valid
				&&
					validateRegX != null
				&&
					currentValue.search( validateRegX  ) < 0
				){
					valid = false;
				}
			/* end */

			/* JavaScript Validation **/
				if(
					valid
				&&
					validateJavaScript != null
				){
					eval('	target.validateJavaScriptFunction = function(){ ' + validateJavaScript + ';return true }	');
					valid = target.validateJavaScriptFunction();
				}
			/* end */

			/* process atleastOneHasValue */
				if( atleastOneHasValue != null ){
					var tempArray = atleastOneHasValue.split(',');
					var newArray = new Array();
					for( var x=0; x < tempArray.length; ++x ){
						if( tempArray[x] == 'this' ){
							newArray.push(target);
						}else if( eval('typeof '+tempArray[x]+' == "undefined"') ){
							newArray.push(targetForm[tempArray[x]]);
						}else if( eval('typeof '+tempArray[x]+' == "object"') ){
							if( eval('typeof '+tempArray[x]+'.length != "undefined"') ){
								eval('var tempArray2 = '+tempArray[x]);
								for( var i=0; i < tempArray2.length; ++i ){
									newArray.push(tempArray2[i]);
								}
							}else{
								eval('newArray.push('+tempArray[x]+')');
							}
						}
					}
					var atleastVALID = false;
					for( x in newArray ){
						if( typeof newArray[x].value != 'undefined' ){
							if( newArray[x].value.length == 0 ){
								atleastVALID = false;
							}else{
								atleastVALID = true;
								break;
							}
						}else if( typeof newArray[x].value == 'undefined' ){
							var message = "One or more of the following fields is invalid\n";
							message += "node Name:"+newArray[x].nodeName;
							return message;
						}
					}
					if( !atleastVALID ){
						if(!invalidMessage){
							invalidMessage='One of the following fields needs value:\n'
								for( x in newArray ){
									if( newArray[x].name ){
										invalidMessage += '   '+x+'. '+newArray[x].name+'\n';
									}else{
										invalidMessage += '   '+x+'. UnNamed Input('+newArray[x].nodeName+')\n';
									}
								}
						}
						valid = false;
					}
				}
			/* end */

			/* process validateType */
				if(
					validateType != null
				&&
					valid
				){
					/* validate : EMAIL */
						if(
							validateType.toLowerCase() == "email"
						&&
							!this.OlOs.validate.isEmail( target.value , false )
						){
							valid = false;
						}
					/* end */
					
					/* validate : date */
						if(
							(
								validateType.toLowerCase() == "basicdate"
							||
								validateType.toLowerCase() == "date"
							)
						&&
							!this.OlOs.validate.isBasicDate( target.value , false )
						){
							valid = false;
						}
					/* end */
					
					/* validate : INTEGER */
						if(
							validateType.toLowerCase() == "integer"
						&&
							!this.OlOs.validate.isInteger( target.value )
						){
							valid = false;
						}
					/* END */
					
					/* validate : POSITIVEinteger */
						if(
							validateType.toLowerCase() == "positiveinteger"
						&&
							!this.OlOs.validate.isPositiveInt( target.value )
						){
							valid = false;
						}
					/* end */
					
					/* validate : MONEY */
						if(
							validateType.toLowerCase() == "money"
						&&
							!this.OlOs.validate.isMoney( target.value )
						){
							valid = false;
						}
					/* end */
				}
			/* end */

			/* switch valid state based on if exception met, if exception isDefined */
				if( exception != null && !valid ){
					eval('target.exceptionMethod = function(){ if('+exception+'){return true}else{return false} }');
					valid = target.exceptionMethod();
				}
			/* end */

			/* invalid processing */
				if( !valid ){
					if( onInvalid != null ){
						this.afterAlertFunctionsArray[this.afterAlertFunctionsArray.length] = target;
					}

					/* attach invalid messages */
						if( validateErrorMessage ){
							this.alerter += "\t- " + validateErrorMessage +"\n";
						}else if( invalidMessage ){
							this.alerter += "\t- " + invalidMessage +"\n";
						}else{
							if( target.name ){
								this.alerter += "\t- " + target.name + " is a required field.\n";
							}else{
								this.alerter += "\t- UnNamed Input("+inputTypeTarget+") is a required field.\n";
							}											
						}
					/* end */
				}
			/* end */

		/* end */
	}
/* END */

/* form data loss prevention */
	form.prototype.checkAllFormsForChanges = function( event ){
		var local	= new Object();

		local.forms			= document.getElementsByTagName('FORM');
		local.form_count	= local.forms.length;

		for( local.x=0; local.x < local.form_count; ++local.x ){
			local.targetForm	= local.forms[local.x];
			local.changeAttr	= local.targetForm.getAttribute("changed");

			if( local.changeAttr === true || local.changeAttr === 'true' ){
				return "Their are unsaved form modifications";
				/*
					if( confirm('Are you sure you want to navigate away from this page?\n\nYou have changes not yet saved.\n\nSAVE CHANGES? - ' + local.targetForm.name) ){
						local.targetForm.submit();
						alert('Changes Saved!');
					}
				*/
			}
		}

	}
/* */
	form.prototype.protectFormChanges = function( form ){
		var local = new Object();

		this.form = form;
		if( typeof(this.form) == typeof(" ") ){
			this.form = document[form];
		}

		/* make it so that when any element changes, we are notified */
			this.form.setAttribute("changed","false");
			local.input_count = this.form.length;
			for( local.x=0; local.x < local.input_count; ++local.x ){
				local.target	= this.form[local.x];
				local.method = function(evt){
					form=(evt.target||evt.srcElement).form;
					form.setAttribute("changed",true);
				}		
	
				if( local.target.attachEvent ){
					local.target.attachEvent( "onchange" , local.method );
				}else if( local.target.addEventListener ){
					local.target.addEventListener( "change" , local.method , false );
				}
			}
		/* end */

		local.method = function(){
			this.setAttribute("changed",false);
		}		

		OlOs.events.appendOnSubmit( this.form , local.method );
		
		/* attach the event to check the form */
			OlOs.events.attachSafeOnBeforeUnload( OlOs.form.checkAllFormsForChanges );
		/* end */
	}
/* end */

if( OlOs == null ){
	document.write("<script type=\"text/javascript\" src=\"OlOs.js\"></script>");
}

OlOs.attachTo( new form(OlOs) , "form" );