// JavaScript Document

/* JSValidate preferences */
var jsOptions = {
	errorTag: "span", // which tag do you want to use for error container. it must be one that opens and closes (div,span,p,b)
	errorClass: "jsvalidation", // this is the css class name given to the tag above
	errorLocation: "afterEnd", // only accepts beforeBegin or afterEnd (either before or after the input element) or none
	//note: if you choose "none" for the above attribute, you must create the error yourself and give the element an ID consisting of the option below + the name of the form + the name of the field to validate.
	errorIDPrefix: "jsvalidator", // prefix of the id of the element above that will attach to the name or id of the form element. don't use spaces or special characters. unfortunately, this is the only option that cannot be applied individually to each element
	startGone: true, //couldn't think of another name for this, but if true, it will apply "display:none", otherwise, the element is just invisible.
	useBR: "none", // accepts before, after, both or none; This will add a new line (<br />) before and/or after the above element.
	useBlur: true, // this will attach an onBlur validator to each form element.
	submitClass: 'submit_action', // apply this class inside any form to let this element submit the form.
	resetClass: 'reset_action', // apply this class inside any form to let this element reset the form.
	resetConfirm: false, // if true, it will prompt user to confirm if they click a reset button.
	highlightColor: '#FFFF99', //default color should be:  #FFFF99
	endColor: '#FFFFFF', //this is what you generally want to set to the background color behind the form elements.
	extMessage: true, // if true, and you have accept value on file input, it tells user what extensions are accepted.
	ajaxURL: '/captcha-validate.txt', // if not blank, validator will attempt to check value against this URL; if return value is not blank, error container will be populated with return value
	fieldSep: '-'
}
//note: can apply any of the custom options above by including {optionname: 'value'} in the element's class.

//setup validators like: name of validator, default message, /regular expression/ !don't forget the / in front and the / in back!!!!
var customValidators = {
	number: {
		className: "jsvalidate_number",
		defaultMessage: "This field must have a numerical value.",
		regExp: /^[-]?\d+(\.\d+)?$/
	},
	digits: {
		className: "jsvalidate_digits",
		defaultMessage: "This field can only contain numbers.",
		regExp: /^[-]?\d+(\.\d+)?$/
	},
	email: {
		className: "jsvalidate_email",
		defaultMessage: "This field must contain a valid email address.",
		regExp: /^([a-zA-Z0-9_\.\-])+(\+[a-zA-Z0-9]+)*\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/
	},
	uscanzip: {
		className: "jsvalidate_uscanzip",
		defaultMessage: "This field must contain a valid US or Canada zip code.",
		regExp: /^((\d{5}([- ])\d{4})|(\d{5})|([AaBbCcEeGgHhJjKkLlMmNnPpRrSsTtVvXxYy]\d[A-Za-z]\s?\d[A-Za-z]\d))$/
	},
	usstate: {
		className: "jsvalidate_usstate",
		defaultMessage: "This field must contain a valid 2 letter US state code.",
		regExp: /^(A[LKSZRAEP]|C[AOT]|D[EC]|F[LM]|G[ANU]|HI|I[ADLN]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$/
	},
	usphone: {
		className: "jsvalidate_usphone",
		defaultMessage: "This field must contain a valid US phone number with area code.",
		regExp: /^([0-9]( |-|.)?)?(\(?[0-9]{3}\)?|[0-9]{3})( |-|.)?([0-9]{3}( |-|.)?[0-9]{4}|[a-zA-Z0-9]{7})$/
	},
	creditcard: {
		className: "jsvalidate_creditcard",
		defaultMessage: "This field must contain a valid credit card number issued by one of the companies noted above.",
		regExp: /^(((4\d{3})|(5[1-5]\d{2})|(6011))([- ])?\d{4}([- ])?\d{4}([- ])?\d{4}|3[4,7]\d{13})$|370000000000002|6011000000000012|5424000000000015|4007000000027/
	},
	ssn: {
		className: "jsvalidate_ssn",
		defaultMessage: "This field must contain a valid social security number.",
		regExp: /(^|\s)(00[1-9]|0[1-9]0|0[1-9][1-9]|[1-6]\d{2}|7[0-6]\d|77[0-2])(-?|[\. ])([1-9]0|0[1-9]|[1-9][1-9])\3(\d{3}[1-9]|[1-9]\d{3}|\d[1-9]\d{2}|\d{2}[1-9]\d)($|\s|[;:,!\.\?])/
	},
	alpha: {
		className: "jsvalidate_alpha",
		defaultMessage: "This field must contain only letters.",
		regExp: /^[a-zA-z\s]+$/
	},
	alphanum: {
		className: "jsvalidate_alphanum",
		defaultMessage: "This field must contain only letters or numbers.",
		regExp: /^[a-zA-Z0-9]+$/
	},
	mmddyy: {
		className: "jsvalidate_mmddyyyy",
		defaultMessage: "Please use the described MM/DD/YYYY format",
		regExp: /^(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])\/[12][0-9][0-9][0-9]$/
	},
	creditcardtype: {
		className: "jsvalidate_cctype",
		defaultMessage: "",
		regExp: /^34|37|5|4|60|65/
	}
};


