/********************************************************************************

	Validator Object
	- holds array of fields to validate.

	<form name="myForm" ... >...
	<input type="..." onclick="validate(this.form);">
	</form>
	  - in the html

	myForm = new Validator( "myForm" )
	  - constructor
	  - "myForm" is the name of the form to be validated

	myForm.add( "myField", "My Field", /regexp/gi, message )
	  - adds an element to myForm.fields
	  - "myField" is the actual html field name
	  - "My Field" is the label used to talk about the field
	  - /regexp/gi  defaults to /[^\W]/i and is the test used on the field
	  - message is a message to alert when validation fails

	the validation chain looks like 
	global function validate(form) 
	returns myForm.validate(form)
	loops through myForm.fields.validate(form) 
	returns false if any fail, otherwise true

********************************************************************************/
function Validator( formname ){
	this.formname = formname;
	this.fields = new Array();
	this.compare = new Array();
	Validator[ this.formname ] = this;
}
Validator.date = "7/1/1969"
Validator.email = /^\w+((-\w+)|(\.\w+))*\@[a-z0-9]+((\.|-)[a-z0-9]+)*\.[a-z0-9]{2,3}$/gi
Validator.numeric = "0123456789"

Validator.prototype.add = function( fieldname, fieldlabel, regexp, message ){
	this.fields[ fieldname ] = new ValidatorField( fieldname, fieldlabel, regexp, message )
}

Validator.prototype.del = function( fieldname ){
	this.fields[ fieldname ] = null;
}

Validator.prototype.validate = function(form){
	for(var i in this.fields){
		if( this.fields[i] != null )
			if( ! this.fields[i].validate(form) ) 
				return false;
	}
	for(var i in this.compare){
		if( ! this.compare[i].validate(form) ) 
			return false;
	}
	return true;
}

function validate(form){
	return Validator[ form.name ].validate(form);
}

Validator.prototype.addCompare = function( first, firstLabel, second, secondLabel, message ){
	this.compare[this.compare.length] = new Comparator(first, firstLabel, second, secondLabel, message);
}

/********************************************************************************

	ValidatorField Object
	- helper object for the Validator

********************************************************************************/
function ValidatorField( fieldname, fieldlabel, regexp, message ){
	this.fieldname = fieldname;
	this.fieldlabel = fieldlabel;
	this.regexp = (regexp) ? regexp : /[^\W]/i;
	this.message = message;
}
ValidatorField.prototype.validate = function(form){
	
	var field = form.elements[ this.fieldname ];	
	
	switch ( field.type ){
		case "select" :
		case "select-one" :		
			var sIndex = field.selectedIndex
			if ( sIndex == 0 ){
				if( this.message ) alert( this.message )
				else alert( "The field \"" + this.fieldlabel + "\" is required." )
				field.focus(); 
				return false;
			}
			return true;
		case "text" :
		default :
			if( field.length > 0 ){
				var req = parseInt(this.regexp)
				if( isNaN(req) ) req = 1;
				
				var ct = 0;
				for( var i=0; i< field.length; i++ ){
					if( field[i].checked ){
						if( ++ct >= req ){
							return true;
						}
					}
				}
				if( req==1 ) alert( 'Please choose at least 1 value for ' + this.fieldlabel )
				else alert( 'Please choose at least ' + req + ' values for ' + this.fieldlabel )
				return false;
			}
			else{
				var s = String( field.value )
				if ( ! this.test(s) ){ 
					if( this.message ) alert( this.message )
					else alert( 'The value "' + s + '" is not valid for ' + this.fieldlabel + '.' );
					field.focus();
					return false;
				}			
			}
	}
	return true;
}
ValidatorField.prototype.test = function( s ){
	if( s == null || s.length == 0 ) return false;
	if( this.regexp == Validator.date ){
		return ( ! isNaN( new Date(s) ) );
	}
	else if( this.regexp == Validator.numeric ){
		return isFloat(s)
	}
	this.regexp.lastIndex = 0;
	return this.regexp.test(s);
}

function isFloat( s ){
	var re = /^\-?[0-9]*\.?[0-9]*$/
	return re.test( s ) && ! isNaN( parseFloat( s ) );
}

/********************************************************************************

	Comparator

********************************************************************************/
function Comparator( first, firstLabel, second, secondLabel, message ){
	this.first = first;
	this.firstLabel = firstLabel;
	this.second = second;
	this.secondLabel = secondLabel;
	this.message = message;
}

Comparator.prototype.validate = function(form){
	if( form.elements[ this.first ].value == form.elements[ this.second ].value ){
		return true;
	}
	else{
		if( this.message ){ alert( this.message ) }
		else { alert( 'Please verify that ' + this.firstLabel + ' and ' + this.secondLabel + ' contain the same values.' ) }
		form.elements[ this.first ].focus();
		return false;
	}
}
