var	fv_ErrorMessage = "Fields in red contain invalid entries and those in white need to be filled in.\nPlease check your information and try again.";

/*	Creat Form Object.  Parameters:
	reference to form and the final action to send to the server */
function formObject( thisForm, requiredFields, labels, useCookie )
{
	this.form = thisForm;
	this.fieldsLeftBlank = requiredFields;		// blank, required fields
	this.requiredFields = requiredFields;		// read only
	this.checkBadFields = checkBadFields;
	this.sendForm = sendForm;
	this.labels = labels;
	this.badFields = [];
	this.clear = clearForm;
	this.clearLabels = clearLabels;
	this.useCookie = useCookie;
	this.isUS = true;
	this.form.formObject = this;
	initFields( this );
	return this;
}

/*	Creates formData object set to label name
	Sets field to label name or cookie value if available
	If set to cookie value, removes field from fieldsLeftBlank
	Sets className accordingly
	Finally, binds events to appropriate fields
*/
function initFields( formObject )
{
	var thisFieldObject, thisField;
	for ( var x=0; x < formObject.form.length; x++)
	{
		thisField = formObject.form[x];

		thisField.parent = formObject;								//	to reference the parent's properties from the child
		thisField.removeFromBlankList = removeFromBlankList;		//	add method to clear it from fieldsLeftBlank when not empty
		thisField.removeFromBadList = removeFromBadList;
		thisField.addToBlankList = addToBlankList;					//	add method to add it to fieldsLeftBlank when blank
		thisField.isLeftBlank = isLeftBlank;						//	check if fieldsLeftBlank contains this field
		thisField.validate = validateField;
		thisField.required = ( formObject.requiredFields.toString().indexOf(thisField.name) > -1 );

		thisField.label = formObject.labels[thisField.name];		//	sets the field's label
		if ( thisField.type == "text" || thisField.type == "textarea" || thisField.type == "password" )
		{
			thisField.initialClass = thisField.className;			//	sets initialClass to the default class for blank fields
			if ( formObject.useCookie && getCookie( thisField.name ) )
			{
				thisField.value = getCookie( thisField.name );
				thisField.removeFromBlankList();
				thisField.className = "goodField";
			}
			else if ( thisField.value == "" && thisField.type != "password" )
				thisField.value = thisField.label;
			bindEvent( thisField, 'focus', clearLabel );
			bindEvent( thisField, 'blur', setLabelListener );
			if ( thisField.name.indexOf("onfirm") > -1 ) bindEvent( thisField, 'blur', confirmMatch );
		}
	
		else if ( thisField.type == "file")
		{
			thisField.initialClass = thisField.className;			//	sets initialClass to the default class for blank fields
			bindEvent( thisField, 'blur', setLabelListener );
		}
	
		else if ( thisField.type == "select-one")
		{
			if ( formObject.useCookie && getCookie( thisField.name ) )
			{
				thisField.selectedIndex = parseInt(getCookie( thisField.name ) );
				thisField.removeFromBlankList();
				thisField.className = "goodField";
			}
				thisField.checkIf_US = checkIf_US;
			bindEvent( thisField, 'focus', clearLabel );
			bindEvent( thisField, 'blur', setLabelListener );
		}

		else if ( thisField.type == "select-multiple") {}
	
		else if ( thisField.type == "checkbox")
		{
			if ( formObject.useCookie && getCookie( thisField.name ) )
			{
				thisField.checked = parseInt(getCookie( thisField.name ) );
				thisField.initialHilite = thisField.parentNode.style.backgroundColor;
			}
			bindEvent( thisField, 'click', setLabelListener );
			thisField.isRadioChecked = isRadioChecked;
		}

		else if ( thisField.type == "radio" )
		{
			for ( var r=0; r < thisField.form[thisField.name].length; r++ )
			{
				thisField.form[thisField.name][r].parent = formObject;
				thisField.form[thisField.name][r].isLeftBlank = isLeftBlank;
				thisField.form[thisField.name][r].addToBlankList = addToBlankList;
				thisField.form[thisField.name][r].isRadioChecked = isRadioChecked;
				thisField.form[thisField.name][r].removeFromBlankList = removeFromBlankList;
				thisField.form[thisField.name][r].setLabel = function() { setLabel( thisField.form[thisField.name][r] ) };
				bindEvent( thisField.form[thisField.name][r], 'click', setLabelListener );
			}
//			x+=( r-1 );
		}
		thisField.setLabel = function() { setLabel( thisField ) };
		thisField.setLabel();
	}
}

