/*
Auto form handling etc
*/
var form = {
	
	// set to automatically hide passed elements
	autohideTimer: 0,
	okText: "&nbsp;",
	
	init: function()
	{
		var s = byTag("SELECT");
		for (var i = 0, l = s.length; i < l; i ++) {
			if (s[i].disabled) {
				form.fixDisabled(s[i]);
			}
		}
	},
			
	// form handling setup
	setup: function(rules, f)
	{
		f = $(f);
		for (var id in rules) {
			// apply to single element or group of elements (checkboxes / radios)
			if ($(id) || f.elements[id + "[]"]) {				
				var objs = ($(id)) ? [$(id)] : f.elements[id + "[]"];
				for (var q = 0, l2 = objs.length; q < l2; q ++) {				
					objs[q].ruleSet = rules[id].rules;
					objs[q].onError = (rules[id].onError) ? rules[id].onError : form.error;
					objs[q].validateRules = function() {								
						for (var x = 0, l = this.ruleSet.length; x < l; x ++) {
							if (! form.validateRule(this, this.ruleSet[x])) {
								return false;
							}
						}
						return true;
					}
					// assign for any events
					if (rules[id].validationEvents) {
						for (var p = 0, k = rules[id].validationEvents.length; p < k; p ++) {
							Event.add(objs[q], rules[id].validationEvents[p], function(e) { 
								var obj = Event.target(e);
								var r = obj.validateRules() ;
								if (!r && typeof(obj.form.submitted) != "undefined") { 
									obj.onError(); 
								} 
								else if (r) {
									obj.onError(); 
								}
							}, false);
						}
					}					
				}
			}
		}
	},
	
	// go through enabling elements for disabled forms
	enableForm: function(f, obj)
	{
		obj.innerHTML = "SAVE";
		for (var q = 0, l = f.elements.length; q < l; q ++) {
			if (f.elements[q].disabled) {
				this.enableElement(f.elements[q]);
			}
		}
		var d = ["img", "iframe"];
		for (var x = 0, y = d.length; x < y; x ++) {
			var i = byTag(d[x]);
			for (var q = 0, l = i.length; q < l; q ++) {
				if (i[q].className == "fixy") {
					i[q].style.display = "none";
				}
			}
		}
	},
	
	// enable a single element
	enableElement: function(el)
	{
		el.disabledState = 1;
		el.disabled = false;
		el.className = el.className.replace(/ ?disabled/, "");		
	},
	
	// setup images over top of disabled elements
	fixDisabled: function(el)
	{	
		// *cough* border hide
		var eTop = position(el, "Top"), eLeft = position(el, "Left"), eWidth = el.offsetWidth, IE = (document.all) ? 1 : 0, y = 0, p = (IE) ? 0 : 2;
		var y = 0;
		do {
			for (var x = 0; x < 2; x ++) {
				if (x || IE) { 
					var i = create(x ? "img" : "iframe");
					i.src = (x) ? "images/clear.gif" : "about:blank";
					i.className = "fixy"
					i.style.left = eLeft + "px";
					i.style.top = (eTop + p) + "px";
					switch (y) {
						// right border
						case 0 :
							i.style.left = (position(el, "Right") - 20) + "px";		
						break;
						// left border
						case 1 :	
							i.style.width = "3px";
						break;
						// top border
						case 2 :
							i.style.height = "2px";
							i.style.width = eWidth + "px";
						break;
						// bottom border
						case 3 :
							i.style.top = (eTop - 3 + el.offsetHeight) + "px";
							i.style.height = "2px";
							i.style.width = eWidth + "px";	
						break;
					}
					document.body.appendChild(i);
				}
			}
			y ++;
			// only ie keeps the borders so need four images
			if (y > 3 || !IE) {
				break;
			}
		} while (1);
		if (IE) el.style.visibility = "visible";
	},
	
	// check condition is met
	checkCondition: function(con, obj)
	{
		var oStr = (con.obj == 'this') ? "obj" : "$('" + con.obj + "')";

		// handle types	
		switch (con.type) {
			case "length" : eval("var conditionPassed = (" + oStr + ".value.length " + con.rule + ");"); break;
			default: eval("var conditionPassed = (" + oStr + ".value " + con.rule + " '" + con.value + "');");
		}
		
		if (! conditionPassed) {
			var i = $(obj.id + "_err");
			if (i) {
				i.style.display = "none";
			}
			return true;
		}
		return false;
	},

	// validate a rule
	validateRule: function(obj, rule)
	{
		// check to make sure the rule condition is met
		if (rule.condition && form.checkCondition(rule.condition, obj)) {
			return true;
		}
		
		obj.errorString = "";
		switch (rule.type) {
	
			// check length
			case "length" : 
				eval("var result = (obj.value.length " + rule.rule + ");");
				if (! result) {
					obj.errorString = form.errorString(rule, "character");					
				}
				return result;
			break;
			
			// check for valid email address
			case "email" : 
				var result = (obj.value.match(/[a-z0-9]+@[a-z0-9\-]{2,}\.[a-z]{2,3}/gi));
				if (! result) {
					if (rule.error) {
						obj.errorString = rule.error;
					}
					else {
						obj.errorString = "please provide a valid email";
					}
				}
				return result;
			break;
			
			// check for valid url
			case "url" : 
				var result = (obj.value.match(/(https?:\/\/)?([a-z0-9-]{2,}\.)[a-z0-9-]{2,}\.([a-z]{2,})/i));
				if (! result) {
					if (rule.error) {
						obj.errorString = rule.error;
					}
					else {
						obj.errorString = "please provide a valid url";
					}
				}
				return result;
			break;
			
			// check for valid email address
			case "regexp" : 
				var re = new RegExp(rule.rule, "i");
				var result = obj.value.match(re);
				if (! result) {
					if (rule.error) {
						obj.errorString = rule.error;
					}
					else {
						obj.errorString = "invalid format";
					}
				}
				return result;
			break;
			
			// check checkboxes
			case "checkbox" :
				// count selected checkboxes
				var c = 0;
				for (var x = 0, l = obj.form[obj.name].length; x < l; x ++) {
					if (obj.form[obj.name][x].checked) {
						c ++;
					}
				}
				eval("var result = (c " + rule.rule + ");");	
				if (! result) {
					obj.errorString = form.errorString(rule, "selection");
				}
				return result;		
			break;
		}
		return true;
	},
	
	// get error string for >=<= rule elements
	errorString: function(rule, type)
	{
		if (rule.error) {
			return rule.error;
		}
		else {
			var m = rule.rule.match(/>=? ?([0-9]+)/);
			if (m) {
				if (!parseInt(m[1])) {
					return "required";
				}
				else {
					return "at least " + m[1] + " " + type + ((m[1] == 1) ? "" : "s");
				}
			}
			else {
				return "less than " + m[1] + " " + type + ((m[1] == 1) ? "" : "s");
			}
		}
	},
		
	// default handling of errors
	error: function()
	{
		var id = (this.id) ? this.id : this.name.replace(/\[\]/, "");	
		
		var i = $(id + "_err");
		if (this.errorString.replace(/\s/, "").length) {
			if (! i) {
				i = create("span");
				i.id = id + "_err";
				this.parentNode.insertBefore(i, this.nextSibling);
			}
			i.className = "formError";
			i.style.display = "";
			i.innerHTML = this.errorString;
		}
		else if (i) {
			i.innerHTML = form.okText;
			i.className = "formOk";
			if (form.autohideTimer) {
				setTimeout("$('" + id + "_err').style.display = 'none';", form.autohideTimer);
			}
		}
	},
	
	// run checks on form elements
	runChecks: function(f)
	{
		var pass = true;
		var multi = [];
		for (var q = 0, l = f.elements.length; q < l; q ++) {
			if (f.elements[q].validateRules) {	

				// make sure multiple radio / checkboxes only run checks once
				if (f.elements[q].name.match(/\[\]$/)) {
					// already done
					if (multi.has(f.elements[q].name)) {
						continue;
					}
					multi.push(f.elements[q].name);
				}

				// check rules			
				if (! f.elements[q].validateRules()) {
					f.elements[q].onError();
					pass = false;
				}
			}
		}		
		return pass;
	},
	
	// handle form (switch submit and images to passable elements)
	autoHandle: function(e)
	{
		var obj = Event.target(e);
		obj.blur();
		var f = obj.form;
		f.submitted = 1;
		
		Event.stop(e);	
		
		if (form.runChecks(f)) {
			var oType = "";
			if (obj.type == "submit" || obj.type == "hidden") {
				oType = obj.type;
				// IE wont allow type switching for security reasons
				if (document.all) {
					var s = create(obj.outerHTML.replace(/type=\"?(submit|image)\"?/, "type=\"hidden\""));
					obj.parentNode.replaceChild(s, obj);	
				}
				else {
					obj.type = "hidden";
				}
			}
			f.submit();
			if (oType.length) {
				// IE wont allow type switching for security reasons
				if (document.all) {
					obj = create(s.outerHTML.replace(/type=\"?hidden\"?/, "type=\"" + oType + "\""));
					s.parentNode.replaceChild(obj, s);	
				}
				else {
					obj.type = oType;
				}
			}
		}
	}
};

Event.add(window, "load", form.init, false);