var validators = new Array();
var ifValidators = new Array();
var _form = null;
var _childMode = false;

var moz = true;
if (typeof document.all == 'object')
{
	moz = false;
}

function findPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
	do {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		} while (obj = obj.offsetParent);
	}
	return [curleft,curtop];
}

function _DOM_backwards(el)
{
	if (el.previousSibling)
	{
		if (el.previousSibling.hasChildNodes())
		{
			el = el.previousSibling;
			while (true)
			{
				if (el.lastChild)
				{
					el = el.lastChild;
				}
				else
				{
					break;
				}
			}
			return el;
		}
		else
		{
			return el.previousSibling;
		}
	}
	else
	{
		if (moz)
		{
			return _DOM_backwards(el.parentNode);
		}
		else
		{
			return _DOM_backwards(el.parentElement);
		}
	}
}

function _test_DOM_backwards(el)
{
	while (el = _DOM_backwards(el))
	{
		if (el.nodeType == 1)
		{
			el.style.backgroundColor = "yellow";
			if (el.focus)
			{
				el.focus();
			}
			if (!confirm(el.tagName)) break;
			el.style.backgroundColor = "";
		}
		else if (el.nodeType == 3)
		{
			if (!confirm(el.textContent)) break;
		}
	}
}

function _field_has_value(_fld)
{
	var _fld2;
	
	if (typeof _fld.length == "undefined")
	{
		_fld2 = _fld;
	}
	else
	{
		_fld2 = _fld[0];
	}
	
	if (_fld2.tagName.toLowerCase() == "input")
	{
		if (_fld2.type == "text")
		{
			return _has_value(_fld.value);
		}
		else if (_fld2.type == "radio")
		{
			return _has_checked(_fld);
		}
		else if (_fld2.type == "checkbox")
		{
			if (typeof _fld.length == "undefined")
			{
				return _fld.checked;
			}
			else
			{
				return _has_checked(_fld);
			}
		}
	}	
	else if (_fld2.tagName.toLowerCase() == "select")
	{
		return _select_has_value(_fld);
	}
	else if (_fld2.tagName.toLowerCase() == "textarea")
	{
		return _has_value(_fld.value);
	}
}

function _has_value(_value)
{
	if (typeof _value == "undefined")
	{
		return null;
	}
	else if (_value.replace(/\s/g, "") == "")
	{
		return false;
	}
	else
	{
		return true;
	}
}

function _has_checked(_grpcheck)
{
	for (var i = 0; i < _grpcheck.length; i++)
	{
		if (_grpcheck[i].checked == true)
		{
			return true;
		}
	}
	return false;
}

