/* --------------------------------

<input name='phoneNumber' validate='type:phone;'/>
OR

var p = document.forms[0].phoneNumber;
p.setAttribute('validate','type:phone;required:true;');
FormValidate.initElement(p);
--------------------------------- */
var FormValidate = { 
	version : { 
		number 	: '1.06', 
		date 	: '02 March 2006',
		author 	: 'Steven Moberg',
		complete : true
	},		
	isValid : [true,false,false],
	status 	: ['valid','invalid','required'],
	
	onKeyUp : function(e){
		e = e.validate_handleFor || e;
		var v = e.validate;
		var _e = e.validate_elements;
		var s = 0;
		if(_e[0].value.length === 0 && v.required)
		{ s = 2; }
		if(s === 0 && v.maxLength > 0)
			{s = (Validate.maxLength(_e[0].value,v.maxLength))?0:1;}
		if(s === 0 && v.minLength > 0)
			{s = (Validate.minLength(_e[0].value,v.minLength))?0:1;}
		return FormValidate.setStatus(e,s);
	},
	
	onBlur : function(e){
		e = e.validate_handleFor || e;
		var v = e.validate;
		var _e = e.validate_elements;
		_e[0].value = _e[0].value.trim();
		if(!FormValidate.onKeyUp(e)) {
			return false; /* item is empty not invalid  */
		}	
		var s = (v.type && !Validate.isValid(_e[0].value, v.type))?1:0;
		return FormValidate.setStatus(e,s);	
	},
	
	onClick : function(e){
		e = e.validate_handleFor || e;
		var v    = e.validate;
		var _e   = e.validate_elements;		
		var _s 	 = v.status;
		var s 	 = 0;
		var c 	 = 0;
		
		for(var i=0; i<_e.length; i++){
			if(_e[i].checked) {c++;} /* incremment valid count */
		}
		/* set valid type based on number of valid items */
		if((v.required && c === 0) || (v.minLength && c < v.minLength))
			{s = 2;} /* required */
		else if(v.maxLength && c > v.maxLength)
			{s = 1;} /* invalid */
		
		/* mark valid status on element and update background color */
		for(var i=0; i<_e.length; i++){
			ClassName.replace(_e[1].parentNode, v[FormValidate.status[s]+'Class'], v[FormValidate.status[_s]+'Class']);
		}
		return FormValidate.setStatus(e,s);
	},
	
	onChange : function(e){
		e = e.validate_handleFor || e;
		var thisStatus = 0;
		var v = e.validate;
		var _e = e.validate_elements[0];	
				
		if(_e.type == 'select-one'){
			if(v.required && _e.selectedIndex < 0)
				s = 2; /* required */
			else if( !Validate.isValid( _e.options[e.selectedIndex] , v.type , v.pattern ) ){
				_e.options[e.selectedIndex].selected = false;
				if(v.required) s = 2; /* required */
			}
		} else {
			/* select-multiple */
			var c = 0;
			for(var i=0; i<_e.options.length; i++){
				if(_e.options[i].selected){
					if(Validate.isValid( _e.options[i], v.type, v.pattern))
						c++;
					else 
						_e.options[i].selected = false;
				}			
			}
			if((v.required && c == 0) || (v.minlength && c < v.minlength))
				s = 2; /* required */
			else if(v.maxlength && c > v.maxlength)
				s = 1; /* invalid */
		}
		
		return FormValidate.setStatus(e,s);
	},
	
	onSubmit : function(f){
		var self = FormValidate;
		var _1 = self.checkForm(f,true);	
		
		if(_1.length){
			if(f.validate.messageTarget == 'alert')
				alert('Invalid Entry Form\n\n'+f.validate_errors.join('\n'));
			else if(f.validate.messageTarget != null)
				f.validate.messageTarget.innerHTML = 'Invalid Entry Form<br/><br/>'+frm.validate_errors.join('<br/>');
			return false;
		} else if(typeof f.validate_onsubmit == 'function'){	
			return f.validate_onsubmit();
		} else {
			return true;
		}
	},	
	oldSchool : function(e){
		var obj = {
			type 			: e.getAttribute('validate'),
			required 		: e.getAttribute('required'),
			message 		: e.getAttribute('message'),
			handleFor		: e.getAttribute('handleFor'),
			validClass 		: e.getAttribute('validClass'),
			invalidClass 	: e.getAttribute('invalidClass'),
			requiredClass 	: e.getAttribute('requiredClass'),
			maxLength		: e.getAttribute('maxLength'),
			minLength		: e.getAttribute('minLength')
		};
		if(typeof obj.type == 'string' && (obj.type.length == 0 || obj.type.indexOf(':') > -1)) obj.type = null;
		if(obj.required != null) obj.required = true;
		var s = "old school\n\n";
		for(o in obj){
			if(obj[o] == null) delete obj[o];
			else s+= o+' : '+obj[o]+'\n';
		}
		return obj;
	}
}
FormValidate.setStatus = function(e,s){
	var self = FormValidate;
	var v = e.validate;
	var _s = v.status;	
	var m = '';
	v.status = s;
	
	ClassName.replace(e, v[self.status[s]+'Class'], v[self.status[_s]+'Class']);
	if(s !== 0){
		m = v.message || self.status[s]+': '+e.name;
		e.form.validate_errors.push(m);
		if(v.suppressInlineMessage || FormValidate.suppressErrors)
			m = '';
	} 
	if(s == 1 && m.length){
		if(v.messageTarget == 'alert')	alert(m);
		else if(v.messageTarget != null) v.messageTarget.innerHTML += m + "<br/>";
	}	
	return self.isValid[s];	
}
FormValidate.checkElement = function(e,b){
	if(b === true) FormValidate.suppressErrors = true;
	var s = 0;
	switch (e.type) {
	  case 'select-one':
	  case 'select-multiple':
		s = FormValidate.onChange(e); break;
	  case 'radio':
	  case 'checkbox':
	  case 'hidden':
		s = FormValidate.onClick(e); break;
	  default :
		s = FormValidate.onBlur(e); break;
	}
	if(b === true) FormValidate.suppressErrors = false;
	return s;
}
FormValidate.checkForm = function(f,s){
	var _1 = [];	
	f.validate_errors = [];
	for(var i=0, e; e = f.validate_elements[i]; i++)
		if(!e.isValid(s)) _1.push(e);
	return _1;
}

