CBI: Free dependencies
[project/luci.git] / libs / cbi / htdocs / luci-static / resources / cbi.js
1 /*
2         LuCI - Lua Configuration Interface
3
4         Copyright 2008 Steven Barth <steven@midlink.org>
5         Copyright 2008-2009 Jo-Philipp Wich <xm@subsignal.org>
6
7         Licensed under the Apache License, Version 2.0 (the "License");
8         you may not use this file except in compliance with the License.
9         You may obtain a copy of the License at
10
11         http://www.apache.org/licenses/LICENSE-2.0
12
13         $Id$
14 */
15
16 var cbi_d = [];
17 var cbi_t = [];
18 var cbi_c = [];
19
20 function cbi_d_add(field, dep, next) {
21         var obj = document.getElementById(field);
22         if (obj) {
23                 var entry
24                 for (var i=0; i<cbi_d.length; i++) {
25                         if (cbi_d[i].id == field) {
26                                 entry = cbi_d[i];
27                                 break;
28                         }
29                 }
30                 if (!entry) {
31                         entry = {
32                                 "node": obj,
33                                 "id": field,
34                                 "parent": obj.parentNode.id,
35                                 "next": next,
36                                 "deps": []
37                         };
38                         cbi_d.unshift(entry);
39                 }
40                 entry.deps.push(dep)
41         }
42 }
43
44 function cbi_d_checkvalue(target, ref) {
45         var t = document.getElementById(target);
46         var value;
47
48         if (!t || !t.value) {
49                 value = "";
50         } else {
51                 value = t.value;
52
53                 if (t.type == "checkbox") {
54                         value = t.checked ? value : "";
55                 }
56         }
57
58         return (value == ref)
59 }
60
61 function cbi_d_check(deps) {
62         var reverse;
63         var def = false;
64         for (var i=0; i<deps.length; i++) {
65                 var istat = true;
66                 reverse = false;
67                 for (var j in deps[i]) {
68                         if (j == "!reverse") {
69                                 reverse = true;
70                         } else if (j == "!default") {
71                                 def = true;
72                                 istat = false;
73                         } else {
74                                 istat = (istat && cbi_d_checkvalue(j, deps[i][j]))
75                         }
76                 }
77                 if (istat) {
78                         return !reverse;
79                 }
80         }
81         return def;
82 }
83
84 function cbi_d_update() {
85         var state = false;
86         for (var i=0; i<cbi_d.length; i++) {
87                 var entry = cbi_d[i];
88                 var next  = document.getElementById(entry.next)
89                 var node  = document.getElementById(entry.id)
90                 var parent = document.getElementById(entry.parent)
91
92                 if (node && node.parentNode && !cbi_d_check(entry.deps)) {
93                         node.parentNode.removeChild(node);
94                         state = (state || !node.parentNode);
95                         if( entry.parent )
96                                 cbi_c[entry.parent]--;
97                 } else if ((!node || !node.parentNode) && cbi_d_check(entry.deps)) {
98                         if (!next) {
99                                 parent.appendChild(entry.node);
100                         } else {
101                                 next.parentNode.insertBefore(entry.node, next);
102                         }
103                         state = (state || (node && node.parentNode))
104                         if( entry.parent )
105                                 cbi_c[entry.parent]++;
106                 }
107         }
108
109         if (entry.parent) {
110                 cbi_t_update();
111         }
112
113         if (state) {
114                 cbi_d_update();
115         }
116 }
117
118 function cbi_bind(obj, type, callback, mode) {
119         if (typeof mode == "undefined") {
120                 mode = false;
121         }
122         if (!obj.addEventListener) {
123                 ieCallback = function(){
124                         var e = window.event;
125                         if (!e.target && e.srcElement) {
126                                 e.target = e.srcElement;
127                         };
128                         e.target['_eCB' + type + callback] = callback;
129                         e.target['_eCB' + type + callback](e);
130                         e.target['_eCB' + type + callback] = null;
131                 };
132                 obj.attachEvent('on' + type, ieCallback);
133         } else {
134                 obj.addEventListener(type, callback, mode);
135         }
136         return obj;
137 }
138
139 function cbi_combobox(id, values, def, man) {
140         var selid = "cbi.combobox." + id;
141         if (document.getElementById(selid)) {
142                 return
143         }
144
145         var obj = document.getElementById(id)
146         var sel = document.createElement("select");
147         sel.id = selid;
148         sel.className = 'cbi-input-select';
149         if (obj.nextSibling) {
150                 obj.parentNode.insertBefore(sel, obj.nextSibling);
151         } else {
152                 obj.parentNode.appendChild(sel);
153         }
154
155         if (!values[obj.value]) {
156                 if (obj.value == "") {
157                         var optdef = document.createElement("option");
158                         optdef.value = "";
159                         optdef.appendChild(document.createTextNode(def));
160                         sel.appendChild(optdef);
161                 } else {
162                         var opt = document.createElement("option");
163                         opt.value = obj.value;
164                         opt.selected = "selected";
165                         opt.appendChild(document.createTextNode(obj.value));
166                         sel.appendChild(opt);
167                 }
168         }
169
170         for (var i in values) {
171                 var opt = document.createElement("option");
172                 opt.value = i;
173
174                 if (obj.value == i) {
175                         opt.selected = "selected";
176                 }
177
178                 opt.appendChild(document.createTextNode(values[i]));
179                 sel.appendChild(opt);
180         }
181
182         var optman = document.createElement("option");
183         optman.value = "";
184         optman.appendChild(document.createTextNode(man));
185         sel.appendChild(optman);
186
187         obj.style.display = "none";
188
189         cbi_bind(sel, "change", function() {
190                 if (sel.selectedIndex == sel.options.length - 1) {
191                         obj.style.display = "inline";
192                         sel.parentNode.removeChild(sel);
193                         obj.focus();
194                 } else {
195                         obj.value = sel.options[sel.selectedIndex].value;
196                 }
197
198                 try {
199                         cbi_d_update();
200                 } catch (e) {
201                         //Do nothing
202                 }
203         })
204 }
205
206 function cbi_combobox_init(id, values, def, man) {
207         var obj = document.getElementById(id);
208         cbi_bind(obj, "blur", function() {
209                 cbi_combobox(id, values, def, man)
210         });
211         cbi_combobox(id, values, def, man);
212 }
213
214 function cbi_filebrowser(id, url, defpath) {
215         var field   = document.getElementById(id);
216         var browser = window.open(
217                 url + ( field.value || defpath || '' ) + '?field=' + id,
218                 "luci_filebrowser", "width=300,height=400,left=100,top=200,scrollbars=yes"
219         );
220
221         browser.focus();
222 }
223
224 //Hijacks the CBI form to send via XHR (requires Prototype)
225 function cbi_hijack_forms(layer, win, fail, load) {
226         var forms = layer.getElementsByTagName('form');
227         for (var i=0; i<forms.length; i++) {
228                 $(forms[i]).observe('submit', function(event) {
229                         // Prevent the form from also submitting the regular way
230                         event.stop();
231
232                         // Submit via XHR
233                         event.element().request({
234                                 onSuccess: win,
235                                 onFailure: fail
236                         });
237
238                         if (load) {
239                                 load();
240                         }
241                 });
242         }
243 }
244
245
246 function cbi_t_add(section, tab) {
247         var t = document.getElementById('tab.' + section + '.' + tab);
248         var c = document.getElementById('container.' + section + '.' + tab);
249
250         if( t && c ) {
251                 cbi_t[section] = (cbi_t[section] || [ ]);
252                 cbi_t[section][tab] = { 'tab': t, 'container': c, 'cid': c.id };
253         }
254 }
255
256 function cbi_t_switch(section, tab) {
257         if( cbi_t[section] && cbi_t[section][tab] ) {
258                 var o = cbi_t[section][tab];
259                 var h = document.getElementById('tab.' + section);
260                 for( var tid in cbi_t[section] ) {
261                         var o2 = cbi_t[section][tid];
262                         if( o.tab.id != o2.tab.id ) {
263                                 o2.tab.className = o2.tab.className.replace(/(^| )cbi-tab( |$)/, " cbi-tab-disabled ");
264                                 o2.container.style.display = 'none';
265                         }
266                         else {
267                                 if(h) h.value = tab;
268                                 o2.tab.className = o2.tab.className.replace(/(^| )cbi-tab-disabled( |$)/, " cbi-tab ");
269                                 o2.container.style.display = 'block';
270                         }
271                 }
272         }
273         return false
274 }
275
276 function cbi_t_update() {
277         for( var sid in cbi_t )
278                 for( var tid in cbi_t[sid] )
279                         if( cbi_c[cbi_t[sid][tid].cid] == 0 ) {
280                                 cbi_t[sid][tid].tab.style.display = 'none';
281                         }
282                         else if( cbi_t[sid][tid].tab && cbi_t[sid][tid].tab.style.display == 'none' ) {
283                                 cbi_t[sid][tid].tab.style.display = '';
284
285                                 var t = cbi_t[sid][tid].tab;
286                                 window.setTimeout(function() { t.className = t.className.replace(/ cbi-tab-highlighted/g, '') }, 750);
287                                 cbi_t[sid][tid].tab.className += ' cbi-tab-highlighted';
288                         }
289 }
290