/* OnFocus Event: Clears labels and hilights fields for editing */
function clearLabel(e)
{
	var targ = getTarget(e);
	if ( targ.form )
	{
		var thisFieldObject = targ.form.formObject.form[targ.name];
		if ( thisFieldObject.type != "select-one" )						// if it's not a dropdown
		{
			if ( thisFieldObject.value == thisFieldObject.label )		// 	and its value is unchanged from its label
			{
				thisFieldObject.value = "";								// 	clear the field for editing
				if ( targ.form.formObject.useCookie )					// if cookie use is enabled in this form
					clearCookie( thisFieldObject.name );				// 	clear this field's cookie
			}
		}
		thisFieldObject.className = "goodField";						// hilite the field for editing
	}
}

function setLabelListener(e)
{
	var targ = getTarget(e);
	setLabel(targ);
}

/*	Displays field label and class accordingly */
function setLabel( thisField )
{
	if ( thisField.type == "select-one" )
	{
		if ( thisField.selectedIndex == 0 )
		{
			thisField.className = thisField.initialClass;
			if ( thisField.isLeftBlank() && thisField.required )					// if required and not already included
				thisField.addToBlankList();											// add field to fieldsLeftBlank
		}
		else {
			thisField.className = "goodField";
			thisField.checkIf_US();
			thisField.removeFromBlankList();
		}
	}
	else if ( thisField.type == "select-multiple" ) {}
	else if ( thisField.type == "file" ) {}
	else if ( thisField.type == "hidden" ) {}
	else if ( thisField.type == "button" ) {}
	else if ( thisField.type == "submit" ) {}
	else if ( thisField.type == "checkbox" )
	{
		if ( thisField.checked )
			thisField.removeFromBlankList();
//		thisField.parentNode.style.backgroundColor = ( thisField.checked ) ? "#FFCC33" : "";
	}
	else if ( thisField.type == "radio" )
	{
		for ( var r=0; r < thisField.form[thisField.name].length; r++ )
		{
			if ( thisField.form[thisField.name][r].isRadioChecked() )
			{
				thisField.removeFromBlankList();
				r = thisField.form[thisField.name].length;
			}
			else if ( thisField.isLeftBlank() && thisField.required )
				thisField.addToBlankList();
		}
	}
	else
	{
		if ( thisField.value == thisField.label || thisField.value == "" )				// if it's unchanged or blank
		{
			if ( thisField.type != "password" )
				thisField.value = thisField.label;										// reset value to label name

			if ( thisField.isLeftBlank() && thisField.required )						// if required and not already included
				thisField.addToBlankList();												// add field to fieldsLeftBlank
			thisField.className = thisField.initialClass;
			thisField.removeFromBadList();
		}
		else
		{
			thisField.validate();
		}
	}
}

function removeFromBlankList()
{
	var x, blankList = this.parent.fieldsLeftBlank;
	for ( x=0; x < blankList.length; x++ )
	{
		if ( blankList[x] == this.name )
			blankList.splice( x, 1 );
	}
//window.status = parent.fieldsLeftBlank;
}

function removeFromBadList()
{
	var x, badList = this.parent.badFields;
	for ( x=0; x < badList.length; x++ )
	{
		if ( badList[x] == this.name )
			badList.splice( x, 1 );
	}
//window.status = parent.badList;
}

function addToBlankList()
{
	this.parent.fieldsLeftBlank.push( this.name );
	if ( parent.useCookie ) clearCookie( this.name );
//window.status = parent.fieldsLeftBlank;
}

function isLeftBlank()
{
	var isBlank = ( this.required )
				? ( this.parent.fieldsLeftBlank.toString().search( this.name ) == -1  )
				: ( ( this.type == "text" || this.type == "textarea" ) &&  this.value == this.label );
	return isBlank;
}


function labelObject( labels_ary )
{
	for ( var x=0; x < labels_ary.length; x++ )
		this[labels_ary[x][0]] = labels_ary[x][1];
	return this;
}

function checkIf_US()
{
	var x, isUS, thisField;
	if ( this.name == 'state' )
		this.parent.isUS = ( this.selectedIndex < 55 );
	else if ( this.name == 'location' )
		this.parent.isUS = ( this.value < 300 );

	for ( x=0; x < this.parent.form.length; x++ )
	{
		thisField = this.parent.form[x];
		if ( thisField.name.search( /(phone)|(zip)|(areaCode)/ ) > -1 )
		{
			if ( thisField.validate )
				setLabel( thisField );
		}
	}
}

function isRadioChecked()
{
	return ( this.checked );
}