/* ********************* Initialize Items ********************* */
FormValidate.init = function(){
	for(var i=0, f; f = document.forms[i]; i++)
		FormValidate.initForm(f);		
}
FormValidate.initForm = function(frm,wElements){
	var self = FormValidate;
	var vStyle = frm.getAttribute('validate');
	
	var v = {
		messageTarget : 'alert',
		suppressInitValidation : true,
		suppressInitMessage : true,
		suppressInlineMessage : false,
		validClass : null,
		invalidClass : null,
		requiredClass : null
	};
	if(typeof vStyle == 'string' && vStyle.length){ 
		vStyle = vStyle.styleToObject();
		for(s in vStyle)
			v[s] = vStyle[s];
	}
	vStyle = self.oldSchool(frm);
	for(s in vStyle){ v[s] = vStyle[s]; }
	/*for(s in v) */
		/* alert(s+' = '+s[v]); */
	
	if(typeof v.messageTarget == 'string' && v.messageTarget != 'alert')
		v.messageTarget = document.getElementById(v.messageTarget);
	
	frm.validate = v;
	frm.validate_elements = [];
	frm.validate_errors   = [];
	frm.validate_onsubmit = frm.onsubmit;
	frm.onsubmit = function(){ return FormValidate.onSubmit(frm); }
	frm.isValid  = function(){ return (FormValidate.checkForm(this,true).length)?false:true;	}
	
	if(wElements === false) return;
	
	for(var i=0, e; e = frm.elements[i]; i++)
		self.initElement(e);
}
FormValidate.initElement = function(e){
	/* this.debug(elem); */
	var self = FormValidate;
	var frm = e.form;
	
	var vStyle = e.getAttribute('validate');
	if(vStyle == null && !/^[\w_]*_validate$/.test(e.name))
		return;
		
	var v = {
		status 		: 0,
		type 		: null,
		handleFor	: null,
		pattern 	: null,
		required 	: null,
		maxLength 	: null,
		minLength 	: null			
	}
	
	for(s in frm.validate){ v[s] = frm.validate[s]; }	
	if(typeof vStyle == 'string' && vStyle.length){ 
		vStyle = vStyle.styleToObject();
		for(s in vStyle){ v[s] = vStyle[s]; }
	}
	vStyle = self.oldSchool(e);
	for(s in vStyle){ v[s] = vStyle[s]; }	
	
	if(typeof v.messageTarget == 'string' && v.messageTarget != 'alert')
		v.messageTarget = document.getElementById(v.messageTarget);
		
		
	frm.validate_elements.push(e);
	e.validate = v;
	e.isValid  = function(s){ return FormValidate.checkElement(e,s); }
	
	if(e.type == 'hidden' && e.validate.handleFor == null && e.name.indexOf('_validate') > -1)
		e.validate.handleFor = e.name.substring(0,e.name.length-9);
	
	var _e = frm[e.validate.handleFor || e.name] || e;
	if(typeof _e[0] == 'undefined') _e = [_e];
	e.validate_elements = _e;
	
	switch (_e[0].type) {
      case 'select-one':
	  case 'select-multiple':
	  	_e[0].validate_handleFor = e;
	  	_e[0].isValid = e.isValid;
		addEvent(_e[0],'change',function(){ FormValidate.onChange(e); }, false);
		break;
	  case 'radio':
	  case 'checkbox':	  	
	   	for(var i=0; i < _e.length; i++){
			_e[i].validate_handleFor = e;
			_e[i].isValid   = e.isValid;
			addEvent(_e[i],'click',function(){ FormValidate.onClick(e); },false);
		}
		break;	
	  default :
	  	_e[0].validate_handleFor = e;
		_e[0].isValid = e.isValid;
		addEvent(_e[0],'keyup',function(){ FormValidate.onKeyUp(e); }, false);
		addEvent(_e[0],'blur' ,function(){ FormValidate.onBlur(e);  }, false);		
	}
	if(!e.validate.suppressInitValidation)
		e.isValid();	
}


