/*Object.prototype.method = function (method) {
	var context = this;
	return function () {
		return method.apply(context, arguments);
	}
}*/

/**
 *	FormValidator - V0.1
 *	---------------------------------------------
 *  Author - Jeroen
 *	
 * 	Rules can be passed like this:
 *
 *	var prules = {
 *		"inputId1" : { 0 : {"type" : "required", "msg" : "titel is verplicht"} },
 *		"inputId2" : {  0 : { "type" : "required", "msg" : "e-mailadres is verplicht"},
 *						1 : { "type" : "email", "msg" : "voer een geldig e-mailadres in"} }
 *	}
 *	
 *	"type" can be required, email, radio, checkbox and select
 */

function FormValidator(pform, prules, perrorhandler){   
	var self = this;
	this.form = pform;
	this.rules = prules;
	this.errorhandler = perrorhandler;
	this.form.onsubmit = self.validate;
}

FormValidator.prototype = {
	
	form : undefined,
	rules : [],
	errorhandler : undefined,
	errors : [],
	doValidate : true,

	validate : function(){

		if(!this.doValidate) return true;
		
		this.errors = [];
		var valid = true;
		var formElem;
		for (elem in this.rules){
			for (var i=0;rule=this.rules[elem][i];i++){

				if (!rule.enabled) continue;

				formElem = document.getElementById(elem);
				if (!formElem) continue;
				
				switch(rule.type){
					case "required":
						valid = (formElem.value != "") ? true : false;
						break;
					case "number":
						valid = Validator.validNumber(formElem.value)
						break;
					case "email":
						valid = Validator.validEmail(formElem.value);
						break;
					case "radio":
						valid = true; // TODO: validate required radiobuttons
						break;
					case "checkbox":
						valid = true; // TODO: validate required checkbox
						break;
					case "select":
						valid = Validator.validSelect(formElem);
						break;
					default: valid = true;
				}
				if(!valid) this.errors.push([formElem,rule.msg]);		
			}           
		};
		if(this.errors.length > 0) {this.handleError();return false;};
		return true;
	},

	handleError : function(){
		if (this.errorhandler) {
			this.errorhandler(this.form, this.errors);
		} else {
			var msg = "- default errorhandler -\n";
			for(var i=0;i<this.errors.length;i++){
				msg = msg + this.errors[i][0].id + ": " + this.errors[i][1] + "\n";
			}
			alert(msg);
		}
	},

	setDoValidate : function(b){
		if(b == true || b == false) this.doValidate = b;
	},

	enableRules : function(elems){
		for (var i=0;i<elems.length;i++){
			if(!this.rules[elems[i]]) continue;
			for (var j=0;rule=this.rules[elems[i]][j];j++){
				rule.enabled = true;
			}
		}
	},
	
	disableRules : function(elems){
		for (var i=0;i<elems.length;i++){
			if(!this.rules[elems[i]]) continue;
			for (var j=0;rule=this.rules[elems[i]][j];j++){
				rule.enabled = false;
			}
		}		
	},

	debugRules : function(){
		var rulesString = "";
		for (elem in this.rules){
			for (var i=0;rule=this.rules[elem][i];i++){
				rulesString = rulesString + elem+": "+rule.enabled + "\n";
			}
		}
		alert(rulesString);
	}

}

var Validator = {
	emailRE : /^.+@.+\..{2,3}$/,

	validNumber : function(n){
		var valid = true;
		if (n != "") {
			valid = (isNaN(parseInt(n))) ? false : true;							
		}
		return valid;		
	},
		
	validEmail : function(s){
		var valid = true;
		if (s != "") {
			valid = (this.emailRE.test(s)) ? true : false;
		}
		return valid;		
	},

	validSelect : function(select){
		var valid = true;
		if (select.selectedIndex == 0) valid = false;
		return valid;		
	}

}

