/// <reference path="prototypePacked.js" />
/// <reference path="HO.js" />
/**********************************************************
HO.Validation library is an extension to the HO library.
This library is used for client side validation. It can be
used for form validation or real-time form element format
validation. It should also be used with the Validation.css
Style sheet file.
***********************************************************/
if((typeof HO=='undefined'))
    throw ("HO.Validation requires the HO JavaScript framework >= 1.0.0");

   HO.Validation = {
   	Version: '1.0.7',
   	Copyright: 'Copyright(c) HarborObjects',
   	Author: 'Glenn Byron',
   	countryUSA: '229',

   	FirstEmptyField: null,
   	// **************************************************************
   	// Used by form validation most of the time.
   	// When used in form validation make sure you check
   	// the different form elements in order so the first element
   	// that is emptpy can be found. Then use the setFocusFirstField()
   	// function to return to or set focus to the first empty element.
   	// **************************************************************
   	isNotEmpty: function(el) {

   		if (el.length == 0) {
   			if (!el) return false;
   		}
   		if (el.length > 0 && el.type != 'select-one') {
   			return this.isRadioListChecked(el);
   		} else if (el.type == 'select-one') {
   			if (el.length == 0) return false;
   			if (el.options[0].selected == true) {
   				this.setErrorColor(el);
   				this._setFirstEmpty(el);
   				return false;
   			}
   		} else if (el.type == 'text' || el.type == 'password' || el.type == 'hidden' || el.type == 'textarea') {
   			if (el.value == "" || el.value == null || el.value == 0) {
   				this.setErrorColor(el);
   				this._setFirstEmpty(el);
   				return false;
   			}
   		} else if (el.type == 'checkbox') {
   			if (!el.checked) {
   				this.setErrorColor(el);
   				this._setFirstEmpty(el);
   				return false;
   			}
   		} else if (el.type == 'radio') {
   			if (!el.checked) {
   				this.setErrorColor($(el.name));
   				this._setFirstEmpty(el);
   			}
   		}
   		return true
   	},

   	isRadioListChecked: function(el) {
   		var radioList;
   		if (el.length == 0)
   			radioList = $A(document.getElementsByName(el.name));
   		else
   			radioList = $A(el);

   		// for IE6 removes top extra element in collection
   		//if(Prototype.Browser.IE) radioList = radioList.without(radioList[0]);

   		for (var i = 0; i < radioList.length; i++) {
   			if (radioList[i].checked) return true;
   		}
   		this._setFirstEmpty(el);

   		// remove labels from list of all labels on form that
   		// are not associated to the list of radio buttons
   		// (htmlfor does not work on IE6)
   		var labelList = $A(document.getElementsByTagName('label')).findAll(function(label) { return label.innerHTML.trim() != ''; });
   		var tempList = labelList;
   		var ckLabel = null;
   		for (var i = 0; i < tempList.length; i++) {
   			ckLabel = radioList.find(function(radioEl) { return (tempList[i].htmlFor == radioEl.id); });
   			if (ckLabel == null) {
   				labelList = labelList.without(tempList[i])
   			}
   		}

   		// sets the error color on the IE radio buttons, and the labels for everyone else.
   		for (var i = 0; i < radioList.length; i++) {
   			var index = radioList.indexOf(radioList[i]);
   			if (labelList[index]) {
   				if (index >= 0) {
   					$(labelList[index]).update('<span class="errorCheckRadioLabel">' + labelList[index].innerHTML + '</span>');
   					this.setErrorColor(radioList[i]);
   				}
   			}
   		}
   		return false;
   	},

   	isSignedNumeric: function(el) {
   		if (el.value.toString().isSignedNumeric()) return true;
   		alert("The selected field must be a number.");
   		this.selectError(el);
   		return false;
   	},

   	isPositiveNumeric: function(el) {
   		if (el.value.toString().isPositiveNumeric()) return true;
   		alert("The selected field must be a positive number.");
   		this.selectError(el);
   		return false;
   	},

   	isSignedInteger: function(el) {
   		if (el.value.toString().isSignedInteger()) return true;
   		alert("The selected field must be a whole number (no decimal).");
   		this.selectError(el);
   		return false;
   	},

   	isPositiveInteger: function(el) {
   		if (el.value.toString().isPostiveInteger()) return true;
   		alert("The selected field must be a positive, whole number (no decimal).");
   		this.selectError(el);
   		return false;
   	},

   	isUSCurrency: function(el) {
   		if (el.value.toString().isUSCurrency()) return true;
   		alert("The selected field must be a currency amount.");
   		this.selectError(el);
   		return false;
   	},

   	isEmailAddr: function(el) {
   		var inputStr = el.value.toString();
   		if (inputStr.length == 0) return true
   		//inputStr = inputStr.toLower();

   		var checkTLD = 1;
   		var knownDomsPat = new $A(Array(
		'com', 'net', 'org', 'biz', 'coop', 'info', 'museum', 'name', 'pro', 'edu', 'gov', 'int', 'mil',
		'ac', 'ad', 'ae', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao', 'aq', 'ar', 'as', 'at', 'au', 'aw', 'az',
		'ba', 'bb', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'bj', 'bm', 'bn', 'bo', 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz',
		'ca', 'cc', 'cd', 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'cr', 'cu', 'cv', 'cx', 'cy', 'cz',
		'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'ee', 'eg', 'eh', 'er', 'es', 'et', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr',
		'ga', 'gd', 'ge', 'gf', 'gg', 'gh', 'gi', 'gl', 'gm', 'gn', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gv', 'gy',
		'hk', 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il', 'im', 'in', 'io', 'iq', 'ir', 'is', 'it',
		'je', 'jm', 'jo', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', 'kr', 'kw', 'ky', 'kz',
		'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly',
		'ma', 'mc', 'md', 'mg', 'mh', 'mk', 'ml', 'mm', 'mn', 'mo', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'mv', 'mw', 'mx', 'my', 'mz',
		'na', 'nc', 'ne', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz',
		'om', 'pa', 'pe', 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'ps', 'pt', 'pw', 'py', 'qa', 're', 'ro', 'rw', 'ru',
		'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr', 'st', 'sv', 'sy', 'sz', 'tc',
		'td', 'tf', 'tg', 'th', 'tj', 'tk', 'tm', 'tn', 'to', 'tp', 'tr', 'tt', 'tv', 'tw', 'tz',
		'ua', 'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'ws', 'wf', 'ye', 'yt', 'yu', 'za', 'zm', 'zw'));
   		var emailPat = /^(.+)@(.+)$/;
   		var specialChars = "\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
   		var validChars = "\[^\\s" + specialChars + "\]";
   		var quotedUser = "(\"[^\"]*\")";
   		var ipDomainPat = /^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
   		var atom = validChars + '+';
   		var word = "(" + atom + "|" + quotedUser + ")";
   		var userPat = new RegExp("^" + word + "(\\." + word + ")*$");
   		var domainPat = new RegExp("^" + atom + "(\\." + atom + ")*$");
   		var matchArray = inputStr.match(emailPat);

   		if (matchArray == null) {
   			alert("Email address Is invalid");
   			this.selectError(el);
   			return false;
   		}

   		var user = matchArray[1];
   		var domain = matchArray[2];
   		for (i = 0; i < user.length; i++) {
   			if (user.charCodeAt(i) > 127) {
   				alert("Email address username contains invalid characters.");
   				this.selectError(el);
   				return false;
   			}
   		}

   		for (i = 0; i < domain.length; i++) {
   			if (domain.charCodeAt(i) > 127) {
   				alert("Email address domain name contains invalid characters.");
   				this.selectError(el);
   				return false;
   			}
   		}

   		if (user.match(userPat) == null) {
   			alert("Email address username is invalid.");
   			this.selectError(el);
   			return false;
   		}

   		var IPArray = domain.match(ipDomainPat);
   		if (IPArray != null) {
   			for (var i = 1; i <= 4; i++) {
   				if (IPArray > 255) {
   					alert("Email address destination IP address is invalid.");
   					this.selectError(el);
   					return false;
   				}
   			}
   			return true;
   		}

   		var atomPat = new RegExp("^" + atom + "$");
   		var domArr = domain.split(".");
   		var len = domArr.length;
   		for (i = 0; i < len; i++) {
   			if (domArr[i].search(atomPat) == -1) {
   				alert("Email address domain name is invalid.");
   				this.selectError(el);
   				return false;
   			}
   		}

   		if (checkTLD && null == knownDomsPat.find(function(domainType) { return (domainType == domArr[domArr.length - 1]); })) {
   			alert("Email address domain name extension is invalid");
   			this.selectError(el);
   			return false;
   		}

   		if (len < 2) {
   			alert("Email address is missing a hostname.");
   			this.selectError(el);
   			return false;
   		}
   		return true;
   	},

   	hasNoSpaces: function(el) {
   		var inputStr = el.value.toString();
   		if (el.type == 'text' || el.type == 'textarea' || el.type == 'password') {
   			if (inputStr.indexOf(' ') >= 1) {
   				alert("The selected field must not have spaces in it.")
   				this.selectError(el);
   				return false;
   			}
   		}
   		return true;
   	},

   	isUSPhone: function(el) {
   		if (el.value.toString().isUSPhone()) {
   			el.value = el.value.toString().cleanSeperators().restoreUSPhone();
   			return true;
   		}
   		alert("A phone number must be 10 numbers only, including Area Code.  The entry format is \'212-555-1212\' or \'2125551212\' or \'(714)555-1212\'.")
   		this.selectError(el);
   		return false
   	},

   	isUSDate: function(el) {
   		if (el.value.toString().isUSDate()) return true;
   		alert("The is not a valid date.\n\nYou can enter dates in the following formats: mmddyyyy, mm/dd/yyyy, or mm-dd-yyyy.  (If the month or date data is not available, enter \'01\' in the appropriate location.)")
   		this.selectError(el);
   		return false; //any other values, bad date
   	},

   	isUSTime: function(el) {
   		if (el.value.toString().isUSTime(true)) return true;
   		alert("The is not a valid time.\n\nYou can enter time in the following format: HH:MM:SS AM/PM (seconds and AM/PM are optional).")
   		this.selectError(el);
   		return false; //any other values, bad time
   	},

   	//checks for formatting of time with AM or PM
   	isUSTimeFormat: function(el) {
   		if (el.value.toString().isUSTime(false)) return true;
   		alert("The is not a valid time.\n\nYou can enter time in the following format: HH:MM:SS AM/PM (seconds and AM/PM are optional).")
   		this.selectError(el);
   		return false; //any other values, bad time
   	},

   	isUSZipCode: function(el) {
   		if (el.value.toString().isPostiveInteger()) {
   			if (el.value.toString().isUSZipCode()) return true;
   			alert("Enter the first five digits of the ZIP code in this field.")
   			this.selectError(el);
   			return false
   		} else {
   			alert("A Zip Code must be all numbers in this field.")
   			this.selectError(el);
   			return false;
   		}
   	},

   	//********************
   	// validation utilities
   	//********************
   	setErrorColor: function(el) {
   		if (el.length > 0 && el.type != 'select-one') return;
   		if (!el) return;

   		if (el.style) {
   			if (el.type == 'select-multiple' && el.type != 'select-one') {
   				Element.removeClassName(el, 'defaultSelectMulti');
   				Element.addClassName(el, 'errorSelect');
   				Event.observe(el, 'blur', this.resetColor.bind(el), true);
   			} else if (el.type == 'select-one') {
   				Element.removeClassName(el, 'defaultSelectOne');
   				Element.addClassName(el, 'errorSelect');
   				Event.observe(el, 'change', this.resetColor.bind(el), true);
   			} else if (el.type == 'text' || el.type == 'password' || el.type == 'textarea') {
   				Element.removeClassName(el, 'defaultTextBox');
   				Element.addClassName(el, 'errorTextBox');
   				Event.observe(el, 'blur', this.resetColor.bind(el), true);
   			} else if (el.type == 'checkbox') {
   				Element.addClassName(el, "errorCheckRadio");
   				var labelList = $A(document.getElementsByTagName('label')).findAll(function(label) { return label.innerHTML.trim() != ''; });
   				var tempList = labelList;
   				var ckLabel = null;
   				for (var i = 0; i < tempList.length; i++) {
   					if (tempList[i].htmlFor != el.id) labelList = labelList.without(tempList[i])
   				}
   				if (labelList.length > 0) {
   					$(labelList[0]).update('<span class="errorCheckRadioLabel">' + labelList[0].innerHTML + '</span>');
   				}
   				Event.observe(el, 'click', this.resetColor.bind(el), true);
   			} else if (el.type == 'radio') {
   				Element.removeClassName(el, "defaultCheckRadio");
   				Element.addClassName(el, "errorCheckRadio");
   			}
   		}
   	},

   	setDefaultColor: function(el) {
   		var tempResetColor = new Function();
   		tempResetColor = this.resetColor.bind($(el));
   		tempResetColor();
   		return;
   	},

   	resetColor: function() {
   		Event.stopObserving(this, 'blur', this.resetColor);
   		if (this.style) {
   			if (this.length > 0 && this.type != 'select-one') {
   				var labels = $A(document.getElementsByTagName('label'));
   				for (var i = 0; i < this.length; i++) {
   					var el = labels.find(function(label) { return (label.attributes[0].value == this[i].id); });
   					this[i].update(stuff.innerHTML.stripTags("span"));
   					this[i].removeClassName("errorCheckRadio");
   					this[i].addClassName("defaultCheckRadio");
   				}
   			} else if (this.type == 'select-multiple' && this.type != 'select-one') {
   				this.removeClassName("errorSelect");
   				this.addClassName("defaultSelectMulti");
   			} else if (this.type == 'select-one') {
   				this.removeClassName("errorSelect");
   				this.addClassName("defaultSelectOne");
   			} else if (this.type == 'text' || this.type == 'password' || this.type == 'textarea') {
   				this.removeClassName("errorTextBox");
   				this.addClassName("defaultTextBox");
   			} else if (this.type == 'checkbox') {
   				var labelList = $A(document.getElementsByTagName('label')).findAll(function(label) { return label.innerHTML.trim() != ''; });
   				var tempList = labelList;
   				for (var i = 0; i < tempList.length; i++) {
   					if (tempList[i].htmlFor != this.id) labelList = labelList.without(tempList[i])
   				}
   				if (labelList.length > 0) {
   					$(labelList[0]).update(labelList[0].innerHTML.stripTags());
   				}
   				this.removeClassName("errorCheckRadio");
   				this.style.border = "";
   			} else if (this.type == 'radio') {
   				this.removeClassName("errorCheckRadio");
   				this.addClassName("defaultCheckRadio");
   			}
   		}
   	},

   	resetRadioColors: function() {
   		var radioList = $A(document.getElementsByName(this.name));

   		// for IE removes extra element from top of collection
   		if (Prototype.Browser.IE) {
   			radioList = radioList.without(radioList[0]);
   		}

   		// remove labels from list of all labels on form that
   		// are not associated to the list of radio buttons
   		// (htmlfor does not work on IE)
   		var labelList = $A(document.getElementsByTagName('label')).findAll(function(label) { return label.innerHTML.trim() != ''; }); ;
   		var tempList = labelList;
   		var ckLabel = null;
   		for (var i = 0; i < tempList.length; i++) {
   			ckLabel = radioList.find(function(radioEl) { return (tempList[i].htmlFor == radioEl.id); });
   			if (ckLabel == null) {
   				labelList = labelList.without(tempList[i])
   			}
   		}

   		for (var i = 0; i < radioList.length; i++) {
   			var index = radioList.indexOf(radioList[i]);
   			if (index >= 0) {
   				$(labelList[index]).update(labelList[index].innerHTML.stripTags());
   				Element.removeClassName(radioList[i], "errorCheckRadio");
   				Element.addClassName(radioList[i], "defaultCheckRadio");
   			}
   		}
   	},

   	selectError: function(el, doNotDefault) {
   		if (!el) return false;
   		//setTimeouts required for IE
   		if (!doNotDefault) el.value = el.defaultValue
   		setTimeout(function() { HO.Validation.setErrorColor(el) } .bind(el), 0);
   		setTimeout(function() { el.focus() } .bind(el), 0);
   		if (el.type != 'select-one') el.select();
   	},

   	_setFirstEmpty: function(el) {
   		if (!this.FoundEmpty) {
   			this.FirstEmptyField = el;
   			this.FoundEmpty = true;
   		}
   	},

   	setFocusFirstField: function() {
   		if (this.FirstEmptyField && this.FirstEmptyField.style) setTimeout("HO.Validation.FirstEmptyField.focus()", 0);
   		this.FoundEmpty = false;
   	},

   	//*****************
   	// Submit validation stuff
   	//********************
   	formElementsToValidate: function(elementId, errorMsg) {
   		this.ElementId = elementId;
   		this.ErrorMsg = errorMsg;
   	},

   	getErrorMessageTop: function(msg) {
   		if (msg == "") {
   			msg = "______________________________________________________\n\n";
   			msg += "You were not able to Continue because of the following error(s).\n";
   			msg += "Please correct these error(s) and click Continue.\n";
   			msg += "______________________________________________________\n\n";
   		}
   		return msg;
   	},

   	getAddressErrorMessageTop: function(msg) {
   		if (msg == "") {
   			msg = "______________________________________________________\n\n";
   			msg += "You started an address, but we don't have everything required.\n";
   			msg += "Please correct these error(s) and click Continue.\n";
   			msg += "______________________________________________________\n\n";
   		}
   		return msg;
   	},

   	submitValidation: function(formElements) {
   		var msg = '';
   		for (var i = 0; i < formElements.length; i++) {
   			var validateField = $(formElements[i].ElementId);
   			if (validateField == null || typeof (validateField.type) == 'undefined' ||
					(validateField.type == 'radio' && document.getElementsByName(formElements[i].ElementId).length >= 1) ||
					(validateField.type == 'checkbox' && document.getElementsByName(formElements[i].ElementId).length >= 1)
					) {
   				validateField = document.getElementsByName(formElements[i].ElementId)
   				if (typeof (validateField.type) == 'undefined' && typeof(formElements[i].ElementId) == 'object') {
   					validateField = formElements[i].ElementId;
   				}
   			}

   			if (!this.isNotEmpty(validateField)) {
   				msg = this.getErrorMessageTop(msg);
   				msg += "-" + formElements[i].ErrorMsg + ".\n";
   			}
   		}
   		return msg;
   	},

   	compareValidator: function(firstElement, secondElement, errorMsg) {
   		if (!(firstElement && secondElement)) return;

   		var msg = '';

   		//If these are IDs they are now elements
   		firstElement = $(firstElement);
   		secondElement = $(secondElement);

   		if (firstElement.value != '' && secondElement.value != '') {
   			if (firstElement.value.toLowerCase() != secondElement.value.toLowerCase()) {
   				msg = this.getErrorMessageTop(msg);
   				msg += "-" + errorMsg + "\n";
   				this.setErrorColor(firstElement);
   				this.setErrorColor(secondElement)
   				this._setFirstEmpty(firstElement);
   			} else {
   				this.setDefaultColor.bind(firstElement);
   				this.setDefaultColor.bind(secondElement);
   			}
   		}
   		return msg;
   	},

   	submitAddressValidation: function(elAddress1, elAddress2, elCity, elState, elPostalCode, elCountryID) {
   		for (var i = 0; i < arguments.length; i++) {
   			if (typeof (arguments[i]) == 'string') arguments[i] = $(arguments[i]); //make sure they are form elements
   			if (typeof (arguments[i]) != 'undefined' && arguments[i]) {
   				this.setDefaultColor(arguments[i]);
   			}
   		}

   		var countryID = this.countryUSA; // default to USA if no country form field
   		if (typeof (elCountryID) != 'undefined' && elCountryID != null) {
   			if (elCountryID.value == '0') elCountryID.value == '';
   			countryID = elCountryID.value;
   		}

   		// if address is only in second address element swap with first
   		if (elAddress1.value == "" && elAddress2.value != "") {
   			elAddress1.value = elAddress2.value;
   			elAddress2.value = "";
   		}

   		var msg = ""
   		if (elAddress1.value + elAddress2.value + elCity.value + elState.value + elPostalCode.value != "" ||
				(typeof (elCountryID) != 'undefined' && countryID == this.countryUSA && elState.value != "")) {

   			formElements = new Array();
   			formElements[0] = new this.formElementsToValidate(elAddress1, 'You must enter an address');
   			formElements[1] = new this.formElementsToValidate(elCity, 'You must enter a city');

   			for (var i = 0; i < formElements.length; i++) {
   				if (!this.isNotEmpty(formElements[i].ElementId)) {
   					msg = this.getAddressErrorMessageTop(msg);
   					msg += "-" + formElements[i].ErrorMsg + ".\n";
   				}
   			}
   			if (countryID == this.countryUSA && !this.isNotEmpty(elState)) {
   				msg = this.getAddressErrorMessageTop(msg);
   				msg += "-" + "You must select a state.\n";
   				this._setFirstEmpty(elState);
   			}
   			if (countryID == this.countryUSA && !this.isNotEmpty(elPostalCode)) {
   				msg = this.getAddressErrorMessageTop(msg);
   				msg += "-" + "You must enter a postal code.\n";
   				this._setFirstEmpty(elPostalCode);
   			}
   		}
   		return msg;
   	}
   }