/* -------------------------- Library.utility.js -------------------------- */
	if(ClassName == null){
		var ClassName = {
			add : function(n,c) {
				if (!ClassName.has(n,c))
					n.className += " " + c;
			},
			remove : function(n,c){
				var _x = new RegExp("(^|\\s)"+c+"(\\s|$)");
				n.className = n.className.replace(_x, "$2");
			},
			replace : function(n,c1,c2){
				ClassName.add(n,c1);
				if(c2 != null && c2 != c1 && c2 != '')
					ClassName.remove(n,c2);
			},
			has : function(n,c){
				var _x = new RegExp("(^|\\s)"+c+"(\\s|$)");
				return _x.test(n.className);
			}
		}
	} 
	if(typeof addEvent == 'undefined'){
		function addEvent(obj,type,fn,useCapture){
			if(window.addEventListener){
				obj.addEventListener(type, fn, useCapture);
			} else if(window.attachEvent){
				obj[type+fn] = function(){ fn.call(this, window.event); }
				obj.attachEvent('on'+type, obj[type+fn]);
			} else {
				obj[type+fn] = obj['on'+type];
				obj['on'+type] = function(){
					fn.call(this, window.event);
					this[type+fn].call(this, window.event);
				}
			} 	
		}
	}
	addEvent(window,'load',FormValidate.init,false);

