/*

	Lost Boys 2006.
	
	De inhoud van dit bestand is in opdracht vervaardigd en eigendom van onze opdrachtgever.
	Niet hergebruiken zonder toestemming.
	Neem voor vragen contact op met Lost Boys, www.lostboys.nl.

	The contents of this file have been produced for and are the property of our client.
	Do not reuse without permission.
	Any questions? Please contact Lost Boys, www.lostboys.nl.

*/
EventListener.addEvent(window, "load", function () {
	FullDateFieldUtil.init();
	changesubject();
	changeinfo();
	checkDynamicForms();
});

DynamicFormUtil =  {
		dynamicForm: null
}

function checkDynamicForms() {
	var forms = document.getElementsByTagName("form");

	for (var i=0; i < forms.length; i++) {
		if (forms[i].getAttribute("lb:rules")) DynamicFormUtil.dynamicForm = new DynamicForm(forms[i]);
	}
}

function makeDate(value) {
	var dateArray = value.split(/-/);
	var date =new Date();
	date.setFullYear(parseInt(dateArray[2]),parseInt(dateArray[1]) - 1,parseInt(dateArray[0]));
	return date;
}

function makeDate(value) {
	var dateArray = value.split(/-/);
	var date =new Date();
	date.setFullYear(parseInt(dateArray[2]),parseInt(dateArray[1]) - 1,parseInt(dateArray[0]));
	return date;
}

function DynamicForm (form) {
	this.form = form;

	this.read(this.form.getAttribute("lb:rules"));

	//Check the current form values
	this.checkConditions([]);

	this.attachEvents();
}

DynamicForm.prototype.handleChange = function (input) {
	this.checkConditions([]);
}

DynamicForm.prototype.handleClick = function (node) {
	this.lastsubmitname = node.name;
}

DynamicForm.prototype.handleSubmit = function (e) {

	var dynamicRules = [];
	this.checkConditions(dynamicRules);

	//Merge dynamic and static rules
	var rules = (this.rules) ? this.rules.concat(dynamicRules) : dynamicRules;
	var errors = new Array();

	try {
		for (var i=0; i < rules.length; i++) {

			if (rules[i].submit && rules[i].submit != this.lastsubmitname) continue;

			var input = document.getElementsByName(rules[i].name)[0];
			if (!this.applies(rules[i], input)) {
				errors[errors.length] = {name:rules[i].name, message:rules[i].message}
			}
		}
	} catch (ex) {alert(rules[i].name+" niet gevonden. Er zit een fout in het XML bestand.")}

	if (errors.length) {
		if (this.handler) {
			this.handler(errors);
		} else {
			var message = "";
			for (var i=0; i < errors.length; i++) message = message + errors[i].message + "\n";
			alert(message);
		}
		return false;
	} else {
		if (document.getElementsByName("method_action")[0]) document.getElementsByName("method_action")[0].value = this.lastsubmitname;
		return true;
	}
}

DynamicForm.prototype.setSubmitHandler = function (pointer) {
	this.handler = pointer;
}

DynamicForm.prototype.checkConditions = function (dynamicRules, subset) {
	var conditions = subset || this.conditions;
	
	if (conditions) {
		for (var i=0; i < conditions.length; i++) {
			var condition = conditions[i];
			var inputs = document.getElementsByName(condition.name);
			for (var j=0; j < inputs.length; j++) {
				var input = inputs[j];
				if (input && this.applies(condition, input)) {
					if (condition.conditions) {
						this.checkConditions(dynamicRules, condition.conditions);
					}

					if (condition.actions) {
						for (var a=0; a < condition.actions.length; a++) {
							this.perform(condition.actions[a]);
						}
					}
					if (condition.rules) {
						for (var r=0; r < condition.rules.length; r++) {
							dynamicRules[dynamicRules.length] = condition.rules[r];
						}
					}
				}
			}
		}
	}
}