/* only change the default message, do not change the className */
var jsValidators = {
	required: {
		className: "jsrequired",
		defaultMessage: "This field is required."
	},
	notfirst: {
		className: "select-notfirst",
		defaultMessage: "Select something other than the first item."
	},
	filetypes: {
		defaultMessage: "This field accepts the following file types:"
	},
	ajax: {
		className: "ajax",
		defaultMessage: "This value should change based on ajax request result."
	}
};


/* begin uneditable code ---- please don't touch */



String.prototype.trim = function() {
	a = this.replace(/^\s+/, '');
	return a.replace(/\s+$/, '');
};

Array.prototype.inArray = function (value){
    var i;
    for (i=0; i < this.length; i++) {
        // Matches identical (===), not just similar (==).
        if (this[i] === value) {
            return true;
        }
    }
    return false;
};

Array.prototype.remove=function(s){
	for(i=0;i<this.length;i++){
		if(s==this[i]) this.splice(i, 1);
	}
};

String.prototype.isEmpty = function() {
   if ((this.value.length == 0) || (this.value==null)) {
      return true;
   }
   return false;
};

// Removes the last element from an array
// and returns that element.
if (!Array.prototype.pop) {
	Array.prototype.pop = function() {
		var last;
		if (this.length) {
			last = this[this.length - 1];
			this.length -= 1;
		}
		return last||null;
	};
}

// Adds one or more elements to the end of an array and returns
// the new length of the array.
if (!Array.prototype.push) {
	Array.prototype.push = function() {
		for (var i = 0; i < arguments.length; ++i) {
			this[this.length] = arguments[i];
		}
		return this.length;
	};
}

function isset(v) {
	return((typeof(v)=='undefined' || v.length==0) ? false : true);
}

function getElementsByClassName(className, tag, elm){
	var testClass = new RegExp("(^|\\s)" + className + "(\\s|$)");
	var tag = tag || "*";
	var elm = elm || document;
	var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
	var returnElements = [];
	var current;
	var length = elements.length;
	for(var i=0; i<length; i++){
		current = elements[i];
		if(testClass.test(current.className)){
			returnElements.push(current);
		}
	}
	return returnElements;
}

function isArray() {
	if (typeof arguments[0] == 'object') {
		var criterion = arguments[0].constructor.toString().match(/array/i);
		return (criterion != null);
	}
	return false;
}

function isString() {
	if (typeof arguments[0] == 'string') return true;
	if (typeof arguments[0] == 'object') {
		var criterion = arguments[0].constructor.toString().match(/string/i);
		return (criterion != null);
	}
	return false;
}


function RemoveDuplicates(arr){
	if(isArray(arr)){
		arr.sort();
		returnArray = true;
	} else {
		returnArray = false;
		arr.trim();
		arr = arr.split(" ");
		arr.sort();
	}
	var result=new Array();
	var lastValue="";
	for (var i=0; i<arr.length; i++){
		var curValue=arr[i];
		if (curValue != lastValue){
			result[result.length] = curValue;
		}
		lastValue = curValue;
	}
	if(!returnArray){
		var newResult = "";
		for (var a=0; a < result.length; a++){
			newResult += result[a] + " ";
		}
		newResult.trim();
		result = newResult;
	}
	return result;
}


