Release 3.6.1
[kivitendo-erp.git] / js / FormManager.js
1 /*
2         Form Manager: A simple method of constructing complex dynamic forms.
3         Written by Twey, http://www.twey.co.uk/.
4         Use, copying, and modification allowed, so long as credit
5         remains intact, under the terms of the GNU General Public License,
6         version 2 or later. See http://www.gnu.org/copyleft/gpl.html for details.
7 */
8
9
10 var FORM_MANAGER_CONDITION_SEPARATOR = " AND ";
11 var FORM_MANAGER_POSSIBILITY_SEPARATOR = " OR ";
12 var FORM_MANAGER_NAME_VALUE_SEPARATOR = " BEING ";
13 var FORM_MANAGER_DEPENDS = "DEPENDS ON ";
14 var FORM_MANAGER_CONFLICTS = "CONFLICTS WITH ";
15 var FORM_MANAGER_EMPTY = "EMPTY";
16
17 function addEvent(el, ev, f) {
18   if(el.addEventListener)
19     el.addEventListener(ev, f, false);
20   else if(el.attachEvent) {
21     var t = function() {
22       f.apply(el);
23     };
24     addEvent.events.push({'element': el, 'event': ev, 'handler': f});
25     el.attachEvent("on" + ev, t);
26   } else
27     el['on' + ev] = f;
28 }
29
30 function addEvents(els, evs, f) {
31   for(var i = 0; i < els.length; ++i)
32     for(var j = 0; j < evs.length; ++j)
33       addEvent(els[i], evs[j], f);
34 }
35
36 addEvent.events = [];
37
38 if(typeof window.event !== "undefined")
39   addEvent(window, "unload", function() {
40       for(var i = 0, e = addEvent.events; i < e.length; ++i)
41         e[i].element.detachEvent("on" + e[i].event, e[i].handler);
42     }
43   );
44
45 function getRadioValue(el) {
46   if(!el.length) return null;
47   for(var i = 0; i < el.length; ++i)
48     if(el[i].checked) return el[i].value;
49   return null;
50 }
51
52 function getSelectValue(el) {
53   if(!el.tagName  || el.tagName.toLowerCase() !== "select")
54     return null;
55   return el.options[el.selectedIndex].value;
56 }
57
58 function isElementValue(el, v) {
59   if(v === FORM_MANAGER_EMPTY) v = '';
60   return (
61     getRadioValue(el) == v ||
62     getSelectValue(el) == v ||
63     (
64       el.tagName &&
65       el.tagName.toLowerCase() !== "select" &&
66       el.value == v
67     )
68   );
69 }
70
71 function setupDependencies() {
72   var showEl = function() {
73     this.style.display = "";
74     if(this.parentNode.tagName.toLowerCase() == "label")
75       this.parentNode.style.display = "";
76   };
77   var hideEl = function() {
78     this.style.display = "none";
79     if(typeof this.checked !== "undefined") this.checked = false;
80     else this.value = "";
81     if(this.parentNode.tagName.toLowerCase() == "label")
82       this.parentNode.style.display = "none";
83     this.hidden = true;
84   };
85   var calcDeps = function() {
86     for(var i = 0, e = this.elements; i < e.length; ++i) {
87       e[i].hidden = false;
88       for(var j = 0, f = e[i].className.split(FORM_MANAGER_CONDITION_SEPARATOR); j < f.length; ++j)
89         if(f[j].indexOf(FORM_MANAGER_DEPENDS) === 0) {
90           for(var k = 0, g = f[j].substr(FORM_MANAGER_DEPENDS.length).split(FORM_MANAGER_POSSIBILITY_SEPARATOR); k < g.length; ++k)
91             if(g[k].indexOf(FORM_MANAGER_NAME_VALUE_SEPARATOR) === -1) {
92               if(e[g[k]] && e[g[k]].checked) break;
93             else if(k + 1 == g.length)
94                 e[i].hide();
95             } else {
96               var n = g[k].split(FORM_MANAGER_NAME_VALUE_SEPARATOR),
97                 v = n[1];
98               n = n[0];
99               if(e[n])
100                 if(isElementValue(e[n], v)) break;
101                 else if(k + 1 == g.length) e[i].hide();
102             }
103         } else if(f[j].indexOf(FORM_MANAGER_CONFLICTS) === 0) {
104           if(f[j].indexOf(FORM_MANAGER_NAME_VALUE_SEPARATOR) === -1) {
105             if(e[f[j].substr(FORM_MANAGER_CONFLICTS.length)] && e[f[j].substr(FORM_MANAGER_CONFLICTS.length)].checked) {
106               e[i].hide();
107               break;
108             }
109           } else {
110             var n = f[j].substr(FORM_MANAGER_CONFLICTS.length).split(FORM_MANAGER_NAME_VALUE_SEPARATOR),
111               v = n[1];
112             n = n[0];
113             if(e[n]) {
114               if(isElementValue(e[n], v)) {
115                 e[i].hide();
116                 break;
117               }
118             }
119           }
120         }
121       if(!e[i].hidden) e[i].show();
122     }
123   };
124   var changeHandler = function() {
125     this.form.calculateDependencies();
126     return true;
127   };
128   for(var i = 0; i < arguments.length; ++i) {
129     for(var j = 0, e = window.document.forms[arguments[i]].elements; j < e.length; ++j) {
130       addEvents([e[j]], ["change", "keyup", "focus", "click", "keydown"], changeHandler);
131       e[j].hide = hideEl;
132       e[j].show = showEl;
133     }
134
135     (e = window.document.forms[arguments[i]]).calculateDependencies = calcDeps;
136     e.calculateDependencies();
137   }
138 }