function customErrorHandler(form, errors) {
	var elem, msg;
	// clear previous errors
	for (var j=0;j<form.elements.length;j++){
		var field = form.elements[j].parentNode;
		// clientside errors
		if (field.errorMessage){
			field.removeChild(field.errorMessage);
			field.errorMessage = null;
		}
		// serverside errors
		var kids = field.childNodes;
		for (var k=0;k<kids.length;k++){
			if(ClassName.contains(kids[k],"error")) {
				field.removeChild(kids[k]);
			}
		}
	}
	// generate errormessages
	for(var i=0;i<errors.length;i++){
		elem = errors[i][0];
		msg = errors[i][1];
		if (!elem.parentNode.errorMessage) {
			var msgbox = document.createElement("SPAN");
			msgbox.className = "error";
			msgbox.appendChild(document.createTextNode(msg));
			elem.parentNode.errorMessage = msgbox;
			elem.parentNode.appendChild(msgbox);
		}
	}
}

/**
 *	InputHandler - V0.1
 *	---------------------------------------------
 *  Author - Jeroen
 *  Depends on: EventListener.js
 */

var InputHandler = {

	init: function() {
		var inputs = document.getElementsByTagName("INPUT");
		for(var i=0; i < inputs.length; i++) {
			if (inputs[i].type == "submit") this.transform(inputs[i]);
			if (inputs[i].type == "text" && inputs[i].title != "") this.handleInputTitles(inputs[i]);
		}
	},

	transform: function(input) {
		var anchor = document.createElement("A");
		anchor.setAttribute("href","#");
		anchor.className = input.className;
		anchor.appendChild(document.createTextNode(input.value));
		anchor.onclick = function() {
			input.click();
			return false;
		}
		//input.style.display = "none";
		ClassName.add(input, "replaced");
		input.parentNode.insertBefore(anchor, input);
	},
	
	handleInputTitles: function(input) {
		if (!input.value || input.value == "") input.value = input.title;
		input.onfocus = function() { if (this.value == this.title) this.value = ""; }
		input.onblur = function() { if (this.value == "") this.value = this.title; }		
	}
}

if (onloadHandler) onloadHandler.add(function() {
	InputHandler.init();
});

/**
 *	AutoSubmitForms - V0.1
 *	---------------------------------------------
 *  Author - Jeroen
 *  Depends on: EventListener.js
 */

var AutoSubmitForms = {

	autoRE:/ ?\bautosubmit\b/i,

	init: function() {
		var forms = document.getElementsByTagName("FORM");
		for (var i=0;i<forms.length;i++) {
			var form = forms[i]
			if (this.autoRE.test(form.className)) {
				for (var j=0;j<form.elements.length;j++) {
					if (form.elements[j].type == "checkbox") {
						form.elements[j].onclick = function() {
							this.form.submit();
						}	
					}
					if (form.elements[j].type == "select-one") {
						form.elements[j].onchange = function() {
							this.form.submit();
						}
					}
				}
			}
			
		}
	}
}

if (onloadHandler) onloadHandler.add(function() {
	AutoSubmitForms.init();
});

/**
 *	FormToolTips - V0.1
 *	---------------------------------------------
 *  Author - Jeroen
 *  Depends on: EventListener.js
 */

var FormToolTips = {

	fieldhelpRE:/ ?\bfieldhelp\b/i,

	init: function() {
		var anchors = document.getElementsByTagName("A");
		for(var i=0; i < anchors.length; i++) {
			if (this.fieldhelpRE.test(anchors[i].className)) {
				anchors[i].onmouseover = anchors[i].onfocus = function() {
					ClassName.add(this, "showhelp");
				}
				anchors[i].onmouseout = anchors[i].onblur = function() {
					ClassName.remove(this, "showhelp");
				}
			}
		}
	}
}

if (onloadHandler) onloadHandler.add(function() {
	FormToolTips.init();
});

/**
 *	ToggleCheckboxes - V0.1
 *	---------------------------------------------
 *  Author - Jeroen
 *  Depends on: EventListener.js
 *  Depending checkbox must be in the same fieldset as the "all" checkbox
 */

