/***********************************
* A Validation library for Javascript forms.
* Each validator implements test(),
* which returns null if the test passes, or 
* an error message if it does not.
************************************/

function ValidatorNotNull( min_size ){
	
	this.test = function( inString ){
		if( !inString || inString.length < min_size )
		{
			returnString = 'Enter a value with at least ' + min_size + ' character';
			if( min_size != 1 ) 
				returnString += 's';
			returnString += ' long.';
			
			return returnString;
		}
		return null;
	}
}


function ValidatorAlphaNumeric( required ){
	this.required = required;
	
	this.test = function ( inString ){
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inString );
			if( result != null ){
				return result;
			}
		}
		
		if( inString.search( /^\w+$/ ) == -1 ){
			return 'Enter only letters and digits([Aa-Zz][0-9]).';
		}
		
		return null;
	}
}



function ValidatorLength( size, required ){
	this.required = required;
	this.size = size;

	this.test = function ( inString ){
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inString );
			if( result != null ){
				return result;
			}
		}
		
		if( inString.length != size && !this.required && inString.length != 0 ){
			return 'You must enter exactly ' + size + ' characters.' ;
		}
		
		return null;
	}
}


function ValidatorZip(){
	this.test = function ( inString ){
		var result = new ValidatorNotNull( 1 ).test( inString );

		if( result != null ){
			return result;
		}
		
		if( inString.search( /^\d{5}$/ ) == -1 ){
			return 'Enter a five-digit zip code.';
		}	
		
		return null;
	}
}

function ValidatorNumber( required ){
	this.required = required;
	
	this.test = function ( inString ){
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inString );
			if( result != null ){
				return result;
			}else if( inString.search( /^0$/ ) != -1 ){
				return 'Enter a number greater than 0.';
			}
		}
		
		if( inString.search( /^\d+$/ ) == -1 ){
			return 'Enter only digits.';
		}
		
		return null;
	}
}


function ValidatorPhone( required ){
	this.required = required;
	
	this.test = function ( inString ){
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inString );
			if( result != null ){
				return result;
			}
		}
		
		if( inString.length > 0 && inString.search( /^\(\d{3}\)\s?\d{3}-\d{4}$/ ) == -1 ){
			return 'Enter a valid phone number in the format (212) 555-1212';
		}
		
		return null;
	}
}

function ValidatorEmail( required ){
	this.required = required;

	this.test = function ( inString ){
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inString );
			if( result != null ){
				return result;
			}
		}
		
		if( inString.length > 0 && inString.search( /^[\w\.]+\@[\w]+\.[\w\.]+$/ ) == -1 ){
			return 'Enter a valid email in the format user@domain.com';
		}
		return null;
	}
}


function ValidatorPassword( minSize ){
	this.minSize = minSize;
	
	this.test = function ( inString ){
		var result = new ValidatorNotNull( this.minSize ).test( inString );
		if( result != null ){
			return result;
		}
		
		if( inString.search( /^[\w]+$/ ) == -1 ){
			return 'Passwords can only contain letters and numbers.';
		}
		return null;
	}
}

function ValidatorPrice( minSize ){
	this.minSize = minSize;
	
	this.test = function ( inString ){
		var result = new ValidatorNotNull( this.minSize ).test( inString );
		if( result != null ){
			return result;
		}
		
		if( inString.search( /^[\d,]+$/ ) == -1 ){
			return 'Price can only contain numbers and commas.';
		}
		return null;
	}
}


function ValidatorMustEqual( matchId ){

	this.test = function ( inString ){
		var matchValue = document.getElementById( matchId );

		if( matchValue.value != inString ){
			return 'Field does not equal match field';
		}
		
		return null;
	}
}


/******************************
* A Helper class to validate, display errors and
* change the color of the text field nearby.
*******************************/
function FormHelper(){
	this.formName;
	this.color = new Array();			//color of error text
	this.errorId;						//element id of error element
	this.formElements = new Array();	//associative array of fieldId and validators
	
	
	this.setFormName = function( formName ){
		this.formName = formName;
	}
	
	this.getFormName = function(){
		return this.formName;
	}
	
	this.setColor = function( type, color ){
		this.color[ type ] = color;
	}
	
	this.getColor = function( type ){
		return this.color[ type ];
	}
	
	this.setErrorId = function( errorId ){
		this.errorId = errorId;
	}
	
	this.getErrorId = function(){
		return this.errorId;
	}
	
	this.setFormElement = function( fieldId, inputField, validator, customError ){
		this.formElements[ fieldId ] = new FormValidator( inputField, validator, customError );
	}
	
	this.getFormElement = function( fieldId ){
		return this.formElements[ fieldId ];
	}
	
	this.submit = function(){
		var form = eval( "document." + this.getFormName() );
		return form.submit();
	}
	
	this.validate = function(){
		
		var errors = ""; 

		for( keyId in this.formElements ){
			var field = eval( "document." + this.getFormName() + "." + keyId );
			var formValidator = this.formElements[ keyId ];
			var fieldKey = document.getElementById( formValidator.inputField );
	
			var testResults = formValidator.validator.test( field.value ); 
			if( testResults != null ){
							
				if( formValidator.customErrorMessage != null ){
					errors += formValidator.customErrorMessage;
				}else{
					errors += testResults;
				}
				errors += "<br/>";
				
				if( fieldKey && this.getColor( "error" ) )
					fieldKey.style.color = this.getColor( "error" );
			}else{
				if( fieldKey && this.getColor( "valid" ) )
					fieldKey.style.color = this.getColor( "valid" );
			}
		}
		
		if( errors != "" ){
			errors = "Please correct the following errors.<br/>" + errors;
			
			document.getElementById( this.getErrorId() ).innerHTML = errors;
			return false;
		}
		
		return true;
	}
}

function FormValidator( inputField, validator, customErrorMessage ){
	this.inputField = inputField;
	this.validator = validator;	
	this.customErrorMessage = customErrorMessage;	
}
