/*
 Validation 2.0 beta
 Copyright (C) 1996-2001  e.magination network, llc.  All Rights Reserved.
   Feel free to reuse or modify this code,
   provided this header remains in tact.
   http://www.emagination.com
   jibba jabba strikes again.

 For more information on regular expressions in JavaScript and VBScript, 
 see:
 http://developer.netscape.com/viewsource/angus_strings.html
 http://msdn.microsoft.com/scripting/vbscript/doc/jsgrpregexpsyntax.htm
 
 Netscape JavaScript Resources:
 http://home.netscape.com/eng/mozilla/3.0/handbook/javascript/
 http://developer.netscape.com/library/documentation/communicator/jsref/index.htm

*/

////regular expression patterns
//integer (non-negative = zero or positive)
_reInteger = /^\s*\d+\s*$/;

//decimal (non-negative, optional decimal point)
_reDecimal = /^\s*\d+(\.\d*)?\s*$/;

//money (non-negative, optional decimal point and two decimal places)
_reMoney = /^\s*\d+(\.\d{0,2})?\s*$/;

//e-mail: asdf.asdf-asdf@asdf.asdf.asdf.aa
_reEmail = /^\s*[\w\.\-]+@([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}\s*$/i;

//zip code: 12345, 12345-1234
_reZipCode = /^\s*\d{5}(-\d{4})?\s*$/;

//phone: 123-456-7890, 123-456-7890 x111
_rePhone = /^\s*\d{3}-\d{3}-\d{4}( x\d+)?\s*$/;

//social security number: 123-45-6789
_reSSN = /^\s*\d{3}-\d{2}-\d{4}\s*$/;

//URL: http://asdf.com/
_reURL = /^\s*http:\/\/([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}(:\d+)?(\/.*)?\s*$/;

//date: 1/1/1111, 01/01/1111
_reDate = /^\s*(0?[1-9]|1[0-2])\/(0?[1-9]|[12]\d|3[01])\/\d{4}\s*$/;
_reGetDate = /^.*\/(\d+)\/.*$/;

//web filename: *.asp, *.html, *.htm
_reWebFilename = /^[^\\\/\:\*\?\"\<\>\|]*\.(asp|html|htm)$/i;




function isBlank(value) {
	return (!(value) || value.match(/^\s*$/)) ? true : false;
}//isBlank

function selectedIndex(selectField) {
//returns index of first option selected in select field
	return selectField.selectedIndex;
}//selectedValue

function selectedValue(selectField) {
//returns value of first option selected in select field
	return (selectField.selectedIndex==-1) ? null : selectField.options[selectField.selectedIndex].value;
}//selectedValue

function checkedIndex(buttonField) {
//returns index of first button checked in radio/checkbox field
	var index = -1;
	if (buttonField.length) {
		for (var i=0; i<buttonField.length; i++) {
			if (buttonField[i].checked) {
				index = i;
				break;
			}
		}//for
	}//if
	return index;
}//checkedIndex

function checkedValue(buttonField) {
//returns value of first button checked in radio/checkbox field
	var val = null;
	if (buttonField.length && (buttonField.checkedIndex())) {
		val = buttonField[buttonField.checkedIndex()].value;
	}//if
	else if (buttonField.checked) {
		val = buttonField.value;
	}
	return val;
}//checkedValue

function fieldIsBlank(field) {
//returns true if field is blank
//criteria for blank depends of type of field
//text related: blank (meaning only contains whitespace)
//select related: selectedIndex == -1 or option selected is blank
//radio/checkbox buttons: none checked
	var bln = false;
	if (typeof(field)=='object') {
		switch (field.type) {
			case 'text':
			case 'textarea':
			case 'password':
			case 'hidden':
				bln = isBlank(field.value);
				break;
			case 'select-one':
			case 'select-multiple':
				bln = ((selectedIndex(field)==-1) || isBlank(selectedValue(field)));
				break;
			case 'radio'://single radio button
			case 'checkbox'://single checkbox button
				bln = (checkedIndex(field)==-1);
				break;
			default://check for multiple buttons
				switch (field[0].type) {
					case 'radio':
					case 'checkbox':
						bln = (checkedIndex(field)==-1);
						break;
					default:
						alert('ERROR: Field "'+field[0].name+'" is a multiple field that is not radio or checkbox.');
						return true;
				}//switch
		}//switch
	}//if
	else {//alert error
		alert('ERROR: Field "'+field.name+'" does not exist!');
		return true;
	}
	return bln;
}//fieldIsBlank

function isMatch(value, re) {
	return (value.match(re));
}//isMatch


function isValidDate(value) {
//returns true if value is a date
	//test format
	var bln = (value.match(_reDate)) ? true : false;
	//test if date number is a number and date in string value matches date in date object;
	var objDate = new Date(value);
	var dateNumber = objDate.getDate();
	bln = (bln && !isNaN(dateNumber) && parseFloat(value.replace(_reGetDate, '$1'))==dateNumber);
	return bln;
}//isInvalidDate





function validation_fieldIsDate(textName) {
//returns true if value of textName field of form object of validation is a valid date
	var field = this.form.elements[textName];
	var bln = (isValidDate(field.value)) ? true : false;
	this.currentField = field;
	if (bln && this.focusField==null) this.focusField = field;
	return bln;
}//validation_fieldIsDate

function validation_fieldIsNotDate(textName) {
//returns false if value of textName field of form object of validation is a valid date
	var field = this.form.elements[textName];
	var bln = (isValidDate(field.value)) ? false : true;
	this.currentField = field;
	if (bln && this.focusField==null) this.focusField = field;
	return bln;
}//validation_fieldIsNotDate



function validation_fieldIsMatch(textName, re) {
//returns true if value of textName field of form object of validation matches pattern
	var field = this.form.elements[textName];
	var bln = (isMatch(field.value, re)) ? true : false;
	this.currentField = field;
	if (bln && this.focusField==null) this.focusField = field;
	return bln;
}//validation_fieldIsMatch

function validation_fieldIsNotMatch(textName, re) {
//returns false if value of textName field of form object of validation matches pattern
	var field = this.form.elements[textName];
	var bln = (isMatch(field.value, re)) ? false : true;
	this.currentField = field;
	if (bln && this.focusField==null) this.focusField = field;
	return bln;
}//validation_fieldIsNotMatch



function validation_selectedIndex(selectName) {
//returns index of first selected option in select field of form object of validation
	return this.form.elements[selectName].selectedIndex;
}//validation_selectedIndex

function validation_selectedValue(selectName) {
//returns value of first selected option in select field of form object of validation
	return selectedValue(this.form.elements[selectName]);
}//validation_selectedValue



function validation_checkedIndex(buttonName) {
//returns index of first button checked in radio/checkbox field of form object of validation
	return checkedIndex(this.form.elements[buttonName]);
}//validation_checkedIndex

function validation_checkedValue(buttonName) {
//returns value of first button checked in radio/checkbox field of form object of validation
	return checkedValue(this.form.elements[buttonName]);
}//validation_checkedValue



function validation_fieldIsBlank(fieldName) {
//returns true if field in form object of validation is blank
	var field = this.form.elements[fieldName];
	if (!(field)) {
		alert('ERROR: Field "' + fieldName + '" does not exist on this form.');
		return true;
	}
	var bln = fieldIsBlank(field);
	this.currentField = field;
	if (bln && this.focusField==null) this.focusField = field;
	return bln;
}//validation_fieldIsBlank



function validation_addError(errorMessage, alternateFocusField) {
//add error item to errors array
	with (this) {
		errors[errors.length] = (errorMessage) ? errorMessage : 'field: ' + currentField.name;
		if (focusField==null) 
			focusField = (alternateFocusField) ? alternateFocusField : currentField;
	}//with
}//validation_addError

function validation_focus() {
//move browser to first error field
	with (this) {
		//focus
		if (focusField && focusField.focus) {
			focusField.focus();
			if (focusField.select) focusField.select();
		}
		//if multiple buttons, focus on first option
		else if ( (focusField[0]) && (focusField[0].focus) ) {
			focusField[0].focus();
		}
		else return;
		//move to absolute left
		var scrollLeft = (typeof(window.pageXOffset)=='number') ? window.pageXOffset : document.body.scrollLeft;
		if (typeof(scrollLeft)=='number') window.scrollBy(-scrollLeft, 0);
	}//with
}//validation_focus

function validation_alertErrors() {
//alert error message if any errors exist
	with (this) {
		if (!isValid()) {
			var message = header + '\n';
			for (var i=0; i<errors.length; i++) {
				message += bullet + errors[i] + '\n';
			}//for
			alert(message);
		}//if
	}//with
}//validation_alertErrors

function validation_isValid() {
//return true if no item in errors array
	return (this.errors.length==0);
}//validation_isValid



function validation_checkRequiredField(fieldName, blankFieldMessage) {
	if (this.fieldIsBlank(fieldName)) this.addError(blankFieldMessage);
}//validation_checkRequiredField

function validation_matchRequiredField(fieldName, re, blankFieldMessage, invalidFieldMessage) {
		if (this.fieldIsBlank(fieldName)) this.addError(blankFieldMessage);
		else if (this.fieldIsNotMatch(fieldName, re)) this.addError(invalidFieldMessage);
}//validation_matchRequiredField

function validation_matchOptionalField(fieldName, re, invalidFieldMessage) {
		if (!this.fieldIsBlank(fieldName) && this.fieldIsNotMatch(fieldName, re)) 
			this.addError(invalidFieldMessage);
}//validation_matchOptionalField




function Validation(form) {
//constructor for Validation object class
	if (!form) alert('ERROR: form object is required in Validation constructor as first argument.');
	this.form = form;
	form.validation = this;
	this.selectedIndex = validation_selectedIndex;
	this.selectedValue = validation_selectedValue;
	this.checkedIndex = validation_checkedIndex;
	this.checkedValue = validation_checkedValue;
	this.fieldIsBlank = validation_fieldIsBlank;
	this.fieldIsMatch = validation_fieldIsMatch;
	this.fieldIsNotMatch = validation_fieldIsNotMatch;
	this.fieldIsDate = validation_fieldIsDate;
	this.fieldIsNotDate = validation_fieldIsNotDate;

	this.checkRequiredField = validation_checkRequiredField;
	this.matchRequiredField = validation_matchRequiredField;
	this.matchOptionalField = validation_matchOptionalField;

	this.bullet = '  >>  ';
	this.header = 'Your form has not been submitted for the following reason(s):';
	this.currentField = null;
	this.focusField = null;
	this.focus = validation_focus;
	this.errors = new Array();
	this.addError = validation_addError;
	this.alertErrors = validation_alertErrors;
	this.isValid = validation_isValid;
}//Validation
  