004e12eaa413ce23b1681c04071c14e76624f260
[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         for (var i=0; i<deps.length; i++) {
63                 var istat = true
64                 for (var j in deps[i]) {
65                         istat = (istat && cbi_d_checkvalue(j, deps[i][j]))
66                 }
67                 if (istat) {
68                         return true
69                 }
70         }
71 }
72
73 function cbi_d_update() {
74         var state = false;
75         for (var i=0; i<cbi_d.length; i++) {
76                 var entry = cbi_d[i];
77                 var next  = document.getElementById(entry.next)
78                 var node  = document.getElementById(entry.id)
79                 var parent = document.getElementById(entry.parent)
80
81                 if (node && node.parentNode && !cbi_d_check(entry.deps)) {
82                         node.parentNode.removeChild(node);
83                         state = (state || !node.parentNode);
84                         if( entry.parent )
85                                 cbi_c[entry.parent]--;
86                 } else if ((!node || !node.parentNode) && cbi_d_check(entry.deps)) {
87                         if (!next) {
88                                 parent.appendChild(entry.node);
89                         } else {
90                                 next.parentNode.insertBefore(entry.node, next);
91                         }
92                         state = (state || (node && node.parentNode))
93                         if( entry.parent )
94                                 cbi_c[entry.parent]++;
95                 }
96         }
97
98         if (entry.parent) {
99                 cbi_t_update();
100         }
101
102         if (state) {
103                 cbi_d_update();
104         }
105 }
106
107 function cbi_bind(obj, type, callback, mode) {
108         if (typeof mode == "undefined") {
109                 mode = false;
110         }
111         if (!obj.addEventListener) {
112                 ieCallback = function(){
113                         var e = window.event;
114                         if (!e.target && e.srcElement) {
115                                 e.target = e.srcElement;
116                         };
117                         e.target['_eCB' + type + callback] = callback;
118                         e.target['_eCB' + type + callback](e);
119                         e.target['_eCB' + type + callback] = null;
120                 };
121                 obj.attachEvent('on' + type, ieCallback);
122         } else {
123                 obj.addEventListener(type, callback, mode);
124         }
125         return obj;
126 }
127
128 function cbi_combobox(id, values, def, man) {
129         var selid = "cbi.combobox." + id;
130         if (document.getElementById(selid)) {
131                 return
132         }
133
134         var obj = document.getElementById(id)
135         var sel = document.createElement("select");
136         sel.id = selid;
137         sel.className = 'cbi-input-select';
138         if (obj.nextSibling) {
139                 obj.parentNode.insertBefore(sel, obj.nextSibling);
140         } else {
141                 obj.parentNode.appendChild(sel);
142         }
143
144         if (!values[obj.value]) {
145                 if (obj.value == "") {
146                         var optdef = document.createElement("option");
147                         optdef.value = "";
148                         optdef.appendChild(document.createTextNode(def));
149                         sel.appendChild(optdef);
150                 } else {
151                         var opt = document.createElement("option");
152                         opt.value = obj.value;
153                         opt.selected = "selected";
154                         opt.appendChild(document.createTextNode(obj.value));
155                         sel.appendChild(opt);
156                 }
157         }
158
159         for (var i in values) {
160                 var opt = document.createElement("option");
161                 opt.value = i;
162
163                 if (obj.value == i) {
164                         opt.selected = "selected";
165                 }
166
167                 opt.appendChild(document.createTextNode(values[i]));
168                 sel.appendChild(opt);
169         }
170
171         var optman = document.createElement("option");
172         optman.value = "";
173         optman.appendChild(document.createTextNode(man));
174         sel.appendChild(optman);
175
176         obj.style.display = "none";
177
178         cbi_bind(sel, "change", function() {
179                 if (sel.selectedIndex == sel.options.length - 1) {
180                         obj.style.display = "inline";
181                         sel.parentNode.removeChild(sel);
182                         obj.focus();
183                 } else {
184                         obj.value = sel.options[sel.selectedIndex].value;
185                 }
186
187                 try {
188                         cbi_d_update();
189                 } catch (e) {
190                         //Do nothing
191                 }
192         })
193 }
194
195 function cbi_combobox_init(id, values, def, man) {
196         var obj = document.getElementById(id);
197         cbi_bind(obj, "blur", function() {
198                 cbi_combobox(id, values, def, man)
199         });
200         cbi_combobox(id, values, def, man);
201 }
202
203 function cbi_filebrowser(id, url, defpath) {
204         var field   = document.getElementById(id);
205         var browser = window.open(
206                 url + ( field.value || defpath || '' ) + '?field=' + id,
207                 "luci_filebrowser", "width=300,height=400,left=100,top=200,scrollbars=yes"
208         );
209
210         browser.focus();
211 }
212
213 //Hijacks the CBI form to send via XHR (requires Prototype)
214 function cbi_hijack_forms(layer, win, fail, load) {
215         var forms = layer.getElementsByTagName('form');
216         for (var i=0; i<forms.length; i++) {
217                 $(forms[i]).observe('submit', function(event) {
218                         // Prevent the form from also submitting the regular way
219                         event.stop();
220
221                         // Submit via XHR
222                         event.element().request({
223                                 onSuccess: win,
224                                 onFailure: fail
225                         });
226
227                         if (load) {
228                                 load();
229                         }
230                 });
231         }
232 }
233
234
235 function cbi_t_add(section, tab) {
236         var t = document.getElementById('tab.' + section + '.' + tab);
237         var c = document.getElementById('container.' + section + '.' + tab);
238
239         if( t && c ) {
240                 cbi_t[section] = (cbi_t[section] || [ ]);
241                 cbi_t[section][tab] = { 'tab': t, 'container': c, 'cid': c.id };
242         }
243 }
244
245 function cbi_t_switch(section, tab) {
246         if( cbi_t[section] && cbi_t[section][tab] ) {
247                 var o = cbi_t[section][tab];
248                 var h = document.getElementById('tab.' + section);
249                 for( var tid in cbi_t[section] ) {
250                         var o2 = cbi_t[section][tid];
251                         if( o.tab.id != o2.tab.id ) {
252                                 o2.tab.className = o2.tab.className.replace(/(^| )cbi-tab( |$)/, " cbi-tab-disabled ");
253                                 o2.container.style.display = 'none';
254                         }
255                         else {
256                                 if(h) h.value = tab;
257                                 o2.tab.className = o2.tab.className.replace(/(^| )cbi-tab-disabled( |$)/, " cbi-tab ");
258                                 o2.container.style.display = 'block';
259                         }
260                 }
261         }
262         return false
263 }
264
265 function cbi_t_update() {
266         for( var sid in cbi_t )
267                 for( var tid in cbi_t[sid] )
268                         if( cbi_c[cbi_t[sid][tid].cid] == 0 ) {
269                                 cbi_t[sid][tid].tab.style.display = 'none';
270                         }
271                         else if( cbi_t[sid][tid].tab && cbi_t[sid][tid].tab.style.display == 'none' ) {
272                                 cbi_t[sid][tid].tab.style.display = '';
273
274                                 var t = cbi_t[sid][tid].tab;
275                                 window.setTimeout(function() { t.className = t.className.replace(/ cbi-tab-highlighted/g, '') }, 750);
276                                 cbi_t[sid][tid].tab.className += ' cbi-tab-highlighted';
277                         }
278 }
279