function onlyJSV(arr){
	if(isArray(arr)){
		arr.sort();
		returnArray = true;
	} else {
		returnArray = false;
		arr.trim();
		arr = arr.split(" ");
		arr.sort();
	}
	var result=new Array();
	for (var i=0; i<arr.length; i++){
		//see if this matches any of my variables.
		for(items in customValidators){
			if(arr[i] == customValidators[items]['className']){
				result[result.length] = arr[i];
			}
		}
		for(items in jsValidators){
			if(arr[i] == jsValidators[items]['className']){
				result[result.length] = arr[i];
			}
		}
	}

	if(!returnArray){
		var newResult = "";
		for (var a=0; a < result.length; a++){
			newResult += result[a] + " ";
		}
		newResult.trim();
		result = newResult;
	}
	return result;
}



var _emptyTags = {
   "IMG":   true,
   "BR":    true,
   "INPUT": true,
   "META":  true,
   "LINK":  true,
   "PARAM": true,
   "HR":    true
};


if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentHTML){
	HTMLElement.prototype.__defineGetter__("outerHTML", function () {
		var attrs = this.attributes;
		var str = "<" + this.tagName;
		for (var i = 0; i < attrs.length; i++)
			str += " " + attrs[i].getAttribute('name') + "=\"" + attrs[i].value + "\"";

		if (_emptyTags[this.tagName])
			return str + ">";

		return str + ">" + this.innerHTML + "</" + this.tagName + ">";
	});

	HTMLElement.prototype.__defineSetter__("outerHTML", function (sHTML) {
		var r = this.ownerDocument.createRange();
		r.setStartBefore(this);
		var df = r.createContextualFragment(sHTML);
		this.parentNode.replaceChild(df, this);
	});


	HTMLElement.prototype.insertAdjacentHTML = function (sWhere, sHTML) {
	var df;   // : DocumentFragment
	var r = this.ownerDocument.createRange();

	switch (String(sWhere).toLowerCase()) {  // convert to string and unify case
	  case "beforebegin":
		 r.setStartBefore(this);
		 df = r.createContextualFragment(sHTML);
		 this.parentNode.insertBefore(df, this);
		 break;

	  case "afterbegin":
		 r.selectNodeContents(this);
		 r.collapse(true);
		 df = r.createContextualFragment(sHTML);
		 this.insertBefore(df, this.firstChild);
		 break;

	  case "beforeend":
		 r.selectNodeContents(this);
		 r.collapse(false);
		 df = r.createContextualFragment(sHTML);
		 this.appendChild(df);
		 break;

	  case "afterend":
		 r.setStartAfter(this);
		 df = r.createContextualFragment(sHTML);
		 this.parentNode.insertBefore(df, this.nextSibling);
		 break;
	}
	};
}

var jsValidator = new Array();
var theseOptions = eval("({})");
var ajaxItems = new Array();
var ajaxPos;
var linkedReset = false;

function findForms(){
	var forms = document.getElementsByTagName('form');
	return forms;
}

function getFields(formref,type){
	var els;
	if(type == "name"){
		els = document.forms[formref].elements;
	}
	if(type == "id"){
		els = Form.getElements(formref);
	}
	return els;
}


function getParentForm(el){
  while(el.parentNode != null && el.tagName != "FORM") el = el.parentNode;
  return (el.getAttribute('name')) ? el.getAttribute('name') : el.getAttribute('id');
}

function hasLabel(el){
	while(el.parentNode != null && el.tagName != "LABEL") el = el.parentNode;
	return (el.tagName == "LABEL") ? true : false;
}

function getLabel(el){
	while(el.parentNode != null && el.tagName != "LABEL") el = el.parentNode;
	return el;
}