DynamicForm.prototype.applies = function (condition, input) {

	var value = this.getInputValue(input);

	switch (condition.operation) {
		case "empty" :
			return (value == "");
		break;
		case "filled" :
			return (value != "");
		break;
		case "equals" :
			return (value == condition.parameters[0]);
		break;
		case "unequals" :
			return (value != condition.parameters[0]);
		break;
		case "match" :
			var xp = (condition.parameters.length >= 2) ? new RegExp(condition.parameters[0],condition.parameters[1]) : new RegExp(condition.parameters[0]);
			return xp.test(value);
		break;
		case "nomatch" :
			var xp = (condition.parameters.length >= 2) ? new RegExp(condition.parameters[0],condition.parameters[1]) : new RegExp(condition.parameters[0]);
			return !xp.test(value);
		break;
		case "checked" :
			if (input.type == "checkbox" || input.type == "radio") {
				return input.checked;
			}
		break;
		case "unchecked" :
			if (input.type == "checkbox" || input.type == "radio") {
				return !input.checked;
			}
		break;
		case "smaller" :
			return (Number(value) != NaN && parseInt(value,10) < parseInt(condition.parameters[0],10));
		break;
		case "larger" :
			return (Number(value) != NaN && parseInt(value,10) > parseInt(condition.parameters[0],10));
		break;
		case "range" :
			return (Number(value) != NaN && parseInt(value,10) >= parseInt(condition.parameters[0],10) && parseInt(value,10) <= parseInt(condition.parameters[1],10));
		break;
		case "outside" :
			return (Number(value) != NaN && parseInt(value,10) < parseInt(condition.parameters[0],10) || parseInt(value,10) > parseInt(condition.parameters[1],10));
		break;
		// extra date function (only apply to "dd-mm-yyyy" (hidden) fields)
		case "futuredate" :
			var date = makeDate(value);
			var today = new Date();
			return (date > today); // && valid(date)
		break;
		case "pastdate" :
			var date = makeDate(value);
			var today = new Date();
			return (date < today); // && valid(date)
		break;
		case "younger" :
			var date = makeDate(value);
			var today = new Date();
			var deadline = today.setFullYear(today.getFullYear() - condition.parameters[0]);
			return (date > deadline); // && valid(date)
		break;
		case "older" :
			var date = makeDate(value);
			var today = new Date();
			var deadline = today.setFullYear(today.getFullYear() - condition.parameters[0]);
			return (date < deadline); // && valid(date)
		break;
		case "withindaysfromnow" :
			var date = makeDate(value);
			var today = new Date();
			var deadline = today.getTime() + 3600 * 1000 * 24 * condition.parameters[0];
			return (date.getTime() <= deadline);
		break;
		case "laterthandaysfromnow" :
			var date = makeDate(value);
			var today = new Date();
			var deadline = today.getTime() + 3600 * 1000 * 24 * condition.parameters[0];
			return (date.getTime() > deadline);
		break;
	}

	return false;
}

DynamicForm.prototype.perform = function (action) {
	if (!action.isCustom) {
		switch (action.operation) {
			case "show" :
				for (var i=0; i < action.parameters.length; i++) {
					if (document.getElementById(action.parameters[i])) document.getElementById(action.parameters[i]).style.display = "block";
				}
			break;
			case "showinline" :
				for (var i=0; i < action.parameters.length; i++) {
					if (document.getElementById(action.parameters[i])) document.getElementById(action.parameters[i]).style.display = "inline";
				}
			break;
			case "hide" :
				for (var i=0; i < action.parameters.length; i++) {
					if (document.getElementById(action.parameters[i])) document.getElementById(action.parameters[i]).style.display = "none";
				}
			break;
			case "addclass" :
				if (document.getElementById(action.parameters[0])) {ClassName.add(document.getElementById(action.parameters[0]), action.parameters[1]);}
			break;
			case "removeclass" :
				if (document.getElementById(action.parameters[0])) ClassName.remove(document.getElementById(action.parameters[0]), action.parameters[1]);
			break;
			case "check" :
				if (document.getElementById(action.parameters[0])) document.getElementById(action.parameters[0]).checked = true;
				document.getElementById(action.parameters[0]).onchange();
			break;
			case "copyvalue" :
				if (document.getElementById(action.parameters[0]) && document.getElementById(action.parameters[1])) {
					this.setInputValue(document.getElementById(action.parameters[1]), this.getInputValue(document.getElementById(action.parameters[0])));
				}
			break;
			case "setvalue" :
				if (document.getElementById(action.parameters[0])) this.setInputValue(document.getElementById(action.parameters[0]), action.parameters[1]);
			break;
			case "clearvalue" :
				if (document.getElementById(action.parameters[0])) this.setInputValue(document.getElementById(action.parameters[0]),"");
			break;
		}
	} else {
		//Perform custom action
		eval(action.operation);
	}
}

DynamicForm.prototype.getInputValue = function (input) {
	switch (input.tagName.toLowerCase()) {
		case "input" :
			switch (input.type) {
				case "checkbox" :
					if (input.checked) return input.value;
				break;
				case "radio" :
					var group = document.getElementsByName(input.name);
					for (var i=0; i < group.length; i++) if (group[i].checked) return group[i].value;
				break;
				case "text" : case "hidden" : case "password" :
					return input.value;
				break;
			}
		break;
		case "select" :
			return input.options[input.selectedIndex].value;
		break;
		case "textarea" :
			return input.value;
		break;
	}

	return "";
}

