/**
*
*/
	function tplObjForm(frm) {
		this.required = new Array();	// holds our required fields
		this.requiredCallBack = new Array(); // holds fields with validation functions requiring an argument
		this.mustMatch = new Array();	// holds our fields that must match
		this.mirrors = new Array();		// holds our fields that mirror values
		this.watches = new Array();		// holds our fields that watch for change
		this.docForm = frm;			// the form that this object referes to
		this.checkSubmit = new Array();

		/**
		*	Adds a required field to the form
		*/
		this.addRequired = function(fieldName, displayName, minLength) {
			tmp = new Object();

			if (!minLength) {
				minLength = 1;
			} //if

			tmp.field = fieldName;
			tmp.name = displayName; 
			tmp.min = minLength;

			this.required[this.required.length] = tmp; 
		} //func
		
		/**
		*	Adds a required callback field to the form
		*/
		this.addRequiredCallBack = function(fieldName, callBack, errorMsg) {
			tmp = new Object();

			tmp.field = fieldName;
			tmp.callBack = callBack; 
			tmp.errorMsg = errorMsg;

			this.requiredCallBack[this.requiredCallBack.length] = tmp; 
		} //func

		/**
		*	Adds a on watch field
		*/
		this.addWatch = function(fieldName, changeFunc) {
			tmp = new Object();

			tmp.field = fieldName;
			tmp.changeFunc = changeFunc; 
			
			this.docForm[fieldName].onchange = changeFunc;
			this.docForm[fieldName].onkeyup = changeFunc;

			this.watches[this.watches.length] = tmp; 
		} //func	

		/**
		*	updates mirrors
		*/
		this.updateMirrors = function(ifCase) {
			if (this.mirrors.length < 1) {
				return false;
			} //if

			
			for (i = 0; i < this.mirrors.length; i++) {
				if (ifCase) {
					thisCase = ifCase;
				} //if
				else {
					thisCase = false;
				} //else
				
				mir = this.mirrors[i];

				if (window.mir.ifCase) {
					thisCase = mir.ifCase;
				} //if

				tplMirrorValue(this.docForm[mir.field1], this.docForm[mir.field2], thisCase, mir.mode);
			} //for
		} //func

		/**
		*	Adds a mirrors field to the form
		*/
		this.addMirror = function(field1, field2, ifCase, mode) {
			tmp = new Object();

		// a field that must match this field
			tmp.field1 = field1;
			tmp.field2 = field2;
			tmp.ifCase = ifCase;
			tmp.mode = mode;

			this.mirrors[this.mirrors.length] = tmp; 
		} //func	

		/**
		*	Adds a must match field to the form
		*/
		this.addMustMatch = function(fieldName, displayName, mirror, mirrorName) {
			tmp = new Object();

		// a field that must match this field
			tmp.mirror = mirror;
			tmp.mirrorName = mirrorName;
			tmp.field = fieldName;
			tmp.name = displayName; 

			this.mustMatch[this.mustMatch.length] = tmp; 
		} //func

		/**
		*	adds a function to call before submit
		*/
		this.addOnSubmit = function(submitFunc) {
			this.onSubmit = submitFunc;
		} //func

		/**
		*	adds a function to check to be able to submit
		*/
		this.addCheckSubmit = function(submitFunc) {
			this.checkSubmit[this.checkSubmit.length] = submitFunc;
		} //func

		/**
		*	removes a function to check to be able to submit
		*/
		this.removeCheckSubmit = function(submitFunc) {
			for (i in this.checkSubmit) {
			    if (this.checkSubmit[i] == submitFunc) {
					delete this.checkSubmit[i];
					break;
			    } //if
			} //for
		} //func

		/**
		*	submits the form
		*/
		this.submitForm = function() {
			if (this.checkSubmit) {
				for (i in this.checkSubmit) {
				    canSubmit = this.checkSubmit[i](this);

					if (canSubmit != true) {
						return false;
					} //if
				} //for				
			} //if			

			var frmErrors = false;
			var alertMsg = '';		// generated error message
			var alertMsgEnd = '';	// appended in sentance format to the end of generated alertMsg
			var errorFields = new Array();

			for (i = 0; i < this.required.length; i++) {
				req = this.required[i];

				switch (req.field) {
					case 'email':
						if (!this.docForm[req.field].value || !tplValidEmail(this.docForm[req.field].value)) {
							alertMsgEnd += "Please enter a valid " + req.name + ".\n";
							frmErrors = true;   
						} //if
					break;
					case 'phone':
						if (!this.docForm[req.field].value || !tplValidPhone(this.docForm[req.field].value)) {
							alertMsgEnd += "Please enter a valid " + req.name + " ex: 333-555-4444.\n";
							frmErrors = true;   
						} //if
					break;
					default:
						if (req.min > 0) {
						// this is a number, must be a required length
							if (this.docForm[req.field].value == undefined) {
								alert('There is an error on this form. Please contact the web administrator about the problem');
								frmErrors = true;
							} //if
							else if (this.docForm[req.field].value.length < req.min) {
								errorFields[errorFields.length] = req.name;
								frmErrors = true;
							} //if
						}
/*
					//USE addRequiredCallback instead of this condition
						else if (req.min.length > 0) {
						// this must be a funtion
						// split by ";", first part is function, second is error message
							part = req.min.split(';');
							
							var func = part[0];
							var error1 = part[1];
							var error2 = part[2];

							stat = eval(func + '("' + this.docForm[req.field].value + '");');
							
							if (stat != 3) {

								if (stat == 2) {
									error = error2; //is a pobox
								} //if
								else if(stat ==  1) {
									error = error1; //is not > 2 characters
								} //elseif
								else if(stat == 0) {
									error = error1 + " " + error2; // this is not really possible
								} //elseif
								
								if (error != undefined) {
									alertMsgEnd += error + "\n";
								} //if
								else {
									errorFields[errorFields.length] = req.name;
								} //elseif
								frmErrors = true;
							} //if
						} //else if
*/
				} //switch
			} //for

			for (i = 0; i < this.mustMatch.length; i++) {
				req = this.mustMatch[i];

				if (this.docForm[req.mirror].value != this.docForm[req.field].value) {
					alertMsgEnd += req.name + " and " + req.mirrorName + " must match.\n";
				} //if
			} //for

			for (i = 0; i < this.requiredCallBack.length; i++) {
				req = this.requiredCallBack[i];

				if (req.callBack(this.docForm[req.field].value, this.docForm[req.field]) != true) {
					alertMsgEnd += req.errorMsg + "\n";
					frmErrors = true;
				} //if
			} //for

			if (frmErrors) {
				for (i = 0; i < (errorFields.length - 1); i++) {
					alertMsg += ' ' + errorFields[i];

					if (errorFields.length > 2) {
						alertMsg += ',';
					} //if
				} //for
				
				if (errorFields.length > 1) {
					alertMsg += ' and ' + errorFields[(errorFields.length - 1)] + ' to continue.\n';
				} //if
				else if (errorFields.length > 0) {
					alertMsg += ' ' + errorFields[(errorFields.length - 1)] + ' to continue.\n'; 
				} //else if 

				if (alertMsg.length > 0) {
					alertMsg = 'You must enter your' + alertMsg;
				} //if
				
				alertMsg += alertMsgEnd;

				alert(alertMsg);
			} //if
			else {
				if (this.onSubmit) {
					this.onSubmit();
				} //if

				this.docForm.submit();
			} //else
		} //func
	} //func