/* -------------------------- Library.utility.prototype.js -------------------------- */
	if(String.prototype.trim == null)
		String.prototype.trim = function(){ return this.replace(/(^\s+)|\s+$/g,""); }
	if(String.prototype.booleanCheck == null){
		String.prototype.booleanCheck = function(){
			if(this.match(/^(1|yes|true)$/i)) return true;
			if(this.match(/^(0|no|false)$/i)) return false;
			return this;
		}
	}
	if(String.prototype.camelize == null){
		String.prototype.camelize = function() {
			var s = this.split("-");
			for(var t=1; t<s.length; t++)
				s[t] = s[t].substr(0,1).toUpperCase() + s[t].substr(1);
			return s.join("");
		}
	}
	if(String.prototype.capitalize == null){
		String.prototype.capitalize = function() {
			var s = this.split(" ");
			for(var t=1; t<s.length; t++)
				s[t] = s[t].substr(0,1).toUpperCase() + s[t].substr(1).toLowerCase();
			return s.join(" ");
		}
	}
	if(String.prototype.styleToObject == null){
		String.prototype.styleToObject = function(){
			var obj = {};
			var style = this.split(';');
			for(var i=0, s; s = style[i]; i++){
				s = s.split(':');
				obj[s[0].trim().camelize()] = (s.length == 2)?s[1].trim().booleanCheck():null;
			}
			return obj;	
		}
	}
	
	if(Array.prototype.indexOf == null){
		Array.prototype.indexOf = function(value,noCase){
			if(noCase == true) value = value.toUpperCase(); else noCase = false;
			for(var i=0;i<this.length;i++)
				if((value == this[i]) || (noCase && value == this[i].toUpperCase())) return i;
			return -1;
		}
	}
	

/* -------------------------- Library.utility.validate.js -------------------------- */
var Validate = {
	isValid : function(txt,types){
		var valid = true;
		var aryType = types.split('+');
		for(var i=0, thisType; thisType = aryType[i]; i++){
			thisType = thisType.trim();
			if(Validate.alias[thisType.toLowerCase()] != null)
				thisType = Validate.alias[thisType.toLowerCase()];
			if(Validate[thisType] != null){
				valid = false;
				if(Validate[thisType](txt))
					return true;
			}			
		}
		return valid;
	},
	alias : {
		'numeric' 	 : 'isNumeric',
		'int' 		 : 'isInteger',
		'bool' 		 : 'isBoolean',
		'email' 	 : 'isEmail',
		'phone' 	 : 'isPhone',
		'state' 	 : 'isState',
		'apo'		 : 'isAPO',
		'zip' 		 : 'isZip',
		'province' 	 : 'isProvince',
		'postalcode' : 'isPostalCode',
		'password'	 : 'strongPassword'
	}
}

