/***********************************
* 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.min_size = min_size;
	
	this.test = function( inField ){
		var inString = inField.value;
		return this.testValue( inString );	
	}
	
	this.testValue = function( inString ){

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


function ValidatorAlphaNumeric( required ){
	this.required = required;
	
	this.test = function ( inField ){
		var inString = inField.value;
		
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inField );
			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 ( inField ){
		var inString = inField.value;
		
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inField );
			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( required ){
	this.required = required;
	
	this.test = function ( inField ){
		var inString = inField.value;
		
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inField );
			if( result != null ){
				return result;
			}
		}
		
		if( inString.length > 0 && inString.search( /^\d{5}$/ ) == -1 ){
			return 'Enter a five-digit zip code.';
		}	
		
		return null;
	}
}

function ValidatorCreditCard( required ){
	this.required = required;
	
	this.test = function( inField ){
		var inString = inField.value;
		this.testValue( inString );	
	}
	
	this.testValue = function( inString ){
		
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).testValue( inString );
			if( result != null ){
				return result;
			}else if( inString.search( /^0$/ ) != -1 ){
				return 'Enter a credit card number.';
			}
		}
		
		if( inString.length > 0 && inString.search( /^[\d]{16}$/ ) == -1 ){
			return 'Enter a credit card number.';
		}
	}
}


function ValidatorNumber( required ){
	this.required = required;
	
	this.test = function ( inField ){
		var inString = inField.value;

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

function ValidatorDouble( required ){
	this.required = required;
	
	this.test = function ( inField ){
		var inString = inField.value;

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

function ValidatorPhone( required ){
	this.required = required;
	
	this.test = function ( inField ){
		var inString = inField.value;
		
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inField );
			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 ( inField ){
		var inString = inField.value;
		return this.testEmail( inString );
	}
	
	this.testEmail = function( inString ){
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).testValue( 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 ValidatorEmailList( required ){
	this.required = required;

	this.test = function ( inField ){
		var inString = inField.value;
		
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inField );
			if( result != null ){
				return result;
			}
		}
		
		var validEmail = true;
		if( inString.length > 0  ){
			var emails = inString.split(",");
			var validator = new ValidatorEmail(0);
			for(i=0; i<emails.length && validEmail;i++){
				if( validator.testEmail( emails[i] ) )
					validEmail = false;
			}
		}
		
		return ( !validEmail ) ? 'Enter all emails in the format user@domain.com' : null;
	}
}


function ValidatorPassword( minSize ){
	this.minSize = minSize;
	
	this.test = function ( inField ){
		var inString = inField.value;
		
		var result = new ValidatorNotNull( this.minSize ).test( inField );
				
		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 ( inField ){
		var inString = inField.value;
		
		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.matchId = matchId;
	
	this.test = function ( inField ){
		var inString = inField.value;
		
		var matchValue = document.getElementById( this.matchId );
		
		if( matchValue.value != inString ){
			return 'Field does not equal match field';
		}
		
		return null;
	}
}


function ValidatorDepends( matchId ){
	this.matchId = matchId;
	
	this.test = function ( inField ){
		var inString = inField.value;
		
		if( inField.value ){
			var matchValue = document.getElementById( this.matchId );

			if( matchValue == null || 
				matchValue.value == null || 
				matchValue.value.length == 0 )
			{
				return 'Field depends on another field.';
			}
		}
		
		return null;
	}
}



function ValidatorDate( required ){

	this.required = required;
	
	this.test = function ( inField ){
		var inString = inField.value;
		
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inField );
			if( result != null ){
				return result;
			}
		}
		
		if( inString.length > 0 && inString.search( /^[\d]{1,2}\/[\d]{1,2}\/[\d]{4}$/ ) == -1 ){
			return 'Date must be in the format MM/DD/YYYY.';
		}
	}
}

function ValidatorUrl( required ){

	this.required = required;
	
	this.test = function ( inField ){
		var inString = inField.value;
		if( this.required ){
			var result = new ValidatorNotNull( 1 ).test( inField );
			if( result != null ){
				return result;
			}
		}
		
		if( inString.length > 0 && inString.search( /http:\/\/.*/ ) == -1 ){
			return 'Enter a valid url starting with http://';
		}
		return null;
	}
}


function ValidatorChecked( required ){

	this.required = required;
	
	this.test = function ( inField ){
		var isChecked = false;
		
		if( inField.checked ){
			isChecked = true;
		}else{
			for( i=0; i < inField.length && !isChecked; i++ ){
				if( inField[i].checked )
					isChecked = true;
			}
		}
		
		if( !isChecked ){
			return 'Field must be checked';
		}
	}
}

/******************************
* 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.scrollX;
	this.scrollY;
	
	this.setFormName = function( formName ){
		this.formName = formName;
	}
	
	this.getFormName = function(){
		return this.formName;
	}
	
	this.getForm = function(){
		return eval( "document." + this.getFormName() );
	}
	
	
	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.setScrollX = function(scrollX){
		this.scrollX = scrollX;
	}
	
	this.setScrollY = function(scrollY){
		this.scrollY = scrollY;
	}
	
	this.validateAndSubmit = function(){
		if( this.validate() )
			this.submit();
		
		return false;
	}
	
	this.submit = function(){
		var form = eval( "document." + this.getFormName() );
		return form.submit();
	}
	
	this.setFieldValue = function( fieldName, fieldValue ){
		var fieldElement = eval( "document." + this.getFormName() + "." + fieldName );
		fieldElement.value = fieldValue;
		
	}
	
	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 ); 

			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" );
			}
		}
		
		var errorElement = document.getElementById( this.getErrorId() );
		if( errorElement )
			errorElement.innerHTML = '';
			
		if( errors != "" ){
			errors = "Please correct the following errors.<br/>" + errors;
			
			if( errorElement )
				errorElement.innerHTML = errors;
				
			
			if( typeof this.scrollX != "undefined" && 
				typeof this.scrollY != "undefined" )
			{
				window.scrollTo( this.scrollX, this.scrollY );
			}
			return false;
		}
		
		return true;
	}
}

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