/********************************************************************************

	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

	myForm.addCompare( first, firstLabel, second, secondLabel, message )

	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

	Updated 7/26/2005 by Alan Draper 
	--  supply the ID of a page element into validate( formName, divID );

********************************************************************************/
function Validator( formname ){
	this.formname = formname;
	this.fields = 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,4}$/gi;
Validator.numeric = "0123456789";
Validator.path = /^[A-Za-z0-9\+\_\.\-]+$/g;
Validator.nospaces = /^[\S]+$/gi;

Validator.prototype.add = function( fieldname, fieldlabel, regexp, message ){
	this.fields[ fieldname ] = new ValidatorField( fieldname, fieldlabel, regexp, message )
}
Validator.prototype.addCompare = function( first, firstLabel, second, secondLabel, message ){
	this.fields[first+second] = new Comparator(first, firstLabel, second, secondLabel, message);
}

Validator.prototype.del = function( fieldname ){
	this.fields[ fieldname ] = null;
}

Validator.prototype.validate = function(form,errDivID){
	var errString = '';
	form.focusSet = null;
	for(var i in this.fields){
		if( this.fields[i] != null ){
			errString += this.fields[i].validate(form);
		}
	}
	errString = cleanErrString(errString);
	
	if( errString != ''){
		var errDiv = document.getElementById(errDivID)
		if( errDiv != null ){
			errDiv.innerHTML = errString.replace( /\n/gi, "<br>" )
		}
		else{
			alert( errString );
		}
		return false;
	}
	return true;
}

function cleanErrString(eS){  //removes "true" from the errString
	eS = eS.replace(/true*/g, "");
	return eS;
}

function validate(form, errDivID){
	return Validator[ form.name ].validate(form,errDivID);
}


/********************************************************************************

	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.takeFocus = function(field){
	if( ! field.form.focusSet ){
		field.form.focusSet = field;
		field.focus();
	}
}
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 ){
				this.takeFocus(field); 
				if( this.message ) return this.message;
				else return "The field \"" + this.fieldlabel + "\" is required.\n" ;
			}
			return '';
		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 '';
						}
					}
				}
				if( req==1 ) return  'Please make a selection for ' + this.fieldlabel + '\n';
				else return 'Please choose at least ' + req + ' values for ' + this.fieldlabel + '\n';
			}
			else{
				var s = String( field.value )
				if ( ! this.test(s) ){ 
					this.takeFocus(field); 
					
					if( this.message ) return  this.message + '\n';
					else if( s.length > 0 ) return  'The value "' + s + '" is not valid for ' + this.fieldlabel + '.\n';
					else return "The field \"" + this.fieldlabel + "\" is required.\n" ;
				}			
			}
	}
	return '';
}
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 '';
	}
	else{
		if( this.message ){
			return this.message;
		}
		else{
			return 'Please verify that "' + this.firstLabel + '" and "' + this.secondLabel + '" contain the same values.';
		}
	}
}