/**
*	Returns up to max numbers from str
*/
	function tplNumsOnly(str, max, decimal) {
		var out = '';
		for (i = 0; i < str.length; i++) {

			addit = null;
			if (max > 0 && out.length >= max) {
				addit = true;
			} //if
			else {
				if (decimal != false) {
					addit = str.charAt(i).match(/([0-9.])/gi);
				} //if
				else {
				    addit = str.charAt(i).match(/([0-9])/gi);
				} //else				
			} //else

			if (addit != null) {
				out += str.charAt(i);
			}
		}
		return out;
	} //func

/**
*	Returns up to max numbers from str
*/
	function tplMaxLength(field, max) {
		str = field.value;
		str.substr(0, max);
		field.value = str;
	} //func

/**
* Sets the value of field to numbers only
*/
	function tplFormatNum(field) {
		if (!field && this) {
			field = this;
		} //if

		newStr = tplNumsOnly(field.value);

		field.value = newStr;
	} //func

/**
* Sets the value of field to field's value in 333-333-4444(x###) phone format
*/
	function tplFormatPhone(field) {
		if (!field && this) {
			field = this;
		} //if

		input  = field.value;
		lastKey = input.substr(input.length - 1, 1);

		newStr = tplNumsOnly(input, 10, false);

		newStr1 = newStr.substr(0, 3);
		newStr2 = newStr.substr(3, 3);
		newStr3 = newStr.substr(6, 10);

	    out = newStr1;

		if (newStr.length > 0) {
		    out = newStr1;

			if (newStr.length >= 4) {
				out += '-' + newStr2;

				if (newStr.length >= 7) {
					out += '-' + newStr3;
				} //if
				else if (lastKey == '-') {
					out += '-';
				} //else if
			} //if
			else if (lastKey == '-') {
				out += '-';
			} //else if
		} //if

		field.value = out;
	} //func