DynamicForm.prototype.setInputValue = function (input,value) {
	switch (input.tagName.toLowerCase()) {
		case "input" :
			switch (input.type) {
				case "checkbox" :
					if (input.value == value) input.checked = true;
				break;
				case "radio" :
					var group = document.getElementsByName(input.name);
					for (var i=0; i < group.length; i++) {
						if (group[i].value == value) {
							group[i].checked = true;
							if (group[i].DC) group[i].DC.updateGUI();
						}
					}
				break;
				case "text" : case "hidden" : case "password" :
					input.value = value;
				break;
			}
		break;
		case "select" :
			for (var i=0; i < input.options.length; i++) {
				if (input.options[i].value == value) input.selectedIndex = i;
			}
		break;
		case "textarea" :
			input.value = value;
		break;
	}
}

DynamicForm.prototype.read = function (xmlURL) {
	var XHR = null;

	if (window.XMLHttpRequest) {
		XHR = new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		try {
			XHR = new ActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			XHR = new ActiveXObject("Microsoft.XMLHTTP");
		}
	}

	if (!XHR) return;

//	XHR.open("GET", xmlURL+"?rnd="+Math.random(), false);
	XHR.open("GET", xmlURL, false);
	XHR.send(null);

	if (XHR.responseXML) {
		var firstNode = XHR.responseXML.childNodes[0];
		if (firstNode.nodeType == 7) firstNode = XHR.responseXML.childNodes[1];//Skip XML declaration
	
		this.conditions = wrapNodes(firstNode, "condition", Condition);
		this.rules = wrapNodes(firstNode, "rule", Rule, true);
	}
}

DynamicForm.prototype.attachEvents = function () {

	var items = this.form.elements;

	for (var i=0; i < items.length; i++) {
		if (items[i].tagName && items[i].tagName == "FIELDSET") continue;
		if (items[i].type && (items[i].type == "radio" || items[i].type == "checkbox")) {
			EventListener.addEvent(items[i], "click", this.handleChange, this);
		} else {
			EventListener.addEvent(items[i], "change", this.handleChange, this);
		}
	}

	this.form.onsubmit = this.method(this.handleSubmit);
}

DynamicForm.prototype.method = function (method) {
	var context = this;
	return function () {
		return method.apply(context, arguments);
	}
}

function Condition (xmlNode) {
	this.name = xmlNode.getAttribute("name");
	this.operation = getOperation(xmlNode.getAttribute("value"));
	this.parameters = getParameters(xmlNode.getAttribute("value"));
	this.conditions = wrapNodes(xmlNode, "condition", Condition);
	this.actions = wrapNodes(xmlNode, "action", Action);
	this.rules = wrapNodes(xmlNode, "rule", Rule);
}

function Action (xmlNode) {
	if (xmlNode.getAttribute("type")) {
		this.operation = getOperation(xmlNode.getAttribute("type"));
		this.parameters = getParameters(xmlNode.getAttribute("type"));
	}
	if (xmlNode.getAttribute("custom")) {
		this.isCustom = true;
		this.operation = xmlNode.getAttribute("custom")
	}
}
Action.prototype.toString = function () {
	var s = this.operation + "(";
	for (var i in this.parameters) s = s + ((i > 0) ? ", " : "") + this.parameters[i];
	s += ")";
	return s;
}

function Rule (xmlNode) {
	this.name = xmlNode.getAttribute("name");
	this.submit = xmlNode.getAttribute("submit");
	this.operation = getOperation(xmlNode.getAttribute("require"));
	this.parameters = getParameters(xmlNode.getAttribute("require"), (this.operation == "match" || this.operation == "nomatch"));
	this.message = getValue(xmlNode.getElementsByTagName("error")[0]);
}

/* utilities */
function getOperation(s) {
	var xp = new RegExp("^([a-zA-Z0-9]+)[(](.*)[)]$");//Expression to extract function/parameter pairs
	xp.test(s);
	xp.exec(s);
	return RegExp.$1;
}
function getParameters(s, nosplit) {
	var xp = new RegExp("^([a-z]+)[(](.*)[)]$");//Expression to extract function/parameter pairs
	xp.test(s);
	xp.exec(s);
	if (nosplit) {
		var p = new Array();
		p[0] = RegExp.$2;
	} else {
		var p = RegExp.$2.split(",");
	}
	if (p[0].length == 0) p.length = 0;
	return p;
}
function wrapNodes(startNode, tagName, o, noNesting) {
	var node = startNode.firstChild;
	var nodeReg = new RegExp('\\b'+tagName+'\\b');
	var objects = [];

	while(node) {
		if (nodeReg.test(node.nodeName)) {
			objects[objects.length] = new o(node);
		}
		node = node.nextSibling;
	}
	
	return objects.length? objects:null;

}
function getValue(element) {
	if (element) {
		var s = (element.firstChild) ? element.firstChild.nodeValue : element.nodeValue;
		s = s.replace( /^\s+/g, "" );
		s = s.replace( /\s+$/g, "" );
		return s;
	} else return null
}