/*	Fields are checked unobtrusively as they're completed.
	Fields with invalid entries are highlighted and cached
*/
function validateField()
{
	var isValid = true;
	if ( this.parent.isUS )
	{
		switch ( this.name )
		{
			case "phone":
				if ( this.value.search(/^\(?[1-9]\d{2}\)?(\s|\.|-)?\d{3}(\s|\.|-)?\d{4}$/) )
					isValid = false;
				else
					this.value = this.value.replace(/\(?(\d{3})\)?(\d{3})(\d{4})/gi, '$1' + '-$2' + '-$3')
				break;
	
			case "areaCode":
				isValid = ( this.value.search(/^\d{3}$/) == 0 );
				break;
	
			case "zip":
				isValid = ( this.value.search(/^\d{5}$/) == 0 );
				break;
		}
	}
	if ( this.name == "email" )
	{
		isValid = ( this.value.search(/[0-9a-z\.\-]{1,64}@([a-z\d]\.|\-?[a-z\d])+\.[a-z]{2,4}$/gi) == 0);
	}
	if ( isValid )
	{
		this.removeFromBlankList();
		this.removeFromBadList();
		this.className = "goodField";
	}
	else
	{
		if ( this.parent.badFields.toString().search( this.name ) == -1 )
			this.parent.badFields.push( this.name );
		this.className = "badField";
	}

	if ( this.type != "button" && this.type != "submit" && this.form.formObject.useCookie )
		setCookie( this.name, ( this.name != "state" ) ? this.value : this.selectedIndex );
	
	return isValid;
}



/* Upon submission, the badFields & blankField arrays are checked and the user notified accordingly */
function checkBadFields()
{
	if ( this.badFields.length > 0 || fieldsLeftBlank.length > 0 )
	{
		var blankFieldLabels = '',
			badFieldLabels = '';
		for ( var x=0; x < fieldsLeftBlank.length; x++ )
		{
			this.form[fieldsLeftBlank[x]].className = this.form[fieldsLeftBlank[x]].initialClass;
			blankFieldLabels += '\n	' + this.labels[ fieldsLeftBlank[x] ];
		}

		if ( fieldsLeftBlank.length > 0 )
		{
			if ( this.form[fieldsLeftBlank[0]].type == "text" || this.form[fieldsLeftBlank[0]].type == "textarea" || this.form[fieldsLeftBlank[0]].type == "select" )
				this.form[fieldsLeftBlank[0]].focus();
	
			if ( this.form[fieldsLeftBlank[0]].type == "text" || this.form[fieldsLeftBlank[0]].type == "textarea" )
				this.form[fieldsLeftBlank[0]].select();
		}

		if ( this.badFields.length > 0 )
		{
			this.form[ this.badFields[0] ].focus();
			this.form[ this.badFields[0] ].select();
		}

		for ( var x=0; x < this.badFields.length; x++ )
		{
			badFieldLabels += '\n	' + this.form[ this.badFields[x] ].label;
		}

		alert( fv_ErrorMessage + '\n\n' + (fieldsLeftBlank.length) + ' blank field' + ( ( fieldsLeftBlank.length == 1) ? '' : 's' ) + ': ' + blankFieldLabels + '\n\n' + this.badFields.length + ' Invalid Field' + ( ( this.badFields.length != 1 ) ? 's' : '' ) + ': ' + badFieldLabels );
		return false;
	}
	return ( ( this.badFields.length + this.fieldsLeftBlank.length ) == 0 )
}

function sendForm()
{
	if ( this.checkBadFields() )
	{
		this.clearLabels();
		this.form.submit();
		return true;
	}
}

function clearLabels()
{
	var thisField;
	for ( var x=0; x < this.form.length; x++ )
	{
		thisField = this.form[x];
		if ( !thisField.required && thisField.isLeftBlank() && ( thisField.type == "text" || thisField.type == "textarea" ) )
		{
			thisField.value = "";
		}
	}
}

function clearForm()
{
	form.reset();
	for ( var x=0; x < form.length-1; x++ )
		form[x].setLabel();
}

function confirmMatch(e)
{
	var targ = getTarget(e),
		matchTarget = targ.name.replace(/confirm/gi, '').toLowerCase();
	if ( targ.form[ matchTarget ].value != targ.value && targ.value != targ.form.formObject.form[targ.name].label && targ.value != "" ) {
		alert( 'Your ' + matchTarget + ' and confirmation do not match.\nPlease try again.');
		targ.form[matchTarget].focus();
		targ.value = "";
		targ.setLabel();
	}
}