function _select_has_value(_sel)
{
	if (_sel.multiple)
	{
		for (var i = 0; i < _sel.options.length; i++)
		{
			if (_sel.options[i].selected)
			{
				return true;
			}
		}
		
		return false;
	}
	else
	{
		if (_sel.value)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
}

function _is_value(obj, _value)
{
	if (typeof obj.length != "undefined")
	{
		for (var i = 0; i < obj.length; i++)
		{
			if (obj[i].value == _value && obj[i].checked) return true;
		}
		return false;
	}
	else if (typeof obj.value != "undefined")
	{
		return (obj.value == _value);
	}
	else
	{
		alert("What?");
		return null;
	}
}

function _get_id()
{
	var _href = location.href.split('?');
	if (_href.length == 2)
	{
		var _qs = _href[1].split('&');
		for (var i = 0; i < _qs.length; i++)
		{
			var _parts = _qs[i].split('=');
			if (_parts[0] == 'id')
			{
				return _parts[1];
			}
		}
	}
	return null;
}

function setObjectContent(obj, content)
{
	if (moz)
	{
		obj.textContent = content;
	}
	else
	{
		obj.innerText = content;
	}
}

function ValidateForm(frm)
{
	_form = frm.id;
	var valid = true;
	var firstValidator;
	for (i in validators)
	{
		if (typeof validators[i].Validate != "undefined")
		{
			validators[i].Validate();
			_v = validators[i];
			while (typeof _v.valid == 'undefined')
			{
				_v = _v.base;
			}
			if (_v.valid == false)
			{
				if (typeof validators[i].field == "undefined")
				{
					alert(i);
				}
				if (typeof firstValidator == "undefined" && (typeof validators[i].field.focus == "function" || typeof validators[i].field.focus == "object" || (typeof validators[i].field[0] != "undefined" && (typeof validators[i].field[0].focus == "function" || typeof validators[i].field[0].focus == "object"))))
				{
					firstValidator = validators[i];
				}

				valid = false;
			}
		}
	}
	for (i in validators)
	{
		if (typeof validators[i].Validate != "undefined")
		{
			_v = validators[i];
			while (typeof _v.valid == 'undefined')
			{
				_v = _v.base;
			}
			if (_v.valid == null)
			{
				window.setTimeout("Validate_SubmitTimer()", 250);
				return false;
			}
		}
	}
	if (!valid)
	{
		var _name;

		if (typeof firstValidator.field.length == "undefined")
		{
			_name = firstValidator.field.name;
		}
		else
		{
			_name = firstValidator.field[0].name;
		}

		if (typeof firstValidator.field.focus == "function" || typeof firstValidator.field.focus == "object")
		{
			firstValidator.field.focus();
		}
		else
		{
			if (typeof validators[i].field[0] != "undefined" && typeof firstValidator.field[0].focus == "function")
			{
				firstValidator.field[0].focus();
			}

			var _validator = document.getElementById(_name + "-validator");
			var vldPos = findPos(_validator);
			window.scrollTo(0, vldPos[1]);
		}
	}
	return valid;
}

function Validate_SubmitTimer()
{
	var valid = true;
	for (i in validators)
	{
		if (i != "extend")
		{
			_v = validators[i];
			while (typeof _v.valid == 'undefined')
			{
				_v = _v.base;
			}
			if (_v.valid == null)
			{
				window.setTimeout("Validate_SubmitTimer()", 250);
				return false;
			}
			
			if (_v.valid == false)
			{
				valid = false;
			}
		}
	}
	if (valid == true)
	{
		SimulateSubmit();
	}
}

function SimulateSubmit()
{
	if (moz)
	{
		var evt = document.createEvent("MouseEvent");
		evt.initMouseEvent("click", true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
		document.forms[0].submit.dispatchEvent(evt);
	}
	else
	{
		document.forms[0].submit.click();
	}
}

function Validator_OnChange(fieldname)
{
	validators[fieldname].Validate();
	if (typeof ifValidators[fieldname] != "undefined")
	{
		_childMode = true;
		for (var i = 0; i < ifValidators[fieldname].length; i++)
		{
			validators[ifValidators[fieldname][i]].Validate();
		}
		_childMode = false;
	}
}

function BaseValidator(field, fieldName, required, inline, ifField, ifValue)
{
	/*
	if (typeof validators[field.name] != 'undefined')
	{
		alert(fieldName + ": you cannot assign two validators to this field.");
	}
	*/

	this.field = field;
	this.fieldName = fieldName;
	this.required = required;
	this.valid = null;
	
	if (typeof this.field.length == "undefined")
	{
		_name = this.field.name;
	}
	else
	{
		_name = this.field[0].name;
	}

	if (typeof ifField != "undefined")
	{
		if (typeof ifField.length == "undefined")
		{
			_iName = ifField.name;
		}
		else
		{
			_iName = ifField[0].name;
		}
	
		this.ifField = ifField;
		if (typeof ifValidators[_iName] == "undefined")
		{
			ifValidators[_iName] = new Array();
		}
		ifValidators[_iName][ifValidators[_iName].length] = _name;
	}
	else
	{
		this.ifField = null;
	}
	if (typeof ifValue != "undefined")
	{
		this.ifValue = ifValue;
	}
	else
	{
		this.ifValue = null;
	}
	
	if (inline == true)
	{
		var _name;

		if (typeof field.length == "undefined")
		{
			_name = field.name;
		}
		else
		{
			_name = field[0].name;
		}

		var span = document.createElement("span");
		span.id = _name + "-validator";
		span.className = "validator-error";
		if (this.required == false)
		{
			span.innerHTML = "&nbsp;";
		}
		else if (this.ifField == null && this.ifValue == null)
		{
			span.innerHTML = "&nbsp;*";
		}
		else if ((this.ifValue == null && _field_has_value(this.ifField)) || _is_value(this.ifField, this.ifValue))
		{
			span.innerHTML = "&nbsp;*";
		}

		if (typeof this.field.length == "undefined")
		{
			if (moz)
			{
				this.field.parentNode.insertBefore(span, this.field.nextSibling);
			}
			else
			{
				this.field.parentElement.insertBefore(span, this.field.nextSibling);
			}
		}
		else
		{
			var tmp = this.field[0];
			var nodeContent;
			
			while (true)
			{
				tmp = _DOM_backwards(tmp);
				if (tmp.nodeType == 3 && tmp.parentNode.tagName.toLowerCase() != "noscript")
				{
					nodeContent = moz ? tmp.textContent : tmp.nodeValue;
					if (nodeContent.replace(/\s+/g, "").length > 0)
					{
						break;
					}
				}
			}

			if (moz)
			{
				if (tmp.nextSibling)
				{
					tmp.parentNode.insertBefore(span, tmp.nextSibling);
				}
				else
				{
					tmp.parentNode.appendChild(span);
				}
				
			}
			else
			{
				if (tmp.nextSibling)
				{
					tmp.parentNode.insertBefore(span, tmp.nextSibling);
				}
				else
				{
					tmp.parentNode.appendChild(span);
				}
			}
		}
		
		if (typeof this.field.length == "undefined")
		{
			eval("this.field.onchange = function() { Validator_OnChange('" + field.name + "'); }");
		}
		else
		{
			for (var i = 0; i < this.field.length; i++)
			{
				eval("this.field[" + i + "].onchange = function() { Validator_OnChange('" + field[i].name + "'); }");
			}
		}
	}

	validators[_name] = this;
}

BaseValidator.prototype.Validate = function() {
	if (this.CheckRequired())
	{
		this.setValid();
	}
	else
	{
		this.setInvalid(this.fieldName + " is a required field.");
	}	
}

BaseValidator.prototype.CheckRequired = function() {
	if (this.required == false || _field_has_value(this.field))
	{
		return true;
	}
	else
	{
		if (this.ifField != null)
		{
			if (this.ifValue != null)
			{
				if (_is_value(this.ifField, this.ifValue))
				{
					return false;
				}
				else
				{
					return true;
				}
			}
			else
			{
				if (_has_value(this.ifField))
				{
					return false;
				}
				else
				{
					return true;
				}
			}
		}
		else
		{
			return false;
		}
	}	
}

BaseValidator.prototype.setValid = function() {
	var _name;

	if (typeof this.field.length == "undefined")
	{
		_name = this.field.name;
	}
	else
	{
		_name = this.field[0].name;
	}

	validators[_name].valid = true;

	var div = document.getElementById(_name + '-validator');
	if (div)
	{
		if (this.required == false)
		{
			div.innerHTML = "&nbsp;";
		}
		else if (this.ifField == null && this.ifValue == null)
		{
			div.innerHTML = "&nbsp;*";
		}
		else if ((this.ifValue == null && _has_value(this.ifField)) || _is_value(this.ifField, this.ifValue))
		{
			div.innerHTML = "&nbsp;*";
		}
		else
		{
			div.innerHTML = "";
		}
	}
}

BaseValidator.prototype.setInvalid = function(invalidString) {
	var _name;

	if (typeof this.field.length == "undefined")
	{
		_field = this.field;
		_name = this.field.name;
	}
	else
	{
		_field = this.field[0];
		_name = this.field[0].name;
	}

	validators[_name].valid = false;
	
	if (!_childMode)
	{
		var div = document.getElementById(_name + '-validator');
		if (div)
		{
			if (this.required == false)
			{
				div.innerHTML = "&nbsp;<br /><small>" + invalidString + "</small>";
			}
			else
			{
				div.innerHTML = "&nbsp;*<br /><small>" + invalidString + "</small>";
			}
		}
		
		//if (typeof _field.focus == "function") _field.focus();
	}
	else
	{
		this.setValid();
	}
}

BaseValidator.prototype.setValidAlert = function(invalidString) {
	var _name;

	if (typeof this.field.length == "undefined")
	{
		_name = this.field.name;
	}
	else
	{
		_name = this.field[0].name;
	}

	validators[_name].valid = true;
	
	var div = document.getElementById(_name + '-validator');
	if (div) div.innerHTML = invalidString;
}

function NumberValidator(field, fieldName, required, inline)
{
	this.base = new BaseValidator(field, fieldName, required, inline);
	this.field = this.base.field;
	validators[field.name] = this;
}

function CheckboxGroupValidator(field, fieldName, required, inline)
{
	this.base = new BaseValidator(field, fieldName, required, inline);
	this.field = this.base.field;
	validators[field.name] = this;
}

CheckboxGroupValidator.prototype.Validate = function()
{
	if (this.required == false || _has_checked(this.field))
	{
		this.setValid();
	}
	else
	{
		this.setInvalid(this.fieldName + " is a required field.");
	}	
}

function PasswordValidator(field, fieldName, required, inline)
{
	this.base = new BaseValidator(field, fieldName, required, inline);
	this.field = this.base.field;
	validators[field.name] = this;
}

PasswordValidator.prototype.Validate = function()
{
	if (!this.base.CheckRequired())
	{
		this.base.setInvalid(this.base.fieldName + " is a required field.");
	}
	else if (this.base.field.value.length < 5)
	{
		this.base.setInvalid(this.base.fieldName + " must be at least 5 characters long.");
	}
	else if (this.base.field.value.length > 10)
	{
		this.base.setInvalid(this.base.fieldName + " must be no more than 10 characters long.");
	}
	else if (!this.base.field.value.match(/(\d+[a-z]+)|([a-z]+\d+)/i))
	{
		this.base.setInvalid(this.base.fieldName + " must contain both letters and numbers.");
	}
	else
	{
		this.base.setValid();
	}
}

function RegexValidator(field, fieldName, required, inline, rex, formatExample, ifField, ifValue)
{
	this.base = new BaseValidator(field, fieldName, required, inline, ifField, ifValue);
	this.field = this.base.field;
	this.regex = rex;
	this.formatExample = formatExample;
	this.valid = null;
	validators[field.name] = this;
}

RegexValidator.prototype.Validate = function() {
	if (!this.base.CheckRequired())
	{
		this.base.setInvalid(this.base.fieldName + " is a required field.");
	}
	else if (this.base.CheckRequired() && !_has_value(this.base.field.value))
	{
		this.base.setValid();
	}
	else if (this.regex.test(this.base.field.value))
	{
		this.base.setValid();
	}
	else
	{
		this.base.setInvalid(this.base.fieldName + " must have the format: " + this.formatExample);
	}
}

function PostalValidator(field, fieldName, required, inline, ifField, ifValue)
{
	this.base = new RegexValidator(field, fieldName, required, inline, /^\s*([a-ceghj-npr-tvxy]\d[a-z])\s?(\d[a-z]\d)\s*|(\d{5}(-\d{4})?)$/i, "T1A 1A1", ifField, ifValue);
	this.field = this.base.base.field;
	validators[field.name] = this;
}

PostalValidator.prototype.Validate = function() {
	if (!this.base.base.CheckRequired())
	{
		this.base.base.setInvalid(this.base.base.fieldName + " is a required field.");
	}
	else if (this.base.base.CheckRequired() && !_has_value(this.base.base.field.value))
	{
		this.base.base.setValid();
	}
	else if (this.base.regex.test(this.base.base.field.value))
	{
		var m = this.base.regex.exec(this.base.base.field.value);
		if (typeof m[1] != "undefined" && typeof m[2] != "undefined")
		{
			this.base.base.field.value = m[1].toUpperCase() + " " + m[2].toUpperCase();
		}
		this.base.base.setValid();
		
	}
	else
	{
		this.base.base.setInvalid(this.base.base.fieldName + " must have the format: " + this.base.formatExample);
	}
}

function PhoneValidator(field, fieldName, required, inline, ifField, ifValue)
{
	this.base = new RegexValidator(field, fieldName, required, inline, new RegExp("^\\(?(\\d{3})\\)?[-\\s.]?(\\d{3})[-.]?(\\d{4})[ a-zA-Z.]*(\\d+)?$"), "(123) 123-1234", ifField, ifValue);
	this.field = this.base.base.field;
	validators[field.name] = this;
}

PhoneValidator.prototype.Validate = function() {
	if (!this.base.base.CheckRequired())
	{
		this.base.base.setInvalid(this.base.base.fieldName + " is a required field.");
	}
	else if (this.base.base.CheckRequired() && !_has_value(this.base.base.field.value))
	{
		this.base.base.setValid();
	}
	else if (this.base.regex.test(this.base.base.field.value))
	{
		var m = this.base.regex.exec(this.base.base.field.value);
		this.base.base.field.value = "(" + m[1] + ") " + m[2] + "-" + m[3];
		if (m[4])
		{
			this.base.base.field.value += " ext. " + m[4];
		}
		this.base.base.setValid();
		
	}
	else
	{
		this.base.base.setInvalid(this.base.base.fieldName + " must have the format: " + this.base.formatExample);
	}
}

function EmailValidator(field, fieldName, required, inline, ifField, ifValue)
{
	this.base = new RegexValidator(field, fieldName, required, inline, new RegExp("^([0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+[a-zA-Z]{2,9})$"), "user@host.com", ifField, ifValue);
	this.field = this.base.base.field;
}

function DateValidator(field, fieldName, required, inline, ifField, ifValue)
{
	this.base = new RegexValidator(field, fieldName, required, inline, new RegExp("^(\\d{2})-(\\d{2})-(\\d{4})$"), "mm-dd-yyyy", ifField, ifValue);
	this.field = this.base.base.field;
	this.valid = null;
	validators[field.name] = this;
}

function daysInFebruary (year){
	// February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
}

function DaysArray(n) {
	for (var i = 1; i <= n; i++) {
		this[i] = 31
		if (i==4 || i==6 || i==9 || i==11) {this[i] = 30}
		if (i==2) {this[i] = 29}
   } 
   return this;
}

DateValidator.prototype.Validate = function() {
	if (!this.base.base.CheckRequired())
	{
		this.base.base.setInvalid(this.base.base.fieldName + " is a required field.");
	}
	else if (this.base.base.CheckRequired() && !_has_value(this.base.base.field.value))
	{
		this.base.base.setValid();
	}
	else
	{
		var arr = this.base.regex.exec(this.base.base.field.value);
		if (arr == null)
		{
			this.base.base.setInvalid(this.base.base.fieldName + " must have the format: " + this.base.formatExample);
		}
		else
		{
			var daysInMonth = DaysArray(12);
			if (RegExp.$1 > 12)
			{
				this.base.base.setInvalid(this.base.base.fieldName + " must specify a valid month.");
			}
			else if ((RegExp.$2 > daysInMonth[parseInt(RegExp.$1)]) || (parseInt(RegExp.$1) == '2' && RegExp.$2 > daysInFebruary(parseInt(RegExp.$3))))
			{
				this.base.base.setInvalid(this.base.base.fieldName + " must specify a valid day of the month.");
			}
			else
			{
				this.base.base.setValid();
			}
		}
	}
}

function AjaxValidator(field, fieldName, required, inline, url, keys, onComplete)
{
	this.base = new BaseValidator(field, fieldName, required, inline);
	this.field = this.base.field;
	this.url = url;
	this.keys = keys;
	this.onComplete = onComplete;
	validators[field.name] = this;
}

AjaxValidator.prototype.Validate = function() {
	if (!this.base.CheckRequired())
	{
		this.base.setInvalid(this.base.fieldName + " is a required field.");
	}
	else
	{
		this.base.valid = null;
		
		var _parameters = this.base.field.name + '=' + this.base.field.value;
		
		if (_get_id())
		{
			_parameters += "&id=" + _get_id();
		}
		
		for (var i = 0; i < this.keys.length; i++)
		{
			_parameters += "&" + this.keys[i] + "=" + this.base.field.form.elements[this.keys[i]].value;
		}
		
		var myAjax = new Ajax.Request(
			this.url,
			{
				method: 'get',
				parameters: _parameters,
				onComplete: this.onComplete
			}
		);
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

