/* -------------------------------------------------------------------- */
/* -------- Form Validation Library ----------------------------------- */
/* -------------------------------------------------------------------- */
/* -------- Heikki Gruner ---- 18 September, 2008 --------------------- */
/* -------------------------------------------------------------------- */


function FormValidation() {
	this.fields = new Array();
	
	this.Initialize = function() { for( var index in this.fields ) this.fields[ index ].Initialize(); }
	
	this.Validate = function( formReference ) {
		// Clear out any preexisting error messages.
		for( var index in this.fields ) this.fields[ index ].ClearError();
		
		// Extract the values of all the supplied fields.
		for( var index = 0; index < formReference.elements.length; index++ ) {
			var currentElement = formReference.elements.item( index );
			
			for( var subIndex in this.fields ) {
				if( currentElement.name == this.fields[ subIndex ].name ) {
					this.fields[ subIndex ].touched = true;
					
					// Determine the linkage between the form element and the field.
					switch( currentElement.type ) {
						case "text":
							this.fields[ subIndex ].value = currentElement.value;
							break;
							
						case "select-one":
							this.fields[ subIndex ].value = currentElement.value;
							break;
							
						case "radio":
							if( currentElement.checked ) this.fields[ subIndex ].value = currentElement.value;
							break;
						
						case "checkbox":
							this.fields[ subIndex ].value = currentElement.checked;
							break; 
							
						case "textarea":
							this.fields[ subIndex ].value = currentElement.value;
							break;
							
						default:
							alert( "Gruner Web Application Framework\nValidation of " + currentElement.type + " form fields not implemented yet." );
					}
					
					break;
				}
			}
		}
		
		
		var error = false;

		// Check for errors in the supplied fields.
		for( var index in this.fields ) {
			if( ! this.fields[ index ].touched ) continue;
			if( ! this.fields[ index ].Validate() ) error = true;
			this.fields[ index ].Reset();
		}
		
		return ! error;
	}
	
	this.ClearErrors = function() {
		for( var index in this.fields )
			this.fields[ index ].ClearError();
	}
}



function FormField( name, errorSpanId ) {
	this.name = name;
	this.errorSpanId = errorSpanId;
	this.touched = false;
	this.value = null;
	
	this.rules = new Array();
	for( var index = 2; index < arguments.length; index++ ) this.rules.push( arguments[ index ] );
	
	
	this.Initialize = function() { this.errorSpan = document.getElementById( this.errorSpanId ); }
	this.ClearError = function() { if( this.errorSpan !== null ) this.errorSpan.innerHTML = ""; }
	this.Reset = function() { this.value = null; this.touched = false; }
	
	this.Validate = function() {
		for( var index = 0; index < this.rules.length; index++ ) {
			var currentRule = this.rules[ index ];
			var result = currentRule.Validate( this.value );
			if( ! result ) continue;
			if( this.errorSpan != null ) this.errorSpan.innerHTML = result;
			return false;
		}
		
		return true;
	}
}



function FieldRuleRequired() {
	this.Validate = function( value ) {
		if( value === null || ! value ) return "&nbsp;(Required)&nbsp;";
		return false;
	}
}

function FieldRuleNumeric( lowerBound, upperBound ) {
	this.lowerBound = lowerBound;
	this.upperBound = upperBound;
	
	this.Validate = function( value ) {
		if( value == "" ) return false;
		if( isNaN( value ) ) return "&nbsp;(Invalid)&nbsp;";
		value = parseFloat( value );
		if( ! isNaN( this.lowerBound ) ) {
			var lowerBound = parseFloat( this.lowerBound );
			if( value < lowerBound ) return "&nbsp;(Invalid)&nbsp;"
		}
		if( ! isNaN( this.upperBound ) ) {
			var upperBound = parseFloat( this.upperBound );
			if( value > upperBound ) return "&nbsp;(Invalid)&nbsp;"
		}
		return false;
	}
}

function FieldRuleInteger( lowerBound, upperBound ) {
	this.lowerBound = lowerBound;
	this.upperBound = upperBound;
	
	this.Validate = function( value ) {
		if( value == "" ) return false;
		if( isNaN( value ) ) return "&nbsp;(Invalid)&nbsp;";
		// Test to see if value is an int.
		value = parseInt( value, 10 );
		if( ! isNaN( this.lowerBound ) ) {
			var lowerBound = parseInt( this.lowerBound );
			if( value < lowerBound ) return "&nbsp;(Invalid)&nbsp;"
		}
		if( ! isNaN( this.upperBound ) ) {
			var upperBound = parseInt( this.upperBound );
			if( value > upperBound ) return "&nbsp;(Invalid)&nbsp;"
		}
		return false;
	}
}