function attachSubmit(formRef){
	var formAttach;
	var parentRef;
	if(formRef.cloneNode(false).getAttribute('name') || formRef.cloneNode(false).getAttribute('id')){
		if(document.forms[formRef.cloneNode(false).getAttribute('name')]){
			formAttach = document.forms[eval("formRef.cloneNode(false).getAttribute('name')")];
			formRef = formRef.cloneNode(false).getAttribute('name');
		} else {
			formAttach = $(eval("formRef.cloneNode(false).getAttribute('id')"));
			formRef = formRef.cloneNode(false).getAttribute('id');
		}
	} else {
		formAttach = formRef;
	}
	if(window.addEventListener){ // Mozilla, Netscape, Firefox
		formAttach.onsubmit = function(){ return submitAction(formRef,'INPUT','submit'); };
	} else { // IE
		formAttach.attachEvent('onsubmit', function(){ return submitAction(formRef,'INPUT','submit'); });
	}

	if(window.addEventListener){ // Mozilla, Netscape, Firefox
		formAttach.onreset = function(){ return resetAction(formRef); };
	} else { // IE
		formAttach.attachEvent('onreset', function(){ return resetAction(formRef); });
	}

	if(getElementsByClassName(jsOptions['submitClass']).length > 0){
		var buttons = getElementsByClassName(jsOptions['submitClass']);
		for(b=0; b < buttons.length; b++){
			parentRef = getParentForm(buttons[b]);
			if(parentRef == formRef){
				tag = buttons[b].tagName;
				if(buttons[b].type){
					type = buttons[b].type.toLowerCase();
				} else {
					type = "";
				}
				Event.observe(buttons[b], 'click', function(){ return submitAction(formRef,tag,type); });
			}
		}
	}

	if(getElementsByClassName(jsOptions['resetClass']).length > 0){
		var buttons = getElementsByClassName(jsOptions['resetClass']);
		for(r=0; r < buttons.length; r++){
			parentRef = getParentForm(buttons[r]);
			if(parentRef == formRef){
				Event.observe(buttons[r], 'click', function(){ linkedReset = true; document.forms[formRef].reset(); return false; });
			}
		}
	}
}

function extractOptions(vals){
	var firstPos = vals.indexOf("{");
	var lastPos = vals.indexOf("}") + 1;
	var theOptions = vals.substring(firstPos,lastPos);
	return theOptions;
}