Validate.strongPassword = function(txt,len){
	if(len == null || !Validate.isNumeric(len))
		len = 6;
	return (txt.length >= len && /\d/.test(txt) && /\W/.test(txt) && /[a-z]/.test(txt) && /[A-Z]/.test(txt));
}
Validate.isNumeric = function(txt){
	var numeric = /(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/;
	return numeric.test(txt);	
}
Validate.isInteger = function(txt){
	var integer = /(^-?\d\d*$)/;
	return integer.test(txt);	
}
Validate.isBoolean = function(txt,type){
	var boolTxt = (type == null)?'1|0|yes|no|true|false':(type)?'1|yes|true':'0|no|false';
	var bool = new RegExp('^('+boolTxt+')$');
	return bool.test(txt);
}
Validate.maxLength = function(txt,len,restrict){
	return (txt.length <= len);
}
Validate.minLength = function(txt,len){
	return (txt.length >= len);
}
Validate.minMaxLength = function(txt,minLen,maxLen){
	return ((txt.length <= maxLen) && (txt.length >= minLen));	
}
Validate.isEmail = function(txt){
	var email = /^[0-9A-Z]+([-_.0-9A-Z])*@[0-9A-Z]+([-.][0-9A-Z]+)*[.][A-Z]{2,4}$/i;
	return email.test(txt);
}
Validate.isPhone = function(txt){
	var phone = /^(\([1-9]\d{2}\)\s?)?\d{3}\-\d{4}$/;
	return phone.test(txt);
}

Validate.__ = {
	state : {
		code : ['AL','AK','AS','AZ','AR','CA','CO','CT','DE','DC','FM','FL','GA','HI','ID','IL','IN','IA','KS','KY','LA','ME','MH','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND','MP','OH','OK','OR','PW','PA','PR','RI','SC','SD','TN','TX','UT','VT','VI','VA','WA','WV','WI','WY'],
		name : ['Alabama','Alaska','American Samoa','Arizona','Arkansas','California','Colorado','Connecticut','Delaware','District of Columbia','Federated States of Micronesia','Florida','Georgia','Guam','Hawaii','Idaho','Illinois','Indiana','Iowa','Kentucky','Louisiana','Maine','Marchall Islands','Maryland','Massachusetts','Michigan','Minnesota','Mississippi','Missouri','Montana','Nebraska','Nevada','New Hampshire','New Jersey','New Mexico','New York','North Carolina','North Dakota','Northern Mariana Islands','Ohio','Oklahoma','Oregon','Palau','Pennsylvania','Puerto Rico','Rhode Island','South Carolina','South Dakota','Tennessee','Texas','Utah','Vermont','Virgin Islands','Virginia','Washington','West Virginia','Wisconsin','Wyoming']
	},
	apo : {
		code : ['AE','AA','AE','AE','AE','AP'],
		name : ['Armed Forces Africa','Armed Forces Americas','Armed Forces Canada','Armed Forces Europe','Armed Forces Middle East','Armed Forces Pacific']
	},
	province : {
		code : ['ON','NF','NB','NS','PE','QC','MB','SK','AB','BC','NT','NU','YT'],
		name : ['Ontario','Newfoundland','New Brunswick','Nova Scotia','Prince Edward Island','Quebec','Manitoba','Saskatchewan','Alberta','British Columbia','Northwest Territories','Nunavut','Yukon']
	}
}


Validate.isState = function(txt){
	txt = txt.toUpperCase();
	if(Validate.__.state.code.indexOf(txt) > -1) return true;
	if(Validate.__.state.name.indexOf(txt,true) > -1) return true;
	return false;
	/* var state = /^(AK|AL|AR|AZ|CA|CO|CT|DC|DE|FL|GA|HI|IA|ID|IL|IN|KS|KY|LA|MA|MD|ME|MI|MN|MO|MS|MT|NE|NB|NC|ND|NH|NJ|NM|NV|NY|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VA|VT|WA|WI|WV|WY)$/i;
	   return state.test(txt); */
}
Validate.isAPO = function(txt){
	txt = txt.toUpperCase();
	if(Validate.__.apo.code.indexOf(txt) > -1) return true;
	if(Validate.__.apo.name.indexOf(txt,true) > -1) return true;
	return false;
}
Validate.isProvince = function(txt){
	txt = txt.toUpperCase();
	if(Validate.__.province.code.indexOf(txt) > -1) return true;
	if(Validate.__.province.name.indexOf(txt,true) > -1) return true;
	return false;
}
Validate.isZip = function(txt){
	var zip = /(^\d{5}$)|(^\d{5}-\d{4}$)/;
	return zip.test(txt);	
}
Validate.isPostalCode = function(txt){
	/* LL LNL NLN */
	var postalCode = /^[A-Z]{2} [A-Z][0-9][A-Z] [0-9][A-Z][0-9]$/i;
	return postalCode.test(txt);
}

/*
validate.isDate = function(value){
	var aryDate = value.split('/');
	var testDate = new Date(value);
	if(isNaN(testDate) || aryDate.length != 3 || testDate.getMonth()+1 != aryDate[0] || testDate.getDate() != aryDate[1] || testDate.getFullYear() != aryDate[2] || aryDate[2].length != 4)
		return false;
	else 
		return true;
}
validate.dateCompare = function(d1,type,d2){
	if(!this.isDate(d1) || !this.isDate(d2))
		return false;
	var thisDate = new Date(d1).getTime();
	var targetDate = new Date(d2).getTime();
	switch (type){
		case "==" 	: return (thisDate == targetDate);
		case "<" 	: return (thisDate < targetDate);
		case "<=" 	: return (thisDate <= targetDate);
		case ">" 	: return (thisDate > targetDate);
		case ">=" 	: return (thisDate >= targetDate);
	}
	return false;
}
*/


