/* 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