var radioNum = 0;
function attachValidation(fieldref,formName){
	var validationMessage = "";
	var theField;
	var theseOptions = eval("({})");
	var isRadio = false;
	var doneRadios = new Array();
	var doExt = true;
	var useBlur = false;
	if(document.forms[formName].elements[fieldref]){
		theField = document.forms[formName].elements[fieldref];
		if(typeof theField.nodeType == "undefined"){
			elType = theField[0].type.toLowerCase();
		} else {
			elType = theField.type.toLowerCase();
		}
		if(elType == "radio"){
			isRadio = true;
		}
	} else {
		theField = $(fieldref);
	}

	if(isRadio){
		classes = "";
		for(r=0; r < theField.length; r++){
			classes += theField[r].className + " ";
		}
	} else {
		classes = theField.className;
	}
	if(classes){
		if(classes.indexOf("{") > -1 && classes.indexOf("}") > -1){
			theseOptions = extractOptions(classes).toString();
			classes = classes.replace(theseOptions,"");
			theseOptions = eval("(" + theseOptions + ")");
		}
		useBlur = (isset(theseOptions['useBlur'])) ? theseOptions['useBlur'] : jsOptions['useBlur'];
		extMessage = (isset(theseOptions['extMessage'])) ? theseOptions['extMessage'] : jsOptions['extMessage'];

		classes.trim();
		classes = RemoveDuplicates(classes);
		classes = onlyJSV(classes);
		classes = classes.trim();
		classList = classes.split(" ");

		for(c=0; c < classList.length; c++){
			for(items in jsValidators){
				if(classList[c] == jsValidators[items]['className']){
					if(validationMessage == ""){
						validationMessage = jsValidators[items]['defaultMessage'];
					} else {
						validationMessage += ' ' + jsValidators[items]['defaultMessage'];
					}
					if(!jsValidator.inArray(fieldref + "," + formName + "," + theField.className)){
						arrayPos = jsValidator.length;
						jsValidator[arrayPos] = fieldref + "," + formName + "," + theField.className;
					}
				}
			}

			for(items in customValidators){
				if(classList[c] == customValidators[items]['className']){
					if(validationMessage == ""){
						validationMessage = customValidators[items]['defaultMessage'];
					} else {
						validationMessage += ' ' + customValidators[items]['defaultMessage'];
					}
					if(!jsValidator.inArray(fieldref + "," + formName + "," + theField.className)){
						arrayPos = jsValidator.length;
						jsValidator[arrayPos] = fieldref + "," + formName + "," + theField.className;
					}
				}
			}

			if(isRadio){
				for(n=0; n < theField.length; n++){
					if(theField[n].getAttribute('alt') != "" && theField[n].getAttribute('alt') != null){
						validationMessage = theField[n].getAttribute('alt');
					}
				}
			} else {
				if(theField.getAttribute('alt')){
					if(theField.getAttribute('alt') != "" && theField.getAttribute('alt') != null){
						validationMessage = theField.getAttribute('alt');
					}
				}
			}

			if(elType == "file" && extMessage && doExt){
				if(theField.getAttribute('accept') != ""){
					if(validationMessage == ""){
						validationMessage = jsValidators['filetypes']['defaultMessage'] + " " + theField.getAttribute('accept');
					} else {
						validationMessage += " " + jsValidators['filetypes']['defaultMessage'] + " " + theField.getAttribute('accept');
					}
				}
				doExt = false;
			}
		}
	}

	if(validationMessage != "" && validationMessage != null){
		errorTag = (isset(theseOptions['errorTag'])) ? theseOptions['errorTag'] : jsOptions['errorTag'];
		errorClass = (isset(theseOptions['errorClass'])) ? theseOptions['errorClass'] : jsOptions['errorClass'];
		startGone = (isset(theseOptions['startGone'])) ? theseOptions['startGone'] : jsOptions['startGone'];
		useBR = (isset(theseOptions['useBR'])) ? theseOptions['useBR'] : jsOptions['useBR'];
		errorLocation = (isset(theseOptions['errorLocation'])) ? theseOptions['errorLocation'] : jsOptions['errorLocation'];

		//var fieldName = jsOptions['errorIDPrefix'] + jsOptions['fieldSep'] + formName + jsOptions['fieldSep'] + fieldref;
		var fieldName = jsOptions['errorIDPrefix'] + jsOptions['fieldSep']  + jsOptions['fieldSep'] + fieldref;
		fieldName = fieldName.trim();

		var html = "<";

		html += errorTag;
		html += " id=\"" + fieldName + "\" ";
		if(errorClass != ""){
			html += "class=\"" + errorClass + "\" ";
		}
		html += "style=\"opacity:0; filter:alpha(opacity=0);";
		if(startGone){
			html +=	" display:none;";
		}
		html += "\">";
		if(useBR != "none"){
			if(useBR == "before" || useBR == "both"){
				html += '<br />';
			}
		}
		html += validationMessage;
		if(useBR != "none"){
			if(useBR == "after" || useBR == "both"){
				html += '<br />';
			}
		}

		html += "</";
		html += errorTag;
		html += ">";

		if(errorLocation == "afterEnd" || errorLocation == "beforeBegin"){
			if(isRadio){
				if(errorLocation == "afterEnd"){
					totalRadios = theField.length - 1;
					if(radioNum == totalRadios){
						addTo = (hasLabel(theField[radioNum])) ? getLabel(theField[radioNum]) : theField[radioNum];
						addTo.insertAdjacentHTML(errorLocation,html);
						radioPos = doneRadios.length;
						doneRadios[radioPos ] = theField[radioNum].getAttribute('name');
					}
					radioNum++;
				} else {
					if(!doneRadios.inArray(theField[0].getAttribute('name'))){
						theField[0].insertAdjacentHTML(errorLocation,html);
						radioPos = doneRadios.length;
						doneRadios[radioPos ] = theField[radioNum].getAttribute('name');
					}
				}
			} else {
				thisType = theField.type.toLowerCase();
				if(thisType == "checkbox"){
					attachTo = (hasLabel(theField)) ? getLabel(theField) : theField;
					attachTo.insertAdjacentHTML(errorLocation,html);
				} else {
					theField.insertAdjacentHTML(errorLocation,html);
				}
			}
		}
		if($(fieldName)){
			new Effect.Opacity(fieldName, {to:0.0, duration: 0 });
		}
		if(errorLocation == "none" && startGone && $(fieldName)){
			$(fieldName).style.display = 'none';
		}
	}

	if(useBlur && classes){
		//setup onBlur feature
		if(theField.isArray && theField[0].type){
			fieldType = theField[0].type;
		} else {
			if(theField.type){
				fieldType = theField.type.toLowerCase();
			}
		}
		if((theField.tagName == "INPUT" && (fieldType == "text" || fieldType == "password")) || theField.tagName == "TEXTAREA"){
			Event.observe(theField, 'blur', function(){ blurAction(theField,formName); });
		}
		if(theField.tagName == "SELECT"){
			Event.observe(theField, 'blur', function(){ blurAction(theField,formName); });
			Event.observe(theField, 'change', function(){ blurAction(theField,formName); });
		}
		if(theField.tagName == "INPUT" && fieldType == "checkbox"){
			Event.observe(theField, 'click', function(){ blurAction(theField,formName); });
		}
		if(theField.tagName == "INPUT" && fieldType == "checkbox"){
			Event.observe(theField, 'blur', function(){ blurAction(theField,formName); });
			Event.observe(theField, 'click', function(){ blurAction(theField,formName); });
			Event.observe(theField, 'change', function(){ blurAction(theField,formName); });
		}
		if(typeof theField.nodeType == "undefined"){
			for(a=0; a < theField.length; a++){
				if(!radioName){
					var radioName = theField[a].getAttribute('name');
				}
				Event.observe(document.forms[formName].elements[radioName][a], 'click', function(){ blurAction(theField,formName); });
			}
		}
	}
}

