/// <reference path="prototype.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.5',
	Copyright: 'Copyright (c)HarborObjects',
	Author: 'Glenn Byron',
	countryUSA: '229',

	FirstEmptyField: null,
    className:' ',    
	// **************************************************************
	// 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 IE 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 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])
			}
		}
		
		// 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;
	},

	isNumeric: function(el) {
		if (el.value.toString().isNumberic()) return true;
		alert("The selected field must be a 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 positive, whole number (no decimal).");
		this.selectError(el);
		return false;
	},

	isEmailAddr: function(el) {
		var inputStr = el.value.toString();		
		if (inputStr.length == 0) return true
		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("The 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("The Username Contains Invalid Characters."); 
				this.selectError(el);
				return false; 
			} 
		} 

		for (i=0; i<domain.length; i++) { 
			if (domain.charCodeAt(i)>127) { 
				alert("Ths Domain Name Contains Invalid Characters."); 
				this.selectError(el);
				return false; 
			} 
		} 

		if (user.match(userPat)==null) { 
			alert("The 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("The 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("The Domain Name Is Invalid."); 
				this.selectError(el);
				return false; 
			} 
		} 

		if (checkTLD && null == knownDomsPat.find(function(domainType){return (domainType == domArr[domArr.length-1]);})) {
			alert("The Domain Name Extension Is Invalid"); 
			this.selectError(el);
			return false; 
		} 

		if (len<2) { 
			alert("The 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 vaild 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
	},

	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;
		className=el.className; 		      
		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');
				Element.removeClassName(el, 'input_name');
				Element.removeClassName(el, 'textBoxCss');
				
				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");
				className=this.className; 				
				if(className=='input_name')
				this.addClassName("input_name");
				else
				this.addClassName("textBoxCss");
			} 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 = document.getElementsByName(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 && seconElement)) 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 = valid.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') {
			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;
	}
}