/**
* Sets the value of field to numbers only
*/
	function tplFormatWord(field) {
		if (!field && this) {
			field = this;
		} //if

		newStr = tplUcwords(field.value);

		field.value = newStr;
	} //func

/**
* Sets the value of field to field's value in 333-22-4444 SSN format
*/
	function tplFormatSSN(field) {
		newStr = tplNumsOnly(field.value);

		newStr1 = newStr.substr(0, 3);
		newStr2 = newStr.substr(3, 2);
		newStr3 = newStr.substr(5, 9);

		out = '';
		if (newStr.length > 0) {
		    out = newStr1;
		} //if

		if (newStr.length > 2) {
		    out += '-' + newStr2;
		} //if

		if (newStr.length > 4) {
		    out += '-' + newStr3;
		} //if

		field.value = out.substr(0, 11);
	} //func

/**
* Returns true|false if email fits standard format
*/
	function tplValidEmail(email) {
		valid = email.match(/\b(^(\S+@).+\.(.{2,4})$)\b/gi);
		return valid;
	}

/**
* Returns true|false if phone fits standard format
*/
	function tplValidPhone(phone) {
		valid = phone.match(/([0-9]{3})-([0-9]{3})-([0-9]{4})(.*)/gi);
		return valid;
	}

/**
* Returns bitmap: 1 if it is at least 2 characters long,  2 if is not a PO Box, 3 if both
*/
	function tplPhysicalAddress(street) {

		valid = 0;
		if (street.length > 2) {
			valid += 1;
		} //if

		test = street.match(/^\s*p\.?\s*o\.?\s*box.*$/gi);

		if (!test) {
			valid += 2;
		} //if

		return valid;
	}

/**
* Tests if street is a valid Physical Address (i.e. not a P.O. Box)
* Returns bool: 0 if it matches regex /^\s*p\.?\s*o\.?\s*box.*$/gi,  1 if not
*/
	function tplValidPhysicalAddress(street) {

		valid = 0;

	//must be at least 2 characters long
		if (street.length > 1) {

			test = street.search(/^\s*p\.?\s*o\.?\s*box.*$/gi);
	
		//if test failed then it is not a PO Box
			if (test == -1) {
				valid = 1;
			} //if

		} //if

		return valid;
	}

	
/**
*
*/
	function tplMirrorValue(field1, field2, ifCase, mode) {
		if (!field1 || !field2) {
			return false;
		} //if

		if (ifCase != true && ifCase != false) {
			ifCase = eval(ifCase);
		} //if

		if (ifCase != true) {
			return false;
		} //if

		if (mode == '+') {
			field1.value += ' ' +  field2.value;
		} //if
		else {
		    field1.value = field2.value;
		} //else
	} //func

/**
*
*/
function tplUcwords(str) {
    var pattern = /(\w)(\w*)/; // a letter, and then one, none or more letters 

    var a = str.split(" "); // split the sentence into an array of words


    for (i = 0 ; i < a.length ; i ++ ) {
        var parts = a[i].match(pattern); // just a temp variable to store the fragments in.

		if (parts) {
			firstLetter = '';
			restOfWord = '';

			if (parts.length > 1) {
				var firstLetter = parts[1].toUpperCase();
			} //if

			if (parts.length > 2) {
				var restOfWord = parts[2].toLowerCase();
			} //if 

			a[i] = firstLetter + restOfWord; // re-assign it back to the array and move on
		} //if        
    }

	str = a.join(' ');
	if (a.length > 1 && a[(a.length - 1)] == "") {
		//str += ' ';
	} //if
    
    return str; // join it back together
}

function strMoney(num) {
	num = num.toString().replace(/\$|\,/g,'');
	if(isNaN(num)) {
		return 'n/a';
	}
	else {
		sign = (num == (num = Math.abs(num)));
		num = Math.floor(num*100+0.50000000001);
		cents = num%100;
		num = Math.floor(num/100).toString();
		if(cents<10)
			cents = "0" + cents;
		for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
			num = num.substring(0,num.length-(4*i+3))+','+
		num.substring(num.length-(4*i+3));

		return (((sign)?'':'-') + '$' + num + '.' + cents);
	}
}