function getFileExtension(filename){
	if( filename.length == 0 ) return "";
	var dot = filename.lastIndexOf(".");
	if( dot == -1 ) return "";
	var extension = filename.substr(dot + 1,filename.length);
	return extension;
}

function blurAction(fieldReference,formRef){
	var fieldName;
	var theResult = true;
	var theseOptions = eval("({})");
	var isRadio = false;
	var isDisabled = false;

	if(($(fieldReference)) || (document.forms[formRef].elements[fieldReference])){
		fieldReference = ($(fieldReference)) ? $(fieldReference) : document.forms[formRef].elements[fieldReference];
	}

	if(typeof fieldReference.nodeType == "undefined"){
		theField = (fieldReference[0].getAttribute('name')) ? fieldReference[0].getAttribute('name') : fieldReference[0].getAttribute('id');
		isRadio = true;
	} else {
		theField = (fieldReference.getAttribute('id')) ? fieldReference.getAttribute('id') : fieldReference.getAttribute('name');
	}

	if(isRadio){
		classes = "";
		for(r=0; r < fieldReference.length; r++){
			classes += fieldReference[r].className + " ";
		}
	} else {
		classes = fieldReference.className;
	}
	if(!isRadio){
		isDisabled = fieldReference.disabled;
	}
	if(classes && !isDisabled){
		if(classes.indexOf("{") > -1 && classes.indexOf("}") > -1){
			theseOptions = extractOptions(classes);
			classes = classes.replace(theseOptions,"");
			theseOptions = eval("(" + theseOptions + ")");
		}
		classes = classes.trim();
		classes = RemoveDuplicates(classes);
		classes = onlyJSV(classes);
		classes = classes.trim();
		classList = classes.split(" ");
		var badField = false;
		var isRequired = false;
		var isAjax = false;

		hColor = (isset(theseOptions['highlightColor'])) ? theseOptions['highlightColor'] : jsOptions['highlightColor'];
		eColor = (isset(theseOptions['endColor'])) ? theseOptions['endColor'] : jsOptions['endColor'];
		startGone = (isset(theseOptions['startGone'])) ? theseOptions['startGone'] : jsOptions['startGone'];
		errorLocation = (isset(theseOptions['errorLocation'])) ? theseOptions['errorLocation'] : jsOptions['errorLocation'];
		ajaxURL = (isset(theseOptions['ajaxURL'])) ? theseOptions['ajaxURL'] : jsOptions['ajaxURL'];

		for(c=0; c < classList.length; c++){
			//fieldName = jsOptions['errorIDPrefix'] + jsOptions['fieldSep'] + formName + jsOptions['fieldSep'] + theField;
			fieldName = jsOptions['errorIDPrefix'] + jsOptions['fieldSep'] + jsOptions['fieldSep'] + theField;
			fieldName = fieldName.trim();

			for(items in customValidators){
				if(classList[c] == customValidators[items]['className'] && fieldReference.value != ""){
					var thisRegExp = customValidators[items]['regExp'];
					if(!thisRegExp.test(fieldReference.value)){
						badField = true;
					}
				}
			}

			if(classList[c] == jsValidators['required']['className']){
				isRequired = true;
				if(typeof fieldReference.nodeType == "undefined"){
					thistype = fieldReference[0].type.toLowerCase();
					fieldType = thistype;
					thisTag = fieldReference[0].tagName;
				} else {
					fieldType = fieldReference.type.toLowerCase();
					thisTag = fieldReference.tagName;
				}
				if((thisTag == "INPUT" && (fieldType == "text" || fieldType == "password")) || thisTag == "TEXTAREA"){
					if(fieldReference.value == ""){
						badField = true;
					}
				}
				if(thisTag == "SELECT"){
					if(fieldReference.value == ""){
						badField = true;
					}
				}
				if(thisTag == "INPUT" && fieldType == "checkbox"){
					if(fieldReference.checked == false){
						badField = true;
					}
				}
				if(thisTag == "INPUT" && fieldType == "file"){
					if(fieldReference.value == ""){
						badField = true;
					} else {
						if(fieldReference.getAttribute('accept') != ""){
							pass = false;
							fileTypes = fieldReference.getAttribute('accept').split(",");
							ext = getFileExtension(fieldReference.value)
							for(f=0; f < fileTypes.length; f++){
								if(ext == fileTypes[f]){
									pass = true;
								}
							}
							if(!pass){
								badField = true;
							}
						}
					}
				}

				if(thisTag == "INPUT" && fieldType == "radio"){
					thisField = (fieldReference.name) ? document.forms[formRef].elements[fieldReference.name] : document.forms[formRef].elements[fieldReference[0].name];
					theRadios = thisField.length;
					badField = true;
					for(t=0; t < theRadios; t++){
						if(thisField[t].checked == true){
							badField = false;
						}
					}
				}
			}

			if(classList[c] == jsValidators['notfirst']['className']){
				if(fieldReference.selectedIndex == 0 && fieldReference.tagName == "SELECT"){
					badField = true;
				}
			}

			if(classList[c] == jsValidators['ajax']['className']){
				isAjax = true;
			}
		}

		if(isAjax){
			if(isRequired && fieldReference.value == ""){
				//reset required message
				replaceHTML = jsValidators['required']['defaultMessage'];
				if(fieldReference.getAttribute('alt')){
					if(fieldReference.getAttribute('alt') != "" && fieldReference.getAttribute('alt') != null){
						replaceHTML = fieldReference.getAttribute('alt');
					}
				}
				Element.update(fieldName, replaceHTML);
			} else {
				if(ajaxURL){
					badField = false;
					ajaxArea = fieldName;
					if(!ajaxItems.inArray(ajaxArea)){
						ajaxPos = ajaxItems.length;
						ajaxItems[ajaxPos] = ajaxArea;
					}
					poststr = theField + "=" + encodeURIComponent(fieldReference.value);
					new Ajax.Request(ajaxURL, { parameters: poststr, onSuccess: function(t){
							response = t.responseText.trim()
							if(response != ""){
								Element.update(ajaxArea, response);
								throwFlag(ajaxArea,hColor,eColor,startGone);
							} else {
								if(fieldReference.value != ""){
									hideFlag(ajaxArea,startGone);
								}
								ajaxItems.remove(ajaxArea);
							}
						}
					});
				}
			}
		}

		if(badField){
			if(errorLocation == "none"){
				if($(fieldName)){
					throwFlag(fieldName, hColor, eColor,startGone);
				}
			} else {
				throwFlag(fieldName, hColor, eColor,startGone);
			}
			theResult = false;
		} else {
			if(errorLocation == "none"){
				if($(fieldName)){
					hideFlag(fieldName,startGone);
				}
			} else {
				hideFlag(fieldName,startGone);
			}
		}
	}

	return theResult;
}