/* Custom functions */

/* Show confirm dialogue
   On OK commit form, on Cancel reset the 'Betreft een verhuizing' radiogroup
*/
var confirmMove = {
	init:function(name){
		this.form = document.getElementById("main-form");
		this.radios = document.getElementsByName("customer.aswitch");
		this.dialog = new FormDialog(name,this);		
	},
	showDialog:function(name){
		if (!this.dialog || this.dialog.container.id != name) {
			this.init(name);			
		}
		if (this.dialog.container.style.display != "block"
				&& this.dialog.container.style.visibility != "visible") {
		this.dialog.toggle(true);
		}
	},
	confirm:function(ok){
		if(ok){
			// push submit button on this form
			var fe = this.form.elements;
			for (var i=0;i<fe.length;i++){
				if(fe[i].type=="submit" && ClassName.contains(fe[i],"next")) {
					fe[i].name="_cancel";
					fe[i].click();
				}
			}
		} else {
			// reset radio
			this.resetRadios();
		}
	},
	resetRadios:function(){
		for(var radio,i=0;i<this.radios.length;i++){
			radio=this.radios[i];
			radio.checked = false;
			if (radio.DC) radio.DC.updateGUI();
		}
	}
}

/* Show confirm dialogue
   On OK commit form, on Cancel reset the 'Betreft een verhuizing' radiogroup
*/
var confirmPayment = {
	init:function(){
		this.radioPaymentIncasso = document.getElementById("yradio1aja");
		this.radioAcceptYes = document.getElementById("yradio5a1");
		this.radioAcceptNo = document.getElementById("yradio5a2");
		this.foldOut = document.getElementById("foldout-yradio1a");
		this.dialog = new FormDialog("dialog-payment",this);		
	},
	showDialog:function(){
		if(!this.dialog) this.init();
		this.dialog.toggle(true);
	},
	confirm:function(ok){
		if(ok){
			// select ja
			this.radioAcceptYes.checked = true;
			if (this.radioAcceptYes.DC) this.radioAcceptYes.DC.updateGUI();
		} else {
			// select automatische incasso
			this.radioAcceptNo.checked = false;
			if(this.radioAcceptNo.DC) this.radioAcceptNo.DC.updateGUI();
			this.foldOut.style.display = "none";
			this.radioPaymentIncasso.checked = true;
			if (this.radioPaymentIncasso.DC) this.radioPaymentIncasso.DC.updateGUI();
		}
	}
}



var districtHeating = {
	init:function(name){
		this.form = document.getElementById("main-form");
		this.radios = document.getElementsByName("districtHeating.hasDistrictHeating");
		this.dialog = new FormDialog(name,this);		
	},
	showDialog:function(name){
		this.init(name);
		this.dialog.toggle(true);
	},
	confirm:function(ok){
		if(ok){
			// push submit button on this form
			var fe = this.form.elements;
			for (var i=0;i<fe.length;i++){
				if(fe[i].type=="submit" && ClassName.contains(fe[i],"next")) {
					fe[i].name="_cancel";
					fe[i].click();
				}
			}
		} else {
			// reset radio
			this.resetRadios();
		}
	},
	resetRadios:function(){
		for(var radio,i=0;i<this.radios.length;i++){
			radio=this.radios[i];
			radio.checked = false;
			if (radio.DC) radio.DC.updateGUI();
		}
	}
}

var continueRegistration = {
	init:function(name){
		this.form = document.getElementById("main-form");
		this.dialog = new FormDialog(name,this);		
	},
	showDialog:function(name){
		this.init(name);
		this.dialog.toggle(true);
	},
	confirm:function(ok){
		if(ok==undefined) {
			DynamicForm.prototype.setInputValue(document.getElementById('redirectToLoginPage'),'J');
			var fe = this.form.elements;
			for (var i=0;i<fe.length;i++){
				if(fe[i].type=="submit" && ClassName.contains(fe[i],"next")) {
					fe[i].name="_cancel";
					fe[i].click();
				}
			} 
		} else if(ok){
			// do nothing
		} else if (!ok) {
			DynamicForm.prototype.setInputValue(document.getElementById('redirectToLoginPage'),'N');
			// push submit button on this form
			var fe = this.form.elements;
			for (var i=0;i<fe.length;i++){
				if(fe[i].type=="submit" && ClassName.contains(fe[i],"next")) {
					fe[i].name="_cancel";
					fe[i].click();
				}
			} 			
		}
	}
}