function ToggleCheckboxes(input) {
	
	this.toggler = input;
	this.inputs = new Array();
	var fieldset = input.parentNode;
	var self = this;
	
	// find containing fieldset
	while (fieldset!=null && !/^fieldset$/i.test(fieldset.nodeName)) fieldset = fieldset.parentNode;	
	if (fieldset!=null && /^fieldset$/i.test(fieldset.nodeName)) {

		// get all checkboxes within fieldset
		var fsInputs = fieldset.getElementsByTagName("input");
		for (var i=0;i<fsInputs.length;i++) {
			if (fsInputs[i].type == "checkbox") this.inputs.push(fsInputs[i]);
		}

		// set clickhandler on fieldset
		addEventHandler(fieldset, "click", function(e) {self.clickHandler(e);});
	}	
}

ToggleCheckboxes.prototype = {

	clickHandler: function(e) {
		var e = e||event;
		if(e.shiftKey || e.ctrlKey || e.altKey) return true;
		var target = e.target||e.srcElement;
		while (!target.nodeName || target.nodeType == 3) target = target.parentNode;
		if (target.nodeName && /^input$/i.test(target.nodeName) && target.type == "checkbox") {
			this.toggle(target);
		} else return true;		
	},
	
	toggle: function(cb) {
		if (cb == this.toggler) {
			if (cb.checked == true) {
				// uncheck all
				for (var i=0;i<this.inputs.length;i++) {
					if (this.inputs[i] != this.toggler) this.inputs[i].checked = false;
				}
			}
		} else {
			if (this.toggler.checked == true) this.toggler.checked = false;
		}
	}
}

/**
 *	autoTab - V0.1
 *	---------------------------------------------
 *  Author - Jeroen
 *  Depends on: EventListener.js
 *  Sets focus on next form element when max length is reached
 */

autoTab = function() {
	var inRE = /[\wÀ-ÿ ]/;
	for (var i=0;i<document.forms.length;i++) {
		addEventHandler(document.forms[i], "keyup",function(e){
			var e = e||window.event, k = String.fromCharCode(e.keyCode), target = e.target||e.srcElement, l = target.value.length, m = target.maxLength, f = target.form.elements;
			if (inRE.test(k) && m > 0 && l >= m) {
				if (target != f[f.length-1]) {
					var i = 0, next = null;
					while (target != next && i < f.length) next = f[i++];
					if (next && next.type.toLowerCase() != "hidden") f[i].focus();
				}
			}
		});
	}
}

if (onloadHandler) onloadHandler.add(function() {
	autoTab();
});

/**
 *	SelectToggler - V0.1
 *	---------------------------------------------
 *  Author - Jeroen
 *  Depends on: EventListener.js
 *  Show/hide element when select has certain value
 */

function SelectToggler(sel,elem,val) {
	this.toggleSelect = sel;
	this.toggleElement = elem;
	this.toggleValue = val;
	this.init();
}
SelectToggler.prototype = {
	init: function(){
		var self = this;
		addEventHandler(this.toggleSelect, "change", function() {self.check();});
		this.check();
	},
	check: function(){
		var selected = this.toggleSelect.options[this.toggleSelect.selectedIndex].value;
		if(selected && selected == this.toggleValue) {
			this.toggle(true);
		} else {
			this.toggle(false);
		}
	},
	toggle: function(open) {
		this.toggleElement.style.display = open ? "block" : "none";
	}
}

/* toggle options in advanced search form */
function AdvancedSearch() {
	var s = document.getElementById("searchsection:input");
	if(s) s.onchange = function() {
		var m = document.getElementById('moreoptions'); 
		if(!m) return;
		if(this.selectedIndex != 0) 
			window.ClassName.add(m, "hidden"); 
		else 
			window.ClassName.remove(m, "hidden");
	}
}

if (onloadHandler) onloadHandler.add(function() {
	AdvancedSearch();
});