function validTag(theTag){
	if(theTag == "INPUT" || theTag == "SELECT" || theTag == "TEXTAREA" || theTag == "BUTTON" || theTag == "ISINDEX"){
		return true;
	}
	return false;
}

function checkJSVForm(formObj){
	var isRadio = false;
	formName = formObj.cloneNode(false).getAttribute('name');
	if(formName){
		fields = getFields(formName,"name");
	} else {
		fields = getFields(formObj.getAttribute('id'),"id");
	}

	for(f=0; f < fields.length; f++){
		if(document.forms[formName].elements[fields[f]]){
			theField = document.forms[formName].elements[fields[f]];
			if(typeof theField.nodeType == "undefined"){
				elType = theField[0].type.toLowerCase();
			} else {
				elType = theField.type.toLowerCase();
			}
			if(elType == "radio"){
				isRadio = true;
			}
		} else {
			theField = $(fields[f]);
		}

		if(isRadio){
			classes = "";
			for(r=0; r < theField.length; r++){
				classes += theField[r].className + " ";
			}
		} else {
			classes = theField.className;
		}
		if(classes){
			if(classes.indexOf("{") > -1 && classes.indexOf("}") > -1){
				theseOptions = extractOptions(classes).toString();
				classes = classes.replace(theseOptions,"");
				theseOptions = eval("(" + theseOptions + ")");
			}
			useBlur = (isset(theseOptions['useBlur'])) ? theseOptions['useBlur'] : jsOptions['useBlur'];
			extMessage = (isset(theseOptions['extMessage'])) ? theseOptions['extMessage'] : jsOptions['extMessage'];

			classes.trim();
			classes = RemoveDuplicates(classes);
			classes = onlyJSV(classes);
			classes = classes.trim();
			if(classes){
				return true;
			}
		}
	}
	return false;
}