function submitForm(formId, pageNumber) {
	var form = document.getElementById(formId);
	if (form) {
	var fe = form.elements;
		for (var i=0;i<fe.length;i++){
			if(fe[i].type=="submit" && ClassName.contains(fe[i],"next")) {
				var oldName=fe[i].name; 
				fe[i].name="_target" + pageNumber;
				fe[i].click();
				fe[i].name=oldName;
			}
		}
	}
}

//Some functions for the contact-forms in corporate, because the rules.xml doesn't work with dropdowns

function changesubject() {
	subject = document.getElementById("contactSubject");
	if (subject != null && typeof(subject) != "undefined") {
		if (subject.value.indexOf("A-jaarverslag_") == 0) {
			document.getElementById("comment").disabled=true;
			document.getElementById("foldout-annualreport").style.display = "block";
			document.getElementById("foldout-comment").style.display = "none";
		} else {
			document.getElementById("comment").disabled=false;
			document.getElementById("foldout-annualreport").style.display = "none";
			document.getElementById("foldout-comment").style.display = "block";
		}
	}
}

function changeinfo() {
	info = document.getElementById("desiredInfoSelect");
	if (info != null && typeof(info) != "undefined") {
		if (info.value == "other") {
			document.getElementById("foldout-infotext").style.display = "block";
		} else {
			document.getElementById("foldout-infotext").style.display = "none";
		}
	}
}

/**
 * Full date field is used in combination with input fields for a date and 
 * the CalendarDialog.
 * When the date is changed a full date is generated by concatenating
 * day, month and year and put in one hidden input field.
 */
FullDateFieldUtil = {
	dateFields: {},
	init: function() {
		var fullDateFields = document.getElementsByTagName("input");
		for(var i=0;i<fullDateFields.length;i++){
			if(ClassName.contains(fullDateFields[i],"fulldate")) {
				var fullDateField = new FullDateField();
				fullDateField.init(fullDateFields[i]);
				this.dateFields[fullDateFields[i].id] = fullDateField;
			}
		}
	},
	update: function(name) {
		var dot = name.indexOf(".");
		if (dot < 0) dot = name.length;
		var thisobj = this.dateFields[name.substring(0, dot) + ".date_full"];
		if (thisobj != null && thisobj != undefined) {
			thisobj.onChange();
			DynamicFormUtil.dynamicForm.handleChange(thisobj.input);
		}

	}
}

function FullDateField() {

}

FullDateField.prototype = {
	init: function(fullDateInput) {

		var set =Utils.getParentByNodeName(fullDateInput, 'div');
		var day = set.getElementsByTagName("input")[0];
		var selects = set.getElementsByTagName("select");
		
		this.input = fullDateInput;		
		this.day = day;
		this.month = selects[0];
		this.year = selects[1];
		
		this.onChange();
		
		EventListener.addEvent(this.day,"change",this.onChange,this);
		// for year and month, as they are selects, 
		// an onchange event is added to the select html tag.
		
	},
	onChange: function() {
		this.input.value = this.day.value + "-" + this.month.options[this.month.selectedIndex].value + "-" +  this.year.options[this.year.selectedIndex].value;
	}
}

$(document).ready( function initDeviation() {
	changeDeviation();
});

function changeDeviation() {
	var selected = $("select#deviationTypes option:selected").val(); 
	if (selected == "Anders, nl:") {
		$("div#foldout-deviationExplanation").show();
	} else {
		$("div#foldout-deviationExplanation").hide();
	}
}

var confirmBBPAdvice = {
		init:function(){
			this.dialog = new FormDialog("dialog-bbp-advice-confirm",this);		
			this.form = document.getElementById("main-form");
			this.amount = document.getElementById("newBBPAmount");
			this.amountInDialog = document.getElementById("advies_confirm_wijziging");
			
		},
		showDialog:function(){
			if(!this.dialog) this.init();
			this.updateAmount();
			this.dialog.toggle(true);
		},
		updateAmount:function(){
			this.amountInDialog.innerHTML = this.amount.value;
		},
		confirm:function(ok){
			var fe = this.form.elements;
			if(ok){
					// change
					for (var i=0;i<fe.length;i++){
						if(fe[i].type=="submit" && fe[i].name=="_change") {
							fe[i].click();
						}
					}
			}

		}
	}