function loadAction(){
	var forms = findForms();
	var attachIt;
	var fields;
	var j;
	var done;
	if(forms.length >= 1){
		for(var i=0; i < forms.length; i++){
			doValidate = checkJSVForm(forms[i]);
			if(doValidate){
				attachIt = attachSubmit(forms[i]);
				formName = forms[i].cloneNode(false).getAttribute('name');
				if(formName){
					fields = getFields(formName,"name");
				} else {
					fields = getFields(forms[i].getAttribute('id'),"id");
				}
				for(j=0; j < fields.length; j++){
					done = false;
					if(fields[j].getAttribute('id') && validTag(fields[j].tagName)){
						attachValidation(fields[j].getAttribute('id'),formName);
						done = true;
					}
					if(fields[j].getAttribute('name') && done == false && validTag(fields[j].tagName)){
						attachValidation(fields[j].getAttribute('name'),formName);
						done = true;
					}
				}
			}
		}
	}
}


function throwFlag(fieldToFlag, hColor, eColor, gone){
	$(fieldToFlag).style.display = '';
	if(Element.getOpacity(fieldToFlag) > .75){
		new Effect.Highlight(fieldToFlag,{duration:1.0, startcolor:hColor, endcolor:eColor });
	} else {
		if(gone){
			$(fieldToFlag).style.display = '';
		}
		new Effect.Opacity(fieldToFlag, {to:1.0, duration: .5 });
	}
}

function hideFlag(fieldToHide, gone){
	$(fieldToHide).style.display = 'none';
	if(Element.getOpacity(fieldToHide) > .25){
		new Effect.Opacity(fieldToHide, {to:0.0, duration: .5 });
		if(gone){
			$(fieldToHide).style.display = 'none';
		}
	}
}


function validateFields(theForm){
	var theField;
	var proceed = true;

	for(var jsV=0; jsV < jsValidator.length; jsV++){
		var badField = false;

		var els = jsValidator[jsV].split(",");

		fieldRef = els[0];
		formRef = els[1];
		classRef = els[2];

		if(formRef == theForm){
			checkField = blurAction(fieldRef,formRef);
			if(!checkField){
				proceed = false;
			}
		}
	}

	return proceed;
}

function resetAction(theForm){
	if(jsOptions['resetConfirm']){
		if(!confirm("Are you sure you want to reset this form?")){
			return false;
		}
	}

	for(var v=0; v < jsValidator.length; v++){
		var els = jsValidator[v].split(",");

		fieldRef = els[0];
		formRef = els[1];
		classRef = els[2];

		if(formRef == theForm){
			//hideFlag(jsOptions['errorIDPrefix'] + jsOptions['fieldSep'] + formName + jsOptions['fieldSep'] + fieldRef);
			hideFlag(jsOptions['errorIDPrefix'] + jsOptions['fieldSep']  + jsOptions['fieldSep'] + fieldRef);
		}
	}
	if(linkedReset){
		linkedReset = false;
		return false;
	} else {
		return true;
	}
}
function submitAction(thisForm,tag,type){
	var process = validateFields(thisForm);
	if(ajaxItems.length > 0){
		//return false;
	}
	if((tag != "INPUT" || (tag == "INPUT" && type != "submit")) && process && (document.forms[thisForm] || $(thisForm))){
		if(document.forms[thisForm]){
			document.forms[thisForm].submit();
		} else {
			$(thisForm).submit();
		}
		return false;
	}

	// stupid hack
//	if (typeof(customFormVal) !== undefined){
//		return customFormVal();
//	}

	return process;
}


//Event.observe(window, 'load', function(){ loadAction(); });