5 <title>Source: ui.js
</title>
8 <script src=
"scripts/prettify/prettify.js"></script>
9 <script src=
"scripts/prettify/lang-css.js"></script>
10 <script src=
"scripts/jquery.min.js"></script>
12 <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
14 <link type=
"text/css" rel=
"stylesheet" href=
"styles/prettify-tomorrow.css">
15 <link type=
"text/css" rel=
"stylesheet" href=
"styles/bootstrap.min.css">
16 <link type=
"text/css" rel=
"stylesheet" href=
"styles/jaguar.css">
20 var config = {
"monospaceLinks":true,
"cleverLinks":true,
"default":{
"outputSourceFiles":true}};
27 <div id=
"wrap" class=
"clearfix">
29 <div class=
"navigation">
30 <h3 class=
"applicationName"><a href=
"index.html"></a></h3>
33 <input id=
"search" type=
"text" class=
"form-control input-sm" placeholder=
"Search Documentations">
37 <li class=
"item" data-name=
"LuCI">
39 <a href=
"LuCI.html">LuCI
</a>
42 <ul class=
"members itemMembers">
44 <span class=
"subtitle">Members
</span>
46 <li data-name=
"LuCI#Class"><a href=
"LuCI.html#Class">Class
</a></li>
48 <li data-name=
"LuCI#dom"><a href=
"LuCI.html#dom">dom
</a></li>
50 <li data-name=
"LuCI#env"><a href=
"LuCI.html#env">env
</a></li>
52 <li data-name=
"LuCI#Poll"><a href=
"LuCI.html#Poll">Poll
</a></li>
54 <li data-name=
"LuCI#Request"><a href=
"LuCI.html#Request">Request
</a></li>
56 <li data-name=
"LuCI#view"><a href=
"LuCI.html#view">view
</a></li>
59 <ul class=
"typedefs itemMembers">
61 <span class=
"subtitle">Typedefs
</span>
63 <li data-name=
"LuCI.requestCallbackFn"><a href=
"LuCI.html#.requestCallbackFn">requestCallbackFn
</a></li>
66 <ul class=
"typedefs itemMembers">
69 <ul class=
"methods itemMembers">
71 <span class=
"subtitle">Methods
</span>
73 <li data-name=
"LuCI#bind"><a href=
"LuCI.html#bind">bind
</a></li>
75 <li data-name=
"LuCI#error"><a href=
"LuCI.html#error">error
</a></li>
77 <li data-name=
"LuCI#fspath"><a href=
"LuCI.html#fspath">fspath
</a></li>
79 <li data-name=
"LuCI#get"><a href=
"LuCI.html#get">get
</a></li>
81 <li data-name=
"LuCI#halt"><a href=
"LuCI.html#halt">halt
</a></li>
83 <li data-name=
"LuCI#hasSystemFeature"><a href=
"LuCI.html#hasSystemFeature">hasSystemFeature
</a></li>
85 <li data-name=
"LuCI#hasViewPermission"><a href=
"LuCI.html#hasViewPermission">hasViewPermission
</a></li>
87 <li data-name=
"LuCI#isObject"><a href=
"LuCI.html#isObject">isObject
</a></li>
89 <li data-name=
"LuCI#location"><a href=
"LuCI.html#location">location
</a></li>
91 <li data-name=
"LuCI#media"><a href=
"LuCI.html#media">media
</a></li>
93 <li data-name=
"LuCI#path"><a href=
"LuCI.html#path">path
</a></li>
95 <li data-name=
"LuCI#poll"><a href=
"LuCI.html#poll">poll
</a></li>
97 <li data-name=
"LuCI#post"><a href=
"LuCI.html#post">post
</a></li>
99 <li data-name=
"LuCI#raise"><a href=
"LuCI.html#raise">raise
</a></li>
101 <li data-name=
"LuCI#require"><a href=
"LuCI.html#require">require
</a></li>
103 <li data-name=
"LuCI#resolveDefault"><a href=
"LuCI.html#resolveDefault">resolveDefault
</a></li>
105 <li data-name=
"LuCI#resource"><a href=
"LuCI.html#resource">resource
</a></li>
107 <li data-name=
"LuCI#run"><a href=
"LuCI.html#run">run
</a></li>
109 <li data-name=
"LuCI#sortedKeys"><a href=
"LuCI.html#sortedKeys">sortedKeys
</a></li>
111 <li data-name=
"LuCI#stop"><a href=
"LuCI.html#stop">stop
</a></li>
113 <li data-name=
"LuCI#toArray"><a href=
"LuCI.html#toArray">toArray
</a></li>
115 <li data-name=
"LuCI#url"><a href=
"LuCI.html#url">url
</a></li>
118 <ul class=
"events itemMembers">
123 <li class=
"item" data-name=
"LuCI.baseclass">
125 <a href=
"LuCI.baseclass.html">LuCI.baseclass
</a>
128 <ul class=
"members itemMembers">
131 <ul class=
"typedefs itemMembers">
134 <ul class=
"typedefs itemMembers">
137 <ul class=
"methods itemMembers">
139 <span class=
"subtitle">Methods
</span>
141 <li data-name=
"LuCI.baseclass.extend"><a href=
"LuCI.baseclass.html#.extend">extend
</a></li>
143 <li data-name=
"LuCI.baseclass.instantiate"><a href=
"LuCI.baseclass.html#.instantiate">instantiate
</a></li>
145 <li data-name=
"LuCI.baseclass.isSubclass"><a href=
"LuCI.baseclass.html#.isSubclass">isSubclass
</a></li>
147 <li data-name=
"LuCI.baseclass.singleton"><a href=
"LuCI.baseclass.html#.singleton">singleton
</a></li>
149 <li data-name=
"LuCI.baseclass#super"><a href=
"LuCI.baseclass.html#super">super
</a></li>
151 <li data-name=
"LuCI.baseclass#varargs"><a href=
"LuCI.baseclass.html#varargs">varargs
</a></li>
154 <ul class=
"events itemMembers">
159 <li class=
"item" data-name=
"LuCI.dom">
161 <a href=
"LuCI.dom.html">LuCI.dom
</a>
164 <ul class=
"members itemMembers">
167 <ul class=
"typedefs itemMembers">
169 <span class=
"subtitle">Typedefs
</span>
171 <li data-name=
"LuCI.dom~ignoreCallbackFn"><a href=
"LuCI.dom.html#~ignoreCallbackFn">ignoreCallbackFn
</a></li>
174 <ul class=
"typedefs itemMembers">
177 <ul class=
"methods itemMembers">
179 <span class=
"subtitle">Methods
</span>
181 <li data-name=
"LuCI.dom#append"><a href=
"LuCI.dom.html#append">append
</a></li>
183 <li data-name=
"LuCI.dom#attr"><a href=
"LuCI.dom.html#attr">attr
</a></li>
185 <li data-name=
"LuCI.dom#bindClassInstance"><a href=
"LuCI.dom.html#bindClassInstance">bindClassInstance
</a></li>
187 <li data-name=
"LuCI.dom#callClassMethod"><a href=
"LuCI.dom.html#callClassMethod">callClassMethod
</a></li>
189 <li data-name=
"LuCI.dom#content"><a href=
"LuCI.dom.html#content">content
</a></li>
191 <li data-name=
"LuCI.dom#create"><a href=
"LuCI.dom.html#create">create
</a></li>
193 <li data-name=
"LuCI.dom#data"><a href=
"LuCI.dom.html#data">data
</a></li>
195 <li data-name=
"LuCI.dom#elem"><a href=
"LuCI.dom.html#elem">elem
</a></li>
197 <li data-name=
"LuCI.dom#findClassInstance"><a href=
"LuCI.dom.html#findClassInstance">findClassInstance
</a></li>
199 <li data-name=
"LuCI.dom#isEmpty"><a href=
"LuCI.dom.html#isEmpty">isEmpty
</a></li>
201 <li data-name=
"LuCI.dom#matches"><a href=
"LuCI.dom.html#matches">matches
</a></li>
203 <li data-name=
"LuCI.dom#parent"><a href=
"LuCI.dom.html#parent">parent
</a></li>
205 <li data-name=
"LuCI.dom#parse"><a href=
"LuCI.dom.html#parse">parse
</a></li>
208 <ul class=
"events itemMembers">
213 <li class=
"item" data-name=
"LuCI.form">
215 <a href=
"LuCI.form.html">LuCI.form
</a>
218 <ul class=
"members itemMembers">
221 <ul class=
"typedefs itemMembers">
224 <ul class=
"typedefs itemMembers">
227 <ul class=
"methods itemMembers">
230 <ul class=
"events itemMembers">
235 <li class=
"item" data-name=
"LuCI.form.AbstractElement">
237 <a href=
"LuCI.form.AbstractElement.html">LuCI.form.AbstractElement
</a>
240 <ul class=
"members itemMembers">
243 <ul class=
"typedefs itemMembers">
246 <ul class=
"typedefs itemMembers">
249 <ul class=
"methods itemMembers">
251 <span class=
"subtitle">Methods
</span>
253 <li data-name=
"LuCI.form.AbstractElement#append"><a href=
"LuCI.form.AbstractElement.html#append">append
</a></li>
255 <li data-name=
"LuCI.form.AbstractElement#parse"><a href=
"LuCI.form.AbstractElement.html#parse">parse
</a></li>
257 <li data-name=
"LuCI.form.AbstractElement#render"><a href=
"LuCI.form.AbstractElement.html#render">render
</a></li>
259 <li data-name=
"LuCI.form.AbstractElement#stripTags"><a href=
"LuCI.form.AbstractElement.html#stripTags">stripTags
</a></li>
261 <li data-name=
"LuCI.form.AbstractElement#titleFn"><a href=
"LuCI.form.AbstractElement.html#titleFn">titleFn
</a></li>
264 <ul class=
"events itemMembers">
269 <li class=
"item" data-name=
"LuCI.form.AbstractSection">
271 <a href=
"LuCI.form.AbstractSection.html">LuCI.form.AbstractSection
</a>
274 <ul class=
"members itemMembers">
276 <span class=
"subtitle">Members
</span>
278 <li data-name=
"LuCI.form.AbstractSection##parentoption"><a href=
"LuCI.form.AbstractSection.html#parentoption">parentoption
</a></li>
281 <ul class=
"typedefs itemMembers">
284 <ul class=
"typedefs itemMembers">
287 <ul class=
"methods itemMembers">
289 <span class=
"subtitle">Methods
</span>
291 <li data-name=
"LuCI.form.AbstractSection#append"><a href=
"LuCI.form.AbstractSection.html#append">append
</a></li>
293 <li data-name=
"LuCI.form.AbstractSection#cfgsections"><a href=
"LuCI.form.AbstractSection.html#cfgsections">cfgsections
</a></li>
295 <li data-name=
"LuCI.form.AbstractSection#cfgvalue"><a href=
"LuCI.form.AbstractSection.html#cfgvalue">cfgvalue
</a></li>
297 <li data-name=
"LuCI.form.AbstractSection#filter"><a href=
"LuCI.form.AbstractSection.html#filter">filter
</a></li>
299 <li data-name=
"LuCI.form.AbstractSection#formvalue"><a href=
"LuCI.form.AbstractSection.html#formvalue">formvalue
</a></li>
301 <li data-name=
"LuCI.form.AbstractSection#getOption"><a href=
"LuCI.form.AbstractSection.html#getOption">getOption
</a></li>
303 <li data-name=
"LuCI.form.AbstractSection#getUIElement"><a href=
"LuCI.form.AbstractSection.html#getUIElement">getUIElement
</a></li>
305 <li data-name=
"LuCI.form.AbstractSection#load"><a href=
"LuCI.form.AbstractSection.html#load">load
</a></li>
307 <li data-name=
"LuCI.form.AbstractSection#option"><a href=
"LuCI.form.AbstractSection.html#option">option
</a></li>
309 <li data-name=
"LuCI.form.AbstractSection#parse"><a href=
"LuCI.form.AbstractSection.html#parse">parse
</a></li>
311 <li data-name=
"LuCI.form.AbstractSection#render"><a href=
"LuCI.form.AbstractSection.html#render">render
</a></li>
313 <li data-name=
"LuCI.form.AbstractSection#stripTags"><a href=
"LuCI.form.AbstractSection.html#stripTags">stripTags
</a></li>
315 <li data-name=
"LuCI.form.AbstractSection#tab"><a href=
"LuCI.form.AbstractSection.html#tab">tab
</a></li>
317 <li data-name=
"LuCI.form.AbstractSection#taboption"><a href=
"LuCI.form.AbstractSection.html#taboption">taboption
</a></li>
319 <li data-name=
"LuCI.form.AbstractSection#titleFn"><a href=
"LuCI.form.AbstractSection.html#titleFn">titleFn
</a></li>
322 <ul class=
"events itemMembers">
327 <li class=
"item" data-name=
"LuCI.form.AbstractValue">
329 <a href=
"LuCI.form.AbstractValue.html">LuCI.form.AbstractValue
</a>
332 <ul class=
"members itemMembers">
334 <span class=
"subtitle">Members
</span>
336 <li data-name=
"LuCI.form.AbstractValue##datatype"><a href=
"LuCI.form.AbstractValue.html#datatype">datatype
</a></li>
338 <li data-name=
"LuCI.form.AbstractValue##default"><a href=
"LuCI.form.AbstractValue.html#default">default
</a></li>
340 <li data-name=
"LuCI.form.AbstractValue##editable"><a href=
"LuCI.form.AbstractValue.html#editable">editable
</a></li>
342 <li data-name=
"LuCI.form.AbstractValue##modalonly"><a href=
"LuCI.form.AbstractValue.html#modalonly">modalonly
</a></li>
344 <li data-name=
"LuCI.form.AbstractValue##onchange"><a href=
"LuCI.form.AbstractValue.html#onchange">onchange
</a></li>
346 <li data-name=
"LuCI.form.AbstractValue##optional"><a href=
"LuCI.form.AbstractValue.html#optional">optional
</a></li>
348 <li data-name=
"LuCI.form.AbstractValue##readonly"><a href=
"LuCI.form.AbstractValue.html#readonly">readonly
</a></li>
350 <li data-name=
"LuCI.form.AbstractValue##rmempty"><a href=
"LuCI.form.AbstractValue.html#rmempty">rmempty
</a></li>
352 <li data-name=
"LuCI.form.AbstractValue##uciconfig"><a href=
"LuCI.form.AbstractValue.html#uciconfig">uciconfig
</a></li>
354 <li data-name=
"LuCI.form.AbstractValue##ucioption"><a href=
"LuCI.form.AbstractValue.html#ucioption">ucioption
</a></li>
356 <li data-name=
"LuCI.form.AbstractValue##ucisection"><a href=
"LuCI.form.AbstractValue.html#ucisection">ucisection
</a></li>
358 <li data-name=
"LuCI.form.AbstractValue##validate"><a href=
"LuCI.form.AbstractValue.html#validate">validate
</a></li>
360 <li data-name=
"LuCI.form.AbstractValue##width"><a href=
"LuCI.form.AbstractValue.html#width">width
</a></li>
363 <ul class=
"typedefs itemMembers">
366 <ul class=
"typedefs itemMembers">
369 <ul class=
"methods itemMembers">
371 <span class=
"subtitle">Methods
</span>
373 <li data-name=
"LuCI.form.AbstractValue#append"><a href=
"LuCI.form.AbstractValue.html#append">append
</a></li>
375 <li data-name=
"LuCI.form.AbstractValue#cbid"><a href=
"LuCI.form.AbstractValue.html#cbid">cbid
</a></li>
377 <li data-name=
"LuCI.form.AbstractValue#cfgvalue"><a href=
"LuCI.form.AbstractValue.html#cfgvalue">cfgvalue
</a></li>
379 <li data-name=
"LuCI.form.AbstractValue#depends"><a href=
"LuCI.form.AbstractValue.html#depends">depends
</a></li>
381 <li data-name=
"LuCI.form.AbstractValue#formvalue"><a href=
"LuCI.form.AbstractValue.html#formvalue">formvalue
</a></li>
383 <li data-name=
"LuCI.form.AbstractValue#getUIElement"><a href=
"LuCI.form.AbstractValue.html#getUIElement">getUIElement
</a></li>
385 <li data-name=
"LuCI.form.AbstractValue#isActive"><a href=
"LuCI.form.AbstractValue.html#isActive">isActive
</a></li>
387 <li data-name=
"LuCI.form.AbstractValue#isValid"><a href=
"LuCI.form.AbstractValue.html#isValid">isValid
</a></li>
389 <li data-name=
"LuCI.form.AbstractValue#load"><a href=
"LuCI.form.AbstractValue.html#load">load
</a></li>
391 <li data-name=
"LuCI.form.AbstractValue#parse"><a href=
"LuCI.form.AbstractValue.html#parse">parse
</a></li>
393 <li data-name=
"LuCI.form.AbstractValue#remove"><a href=
"LuCI.form.AbstractValue.html#remove">remove
</a></li>
395 <li data-name=
"LuCI.form.AbstractValue#render"><a href=
"LuCI.form.AbstractValue.html#render">render
</a></li>
397 <li data-name=
"LuCI.form.AbstractValue#stripTags"><a href=
"LuCI.form.AbstractValue.html#stripTags">stripTags
</a></li>
399 <li data-name=
"LuCI.form.AbstractValue#textvalue"><a href=
"LuCI.form.AbstractValue.html#textvalue">textvalue
</a></li>
401 <li data-name=
"LuCI.form.AbstractValue#titleFn"><a href=
"LuCI.form.AbstractValue.html#titleFn">titleFn
</a></li>
403 <li data-name=
"LuCI.form.AbstractValue#validate"><a href=
"LuCI.form.AbstractValue.html#validate">validate
</a></li>
405 <li data-name=
"LuCI.form.AbstractValue#write"><a href=
"LuCI.form.AbstractValue.html#write">write
</a></li>
408 <ul class=
"events itemMembers">
413 <li class=
"item" data-name=
"LuCI.form.ButtonValue">
415 <a href=
"LuCI.form.ButtonValue.html">LuCI.form.ButtonValue
</a>
418 <ul class=
"members itemMembers">
420 <span class=
"subtitle">Members
</span>
422 <li data-name=
"LuCI.form.ButtonValue##inputstyle"><a href=
"LuCI.form.ButtonValue.html#inputstyle">inputstyle
</a></li>
424 <li data-name=
"LuCI.form.ButtonValue##inputtitle"><a href=
"LuCI.form.ButtonValue.html#inputtitle">inputtitle
</a></li>
426 <li data-name=
"LuCI.form.ButtonValue##onclick"><a href=
"LuCI.form.ButtonValue.html#onclick">onclick
</a></li>
428 <li data-name=
"LuCI.form.ButtonValue#datatype"><a href=
"LuCI.form.ButtonValue.html#datatype">datatype
</a></li>
430 <li data-name=
"LuCI.form.ButtonValue#default"><a href=
"LuCI.form.ButtonValue.html#default">default
</a></li>
432 <li data-name=
"LuCI.form.ButtonValue#editable"><a href=
"LuCI.form.ButtonValue.html#editable">editable
</a></li>
434 <li data-name=
"LuCI.form.ButtonValue#modalonly"><a href=
"LuCI.form.ButtonValue.html#modalonly">modalonly
</a></li>
436 <li data-name=
"LuCI.form.ButtonValue#onchange"><a href=
"LuCI.form.ButtonValue.html#onchange">onchange
</a></li>
438 <li data-name=
"LuCI.form.ButtonValue#optional"><a href=
"LuCI.form.ButtonValue.html#optional">optional
</a></li>
440 <li data-name=
"LuCI.form.ButtonValue#password"><a href=
"LuCI.form.ButtonValue.html#password">password
</a></li>
442 <li data-name=
"LuCI.form.ButtonValue#placeholder"><a href=
"LuCI.form.ButtonValue.html#placeholder">placeholder
</a></li>
444 <li data-name=
"LuCI.form.ButtonValue#readonly"><a href=
"LuCI.form.ButtonValue.html#readonly">readonly
</a></li>
446 <li data-name=
"LuCI.form.ButtonValue#rmempty"><a href=
"LuCI.form.ButtonValue.html#rmempty">rmempty
</a></li>
448 <li data-name=
"LuCI.form.ButtonValue#uciconfig"><a href=
"LuCI.form.ButtonValue.html#uciconfig">uciconfig
</a></li>
450 <li data-name=
"LuCI.form.ButtonValue#ucioption"><a href=
"LuCI.form.ButtonValue.html#ucioption">ucioption
</a></li>
452 <li data-name=
"LuCI.form.ButtonValue#ucisection"><a href=
"LuCI.form.ButtonValue.html#ucisection">ucisection
</a></li>
454 <li data-name=
"LuCI.form.ButtonValue#validate"><a href=
"LuCI.form.ButtonValue.html#validate">validate
</a></li>
456 <li data-name=
"LuCI.form.ButtonValue#width"><a href=
"LuCI.form.ButtonValue.html#width">width
</a></li>
459 <ul class=
"typedefs itemMembers">
462 <ul class=
"typedefs itemMembers">
465 <ul class=
"methods itemMembers">
467 <span class=
"subtitle">Methods
</span>
469 <li data-name=
"LuCI.form.ButtonValue#append"><a href=
"LuCI.form.ButtonValue.html#append">append
</a></li>
471 <li data-name=
"LuCI.form.ButtonValue#cbid"><a href=
"LuCI.form.ButtonValue.html#cbid">cbid
</a></li>
473 <li data-name=
"LuCI.form.ButtonValue#cfgvalue"><a href=
"LuCI.form.ButtonValue.html#cfgvalue">cfgvalue
</a></li>
475 <li data-name=
"LuCI.form.ButtonValue#depends"><a href=
"LuCI.form.ButtonValue.html#depends">depends
</a></li>
477 <li data-name=
"LuCI.form.ButtonValue#formvalue"><a href=
"LuCI.form.ButtonValue.html#formvalue">formvalue
</a></li>
479 <li data-name=
"LuCI.form.ButtonValue#getUIElement"><a href=
"LuCI.form.ButtonValue.html#getUIElement">getUIElement
</a></li>
481 <li data-name=
"LuCI.form.ButtonValue#isActive"><a href=
"LuCI.form.ButtonValue.html#isActive">isActive
</a></li>
483 <li data-name=
"LuCI.form.ButtonValue#isValid"><a href=
"LuCI.form.ButtonValue.html#isValid">isValid
</a></li>
485 <li data-name=
"LuCI.form.ButtonValue#load"><a href=
"LuCI.form.ButtonValue.html#load">load
</a></li>
487 <li data-name=
"LuCI.form.ButtonValue#parse"><a href=
"LuCI.form.ButtonValue.html#parse">parse
</a></li>
489 <li data-name=
"LuCI.form.ButtonValue#remove"><a href=
"LuCI.form.ButtonValue.html#remove">remove
</a></li>
491 <li data-name=
"LuCI.form.ButtonValue#stripTags"><a href=
"LuCI.form.ButtonValue.html#stripTags">stripTags
</a></li>
493 <li data-name=
"LuCI.form.ButtonValue#textvalue"><a href=
"LuCI.form.ButtonValue.html#textvalue">textvalue
</a></li>
495 <li data-name=
"LuCI.form.ButtonValue#titleFn"><a href=
"LuCI.form.ButtonValue.html#titleFn">titleFn
</a></li>
497 <li data-name=
"LuCI.form.ButtonValue#value"><a href=
"LuCI.form.ButtonValue.html#value">value
</a></li>
499 <li data-name=
"LuCI.form.ButtonValue#write"><a href=
"LuCI.form.ButtonValue.html#write">write
</a></li>
502 <ul class=
"events itemMembers">
507 <li class=
"item" data-name=
"LuCI.form.DummyValue">
509 <a href=
"LuCI.form.DummyValue.html">LuCI.form.DummyValue
</a>
512 <ul class=
"members itemMembers">
514 <span class=
"subtitle">Members
</span>
516 <li data-name=
"LuCI.form.DummyValue##href"><a href=
"LuCI.form.DummyValue.html#href">href
</a></li>
518 <li data-name=
"LuCI.form.DummyValue##rawhtml"><a href=
"LuCI.form.DummyValue.html#rawhtml">rawhtml
</a></li>
520 <li data-name=
"LuCI.form.DummyValue#datatype"><a href=
"LuCI.form.DummyValue.html#datatype">datatype
</a></li>
522 <li data-name=
"LuCI.form.DummyValue#default"><a href=
"LuCI.form.DummyValue.html#default">default
</a></li>
524 <li data-name=
"LuCI.form.DummyValue#editable"><a href=
"LuCI.form.DummyValue.html#editable">editable
</a></li>
526 <li data-name=
"LuCI.form.DummyValue#modalonly"><a href=
"LuCI.form.DummyValue.html#modalonly">modalonly
</a></li>
528 <li data-name=
"LuCI.form.DummyValue#onchange"><a href=
"LuCI.form.DummyValue.html#onchange">onchange
</a></li>
530 <li data-name=
"LuCI.form.DummyValue#optional"><a href=
"LuCI.form.DummyValue.html#optional">optional
</a></li>
532 <li data-name=
"LuCI.form.DummyValue#password"><a href=
"LuCI.form.DummyValue.html#password">password
</a></li>
534 <li data-name=
"LuCI.form.DummyValue#placeholder"><a href=
"LuCI.form.DummyValue.html#placeholder">placeholder
</a></li>
536 <li data-name=
"LuCI.form.DummyValue#readonly"><a href=
"LuCI.form.DummyValue.html#readonly">readonly
</a></li>
538 <li data-name=
"LuCI.form.DummyValue#rmempty"><a href=
"LuCI.form.DummyValue.html#rmempty">rmempty
</a></li>
540 <li data-name=
"LuCI.form.DummyValue#uciconfig"><a href=
"LuCI.form.DummyValue.html#uciconfig">uciconfig
</a></li>
542 <li data-name=
"LuCI.form.DummyValue#ucioption"><a href=
"LuCI.form.DummyValue.html#ucioption">ucioption
</a></li>
544 <li data-name=
"LuCI.form.DummyValue#ucisection"><a href=
"LuCI.form.DummyValue.html#ucisection">ucisection
</a></li>
546 <li data-name=
"LuCI.form.DummyValue#validate"><a href=
"LuCI.form.DummyValue.html#validate">validate
</a></li>
548 <li data-name=
"LuCI.form.DummyValue#width"><a href=
"LuCI.form.DummyValue.html#width">width
</a></li>
551 <ul class=
"typedefs itemMembers">
554 <ul class=
"typedefs itemMembers">
557 <ul class=
"methods itemMembers">
559 <span class=
"subtitle">Methods
</span>
561 <li data-name=
"LuCI.form.DummyValue#append"><a href=
"LuCI.form.DummyValue.html#append">append
</a></li>
563 <li data-name=
"LuCI.form.DummyValue#cbid"><a href=
"LuCI.form.DummyValue.html#cbid">cbid
</a></li>
565 <li data-name=
"LuCI.form.DummyValue#cfgvalue"><a href=
"LuCI.form.DummyValue.html#cfgvalue">cfgvalue
</a></li>
567 <li data-name=
"LuCI.form.DummyValue#depends"><a href=
"LuCI.form.DummyValue.html#depends">depends
</a></li>
569 <li data-name=
"LuCI.form.DummyValue#formvalue"><a href=
"LuCI.form.DummyValue.html#formvalue">formvalue
</a></li>
571 <li data-name=
"LuCI.form.DummyValue#getUIElement"><a href=
"LuCI.form.DummyValue.html#getUIElement">getUIElement
</a></li>
573 <li data-name=
"LuCI.form.DummyValue#isActive"><a href=
"LuCI.form.DummyValue.html#isActive">isActive
</a></li>
575 <li data-name=
"LuCI.form.DummyValue#isValid"><a href=
"LuCI.form.DummyValue.html#isValid">isValid
</a></li>
577 <li data-name=
"LuCI.form.DummyValue#load"><a href=
"LuCI.form.DummyValue.html#load">load
</a></li>
579 <li data-name=
"LuCI.form.DummyValue#parse"><a href=
"LuCI.form.DummyValue.html#parse">parse
</a></li>
581 <li data-name=
"LuCI.form.DummyValue#remove"><a href=
"LuCI.form.DummyValue.html#remove">remove
</a></li>
583 <li data-name=
"LuCI.form.DummyValue#stripTags"><a href=
"LuCI.form.DummyValue.html#stripTags">stripTags
</a></li>
585 <li data-name=
"LuCI.form.DummyValue#textvalue"><a href=
"LuCI.form.DummyValue.html#textvalue">textvalue
</a></li>
587 <li data-name=
"LuCI.form.DummyValue#titleFn"><a href=
"LuCI.form.DummyValue.html#titleFn">titleFn
</a></li>
589 <li data-name=
"LuCI.form.DummyValue#value"><a href=
"LuCI.form.DummyValue.html#value">value
</a></li>
591 <li data-name=
"LuCI.form.DummyValue#write"><a href=
"LuCI.form.DummyValue.html#write">write
</a></li>
594 <ul class=
"events itemMembers">
599 <li class=
"item" data-name=
"LuCI.form.DynamicList">
601 <a href=
"LuCI.form.DynamicList.html">LuCI.form.DynamicList
</a>
604 <ul class=
"members itemMembers">
606 <span class=
"subtitle">Members
</span>
608 <li data-name=
"LuCI.form.DynamicList#datatype"><a href=
"LuCI.form.DynamicList.html#datatype">datatype
</a></li>
610 <li data-name=
"LuCI.form.DynamicList#default"><a href=
"LuCI.form.DynamicList.html#default">default
</a></li>
612 <li data-name=
"LuCI.form.DynamicList#editable"><a href=
"LuCI.form.DynamicList.html#editable">editable
</a></li>
614 <li data-name=
"LuCI.form.DynamicList#modalonly"><a href=
"LuCI.form.DynamicList.html#modalonly">modalonly
</a></li>
616 <li data-name=
"LuCI.form.DynamicList#onchange"><a href=
"LuCI.form.DynamicList.html#onchange">onchange
</a></li>
618 <li data-name=
"LuCI.form.DynamicList#optional"><a href=
"LuCI.form.DynamicList.html#optional">optional
</a></li>
620 <li data-name=
"LuCI.form.DynamicList#password"><a href=
"LuCI.form.DynamicList.html#password">password
</a></li>
622 <li data-name=
"LuCI.form.DynamicList#placeholder"><a href=
"LuCI.form.DynamicList.html#placeholder">placeholder
</a></li>
624 <li data-name=
"LuCI.form.DynamicList#readonly"><a href=
"LuCI.form.DynamicList.html#readonly">readonly
</a></li>
626 <li data-name=
"LuCI.form.DynamicList#rmempty"><a href=
"LuCI.form.DynamicList.html#rmempty">rmempty
</a></li>
628 <li data-name=
"LuCI.form.DynamicList#uciconfig"><a href=
"LuCI.form.DynamicList.html#uciconfig">uciconfig
</a></li>
630 <li data-name=
"LuCI.form.DynamicList#ucioption"><a href=
"LuCI.form.DynamicList.html#ucioption">ucioption
</a></li>
632 <li data-name=
"LuCI.form.DynamicList#ucisection"><a href=
"LuCI.form.DynamicList.html#ucisection">ucisection
</a></li>
634 <li data-name=
"LuCI.form.DynamicList#validate"><a href=
"LuCI.form.DynamicList.html#validate">validate
</a></li>
636 <li data-name=
"LuCI.form.DynamicList#width"><a href=
"LuCI.form.DynamicList.html#width">width
</a></li>
639 <ul class=
"typedefs itemMembers">
642 <ul class=
"typedefs itemMembers">
645 <ul class=
"methods itemMembers">
647 <span class=
"subtitle">Methods
</span>
649 <li data-name=
"LuCI.form.DynamicList#append"><a href=
"LuCI.form.DynamicList.html#append">append
</a></li>
651 <li data-name=
"LuCI.form.DynamicList#cbid"><a href=
"LuCI.form.DynamicList.html#cbid">cbid
</a></li>
653 <li data-name=
"LuCI.form.DynamicList#cfgvalue"><a href=
"LuCI.form.DynamicList.html#cfgvalue">cfgvalue
</a></li>
655 <li data-name=
"LuCI.form.DynamicList#depends"><a href=
"LuCI.form.DynamicList.html#depends">depends
</a></li>
657 <li data-name=
"LuCI.form.DynamicList#formvalue"><a href=
"LuCI.form.DynamicList.html#formvalue">formvalue
</a></li>
659 <li data-name=
"LuCI.form.DynamicList#getUIElement"><a href=
"LuCI.form.DynamicList.html#getUIElement">getUIElement
</a></li>
661 <li data-name=
"LuCI.form.DynamicList#isActive"><a href=
"LuCI.form.DynamicList.html#isActive">isActive
</a></li>
663 <li data-name=
"LuCI.form.DynamicList#isValid"><a href=
"LuCI.form.DynamicList.html#isValid">isValid
</a></li>
665 <li data-name=
"LuCI.form.DynamicList#load"><a href=
"LuCI.form.DynamicList.html#load">load
</a></li>
667 <li data-name=
"LuCI.form.DynamicList#parse"><a href=
"LuCI.form.DynamicList.html#parse">parse
</a></li>
669 <li data-name=
"LuCI.form.DynamicList#remove"><a href=
"LuCI.form.DynamicList.html#remove">remove
</a></li>
671 <li data-name=
"LuCI.form.DynamicList#stripTags"><a href=
"LuCI.form.DynamicList.html#stripTags">stripTags
</a></li>
673 <li data-name=
"LuCI.form.DynamicList#textvalue"><a href=
"LuCI.form.DynamicList.html#textvalue">textvalue
</a></li>
675 <li data-name=
"LuCI.form.DynamicList#titleFn"><a href=
"LuCI.form.DynamicList.html#titleFn">titleFn
</a></li>
677 <li data-name=
"LuCI.form.DynamicList#value"><a href=
"LuCI.form.DynamicList.html#value">value
</a></li>
679 <li data-name=
"LuCI.form.DynamicList#write"><a href=
"LuCI.form.DynamicList.html#write">write
</a></li>
682 <ul class=
"events itemMembers">
687 <li class=
"item" data-name=
"LuCI.form.FileUpload">
689 <a href=
"LuCI.form.FileUpload.html">LuCI.form.FileUpload
</a>
692 <ul class=
"members itemMembers">
694 <span class=
"subtitle">Members
</span>
696 <li data-name=
"LuCI.form.FileUpload##enable_remove"><a href=
"LuCI.form.FileUpload.html#enable_remove">enable_remove
</a></li>
698 <li data-name=
"LuCI.form.FileUpload##enable_upload"><a href=
"LuCI.form.FileUpload.html#enable_upload">enable_upload
</a></li>
700 <li data-name=
"LuCI.form.FileUpload##root_directory"><a href=
"LuCI.form.FileUpload.html#root_directory">root_directory
</a></li>
702 <li data-name=
"LuCI.form.FileUpload##show_hidden"><a href=
"LuCI.form.FileUpload.html#show_hidden">show_hidden
</a></li>
704 <li data-name=
"LuCI.form.FileUpload#datatype"><a href=
"LuCI.form.FileUpload.html#datatype">datatype
</a></li>
706 <li data-name=
"LuCI.form.FileUpload#default"><a href=
"LuCI.form.FileUpload.html#default">default
</a></li>
708 <li data-name=
"LuCI.form.FileUpload#editable"><a href=
"LuCI.form.FileUpload.html#editable">editable
</a></li>
710 <li data-name=
"LuCI.form.FileUpload#modalonly"><a href=
"LuCI.form.FileUpload.html#modalonly">modalonly
</a></li>
712 <li data-name=
"LuCI.form.FileUpload#onchange"><a href=
"LuCI.form.FileUpload.html#onchange">onchange
</a></li>
714 <li data-name=
"LuCI.form.FileUpload#optional"><a href=
"LuCI.form.FileUpload.html#optional">optional
</a></li>
716 <li data-name=
"LuCI.form.FileUpload#password"><a href=
"LuCI.form.FileUpload.html#password">password
</a></li>
718 <li data-name=
"LuCI.form.FileUpload#placeholder"><a href=
"LuCI.form.FileUpload.html#placeholder">placeholder
</a></li>
720 <li data-name=
"LuCI.form.FileUpload#readonly"><a href=
"LuCI.form.FileUpload.html#readonly">readonly
</a></li>
722 <li data-name=
"LuCI.form.FileUpload#rmempty"><a href=
"LuCI.form.FileUpload.html#rmempty">rmempty
</a></li>
724 <li data-name=
"LuCI.form.FileUpload#uciconfig"><a href=
"LuCI.form.FileUpload.html#uciconfig">uciconfig
</a></li>
726 <li data-name=
"LuCI.form.FileUpload#ucioption"><a href=
"LuCI.form.FileUpload.html#ucioption">ucioption
</a></li>
728 <li data-name=
"LuCI.form.FileUpload#ucisection"><a href=
"LuCI.form.FileUpload.html#ucisection">ucisection
</a></li>
730 <li data-name=
"LuCI.form.FileUpload#validate"><a href=
"LuCI.form.FileUpload.html#validate">validate
</a></li>
732 <li data-name=
"LuCI.form.FileUpload#width"><a href=
"LuCI.form.FileUpload.html#width">width
</a></li>
735 <ul class=
"typedefs itemMembers">
738 <ul class=
"typedefs itemMembers">
741 <ul class=
"methods itemMembers">
743 <span class=
"subtitle">Methods
</span>
745 <li data-name=
"LuCI.form.FileUpload#append"><a href=
"LuCI.form.FileUpload.html#append">append
</a></li>
747 <li data-name=
"LuCI.form.FileUpload#cbid"><a href=
"LuCI.form.FileUpload.html#cbid">cbid
</a></li>
749 <li data-name=
"LuCI.form.FileUpload#cfgvalue"><a href=
"LuCI.form.FileUpload.html#cfgvalue">cfgvalue
</a></li>
751 <li data-name=
"LuCI.form.FileUpload#depends"><a href=
"LuCI.form.FileUpload.html#depends">depends
</a></li>
753 <li data-name=
"LuCI.form.FileUpload#formvalue"><a href=
"LuCI.form.FileUpload.html#formvalue">formvalue
</a></li>
755 <li data-name=
"LuCI.form.FileUpload#getUIElement"><a href=
"LuCI.form.FileUpload.html#getUIElement">getUIElement
</a></li>
757 <li data-name=
"LuCI.form.FileUpload#isActive"><a href=
"LuCI.form.FileUpload.html#isActive">isActive
</a></li>
759 <li data-name=
"LuCI.form.FileUpload#isValid"><a href=
"LuCI.form.FileUpload.html#isValid">isValid
</a></li>
761 <li data-name=
"LuCI.form.FileUpload#load"><a href=
"LuCI.form.FileUpload.html#load">load
</a></li>
763 <li data-name=
"LuCI.form.FileUpload#parse"><a href=
"LuCI.form.FileUpload.html#parse">parse
</a></li>
765 <li data-name=
"LuCI.form.FileUpload#remove"><a href=
"LuCI.form.FileUpload.html#remove">remove
</a></li>
767 <li data-name=
"LuCI.form.FileUpload#stripTags"><a href=
"LuCI.form.FileUpload.html#stripTags">stripTags
</a></li>
769 <li data-name=
"LuCI.form.FileUpload#textvalue"><a href=
"LuCI.form.FileUpload.html#textvalue">textvalue
</a></li>
771 <li data-name=
"LuCI.form.FileUpload#titleFn"><a href=
"LuCI.form.FileUpload.html#titleFn">titleFn
</a></li>
773 <li data-name=
"LuCI.form.FileUpload#value"><a href=
"LuCI.form.FileUpload.html#value">value
</a></li>
775 <li data-name=
"LuCI.form.FileUpload#write"><a href=
"LuCI.form.FileUpload.html#write">write
</a></li>
778 <ul class=
"events itemMembers">
783 <li class=
"item" data-name=
"LuCI.form.FlagValue">
785 <a href=
"LuCI.form.FlagValue.html">LuCI.form.FlagValue
</a>
788 <ul class=
"members itemMembers">
790 <span class=
"subtitle">Members
</span>
792 <li data-name=
"LuCI.form.FlagValue##disabled"><a href=
"LuCI.form.FlagValue.html#disabled">disabled
</a></li>
794 <li data-name=
"LuCI.form.FlagValue##enabled"><a href=
"LuCI.form.FlagValue.html#enabled">enabled
</a></li>
796 <li data-name=
"LuCI.form.FlagValue#datatype"><a href=
"LuCI.form.FlagValue.html#datatype">datatype
</a></li>
798 <li data-name=
"LuCI.form.FlagValue#default"><a href=
"LuCI.form.FlagValue.html#default">default
</a></li>
800 <li data-name=
"LuCI.form.FlagValue#editable"><a href=
"LuCI.form.FlagValue.html#editable">editable
</a></li>
802 <li data-name=
"LuCI.form.FlagValue#modalonly"><a href=
"LuCI.form.FlagValue.html#modalonly">modalonly
</a></li>
804 <li data-name=
"LuCI.form.FlagValue#onchange"><a href=
"LuCI.form.FlagValue.html#onchange">onchange
</a></li>
806 <li data-name=
"LuCI.form.FlagValue#optional"><a href=
"LuCI.form.FlagValue.html#optional">optional
</a></li>
808 <li data-name=
"LuCI.form.FlagValue#password"><a href=
"LuCI.form.FlagValue.html#password">password
</a></li>
810 <li data-name=
"LuCI.form.FlagValue#placeholder"><a href=
"LuCI.form.FlagValue.html#placeholder">placeholder
</a></li>
812 <li data-name=
"LuCI.form.FlagValue#readonly"><a href=
"LuCI.form.FlagValue.html#readonly">readonly
</a></li>
814 <li data-name=
"LuCI.form.FlagValue#rmempty"><a href=
"LuCI.form.FlagValue.html#rmempty">rmempty
</a></li>
816 <li data-name=
"LuCI.form.FlagValue#uciconfig"><a href=
"LuCI.form.FlagValue.html#uciconfig">uciconfig
</a></li>
818 <li data-name=
"LuCI.form.FlagValue#ucioption"><a href=
"LuCI.form.FlagValue.html#ucioption">ucioption
</a></li>
820 <li data-name=
"LuCI.form.FlagValue#ucisection"><a href=
"LuCI.form.FlagValue.html#ucisection">ucisection
</a></li>
822 <li data-name=
"LuCI.form.FlagValue#validate"><a href=
"LuCI.form.FlagValue.html#validate">validate
</a></li>
824 <li data-name=
"LuCI.form.FlagValue#width"><a href=
"LuCI.form.FlagValue.html#width">width
</a></li>
827 <ul class=
"typedefs itemMembers">
830 <ul class=
"typedefs itemMembers">
833 <ul class=
"methods itemMembers">
835 <span class=
"subtitle">Methods
</span>
837 <li data-name=
"LuCI.form.FlagValue#append"><a href=
"LuCI.form.FlagValue.html#append">append
</a></li>
839 <li data-name=
"LuCI.form.FlagValue#cbid"><a href=
"LuCI.form.FlagValue.html#cbid">cbid
</a></li>
841 <li data-name=
"LuCI.form.FlagValue#cfgvalue"><a href=
"LuCI.form.FlagValue.html#cfgvalue">cfgvalue
</a></li>
843 <li data-name=
"LuCI.form.FlagValue#depends"><a href=
"LuCI.form.FlagValue.html#depends">depends
</a></li>
845 <li data-name=
"LuCI.form.FlagValue#formvalue"><a href=
"LuCI.form.FlagValue.html#formvalue">formvalue
</a></li>
847 <li data-name=
"LuCI.form.FlagValue#getUIElement"><a href=
"LuCI.form.FlagValue.html#getUIElement">getUIElement
</a></li>
849 <li data-name=
"LuCI.form.FlagValue#isActive"><a href=
"LuCI.form.FlagValue.html#isActive">isActive
</a></li>
851 <li data-name=
"LuCI.form.FlagValue#isValid"><a href=
"LuCI.form.FlagValue.html#isValid">isValid
</a></li>
853 <li data-name=
"LuCI.form.FlagValue#load"><a href=
"LuCI.form.FlagValue.html#load">load
</a></li>
855 <li data-name=
"LuCI.form.FlagValue#parse"><a href=
"LuCI.form.FlagValue.html#parse">parse
</a></li>
857 <li data-name=
"LuCI.form.FlagValue#remove"><a href=
"LuCI.form.FlagValue.html#remove">remove
</a></li>
859 <li data-name=
"LuCI.form.FlagValue#stripTags"><a href=
"LuCI.form.FlagValue.html#stripTags">stripTags
</a></li>
861 <li data-name=
"LuCI.form.FlagValue#textvalue"><a href=
"LuCI.form.FlagValue.html#textvalue">textvalue
</a></li>
863 <li data-name=
"LuCI.form.FlagValue#titleFn"><a href=
"LuCI.form.FlagValue.html#titleFn">titleFn
</a></li>
865 <li data-name=
"LuCI.form.FlagValue#value"><a href=
"LuCI.form.FlagValue.html#value">value
</a></li>
867 <li data-name=
"LuCI.form.FlagValue#write"><a href=
"LuCI.form.FlagValue.html#write">write
</a></li>
870 <ul class=
"events itemMembers">
875 <li class=
"item" data-name=
"LuCI.form.GridSection">
877 <a href=
"LuCI.form.GridSection.html">LuCI.form.GridSection
</a>
880 <ul class=
"members itemMembers">
882 <span class=
"subtitle">Members
</span>
884 <li data-name=
"LuCI.form.GridSection#addbtntitle"><a href=
"LuCI.form.GridSection.html#addbtntitle">addbtntitle
</a></li>
886 <li data-name=
"LuCI.form.GridSection#addremove"><a href=
"LuCI.form.GridSection.html#addremove">addremove
</a></li>
888 <li data-name=
"LuCI.form.GridSection#anonymous"><a href=
"LuCI.form.GridSection.html#anonymous">anonymous
</a></li>
890 <li data-name=
"LuCI.form.GridSection#extedit"><a href=
"LuCI.form.GridSection.html#extedit">extedit
</a></li>
892 <li data-name=
"LuCI.form.GridSection#max_cols"><a href=
"LuCI.form.GridSection.html#max_cols">max_cols
</a></li>
894 <li data-name=
"LuCI.form.GridSection#modaltitle"><a href=
"LuCI.form.GridSection.html#modaltitle">modaltitle
</a></li>
896 <li data-name=
"LuCI.form.GridSection#nodescriptions"><a href=
"LuCI.form.GridSection.html#nodescriptions">nodescriptions
</a></li>
898 <li data-name=
"LuCI.form.GridSection#parentoption"><a href=
"LuCI.form.GridSection.html#parentoption">parentoption
</a></li>
900 <li data-name=
"LuCI.form.GridSection#rowcolors"><a href=
"LuCI.form.GridSection.html#rowcolors">rowcolors
</a></li>
902 <li data-name=
"LuCI.form.GridSection#sectiontitle"><a href=
"LuCI.form.GridSection.html#sectiontitle">sectiontitle
</a></li>
904 <li data-name=
"LuCI.form.GridSection#sortable"><a href=
"LuCI.form.GridSection.html#sortable">sortable
</a></li>
906 <li data-name=
"LuCI.form.GridSection#tabbed"><a href=
"LuCI.form.GridSection.html#tabbed">tabbed
</a></li>
908 <li data-name=
"LuCI.form.GridSection#uciconfig"><a href=
"LuCI.form.GridSection.html#uciconfig">uciconfig
</a></li>
911 <ul class=
"typedefs itemMembers">
914 <ul class=
"typedefs itemMembers">
917 <ul class=
"methods itemMembers">
919 <span class=
"subtitle">Methods
</span>
921 <li data-name=
"LuCI.form.GridSection#addModalOptions"><a href=
"LuCI.form.GridSection.html#addModalOptions">addModalOptions
</a></li>
923 <li data-name=
"LuCI.form.GridSection#append"><a href=
"LuCI.form.GridSection.html#append">append
</a></li>
925 <li data-name=
"LuCI.form.GridSection#cfgvalue"><a href=
"LuCI.form.GridSection.html#cfgvalue">cfgvalue
</a></li>
927 <li data-name=
"LuCI.form.GridSection#filter"><a href=
"LuCI.form.GridSection.html#filter">filter
</a></li>
929 <li data-name=
"LuCI.form.GridSection#formvalue"><a href=
"LuCI.form.GridSection.html#formvalue">formvalue
</a></li>
931 <li data-name=
"LuCI.form.GridSection#getOption"><a href=
"LuCI.form.GridSection.html#getOption">getOption
</a></li>
933 <li data-name=
"LuCI.form.GridSection#getUIElement"><a href=
"LuCI.form.GridSection.html#getUIElement">getUIElement
</a></li>
935 <li data-name=
"LuCI.form.GridSection#load"><a href=
"LuCI.form.GridSection.html#load">load
</a></li>
937 <li data-name=
"LuCI.form.GridSection#option"><a href=
"LuCI.form.GridSection.html#option">option
</a></li>
939 <li data-name=
"LuCI.form.GridSection#parse"><a href=
"LuCI.form.GridSection.html#parse">parse
</a></li>
941 <li data-name=
"LuCI.form.GridSection#stripTags"><a href=
"LuCI.form.GridSection.html#stripTags">stripTags
</a></li>
943 <li data-name=
"LuCI.form.GridSection#tab"><a href=
"LuCI.form.GridSection.html#tab">tab
</a></li>
945 <li data-name=
"LuCI.form.GridSection#taboption"><a href=
"LuCI.form.GridSection.html#taboption">taboption
</a></li>
947 <li data-name=
"LuCI.form.GridSection#titleFn"><a href=
"LuCI.form.GridSection.html#titleFn">titleFn
</a></li>
950 <ul class=
"events itemMembers">
955 <li class=
"item" data-name=
"LuCI.form.HiddenValue">
957 <a href=
"LuCI.form.HiddenValue.html">LuCI.form.HiddenValue
</a>
960 <ul class=
"members itemMembers">
962 <span class=
"subtitle">Members
</span>
964 <li data-name=
"LuCI.form.HiddenValue#datatype"><a href=
"LuCI.form.HiddenValue.html#datatype">datatype
</a></li>
966 <li data-name=
"LuCI.form.HiddenValue#default"><a href=
"LuCI.form.HiddenValue.html#default">default
</a></li>
968 <li data-name=
"LuCI.form.HiddenValue#editable"><a href=
"LuCI.form.HiddenValue.html#editable">editable
</a></li>
970 <li data-name=
"LuCI.form.HiddenValue#modalonly"><a href=
"LuCI.form.HiddenValue.html#modalonly">modalonly
</a></li>
972 <li data-name=
"LuCI.form.HiddenValue#onchange"><a href=
"LuCI.form.HiddenValue.html#onchange">onchange
</a></li>
974 <li data-name=
"LuCI.form.HiddenValue#optional"><a href=
"LuCI.form.HiddenValue.html#optional">optional
</a></li>
976 <li data-name=
"LuCI.form.HiddenValue#password"><a href=
"LuCI.form.HiddenValue.html#password">password
</a></li>
978 <li data-name=
"LuCI.form.HiddenValue#placeholder"><a href=
"LuCI.form.HiddenValue.html#placeholder">placeholder
</a></li>
980 <li data-name=
"LuCI.form.HiddenValue#readonly"><a href=
"LuCI.form.HiddenValue.html#readonly">readonly
</a></li>
982 <li data-name=
"LuCI.form.HiddenValue#rmempty"><a href=
"LuCI.form.HiddenValue.html#rmempty">rmempty
</a></li>
984 <li data-name=
"LuCI.form.HiddenValue#uciconfig"><a href=
"LuCI.form.HiddenValue.html#uciconfig">uciconfig
</a></li>
986 <li data-name=
"LuCI.form.HiddenValue#ucioption"><a href=
"LuCI.form.HiddenValue.html#ucioption">ucioption
</a></li>
988 <li data-name=
"LuCI.form.HiddenValue#ucisection"><a href=
"LuCI.form.HiddenValue.html#ucisection">ucisection
</a></li>
990 <li data-name=
"LuCI.form.HiddenValue#validate"><a href=
"LuCI.form.HiddenValue.html#validate">validate
</a></li>
992 <li data-name=
"LuCI.form.HiddenValue#width"><a href=
"LuCI.form.HiddenValue.html#width">width
</a></li>
995 <ul class=
"typedefs itemMembers">
998 <ul class=
"typedefs itemMembers">
1001 <ul class=
"methods itemMembers">
1003 <span class=
"subtitle">Methods
</span>
1005 <li data-name=
"LuCI.form.HiddenValue#append"><a href=
"LuCI.form.HiddenValue.html#append">append
</a></li>
1007 <li data-name=
"LuCI.form.HiddenValue#cbid"><a href=
"LuCI.form.HiddenValue.html#cbid">cbid
</a></li>
1009 <li data-name=
"LuCI.form.HiddenValue#cfgvalue"><a href=
"LuCI.form.HiddenValue.html#cfgvalue">cfgvalue
</a></li>
1011 <li data-name=
"LuCI.form.HiddenValue#depends"><a href=
"LuCI.form.HiddenValue.html#depends">depends
</a></li>
1013 <li data-name=
"LuCI.form.HiddenValue#formvalue"><a href=
"LuCI.form.HiddenValue.html#formvalue">formvalue
</a></li>
1015 <li data-name=
"LuCI.form.HiddenValue#getUIElement"><a href=
"LuCI.form.HiddenValue.html#getUIElement">getUIElement
</a></li>
1017 <li data-name=
"LuCI.form.HiddenValue#isActive"><a href=
"LuCI.form.HiddenValue.html#isActive">isActive
</a></li>
1019 <li data-name=
"LuCI.form.HiddenValue#isValid"><a href=
"LuCI.form.HiddenValue.html#isValid">isValid
</a></li>
1021 <li data-name=
"LuCI.form.HiddenValue#load"><a href=
"LuCI.form.HiddenValue.html#load">load
</a></li>
1023 <li data-name=
"LuCI.form.HiddenValue#parse"><a href=
"LuCI.form.HiddenValue.html#parse">parse
</a></li>
1025 <li data-name=
"LuCI.form.HiddenValue#remove"><a href=
"LuCI.form.HiddenValue.html#remove">remove
</a></li>
1027 <li data-name=
"LuCI.form.HiddenValue#stripTags"><a href=
"LuCI.form.HiddenValue.html#stripTags">stripTags
</a></li>
1029 <li data-name=
"LuCI.form.HiddenValue#textvalue"><a href=
"LuCI.form.HiddenValue.html#textvalue">textvalue
</a></li>
1031 <li data-name=
"LuCI.form.HiddenValue#titleFn"><a href=
"LuCI.form.HiddenValue.html#titleFn">titleFn
</a></li>
1033 <li data-name=
"LuCI.form.HiddenValue#value"><a href=
"LuCI.form.HiddenValue.html#value">value
</a></li>
1035 <li data-name=
"LuCI.form.HiddenValue#write"><a href=
"LuCI.form.HiddenValue.html#write">write
</a></li>
1038 <ul class=
"events itemMembers">
1043 <li class=
"item" data-name=
"LuCI.form.JSONMap">
1044 <span class=
"title">
1045 <a href=
"LuCI.form.JSONMap.html">LuCI.form.JSONMap
</a>
1048 <ul class=
"members itemMembers">
1050 <span class=
"subtitle">Members
</span>
1052 <li data-name=
"LuCI.form.JSONMap#readonly"><a href=
"LuCI.form.JSONMap.html#readonly">readonly
</a></li>
1055 <ul class=
"typedefs itemMembers">
1058 <ul class=
"typedefs itemMembers">
1061 <ul class=
"methods itemMembers">
1063 <span class=
"subtitle">Methods
</span>
1065 <li data-name=
"LuCI.form.JSONMap#append"><a href=
"LuCI.form.JSONMap.html#append">append
</a></li>
1067 <li data-name=
"LuCI.form.JSONMap#chain"><a href=
"LuCI.form.JSONMap.html#chain">chain
</a></li>
1069 <li data-name=
"LuCI.form.JSONMap#findElement"><a href=
"LuCI.form.JSONMap.html#findElement">findElement
</a></li>
1071 <li data-name=
"LuCI.form.JSONMap#findElements"><a href=
"LuCI.form.JSONMap.html#findElements">findElements
</a></li>
1073 <li data-name=
"LuCI.form.JSONMap#load"><a href=
"LuCI.form.JSONMap.html#load">load
</a></li>
1075 <li data-name=
"LuCI.form.JSONMap#lookupOption"><a href=
"LuCI.form.JSONMap.html#lookupOption">lookupOption
</a></li>
1077 <li data-name=
"LuCI.form.JSONMap#parse"><a href=
"LuCI.form.JSONMap.html#parse">parse
</a></li>
1079 <li data-name=
"LuCI.form.JSONMap#render"><a href=
"LuCI.form.JSONMap.html#render">render
</a></li>
1081 <li data-name=
"LuCI.form.JSONMap#reset"><a href=
"LuCI.form.JSONMap.html#reset">reset
</a></li>
1083 <li data-name=
"LuCI.form.JSONMap#save"><a href=
"LuCI.form.JSONMap.html#save">save
</a></li>
1085 <li data-name=
"LuCI.form.JSONMap#section"><a href=
"LuCI.form.JSONMap.html#section">section
</a></li>
1087 <li data-name=
"LuCI.form.JSONMap#stripTags"><a href=
"LuCI.form.JSONMap.html#stripTags">stripTags
</a></li>
1089 <li data-name=
"LuCI.form.JSONMap#titleFn"><a href=
"LuCI.form.JSONMap.html#titleFn">titleFn
</a></li>
1092 <ul class=
"events itemMembers">
1097 <li class=
"item" data-name=
"LuCI.form.ListValue">
1098 <span class=
"title">
1099 <a href=
"LuCI.form.ListValue.html">LuCI.form.ListValue
</a>
1102 <ul class=
"members itemMembers">
1104 <span class=
"subtitle">Members
</span>
1106 <li data-name=
"LuCI.form.ListValue##orientation"><a href=
"LuCI.form.ListValue.html#orientation">orientation
</a></li>
1108 <li data-name=
"LuCI.form.ListValue##size"><a href=
"LuCI.form.ListValue.html#size">size
</a></li>
1110 <li data-name=
"LuCI.form.ListValue##widget"><a href=
"LuCI.form.ListValue.html#widget">widget
</a></li>
1112 <li data-name=
"LuCI.form.ListValue#datatype"><a href=
"LuCI.form.ListValue.html#datatype">datatype
</a></li>
1114 <li data-name=
"LuCI.form.ListValue#default"><a href=
"LuCI.form.ListValue.html#default">default
</a></li>
1116 <li data-name=
"LuCI.form.ListValue#editable"><a href=
"LuCI.form.ListValue.html#editable">editable
</a></li>
1118 <li data-name=
"LuCI.form.ListValue#modalonly"><a href=
"LuCI.form.ListValue.html#modalonly">modalonly
</a></li>
1120 <li data-name=
"LuCI.form.ListValue#onchange"><a href=
"LuCI.form.ListValue.html#onchange">onchange
</a></li>
1122 <li data-name=
"LuCI.form.ListValue#optional"><a href=
"LuCI.form.ListValue.html#optional">optional
</a></li>
1124 <li data-name=
"LuCI.form.ListValue#password"><a href=
"LuCI.form.ListValue.html#password">password
</a></li>
1126 <li data-name=
"LuCI.form.ListValue#placeholder"><a href=
"LuCI.form.ListValue.html#placeholder">placeholder
</a></li>
1128 <li data-name=
"LuCI.form.ListValue#readonly"><a href=
"LuCI.form.ListValue.html#readonly">readonly
</a></li>
1130 <li data-name=
"LuCI.form.ListValue#rmempty"><a href=
"LuCI.form.ListValue.html#rmempty">rmempty
</a></li>
1132 <li data-name=
"LuCI.form.ListValue#uciconfig"><a href=
"LuCI.form.ListValue.html#uciconfig">uciconfig
</a></li>
1134 <li data-name=
"LuCI.form.ListValue#ucioption"><a href=
"LuCI.form.ListValue.html#ucioption">ucioption
</a></li>
1136 <li data-name=
"LuCI.form.ListValue#ucisection"><a href=
"LuCI.form.ListValue.html#ucisection">ucisection
</a></li>
1138 <li data-name=
"LuCI.form.ListValue#validate"><a href=
"LuCI.form.ListValue.html#validate">validate
</a></li>
1140 <li data-name=
"LuCI.form.ListValue#width"><a href=
"LuCI.form.ListValue.html#width">width
</a></li>
1143 <ul class=
"typedefs itemMembers">
1146 <ul class=
"typedefs itemMembers">
1149 <ul class=
"methods itemMembers">
1151 <span class=
"subtitle">Methods
</span>
1153 <li data-name=
"LuCI.form.ListValue#append"><a href=
"LuCI.form.ListValue.html#append">append
</a></li>
1155 <li data-name=
"LuCI.form.ListValue#cbid"><a href=
"LuCI.form.ListValue.html#cbid">cbid
</a></li>
1157 <li data-name=
"LuCI.form.ListValue#cfgvalue"><a href=
"LuCI.form.ListValue.html#cfgvalue">cfgvalue
</a></li>
1159 <li data-name=
"LuCI.form.ListValue#depends"><a href=
"LuCI.form.ListValue.html#depends">depends
</a></li>
1161 <li data-name=
"LuCI.form.ListValue#formvalue"><a href=
"LuCI.form.ListValue.html#formvalue">formvalue
</a></li>
1163 <li data-name=
"LuCI.form.ListValue#getUIElement"><a href=
"LuCI.form.ListValue.html#getUIElement">getUIElement
</a></li>
1165 <li data-name=
"LuCI.form.ListValue#isActive"><a href=
"LuCI.form.ListValue.html#isActive">isActive
</a></li>
1167 <li data-name=
"LuCI.form.ListValue#isValid"><a href=
"LuCI.form.ListValue.html#isValid">isValid
</a></li>
1169 <li data-name=
"LuCI.form.ListValue#load"><a href=
"LuCI.form.ListValue.html#load">load
</a></li>
1171 <li data-name=
"LuCI.form.ListValue#parse"><a href=
"LuCI.form.ListValue.html#parse">parse
</a></li>
1173 <li data-name=
"LuCI.form.ListValue#remove"><a href=
"LuCI.form.ListValue.html#remove">remove
</a></li>
1175 <li data-name=
"LuCI.form.ListValue#stripTags"><a href=
"LuCI.form.ListValue.html#stripTags">stripTags
</a></li>
1177 <li data-name=
"LuCI.form.ListValue#textvalue"><a href=
"LuCI.form.ListValue.html#textvalue">textvalue
</a></li>
1179 <li data-name=
"LuCI.form.ListValue#titleFn"><a href=
"LuCI.form.ListValue.html#titleFn">titleFn
</a></li>
1181 <li data-name=
"LuCI.form.ListValue#value"><a href=
"LuCI.form.ListValue.html#value">value
</a></li>
1183 <li data-name=
"LuCI.form.ListValue#write"><a href=
"LuCI.form.ListValue.html#write">write
</a></li>
1186 <ul class=
"events itemMembers">
1191 <li class=
"item" data-name=
"LuCI.form.Map">
1192 <span class=
"title">
1193 <a href=
"LuCI.form.Map.html">LuCI.form.Map
</a>
1196 <ul class=
"members itemMembers">
1198 <span class=
"subtitle">Members
</span>
1200 <li data-name=
"LuCI.form.Map##readonly"><a href=
"LuCI.form.Map.html#readonly">readonly
</a></li>
1203 <ul class=
"typedefs itemMembers">
1206 <ul class=
"typedefs itemMembers">
1209 <ul class=
"methods itemMembers">
1211 <span class=
"subtitle">Methods
</span>
1213 <li data-name=
"LuCI.form.Map#append"><a href=
"LuCI.form.Map.html#append">append
</a></li>
1215 <li data-name=
"LuCI.form.Map#chain"><a href=
"LuCI.form.Map.html#chain">chain
</a></li>
1217 <li data-name=
"LuCI.form.Map#findElement"><a href=
"LuCI.form.Map.html#findElement">findElement
</a></li>
1219 <li data-name=
"LuCI.form.Map#findElements"><a href=
"LuCI.form.Map.html#findElements">findElements
</a></li>
1221 <li data-name=
"LuCI.form.Map#load"><a href=
"LuCI.form.Map.html#load">load
</a></li>
1223 <li data-name=
"LuCI.form.Map#lookupOption"><a href=
"LuCI.form.Map.html#lookupOption">lookupOption
</a></li>
1225 <li data-name=
"LuCI.form.Map#parse"><a href=
"LuCI.form.Map.html#parse">parse
</a></li>
1227 <li data-name=
"LuCI.form.Map#render"><a href=
"LuCI.form.Map.html#render">render
</a></li>
1229 <li data-name=
"LuCI.form.Map#reset"><a href=
"LuCI.form.Map.html#reset">reset
</a></li>
1231 <li data-name=
"LuCI.form.Map#save"><a href=
"LuCI.form.Map.html#save">save
</a></li>
1233 <li data-name=
"LuCI.form.Map#section"><a href=
"LuCI.form.Map.html#section">section
</a></li>
1235 <li data-name=
"LuCI.form.Map#stripTags"><a href=
"LuCI.form.Map.html#stripTags">stripTags
</a></li>
1237 <li data-name=
"LuCI.form.Map#titleFn"><a href=
"LuCI.form.Map.html#titleFn">titleFn
</a></li>
1240 <ul class=
"events itemMembers">
1245 <li class=
"item" data-name=
"LuCI.form.MultiValue">
1246 <span class=
"title">
1247 <a href=
"LuCI.form.MultiValue.html">LuCI.form.MultiValue
</a>
1250 <ul class=
"members itemMembers">
1252 <span class=
"subtitle">Members
</span>
1254 <li data-name=
"LuCI.form.MultiValue##display_size"><a href=
"LuCI.form.MultiValue.html#display_size">display_size
</a></li>
1256 <li data-name=
"LuCI.form.MultiValue##dropdown_size"><a href=
"LuCI.form.MultiValue.html#dropdown_size">dropdown_size
</a></li>
1258 <li data-name=
"LuCI.form.MultiValue#datatype"><a href=
"LuCI.form.MultiValue.html#datatype">datatype
</a></li>
1260 <li data-name=
"LuCI.form.MultiValue#default"><a href=
"LuCI.form.MultiValue.html#default">default
</a></li>
1262 <li data-name=
"LuCI.form.MultiValue#editable"><a href=
"LuCI.form.MultiValue.html#editable">editable
</a></li>
1264 <li data-name=
"LuCI.form.MultiValue#modalonly"><a href=
"LuCI.form.MultiValue.html#modalonly">modalonly
</a></li>
1266 <li data-name=
"LuCI.form.MultiValue#onchange"><a href=
"LuCI.form.MultiValue.html#onchange">onchange
</a></li>
1268 <li data-name=
"LuCI.form.MultiValue#optional"><a href=
"LuCI.form.MultiValue.html#optional">optional
</a></li>
1270 <li data-name=
"LuCI.form.MultiValue#password"><a href=
"LuCI.form.MultiValue.html#password">password
</a></li>
1272 <li data-name=
"LuCI.form.MultiValue#placeholder"><a href=
"LuCI.form.MultiValue.html#placeholder">placeholder
</a></li>
1274 <li data-name=
"LuCI.form.MultiValue#readonly"><a href=
"LuCI.form.MultiValue.html#readonly">readonly
</a></li>
1276 <li data-name=
"LuCI.form.MultiValue#rmempty"><a href=
"LuCI.form.MultiValue.html#rmempty">rmempty
</a></li>
1278 <li data-name=
"LuCI.form.MultiValue#uciconfig"><a href=
"LuCI.form.MultiValue.html#uciconfig">uciconfig
</a></li>
1280 <li data-name=
"LuCI.form.MultiValue#ucioption"><a href=
"LuCI.form.MultiValue.html#ucioption">ucioption
</a></li>
1282 <li data-name=
"LuCI.form.MultiValue#ucisection"><a href=
"LuCI.form.MultiValue.html#ucisection">ucisection
</a></li>
1284 <li data-name=
"LuCI.form.MultiValue#validate"><a href=
"LuCI.form.MultiValue.html#validate">validate
</a></li>
1286 <li data-name=
"LuCI.form.MultiValue#width"><a href=
"LuCI.form.MultiValue.html#width">width
</a></li>
1289 <ul class=
"typedefs itemMembers">
1292 <ul class=
"typedefs itemMembers">
1295 <ul class=
"methods itemMembers">
1297 <span class=
"subtitle">Methods
</span>
1299 <li data-name=
"LuCI.form.MultiValue#append"><a href=
"LuCI.form.MultiValue.html#append">append
</a></li>
1301 <li data-name=
"LuCI.form.MultiValue#cbid"><a href=
"LuCI.form.MultiValue.html#cbid">cbid
</a></li>
1303 <li data-name=
"LuCI.form.MultiValue#cfgvalue"><a href=
"LuCI.form.MultiValue.html#cfgvalue">cfgvalue
</a></li>
1305 <li data-name=
"LuCI.form.MultiValue#depends"><a href=
"LuCI.form.MultiValue.html#depends">depends
</a></li>
1307 <li data-name=
"LuCI.form.MultiValue#formvalue"><a href=
"LuCI.form.MultiValue.html#formvalue">formvalue
</a></li>
1309 <li data-name=
"LuCI.form.MultiValue#getUIElement"><a href=
"LuCI.form.MultiValue.html#getUIElement">getUIElement
</a></li>
1311 <li data-name=
"LuCI.form.MultiValue#isActive"><a href=
"LuCI.form.MultiValue.html#isActive">isActive
</a></li>
1313 <li data-name=
"LuCI.form.MultiValue#isValid"><a href=
"LuCI.form.MultiValue.html#isValid">isValid
</a></li>
1315 <li data-name=
"LuCI.form.MultiValue#load"><a href=
"LuCI.form.MultiValue.html#load">load
</a></li>
1317 <li data-name=
"LuCI.form.MultiValue#parse"><a href=
"LuCI.form.MultiValue.html#parse">parse
</a></li>
1319 <li data-name=
"LuCI.form.MultiValue#remove"><a href=
"LuCI.form.MultiValue.html#remove">remove
</a></li>
1321 <li data-name=
"LuCI.form.MultiValue#stripTags"><a href=
"LuCI.form.MultiValue.html#stripTags">stripTags
</a></li>
1323 <li data-name=
"LuCI.form.MultiValue#textvalue"><a href=
"LuCI.form.MultiValue.html#textvalue">textvalue
</a></li>
1325 <li data-name=
"LuCI.form.MultiValue#titleFn"><a href=
"LuCI.form.MultiValue.html#titleFn">titleFn
</a></li>
1327 <li data-name=
"LuCI.form.MultiValue#value"><a href=
"LuCI.form.MultiValue.html#value">value
</a></li>
1329 <li data-name=
"LuCI.form.MultiValue#write"><a href=
"LuCI.form.MultiValue.html#write">write
</a></li>
1332 <ul class=
"events itemMembers">
1337 <li class=
"item" data-name=
"LuCI.form.NamedSection">
1338 <span class=
"title">
1339 <a href=
"LuCI.form.NamedSection.html">LuCI.form.NamedSection
</a>
1342 <ul class=
"members itemMembers">
1344 <span class=
"subtitle">Members
</span>
1346 <li data-name=
"LuCI.form.NamedSection##addremove"><a href=
"LuCI.form.NamedSection.html#addremove">addremove
</a></li>
1348 <li data-name=
"LuCI.form.NamedSection##uciconfig"><a href=
"LuCI.form.NamedSection.html#uciconfig">uciconfig
</a></li>
1350 <li data-name=
"LuCI.form.NamedSection#parentoption"><a href=
"LuCI.form.NamedSection.html#parentoption">parentoption
</a></li>
1353 <ul class=
"typedefs itemMembers">
1356 <ul class=
"typedefs itemMembers">
1359 <ul class=
"methods itemMembers">
1361 <span class=
"subtitle">Methods
</span>
1363 <li data-name=
"LuCI.form.NamedSection#append"><a href=
"LuCI.form.NamedSection.html#append">append
</a></li>
1365 <li data-name=
"LuCI.form.NamedSection#cfgsections"><a href=
"LuCI.form.NamedSection.html#cfgsections">cfgsections
</a></li>
1367 <li data-name=
"LuCI.form.NamedSection#cfgvalue"><a href=
"LuCI.form.NamedSection.html#cfgvalue">cfgvalue
</a></li>
1369 <li data-name=
"LuCI.form.NamedSection#filter"><a href=
"LuCI.form.NamedSection.html#filter">filter
</a></li>
1371 <li data-name=
"LuCI.form.NamedSection#formvalue"><a href=
"LuCI.form.NamedSection.html#formvalue">formvalue
</a></li>
1373 <li data-name=
"LuCI.form.NamedSection#getOption"><a href=
"LuCI.form.NamedSection.html#getOption">getOption
</a></li>
1375 <li data-name=
"LuCI.form.NamedSection#getUIElement"><a href=
"LuCI.form.NamedSection.html#getUIElement">getUIElement
</a></li>
1377 <li data-name=
"LuCI.form.NamedSection#load"><a href=
"LuCI.form.NamedSection.html#load">load
</a></li>
1379 <li data-name=
"LuCI.form.NamedSection#option"><a href=
"LuCI.form.NamedSection.html#option">option
</a></li>
1381 <li data-name=
"LuCI.form.NamedSection#parse"><a href=
"LuCI.form.NamedSection.html#parse">parse
</a></li>
1383 <li data-name=
"LuCI.form.NamedSection#render"><a href=
"LuCI.form.NamedSection.html#render">render
</a></li>
1385 <li data-name=
"LuCI.form.NamedSection#stripTags"><a href=
"LuCI.form.NamedSection.html#stripTags">stripTags
</a></li>
1387 <li data-name=
"LuCI.form.NamedSection#tab"><a href=
"LuCI.form.NamedSection.html#tab">tab
</a></li>
1389 <li data-name=
"LuCI.form.NamedSection#taboption"><a href=
"LuCI.form.NamedSection.html#taboption">taboption
</a></li>
1391 <li data-name=
"LuCI.form.NamedSection#titleFn"><a href=
"LuCI.form.NamedSection.html#titleFn">titleFn
</a></li>
1394 <ul class=
"events itemMembers">
1399 <li class=
"item" data-name=
"LuCI.form.SectionValue">
1400 <span class=
"title">
1401 <a href=
"LuCI.form.SectionValue.html">LuCI.form.SectionValue
</a>
1404 <ul class=
"members itemMembers">
1406 <span class=
"subtitle">Members
</span>
1408 <li data-name=
"LuCI.form.SectionValue##subsection"><a href=
"LuCI.form.SectionValue.html#subsection">subsection
</a></li>
1410 <li data-name=
"LuCI.form.SectionValue#datatype"><a href=
"LuCI.form.SectionValue.html#datatype">datatype
</a></li>
1412 <li data-name=
"LuCI.form.SectionValue#default"><a href=
"LuCI.form.SectionValue.html#default">default
</a></li>
1414 <li data-name=
"LuCI.form.SectionValue#editable"><a href=
"LuCI.form.SectionValue.html#editable">editable
</a></li>
1416 <li data-name=
"LuCI.form.SectionValue#modalonly"><a href=
"LuCI.form.SectionValue.html#modalonly">modalonly
</a></li>
1418 <li data-name=
"LuCI.form.SectionValue#onchange"><a href=
"LuCI.form.SectionValue.html#onchange">onchange
</a></li>
1420 <li data-name=
"LuCI.form.SectionValue#optional"><a href=
"LuCI.form.SectionValue.html#optional">optional
</a></li>
1422 <li data-name=
"LuCI.form.SectionValue#password"><a href=
"LuCI.form.SectionValue.html#password">password
</a></li>
1424 <li data-name=
"LuCI.form.SectionValue#placeholder"><a href=
"LuCI.form.SectionValue.html#placeholder">placeholder
</a></li>
1426 <li data-name=
"LuCI.form.SectionValue#readonly"><a href=
"LuCI.form.SectionValue.html#readonly">readonly
</a></li>
1428 <li data-name=
"LuCI.form.SectionValue#rmempty"><a href=
"LuCI.form.SectionValue.html#rmempty">rmempty
</a></li>
1430 <li data-name=
"LuCI.form.SectionValue#uciconfig"><a href=
"LuCI.form.SectionValue.html#uciconfig">uciconfig
</a></li>
1432 <li data-name=
"LuCI.form.SectionValue#ucioption"><a href=
"LuCI.form.SectionValue.html#ucioption">ucioption
</a></li>
1434 <li data-name=
"LuCI.form.SectionValue#ucisection"><a href=
"LuCI.form.SectionValue.html#ucisection">ucisection
</a></li>
1436 <li data-name=
"LuCI.form.SectionValue#validate"><a href=
"LuCI.form.SectionValue.html#validate">validate
</a></li>
1438 <li data-name=
"LuCI.form.SectionValue#width"><a href=
"LuCI.form.SectionValue.html#width">width
</a></li>
1441 <ul class=
"typedefs itemMembers">
1444 <ul class=
"typedefs itemMembers">
1447 <ul class=
"methods itemMembers">
1449 <span class=
"subtitle">Methods
</span>
1451 <li data-name=
"LuCI.form.SectionValue#append"><a href=
"LuCI.form.SectionValue.html#append">append
</a></li>
1453 <li data-name=
"LuCI.form.SectionValue#cbid"><a href=
"LuCI.form.SectionValue.html#cbid">cbid
</a></li>
1455 <li data-name=
"LuCI.form.SectionValue#cfgvalue"><a href=
"LuCI.form.SectionValue.html#cfgvalue">cfgvalue
</a></li>
1457 <li data-name=
"LuCI.form.SectionValue#depends"><a href=
"LuCI.form.SectionValue.html#depends">depends
</a></li>
1459 <li data-name=
"LuCI.form.SectionValue#formvalue"><a href=
"LuCI.form.SectionValue.html#formvalue">formvalue
</a></li>
1461 <li data-name=
"LuCI.form.SectionValue#getUIElement"><a href=
"LuCI.form.SectionValue.html#getUIElement">getUIElement
</a></li>
1463 <li data-name=
"LuCI.form.SectionValue#isActive"><a href=
"LuCI.form.SectionValue.html#isActive">isActive
</a></li>
1465 <li data-name=
"LuCI.form.SectionValue#isValid"><a href=
"LuCI.form.SectionValue.html#isValid">isValid
</a></li>
1467 <li data-name=
"LuCI.form.SectionValue#load"><a href=
"LuCI.form.SectionValue.html#load">load
</a></li>
1469 <li data-name=
"LuCI.form.SectionValue#parse"><a href=
"LuCI.form.SectionValue.html#parse">parse
</a></li>
1471 <li data-name=
"LuCI.form.SectionValue#remove"><a href=
"LuCI.form.SectionValue.html#remove">remove
</a></li>
1473 <li data-name=
"LuCI.form.SectionValue#stripTags"><a href=
"LuCI.form.SectionValue.html#stripTags">stripTags
</a></li>
1475 <li data-name=
"LuCI.form.SectionValue#textvalue"><a href=
"LuCI.form.SectionValue.html#textvalue">textvalue
</a></li>
1477 <li data-name=
"LuCI.form.SectionValue#titleFn"><a href=
"LuCI.form.SectionValue.html#titleFn">titleFn
</a></li>
1479 <li data-name=
"LuCI.form.SectionValue#value"><a href=
"LuCI.form.SectionValue.html#value">value
</a></li>
1481 <li data-name=
"LuCI.form.SectionValue#write"><a href=
"LuCI.form.SectionValue.html#write">write
</a></li>
1484 <ul class=
"events itemMembers">
1489 <li class=
"item" data-name=
"LuCI.form.TableSection">
1490 <span class=
"title">
1491 <a href=
"LuCI.form.TableSection.html">LuCI.form.TableSection
</a>
1494 <ul class=
"members itemMembers">
1496 <span class=
"subtitle">Members
</span>
1498 <li data-name=
"LuCI.form.TableSection##addbtntitle"><a href=
"LuCI.form.TableSection.html#addbtntitle">addbtntitle
</a></li>
1500 <li data-name=
"LuCI.form.TableSection##addremove"><a href=
"LuCI.form.TableSection.html#addremove">addremove
</a></li>
1502 <li data-name=
"LuCI.form.TableSection##anonymous"><a href=
"LuCI.form.TableSection.html#anonymous">anonymous
</a></li>
1504 <li data-name=
"LuCI.form.TableSection##extedit"><a href=
"LuCI.form.TableSection.html#extedit">extedit
</a></li>
1506 <li data-name=
"LuCI.form.TableSection##max_cols"><a href=
"LuCI.form.TableSection.html#max_cols">max_cols
</a></li>
1508 <li data-name=
"LuCI.form.TableSection##modaltitle"><a href=
"LuCI.form.TableSection.html#modaltitle">modaltitle
</a></li>
1510 <li data-name=
"LuCI.form.TableSection##nodescriptions"><a href=
"LuCI.form.TableSection.html#nodescriptions">nodescriptions
</a></li>
1512 <li data-name=
"LuCI.form.TableSection##rowcolors"><a href=
"LuCI.form.TableSection.html#rowcolors">rowcolors
</a></li>
1514 <li data-name=
"LuCI.form.TableSection##sectiontitle"><a href=
"LuCI.form.TableSection.html#sectiontitle">sectiontitle
</a></li>
1516 <li data-name=
"LuCI.form.TableSection##sortable"><a href=
"LuCI.form.TableSection.html#sortable">sortable
</a></li>
1518 <li data-name=
"LuCI.form.TableSection##uciconfig"><a href=
"LuCI.form.TableSection.html#uciconfig">uciconfig
</a></li>
1520 <li data-name=
"LuCI.form.TableSection#addbtntitle"><a href=
"LuCI.form.TableSection.html#addbtntitle">addbtntitle
</a></li>
1522 <li data-name=
"LuCI.form.TableSection#addremove"><a href=
"LuCI.form.TableSection.html#addremove">addremove
</a></li>
1524 <li data-name=
"LuCI.form.TableSection#anonymous"><a href=
"LuCI.form.TableSection.html#anonymous">anonymous
</a></li>
1526 <li data-name=
"LuCI.form.TableSection#parentoption"><a href=
"LuCI.form.TableSection.html#parentoption">parentoption
</a></li>
1528 <li data-name=
"LuCI.form.TableSection#tabbed"><a href=
"LuCI.form.TableSection.html#tabbed">tabbed
</a></li>
1530 <li data-name=
"LuCI.form.TableSection#uciconfig"><a href=
"LuCI.form.TableSection.html#uciconfig">uciconfig
</a></li>
1533 <ul class=
"typedefs itemMembers">
1536 <ul class=
"typedefs itemMembers">
1539 <ul class=
"methods itemMembers">
1541 <span class=
"subtitle">Methods
</span>
1543 <li data-name=
"LuCI.form.TableSection#addModalOptions"><a href=
"LuCI.form.TableSection.html#addModalOptions">addModalOptions
</a></li>
1545 <li data-name=
"LuCI.form.TableSection#append"><a href=
"LuCI.form.TableSection.html#append">append
</a></li>
1547 <li data-name=
"LuCI.form.TableSection#cfgvalue"><a href=
"LuCI.form.TableSection.html#cfgvalue">cfgvalue
</a></li>
1549 <li data-name=
"LuCI.form.TableSection#filter"><a href=
"LuCI.form.TableSection.html#filter">filter
</a></li>
1551 <li data-name=
"LuCI.form.TableSection#formvalue"><a href=
"LuCI.form.TableSection.html#formvalue">formvalue
</a></li>
1553 <li data-name=
"LuCI.form.TableSection#getOption"><a href=
"LuCI.form.TableSection.html#getOption">getOption
</a></li>
1555 <li data-name=
"LuCI.form.TableSection#getUIElement"><a href=
"LuCI.form.TableSection.html#getUIElement">getUIElement
</a></li>
1557 <li data-name=
"LuCI.form.TableSection#load"><a href=
"LuCI.form.TableSection.html#load">load
</a></li>
1559 <li data-name=
"LuCI.form.TableSection#option"><a href=
"LuCI.form.TableSection.html#option">option
</a></li>
1561 <li data-name=
"LuCI.form.TableSection#parse"><a href=
"LuCI.form.TableSection.html#parse">parse
</a></li>
1563 <li data-name=
"LuCI.form.TableSection#stripTags"><a href=
"LuCI.form.TableSection.html#stripTags">stripTags
</a></li>
1565 <li data-name=
"LuCI.form.TableSection#tab"><a href=
"LuCI.form.TableSection.html#tab">tab
</a></li>
1567 <li data-name=
"LuCI.form.TableSection#taboption"><a href=
"LuCI.form.TableSection.html#taboption">taboption
</a></li>
1569 <li data-name=
"LuCI.form.TableSection#titleFn"><a href=
"LuCI.form.TableSection.html#titleFn">titleFn
</a></li>
1572 <ul class=
"events itemMembers">
1577 <li class=
"item" data-name=
"LuCI.form.TextValue">
1578 <span class=
"title">
1579 <a href=
"LuCI.form.TextValue.html">LuCI.form.TextValue
</a>
1582 <ul class=
"members itemMembers">
1584 <span class=
"subtitle">Members
</span>
1586 <li data-name=
"LuCI.form.TextValue##cols"><a href=
"LuCI.form.TextValue.html#cols">cols
</a></li>
1588 <li data-name=
"LuCI.form.TextValue##monospace"><a href=
"LuCI.form.TextValue.html#monospace">monospace
</a></li>
1590 <li data-name=
"LuCI.form.TextValue##rows"><a href=
"LuCI.form.TextValue.html#rows">rows
</a></li>
1592 <li data-name=
"LuCI.form.TextValue##wrap"><a href=
"LuCI.form.TextValue.html#wrap">wrap
</a></li>
1594 <li data-name=
"LuCI.form.TextValue#datatype"><a href=
"LuCI.form.TextValue.html#datatype">datatype
</a></li>
1596 <li data-name=
"LuCI.form.TextValue#default"><a href=
"LuCI.form.TextValue.html#default">default
</a></li>
1598 <li data-name=
"LuCI.form.TextValue#editable"><a href=
"LuCI.form.TextValue.html#editable">editable
</a></li>
1600 <li data-name=
"LuCI.form.TextValue#modalonly"><a href=
"LuCI.form.TextValue.html#modalonly">modalonly
</a></li>
1602 <li data-name=
"LuCI.form.TextValue#onchange"><a href=
"LuCI.form.TextValue.html#onchange">onchange
</a></li>
1604 <li data-name=
"LuCI.form.TextValue#optional"><a href=
"LuCI.form.TextValue.html#optional">optional
</a></li>
1606 <li data-name=
"LuCI.form.TextValue#password"><a href=
"LuCI.form.TextValue.html#password">password
</a></li>
1608 <li data-name=
"LuCI.form.TextValue#placeholder"><a href=
"LuCI.form.TextValue.html#placeholder">placeholder
</a></li>
1610 <li data-name=
"LuCI.form.TextValue#readonly"><a href=
"LuCI.form.TextValue.html#readonly">readonly
</a></li>
1612 <li data-name=
"LuCI.form.TextValue#rmempty"><a href=
"LuCI.form.TextValue.html#rmempty">rmempty
</a></li>
1614 <li data-name=
"LuCI.form.TextValue#uciconfig"><a href=
"LuCI.form.TextValue.html#uciconfig">uciconfig
</a></li>
1616 <li data-name=
"LuCI.form.TextValue#ucioption"><a href=
"LuCI.form.TextValue.html#ucioption">ucioption
</a></li>
1618 <li data-name=
"LuCI.form.TextValue#ucisection"><a href=
"LuCI.form.TextValue.html#ucisection">ucisection
</a></li>
1620 <li data-name=
"LuCI.form.TextValue#validate"><a href=
"LuCI.form.TextValue.html#validate">validate
</a></li>
1622 <li data-name=
"LuCI.form.TextValue#width"><a href=
"LuCI.form.TextValue.html#width">width
</a></li>
1625 <ul class=
"typedefs itemMembers">
1628 <ul class=
"typedefs itemMembers">
1631 <ul class=
"methods itemMembers">
1633 <span class=
"subtitle">Methods
</span>
1635 <li data-name=
"LuCI.form.TextValue#append"><a href=
"LuCI.form.TextValue.html#append">append
</a></li>
1637 <li data-name=
"LuCI.form.TextValue#cbid"><a href=
"LuCI.form.TextValue.html#cbid">cbid
</a></li>
1639 <li data-name=
"LuCI.form.TextValue#cfgvalue"><a href=
"LuCI.form.TextValue.html#cfgvalue">cfgvalue
</a></li>
1641 <li data-name=
"LuCI.form.TextValue#depends"><a href=
"LuCI.form.TextValue.html#depends">depends
</a></li>
1643 <li data-name=
"LuCI.form.TextValue#formvalue"><a href=
"LuCI.form.TextValue.html#formvalue">formvalue
</a></li>
1645 <li data-name=
"LuCI.form.TextValue#getUIElement"><a href=
"LuCI.form.TextValue.html#getUIElement">getUIElement
</a></li>
1647 <li data-name=
"LuCI.form.TextValue#isActive"><a href=
"LuCI.form.TextValue.html#isActive">isActive
</a></li>
1649 <li data-name=
"LuCI.form.TextValue#isValid"><a href=
"LuCI.form.TextValue.html#isValid">isValid
</a></li>
1651 <li data-name=
"LuCI.form.TextValue#load"><a href=
"LuCI.form.TextValue.html#load">load
</a></li>
1653 <li data-name=
"LuCI.form.TextValue#parse"><a href=
"LuCI.form.TextValue.html#parse">parse
</a></li>
1655 <li data-name=
"LuCI.form.TextValue#remove"><a href=
"LuCI.form.TextValue.html#remove">remove
</a></li>
1657 <li data-name=
"LuCI.form.TextValue#stripTags"><a href=
"LuCI.form.TextValue.html#stripTags">stripTags
</a></li>
1659 <li data-name=
"LuCI.form.TextValue#textvalue"><a href=
"LuCI.form.TextValue.html#textvalue">textvalue
</a></li>
1661 <li data-name=
"LuCI.form.TextValue#titleFn"><a href=
"LuCI.form.TextValue.html#titleFn">titleFn
</a></li>
1663 <li data-name=
"LuCI.form.TextValue#write"><a href=
"LuCI.form.TextValue.html#write">write
</a></li>
1666 <ul class=
"events itemMembers">
1671 <li class=
"item" data-name=
"LuCI.form.TypedSection">
1672 <span class=
"title">
1673 <a href=
"LuCI.form.TypedSection.html">LuCI.form.TypedSection
</a>
1676 <ul class=
"members itemMembers">
1678 <span class=
"subtitle">Members
</span>
1680 <li data-name=
"LuCI.form.TypedSection##addbtntitle"><a href=
"LuCI.form.TypedSection.html#addbtntitle">addbtntitle
</a></li>
1682 <li data-name=
"LuCI.form.TypedSection##addremove"><a href=
"LuCI.form.TypedSection.html#addremove">addremove
</a></li>
1684 <li data-name=
"LuCI.form.TypedSection##anonymous"><a href=
"LuCI.form.TypedSection.html#anonymous">anonymous
</a></li>
1686 <li data-name=
"LuCI.form.TypedSection##tabbed"><a href=
"LuCI.form.TypedSection.html#tabbed">tabbed
</a></li>
1688 <li data-name=
"LuCI.form.TypedSection##uciconfig"><a href=
"LuCI.form.TypedSection.html#uciconfig">uciconfig
</a></li>
1690 <li data-name=
"LuCI.form.TypedSection#parentoption"><a href=
"LuCI.form.TypedSection.html#parentoption">parentoption
</a></li>
1693 <ul class=
"typedefs itemMembers">
1696 <ul class=
"typedefs itemMembers">
1699 <ul class=
"methods itemMembers">
1701 <span class=
"subtitle">Methods
</span>
1703 <li data-name=
"LuCI.form.TypedSection#append"><a href=
"LuCI.form.TypedSection.html#append">append
</a></li>
1705 <li data-name=
"LuCI.form.TypedSection#cfgsections"><a href=
"LuCI.form.TypedSection.html#cfgsections">cfgsections
</a></li>
1707 <li data-name=
"LuCI.form.TypedSection#cfgvalue"><a href=
"LuCI.form.TypedSection.html#cfgvalue">cfgvalue
</a></li>
1709 <li data-name=
"LuCI.form.TypedSection#filter"><a href=
"LuCI.form.TypedSection.html#filter">filter
</a></li>
1711 <li data-name=
"LuCI.form.TypedSection#formvalue"><a href=
"LuCI.form.TypedSection.html#formvalue">formvalue
</a></li>
1713 <li data-name=
"LuCI.form.TypedSection#getOption"><a href=
"LuCI.form.TypedSection.html#getOption">getOption
</a></li>
1715 <li data-name=
"LuCI.form.TypedSection#getUIElement"><a href=
"LuCI.form.TypedSection.html#getUIElement">getUIElement
</a></li>
1717 <li data-name=
"LuCI.form.TypedSection#load"><a href=
"LuCI.form.TypedSection.html#load">load
</a></li>
1719 <li data-name=
"LuCI.form.TypedSection#option"><a href=
"LuCI.form.TypedSection.html#option">option
</a></li>
1721 <li data-name=
"LuCI.form.TypedSection#parse"><a href=
"LuCI.form.TypedSection.html#parse">parse
</a></li>
1723 <li data-name=
"LuCI.form.TypedSection#render"><a href=
"LuCI.form.TypedSection.html#render">render
</a></li>
1725 <li data-name=
"LuCI.form.TypedSection#stripTags"><a href=
"LuCI.form.TypedSection.html#stripTags">stripTags
</a></li>
1727 <li data-name=
"LuCI.form.TypedSection#tab"><a href=
"LuCI.form.TypedSection.html#tab">tab
</a></li>
1729 <li data-name=
"LuCI.form.TypedSection#taboption"><a href=
"LuCI.form.TypedSection.html#taboption">taboption
</a></li>
1731 <li data-name=
"LuCI.form.TypedSection#titleFn"><a href=
"LuCI.form.TypedSection.html#titleFn">titleFn
</a></li>
1734 <ul class=
"events itemMembers">
1739 <li class=
"item" data-name=
"LuCI.form.Value">
1740 <span class=
"title">
1741 <a href=
"LuCI.form.Value.html">LuCI.form.Value
</a>
1744 <ul class=
"members itemMembers">
1746 <span class=
"subtitle">Members
</span>
1748 <li data-name=
"LuCI.form.Value##password"><a href=
"LuCI.form.Value.html#password">password
</a></li>
1750 <li data-name=
"LuCI.form.Value##placeholder"><a href=
"LuCI.form.Value.html#placeholder">placeholder
</a></li>
1752 <li data-name=
"LuCI.form.Value#datatype"><a href=
"LuCI.form.Value.html#datatype">datatype
</a></li>
1754 <li data-name=
"LuCI.form.Value#default"><a href=
"LuCI.form.Value.html#default">default
</a></li>
1756 <li data-name=
"LuCI.form.Value#editable"><a href=
"LuCI.form.Value.html#editable">editable
</a></li>
1758 <li data-name=
"LuCI.form.Value#modalonly"><a href=
"LuCI.form.Value.html#modalonly">modalonly
</a></li>
1760 <li data-name=
"LuCI.form.Value#onchange"><a href=
"LuCI.form.Value.html#onchange">onchange
</a></li>
1762 <li data-name=
"LuCI.form.Value#optional"><a href=
"LuCI.form.Value.html#optional">optional
</a></li>
1764 <li data-name=
"LuCI.form.Value#readonly"><a href=
"LuCI.form.Value.html#readonly">readonly
</a></li>
1766 <li data-name=
"LuCI.form.Value#rmempty"><a href=
"LuCI.form.Value.html#rmempty">rmempty
</a></li>
1768 <li data-name=
"LuCI.form.Value#uciconfig"><a href=
"LuCI.form.Value.html#uciconfig">uciconfig
</a></li>
1770 <li data-name=
"LuCI.form.Value#ucioption"><a href=
"LuCI.form.Value.html#ucioption">ucioption
</a></li>
1772 <li data-name=
"LuCI.form.Value#ucisection"><a href=
"LuCI.form.Value.html#ucisection">ucisection
</a></li>
1774 <li data-name=
"LuCI.form.Value#validate"><a href=
"LuCI.form.Value.html#validate">validate
</a></li>
1776 <li data-name=
"LuCI.form.Value#width"><a href=
"LuCI.form.Value.html#width">width
</a></li>
1779 <ul class=
"typedefs itemMembers">
1782 <ul class=
"typedefs itemMembers">
1785 <ul class=
"methods itemMembers">
1787 <span class=
"subtitle">Methods
</span>
1789 <li data-name=
"LuCI.form.Value#append"><a href=
"LuCI.form.Value.html#append">append
</a></li>
1791 <li data-name=
"LuCI.form.Value#cbid"><a href=
"LuCI.form.Value.html#cbid">cbid
</a></li>
1793 <li data-name=
"LuCI.form.Value#cfgvalue"><a href=
"LuCI.form.Value.html#cfgvalue">cfgvalue
</a></li>
1795 <li data-name=
"LuCI.form.Value#depends"><a href=
"LuCI.form.Value.html#depends">depends
</a></li>
1797 <li data-name=
"LuCI.form.Value#formvalue"><a href=
"LuCI.form.Value.html#formvalue">formvalue
</a></li>
1799 <li data-name=
"LuCI.form.Value#getUIElement"><a href=
"LuCI.form.Value.html#getUIElement">getUIElement
</a></li>
1801 <li data-name=
"LuCI.form.Value#isActive"><a href=
"LuCI.form.Value.html#isActive">isActive
</a></li>
1803 <li data-name=
"LuCI.form.Value#isValid"><a href=
"LuCI.form.Value.html#isValid">isValid
</a></li>
1805 <li data-name=
"LuCI.form.Value#load"><a href=
"LuCI.form.Value.html#load">load
</a></li>
1807 <li data-name=
"LuCI.form.Value#parse"><a href=
"LuCI.form.Value.html#parse">parse
</a></li>
1809 <li data-name=
"LuCI.form.Value#remove"><a href=
"LuCI.form.Value.html#remove">remove
</a></li>
1811 <li data-name=
"LuCI.form.Value#render"><a href=
"LuCI.form.Value.html#render">render
</a></li>
1813 <li data-name=
"LuCI.form.Value#stripTags"><a href=
"LuCI.form.Value.html#stripTags">stripTags
</a></li>
1815 <li data-name=
"LuCI.form.Value#textvalue"><a href=
"LuCI.form.Value.html#textvalue">textvalue
</a></li>
1817 <li data-name=
"LuCI.form.Value#titleFn"><a href=
"LuCI.form.Value.html#titleFn">titleFn
</a></li>
1819 <li data-name=
"LuCI.form.Value#value"><a href=
"LuCI.form.Value.html#value">value
</a></li>
1821 <li data-name=
"LuCI.form.Value#write"><a href=
"LuCI.form.Value.html#write">write
</a></li>
1824 <ul class=
"events itemMembers">
1829 <li class=
"item" data-name=
"LuCI.fs">
1830 <span class=
"title">
1831 <a href=
"LuCI.fs.html">LuCI.fs
</a>
1834 <ul class=
"members itemMembers">
1837 <ul class=
"typedefs itemMembers">
1839 <span class=
"subtitle">Typedefs
</span>
1841 <li data-name=
"LuCI.fs.FileExecResult"><a href=
"LuCI.fs.html#.FileExecResult">FileExecResult
</a></li>
1843 <li data-name=
"LuCI.fs.FileStatEntry"><a href=
"LuCI.fs.html#.FileStatEntry">FileStatEntry
</a></li>
1846 <ul class=
"typedefs itemMembers">
1849 <ul class=
"methods itemMembers">
1851 <span class=
"subtitle">Methods
</span>
1853 <li data-name=
"LuCI.fs#exec"><a href=
"LuCI.fs.html#exec">exec
</a></li>
1855 <li data-name=
"LuCI.fs#exec_direct"><a href=
"LuCI.fs.html#exec_direct">exec_direct
</a></li>
1857 <li data-name=
"LuCI.fs#lines"><a href=
"LuCI.fs.html#lines">lines
</a></li>
1859 <li data-name=
"LuCI.fs#list"><a href=
"LuCI.fs.html#list">list
</a></li>
1861 <li data-name=
"LuCI.fs#read"><a href=
"LuCI.fs.html#read">read
</a></li>
1863 <li data-name=
"LuCI.fs#read_direct"><a href=
"LuCI.fs.html#read_direct">read_direct
</a></li>
1865 <li data-name=
"LuCI.fs#remove"><a href=
"LuCI.fs.html#remove">remove
</a></li>
1867 <li data-name=
"LuCI.fs#stat"><a href=
"LuCI.fs.html#stat">stat
</a></li>
1869 <li data-name=
"LuCI.fs#trimmed"><a href=
"LuCI.fs.html#trimmed">trimmed
</a></li>
1871 <li data-name=
"LuCI.fs#write"><a href=
"LuCI.fs.html#write">write
</a></li>
1874 <ul class=
"events itemMembers">
1879 <li class=
"item" data-name=
"LuCI.headers">
1880 <span class=
"title">
1881 <a href=
"LuCI.headers.html">LuCI.headers
</a>
1884 <ul class=
"members itemMembers">
1887 <ul class=
"typedefs itemMembers">
1890 <ul class=
"typedefs itemMembers">
1893 <ul class=
"methods itemMembers">
1895 <span class=
"subtitle">Methods
</span>
1897 <li data-name=
"LuCI.headers#get"><a href=
"LuCI.headers.html#get">get
</a></li>
1899 <li data-name=
"LuCI.headers#has"><a href=
"LuCI.headers.html#has">has
</a></li>
1902 <ul class=
"events itemMembers">
1907 <li class=
"item" data-name=
"LuCI.network">
1908 <span class=
"title">
1909 <a href=
"LuCI.network.html">LuCI.network
</a>
1912 <ul class=
"members itemMembers">
1915 <ul class=
"typedefs itemMembers">
1917 <span class=
"subtitle">Typedefs
</span>
1919 <li data-name=
"LuCI.network.SwitchTopology"><a href=
"LuCI.network.html#.SwitchTopology">SwitchTopology
</a></li>
1921 <li data-name=
"LuCI.network.WifiEncryption"><a href=
"LuCI.network.html#.WifiEncryption">WifiEncryption
</a></li>
1923 <li data-name=
"LuCI.network.WifiPeerEntry"><a href=
"LuCI.network.html#.WifiPeerEntry">WifiPeerEntry
</a></li>
1925 <li data-name=
"LuCI.network.WifiRateEntry"><a href=
"LuCI.network.html#.WifiRateEntry">WifiRateEntry
</a></li>
1927 <li data-name=
"LuCI.network.WifiScanResult"><a href=
"LuCI.network.html#.WifiScanResult">WifiScanResult
</a></li>
1930 <ul class=
"typedefs itemMembers">
1933 <ul class=
"methods itemMembers">
1935 <span class=
"subtitle">Methods
</span>
1937 <li data-name=
"LuCI.network#addNetwork"><a href=
"LuCI.network.html#addNetwork">addNetwork
</a></li>
1939 <li data-name=
"LuCI.network#addWifiNetwork"><a href=
"LuCI.network.html#addWifiNetwork">addWifiNetwork
</a></li>
1941 <li data-name=
"LuCI.network#deleteNetwork"><a href=
"LuCI.network.html#deleteNetwork">deleteNetwork
</a></li>
1943 <li data-name=
"LuCI.network#deleteWifiNetwork"><a href=
"LuCI.network.html#deleteWifiNetwork">deleteWifiNetwork
</a></li>
1945 <li data-name=
"LuCI.network#flushCache"><a href=
"LuCI.network.html#flushCache">flushCache
</a></li>
1947 <li data-name=
"LuCI.network#formatWifiEncryption"><a href=
"LuCI.network.html#formatWifiEncryption">formatWifiEncryption
</a></li>
1949 <li data-name=
"LuCI.network#getDevice"><a href=
"LuCI.network.html#getDevice">getDevice
</a></li>
1951 <li data-name=
"LuCI.network#getDevices"><a href=
"LuCI.network.html#getDevices">getDevices
</a></li>
1953 <li data-name=
"LuCI.network#getDSLModemType"><a href=
"LuCI.network.html#getDSLModemType">getDSLModemType
</a></li>
1955 <li data-name=
"LuCI.network#getHostHints"><a href=
"LuCI.network.html#getHostHints">getHostHints
</a></li>
1957 <li data-name=
"LuCI.network#getIfnameOf"><a href=
"LuCI.network.html#getIfnameOf">getIfnameOf
</a></li>
1959 <li data-name=
"LuCI.network#getNetwork"><a href=
"LuCI.network.html#getNetwork">getNetwork
</a></li>
1961 <li data-name=
"LuCI.network#getNetworks"><a href=
"LuCI.network.html#getNetworks">getNetworks
</a></li>
1963 <li data-name=
"LuCI.network#getProtocol"><a href=
"LuCI.network.html#getProtocol">getProtocol
</a></li>
1965 <li data-name=
"LuCI.network#getProtocols"><a href=
"LuCI.network.html#getProtocols">getProtocols
</a></li>
1967 <li data-name=
"LuCI.network#getSwitchTopologies"><a href=
"LuCI.network.html#getSwitchTopologies">getSwitchTopologies
</a></li>
1969 <li data-name=
"LuCI.network#getWAN6Networks"><a href=
"LuCI.network.html#getWAN6Networks">getWAN6Networks
</a></li>
1971 <li data-name=
"LuCI.network#getWANNetworks"><a href=
"LuCI.network.html#getWANNetworks">getWANNetworks
</a></li>
1973 <li data-name=
"LuCI.network#getWifiDevice"><a href=
"LuCI.network.html#getWifiDevice">getWifiDevice
</a></li>
1975 <li data-name=
"LuCI.network#getWifiDevices"><a href=
"LuCI.network.html#getWifiDevices">getWifiDevices
</a></li>
1977 <li data-name=
"LuCI.network#getWifiNetwork"><a href=
"LuCI.network.html#getWifiNetwork">getWifiNetwork
</a></li>
1979 <li data-name=
"LuCI.network#getWifiNetworks"><a href=
"LuCI.network.html#getWifiNetworks">getWifiNetworks
</a></li>
1981 <li data-name=
"LuCI.network#isIgnoredDevice"><a href=
"LuCI.network.html#isIgnoredDevice">isIgnoredDevice
</a></li>
1983 <li data-name=
"LuCI.network#maskToPrefix"><a href=
"LuCI.network.html#maskToPrefix">maskToPrefix
</a></li>
1985 <li data-name=
"LuCI.network#prefixToMask"><a href=
"LuCI.network.html#prefixToMask">prefixToMask
</a></li>
1987 <li data-name=
"LuCI.network#registerErrorCode"><a href=
"LuCI.network.html#registerErrorCode">registerErrorCode
</a></li>
1989 <li data-name=
"LuCI.network#registerPatternVirtual"><a href=
"LuCI.network.html#registerPatternVirtual">registerPatternVirtual
</a></li>
1991 <li data-name=
"LuCI.network#registerProtocol"><a href=
"LuCI.network.html#registerProtocol">registerProtocol
</a></li>
1993 <li data-name=
"LuCI.network#renameNetwork"><a href=
"LuCI.network.html#renameNetwork">renameNetwork
</a></li>
1996 <ul class=
"events itemMembers">
2001 <li class=
"item" data-name=
"LuCI.network.Device">
2002 <span class=
"title">
2003 <a href=
"LuCI.network.Device.html">LuCI.network.Device
</a>
2006 <ul class=
"members itemMembers">
2009 <ul class=
"typedefs itemMembers">
2012 <ul class=
"typedefs itemMembers">
2015 <ul class=
"methods itemMembers">
2017 <span class=
"subtitle">Methods
</span>
2019 <li data-name=
"LuCI.network.Device#getBridgeID"><a href=
"LuCI.network.Device.html#getBridgeID">getBridgeID
</a></li>
2021 <li data-name=
"LuCI.network.Device#getBridgeSTP"><a href=
"LuCI.network.Device.html#getBridgeSTP">getBridgeSTP
</a></li>
2023 <li data-name=
"LuCI.network.Device#getI18n"><a href=
"LuCI.network.Device.html#getI18n">getI18n
</a></li>
2025 <li data-name=
"LuCI.network.Device#getIP6Addrs"><a href=
"LuCI.network.Device.html#getIP6Addrs">getIP6Addrs
</a></li>
2027 <li data-name=
"LuCI.network.Device#getIPAddrs"><a href=
"LuCI.network.Device.html#getIPAddrs">getIPAddrs
</a></li>
2029 <li data-name=
"LuCI.network.Device#getMAC"><a href=
"LuCI.network.Device.html#getMAC">getMAC
</a></li>
2031 <li data-name=
"LuCI.network.Device#getMTU"><a href=
"LuCI.network.Device.html#getMTU">getMTU
</a></li>
2033 <li data-name=
"LuCI.network.Device#getName"><a href=
"LuCI.network.Device.html#getName">getName
</a></li>
2035 <li data-name=
"LuCI.network.Device#getNetwork"><a href=
"LuCI.network.Device.html#getNetwork">getNetwork
</a></li>
2037 <li data-name=
"LuCI.network.Device#getNetworks"><a href=
"LuCI.network.Device.html#getNetworks">getNetworks
</a></li>
2039 <li data-name=
"LuCI.network.Device#getPorts"><a href=
"LuCI.network.Device.html#getPorts">getPorts
</a></li>
2041 <li data-name=
"LuCI.network.Device#getRXBytes"><a href=
"LuCI.network.Device.html#getRXBytes">getRXBytes
</a></li>
2043 <li data-name=
"LuCI.network.Device#getRXPackets"><a href=
"LuCI.network.Device.html#getRXPackets">getRXPackets
</a></li>
2045 <li data-name=
"LuCI.network.Device#getShortName"><a href=
"LuCI.network.Device.html#getShortName">getShortName
</a></li>
2047 <li data-name=
"LuCI.network.Device#getTXBytes"><a href=
"LuCI.network.Device.html#getTXBytes">getTXBytes
</a></li>
2049 <li data-name=
"LuCI.network.Device#getTXPackets"><a href=
"LuCI.network.Device.html#getTXPackets">getTXPackets
</a></li>
2051 <li data-name=
"LuCI.network.Device#getType"><a href=
"LuCI.network.Device.html#getType">getType
</a></li>
2053 <li data-name=
"LuCI.network.Device#getTypeI18n"><a href=
"LuCI.network.Device.html#getTypeI18n">getTypeI18n
</a></li>
2055 <li data-name=
"LuCI.network.Device#getWifiNetwork"><a href=
"LuCI.network.Device.html#getWifiNetwork">getWifiNetwork
</a></li>
2057 <li data-name=
"LuCI.network.Device#isBridge"><a href=
"LuCI.network.Device.html#isBridge">isBridge
</a></li>
2059 <li data-name=
"LuCI.network.Device#isBridgePort"><a href=
"LuCI.network.Device.html#isBridgePort">isBridgePort
</a></li>
2061 <li data-name=
"LuCI.network.Device#isUp"><a href=
"LuCI.network.Device.html#isUp">isUp
</a></li>
2064 <ul class=
"events itemMembers">
2069 <li class=
"item" data-name=
"LuCI.network.Hosts">
2070 <span class=
"title">
2071 <a href=
"LuCI.network.Hosts.html">LuCI.network.Hosts
</a>
2074 <ul class=
"members itemMembers">
2077 <ul class=
"typedefs itemMembers">
2080 <ul class=
"typedefs itemMembers">
2083 <ul class=
"methods itemMembers">
2085 <span class=
"subtitle">Methods
</span>
2087 <li data-name=
"LuCI.network.Hosts#getHostnameByIP6Addr"><a href=
"LuCI.network.Hosts.html#getHostnameByIP6Addr">getHostnameByIP6Addr
</a></li>
2089 <li data-name=
"LuCI.network.Hosts#getHostnameByIPAddr"><a href=
"LuCI.network.Hosts.html#getHostnameByIPAddr">getHostnameByIPAddr
</a></li>
2091 <li data-name=
"LuCI.network.Hosts#getHostnameByMACAddr"><a href=
"LuCI.network.Hosts.html#getHostnameByMACAddr">getHostnameByMACAddr
</a></li>
2093 <li data-name=
"LuCI.network.Hosts#getIP6AddrByMACAddr"><a href=
"LuCI.network.Hosts.html#getIP6AddrByMACAddr">getIP6AddrByMACAddr
</a></li>
2095 <li data-name=
"LuCI.network.Hosts#getIPAddrByMACAddr"><a href=
"LuCI.network.Hosts.html#getIPAddrByMACAddr">getIPAddrByMACAddr
</a></li>
2097 <li data-name=
"LuCI.network.Hosts#getMACAddrByIP6Addr"><a href=
"LuCI.network.Hosts.html#getMACAddrByIP6Addr">getMACAddrByIP6Addr
</a></li>
2099 <li data-name=
"LuCI.network.Hosts#getMACAddrByIPAddr"><a href=
"LuCI.network.Hosts.html#getMACAddrByIPAddr">getMACAddrByIPAddr
</a></li>
2101 <li data-name=
"LuCI.network.Hosts#getMACHints"><a href=
"LuCI.network.Hosts.html#getMACHints">getMACHints
</a></li>
2104 <ul class=
"events itemMembers">
2109 <li class=
"item" data-name=
"LuCI.network.Protocol">
2110 <span class=
"title">
2111 <a href=
"LuCI.network.Protocol.html">LuCI.network.Protocol
</a>
2114 <ul class=
"members itemMembers">
2117 <ul class=
"typedefs itemMembers">
2120 <ul class=
"typedefs itemMembers">
2123 <ul class=
"methods itemMembers">
2125 <span class=
"subtitle">Methods
</span>
2127 <li data-name=
"LuCI.network.Protocol#addDevice"><a href=
"LuCI.network.Protocol.html#addDevice">addDevice
</a></li>
2129 <li data-name=
"LuCI.network.Protocol#containsDevice"><a href=
"LuCI.network.Protocol.html#containsDevice">containsDevice
</a></li>
2131 <li data-name=
"LuCI.network.Protocol#deleteConfiguration"><a href=
"LuCI.network.Protocol.html#deleteConfiguration">deleteConfiguration
</a></li>
2133 <li data-name=
"LuCI.network.Protocol#deleteDevice"><a href=
"LuCI.network.Protocol.html#deleteDevice">deleteDevice
</a></li>
2135 <li data-name=
"LuCI.network.Protocol#get"><a href=
"LuCI.network.Protocol.html#get">get
</a></li>
2137 <li data-name=
"LuCI.network.Protocol#getDevice"><a href=
"LuCI.network.Protocol.html#getDevice">getDevice
</a></li>
2139 <li data-name=
"LuCI.network.Protocol#getDevices"><a href=
"LuCI.network.Protocol.html#getDevices">getDevices
</a></li>
2141 <li data-name=
"LuCI.network.Protocol#getDNS6Addrs"><a href=
"LuCI.network.Protocol.html#getDNS6Addrs">getDNS6Addrs
</a></li>
2143 <li data-name=
"LuCI.network.Protocol#getDNSAddrs"><a href=
"LuCI.network.Protocol.html#getDNSAddrs">getDNSAddrs
</a></li>
2145 <li data-name=
"LuCI.network.Protocol#getErrors"><a href=
"LuCI.network.Protocol.html#getErrors">getErrors
</a></li>
2147 <li data-name=
"LuCI.network.Protocol#getExpiry"><a href=
"LuCI.network.Protocol.html#getExpiry">getExpiry
</a></li>
2149 <li data-name=
"LuCI.network.Protocol#getGateway6Addr"><a href=
"LuCI.network.Protocol.html#getGateway6Addr">getGateway6Addr
</a></li>
2151 <li data-name=
"LuCI.network.Protocol#getGatewayAddr"><a href=
"LuCI.network.Protocol.html#getGatewayAddr">getGatewayAddr
</a></li>
2153 <li data-name=
"LuCI.network.Protocol#getI18n"><a href=
"LuCI.network.Protocol.html#getI18n">getI18n
</a></li>
2155 <li data-name=
"LuCI.network.Protocol#getIfname"><a href=
"LuCI.network.Protocol.html#getIfname">getIfname
</a></li>
2157 <li data-name=
"LuCI.network.Protocol#getIP6Addr"><a href=
"LuCI.network.Protocol.html#getIP6Addr">getIP6Addr
</a></li>
2159 <li data-name=
"LuCI.network.Protocol#getIP6Addrs"><a href=
"LuCI.network.Protocol.html#getIP6Addrs">getIP6Addrs
</a></li>
2161 <li data-name=
"LuCI.network.Protocol#getIP6Prefix"><a href=
"LuCI.network.Protocol.html#getIP6Prefix">getIP6Prefix
</a></li>
2163 <li data-name=
"LuCI.network.Protocol#getIPAddr"><a href=
"LuCI.network.Protocol.html#getIPAddr">getIPAddr
</a></li>
2165 <li data-name=
"LuCI.network.Protocol#getIPAddrs"><a href=
"LuCI.network.Protocol.html#getIPAddrs">getIPAddrs
</a></li>
2167 <li data-name=
"LuCI.network.Protocol#getL2Device"><a href=
"LuCI.network.Protocol.html#getL2Device">getL2Device
</a></li>
2169 <li data-name=
"LuCI.network.Protocol#getL3Device"><a href=
"LuCI.network.Protocol.html#getL3Device">getL3Device
</a></li>
2171 <li data-name=
"LuCI.network.Protocol#getMetric"><a href=
"LuCI.network.Protocol.html#getMetric">getMetric
</a></li>
2173 <li data-name=
"LuCI.network.Protocol#getName"><a href=
"LuCI.network.Protocol.html#getName">getName
</a></li>
2175 <li data-name=
"LuCI.network.Protocol#getNetmask"><a href=
"LuCI.network.Protocol.html#getNetmask">getNetmask
</a></li>
2177 <li data-name=
"LuCI.network.Protocol#getOpkgPackage"><a href=
"LuCI.network.Protocol.html#getOpkgPackage">getOpkgPackage
</a></li>
2179 <li data-name=
"LuCI.network.Protocol#getProtocol"><a href=
"LuCI.network.Protocol.html#getProtocol">getProtocol
</a></li>
2181 <li data-name=
"LuCI.network.Protocol#getType"><a href=
"LuCI.network.Protocol.html#getType">getType
</a></li>
2183 <li data-name=
"LuCI.network.Protocol#getUptime"><a href=
"LuCI.network.Protocol.html#getUptime">getUptime
</a></li>
2185 <li data-name=
"LuCI.network.Protocol#getZoneName"><a href=
"LuCI.network.Protocol.html#getZoneName">getZoneName
</a></li>
2187 <li data-name=
"LuCI.network.Protocol#isAlias"><a href=
"LuCI.network.Protocol.html#isAlias">isAlias
</a></li>
2189 <li data-name=
"LuCI.network.Protocol#isBridge"><a href=
"LuCI.network.Protocol.html#isBridge">isBridge
</a></li>
2191 <li data-name=
"LuCI.network.Protocol#isCreateable"><a href=
"LuCI.network.Protocol.html#isCreateable">isCreateable
</a></li>
2193 <li data-name=
"LuCI.network.Protocol#isDynamic"><a href=
"LuCI.network.Protocol.html#isDynamic">isDynamic
</a></li>
2195 <li data-name=
"LuCI.network.Protocol#isEmpty"><a href=
"LuCI.network.Protocol.html#isEmpty">isEmpty
</a></li>
2197 <li data-name=
"LuCI.network.Protocol#isFloating"><a href=
"LuCI.network.Protocol.html#isFloating">isFloating
</a></li>
2199 <li data-name=
"LuCI.network.Protocol#isInstalled"><a href=
"LuCI.network.Protocol.html#isInstalled">isInstalled
</a></li>
2201 <li data-name=
"LuCI.network.Protocol#isUp"><a href=
"LuCI.network.Protocol.html#isUp">isUp
</a></li>
2203 <li data-name=
"LuCI.network.Protocol#isVirtual"><a href=
"LuCI.network.Protocol.html#isVirtual">isVirtual
</a></li>
2205 <li data-name=
"LuCI.network.Protocol#set"><a href=
"LuCI.network.Protocol.html#set">set
</a></li>
2208 <ul class=
"events itemMembers">
2213 <li class=
"item" data-name=
"LuCI.network.WifiDevice">
2214 <span class=
"title">
2215 <a href=
"LuCI.network.WifiDevice.html">LuCI.network.WifiDevice
</a>
2218 <ul class=
"members itemMembers">
2221 <ul class=
"typedefs itemMembers">
2224 <ul class=
"typedefs itemMembers">
2227 <ul class=
"methods itemMembers">
2229 <span class=
"subtitle">Methods
</span>
2231 <li data-name=
"LuCI.network.WifiDevice#addWifiNetwork"><a href=
"LuCI.network.WifiDevice.html#addWifiNetwork">addWifiNetwork
</a></li>
2233 <li data-name=
"LuCI.network.WifiDevice#deleteWifiNetwork"><a href=
"LuCI.network.WifiDevice.html#deleteWifiNetwork">deleteWifiNetwork
</a></li>
2235 <li data-name=
"LuCI.network.WifiDevice#get"><a href=
"LuCI.network.WifiDevice.html#get">get
</a></li>
2237 <li data-name=
"LuCI.network.WifiDevice#getHTModes"><a href=
"LuCI.network.WifiDevice.html#getHTModes">getHTModes
</a></li>
2239 <li data-name=
"LuCI.network.WifiDevice#getHWModes"><a href=
"LuCI.network.WifiDevice.html#getHWModes">getHWModes
</a></li>
2241 <li data-name=
"LuCI.network.WifiDevice#getI18n"><a href=
"LuCI.network.WifiDevice.html#getI18n">getI18n
</a></li>
2243 <li data-name=
"LuCI.network.WifiDevice#getName"><a href=
"LuCI.network.WifiDevice.html#getName">getName
</a></li>
2245 <li data-name=
"LuCI.network.WifiDevice#getScanList"><a href=
"LuCI.network.WifiDevice.html#getScanList">getScanList
</a></li>
2247 <li data-name=
"LuCI.network.WifiDevice#getWifiNetwork"><a href=
"LuCI.network.WifiDevice.html#getWifiNetwork">getWifiNetwork
</a></li>
2249 <li data-name=
"LuCI.network.WifiDevice#getWifiNetworks"><a href=
"LuCI.network.WifiDevice.html#getWifiNetworks">getWifiNetworks
</a></li>
2251 <li data-name=
"LuCI.network.WifiDevice#isDisabled"><a href=
"LuCI.network.WifiDevice.html#isDisabled">isDisabled
</a></li>
2253 <li data-name=
"LuCI.network.WifiDevice#isUp"><a href=
"LuCI.network.WifiDevice.html#isUp">isUp
</a></li>
2255 <li data-name=
"LuCI.network.WifiDevice#set"><a href=
"LuCI.network.WifiDevice.html#set">set
</a></li>
2258 <ul class=
"events itemMembers">
2263 <li class=
"item" data-name=
"LuCI.network.WifiNetwork">
2264 <span class=
"title">
2265 <a href=
"LuCI.network.WifiNetwork.html">LuCI.network.WifiNetwork
</a>
2268 <ul class=
"members itemMembers">
2271 <ul class=
"typedefs itemMembers">
2274 <ul class=
"typedefs itemMembers">
2277 <ul class=
"methods itemMembers">
2279 <span class=
"subtitle">Methods
</span>
2281 <li data-name=
"LuCI.network.WifiNetwork#disconnectClient"><a href=
"LuCI.network.WifiNetwork.html#disconnectClient">disconnectClient
</a></li>
2283 <li data-name=
"LuCI.network.WifiNetwork#get"><a href=
"LuCI.network.WifiNetwork.html#get">get
</a></li>
2285 <li data-name=
"LuCI.network.WifiNetwork#getActiveBSSID"><a href=
"LuCI.network.WifiNetwork.html#getActiveBSSID">getActiveBSSID
</a></li>
2287 <li data-name=
"LuCI.network.WifiNetwork#getActiveEncryption"><a href=
"LuCI.network.WifiNetwork.html#getActiveEncryption">getActiveEncryption
</a></li>
2289 <li data-name=
"LuCI.network.WifiNetwork#getActiveMode"><a href=
"LuCI.network.WifiNetwork.html#getActiveMode">getActiveMode
</a></li>
2291 <li data-name=
"LuCI.network.WifiNetwork#getActiveModeI18n"><a href=
"LuCI.network.WifiNetwork.html#getActiveModeI18n">getActiveModeI18n
</a></li>
2293 <li data-name=
"LuCI.network.WifiNetwork#getActiveSSID"><a href=
"LuCI.network.WifiNetwork.html#getActiveSSID">getActiveSSID
</a></li>
2295 <li data-name=
"LuCI.network.WifiNetwork#getAssocList"><a href=
"LuCI.network.WifiNetwork.html#getAssocList">getAssocList
</a></li>
2297 <li data-name=
"LuCI.network.WifiNetwork#getBitRate"><a href=
"LuCI.network.WifiNetwork.html#getBitRate">getBitRate
</a></li>
2299 <li data-name=
"LuCI.network.WifiNetwork#getBSSID"><a href=
"LuCI.network.WifiNetwork.html#getBSSID">getBSSID
</a></li>
2301 <li data-name=
"LuCI.network.WifiNetwork#getChannel"><a href=
"LuCI.network.WifiNetwork.html#getChannel">getChannel
</a></li>
2303 <li data-name=
"LuCI.network.WifiNetwork#getCountryCode"><a href=
"LuCI.network.WifiNetwork.html#getCountryCode">getCountryCode
</a></li>
2305 <li data-name=
"LuCI.network.WifiNetwork#getDevice"><a href=
"LuCI.network.WifiNetwork.html#getDevice">getDevice
</a></li>
2307 <li data-name=
"LuCI.network.WifiNetwork#getFrequency"><a href=
"LuCI.network.WifiNetwork.html#getFrequency">getFrequency
</a></li>
2309 <li data-name=
"LuCI.network.WifiNetwork#getI18n"><a href=
"LuCI.network.WifiNetwork.html#getI18n">getI18n
</a></li>
2311 <li data-name=
"LuCI.network.WifiNetwork#getID"><a href=
"LuCI.network.WifiNetwork.html#getID">getID
</a></li>
2313 <li data-name=
"LuCI.network.WifiNetwork#getIfname"><a href=
"LuCI.network.WifiNetwork.html#getIfname">getIfname
</a></li>
2315 <li data-name=
"LuCI.network.WifiNetwork#getMeshID"><a href=
"LuCI.network.WifiNetwork.html#getMeshID">getMeshID
</a></li>
2317 <li data-name=
"LuCI.network.WifiNetwork#getMode"><a href=
"LuCI.network.WifiNetwork.html#getMode">getMode
</a></li>
2319 <li data-name=
"LuCI.network.WifiNetwork#getName"><a href=
"LuCI.network.WifiNetwork.html#getName">getName
</a></li>
2321 <li data-name=
"LuCI.network.WifiNetwork#getNetwork"><a href=
"LuCI.network.WifiNetwork.html#getNetwork">getNetwork
</a></li>
2323 <li data-name=
"LuCI.network.WifiNetwork#getNetworkNames"><a href=
"LuCI.network.WifiNetwork.html#getNetworkNames">getNetworkNames
</a></li>
2325 <li data-name=
"LuCI.network.WifiNetwork#getNetworks"><a href=
"LuCI.network.WifiNetwork.html#getNetworks">getNetworks
</a></li>
2327 <li data-name=
"LuCI.network.WifiNetwork#getNoise"><a href=
"LuCI.network.WifiNetwork.html#getNoise">getNoise
</a></li>
2329 <li data-name=
"LuCI.network.WifiNetwork#getShortName"><a href=
"LuCI.network.WifiNetwork.html#getShortName">getShortName
</a></li>
2331 <li data-name=
"LuCI.network.WifiNetwork#getSignal"><a href=
"LuCI.network.WifiNetwork.html#getSignal">getSignal
</a></li>
2333 <li data-name=
"LuCI.network.WifiNetwork#getSignalLevel"><a href=
"LuCI.network.WifiNetwork.html#getSignalLevel">getSignalLevel
</a></li>
2335 <li data-name=
"LuCI.network.WifiNetwork#getSignalPercent"><a href=
"LuCI.network.WifiNetwork.html#getSignalPercent">getSignalPercent
</a></li>
2337 <li data-name=
"LuCI.network.WifiNetwork#getSSID"><a href=
"LuCI.network.WifiNetwork.html#getSSID">getSSID
</a></li>
2339 <li data-name=
"LuCI.network.WifiNetwork#getTXPower"><a href=
"LuCI.network.WifiNetwork.html#getTXPower">getTXPower
</a></li>
2341 <li data-name=
"LuCI.network.WifiNetwork#getTXPowerOffset"><a href=
"LuCI.network.WifiNetwork.html#getTXPowerOffset">getTXPowerOffset
</a></li>
2343 <li data-name=
"LuCI.network.WifiNetwork#getWifiDevice"><a href=
"LuCI.network.WifiNetwork.html#getWifiDevice">getWifiDevice
</a></li>
2345 <li data-name=
"LuCI.network.WifiNetwork#getWifiDeviceName"><a href=
"LuCI.network.WifiNetwork.html#getWifiDeviceName">getWifiDeviceName
</a></li>
2347 <li data-name=
"LuCI.network.WifiNetwork#isClientDisconnectSupported"><a href=
"LuCI.network.WifiNetwork.html#isClientDisconnectSupported">isClientDisconnectSupported
</a></li>
2349 <li data-name=
"LuCI.network.WifiNetwork#isDisabled"><a href=
"LuCI.network.WifiNetwork.html#isDisabled">isDisabled
</a></li>
2351 <li data-name=
"LuCI.network.WifiNetwork#isUp"><a href=
"LuCI.network.WifiNetwork.html#isUp">isUp
</a></li>
2353 <li data-name=
"LuCI.network.WifiNetwork#set"><a href=
"LuCI.network.WifiNetwork.html#set">set
</a></li>
2356 <ul class=
"events itemMembers">
2361 <li class=
"item" data-name=
"LuCI.poll">
2362 <span class=
"title">
2363 <a href=
"LuCI.poll.html">LuCI.poll
</a>
2366 <ul class=
"members itemMembers">
2369 <ul class=
"typedefs itemMembers">
2372 <ul class=
"typedefs itemMembers">
2375 <ul class=
"methods itemMembers">
2377 <span class=
"subtitle">Methods
</span>
2379 <li data-name=
"LuCI.poll#active"><a href=
"LuCI.poll.html#active">active
</a></li>
2381 <li data-name=
"LuCI.poll#add"><a href=
"LuCI.poll.html#add">add
</a></li>
2383 <li data-name=
"LuCI.poll#remove"><a href=
"LuCI.poll.html#remove">remove
</a></li>
2385 <li data-name=
"LuCI.poll#start"><a href=
"LuCI.poll.html#start">start
</a></li>
2387 <li data-name=
"LuCI.poll#stop"><a href=
"LuCI.poll.html#stop">stop
</a></li>
2390 <ul class=
"events itemMembers">
2395 <li class=
"item" data-name=
"LuCI.request">
2396 <span class=
"title">
2397 <a href=
"LuCI.request.html">LuCI.request
</a>
2400 <ul class=
"members itemMembers">
2403 <ul class=
"typedefs itemMembers">
2405 <span class=
"subtitle">Typedefs
</span>
2407 <li data-name=
"LuCI.request.interceptorFn"><a href=
"LuCI.request.html#.interceptorFn">interceptorFn
</a></li>
2409 <li data-name=
"LuCI.request.RequestOptions"><a href=
"LuCI.request.html#.RequestOptions">RequestOptions
</a></li>
2412 <ul class=
"typedefs itemMembers">
2415 <ul class=
"methods itemMembers">
2417 <span class=
"subtitle">Methods
</span>
2419 <li data-name=
"LuCI.request#addInterceptor"><a href=
"LuCI.request.html#addInterceptor">addInterceptor
</a></li>
2421 <li data-name=
"LuCI.request#expandURL"><a href=
"LuCI.request.html#expandURL">expandURL
</a></li>
2423 <li data-name=
"LuCI.request#get"><a href=
"LuCI.request.html#get">get
</a></li>
2425 <li data-name=
"LuCI.request#post"><a href=
"LuCI.request.html#post">post
</a></li>
2427 <li data-name=
"LuCI.request#removeInterceptor"><a href=
"LuCI.request.html#removeInterceptor">removeInterceptor
</a></li>
2429 <li data-name=
"LuCI.request#request"><a href=
"LuCI.request.html#request">request
</a></li>
2432 <ul class=
"events itemMembers">
2437 <li class=
"item" data-name=
"LuCI.request.poll">
2438 <span class=
"title">
2439 <a href=
"LuCI.request.poll.html">LuCI.request.poll
</a>
2442 <ul class=
"members itemMembers">
2445 <ul class=
"typedefs itemMembers">
2447 <span class=
"subtitle">Typedefs
</span>
2449 <li data-name=
"LuCI.request.poll~callbackFn"><a href=
"LuCI.request.poll.html#~callbackFn">callbackFn
</a></li>
2452 <ul class=
"typedefs itemMembers">
2455 <ul class=
"methods itemMembers">
2457 <span class=
"subtitle">Methods
</span>
2459 <li data-name=
"LuCI.request.poll#active"><a href=
"LuCI.request.poll.html#active">active
</a></li>
2461 <li data-name=
"LuCI.request.poll#add"><a href=
"LuCI.request.poll.html#add">add
</a></li>
2463 <li data-name=
"LuCI.request.poll#remove"><a href=
"LuCI.request.poll.html#remove">remove
</a></li>
2465 <li data-name=
"LuCI.request.poll#start"><a href=
"LuCI.request.poll.html#start">start
</a></li>
2467 <li data-name=
"LuCI.request.poll#stop"><a href=
"LuCI.request.poll.html#stop">stop
</a></li>
2470 <ul class=
"events itemMembers">
2475 <li class=
"item" data-name=
"LuCI.response">
2476 <span class=
"title">
2477 <a href=
"LuCI.response.html">LuCI.response
</a>
2480 <ul class=
"members itemMembers">
2482 <span class=
"subtitle">Members
</span>
2484 <li data-name=
"LuCI.response#duration"><a href=
"LuCI.response.html#duration">duration
</a></li>
2486 <li data-name=
"LuCI.response#headers"><a href=
"LuCI.response.html#headers">headers
</a></li>
2488 <li data-name=
"LuCI.response#ok"><a href=
"LuCI.response.html#ok">ok
</a></li>
2490 <li data-name=
"LuCI.response#status"><a href=
"LuCI.response.html#status">status
</a></li>
2492 <li data-name=
"LuCI.response#statusText"><a href=
"LuCI.response.html#statusText">statusText
</a></li>
2494 <li data-name=
"LuCI.response#url"><a href=
"LuCI.response.html#url">url
</a></li>
2497 <ul class=
"typedefs itemMembers">
2500 <ul class=
"typedefs itemMembers">
2503 <ul class=
"methods itemMembers">
2505 <span class=
"subtitle">Methods
</span>
2507 <li data-name=
"LuCI.response#blob"><a href=
"LuCI.response.html#blob">blob
</a></li>
2509 <li data-name=
"LuCI.response#clone"><a href=
"LuCI.response.html#clone">clone
</a></li>
2511 <li data-name=
"LuCI.response#json"><a href=
"LuCI.response.html#json">json
</a></li>
2513 <li data-name=
"LuCI.response#text"><a href=
"LuCI.response.html#text">text
</a></li>
2516 <ul class=
"events itemMembers">
2521 <li class=
"item" data-name=
"LuCI.rpc">
2522 <span class=
"title">
2523 <a href=
"LuCI.rpc.html">LuCI.rpc
</a>
2526 <ul class=
"members itemMembers">
2529 <ul class=
"typedefs itemMembers">
2531 <span class=
"subtitle">Typedefs
</span>
2533 <li data-name=
"LuCI.rpc.DeclareOptions"><a href=
"LuCI.rpc.html#.DeclareOptions">DeclareOptions
</a></li>
2535 <li data-name=
"LuCI.rpc~filterFn"><a href=
"LuCI.rpc.html#~filterFn">filterFn
</a></li>
2537 <li data-name=
"LuCI.rpc~interceptorFn"><a href=
"LuCI.rpc.html#~interceptorFn">interceptorFn
</a></li>
2539 <li data-name=
"LuCI.rpc~invokeFn"><a href=
"LuCI.rpc.html#~invokeFn">invokeFn
</a></li>
2542 <ul class=
"typedefs itemMembers">
2545 <ul class=
"methods itemMembers">
2547 <span class=
"subtitle">Methods
</span>
2549 <li data-name=
"LuCI.rpc#addInterceptor"><a href=
"LuCI.rpc.html#addInterceptor">addInterceptor
</a></li>
2551 <li data-name=
"LuCI.rpc#declare"><a href=
"LuCI.rpc.html#declare">declare
</a></li>
2553 <li data-name=
"LuCI.rpc#getBaseURL"><a href=
"LuCI.rpc.html#getBaseURL">getBaseURL
</a></li>
2555 <li data-name=
"LuCI.rpc#getSessionID"><a href=
"LuCI.rpc.html#getSessionID">getSessionID
</a></li>
2557 <li data-name=
"LuCI.rpc#getStatusText"><a href=
"LuCI.rpc.html#getStatusText">getStatusText
</a></li>
2559 <li data-name=
"LuCI.rpc#list"><a href=
"LuCI.rpc.html#list">list
</a></li>
2561 <li data-name=
"LuCI.rpc#removeInterceptor"><a href=
"LuCI.rpc.html#removeInterceptor">removeInterceptor
</a></li>
2563 <li data-name=
"LuCI.rpc#setBaseURL"><a href=
"LuCI.rpc.html#setBaseURL">setBaseURL
</a></li>
2565 <li data-name=
"LuCI.rpc#setSessionID"><a href=
"LuCI.rpc.html#setSessionID">setSessionID
</a></li>
2568 <ul class=
"events itemMembers">
2573 <li class=
"item" data-name=
"LuCI.session">
2574 <span class=
"title">
2575 <a href=
"LuCI.session.html">LuCI.session
</a>
2578 <ul class=
"members itemMembers">
2581 <ul class=
"typedefs itemMembers">
2584 <ul class=
"typedefs itemMembers">
2587 <ul class=
"methods itemMembers">
2589 <span class=
"subtitle">Methods
</span>
2591 <li data-name=
"LuCI.session#getID"><a href=
"LuCI.session.html#getID">getID
</a></li>
2593 <li data-name=
"LuCI.session#getLocalData"><a href=
"LuCI.session.html#getLocalData">getLocalData
</a></li>
2595 <li data-name=
"LuCI.session#getToken"><a href=
"LuCI.session.html#getToken">getToken
</a></li>
2597 <li data-name=
"LuCI.session#setLocalData"><a href=
"LuCI.session.html#setLocalData">setLocalData
</a></li>
2600 <ul class=
"events itemMembers">
2605 <li class=
"item" data-name=
"LuCI.uci">
2606 <span class=
"title">
2607 <a href=
"LuCI.uci.html">LuCI.uci
</a>
2610 <ul class=
"members itemMembers">
2613 <ul class=
"typedefs itemMembers">
2615 <span class=
"subtitle">Typedefs
</span>
2617 <li data-name=
"LuCI.uci.ChangeRecord"><a href=
"LuCI.uci.html#.ChangeRecord">ChangeRecord
</a></li>
2619 <li data-name=
"LuCI.uci.SectionObject"><a href=
"LuCI.uci.html#.SectionObject">SectionObject
</a></li>
2621 <li data-name=
"LuCI.uci~sectionsFn"><a href=
"LuCI.uci.html#~sectionsFn">sectionsFn
</a></li>
2624 <ul class=
"typedefs itemMembers">
2627 <ul class=
"methods itemMembers">
2629 <span class=
"subtitle">Methods
</span>
2631 <li data-name=
"LuCI.uci#add"><a href=
"LuCI.uci.html#add">add
</a></li>
2633 <li data-name=
"LuCI.uci#apply"><a href=
"LuCI.uci.html#apply">apply
</a></li>
2635 <li data-name=
"LuCI.uci#changes"><a href=
"LuCI.uci.html#changes">changes
</a></li>
2637 <li data-name=
"LuCI.uci#createSID"><a href=
"LuCI.uci.html#createSID">createSID
</a></li>
2639 <li data-name=
"LuCI.uci#get"><a href=
"LuCI.uci.html#get">get
</a></li>
2641 <li data-name=
"LuCI.uci#get_first"><a href=
"LuCI.uci.html#get_first">get_first
</a></li>
2643 <li data-name=
"LuCI.uci#load"><a href=
"LuCI.uci.html#load">load
</a></li>
2645 <li data-name=
"LuCI.uci#move"><a href=
"LuCI.uci.html#move">move
</a></li>
2647 <li data-name=
"LuCI.uci#remove"><a href=
"LuCI.uci.html#remove">remove
</a></li>
2649 <li data-name=
"LuCI.uci#resolveSID"><a href=
"LuCI.uci.html#resolveSID">resolveSID
</a></li>
2651 <li data-name=
"LuCI.uci#save"><a href=
"LuCI.uci.html#save">save
</a></li>
2653 <li data-name=
"LuCI.uci#sections"><a href=
"LuCI.uci.html#sections">sections
</a></li>
2655 <li data-name=
"LuCI.uci#set"><a href=
"LuCI.uci.html#set">set
</a></li>
2657 <li data-name=
"LuCI.uci#set_first"><a href=
"LuCI.uci.html#set_first">set_first
</a></li>
2659 <li data-name=
"LuCI.uci#unload"><a href=
"LuCI.uci.html#unload">unload
</a></li>
2661 <li data-name=
"LuCI.uci#unset"><a href=
"LuCI.uci.html#unset">unset
</a></li>
2663 <li data-name=
"LuCI.uci#unset_first"><a href=
"LuCI.uci.html#unset_first">unset_first
</a></li>
2666 <ul class=
"events itemMembers">
2671 <li class=
"item" data-name=
"LuCI.ui">
2672 <span class=
"title">
2673 <a href=
"LuCI.ui.html">LuCI.ui
</a>
2676 <ul class=
"members itemMembers">
2679 <ul class=
"typedefs itemMembers">
2681 <span class=
"subtitle">Typedefs
</span>
2683 <li data-name=
"LuCI.ui.FileUploadReply"><a href=
"LuCI.ui.html#.FileUploadReply">FileUploadReply
</a></li>
2686 <ul class=
"typedefs itemMembers">
2689 <ul class=
"methods itemMembers">
2691 <span class=
"subtitle">Methods
</span>
2693 <li data-name=
"LuCI.ui#addNotification"><a href=
"LuCI.ui.html#addNotification">addNotification
</a></li>
2695 <li data-name=
"LuCI.ui#addValidator"><a href=
"LuCI.ui.html#addValidator">addValidator
</a></li>
2697 <li data-name=
"LuCI.ui#awaitReconnect"><a href=
"LuCI.ui.html#awaitReconnect">awaitReconnect
</a></li>
2699 <li data-name=
"LuCI.ui#createHandlerFn"><a href=
"LuCI.ui.html#createHandlerFn">createHandlerFn
</a></li>
2701 <li data-name=
"LuCI.ui#hideIndicator"><a href=
"LuCI.ui.html#hideIndicator">hideIndicator
</a></li>
2703 <li data-name=
"LuCI.ui#hideModal"><a href=
"LuCI.ui.html#hideModal">hideModal
</a></li>
2705 <li data-name=
"LuCI.ui#instantiateView"><a href=
"LuCI.ui.html#instantiateView">instantiateView
</a></li>
2707 <li data-name=
"LuCI.ui#itemlist"><a href=
"LuCI.ui.html#itemlist">itemlist
</a></li>
2709 <li data-name=
"LuCI.ui#pingDevice"><a href=
"LuCI.ui.html#pingDevice">pingDevice
</a></li>
2711 <li data-name=
"LuCI.ui#showIndicator"><a href=
"LuCI.ui.html#showIndicator">showIndicator
</a></li>
2713 <li data-name=
"LuCI.ui#showModal"><a href=
"LuCI.ui.html#showModal">showModal
</a></li>
2715 <li data-name=
"LuCI.ui#uploadFile"><a href=
"LuCI.ui.html#uploadFile">uploadFile
</a></li>
2718 <ul class=
"events itemMembers">
2723 <li class=
"item" data-name=
"LuCI.ui.AbstractElement">
2724 <span class=
"title">
2725 <a href=
"LuCI.ui.AbstractElement.html">LuCI.ui.AbstractElement
</a>
2728 <ul class=
"members itemMembers">
2731 <ul class=
"typedefs itemMembers">
2733 <span class=
"subtitle">Typedefs
</span>
2735 <li data-name=
"LuCI.ui.AbstractElement.InitOptions"><a href=
"LuCI.ui.AbstractElement.html#.InitOptions">InitOptions
</a></li>
2738 <ul class=
"typedefs itemMembers">
2741 <ul class=
"methods itemMembers">
2743 <span class=
"subtitle">Methods
</span>
2745 <li data-name=
"LuCI.ui.AbstractElement#getValue"><a href=
"LuCI.ui.AbstractElement.html#getValue">getValue
</a></li>
2747 <li data-name=
"LuCI.ui.AbstractElement#isChanged"><a href=
"LuCI.ui.AbstractElement.html#isChanged">isChanged
</a></li>
2749 <li data-name=
"LuCI.ui.AbstractElement#isValid"><a href=
"LuCI.ui.AbstractElement.html#isValid">isValid
</a></li>
2751 <li data-name=
"LuCI.ui.AbstractElement#registerEvents"><a href=
"LuCI.ui.AbstractElement.html#registerEvents">registerEvents
</a></li>
2753 <li data-name=
"LuCI.ui.AbstractElement#render"><a href=
"LuCI.ui.AbstractElement.html#render">render
</a></li>
2755 <li data-name=
"LuCI.ui.AbstractElement#setChangeEvents"><a href=
"LuCI.ui.AbstractElement.html#setChangeEvents">setChangeEvents
</a></li>
2757 <li data-name=
"LuCI.ui.AbstractElement#setPlaceholder"><a href=
"LuCI.ui.AbstractElement.html#setPlaceholder">setPlaceholder
</a></li>
2759 <li data-name=
"LuCI.ui.AbstractElement#setUpdateEvents"><a href=
"LuCI.ui.AbstractElement.html#setUpdateEvents">setUpdateEvents
</a></li>
2761 <li data-name=
"LuCI.ui.AbstractElement#setValue"><a href=
"LuCI.ui.AbstractElement.html#setValue">setValue
</a></li>
2763 <li data-name=
"LuCI.ui.AbstractElement#triggerValidation"><a href=
"LuCI.ui.AbstractElement.html#triggerValidation">triggerValidation
</a></li>
2766 <ul class=
"events itemMembers">
2771 <li class=
"item" data-name=
"LuCI.ui.changes">
2772 <span class=
"title">
2773 <a href=
"LuCI.ui.changes.html">LuCI.ui.changes
</a>
2776 <ul class=
"members itemMembers">
2779 <ul class=
"typedefs itemMembers">
2782 <ul class=
"typedefs itemMembers">
2785 <ul class=
"methods itemMembers">
2787 <span class=
"subtitle">Methods
</span>
2789 <li data-name=
"LuCI.ui.changes#apply"><a href=
"LuCI.ui.changes.html#apply">apply
</a></li>
2791 <li data-name=
"LuCI.ui.changes#displayChanges"><a href=
"LuCI.ui.changes.html#displayChanges">displayChanges
</a></li>
2793 <li data-name=
"LuCI.ui.changes#renderChangeIndicator"><a href=
"LuCI.ui.changes.html#renderChangeIndicator">renderChangeIndicator
</a></li>
2795 <li data-name=
"LuCI.ui.changes#revert"><a href=
"LuCI.ui.changes.html#revert">revert
</a></li>
2797 <li data-name=
"LuCI.ui.changes#setIndicator"><a href=
"LuCI.ui.changes.html#setIndicator">setIndicator
</a></li>
2800 <ul class=
"events itemMembers">
2805 <li class=
"item" data-name=
"LuCI.ui.Checkbox">
2806 <span class=
"title">
2807 <a href=
"LuCI.ui.Checkbox.html">LuCI.ui.Checkbox
</a>
2810 <ul class=
"members itemMembers">
2813 <ul class=
"typedefs itemMembers">
2815 <span class=
"subtitle">Typedefs
</span>
2817 <li data-name=
"LuCI.ui.Checkbox.InitOptions"><a href=
"LuCI.ui.Checkbox.html#.InitOptions">InitOptions
</a></li>
2820 <ul class=
"typedefs itemMembers">
2823 <ul class=
"methods itemMembers">
2825 <span class=
"subtitle">Methods
</span>
2827 <li data-name=
"LuCI.ui.Checkbox#getValue"><a href=
"LuCI.ui.Checkbox.html#getValue">getValue
</a></li>
2829 <li data-name=
"LuCI.ui.Checkbox#isChanged"><a href=
"LuCI.ui.Checkbox.html#isChanged">isChanged
</a></li>
2831 <li data-name=
"LuCI.ui.Checkbox#isChecked"><a href=
"LuCI.ui.Checkbox.html#isChecked">isChecked
</a></li>
2833 <li data-name=
"LuCI.ui.Checkbox#isValid"><a href=
"LuCI.ui.Checkbox.html#isValid">isValid
</a></li>
2835 <li data-name=
"LuCI.ui.Checkbox#registerEvents"><a href=
"LuCI.ui.Checkbox.html#registerEvents">registerEvents
</a></li>
2837 <li data-name=
"LuCI.ui.Checkbox#render"><a href=
"LuCI.ui.Checkbox.html#render">render
</a></li>
2839 <li data-name=
"LuCI.ui.Checkbox#setChangeEvents"><a href=
"LuCI.ui.Checkbox.html#setChangeEvents">setChangeEvents
</a></li>
2841 <li data-name=
"LuCI.ui.Checkbox#setPlaceholder"><a href=
"LuCI.ui.Checkbox.html#setPlaceholder">setPlaceholder
</a></li>
2843 <li data-name=
"LuCI.ui.Checkbox#setUpdateEvents"><a href=
"LuCI.ui.Checkbox.html#setUpdateEvents">setUpdateEvents
</a></li>
2845 <li data-name=
"LuCI.ui.Checkbox#setValue"><a href=
"LuCI.ui.Checkbox.html#setValue">setValue
</a></li>
2847 <li data-name=
"LuCI.ui.Checkbox#triggerValidation"><a href=
"LuCI.ui.Checkbox.html#triggerValidation">triggerValidation
</a></li>
2850 <ul class=
"events itemMembers">
2855 <li class=
"item" data-name=
"LuCI.ui.Combobox">
2856 <span class=
"title">
2857 <a href=
"LuCI.ui.Combobox.html">LuCI.ui.Combobox
</a>
2860 <ul class=
"members itemMembers">
2863 <ul class=
"typedefs itemMembers">
2865 <span class=
"subtitle">Typedefs
</span>
2867 <li data-name=
"LuCI.ui.Combobox.InitOptions"><a href=
"LuCI.ui.Combobox.html#.InitOptions">InitOptions
</a></li>
2870 <ul class=
"typedefs itemMembers">
2873 <ul class=
"methods itemMembers">
2875 <span class=
"subtitle">Methods
</span>
2877 <li data-name=
"LuCI.ui.Combobox#addChoices"><a href=
"LuCI.ui.Combobox.html#addChoices">addChoices
</a></li>
2879 <li data-name=
"LuCI.ui.Combobox#clearChoices"><a href=
"LuCI.ui.Combobox.html#clearChoices">clearChoices
</a></li>
2881 <li data-name=
"LuCI.ui.Combobox#closeAllDropdowns"><a href=
"LuCI.ui.Combobox.html#closeAllDropdowns">closeAllDropdowns
</a></li>
2883 <li data-name=
"LuCI.ui.Combobox#isChanged"><a href=
"LuCI.ui.Combobox.html#isChanged">isChanged
</a></li>
2885 <li data-name=
"LuCI.ui.Combobox#isValid"><a href=
"LuCI.ui.Combobox.html#isValid">isValid
</a></li>
2887 <li data-name=
"LuCI.ui.Combobox#registerEvents"><a href=
"LuCI.ui.Combobox.html#registerEvents">registerEvents
</a></li>
2889 <li data-name=
"LuCI.ui.Combobox#setChangeEvents"><a href=
"LuCI.ui.Combobox.html#setChangeEvents">setChangeEvents
</a></li>
2891 <li data-name=
"LuCI.ui.Combobox#setPlaceholder"><a href=
"LuCI.ui.Combobox.html#setPlaceholder">setPlaceholder
</a></li>
2893 <li data-name=
"LuCI.ui.Combobox#setUpdateEvents"><a href=
"LuCI.ui.Combobox.html#setUpdateEvents">setUpdateEvents
</a></li>
2895 <li data-name=
"LuCI.ui.Combobox#triggerValidation"><a href=
"LuCI.ui.Combobox.html#triggerValidation">triggerValidation
</a></li>
2898 <ul class=
"events itemMembers">
2903 <li class=
"item" data-name=
"LuCI.ui.ComboButton">
2904 <span class=
"title">
2905 <a href=
"LuCI.ui.ComboButton.html">LuCI.ui.ComboButton
</a>
2908 <ul class=
"members itemMembers">
2911 <ul class=
"typedefs itemMembers">
2913 <span class=
"subtitle">Typedefs
</span>
2915 <li data-name=
"LuCI.ui.ComboButton.InitOptions"><a href=
"LuCI.ui.ComboButton.html#.InitOptions">InitOptions
</a></li>
2918 <ul class=
"typedefs itemMembers">
2921 <ul class=
"methods itemMembers">
2923 <span class=
"subtitle">Methods
</span>
2925 <li data-name=
"LuCI.ui.ComboButton#addChoices"><a href=
"LuCI.ui.ComboButton.html#addChoices">addChoices
</a></li>
2927 <li data-name=
"LuCI.ui.ComboButton#clearChoices"><a href=
"LuCI.ui.ComboButton.html#clearChoices">clearChoices
</a></li>
2929 <li data-name=
"LuCI.ui.ComboButton#closeAllDropdowns"><a href=
"LuCI.ui.ComboButton.html#closeAllDropdowns">closeAllDropdowns
</a></li>
2931 <li data-name=
"LuCI.ui.ComboButton#isChanged"><a href=
"LuCI.ui.ComboButton.html#isChanged">isChanged
</a></li>
2933 <li data-name=
"LuCI.ui.ComboButton#isValid"><a href=
"LuCI.ui.ComboButton.html#isValid">isValid
</a></li>
2935 <li data-name=
"LuCI.ui.ComboButton#registerEvents"><a href=
"LuCI.ui.ComboButton.html#registerEvents">registerEvents
</a></li>
2937 <li data-name=
"LuCI.ui.ComboButton#setChangeEvents"><a href=
"LuCI.ui.ComboButton.html#setChangeEvents">setChangeEvents
</a></li>
2939 <li data-name=
"LuCI.ui.ComboButton#setPlaceholder"><a href=
"LuCI.ui.ComboButton.html#setPlaceholder">setPlaceholder
</a></li>
2941 <li data-name=
"LuCI.ui.ComboButton#setUpdateEvents"><a href=
"LuCI.ui.ComboButton.html#setUpdateEvents">setUpdateEvents
</a></li>
2943 <li data-name=
"LuCI.ui.ComboButton#triggerValidation"><a href=
"LuCI.ui.ComboButton.html#triggerValidation">triggerValidation
</a></li>
2946 <ul class=
"events itemMembers">
2951 <li class=
"item" data-name=
"LuCI.ui.Dropdown">
2952 <span class=
"title">
2953 <a href=
"LuCI.ui.Dropdown.html">LuCI.ui.Dropdown
</a>
2956 <ul class=
"members itemMembers">
2959 <ul class=
"typedefs itemMembers">
2961 <span class=
"subtitle">Typedefs
</span>
2963 <li data-name=
"LuCI.ui.Dropdown.InitOptions"><a href=
"LuCI.ui.Dropdown.html#.InitOptions">InitOptions
</a></li>
2966 <ul class=
"typedefs itemMembers">
2969 <ul class=
"methods itemMembers">
2971 <span class=
"subtitle">Methods
</span>
2973 <li data-name=
"LuCI.ui.Dropdown#addChoices"><a href=
"LuCI.ui.Dropdown.html#addChoices">addChoices
</a></li>
2975 <li data-name=
"LuCI.ui.Dropdown#clearChoices"><a href=
"LuCI.ui.Dropdown.html#clearChoices">clearChoices
</a></li>
2977 <li data-name=
"LuCI.ui.Dropdown#closeAllDropdowns"><a href=
"LuCI.ui.Dropdown.html#closeAllDropdowns">closeAllDropdowns
</a></li>
2979 <li data-name=
"LuCI.ui.Dropdown#getValue"><a href=
"LuCI.ui.Dropdown.html#getValue">getValue
</a></li>
2981 <li data-name=
"LuCI.ui.Dropdown#isChanged"><a href=
"LuCI.ui.Dropdown.html#isChanged">isChanged
</a></li>
2983 <li data-name=
"LuCI.ui.Dropdown#isValid"><a href=
"LuCI.ui.Dropdown.html#isValid">isValid
</a></li>
2985 <li data-name=
"LuCI.ui.Dropdown#registerEvents"><a href=
"LuCI.ui.Dropdown.html#registerEvents">registerEvents
</a></li>
2987 <li data-name=
"LuCI.ui.Dropdown#render"><a href=
"LuCI.ui.Dropdown.html#render">render
</a></li>
2989 <li data-name=
"LuCI.ui.Dropdown#setChangeEvents"><a href=
"LuCI.ui.Dropdown.html#setChangeEvents">setChangeEvents
</a></li>
2991 <li data-name=
"LuCI.ui.Dropdown#setPlaceholder"><a href=
"LuCI.ui.Dropdown.html#setPlaceholder">setPlaceholder
</a></li>
2993 <li data-name=
"LuCI.ui.Dropdown#setUpdateEvents"><a href=
"LuCI.ui.Dropdown.html#setUpdateEvents">setUpdateEvents
</a></li>
2995 <li data-name=
"LuCI.ui.Dropdown#setValue"><a href=
"LuCI.ui.Dropdown.html#setValue">setValue
</a></li>
2997 <li data-name=
"LuCI.ui.Dropdown#triggerValidation"><a href=
"LuCI.ui.Dropdown.html#triggerValidation">triggerValidation
</a></li>
3000 <ul class=
"events itemMembers">
3005 <li class=
"item" data-name=
"LuCI.ui.DynamicList">
3006 <span class=
"title">
3007 <a href=
"LuCI.ui.DynamicList.html">LuCI.ui.DynamicList
</a>
3010 <ul class=
"members itemMembers">
3013 <ul class=
"typedefs itemMembers">
3015 <span class=
"subtitle">Typedefs
</span>
3017 <li data-name=
"LuCI.ui.DynamicList.InitOptions"><a href=
"LuCI.ui.DynamicList.html#.InitOptions">InitOptions
</a></li>
3020 <ul class=
"typedefs itemMembers">
3023 <ul class=
"methods itemMembers">
3025 <span class=
"subtitle">Methods
</span>
3027 <li data-name=
"LuCI.ui.DynamicList#addChoices"><a href=
"LuCI.ui.DynamicList.html#addChoices">addChoices
</a></li>
3029 <li data-name=
"LuCI.ui.DynamicList#clearChoices"><a href=
"LuCI.ui.DynamicList.html#clearChoices">clearChoices
</a></li>
3031 <li data-name=
"LuCI.ui.DynamicList#getValue"><a href=
"LuCI.ui.DynamicList.html#getValue">getValue
</a></li>
3033 <li data-name=
"LuCI.ui.DynamicList#isChanged"><a href=
"LuCI.ui.DynamicList.html#isChanged">isChanged
</a></li>
3035 <li data-name=
"LuCI.ui.DynamicList#isValid"><a href=
"LuCI.ui.DynamicList.html#isValid">isValid
</a></li>
3037 <li data-name=
"LuCI.ui.DynamicList#registerEvents"><a href=
"LuCI.ui.DynamicList.html#registerEvents">registerEvents
</a></li>
3039 <li data-name=
"LuCI.ui.DynamicList#render"><a href=
"LuCI.ui.DynamicList.html#render">render
</a></li>
3041 <li data-name=
"LuCI.ui.DynamicList#setChangeEvents"><a href=
"LuCI.ui.DynamicList.html#setChangeEvents">setChangeEvents
</a></li>
3043 <li data-name=
"LuCI.ui.DynamicList#setPlaceholder"><a href=
"LuCI.ui.DynamicList.html#setPlaceholder">setPlaceholder
</a></li>
3045 <li data-name=
"LuCI.ui.DynamicList#setUpdateEvents"><a href=
"LuCI.ui.DynamicList.html#setUpdateEvents">setUpdateEvents
</a></li>
3047 <li data-name=
"LuCI.ui.DynamicList#setValue"><a href=
"LuCI.ui.DynamicList.html#setValue">setValue
</a></li>
3049 <li data-name=
"LuCI.ui.DynamicList#triggerValidation"><a href=
"LuCI.ui.DynamicList.html#triggerValidation">triggerValidation
</a></li>
3052 <ul class=
"events itemMembers">
3057 <li class=
"item" data-name=
"LuCI.ui.FileUpload">
3058 <span class=
"title">
3059 <a href=
"LuCI.ui.FileUpload.html">LuCI.ui.FileUpload
</a>
3062 <ul class=
"members itemMembers">
3065 <ul class=
"typedefs itemMembers">
3067 <span class=
"subtitle">Typedefs
</span>
3069 <li data-name=
"LuCI.ui.FileUpload.InitOptions"><a href=
"LuCI.ui.FileUpload.html#.InitOptions">InitOptions
</a></li>
3072 <ul class=
"typedefs itemMembers">
3075 <ul class=
"methods itemMembers">
3077 <span class=
"subtitle">Methods
</span>
3079 <li data-name=
"LuCI.ui.FileUpload#getValue"><a href=
"LuCI.ui.FileUpload.html#getValue">getValue
</a></li>
3081 <li data-name=
"LuCI.ui.FileUpload#isChanged"><a href=
"LuCI.ui.FileUpload.html#isChanged">isChanged
</a></li>
3083 <li data-name=
"LuCI.ui.FileUpload#isValid"><a href=
"LuCI.ui.FileUpload.html#isValid">isValid
</a></li>
3085 <li data-name=
"LuCI.ui.FileUpload#registerEvents"><a href=
"LuCI.ui.FileUpload.html#registerEvents">registerEvents
</a></li>
3087 <li data-name=
"LuCI.ui.FileUpload#render"><a href=
"LuCI.ui.FileUpload.html#render">render
</a></li>
3089 <li data-name=
"LuCI.ui.FileUpload#setChangeEvents"><a href=
"LuCI.ui.FileUpload.html#setChangeEvents">setChangeEvents
</a></li>
3091 <li data-name=
"LuCI.ui.FileUpload#setPlaceholder"><a href=
"LuCI.ui.FileUpload.html#setPlaceholder">setPlaceholder
</a></li>
3093 <li data-name=
"LuCI.ui.FileUpload#setUpdateEvents"><a href=
"LuCI.ui.FileUpload.html#setUpdateEvents">setUpdateEvents
</a></li>
3095 <li data-name=
"LuCI.ui.FileUpload#setValue"><a href=
"LuCI.ui.FileUpload.html#setValue">setValue
</a></li>
3097 <li data-name=
"LuCI.ui.FileUpload#triggerValidation"><a href=
"LuCI.ui.FileUpload.html#triggerValidation">triggerValidation
</a></li>
3100 <ul class=
"events itemMembers">
3105 <li class=
"item" data-name=
"LuCI.ui.Hiddenfield">
3106 <span class=
"title">
3107 <a href=
"LuCI.ui.Hiddenfield.html">LuCI.ui.Hiddenfield
</a>
3110 <ul class=
"members itemMembers">
3113 <ul class=
"typedefs itemMembers">
3116 <ul class=
"typedefs itemMembers">
3119 <ul class=
"methods itemMembers">
3121 <span class=
"subtitle">Methods
</span>
3123 <li data-name=
"LuCI.ui.Hiddenfield#getValue"><a href=
"LuCI.ui.Hiddenfield.html#getValue">getValue
</a></li>
3125 <li data-name=
"LuCI.ui.Hiddenfield#isChanged"><a href=
"LuCI.ui.Hiddenfield.html#isChanged">isChanged
</a></li>
3127 <li data-name=
"LuCI.ui.Hiddenfield#isValid"><a href=
"LuCI.ui.Hiddenfield.html#isValid">isValid
</a></li>
3129 <li data-name=
"LuCI.ui.Hiddenfield#registerEvents"><a href=
"LuCI.ui.Hiddenfield.html#registerEvents">registerEvents
</a></li>
3131 <li data-name=
"LuCI.ui.Hiddenfield#render"><a href=
"LuCI.ui.Hiddenfield.html#render">render
</a></li>
3133 <li data-name=
"LuCI.ui.Hiddenfield#setChangeEvents"><a href=
"LuCI.ui.Hiddenfield.html#setChangeEvents">setChangeEvents
</a></li>
3135 <li data-name=
"LuCI.ui.Hiddenfield#setPlaceholder"><a href=
"LuCI.ui.Hiddenfield.html#setPlaceholder">setPlaceholder
</a></li>
3137 <li data-name=
"LuCI.ui.Hiddenfield#setUpdateEvents"><a href=
"LuCI.ui.Hiddenfield.html#setUpdateEvents">setUpdateEvents
</a></li>
3139 <li data-name=
"LuCI.ui.Hiddenfield#setValue"><a href=
"LuCI.ui.Hiddenfield.html#setValue">setValue
</a></li>
3141 <li data-name=
"LuCI.ui.Hiddenfield#triggerValidation"><a href=
"LuCI.ui.Hiddenfield.html#triggerValidation">triggerValidation
</a></li>
3144 <ul class=
"events itemMembers">
3149 <li class=
"item" data-name=
"LuCI.ui.menu">
3150 <span class=
"title">
3151 <a href=
"LuCI.ui.menu.html">LuCI.ui.menu
</a>
3154 <ul class=
"members itemMembers">
3157 <ul class=
"typedefs itemMembers">
3159 <span class=
"subtitle">Typedefs
</span>
3161 <li data-name=
"LuCI.ui.menu.MenuNode"><a href=
"LuCI.ui.menu.html#.MenuNode">MenuNode
</a></li>
3164 <ul class=
"typedefs itemMembers">
3167 <ul class=
"methods itemMembers">
3169 <span class=
"subtitle">Methods
</span>
3171 <li data-name=
"LuCI.ui.menu#flushCache"><a href=
"LuCI.ui.menu.html#flushCache">flushCache
</a></li>
3173 <li data-name=
"LuCI.ui.menu#getChildren"><a href=
"LuCI.ui.menu.html#getChildren">getChildren
</a></li>
3175 <li data-name=
"LuCI.ui.menu#load"><a href=
"LuCI.ui.menu.html#load">load
</a></li>
3178 <ul class=
"events itemMembers">
3183 <li class=
"item" data-name=
"LuCI.ui.Select">
3184 <span class=
"title">
3185 <a href=
"LuCI.ui.Select.html">LuCI.ui.Select
</a>
3188 <ul class=
"members itemMembers">
3191 <ul class=
"typedefs itemMembers">
3193 <span class=
"subtitle">Typedefs
</span>
3195 <li data-name=
"LuCI.ui.Select.InitOptions"><a href=
"LuCI.ui.Select.html#.InitOptions">InitOptions
</a></li>
3198 <ul class=
"typedefs itemMembers">
3201 <ul class=
"methods itemMembers">
3203 <span class=
"subtitle">Methods
</span>
3205 <li data-name=
"LuCI.ui.Select#getValue"><a href=
"LuCI.ui.Select.html#getValue">getValue
</a></li>
3207 <li data-name=
"LuCI.ui.Select#isChanged"><a href=
"LuCI.ui.Select.html#isChanged">isChanged
</a></li>
3209 <li data-name=
"LuCI.ui.Select#isValid"><a href=
"LuCI.ui.Select.html#isValid">isValid
</a></li>
3211 <li data-name=
"LuCI.ui.Select#registerEvents"><a href=
"LuCI.ui.Select.html#registerEvents">registerEvents
</a></li>
3213 <li data-name=
"LuCI.ui.Select#render"><a href=
"LuCI.ui.Select.html#render">render
</a></li>
3215 <li data-name=
"LuCI.ui.Select#setChangeEvents"><a href=
"LuCI.ui.Select.html#setChangeEvents">setChangeEvents
</a></li>
3217 <li data-name=
"LuCI.ui.Select#setPlaceholder"><a href=
"LuCI.ui.Select.html#setPlaceholder">setPlaceholder
</a></li>
3219 <li data-name=
"LuCI.ui.Select#setUpdateEvents"><a href=
"LuCI.ui.Select.html#setUpdateEvents">setUpdateEvents
</a></li>
3221 <li data-name=
"LuCI.ui.Select#setValue"><a href=
"LuCI.ui.Select.html#setValue">setValue
</a></li>
3223 <li data-name=
"LuCI.ui.Select#triggerValidation"><a href=
"LuCI.ui.Select.html#triggerValidation">triggerValidation
</a></li>
3226 <ul class=
"events itemMembers">
3231 <li class=
"item" data-name=
"LuCI.ui.tabs">
3232 <span class=
"title">
3233 <a href=
"LuCI.ui.tabs.html">LuCI.ui.tabs
</a>
3236 <ul class=
"members itemMembers">
3239 <ul class=
"typedefs itemMembers">
3242 <ul class=
"typedefs itemMembers">
3245 <ul class=
"methods itemMembers">
3247 <span class=
"subtitle">Methods
</span>
3249 <li data-name=
"LuCI.ui.tabs#initTabGroup"><a href=
"LuCI.ui.tabs.html#initTabGroup">initTabGroup
</a></li>
3251 <li data-name=
"LuCI.ui.tabs#isEmptyPane"><a href=
"LuCI.ui.tabs.html#isEmptyPane">isEmptyPane
</a></li>
3254 <ul class=
"events itemMembers">
3259 <li class=
"item" data-name=
"LuCI.ui.Textarea">
3260 <span class=
"title">
3261 <a href=
"LuCI.ui.Textarea.html">LuCI.ui.Textarea
</a>
3264 <ul class=
"members itemMembers">
3267 <ul class=
"typedefs itemMembers">
3269 <span class=
"subtitle">Typedefs
</span>
3271 <li data-name=
"LuCI.ui.Textarea.InitOptions"><a href=
"LuCI.ui.Textarea.html#.InitOptions">InitOptions
</a></li>
3274 <ul class=
"typedefs itemMembers">
3277 <ul class=
"methods itemMembers">
3279 <span class=
"subtitle">Methods
</span>
3281 <li data-name=
"LuCI.ui.Textarea#getValue"><a href=
"LuCI.ui.Textarea.html#getValue">getValue
</a></li>
3283 <li data-name=
"LuCI.ui.Textarea#isChanged"><a href=
"LuCI.ui.Textarea.html#isChanged">isChanged
</a></li>
3285 <li data-name=
"LuCI.ui.Textarea#isValid"><a href=
"LuCI.ui.Textarea.html#isValid">isValid
</a></li>
3287 <li data-name=
"LuCI.ui.Textarea#registerEvents"><a href=
"LuCI.ui.Textarea.html#registerEvents">registerEvents
</a></li>
3289 <li data-name=
"LuCI.ui.Textarea#render"><a href=
"LuCI.ui.Textarea.html#render">render
</a></li>
3291 <li data-name=
"LuCI.ui.Textarea#setChangeEvents"><a href=
"LuCI.ui.Textarea.html#setChangeEvents">setChangeEvents
</a></li>
3293 <li data-name=
"LuCI.ui.Textarea#setPlaceholder"><a href=
"LuCI.ui.Textarea.html#setPlaceholder">setPlaceholder
</a></li>
3295 <li data-name=
"LuCI.ui.Textarea#setUpdateEvents"><a href=
"LuCI.ui.Textarea.html#setUpdateEvents">setUpdateEvents
</a></li>
3297 <li data-name=
"LuCI.ui.Textarea#setValue"><a href=
"LuCI.ui.Textarea.html#setValue">setValue
</a></li>
3299 <li data-name=
"LuCI.ui.Textarea#triggerValidation"><a href=
"LuCI.ui.Textarea.html#triggerValidation">triggerValidation
</a></li>
3302 <ul class=
"events itemMembers">
3307 <li class=
"item" data-name=
"LuCI.ui.Textfield">
3308 <span class=
"title">
3309 <a href=
"LuCI.ui.Textfield.html">LuCI.ui.Textfield
</a>
3312 <ul class=
"members itemMembers">
3315 <ul class=
"typedefs itemMembers">
3317 <span class=
"subtitle">Typedefs
</span>
3319 <li data-name=
"LuCI.ui.Textfield.InitOptions"><a href=
"LuCI.ui.Textfield.html#.InitOptions">InitOptions
</a></li>
3322 <ul class=
"typedefs itemMembers">
3325 <ul class=
"methods itemMembers">
3327 <span class=
"subtitle">Methods
</span>
3329 <li data-name=
"LuCI.ui.Textfield#getValue"><a href=
"LuCI.ui.Textfield.html#getValue">getValue
</a></li>
3331 <li data-name=
"LuCI.ui.Textfield#isChanged"><a href=
"LuCI.ui.Textfield.html#isChanged">isChanged
</a></li>
3333 <li data-name=
"LuCI.ui.Textfield#isValid"><a href=
"LuCI.ui.Textfield.html#isValid">isValid
</a></li>
3335 <li data-name=
"LuCI.ui.Textfield#registerEvents"><a href=
"LuCI.ui.Textfield.html#registerEvents">registerEvents
</a></li>
3337 <li data-name=
"LuCI.ui.Textfield#render"><a href=
"LuCI.ui.Textfield.html#render">render
</a></li>
3339 <li data-name=
"LuCI.ui.Textfield#setChangeEvents"><a href=
"LuCI.ui.Textfield.html#setChangeEvents">setChangeEvents
</a></li>
3341 <li data-name=
"LuCI.ui.Textfield#setPlaceholder"><a href=
"LuCI.ui.Textfield.html#setPlaceholder">setPlaceholder
</a></li>
3343 <li data-name=
"LuCI.ui.Textfield#setUpdateEvents"><a href=
"LuCI.ui.Textfield.html#setUpdateEvents">setUpdateEvents
</a></li>
3345 <li data-name=
"LuCI.ui.Textfield#setValue"><a href=
"LuCI.ui.Textfield.html#setValue">setValue
</a></li>
3347 <li data-name=
"LuCI.ui.Textfield#triggerValidation"><a href=
"LuCI.ui.Textfield.html#triggerValidation">triggerValidation
</a></li>
3350 <ul class=
"events itemMembers">
3355 <li class=
"item" data-name=
"LuCI.view">
3356 <span class=
"title">
3357 <a href=
"LuCI.view.html">LuCI.view
</a>
3360 <ul class=
"members itemMembers">
3363 <ul class=
"typedefs itemMembers">
3366 <ul class=
"typedefs itemMembers">
3369 <ul class=
"methods itemMembers">
3371 <span class=
"subtitle">Methods
</span>
3373 <li data-name=
"LuCI.view#addFooter"><a href=
"LuCI.view.html#addFooter">addFooter
</a></li>
3375 <li data-name=
"LuCI.view#handleReset"><a href=
"LuCI.view.html#handleReset">handleReset
</a></li>
3377 <li data-name=
"LuCI.view#handleSave"><a href=
"LuCI.view.html#handleSave">handleSave
</a></li>
3379 <li data-name=
"LuCI.view#handleSaveApply"><a href=
"LuCI.view.html#handleSaveApply">handleSaveApply
</a></li>
3381 <li data-name=
"LuCI.view#load"><a href=
"LuCI.view.html#load">load
</a></li>
3383 <li data-name=
"LuCI.view#render"><a href=
"LuCI.view.html#render">render
</a></li>
3386 <ul class=
"events itemMembers">
3391 <li class=
"item" data-name=
"LuCI.xhr">
3392 <span class=
"title">
3393 <a href=
"LuCI.xhr.html">LuCI.xhr
</a>
3396 <ul class=
"members itemMembers">
3399 <ul class=
"typedefs itemMembers">
3402 <ul class=
"typedefs itemMembers">
3405 <ul class=
"methods itemMembers">
3407 <span class=
"subtitle">Methods
</span>
3409 <li data-name=
"LuCI.xhr#abort"><a href=
"LuCI.xhr.html#abort">abort
</a></li>
3411 <li data-name=
"LuCI.xhr#busy"><a href=
"LuCI.xhr.html#busy">busy
</a></li>
3413 <li data-name=
"LuCI.xhr#cancel"><a href=
"LuCI.xhr.html#cancel">cancel
</a></li>
3415 <li data-name=
"LuCI.xhr#get"><a href=
"LuCI.xhr.html#get">get
</a></li>
3417 <li data-name=
"LuCI.xhr#post"><a href=
"LuCI.xhr.html#post">post
</a></li>
3419 <li data-name=
"LuCI.xhr#send_form"><a href=
"LuCI.xhr.html#send_form">send_form
</a></li>
3422 <ul class=
"events itemMembers">
3430 <h1 class=
"page-title" data-filename=
"ui.js.html">Source: ui.js
</h1>
3437 <pre id=
"source-code" class=
"prettyprint source "><code>'use strict';
3438 'require validation';
3439 'require baseclass';
3448 var modalDiv = null,
3450 indicatorDiv = null,
3451 tooltipTimeout = null;
3454 * @class AbstractElement
3459 * The `AbstractElement` class serves as abstract base for the different widgets
3460 * implemented by `LuCI.ui`. It provides the common logic for getting and
3461 * setting values, for checking the validity state and for wiring up required
3464 * UI widget instances are usually not supposed to be created by view code
3465 * directly, instead they're implicitely created by `LuCI.form` when
3466 * instantiating CBI forms.
3468 * This class is automatically instantiated as part of `LuCI.ui`. To use it
3469 * in views, use `'require ui'` and refer to `ui.AbstractElement`. To import
3470 * it in external JavaScript, use `L.require(
"ui").then(...)` and access the
3471 * `AbstractElement` property of the class instance value.
3473 var UIElement = baseclass.extend(/** @lends LuCI.ui.AbstractElement.prototype */ {
3475 * @typedef {Object} InitOptions
3476 * @memberof LuCI.ui.AbstractElement
3478 * @property {string} [id]
3479 * Specifies the widget ID to use. It will be used as HTML `id` attribute
3480 * on the toplevel widget DOM node.
3482 * @property {string} [name]
3483 * Specifies the widget name which is set as HTML `name` attribute on the
3484 * corresponding `
<input
>` element.
3486 * @property {boolean} [optional=true]
3487 * Specifies whether the input field allows empty values.
3489 * @property {string} [datatype=string]
3490 * An expression describing the input data validation constraints.
3491 * It defaults to `string` which will allow any value.
3492 * See {@link LuCI.validation} for details on the expression format.
3494 * @property {function} [validator]
3495 * Specifies a custom validator function which is invoked after the
3496 * standard validation constraints are checked. The function should return
3497 * `true` to accept the given input value. Any other return value type is
3498 * converted to a string and treated as validation error message.
3500 * @property {boolean} [disabled=false]
3501 * Specifies whether the widget should be rendered in disabled state
3502 * (`true`) or not (`false`). Disabled widgets cannot be interacted with
3503 * and are displayed in a slightly faded style.
3507 * Read the current value of the input widget.
3510 * @memberof LuCI.ui.AbstractElement
3511 * @returns {string|string[]|null}
3512 * The current value of the input element. For simple inputs like text
3513 * fields or selects, the return value type will be a - possibly empty -
3514 * string. Complex widgets such as `DynamicList` instances may result in
3515 * an array of strings or `null` for unset values.
3517 getValue: function() {
3518 if (dom.matches(this.node, 'select') || dom.matches(this.node, 'input'))
3519 return this.node.value;
3525 * Set the current value of the input widget.
3528 * @memberof LuCI.ui.AbstractElement
3529 * @param {string|string[]|null} value
3530 * The value to set the input element to. For simple inputs like text
3531 * fields or selects, the value should be a - possibly empty - string.
3532 * Complex widgets such as `DynamicList` instances may accept string array
3535 setValue: function(value) {
3536 if (dom.matches(this.node, 'select') || dom.matches(this.node, 'input'))
3537 this.node.value = value;
3541 * Set the current placeholder value of the input widget.
3544 * @memberof LuCI.ui.AbstractElement
3545 * @param {string|string[]|null} value
3546 * The placeholder to set for the input element. Only applicable to text
3547 * inputs, not to radio buttons, selects or similar.
3549 setPlaceholder: function(value) {
3550 var node = this.node ? this.node.querySelector('input,textarea') : null;
3552 switch (node.getAttribute('type') || 'text') {
3558 if (value != null
&& value != '')
3559 node.setAttribute('placeholder', value);
3561 node.removeAttribute('placeholder');
3567 * Check whether the input value was altered by the user.
3570 * @memberof LuCI.ui.AbstractElement
3571 * @returns {boolean}
3572 * Returns `true` if the input value has been altered by the user or
3573 * `false` if it is unchaged. Note that if the user modifies the initial
3574 * value and changes it back to the original state, it is still reported
3577 isChanged: function() {
3578 return (this.node ? this.node.getAttribute('data-changed') : null) == 'true';
3582 * Check whether the current input value is valid.
3585 * @memberof LuCI.ui.AbstractElement
3586 * @returns {boolean}
3587 * Returns `true` if the current input value is valid or `false` if it does
3588 * not meet the validation constraints.
3590 isValid: function() {
3591 return (this.validState !== false);
3595 * Force validation of the current input value.
3597 * Usually input validation is automatically triggered by various DOM events
3598 * bound to the input widget. In some cases it is required though to manually
3599 * trigger validation runs, e.g. when programmatically altering values.
3602 * @memberof LuCI.ui.AbstractElement
3604 triggerValidation: function() {
3605 if (typeof(this.vfunc) != 'function')
3608 var wasValid = this.isValid();
3612 return (wasValid != this.isValid());
3616 * Dispatch a custom (synthetic) event in response to received events.
3618 * Sets up event handlers on the given target DOM node for the given event
3619 * names that dispatch a custom event of the given type to the widget root
3622 * The primary purpose of this function is to set up a series of custom
3623 * uniform standard events such as `widget-update`, `validation-success`,
3624 * `validation-failure` etc. which are triggered by various different
3625 * widget specific native DOM events.
3628 * @memberof LuCI.ui.AbstractElement
3629 * @param {Node} targetNode
3630 * Specifies the DOM node on which the native event listeners should be
3633 * @param {string} synevent
3634 * The name of the custom event to dispatch to the widget root DOM node.
3636 * @param {string[]} events
3637 * The native DOM events for which event handlers should be registered.
3639 registerEvents: function(targetNode, synevent, events) {
3640 var dispatchFn = L.bind(function(ev) {
3641 this.node.dispatchEvent(new CustomEvent(synevent, { bubbles: true }));
3644 for (var i =
0; i
< events.length; i++)
3645 targetNode.addEventListener(events[i], dispatchFn);
3649 * Setup listeners for native DOM events that may update the widget value.
3651 * Sets up event handlers on the given target DOM node for the given event
3652 * names which may cause the input value to update, such as `keyup` or
3653 * `onclick` events. In contrast to change events, such update events will
3654 * trigger input value validation.
3657 * @memberof LuCI.ui.AbstractElement
3658 * @param {Node} targetNode
3659 * Specifies the DOM node on which the event listeners should be registered.
3661 * @param {...string} events
3662 * The DOM events for which event handlers should be registered.
3664 setUpdateEvents: function(targetNode /*, ... */) {
3665 var datatype = this.options.datatype,
3666 optional = this.options.hasOwnProperty('optional') ? this.options.optional : true,
3667 validate = this.options.validate,
3668 events = this.varargs(arguments,
1);
3670 this.registerEvents(targetNode, 'widget-update', events);
3672 if (!datatype
&& !validate)
3675 this.vfunc = UI.prototype.addValidator.apply(UI.prototype, [
3676 targetNode, datatype || 'string',
3680 this.node.addEventListener('validation-success', L.bind(function(ev) {
3681 this.validState = true;
3684 this.node.addEventListener('validation-failure', L.bind(function(ev) {
3685 this.validState = false;
3690 * Setup listeners for native DOM events that may change the widget value.
3692 * Sets up event handlers on the given target DOM node for the given event
3693 * names which may cause the input value to change completely, such as
3694 * `change` events in a select menu. In contrast to update events, such
3695 * change events will not trigger input value validation but they may cause
3696 * field dependencies to get re-evaluated and will mark the input widget
3700 * @memberof LuCI.ui.AbstractElement
3701 * @param {Node} targetNode
3702 * Specifies the DOM node on which the event listeners should be registered.
3704 * @param {...string} events
3705 * The DOM events for which event handlers should be registered.
3707 setChangeEvents: function(targetNode /*, ... */) {
3708 var tag_changed = L.bind(function(ev) { this.setAttribute('data-changed', true) }, this.node);
3710 for (var i =
1; i
< arguments.length; i++)
3711 targetNode.addEventListener(arguments[i], tag_changed);
3713 this.registerEvents(targetNode, 'widget-change', this.varargs(arguments,
1));
3717 * Render the widget, setup event listeners and return resulting markup.
3720 * @memberof LuCI.ui.AbstractElement
3723 * Returns a DOM Node or DocumentFragment containing the rendered
3726 render: function() {}
3730 * Instantiate a text input widget.
3732 * @constructor Textfield
3734 * @augments LuCI.ui.AbstractElement
3738 * The `Textfield` class implements a standard single line text input field.
3740 * UI widget instances are usually not supposed to be created by view code
3741 * directly, instead they're implicitely created by `LuCI.form` when
3742 * instantiating CBI forms.
3744 * This class is automatically instantiated as part of `LuCI.ui`. To use it
3745 * in views, use `'require ui'` and refer to `ui.Textfield`. To import it in
3746 * external JavaScript, use `L.require(
"ui").then(...)` and access the
3747 * `Textfield` property of the class instance value.
3749 * @param {string} [value=null]
3750 * The initial input value.
3752 * @param {LuCI.ui.Textfield.InitOptions} [options]
3753 * Object describing the widget specific options to initialize the input.
3755 var UITextfield = UIElement.extend(/** @lends LuCI.ui.Textfield.prototype */ {
3757 * In addition to the [AbstractElement.InitOptions]{@link LuCI.ui.AbstractElement.InitOptions}
3758 * the following properties are recognized:
3760 * @typedef {LuCI.ui.AbstractElement.InitOptions} InitOptions
3761 * @memberof LuCI.ui.Textfield
3763 * @property {boolean} [password=false]
3764 * Specifies whether the input should be rendered as concealed password field.
3766 * @property {boolean} [readonly=false]
3767 * Specifies whether the input widget should be rendered readonly.
3769 * @property {number} [maxlength]
3770 * Specifies the HTML `maxlength` attribute to set on the corresponding
3771 * `
<input
>` element. Note that this a legacy property that exists for
3772 * compatibility reasons. It is usually better to `maxlength(N)` validation
3775 * @property {string} [placeholder]
3776 * Specifies the HTML `placeholder` attribute which is displayed when the
3777 * corresponding `
<input
>` element is empty.
3779 __init__: function(value, options) {
3781 this.options = Object.assign({
3788 render: function() {
3789 var frameEl = E('div', { 'id': this.options.id });
3790 var inputEl = E('input', {
3791 'id': this.options.id ? 'widget.' + this.options.id : null,
3792 'name': this.options.name,
3794 'class': this.options.password ? 'cbi-input-password' : 'cbi-input-text',
3795 'readonly': this.options.readonly ? '' : null,
3796 'disabled': this.options.disabled ? '' : null,
3797 'maxlength': this.options.maxlength,
3798 'placeholder': this.options.placeholder,
3799 'value': this.value,
3802 if (this.options.password) {
3803 frameEl.appendChild(E('div', { 'class': 'control-group' }, [
3806 'class': 'cbi-button cbi-button-neutral',
3807 'title': _('Reveal/hide password'),
3808 'aria-label': _('Reveal/hide password'),
3809 'click': function(ev) {
3810 var e = this.previousElementSibling;
3811 e.type = (e.type === 'password') ? 'text' : 'password';
3812 ev.preventDefault();
3817 window.requestAnimationFrame(function() { inputEl.type = 'password' });
3820 frameEl.appendChild(inputEl);
3823 return this.bind(frameEl);
3827 bind: function(frameEl) {
3828 var inputEl = frameEl.querySelector('input');
3830 this.node = frameEl;
3832 this.setUpdateEvents(inputEl, 'keyup', 'blur');
3833 this.setChangeEvents(inputEl, 'change');
3835 dom.bindClassInstance(frameEl, this);
3841 getValue: function() {
3842 var inputEl = this.node.querySelector('input');
3843 return inputEl.value;
3847 setValue: function(value) {
3848 var inputEl = this.node.querySelector('input');
3849 inputEl.value = value;
3854 * Instantiate a textarea widget.
3856 * @constructor Textarea
3858 * @augments LuCI.ui.AbstractElement
3862 * The `Textarea` class implements a multiline text area input field.
3864 * UI widget instances are usually not supposed to be created by view code
3865 * directly, instead they're implicitely created by `LuCI.form` when
3866 * instantiating CBI forms.
3868 * This class is automatically instantiated as part of `LuCI.ui`. To use it
3869 * in views, use `'require ui'` and refer to `ui.Textarea`. To import it in
3870 * external JavaScript, use `L.require(
"ui").then(...)` and access the
3871 * `Textarea` property of the class instance value.
3873 * @param {string} [value=null]
3874 * The initial input value.
3876 * @param {LuCI.ui.Textarea.InitOptions} [options]
3877 * Object describing the widget specific options to initialize the input.
3879 var UITextarea = UIElement.extend(/** @lends LuCI.ui.Textarea.prototype */ {
3881 * In addition to the [AbstractElement.InitOptions]{@link LuCI.ui.AbstractElement.InitOptions}
3882 * the following properties are recognized:
3884 * @typedef {LuCI.ui.AbstractElement.InitOptions} InitOptions
3885 * @memberof LuCI.ui.Textarea
3887 * @property {boolean} [readonly=false]
3888 * Specifies whether the input widget should be rendered readonly.
3890 * @property {string} [placeholder]
3891 * Specifies the HTML `placeholder` attribute which is displayed when the
3892 * corresponding `
<textarea
>` element is empty.
3894 * @property {boolean} [monospace=false]
3895 * Specifies whether a monospace font should be forced for the textarea
3898 * @property {number} [cols]
3899 * Specifies the HTML `cols` attribute to set on the corresponding
3900 * `
<textarea
>` element.
3902 * @property {number} [rows]
3903 * Specifies the HTML `rows` attribute to set on the corresponding
3904 * `
<textarea
>` element.
3906 * @property {boolean} [wrap=false]
3907 * Specifies whether the HTML `wrap` attribute should be set.
3909 __init__: function(value, options) {
3911 this.options = Object.assign({
3920 render: function() {
3921 var style = !this.options.cols ? 'width:
100%' : null,
3922 frameEl = E('div', { 'id': this.options.id, 'style': style }),
3923 value = (this.value != null) ? String(this.value) : '';
3925 frameEl.appendChild(E('textarea', {
3926 'id': this.options.id ? 'widget.' + this.options.id : null,
3927 'name': this.options.name,
3928 'class': 'cbi-input-textarea',
3929 'readonly': this.options.readonly ? '' : null,
3930 'disabled': this.options.disabled ? '' : null,
3931 'placeholder': this.options.placeholder,
3933 'cols': this.options.cols,
3934 'rows': this.options.rows,
3935 'wrap': this.options.wrap ? '' : null
3938 if (this.options.monospace)
3939 frameEl.firstElementChild.style.fontFamily = 'monospace';
3941 return this.bind(frameEl);
3945 bind: function(frameEl) {
3946 var inputEl = frameEl.firstElementChild;
3948 this.node = frameEl;
3950 this.setUpdateEvents(inputEl, 'keyup', 'blur');
3951 this.setChangeEvents(inputEl, 'change');
3953 dom.bindClassInstance(frameEl, this);
3959 getValue: function() {
3960 return this.node.firstElementChild.value;
3964 setValue: function(value) {
3965 this.node.firstElementChild.value = value;
3970 * Instantiate a checkbox widget.
3972 * @constructor Checkbox
3974 * @augments LuCI.ui.AbstractElement
3978 * The `Checkbox` class implements a simple checkbox input field.
3980 * UI widget instances are usually not supposed to be created by view code
3981 * directly, instead they're implicitely created by `LuCI.form` when
3982 * instantiating CBI forms.
3984 * This class is automatically instantiated as part of `LuCI.ui`. To use it
3985 * in views, use `'require ui'` and refer to `ui.Checkbox`. To import it in
3986 * external JavaScript, use `L.require(
"ui").then(...)` and access the
3987 * `Checkbox` property of the class instance value.
3989 * @param {string} [value=null]
3990 * The initial input value.
3992 * @param {LuCI.ui.Checkbox.InitOptions} [options]
3993 * Object describing the widget specific options to initialize the input.
3995 var UICheckbox = UIElement.extend(/** @lends LuCI.ui.Checkbox.prototype */ {
3997 * In addition to the [AbstractElement.InitOptions]{@link LuCI.ui.AbstractElement.InitOptions}
3998 * the following properties are recognized:
4000 * @typedef {LuCI.ui.AbstractElement.InitOptions} InitOptions
4001 * @memberof LuCI.ui.Checkbox
4003 * @property {string} [value_enabled=
1]
4004 * Specifies the value corresponding to a checked checkbox.
4006 * @property {string} [value_disabled=
0]
4007 * Specifies the value corresponding to an unchecked checkbox.
4009 * @property {string} [hiddenname]
4010 * Specifies the HTML `name` attribute of the hidden input backing the
4011 * checkbox. This is a legacy property existing for compatibility reasons,
4012 * it is required for HTML based form submissions.
4014 __init__: function(value, options) {
4016 this.options = Object.assign({
4023 render: function() {
4024 var id = 'cb%
08x'.format(Math.random() *
0xffffffff);
4025 var frameEl = E('div', {
4026 'id': this.options.id,
4027 'class': 'cbi-checkbox'
4030 if (this.options.hiddenname)
4031 frameEl.appendChild(E('input', {
4033 'name': this.options.hiddenname,
4037 frameEl.appendChild(E('input', {
4039 'name': this.options.name,
4041 'value': this.options.value_enabled,
4042 'checked': (this.value == this.options.value_enabled) ? '' : null,
4043 'disabled': this.options.disabled ? '' : null,
4044 'data-widget-id': this.options.id ? 'widget.' + this.options.id : null
4047 frameEl.appendChild(E('label', { 'for': id }));
4049 return this.bind(frameEl);
4053 bind: function(frameEl) {
4054 this.node = frameEl;
4056 this.setUpdateEvents(frameEl.lastElementChild.previousElementSibling, 'click', 'blur');
4057 this.setChangeEvents(frameEl.lastElementChild.previousElementSibling, 'change');
4059 dom.bindClassInstance(frameEl, this);
4065 * Test whether the checkbox is currently checked.
4068 * @memberof LuCI.ui.Checkbox
4069 * @returns {boolean}
4070 * Returns `true` when the checkbox is currently checked, otherwise `false`.
4072 isChecked: function() {
4073 return this.node.lastElementChild.previousElementSibling.checked;
4077 getValue: function() {
4078 return this.isChecked()
4079 ? this.options.value_enabled
4080 : this.options.value_disabled;
4084 setValue: function(value) {
4085 this.node.lastElementChild.previousElementSibling.checked = (value == this.options.value_enabled);
4090 * Instantiate a select dropdown or checkbox/radiobutton group.
4092 * @constructor Select
4094 * @augments LuCI.ui.AbstractElement
4098 * The `Select` class implements either a traditional HTML `
<select
>` element
4099 * or a group of checkboxes or radio buttons, depending on whether multiple
4100 * values are enabled or not.
4102 * UI widget instances are usually not supposed to be created by view code
4103 * directly, instead they're implicitely created by `LuCI.form` when
4104 * instantiating CBI forms.
4106 * This class is automatically instantiated as part of `LuCI.ui`. To use it
4107 * in views, use `'require ui'` and refer to `ui.Select`. To import it in
4108 * external JavaScript, use `L.require(
"ui").then(...)` and access the
4109 * `Select` property of the class instance value.
4111 * @param {string|string[]} [value=null]
4112 * The initial input value(s).
4114 * @param {Object
<string, string
>} choices
4115 * Object containing the selectable choices of the widget. The object keys
4116 * serve as values for the different choices while the values are used as
4119 * @param {LuCI.ui.Select.InitOptions} [options]
4120 * Object describing the widget specific options to initialize the inputs.
4122 var UISelect = UIElement.extend(/** @lends LuCI.ui.Select.prototype */ {
4124 * In addition to the [AbstractElement.InitOptions]{@link LuCI.ui.AbstractElement.InitOptions}
4125 * the following properties are recognized:
4127 * @typedef {LuCI.ui.AbstractElement.InitOptions} InitOptions
4128 * @memberof LuCI.ui.Select
4130 * @property {boolean} [multiple=false]
4131 * Specifies whether multiple choice values may be selected.
4133 * @property {string} [widget=select]
4134 * Specifies the kind of widget to render. May be either `select` or
4135 * `individual`. When set to `select` an HTML `
<select
>` element will be
4136 * used, otherwise a group of checkbox or radio button elements is created,
4137 * depending on the value of the `multiple` option.
4139 * @property {string} [orientation=horizontal]
4140 * Specifies whether checkbox / radio button groups should be rendered
4141 * in a `horizontal` or `vertical` manner. Does not apply to the `select`
4144 * @property {boolean|string[]} [sort=false]
4145 * Specifies if and how to sort choice values. If set to `true`, the choice
4146 * values will be sorted alphabetically. If set to an array of strings, the
4147 * choice sort order is derived from the array.
4149 * @property {number} [size]
4150 * Specifies the HTML `size` attribute to set on the `
<select
>` element.
4151 * Only applicable to the `select` widget type.
4153 * @property {string} [placeholder=-- Please choose --]
4154 * Specifies a placeholder text which is displayed when no choice is
4155 * selected yet. Only applicable to the `select` widget type.
4157 __init__: function(value, choices, options) {
4158 if (!L.isObject(choices))
4161 if (!Array.isArray(value))
4162 value = (value != null
&& value != '') ? [ value ] : [];
4164 if (!options.multiple
&& value.length
> 1)
4167 this.values = value;
4168 this.choices = choices;
4169 this.options = Object.assign({
4172 orientation: 'horizontal'
4175 if (this.choices.hasOwnProperty(''))
4176 this.options.optional = true;
4180 render: function() {
4181 var frameEl = E('div', { 'id': this.options.id }),
4182 keys = Object.keys(this.choices);
4184 if (this.options.sort === true)
4186 else if (Array.isArray(this.options.sort))
4187 keys = this.options.sort;
4189 if (this.options.widget != 'radio'
&& this.options.widget != 'checkbox') {
4190 frameEl.appendChild(E('select', {
4191 'id': this.options.id ? 'widget.' + this.options.id : null,
4192 'name': this.options.name,
4193 'size': this.options.size,
4194 'class': 'cbi-input-select',
4195 'multiple': this.options.multiple ? '' : null,
4196 'disabled': this.options.disabled ? '' : null
4199 if (this.options.optional)
4200 frameEl.lastChild.appendChild(E('option', {
4202 'selected': (this.values.length ==
0 || this.values[
0] == '') ? '' : null
4203 }, [ this.choices[''] || this.options.placeholder || _('-- Please choose --') ]));
4205 for (var i =
0; i
< keys.length; i++) {
4206 if (keys[i] == null || keys[i] == '')
4209 frameEl.lastChild.appendChild(E('option', {
4211 'selected': (this.values.indexOf(keys[i])
> -
1) ? '' : null
4212 }, [ this.choices[keys[i]] || keys[i] ]));
4216 var brEl = (this.options.orientation === 'horizontal') ? document.createTextNode(' \xa0 ') : E('br');
4218 for (var i =
0; i
< keys.length; i++) {
4219 frameEl.appendChild(E('span', {
4220 'class': 'cbi-%s'.format(this.options.multiple ? 'checkbox' : 'radio')
4223 'id': this.options.id ? 'widget.%s.%d'.format(this.options.id, i) : null,
4224 'name': this.options.id || this.options.name,
4225 'type': this.options.multiple ? 'checkbox' : 'radio',
4226 'class': this.options.multiple ? 'cbi-input-checkbox' : 'cbi-input-radio',
4228 'checked': (this.values.indexOf(keys[i])
> -
1) ? '' : null,
4229 'disabled': this.options.disabled ? '' : null
4231 E('label', { 'for': this.options.id ? 'widget.%s.%d'.format(this.options.id, i) : null }),
4233 'click': function(ev) {
4234 ev.currentTarget.previousElementSibling.previousElementSibling.click();
4236 }, [ this.choices[keys[i]] || keys[i] ])
4239 frameEl.appendChild(brEl.cloneNode());
4243 return this.bind(frameEl);
4247 bind: function(frameEl) {
4248 this.node = frameEl;
4250 if (this.options.widget != 'radio'
&& this.options.widget != 'checkbox') {
4251 this.setUpdateEvents(frameEl.firstChild, 'change', 'click', 'blur');
4252 this.setChangeEvents(frameEl.firstChild, 'change');
4255 var radioEls = frameEl.querySelectorAll('input[
type=
"radio"]');
4256 for (var i =
0; i
< radioEls.length; i++) {
4257 this.setUpdateEvents(radioEls[i], 'change', 'click', 'blur');
4258 this.setChangeEvents(radioEls[i], 'change', 'click', 'blur');
4262 dom.bindClassInstance(frameEl, this);
4268 getValue: function() {
4269 if (this.options.widget != 'radio'
&& this.options.widget != 'checkbox')
4270 return this.node.firstChild.value;
4272 var radioEls = this.node.querySelectorAll('input[
type=
"radio"]');
4273 for (var i =
0; i
< radioEls.length; i++)
4274 if (radioEls[i].checked)
4275 return radioEls[i].value;
4281 setValue: function(value) {
4282 if (this.options.widget != 'radio'
&& this.options.widget != 'checkbox') {
4286 for (var i =
0; i
< this.node.firstChild.options.length; i++)
4287 this.node.firstChild.options[i].selected = (this.node.firstChild.options[i].value == value);
4292 var radioEls = frameEl.querySelectorAll('input[
type=
"radio"]');
4293 for (var i =
0; i
< radioEls.length; i++)
4294 radioEls[i].checked = (radioEls[i].value == value);
4299 * Instantiate a rich dropdown choice widget.
4301 * @constructor Dropdown
4303 * @augments LuCI.ui.AbstractElement
4307 * The `Dropdown` class implements a rich, stylable dropdown menu which
4308 * supports non-text choice labels.
4310 * UI widget instances are usually not supposed to be created by view code
4311 * directly, instead they're implicitely created by `LuCI.form` when
4312 * instantiating CBI forms.
4314 * This class is automatically instantiated as part of `LuCI.ui`. To use it
4315 * in views, use `'require ui'` and refer to `ui.Dropdown`. To import it in
4316 * external JavaScript, use `L.require(
"ui").then(...)` and access the
4317 * `Dropdown` property of the class instance value.
4319 * @param {string|string[]} [value=null]
4320 * The initial input value(s).
4322 * @param {Object
<string, *
>} choices
4323 * Object containing the selectable choices of the widget. The object keys
4324 * serve as values for the different choices while the values are used as
4327 * @param {LuCI.ui.Dropdown.InitOptions} [options]
4328 * Object describing the widget specific options to initialize the dropdown.
4330 var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
4332 * In addition to the [AbstractElement.InitOptions]{@link LuCI.ui.AbstractElement.InitOptions}
4333 * the following properties are recognized:
4335 * @typedef {LuCI.ui.AbstractElement.InitOptions} InitOptions
4336 * @memberof LuCI.ui.Dropdown
4338 * @property {boolean} [optional=true]
4339 * Specifies whether the dropdown selection is optional. In contrast to
4340 * other widgets, the `optional` constraint of dropdowns works differently;
4341 * instead of marking the widget invalid on empty values when set to `false`,
4342 * the user is not allowed to deselect all choices.
4344 * For single value dropdowns that means that no empty
"please select"
4345 * choice is offered and for multi value dropdowns, the last selected choice
4346 * may not be deselected without selecting another choice first.
4348 * @property {boolean} [multiple]
4349 * Specifies whether multiple choice values may be selected. It defaults
4350 * to `true` when an array is passed as input value to the constructor.
4352 * @property {boolean|string[]} [sort=false]
4353 * Specifies if and how to sort choice values. If set to `true`, the choice
4354 * values will be sorted alphabetically. If set to an array of strings, the
4355 * choice sort order is derived from the array.
4357 * @property {string} [select_placeholder=-- Please choose --]
4358 * Specifies a placeholder text which is displayed when no choice is
4361 * @property {string} [custom_placeholder=-- custom --]
4362 * Specifies a placeholder text which is displayed in the text input
4363 * field allowing to enter custom choice values. Only applicable if the
4364 * `create` option is set to `true`.
4366 * @property {boolean} [create=false]
4367 * Specifies whether custom choices may be entered into the dropdown
4370 * @property {string} [create_query=.create-item-input]
4371 * Specifies a CSS selector expression used to find the input element
4372 * which is used to enter custom choice values. This should not normally
4373 * be used except by widgets derived from the Dropdown class.
4375 * @property {string} [create_template=script[
type=
"item-template"]]
4376 * Specifies a CSS selector expression used to find an HTML element
4377 * serving as template for newly added custom choice values.
4379 * Any `{{value}}` placeholder string within the template elements text
4380 * content will be replaced by the user supplied choice value, the
4381 * resulting string is parsed as HTML and appended to the end of the
4382 * choice list. The template markup may specify one HTML element with a
4383 * `data-label-placeholder` attribute which is replaced by a matching
4384 * label value from the `choices` object or with the user supplied value
4385 * itself in case `choices` contains no matching choice label.
4387 * If the template element is not found or if no `create_template` selector
4388 * expression is specified, the default markup for newly created elements is
4389 * `
<li
data-value=
"{{value}}"><span
data-label-placeholder=
"true" /></li
>`.
4391 * @property {string} [create_markup]
4392 * This property allows specifying the markup for custom choices directly
4393 * instead of referring to a template element through CSS selectors.
4395 * Apart from that it works exactly like `create_template`.
4397 * @property {number} [display_items=
3]
4398 * Specifies the maximum amount of choice labels that should be shown in
4399 * collapsed dropdown state before further selected choices are cut off.
4401 * Only applicable when `multiple` is `true`.
4403 * @property {number} [dropdown_items=-
1]
4404 * Specifies the maximum amount of choices that should be shown when the
4405 * dropdown is open. If the amount of available choices exceeds this number,
4406 * the dropdown area must be scrolled to reach further items.
4408 * If set to `-
1`, the dropdown menu will attempt to show all choice values
4409 * and only resort to scrolling if the amount of choices exceeds the available
4410 * screen space above and below the dropdown widget.
4412 * @property {string} [placeholder]
4413 * This property serves as a shortcut to set both `select_placeholder` and
4414 * `custom_placeholder`. Either of these properties will fallback to
4415 * `placeholder` if not specified.
4417 * @property {boolean} [readonly=false]
4418 * Specifies whether the custom choice input field should be rendered
4419 * readonly. Only applicable when `create` is `true`.
4421 * @property {number} [maxlength]
4422 * Specifies the HTML `maxlength` attribute to set on the custom choice
4423 * `
<input
>` element. Note that this a legacy property that exists for
4424 * compatibility reasons. It is usually better to `maxlength(N)` validation
4425 * expression. Only applicable when `create` is `true`.
4427 __init__: function(value, choices, options) {
4428 if (typeof(choices) != 'object')
4431 if (!Array.isArray(value))
4432 this.values = (value != null
&& value != '') ? [ value ] : [];
4434 this.values = value;
4436 this.choices = choices;
4437 this.options = Object.assign({
4439 multiple: Array.isArray(value),
4441 select_placeholder: _('-- Please choose --'),
4442 custom_placeholder: _('-- custom --'),
4446 create_query: '.create-item-input',
4447 create_template: 'script[
type=
"item-template"]'
4452 render: function() {
4454 'id': this.options.id,
4455 'class': 'cbi-dropdown',
4456 'multiple': this.options.multiple ? '' : null,
4457 'optional': this.options.optional ? '' : null,
4458 'disabled': this.options.disabled ? '' : null
4461 var keys = Object.keys(this.choices);
4463 if (this.options.sort === true)
4465 else if (Array.isArray(this.options.sort))
4466 keys = this.options.sort;
4468 if (this.options.create)
4469 for (var i =
0; i
< this.values.length; i++)
4470 if (!this.choices.hasOwnProperty(this.values[i]))
4471 keys.push(this.values[i]);
4473 for (var i =
0; i
< keys.length; i++) {
4474 var label = this.choices[keys[i]];
4476 if (dom.elem(label))
4477 label = label.cloneNode(true);
4479 sb.lastElementChild.appendChild(E('li', {
4480 'data-value': keys[i],
4481 'selected': (this.values.indexOf(keys[i])
> -
1) ? '' : null
4482 }, [ label || keys[i] ]));
4485 if (this.options.create) {
4486 var createEl = E('input', {
4488 'class': 'create-item-input',
4489 'readonly': this.options.readonly ? '' : null,
4490 'maxlength': this.options.maxlength,
4491 'placeholder': this.options.custom_placeholder || this.options.placeholder
4494 if (this.options.datatype || this.options.validate)
4495 UI.prototype.addValidator(createEl, this.options.datatype || 'string',
4496 true, this.options.validate, 'blur', 'keyup');
4498 sb.lastElementChild.appendChild(E('li', { 'data-value': '-' }, createEl));
4501 if (this.options.create_markup)
4502 sb.appendChild(E('script', { type: 'item-template' },
4503 this.options.create_markup));
4505 return this.bind(sb);
4509 bind: function(sb) {
4510 var o = this.options;
4512 o.multiple = sb.hasAttribute('multiple');
4513 o.optional = sb.hasAttribute('optional');
4514 o.placeholder = sb.getAttribute('placeholder') || o.placeholder;
4515 o.display_items = parseInt(sb.getAttribute('display-items') || o.display_items);
4516 o.dropdown_items = parseInt(sb.getAttribute('dropdown-items') || o.dropdown_items);
4517 o.create_query = sb.getAttribute('item-create') || o.create_query;
4518 o.create_template = sb.getAttribute('item-template') || o.create_template;
4520 var ul = sb.querySelector('ul'),
4521 more = sb.appendChild(E('span', { class: 'more', tabindex: -
1 }, '···')),
4522 open = sb.appendChild(E('span', { class: 'open', tabindex: -
1 }, '▾')),
4523 canary = sb.appendChild(E('div')),
4524 create = sb.querySelector(this.options.create_query),
4525 ndisplay = this.options.display_items,
4528 if (this.options.multiple) {
4529 var items = ul.querySelectorAll('li');
4531 for (var i =
0; i
< items.length; i++) {
4532 this.transformItem(sb, items[i]);
4534 if (items[i].hasAttribute('selected')
&& ndisplay--
> 0)
4535 items[i].setAttribute('display', n++);
4539 if (this.options.optional
&& !ul.querySelector('li[
data-value=
""]')) {
4540 var placeholder = E('li', { placeholder: '' },
4541 this.options.select_placeholder || this.options.placeholder);
4544 ? ul.insertBefore(placeholder, ul.firstChild)
4545 : ul.appendChild(placeholder);
4548 var items = ul.querySelectorAll('li'),
4549 sel = sb.querySelectorAll('[selected]');
4551 sel.forEach(function(s) {
4552 s.removeAttribute('selected');
4555 var s = sel[
0] || items[
0];
4557 s.setAttribute('selected', '');
4558 s.setAttribute('display', n++);
4564 this.saveValues(sb, ul);
4566 ul.setAttribute('tabindex', -
1);
4567 sb.setAttribute('tabindex',
0);
4569 if (ndisplay
< 0)
4570 sb.setAttribute('more', '')
4572 sb.removeAttribute('more');
4574 if (ndisplay == this.options.display_items)
4575 sb.setAttribute('empty', '')
4577 sb.removeAttribute('empty');
4579 dom.content(more, (ndisplay == this.options.display_items)
4580 ? (this.options.select_placeholder || this.options.placeholder) : '···');
4583 sb.addEventListener('click', this.handleClick.bind(this));
4584 sb.addEventListener('keydown', this.handleKeydown.bind(this));
4585 sb.addEventListener('cbi-dropdown-close', this.handleDropdownClose.bind(this));
4586 sb.addEventListener('cbi-dropdown-select', this.handleDropdownSelect.bind(this));
4588 if ('ontouchstart' in window) {
4589 sb.addEventListener('touchstart', function(ev) { ev.stopPropagation(); });
4590 window.addEventListener('touchstart', this.closeAllDropdowns);
4593 sb.addEventListener('mouseover', this.handleMouseover.bind(this));
4594 sb.addEventListener('focus', this.handleFocus.bind(this));
4596 canary.addEventListener('focus', this.handleCanaryFocus.bind(this));
4598 window.addEventListener('mouseover', this.setFocus);
4599 window.addEventListener('click', this.closeAllDropdowns);
4603 create.addEventListener('keydown', this.handleCreateKeydown.bind(this));
4604 create.addEventListener('focus', this.handleCreateFocus.bind(this));
4605 create.addEventListener('blur', this.handleCreateBlur.bind(this));
4607 var li = findParent(create, 'li');
4609 li.setAttribute('unselectable', '');
4610 li.addEventListener('click', this.handleCreateClick.bind(this));
4615 this.setUpdateEvents(sb, 'cbi-dropdown-open', 'cbi-dropdown-close');
4616 this.setChangeEvents(sb, 'cbi-dropdown-change', 'cbi-dropdown-close');
4618 dom.bindClassInstance(sb, this);
4624 openDropdown: function(sb) {
4625 var st = window.getComputedStyle(sb, null),
4626 ul = sb.querySelector('ul'),
4627 li = ul.querySelectorAll('li'),
4628 fl = findParent(sb, '.cbi-value-field'),
4629 sel = ul.querySelector('[selected]'),
4630 rect = sb.getBoundingClientRect(),
4631 items = Math.min(this.options.dropdown_items, li.length);
4633 document.querySelectorAll('.cbi-dropdown[open]').forEach(function(s) {
4634 s.dispatchEvent(new CustomEvent('cbi-dropdown-close', {}));
4637 sb.setAttribute('open', '');
4639 var pv = ul.cloneNode(true);
4640 pv.classList.add('preview');
4643 fl.classList.add('cbi-dropdown-open');
4645 if ('ontouchstart' in window) {
4646 var vpWidth = Math.max(document.documentElement.clientWidth, window.innerWidth ||
0),
4647 vpHeight = Math.max(document.documentElement.clientHeight, window.innerHeight ||
0),
4650 ul.style.top = sb.offsetHeight + 'px';
4651 ul.style.left = -rect.left + 'px';
4652 ul.style.right = (rect.right - vpWidth) + 'px';
4653 ul.style.maxHeight = (vpHeight *
0.5) + 'px';
4654 ul.style.WebkitOverflowScrolling = 'touch';
4656 var getScrollParent = function(element) {
4657 var parent = element,
4658 style = getComputedStyle(element),
4659 excludeStaticParent = (style.position === 'absolute');
4661 if (style.position === 'fixed')
4662 return document.body;
4664 while ((parent = parent.parentElement) != null) {
4665 style = getComputedStyle(parent);
4667 if (excludeStaticParent
&& style.position === 'static')
4670 if (/(auto|scroll)/.test(style.overflow + style.overflowY + style.overflowX))
4674 return document.body;
4677 var scrollParent = getScrollParent(sb),
4678 scrollFrom = scrollParent.scrollTop,
4679 scrollTo = scrollFrom + rect.top - vpHeight *
0.5;
4681 var scrollStep = function(timestamp) {
4684 ul.scrollTop = sel ? Math.max(sel.offsetTop - sel.offsetHeight,
0) :
0;
4687 var duration = Math.max(timestamp - start,
1);
4688 if (duration
< 100) {
4689 scrollParent.scrollTop = scrollFrom + (scrollTo - scrollFrom) * (duration /
100);
4690 window.requestAnimationFrame(scrollStep);
4693 scrollParent.scrollTop = scrollTo;
4697 window.requestAnimationFrame(scrollStep);
4700 ul.style.maxHeight = '
1px';
4701 ul.style.top = ul.style.bottom = '';
4703 window.requestAnimationFrame(function() {
4704 var itemHeight = li[Math.max(
0, li.length -
2)].getBoundingClientRect().height,
4706 spaceAbove = rect.top,
4707 spaceBelow = window.innerHeight - rect.height - rect.top;
4709 for (var i =
0; i
< (items == -
1 ? li.length : items); i++)
4710 fullHeight += li[i].getBoundingClientRect().height;
4712 if (fullHeight
<= spaceBelow) {
4713 ul.style.top = rect.height + 'px';
4714 ul.style.maxHeight = spaceBelow + 'px';
4716 else if (fullHeight
<= spaceAbove) {
4717 ul.style.bottom = rect.height + 'px';
4718 ul.style.maxHeight = spaceAbove + 'px';
4720 else if (spaceBelow
>= spaceAbove) {
4721 ul.style.top = rect.height + 'px';
4722 ul.style.maxHeight = (spaceBelow - (spaceBelow % itemHeight)) + 'px';
4725 ul.style.bottom = rect.height + 'px';
4726 ul.style.maxHeight = (spaceAbove - (spaceAbove % itemHeight)) + 'px';
4729 ul.scrollTop = sel ? Math.max(sel.offsetTop - sel.offsetHeight,
0) :
0;
4733 var cboxes = ul.querySelectorAll('[selected] input[
type=
"checkbox"]');
4734 for (var i =
0; i
< cboxes.length; i++) {
4735 cboxes[i].checked = true;
4736 cboxes[i].disabled = (cboxes.length ==
1 && !this.options.optional);
4739 ul.classList.add('dropdown');
4741 sb.insertBefore(pv, ul.nextElementSibling);
4743 li.forEach(function(l) {
4744 l.setAttribute('tabindex',
0);
4747 sb.lastElementChild.setAttribute('tabindex',
0);
4749 this.setFocus(sb, sel || li[
0], true);
4753 closeDropdown: function(sb, no_focus) {
4754 if (!sb.hasAttribute('open'))
4757 var pv = sb.querySelector('ul.preview'),
4758 ul = sb.querySelector('ul.dropdown'),
4759 li = ul.querySelectorAll('li'),
4760 fl = findParent(sb, '.cbi-value-field');
4762 li.forEach(function(l) { l.removeAttribute('tabindex'); });
4763 sb.lastElementChild.removeAttribute('tabindex');
4766 sb.removeAttribute('open');
4767 sb.style.width = sb.style.height = '';
4769 ul.classList.remove('dropdown');
4770 ul.style.top = ul.style.bottom = ul.style.maxHeight = '';
4773 fl.classList.remove('cbi-dropdown-open');
4776 this.setFocus(sb, sb);
4778 this.saveValues(sb, ul);
4782 toggleItem: function(sb, li, force_state) {
4783 if (li.hasAttribute('unselectable'))
4786 if (this.options.multiple) {
4787 var cbox = li.querySelector('input[
type=
"checkbox"]'),
4788 items = li.parentNode.querySelectorAll('li'),
4789 label = sb.querySelector('ul.preview'),
4790 sel = li.parentNode.querySelectorAll('[selected]').length,
4791 more = sb.querySelector('.more'),
4792 ndisplay = this.options.display_items,
4795 if (li.hasAttribute('selected')) {
4796 if (force_state !== true) {
4797 if (sel
> 1 || this.options.optional) {
4798 li.removeAttribute('selected');
4799 cbox.checked = cbox.disabled = false;
4803 cbox.disabled = true;
4808 if (force_state !== false) {
4809 li.setAttribute('selected', '');
4810 cbox.checked = true;
4811 cbox.disabled = false;
4816 while (label
&& label.firstElementChild)
4817 label.removeChild(label.firstElementChild);
4819 for (var i =
0; i
< items.length; i++) {
4820 items[i].removeAttribute('display');
4821 if (items[i].hasAttribute('selected')) {
4822 if (ndisplay--
> 0) {
4823 items[i].setAttribute('display', n++);
4825 label.appendChild(items[i].cloneNode(true));
4827 var c = items[i].querySelector('input[
type=
"checkbox"]');
4829 c.disabled = (sel ==
1 && !this.options.optional);
4833 if (ndisplay
< 0)
4834 sb.setAttribute('more', '');
4836 sb.removeAttribute('more');
4838 if (ndisplay === this.options.display_items)
4839 sb.setAttribute('empty', '');
4841 sb.removeAttribute('empty');
4843 dom.content(more, (ndisplay === this.options.display_items)
4844 ? (this.options.select_placeholder || this.options.placeholder) : '···');
4847 var sel = li.parentNode.querySelector('[selected]');
4849 sel.removeAttribute('display');
4850 sel.removeAttribute('selected');
4853 li.setAttribute('display',
0);
4854 li.setAttribute('selected', '');
4856 this.closeDropdown(sb, true);
4859 this.saveValues(sb, li.parentNode);
4863 transformItem: function(sb, li) {
4864 var cbox = E('form', {}, E('input', { type: 'checkbox', tabindex: -
1, onclick: 'event.preventDefault()' })),
4867 while (li.firstChild)
4868 label.appendChild(li.firstChild);
4870 li.appendChild(cbox);
4871 li.appendChild(label);
4875 saveValues: function(sb, ul) {
4876 var sel = ul.querySelectorAll('li[selected]'),
4877 div = sb.lastElementChild,
4878 name = this.options.name,
4882 while (div.lastElementChild)
4883 div.removeChild(div.lastElementChild);
4885 sel.forEach(function (s) {
4886 if (s.hasAttribute('placeholder'))
4891 value: s.hasAttribute('data-value') ? s.getAttribute('data-value') : s.innerText,
4895 div.appendChild(E('input', {
4903 strval += strval.length ? ' ' + v.value : v.value;
4911 if (this.options.multiple)
4912 detail.values = values;
4914 detail.value = values.length ? values[
0] : null;
4918 sb.dispatchEvent(new CustomEvent('cbi-dropdown-change', {
4925 setValues: function(sb, values) {
4926 var ul = sb.querySelector('ul');
4928 if (this.options.create) {
4929 for (var value in values) {
4930 this.createItems(sb, value);
4932 if (!this.options.multiple)
4937 if (this.options.multiple) {
4938 var lis = ul.querySelectorAll('li[data-value]');
4939 for (var i =
0; i
< lis.length; i++) {
4940 var value = lis[i].getAttribute('data-value');
4941 if (values === null || !(value in values))
4942 this.toggleItem(sb, lis[i], false);
4944 this.toggleItem(sb, lis[i], true);
4948 var ph = ul.querySelector('li[placeholder]');
4950 this.toggleItem(sb, ph);
4952 var lis = ul.querySelectorAll('li[data-value]');
4953 for (var i =
0; i
< lis.length; i++) {
4954 var value = lis[i].getAttribute('data-value');
4955 if (values !== null
&& (value in values))
4956 this.toggleItem(sb, lis[i]);
4962 setFocus: function(sb, elem, scroll) {
4963 if (sb
&& sb.hasAttribute
&& sb.hasAttribute('locked-in'))
4966 if (sb.target
&& findParent(sb.target, 'ul.dropdown'))
4969 document.querySelectorAll('.focus').forEach(function(e) {
4970 if (!matchesElem(e, 'input')) {
4971 e.classList.remove('focus');
4978 elem.classList.add('focus');
4981 elem.parentNode.scrollTop = elem.offsetTop - elem.parentNode.offsetTop;
4986 createChoiceElement: function(sb, value, label) {
4987 var tpl = sb.querySelector(this.options.create_template),
4991 markup = (tpl.textContent || tpl.innerHTML || tpl.firstChild.data).replace(/^
<!--|-->$/, '').trim();
4993 markup = '
<li
data-value=
"{{value}}"><span
data-label-placeholder=
"true" /></li
>';
4995 var new_item = E(markup.replace(/{{value}}/g, '%h'.format(value))),
4996 placeholder = new_item.querySelector('[data-label-placeholder]');
4999 var content = E('span', {}, label || this.choices[value] || [ value ]);
5001 while (content.firstChild)
5002 placeholder.parentNode.insertBefore(content.firstChild, placeholder);
5004 placeholder.parentNode.removeChild(placeholder);
5007 if (this.options.multiple)
5008 this.transformItem(sb, new_item);
5014 createItems: function(sb, value) {
5016 val = (value || '').trim(),
5017 ul = sb.querySelector('ul');
5019 if (!sbox.options.multiple)
5020 val = val.length ? [ val ] : [];
5022 val = val.length ? val.split(/\s+/) : [];
5024 val.forEach(function(item) {
5025 var new_item = null;
5027 ul.childNodes.forEach(function(li) {
5028 if (li.getAttribute
&& li.getAttribute('data-value') === item)
5033 new_item = sbox.createChoiceElement(sb, item);
5035 if (!sbox.options.multiple) {
5036 var old = ul.querySelector('li[created]');
5038 ul.removeChild(old);
5040 new_item.setAttribute('created', '');
5043 new_item = ul.insertBefore(new_item, ul.lastElementChild);
5046 sbox.toggleItem(sb, new_item, true);
5047 sbox.setFocus(sb, new_item, true);
5052 * Remove all existing choices from the dropdown menu.
5054 * This function removes all preexisting dropdown choices from the widget,
5055 * keeping only choices currently being selected unless `reset_values` is
5056 * given, in which case all choices and deselected and removed.
5059 * @memberof LuCI.ui.Dropdown
5060 * @param {boolean} [reset_value=false]
5061 * If set to `true`, deselect and remove selected choices as well instead
5064 clearChoices: function(reset_value) {
5065 var ul = this.node.querySelector('ul'),
5066 lis = ul ? ul.querySelectorAll('li[data-value]') : [],
5067 len = lis.length - (this.options.create ?
1 :
0),
5068 val = reset_value ? null : this.getValue();
5070 for (var i =
0; i
< len; i++) {
5071 var lival = lis[i].getAttribute('data-value');
5073 (!this.options.multiple
&& val != lival) ||
5074 (this.options.multiple
&& val.indexOf(lival) == -
1))
5075 ul.removeChild(lis[i]);
5079 this.setValues(this.node, {});
5083 * Add new choices to the dropdown menu.
5085 * This function adds further choices to an existing dropdown menu,
5086 * ignoring choice values which are already present.
5089 * @memberof LuCI.ui.Dropdown
5090 * @param {string[]} values
5091 * The choice values to add to the dropdown widget.
5093 * @param {Object
<string, *
>} labels
5094 * The choice label values to use when adding dropdown choices. If no
5095 * label is found for a particular choice value, the value itself is used
5096 * as label text. Choice labels may be any valid value accepted by
5097 * {@link LuCI.dom#content}.
5099 addChoices: function(values, labels) {
5101 ul = sb.querySelector('ul'),
5102 lis = ul ? ul.querySelectorAll('li[data-value]') : [];
5104 if (!Array.isArray(values))
5105 values = L.toArray(values);
5107 if (!L.isObject(labels))
5110 for (var i =
0; i
< values.length; i++) {
5113 for (var j =
0; j
< lis.length; j++) {
5114 if (lis[j].getAttribute('data-value') === values[i]) {
5124 this.createChoiceElement(sb, values[i], labels[values[i]]),
5125 ul.lastElementChild);
5130 * Close all open dropdown widgets in the current document.
5132 closeAllDropdowns: function() {
5133 document.querySelectorAll('.cbi-dropdown[open]').forEach(function(s) {
5134 s.dispatchEvent(new CustomEvent('cbi-dropdown-close', {}));
5139 handleClick: function(ev) {
5140 var sb = ev.currentTarget;
5142 if (!sb.hasAttribute('open')) {
5143 if (!matchesElem(ev.target, 'input'))
5144 this.openDropdown(sb);
5147 var li = findParent(ev.target, 'li');
5148 if (li
&& li.parentNode.classList.contains('dropdown'))
5149 this.toggleItem(sb, li);
5150 else if (li
&& li.parentNode.classList.contains('preview'))
5151 this.closeDropdown(sb);
5152 else if (matchesElem(ev.target, 'span.open, span.more'))
5153 this.closeDropdown(sb);
5156 ev.preventDefault();
5157 ev.stopPropagation();
5161 handleKeydown: function(ev) {
5162 var sb = ev.currentTarget;
5164 if (matchesElem(ev.target, 'input'))
5167 if (!sb.hasAttribute('open')) {
5168 switch (ev.keyCode) {
5173 this.openDropdown(sb);
5174 ev.preventDefault();
5178 var active = findParent(document.activeElement, 'li');
5180 switch (ev.keyCode) {
5182 this.closeDropdown(sb);
5187 if (!active.hasAttribute('selected'))
5188 this.toggleItem(sb, active);
5189 this.closeDropdown(sb);
5190 ev.preventDefault();
5196 this.toggleItem(sb, active);
5197 ev.preventDefault();
5202 if (active
&& active.previousElementSibling) {
5203 this.setFocus(sb, active.previousElementSibling);
5204 ev.preventDefault();
5209 if (active
&& active.nextElementSibling) {
5210 this.setFocus(sb, active.nextElementSibling);
5211 ev.preventDefault();
5219 handleDropdownClose: function(ev) {
5220 var sb = ev.currentTarget;
5222 this.closeDropdown(sb, true);
5226 handleDropdownSelect: function(ev) {
5227 var sb = ev.currentTarget,
5228 li = findParent(ev.target, 'li');
5233 this.toggleItem(sb, li);
5234 this.closeDropdown(sb, true);
5238 handleMouseover: function(ev) {
5239 var sb = ev.currentTarget;
5241 if (!sb.hasAttribute('open'))
5244 var li = findParent(ev.target, 'li');
5246 if (li
&& li.parentNode.classList.contains('dropdown'))
5247 this.setFocus(sb, li);
5251 handleFocus: function(ev) {
5252 var sb = ev.currentTarget;
5254 document.querySelectorAll('.cbi-dropdown[open]').forEach(function(s) {
5255 if (s !== sb || sb.hasAttribute('open'))
5256 s.dispatchEvent(new CustomEvent('cbi-dropdown-close', {}));
5261 handleCanaryFocus: function(ev) {
5262 this.closeDropdown(ev.currentTarget.parentNode);
5266 handleCreateKeydown: function(ev) {
5267 var input = ev.currentTarget,
5268 sb = findParent(input, '.cbi-dropdown');
5270 switch (ev.keyCode) {
5272 ev.preventDefault();
5274 if (input.classList.contains('cbi-input-invalid'))
5277 this.createItems(sb, input.value);
5285 handleCreateFocus: function(ev) {
5286 var input = ev.currentTarget,
5287 cbox = findParent(input, 'li').querySelector('input[
type=
"checkbox"]'),
5288 sb = findParent(input, '.cbi-dropdown');
5291 cbox.checked = true;
5293 sb.setAttribute('locked-in', '');
5297 handleCreateBlur: function(ev) {
5298 var input = ev.currentTarget,
5299 cbox = findParent(input, 'li').querySelector('input[
type=
"checkbox"]'),
5300 sb = findParent(input, '.cbi-dropdown');
5303 cbox.checked = false;
5305 sb.removeAttribute('locked-in');
5309 handleCreateClick: function(ev) {
5310 ev.currentTarget.querySelector(this.options.create_query).focus();
5314 setValue: function(values) {
5315 if (this.options.multiple) {
5316 if (!Array.isArray(values))
5317 values = (values != null
&& values != '') ? [ values ] : [];
5321 for (var i =
0; i
< values.length; i++)
5322 v[values[i]] = true;
5324 this.setValues(this.node, v);
5329 if (values != null) {
5330 if (Array.isArray(values))
5331 v[values[
0]] = true;
5336 this.setValues(this.node, v);
5341 getValue: function() {
5342 var div = this.node.lastElementChild,
5343 h = div.querySelectorAll('input[
type=
"hidden"]'),
5346 for (var i =
0; i
< h.length; i++)
5349 return this.options.multiple ? v : v[
0];
5354 * Instantiate a rich dropdown choice widget allowing custom values.
5356 * @constructor Combobox
5358 * @augments LuCI.ui.Dropdown
5362 * The `Combobox` class implements a rich, stylable dropdown menu which allows
5363 * to enter custom values. Historically, comboboxes used to be a dedicated
5364 * widget type in LuCI but nowadays they are direct aliases of dropdown widgets
5365 * with a set of enforced default properties for easier instantiation.
5367 * UI widget instances are usually not supposed to be created by view code
5368 * directly, instead they're implicitely created by `LuCI.form` when
5369 * instantiating CBI forms.
5371 * This class is automatically instantiated as part of `LuCI.ui`. To use it
5372 * in views, use `'require ui'` and refer to `ui.Combobox`. To import it in
5373 * external JavaScript, use `L.require(
"ui").then(...)` and access the
5374 * `Combobox` property of the class instance value.
5376 * @param {string|string[]} [value=null]
5377 * The initial input value(s).
5379 * @param {Object
<string, *
>} choices
5380 * Object containing the selectable choices of the widget. The object keys
5381 * serve as values for the different choices while the values are used as
5384 * @param {LuCI.ui.Combobox.InitOptions} [options]
5385 * Object describing the widget specific options to initialize the dropdown.
5387 var UICombobox = UIDropdown.extend(/** @lends LuCI.ui.Combobox.prototype */ {
5389 * Comboboxes support the same properties as
5390 * [Dropdown.InitOptions]{@link LuCI.ui.Dropdown.InitOptions} but enforce
5391 * specific values for the following properties:
5393 * @typedef {LuCI.ui.Dropdown.InitOptions} InitOptions
5394 * @memberof LuCI.ui.Combobox
5396 * @property {boolean} multiple=false
5397 * Since Comboboxes never allow selecting multiple values, this property
5398 * is forcibly set to `false`.
5400 * @property {boolean} create=true
5401 * Since Comboboxes always allow custom choice values, this property is
5402 * forcibly set to `true`.
5404 * @property {boolean} optional=true
5405 * Since Comboboxes are always optional, this property is forcibly set to
5408 __init__: function(value, choices, options) {
5409 this.super('__init__', [ value, choices, Object.assign({
5410 select_placeholder: _('-- Please choose --'),
5411 custom_placeholder: _('-- custom --'),
5423 * Instantiate a combo button widget offering multiple action choices.
5425 * @constructor ComboButton
5427 * @augments LuCI.ui.Dropdown
5431 * The `ComboButton` class implements a button element which can be expanded
5432 * into a dropdown to chose from a set of different action choices.
5434 * UI widget instances are usually not supposed to be created by view code
5435 * directly, instead they're implicitely created by `LuCI.form` when
5436 * instantiating CBI forms.
5438 * This class is automatically instantiated as part of `LuCI.ui`. To use it
5439 * in views, use `'require ui'` and refer to `ui.ComboButton`. To import it in
5440 * external JavaScript, use `L.require(
"ui").then(...)` and access the
5441 * `ComboButton` property of the class instance value.
5443 * @param {string|string[]} [value=null]
5444 * The initial input value(s).
5446 * @param {Object
<string, *
>} choices
5447 * Object containing the selectable choices of the widget. The object keys
5448 * serve as values for the different choices while the values are used as
5451 * @param {LuCI.ui.ComboButton.InitOptions} [options]
5452 * Object describing the widget specific options to initialize the button.
5454 var UIComboButton = UIDropdown.extend(/** @lends LuCI.ui.ComboButton.prototype */ {
5456 * ComboButtons support the same properties as
5457 * [Dropdown.InitOptions]{@link LuCI.ui.Dropdown.InitOptions} but enforce
5458 * specific values for some properties and add aditional button specific
5461 * @typedef {LuCI.ui.Dropdown.InitOptions} InitOptions
5462 * @memberof LuCI.ui.ComboButton
5464 * @property {boolean} multiple=false
5465 * Since ComboButtons never allow selecting multiple actions, this property
5466 * is forcibly set to `false`.
5468 * @property {boolean} create=false
5469 * Since ComboButtons never allow creating custom choices, this property
5470 * is forcibly set to `false`.
5472 * @property {boolean} optional=false
5473 * Since ComboButtons must always select one action, this property is
5474 * forcibly set to `false`.
5476 * @property {Object
<string, string
>} [classes]
5477 * Specifies a mapping of choice values to CSS class names. If an action
5478 * choice is selected by the user and if a corresponding entry exists in
5479 * the `classes` object, the class names corresponding to the selected
5480 * value are set on the button element.
5482 * This is useful to apply different button styles, such as colors, to the
5483 * combined button depending on the selected action.
5485 * @property {function} [click]
5486 * Specifies a handler function to invoke when the user clicks the button.
5487 * This function will be called with the button DOM node as `this` context
5488 * and receive the DOM click event as first as well as the selected action
5489 * choice value as second argument.
5491 __init__: function(value, choices, options) {
5492 this.super('__init__', [ value, choices, Object.assign({
5502 render: function(/* ... */) {
5503 var node = UIDropdown.prototype.render.apply(this, arguments),
5504 val = this.getValue();
5506 if (L.isObject(this.options.classes)
&& this.options.classes.hasOwnProperty(val))
5507 node.setAttribute('class', 'cbi-dropdown ' + this.options.classes[val]);
5513 handleClick: function(ev) {
5514 var sb = ev.currentTarget,
5517 if (sb.hasAttribute('open') || dom.matches(t, '.cbi-dropdown
> span.open'))
5518 return UIDropdown.prototype.handleClick.apply(this, arguments);
5520 if (this.options.click)
5521 return this.options.click.call(sb, ev, this.getValue());
5525 toggleItem: function(sb /*, ... */) {
5526 var rv = UIDropdown.prototype.toggleItem.apply(this, arguments),
5527 val = this.getValue();
5529 if (L.isObject(this.options.classes)
&& this.options.classes.hasOwnProperty(val))
5530 sb.setAttribute('class', 'cbi-dropdown ' + this.options.classes[val]);
5532 sb.setAttribute('class', 'cbi-dropdown');
5539 * Instantiate a dynamic list widget.
5541 * @constructor DynamicList
5543 * @augments LuCI.ui.AbstractElement
5547 * The `DynamicList` class implements a widget which allows the user to specify
5548 * an arbitrary amount of input values, either from free formed text input or
5549 * from a set of predefined choices.
5551 * UI widget instances are usually not supposed to be created by view code
5552 * directly, instead they're implicitely created by `LuCI.form` when
5553 * instantiating CBI forms.
5555 * This class is automatically instantiated as part of `LuCI.ui`. To use it
5556 * in views, use `'require ui'` and refer to `ui.DynamicList`. To import it in
5557 * external JavaScript, use `L.require(
"ui").then(...)` and access the
5558 * `DynamicList` property of the class instance value.
5560 * @param {string|string[]} [value=null]
5561 * The initial input value(s).
5563 * @param {Object
<string, *
>} [choices]
5564 * Object containing the selectable choices of the widget. The object keys
5565 * serve as values for the different choices while the values are used as
5566 * choice labels. If omitted, no default choices are presented to the user,
5567 * instead a plain text input field is rendered allowing the user to add
5568 * arbitrary values to the dynamic list.
5570 * @param {LuCI.ui.DynamicList.InitOptions} [options]
5571 * Object describing the widget specific options to initialize the dynamic list.
5573 var UIDynamicList = UIElement.extend(/** @lends LuCI.ui.DynamicList.prototype */ {
5575 * In case choices are passed to the dynamic list contructor, the widget
5576 * supports the same properties as [Dropdown.InitOptions]{@link LuCI.ui.Dropdown.InitOptions}
5577 * but enforces specific values for some dropdown properties.
5579 * @typedef {LuCI.ui.Dropdown.InitOptions} InitOptions
5580 * @memberof LuCI.ui.DynamicList
5582 * @property {boolean} multiple=false
5583 * Since dynamic lists never allow selecting multiple choices when adding
5584 * another list item, this property is forcibly set to `false`.
5586 * @property {boolean} optional=true
5587 * Since dynamic lists use an embedded dropdown to present a list of
5588 * predefined choice values, the dropdown must be made optional to allow
5589 * it to remain unselected.
5591 __init__: function(values, choices, options) {
5592 if (!Array.isArray(values))
5593 values = (values != null
&& values != '') ? [ values ] : [];
5595 if (typeof(choices) != 'object')
5598 this.values = values;
5599 this.choices = choices;
5600 this.options = Object.assign({}, options, {
5607 render: function() {
5609 'id': this.options.id,
5610 'class': 'cbi-dynlist',
5611 'disabled': this.options.disabled ? '' : null
5612 }, E('div', { 'class': 'add-item' }));
5615 if (this.options.placeholder != null)
5616 this.options.select_placeholder = this.options.placeholder;
5618 var cbox = new UICombobox(null, this.choices, this.options);
5620 dl.lastElementChild.appendChild(cbox.render());
5623 var inputEl = E('input', {
5624 'id': this.options.id ? 'widget.' + this.options.id : null,
5626 'class': 'cbi-input-text',
5627 'placeholder': this.options.placeholder,
5628 'disabled': this.options.disabled ? '' : null
5631 dl.lastElementChild.appendChild(inputEl);
5632 dl.lastElementChild.appendChild(E('div', { 'class': 'btn cbi-button cbi-button-add' }, '+'));
5634 if (this.options.datatype || this.options.validate)
5635 UI.prototype.addValidator(inputEl, this.options.datatype || 'string',
5636 true, this.options.validate, 'blur', 'keyup');
5639 for (var i =
0; i
< this.values.length; i++) {
5640 var label = this.choices ? this.choices[this.values[i]] : null;
5642 if (dom.elem(label))
5643 label = label.cloneNode(true);
5645 this.addItem(dl, this.values[i], label);
5648 return this.bind(dl);
5652 bind: function(dl) {
5653 dl.addEventListener('click', L.bind(this.handleClick, this));
5654 dl.addEventListener('keydown', L.bind(this.handleKeydown, this));
5655 dl.addEventListener('cbi-dropdown-change', L.bind(this.handleDropdownChange, this));
5659 this.setUpdateEvents(dl, 'cbi-dynlist-change');
5660 this.setChangeEvents(dl, 'cbi-dynlist-change');
5662 dom.bindClassInstance(dl, this);
5668 addItem: function(dl, value, text, flash) {
5670 new_item = E('div', { 'class': flash ? 'item flash' : 'item', 'tabindex':
0 }, [
5671 E('span', {}, [ text || value ]),
5674 'name': this.options.name,
5675 'value': value })]);
5677 dl.querySelectorAll('.item').forEach(function(item) {
5681 var hidden = item.querySelector('input[
type=
"hidden"]');
5683 if (hidden
&& hidden.parentNode !== item)
5686 if (hidden
&& hidden.value === value)
5691 var ai = dl.querySelector('.add-item');
5692 ai.parentNode.insertBefore(new_item, ai);
5695 dl.dispatchEvent(new CustomEvent('cbi-dynlist-change', {
5707 removeItem: function(dl, item) {
5708 var value = item.querySelector('input[
type=
"hidden"]').value;
5709 var sb = dl.querySelector('.cbi-dropdown');
5711 sb.querySelectorAll('ul
> li').forEach(function(li) {
5712 if (li.getAttribute('data-value') === value) {
5713 if (li.hasAttribute('dynlistcustom'))
5714 li.parentNode.removeChild(li);
5716 li.removeAttribute('unselectable');
5720 item.parentNode.removeChild(item);
5722 dl.dispatchEvent(new CustomEvent('cbi-dynlist-change', {
5734 handleClick: function(ev) {
5735 var dl = ev.currentTarget,
5736 item = findParent(ev.target, '.item');
5738 if (this.options.disabled)
5742 this.removeItem(dl, item);
5744 else if (matchesElem(ev.target, '.cbi-button-add')) {
5745 var input = ev.target.previousElementSibling;
5746 if (input.value.length
&& !input.classList.contains('cbi-input-invalid')) {
5747 this.addItem(dl, input.value, null, true);
5754 handleDropdownChange: function(ev) {
5755 var dl = ev.currentTarget,
5756 sbIn = ev.detail.instance,
5757 sbEl = ev.detail.element,
5758 sbVal = ev.detail.value;
5763 sbIn.setValues(sbEl, null);
5764 sbVal.element.setAttribute('unselectable', '');
5766 if (sbVal.element.hasAttribute('created')) {
5767 sbVal.element.removeAttribute('created');
5768 sbVal.element.setAttribute('dynlistcustom', '');
5771 var label = sbVal.text;
5773 if (sbVal.element) {
5776 for (var i =
0; i
< sbVal.element.childNodes.length; i++)
5777 label.appendChild(sbVal.element.childNodes[i].cloneNode(true));
5780 this.addItem(dl, sbVal.value, label, true);
5784 handleKeydown: function(ev) {
5785 var dl = ev.currentTarget,
5786 item = findParent(ev.target, '.item');
5789 switch (ev.keyCode) {
5790 case
8: /* backspace */
5791 if (item.previousElementSibling)
5792 item.previousElementSibling.focus();
5794 this.removeItem(dl, item);
5797 case
46: /* delete */
5798 if (item.nextElementSibling) {
5799 if (item.nextElementSibling.classList.contains('item'))
5800 item.nextElementSibling.focus();
5802 item.nextElementSibling.firstElementChild.focus();
5805 this.removeItem(dl, item);
5809 else if (matchesElem(ev.target, '.cbi-input-text')) {
5810 switch (ev.keyCode) {
5811 case
13: /* enter */
5812 if (ev.target.value.length
&& !ev.target.classList.contains('cbi-input-invalid')) {
5813 this.addItem(dl, ev.target.value, null, true);
5814 ev.target.value = '';
5819 ev.preventDefault();
5826 getValue: function() {
5827 var items = this.node.querySelectorAll('.item
> input[
type=
"hidden"]'),
5828 input = this.node.querySelector('.add-item
> input[
type=
"text"]'),
5831 for (var i =
0; i
< items.length; i++)
5832 v.push(items[i].value);
5834 if (input
&& input.value != null
&& input.value.match(/\S/)
&&
5835 input.classList.contains('cbi-input-invalid') == false
&&
5836 v.filter(function(s) { return s == input.value }).length ==
0)
5837 v.push(input.value);
5843 setValue: function(values) {
5844 if (!Array.isArray(values))
5845 values = (values != null
&& values != '') ? [ values ] : [];
5847 var items = this.node.querySelectorAll('.item');
5849 for (var i =
0; i
< items.length; i++)
5850 if (items[i].parentNode === this.node)
5851 this.removeItem(this.node, items[i]);
5853 for (var i =
0; i
< values.length; i++)
5854 this.addItem(this.node, values[i],
5855 this.choices ? this.choices[values[i]] : null);
5859 * Add new suggested choices to the dynamic list.
5861 * This function adds further choices to an existing dynamic list,
5862 * ignoring choice values which are already present.
5865 * @memberof LuCI.ui.DynamicList
5866 * @param {string[]} values
5867 * The choice values to add to the dynamic lists suggestion dropdown.
5869 * @param {Object
<string, *
>} labels
5870 * The choice label values to use when adding suggested choices. If no
5871 * label is found for a particular choice value, the value itself is used
5872 * as label text. Choice labels may be any valid value accepted by
5873 * {@link LuCI.dom#content}.
5875 addChoices: function(values, labels) {
5876 var dl = this.node.lastElementChild.firstElementChild;
5877 dom.callClassMethod(dl, 'addChoices', values, labels);
5881 * Remove all existing choices from the dynamic list.
5883 * This function removes all preexisting suggested choices from the widget.
5886 * @memberof LuCI.ui.DynamicList
5888 clearChoices: function() {
5889 var dl = this.node.lastElementChild.firstElementChild;
5890 dom.callClassMethod(dl, 'clearChoices');
5895 * Instantiate a hidden input field widget.
5897 * @constructor Hiddenfield
5899 * @augments LuCI.ui.AbstractElement
5903 * The `Hiddenfield` class implements an HTML `
<input
type=
"hidden">` field
5904 * which allows to store form data without exposing it to the user.
5906 * UI widget instances are usually not supposed to be created by view code
5907 * directly, instead they're implicitely created by `LuCI.form` when
5908 * instantiating CBI forms.
5910 * This class is automatically instantiated as part of `LuCI.ui`. To use it
5911 * in views, use `'require ui'` and refer to `ui.Hiddenfield`. To import it in
5912 * external JavaScript, use `L.require(
"ui").then(...)` and access the
5913 * `Hiddenfield` property of the class instance value.
5915 * @param {string|string[]} [value=null]
5916 * The initial input value.
5918 * @param {LuCI.ui.AbstractElement.InitOptions} [options]
5919 * Object describing the widget specific options to initialize the hidden input.
5921 var UIHiddenfield = UIElement.extend(/** @lends LuCI.ui.Hiddenfield.prototype */ {
5922 __init__: function(value, options) {
5924 this.options = Object.assign({
5930 render: function() {
5931 var hiddenEl = E('input', {
5932 'id': this.options.id,
5937 return this.bind(hiddenEl);
5941 bind: function(hiddenEl) {
5942 this.node = hiddenEl;
5944 dom.bindClassInstance(hiddenEl, this);
5950 getValue: function() {
5951 return this.node.value;
5955 setValue: function(value) {
5956 this.node.value = value;
5961 * Instantiate a file upload widget.
5963 * @constructor FileUpload
5965 * @augments LuCI.ui.AbstractElement
5969 * The `FileUpload` class implements a widget which allows the user to upload,
5970 * browse, select and delete files beneath a predefined remote directory.
5972 * UI widget instances are usually not supposed to be created by view code
5973 * directly, instead they're implicitely created by `LuCI.form` when
5974 * instantiating CBI forms.
5976 * This class is automatically instantiated as part of `LuCI.ui`. To use it
5977 * in views, use `'require ui'` and refer to `ui.FileUpload`. To import it in
5978 * external JavaScript, use `L.require(
"ui").then(...)` and access the
5979 * `FileUpload` property of the class instance value.
5981 * @param {string|string[]} [value=null]
5982 * The initial input value.
5984 * @param {LuCI.ui.DynamicList.InitOptions} [options]
5985 * Object describing the widget specific options to initialize the file
5988 var UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */ {
5990 * In addition to the [AbstractElement.InitOptions]{@link LuCI.ui.AbstractElement.InitOptions}
5991 * the following properties are recognized:
5993 * @typedef {LuCI.ui.AbstractElement.InitOptions} InitOptions
5994 * @memberof LuCI.ui.FileUpload
5996 * @property {boolean} [show_hidden=false]
5997 * Specifies whether hidden files should be displayed when browsing remote
5998 * files. Note that this is not a security feature, hidden files are always
5999 * present in the remote file listings received, this option merely controls
6000 * whether they're displayed or not.
6002 * @property {boolean} [enable_upload=true]
6003 * Specifies whether the widget allows the user to upload files. If set to
6004 * `false`, only existing files may be selected. Note that this is not a
6005 * security feature. Whether file upload requests are accepted remotely
6006 * depends on the ACL setup for the current session. This option merely
6007 * controls whether the upload controls are rendered or not.
6009 * @property {boolean} [enable_remove=true]
6010 * Specifies whether the widget allows the user to delete remove files.
6011 * If set to `false`, existing files may not be removed. Note that this is
6012 * not a security feature. Whether file delete requests are accepted
6013 * remotely depends on the ACL setup for the current session. This option
6014 * merely controls whether the file remove controls are rendered or not.
6016 * @property {string} [root_directory=/etc/luci-uploads]
6017 * Specifies the remote directory the upload and file browsing actions take
6018 * place in. Browsing to directories outside of the root directory is
6019 * prevented by the widget. Note that this is not a security feature.
6020 * Whether remote directories are browseable or not solely depends on the
6021 * ACL setup for the current session.
6023 __init__: function(value, options) {
6025 this.options = Object.assign({
6027 enable_upload: true,
6028 enable_remove: true,
6029 root_directory: '/etc/luci-uploads'
6034 bind: function(browserEl) {
6035 this.node = browserEl;
6037 this.setUpdateEvents(browserEl, 'cbi-fileupload-select', 'cbi-fileupload-cancel');
6038 this.setChangeEvents(browserEl, 'cbi-fileupload-select', 'cbi-fileupload-cancel');
6040 dom.bindClassInstance(browserEl, this);
6046 render: function() {
6047 return L.resolveDefault(this.value != null ? fs.stat(this.value) : null).then(L.bind(function(stat) {
6050 if (L.isObject(stat)
&& stat.type != 'directory')
6053 if (this.stat != null)
6054 label = [ this.iconForType(this.stat.type), ' %s (%
1000mB)'.format(this.truncatePath(this.stat.path), this.stat.size) ];
6055 else if (this.value != null)
6056 label = [ this.iconForType('file'), ' %s (%s)'.format(this.truncatePath(this.value), _('File not accessible')) ];
6058 label = [ _('Select file…') ];
6060 return this.bind(E('div', { 'id': this.options.id }, [
6063 'click': UI.prototype.createHandlerFn(this, 'handleFileBrowser'),
6064 'disabled': this.options.disabled ? '' : null
6067 'class': 'cbi-filebrowser'
6071 'name': this.options.name,
6079 truncatePath: function(path) {
6080 if (path.length
> 50)
6081 path = path.substring(
0,
25) + '…' + path.substring(path.length -
25);
6087 iconForType: function(type) {
6091 'src': L.resource('cbi/link.svg'),
6093 'title': _('Symbolic link'),
6099 'src': L.resource('cbi/folder.svg'),
6101 'title': _('Directory'),
6107 'src': L.resource('cbi/file.svg'),
6116 canonicalizePath: function(path) {
6117 return path.replace(/\/{
2,}/, '/')
6118 .replace(/\/\.(\/|$)/g, '/')
6119 .replace(/[^\/]+\/\.\.(\/|$)/g, '/')
6120 .replace(/\/$/, '');
6124 splitPath: function(path) {
6125 var croot = this.canonicalizePath(this.options.root_directory || '/'),
6126 cpath = this.canonicalizePath(path || '/');
6128 if (cpath.length
<= croot.length)
6131 if (cpath.charAt(croot.length) != '/')
6134 var parts = cpath.substring(croot.length +
1).split(/\//);
6136 parts.unshift(croot);
6142 handleUpload: function(path, list, ev) {
6143 var form = ev.target.parentNode,
6144 fileinput = form.querySelector('input[
type=
"file"]'),
6145 nameinput = form.querySelector('input[
type=
"text"]'),
6146 filename = (nameinput.value != null ? nameinput.value : '').trim();
6148 ev.preventDefault();
6150 if (filename == '' || filename.match(/\//) || fileinput.files[
0] == null)
6153 var existing = list.filter(function(e) { return e.name == filename })[
0];
6155 if (existing != null
&& existing.type == 'directory')
6156 return alert(_('A directory with the same name already exists.'));
6157 else if (existing != null
&& !confirm(_('Overwrite existing file
"%s" ?').format(filename)))
6160 var data = new FormData();
6162 data.append('sessionid', L.env.sessionid);
6163 data.append('filename', path + '/' + filename);
6164 data.append('filedata', fileinput.files[
0]);
6166 return request.post(L.env.cgi_base + '/cgi-upload', data, {
6167 progress: L.bind(function(btn, ev) {
6168 btn.firstChild.data = '%
.2f%%'.format((ev.loaded / ev.total) *
100);
6170 }).then(L.bind(function(path, ev, res) {
6171 var reply = res.json();
6173 if (L.isObject(reply)
&& reply.failure)
6174 alert(_('Upload request failed: %s').format(reply.message));
6176 return this.handleSelect(path, null, ev);
6177 }, this, path, ev));
6181 handleDelete: function(path, fileStat, ev) {
6182 var parent = path.replace(/\/[^\/]+$/, '') || '/',
6183 name = path.replace(/^.+\//, ''),
6186 ev.preventDefault();
6188 if (fileStat.type == 'directory')
6189 msg = _('Do you really want to recursively delete the directory
"%s" ?').format(name);
6191 msg = _('Do you really want to delete
"%s" ?').format(name);
6194 var button = this.node.firstElementChild,
6195 hidden = this.node.lastElementChild;
6197 if (path == hidden.value) {
6198 dom.content(button, _('Select file…'));
6202 return fs.remove(path).then(L.bind(function(parent, ev) {
6203 return this.handleSelect(parent, null, ev);
6204 }, this, parent, ev)).catch(function(err) {
6205 alert(_('Delete request failed: %s').format(err.message));
6211 renderUpload: function(path, list) {
6212 if (!this.options.enable_upload)
6218 'class': 'btn cbi-button-positive',
6219 'click': function(ev) {
6220 var uploadForm = ev.target.nextElementSibling,
6221 fileInput = uploadForm.querySelector('input[
type=
"file"]');
6223 ev.target.style.display = 'none';
6224 uploadForm.style.display = '';
6227 }, _('Upload file…')),
6228 E('div', { 'class': 'upload', 'style': 'display:none' }, [
6231 'style': 'display:none',
6232 'change': function(ev) {
6233 var nameinput = ev.target.parentNode.querySelector('input[
type=
"text"]'),
6234 uploadbtn = ev.target.parentNode.querySelector('button.cbi-button-save');
6236 nameinput.value = ev.target.value.replace(/^.+[\/\\]/, '');
6237 uploadbtn.disabled = false;
6242 'click': function(ev) {
6243 ev.preventDefault();
6244 ev.target.previousElementSibling.click();
6246 }, [ _('Browse…') ]),
6247 E('div', {}, E('input', { 'type': 'text', 'placeholder': _('Filename') })),
6249 'class': 'btn cbi-button-save',
6250 'click': UI.prototype.createHandlerFn(this, 'handleUpload', path, list),
6252 }, [ _('Upload file') ])
6258 renderListing: function(container, path, list) {
6259 var breadcrumb = E('p'),
6262 list.sort(function(a, b) {
6263 var isDirA = (a.type == 'directory'),
6264 isDirB = (b.type == 'directory');
6266 if (isDirA != isDirB)
6267 return isDirA
< isDirB;
6269 return a.name
> b.name;
6272 for (var i =
0; i
< list.length; i++) {
6273 if (!this.options.show_hidden
&& list[i].name.charAt(
0) == '.')
6276 var entrypath = this.canonicalizePath(path + '/' + list[i].name),
6277 selected = (entrypath == this.node.lastElementChild.value),
6278 mtime = new Date(list[i].mtime *
1000);
6280 rows.appendChild(E('li', [
6281 E('div', { 'class': 'name' }, [
6282 this.iconForType(list[i].type),
6286 'style': selected ? 'font-weight:bold' : null,
6287 'click': UI.prototype.createHandlerFn(this, 'handleSelect',
6288 entrypath, list[i].type != 'directory' ? list[i] : null)
6289 }, '%h'.format(list[i].name))
6291 E('div', { 'class': 'mtime hide-xs' }, [
6292 ' %
04d-%
02d-%
02d %
02d:%
02d:%
02d '.format(
6293 mtime.getFullYear(),
6294 mtime.getMonth() +
1,
6301 selected ? E('button', {
6303 'click': UI.prototype.createHandlerFn(this, 'handleReset')
6304 }, [ _('Deselect') ]) : '',
6305 this.options.enable_remove ? E('button', {
6306 'class': 'btn cbi-button-negative',
6307 'click': UI.prototype.createHandlerFn(this, 'handleDelete', entrypath, list[i])
6308 }, [ _('Delete') ]) : ''
6313 if (!rows.firstElementChild)
6314 rows.appendChild(E('em', _('No entries in this directory')));
6316 var dirs = this.splitPath(path),
6319 for (var i =
0; i
< dirs.length; i++) {
6320 cur = cur ? cur + '/' + dirs[i] : dirs[i];
6321 dom.append(breadcrumb, [
6325 'click': UI.prototype.createHandlerFn(this, 'handleSelect', cur || '/', null)
6326 }, dirs[i] != '' ? '%h'.format(dirs[i]) : E('em', '(root)')),
6330 dom.content(container, [
6333 E('div', { 'class': 'right' }, [
6334 this.renderUpload(path, list),
6338 'click': UI.prototype.createHandlerFn(this, 'handleCancel')
6345 handleCancel: function(ev) {
6346 var button = this.node.firstElementChild,
6347 browser = button.nextElementSibling;
6349 browser.classList.remove('open');
6350 button.style.display = '';
6352 this.node.dispatchEvent(new CustomEvent('cbi-fileupload-cancel', {}));
6354 ev.preventDefault();
6358 handleReset: function(ev) {
6359 var button = this.node.firstElementChild,
6360 hidden = this.node.lastElementChild;
6363 dom.content(button, _('Select file…'));
6365 this.handleCancel(ev);
6369 handleSelect: function(path, fileStat, ev) {
6370 var browser = dom.parent(ev.target, '.cbi-filebrowser'),
6371 ul = browser.querySelector('ul');
6373 if (fileStat == null) {
6374 dom.content(ul, E('em', { 'class': 'spinning' }, _('Loading directory contents…')));
6375 L.resolveDefault(fs.list(path), []).then(L.bind(this.renderListing, this, browser, path));
6378 var button = this.node.firstElementChild,
6379 hidden = this.node.lastElementChild;
6381 path = this.canonicalizePath(path);
6383 dom.content(button, [
6384 this.iconForType(fileStat.type),
6385 ' %s (%
1000mB)'.format(this.truncatePath(path), fileStat.size)
6388 browser.classList.remove('open');
6389 button.style.display = '';
6390 hidden.value = path;
6392 this.stat = Object.assign({ path: path }, fileStat);
6393 this.node.dispatchEvent(new CustomEvent('cbi-fileupload-select', { detail: this.stat }));
6398 handleFileBrowser: function(ev) {
6399 var button = ev.target,
6400 browser = button.nextElementSibling,
6401 path = this.stat ? this.stat.path.replace(/\/[^\/]+$/, '') : (this.options.initial_directory || this.options.root_directory);
6403 if (path.indexOf(this.options.root_directory) !=
0)
6404 path = this.options.root_directory;
6406 ev.preventDefault();
6408 return L.resolveDefault(fs.list(path), []).then(L.bind(function(button, browser, path, list) {
6409 document.querySelectorAll('.cbi-filebrowser.open').forEach(function(browserEl) {
6410 dom.findClassInstance(browserEl).handleCancel(ev);
6413 button.style.display = 'none';
6414 browser.classList.add('open');
6416 return this.renderListing(browser, path, list);
6417 }, this, button, browser, path));
6421 getValue: function() {
6422 return this.node.lastElementChild.value;
6426 setValue: function(value) {
6427 this.node.lastElementChild.value = value;
6432 function scrubMenu(node) {
6433 var hasSatisfiedChild = false;
6435 if (L.isObject(node.children)) {
6436 for (var k in node.children) {
6437 var child = scrubMenu(node.children[k]);
6440 hasSatisfiedChild = hasSatisfiedChild || child.satisfied;
6444 if (L.isObject(node.action)
&&
6445 node.action.type == 'firstchild'
&&
6446 hasSatisfiedChild == false)
6447 node.satisfied = false;
6462 var UIMenu = baseclass.singleton(/** @lends LuCI.ui.menu.prototype */ {
6464 * @typedef {Object} MenuNode
6465 * @memberof LuCI.ui.menu
6467 * @property {string} name - The internal name of the node, as used in the URL
6468 * @property {number} order - The sort index of the menu node
6469 * @property {string} [title] - The title of the menu node, `null` if the node should be hidden
6470 * @property {satisified} boolean - Boolean indicating whether the menu enries dependencies are satisfied
6471 * @property {readonly} [boolean] - Boolean indicating whether the menu entries underlying ACLs are readonly
6472 * @property {LuCI.ui.menu.MenuNode[]} [children] - Array of child menu nodes.
6476 * Load and cache current menu tree.
6478 * @returns {Promise
<LuCI.ui.menu.MenuNode
>}
6479 * Returns a promise resolving to the root element of the menu tree.
6482 if (this.menu == null)
6483 this.menu = session.getLocalData('menu');
6485 if (!L.isObject(this.menu)) {
6486 this.menu = request.get(L.url('admin/menu')).then(L.bind(function(menu) {
6487 this.menu = scrubMenu(menu.json());
6488 session.setLocalData('menu', this.menu);
6494 return Promise.resolve(this.menu);
6498 * Flush the internal menu cache to force loading a new structure on the
6501 flushCache: function() {
6502 session.setLocalData('menu', null);
6506 * @param {LuCI.ui.menu.MenuNode} [node]
6507 * The menu node to retrieve the children for. Defaults to the menu's
6508 * internal root node if omitted.
6510 * @returns {LuCI.ui.menu.MenuNode[]}
6511 * Returns an array of child menu nodes.
6513 getChildren: function(node) {
6519 for (var k in node.children) {
6520 if (!node.children.hasOwnProperty(k))
6523 if (!node.children[k].satisfied)
6526 if (!node.children[k].hasOwnProperty('title'))
6529 children.push(Object.assign(node.children[k], { name: k }));
6532 return children.sort(function(a, b) {
6533 var wA = a.order ||
1000,
6534 wB = b.order ||
1000;
6539 return a.name
> b.name;
6550 * Provides high level UI helper functionality.
6551 * To import the class in views, use `'require ui'`, to import it in
6552 * external JavaScript, use `L.require(
"ui").then(...)`.
6554 var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
6555 __init__: function() {
6556 modalDiv = document.body.appendChild(
6557 dom.create('div', { id: 'modal_overlay' },
6558 dom.create('div', { class: 'modal', role: 'dialog', 'aria-modal': true })));
6560 tooltipDiv = document.body.appendChild(
6561 dom.create('div', { class: 'cbi-tooltip' }));
6563 /* setup old aliases */
6564 L.showModal = this.showModal;
6565 L.hideModal = this.hideModal;
6566 L.showTooltip = this.showTooltip;
6567 L.hideTooltip = this.hideTooltip;
6568 L.itemlist = this.itemlist;
6570 document.addEventListener('mouseover', this.showTooltip.bind(this), true);
6571 document.addEventListener('mouseout', this.hideTooltip.bind(this), true);
6572 document.addEventListener('focus', this.showTooltip.bind(this), true);
6573 document.addEventListener('blur', this.hideTooltip.bind(this), true);
6575 document.addEventListener('luci-loaded', this.tabs.init.bind(this.tabs));
6576 document.addEventListener('luci-loaded', this.changes.init.bind(this.changes));
6577 document.addEventListener('uci-loaded', this.changes.init.bind(this.changes));
6581 * Display a modal overlay dialog with the specified contents.
6583 * The modal overlay dialog covers the current view preventing interaction
6584 * with the underlying view contents. Only one modal dialog instance can
6585 * be opened. Invoking showModal() while a modal dialog is already open will
6586 * replace the open dialog with a new one having the specified contents.
6588 * Additional CSS class names may be passed to influence the appearence of
6589 * the dialog. Valid values for the classes depend on the underlying theme.
6591 * @see LuCI.dom.content
6593 * @param {string} [title]
6594 * The title of the dialog. If `null`, no title element will be rendered.
6596 * @param {*} contents
6597 * The contents to add to the modal dialog. This should be a DOM node or
6598 * a document fragment in most cases. The value is passed as-is to the
6599 * `dom.content()` function - refer to its documentation for applicable
6602 * @param {...string} [classes]
6603 * A number of extra CSS class names which are set on the modal dialog
6607 * Returns a DOM Node representing the modal dialog element.
6609 showModal: function(title, children /* , ... */) {
6610 var dlg = modalDiv.firstElementChild;
6612 dlg.setAttribute('class', 'modal');
6614 for (var i =
2; i
< arguments.length; i++)
6615 dlg.classList.add(arguments[i]);
6617 dom.content(dlg, dom.create('h4', {}, title));
6618 dom.append(dlg, children);
6620 document.body.classList.add('modal-overlay-active');
6621 modalDiv.scrollTop =
0;
6627 * Close the open modal overlay dialog.
6629 * This function will close an open modal dialog and restore the normal view
6630 * behaviour. It has no effect if no modal dialog is currently open.
6632 * Note that this function is stand-alone, it does not rely on `this` and
6633 * will not invoke other class functions so it suitable to be used as event
6634 * handler as-is without the need to bind it first.
6636 hideModal: function() {
6637 document.body.classList.remove('modal-overlay-active');
6641 showTooltip: function(ev) {
6642 var target = findParent(ev.target, '[data-tooltip]');
6647 if (tooltipTimeout !== null) {
6648 window.clearTimeout(tooltipTimeout);
6649 tooltipTimeout = null;
6652 var rect = target.getBoundingClientRect(),
6653 x = rect.left + window.pageXOffset,
6654 y = rect.top + rect.height + window.pageYOffset;
6656 tooltipDiv.className = 'cbi-tooltip';
6657 tooltipDiv.innerHTML = '▲ ';
6658 tooltipDiv.firstChild.data += target.getAttribute('data-tooltip');
6660 if (target.hasAttribute('data-tooltip-style'))
6661 tooltipDiv.classList.add(target.getAttribute('data-tooltip-style'));
6663 if ((y + tooltipDiv.offsetHeight)
> (window.innerHeight + window.pageYOffset)) {
6664 y -= (tooltipDiv.offsetHeight + target.offsetHeight);
6665 tooltipDiv.firstChild.data = '▼ ' + tooltipDiv.firstChild.data.substr(
2);
6668 tooltipDiv.style.top = y + 'px';
6669 tooltipDiv.style.left = x + 'px';
6670 tooltipDiv.style.opacity =
1;
6672 tooltipDiv.dispatchEvent(new CustomEvent('tooltip-open', {
6674 detail: { target: target }
6679 hideTooltip: function(ev) {
6680 if (ev.target === tooltipDiv || ev.relatedTarget === tooltipDiv ||
6681 tooltipDiv.contains(ev.target) || tooltipDiv.contains(ev.relatedTarget))
6684 if (tooltipTimeout !== null) {
6685 window.clearTimeout(tooltipTimeout);
6686 tooltipTimeout = null;
6689 tooltipDiv.style.opacity =
0;
6690 tooltipTimeout = window.setTimeout(function() { tooltipDiv.removeAttribute('style'); },
250);
6692 tooltipDiv.dispatchEvent(new CustomEvent('tooltip-close', { bubbles: true }));
6696 * Add a notification banner at the top of the current view.
6698 * A notification banner is an alert message usually displayed at the
6699 * top of the current view, spanning the entire availibe width.
6700 * Notification banners will stay in place until dismissed by the user.
6701 * Multiple banners may be shown at the same time.
6703 * Additional CSS class names may be passed to influence the appearence of
6704 * the banner. Valid values for the classes depend on the underlying theme.
6706 * @see LuCI.dom.content
6708 * @param {string} [title]
6709 * The title of the notification banner. If `null`, no title element
6712 * @param {*} contents
6713 * The contents to add to the notification banner. This should be a DOM
6714 * node or a document fragment in most cases. The value is passed as-is
6715 * to the `dom.content()` function - refer to its documentation for
6716 * applicable values.
6718 * @param {...string} [classes]
6719 * A number of extra CSS class names which are set on the notification
6723 * Returns a DOM Node representing the notification banner element.
6725 addNotification: function(title, children /*, ... */) {
6726 var mc = document.querySelector('#maincontent') || document.body;
6727 var msg = E('div', {
6728 'class': 'alert-message fade-in',
6729 'style': 'display:flex',
6730 'transitionend': function(ev) {
6731 var node = ev.currentTarget;
6732 if (node.parentNode
&& node.classList.contains('fade-out'))
6733 node.parentNode.removeChild(node);
6736 E('div', { 'style': 'flex:
10' }),
6737 E('div', { 'style': 'flex:
1 1 auto; display:flex' }, [
6740 'style': 'margin-left:auto; margin-top:auto',
6741 'click': function(ev) {
6742 dom.parent(ev.target, '.alert-message').classList.add('fade-out');
6745 }, [ _('Dismiss') ])
6750 dom.append(msg.firstElementChild, E('h4', {}, title));
6752 dom.append(msg.firstElementChild, children);
6754 for (var i =
2; i
< arguments.length; i++)
6755 msg.classList.add(arguments[i]);
6757 mc.insertBefore(msg, mc.firstElementChild);
6763 * Display or update an header area indicator.
6765 * An indicator is a small label displayed in the header area of the screen
6766 * providing few amounts of status information such as item counts or state
6767 * toggle indicators.
6769 * Multiple indicators may be shown at the same time and indicator labels
6770 * may be made clickable to display extended information or to initiate
6773 * Indicators can either use a default `active` or a less accented `inactive`
6774 * style which is useful for indicators representing state toggles.
6776 * @param {string} id
6777 * The ID of the indicator. If an indicator with the given ID already exists,
6778 * it is updated with the given label and style.
6780 * @param {string} label
6781 * The text to display in the indicator label.
6783 * @param {function} [handler]
6784 * A handler function to invoke when the indicator label is clicked/touched
6785 * by the user. If omitted, the indicator is not clickable/touchable.
6787 * Note that this parameter only applies to new indicators, when updating
6788 * existing labels it is ignored.
6790 * @param {string} [style=active]
6791 * The indicator style to use. May be either `active` or `inactive`.
6793 * @returns {boolean}
6794 * Returns `true` when the indicator has been updated or `false` when no
6795 * changes were made.
6797 showIndicator: function(id, label, handler, style) {
6798 if (indicatorDiv == null) {
6799 indicatorDiv = document.body.querySelector('#indicators');
6801 if (indicatorDiv == null)
6805 var handlerFn = (typeof(handler) == 'function') ? handler : null,
6806 indicatorElem = indicatorDiv.querySelector('span[
data-indicator=
"%s"]'.format(id));
6808 if (indicatorElem == null) {
6809 var beforeElem = null;
6811 for (beforeElem = indicatorDiv.firstElementChild;
6813 beforeElem = beforeElem.nextElementSibling)
6814 if (beforeElem.getAttribute('data-indicator')
> id)
6817 indicatorElem = indicatorDiv.insertBefore(E('span', {
6818 'data-indicator': id,
6819 'data-clickable': handlerFn ? true : null,
6821 }, ['']), beforeElem);
6824 if (label == indicatorElem.firstChild.data
&& style == indicatorElem.getAttribute('data-style'))
6827 indicatorElem.firstChild.data = label;
6828 indicatorElem.setAttribute('data-style', (style == 'inactive') ? 'inactive' : 'active');
6833 * Remove an header area indicator.
6835 * This function removes the given indicator label from the header indicator
6836 * area. When the given indicator is not found, this function does nothing.
6838 * @param {string} id
6839 * The ID of the indicator to remove.
6841 * @returns {boolean}
6842 * Returns `true` when the indicator has been removed or `false` when the
6843 * requested indicator was not found.
6845 hideIndicator: function(id) {
6846 var indicatorElem = indicatorDiv ? indicatorDiv.querySelector('span[
data-indicator=
"%s"]'.format(id)) : null;
6848 if (indicatorElem == null)
6851 indicatorDiv.removeChild(indicatorElem);
6856 * Formats a series of label/value pairs into list-like markup.
6858 * This function transforms a flat array of alternating label and value
6859 * elements into a list-like markup, using the values in `separators` as
6860 * separators and appends the resulting nodes to the given parent DOM node.
6862 * Each label is suffixed with `: ` and wrapped into a `
<strong
>` tag, the
6863 * `
<strong
>` element and the value corresponding to the label are
6864 * subsequently wrapped into a `
<span
class=
"nowrap">` element.
6866 * The resulting `
<span
>` element tuples are joined by the given separators
6867 * to form the final markup which is appened to the given parent DOM node.
6869 * @param {Node} node
6870 * The parent DOM node to append the markup to. Any previous child elements
6873 * @param {Array
<*
>} items
6874 * An alternating array of labels and values. The label values will be
6875 * converted to plain strings, the values are used as-is and may be of
6876 * any type accepted by `LuCI.dom.content()`.
6878 * @param {*|Array
<*
>} [separators=[E('br')]]
6879 * A single value or an array of separator values to separate each
6880 * label/value pair with. The function will cycle through the separators
6881 * when joining the pairs. If omitted, the default separator is a sole HTML
6882 * `
<br
>` element. Separator values are used as-is and may be of any type
6883 * accepted by `LuCI.dom.content()`.
6886 * Returns the parent DOM node the formatted markup has been added to.
6888 itemlist: function(node, items, separators) {
6891 if (!Array.isArray(separators))
6892 separators = [ separators || E('br') ];
6894 for (var i =
0; i
< items.length; i +=
2) {
6895 if (items[i+
1] !== null
&& items[i+
1] !== undefined) {
6896 var sep = separators[(i/
2) % separators.length],
6899 children.push(E('span', { class: 'nowrap' }, [
6900 items[i] ? E('strong', items[i] + ': ') : '',
6904 if ((i+
2)
< items.length)
6905 children.push(dom.elem(sep) ? sep.cloneNode(true) : sep);
6909 dom.content(node, children);
6920 * The `tabs` class handles tab menu groups used throughout the view area.
6921 * It takes care of setting up tab groups, tracking their state and handling
6924 * This class is automatically instantiated as part of `LuCI.ui`. To use it
6925 * in views, use `'require ui'` and refer to `ui.tabs`. To import it in
6926 * external JavaScript, use `L.require(
"ui").then(...)` and access the
6927 * `tabs` property of the class instance value.
6929 tabs: baseclass.singleton(/* @lends LuCI.ui.tabs.prototype */ {
6932 var groups = [], prevGroup = null, currGroup = null;
6934 document.querySelectorAll('[data-tab]').forEach(function(tab) {
6935 var parent = tab.parentNode;
6937 if (dom.matches(tab, 'li')
&& dom.matches(parent, 'ul.cbi-tabmenu'))
6940 if (!parent.hasAttribute('data-tab-group'))
6941 parent.setAttribute('data-tab-group', groups.length);
6943 currGroup = +parent.getAttribute('data-tab-group');
6945 if (currGroup !== prevGroup) {
6946 prevGroup = currGroup;
6948 if (!groups[currGroup])
6949 groups[currGroup] = [];
6952 groups[currGroup].push(tab);
6955 for (var i =
0; i
< groups.length; i++)
6956 this.initTabGroup(groups[i]);
6958 document.addEventListener('dependency-update', this.updateTabs.bind(this));
6964 * Initializes a new tab group from the given tab pane collection.
6966 * This function cycles through the given tab pane DOM nodes, extracts
6967 * their tab IDs, titles and active states, renders a corresponding
6968 * tab menu and prepends it to the tab panes common parent DOM node.
6970 * The tab menu labels will be set to the value of the `data-tab-title`
6971 * attribute of each corresponding pane. The last pane with the
6972 * `data-tab-active` attribute set to `true` will be selected by default.
6974 * If no pane is marked as active, the first one will be preselected.
6977 * @memberof LuCI.ui.tabs
6978 * @param {Array
<Node
>|NodeList} panes
6979 * A collection of tab panes to build a tab group menu for. May be a
6980 * plain array of DOM nodes or a NodeList collection, such as the result
6981 * of a `querySelectorAll()` call or the `.childNodes` property of a
6984 initTabGroup: function(panes) {
6985 if (typeof(panes) != 'object' || !('length' in panes) || panes.length ===
0)
6988 var menu = E('ul', { 'class': 'cbi-tabmenu' }),
6989 group = panes[
0].parentNode,
6990 groupId = +group.getAttribute('data-tab-group'),
6993 if (group.getAttribute('data-initialized') === 'true')
6996 for (var i =
0, pane; pane = panes[i]; i++) {
6997 var name = pane.getAttribute('data-tab'),
6998 title = pane.getAttribute('data-tab-title'),
6999 active = pane.getAttribute('data-tab-active') === 'true';
7001 menu.appendChild(E('li', {
7002 'style': this.isEmptyPane(pane) ? 'display:none' : null,
7003 'class': active ? 'cbi-tab' : 'cbi-tab-disabled',
7007 'click': this.switchTab.bind(this)
7014 group.parentNode.insertBefore(menu, group);
7015 group.setAttribute('data-initialized', true);
7017 if (selected === null) {
7018 selected = this.getActiveTabId(panes[
0]);
7020 if (selected
< 0 || selected
>= panes.length || this.isEmptyPane(panes[selected])) {
7021 for (var i =
0; i
< panes.length; i++) {
7022 if (!this.isEmptyPane(panes[i])) {
7029 menu.childNodes[selected].classList.add('cbi-tab');
7030 menu.childNodes[selected].classList.remove('cbi-tab-disabled');
7031 panes[selected].setAttribute('data-tab-active', 'true');
7033 this.setActiveTabId(panes[selected], selected);
7036 panes[selected].dispatchEvent(new CustomEvent('cbi-tab-active', {
7037 detail: { tab: panes[selected].getAttribute('data-tab') }
7040 this.updateTabs(group);
7044 * Checks whether the given tab pane node is empty.
7047 * @memberof LuCI.ui.tabs
7048 * @param {Node} pane
7049 * The tab pane to check.
7051 * @returns {boolean}
7052 * Returns `true` if the pane is empty, else `false`.
7054 isEmptyPane: function(pane) {
7055 return dom.isEmpty(pane, function(n) { return n.classList.contains('cbi-tab-descr') });
7059 getPathForPane: function(pane) {
7060 var path = [], node = null;
7062 for (node = pane ? pane.parentNode : null;
7063 node != null
&& node.hasAttribute != null;
7064 node = node.parentNode)
7066 if (node.hasAttribute('data-tab'))
7067 path.unshift(node.getAttribute('data-tab'));
7068 else if (node.hasAttribute('data-section-id'))
7069 path.unshift(node.getAttribute('data-section-id'));
7072 return path.join('/');
7076 getActiveTabState: function() {
7077 var page = document.body.getAttribute('data-page'),
7078 state = session.getLocalData('tab');
7080 if (L.isObject(state)
&& state.page === page
&& L.isObject(state.paths))
7083 session.setLocalData('tab', null);
7085 return { page: page, paths: {} };
7089 getActiveTabId: function(pane) {
7090 var path = this.getPathForPane(pane);
7091 return +this.getActiveTabState().paths[path] ||
0;
7095 setActiveTabId: function(pane, tabIndex) {
7096 var path = this.getPathForPane(pane),
7097 state = this.getActiveTabState();
7099 state.paths[path] = tabIndex;
7101 return session.setLocalData('tab', state);
7105 updateTabs: function(ev, root) {
7106 (root || document).querySelectorAll('[data-tab-title]').forEach(L.bind(function(pane) {
7107 var menu = pane.parentNode.previousElementSibling,
7108 tab = menu ? menu.querySelector('[
data-tab=
"%s"]'.format(pane.getAttribute('data-tab'))) : null,
7109 n_errors = pane.querySelectorAll('.cbi-input-invalid').length;
7114 if (this.isEmptyPane(pane)) {
7115 tab.style.display = 'none';
7116 tab.classList.remove('flash');
7118 else if (tab.style.display === 'none') {
7119 tab.style.display = '';
7120 requestAnimationFrame(function() { tab.classList.add('flash') });
7124 tab.setAttribute('data-errors', n_errors);
7125 tab.setAttribute('data-tooltip', _('%d invalid field(s)').format(n_errors));
7126 tab.setAttribute('data-tooltip-style', 'error');
7129 tab.removeAttribute('data-errors');
7130 tab.removeAttribute('data-tooltip');
7136 switchTab: function(ev) {
7137 var tab = ev.target.parentNode,
7138 name = tab.getAttribute('data-tab'),
7139 menu = tab.parentNode,
7140 group = menu.nextElementSibling,
7141 groupId = +group.getAttribute('data-tab-group'),
7144 ev.preventDefault();
7146 if (!tab.classList.contains('cbi-tab-disabled'))
7149 menu.querySelectorAll('[data-tab]').forEach(function(tab) {
7150 tab.classList.remove('cbi-tab');
7151 tab.classList.remove('cbi-tab-disabled');
7153 tab.getAttribute('data-tab') === name ? 'cbi-tab' : 'cbi-tab-disabled');
7156 group.childNodes.forEach(function(pane) {
7157 if (dom.matches(pane, '[data-tab]')) {
7158 if (pane.getAttribute('data-tab') === name) {
7159 pane.setAttribute('data-tab-active', 'true');
7160 pane.dispatchEvent(new CustomEvent('cbi-tab-active', { detail: { tab: name } }));
7161 UI.prototype.tabs.setActiveTabId(pane, index);
7164 pane.setAttribute('data-tab-active', 'false');
7174 * @typedef {Object} FileUploadReply
7177 * @property {string} name - Name of the uploaded file without directory components
7178 * @property {number} size - Size of the uploaded file in bytes
7179 * @property {string} checksum - The MD5 checksum of the received file data
7180 * @property {string} sha256sum - The SHA256 checksum of the received file data
7184 * Display a modal file upload prompt.
7186 * This function opens a modal dialog prompting the user to select and
7187 * upload a file to a predefined remote destination path.
7189 * @param {string} path
7190 * The remote file path to upload the local file to.
7192 * @param {Node} [progessStatusNode]
7193 * An optional DOM text node whose content text is set to the progress
7194 * percentage value during file upload.
7196 * @returns {Promise
<LuCI.ui.FileUploadReply
>}
7197 * Returns a promise resolving to a file upload status object on success
7198 * or rejecting with an error in case the upload failed or has been
7199 * cancelled by the user.
7201 uploadFile: function(path, progressStatusNode) {
7202 return new Promise(function(resolveFn, rejectFn) {
7203 UI.prototype.showModal(_('Uploading file…'), [
7204 E('p', _('Please select the file to upload.')),
7205 E('div', { 'style': 'display:flex' }, [
7206 E('div', { 'class': 'left', 'style': 'flex:
1' }, [
7209 style: 'display:none',
7210 change: function(ev) {
7211 var modal = dom.parent(ev.target, '.modal'),
7212 body = modal.querySelector('p'),
7213 upload = modal.querySelector('.cbi-button-action.important'),
7214 file = ev.currentTarget.files[
0];
7221 E('li', {}, [ '%s: %s'.format(_('Name'), file.name.replace(/^.*[\\\/]/, '')) ]),
7222 E('li', {}, [ '%s: %
1024mB'.format(_('Size'), file.size) ])
7226 upload.disabled = false;
7232 'click': function(ev) {
7233 ev.target.previousElementSibling.click();
7235 }, [ _('Browse…') ])
7237 E('div', { 'class': 'right', 'style': 'flex:
1' }, [
7240 'click': function() {
7241 UI.prototype.hideModal();
7242 rejectFn(new Error('Upload has been cancelled'));
7244 }, [ _('Cancel') ]),
7247 'class': 'btn cbi-button-action important',
7249 'click': function(ev) {
7250 var input = dom.parent(ev.target, '.modal').querySelector('input[
type=
"file"]');
7252 if (!input.files[
0])
7255 var progress = E('div', { 'class': 'cbi-progressbar', 'title': '
0%' }, E('div', { 'style': 'width:
0' }));
7257 UI.prototype.showModal(_('Uploading file…'), [ progress ]);
7259 var data = new FormData();
7261 data.append('sessionid', rpc.getSessionID());
7262 data.append('filename', path);
7263 data.append('filedata', input.files[
0]);
7265 var filename = input.files[
0].name;
7267 request.post(L.env.cgi_base + '/cgi-upload', data, {
7269 progress: function(pev) {
7270 var percent = (pev.loaded / pev.total) *
100;
7272 if (progressStatusNode)
7273 progressStatusNode.data = '%
.2f%%'.format(percent);
7275 progress.setAttribute('title', '%
.2f%%'.format(percent));
7276 progress.firstElementChild.style.width = '%
.2f%%'.format(percent);
7278 }).then(function(res) {
7279 var reply = res.json();
7281 UI.prototype.hideModal();
7283 if (L.isObject(reply)
&& reply.failure) {
7284 UI.prototype.addNotification(null, E('p', _('Upload request failed: %s').format(reply.message)));
7285 rejectFn(new Error(reply.failure));
7288 reply.name = filename;
7292 UI.prototype.hideModal();
7304 * Perform a device connectivity test.
7306 * Attempt to fetch a well known ressource from the remote device via HTTP
7307 * in order to test connectivity. This function is mainly useful to wait
7308 * for the router to come back online after a reboot or reconfiguration.
7310 * @param {string} [proto=http]
7311 * The protocol to use for fetching the resource. May be either `http`
7312 * (the default) or `https`.
7314 * @param {string} [host=window.location.host]
7315 * Override the host address to probe. By default the current host as seen
7316 * in the address bar is probed.
7318 * @returns {Promise
<Event
>}
7319 * Returns a promise resolving to a `load` event in case the device is
7320 * reachable or rejecting with an `error` event in case it is not reachable
7321 * or rejecting with `null` when the connectivity check timed out.
7323 pingDevice: function(proto, ipaddr) {
7324 var target = '%s://%s%s?%s'.format(proto || 'http', ipaddr || window.location.host, L.resource('icons/loading.gif'), Math.random());
7326 return new Promise(function(resolveFn, rejectFn) {
7327 var img = new Image();
7329 img.onload = resolveFn;
7330 img.onerror = rejectFn;
7332 window.setTimeout(rejectFn,
1000);
7339 * Wait for device to come back online and reconnect to it.
7341 * Poll each given hostname or IP address and navigate to it as soon as
7342 * one of the addresses becomes reachable.
7344 * @param {...string} [hosts=[window.location.host]]
7345 * The list of IP addresses and host names to check for reachability.
7346 * If omitted, the current value of `window.location.host` is used by
7349 awaitReconnect: function(/* ... */) {
7350 var ipaddrs = arguments.length ? arguments : [ window.location.host ];
7352 window.setTimeout(L.bind(function() {
7353 poll.add(L.bind(function() {
7354 var tasks = [], reachable = false;
7356 for (var i =
0; i
< 2; i++)
7357 for (var j =
0; j
< ipaddrs.length; j++)
7358 tasks.push(this.pingDevice(i ? 'https' : 'http', ipaddrs[j])
7359 .then(function(ev) { reachable = ev.target.src.replace(/^(https?:\/\/[^\/]+).*$/, '$
1/') }, function() {}));
7361 return Promise.all(tasks).then(function() {
7364 window.location = reachable;
7377 * The `changes` class encapsulates logic for visualizing, applying,
7378 * confirming and reverting staged UCI changesets.
7380 * This class is automatically instantiated as part of `LuCI.ui`. To use it
7381 * in views, use `'require ui'` and refer to `ui.changes`. To import it in
7382 * external JavaScript, use `L.require(
"ui").then(...)` and access the
7383 * `changes` property of the class instance value.
7385 changes: baseclass.singleton(/* @lends LuCI.ui.changes.prototype */ {
7387 if (!L.env.sessionid)
7390 return uci.changes().then(L.bind(this.renderChangeIndicator, this));
7394 * Set the change count indicator.
7396 * This function updates or hides the UCI change count indicator,
7397 * depending on the passed change count. When the count is greater
7398 * than
0, the change indicator is displayed or updated, otherwise it
7402 * @memberof LuCI.ui.changes
7403 * @param {number} numChanges
7404 * The number of changes to indicate.
7406 setIndicator: function(n) {
7408 UI.prototype.showIndicator('uci-changes',
7409 '%s: %d'.format(_('Unsaved Changes'), n),
7410 L.bind(this.displayChanges, this));
7413 UI.prototype.hideIndicator('uci-changes');
7418 * Update the change count indicator.
7420 * This function updates the UCI change count indicator from the given
7421 * UCI changeset structure.
7424 * @memberof LuCI.ui.changes
7425 * @param {Object
<string, Array
<LuCI.uci.ChangeRecord
>>} changes
7426 * The UCI changeset to count.
7428 renderChangeIndicator: function(changes) {
7431 for (var config in changes)
7432 if (changes.hasOwnProperty(config))
7433 n_changes += changes[config].length;
7435 this.changes = changes;
7436 this.setIndicator(n_changes);
7441 'add-
3': '
<ins
>uci add %
0 <strong
>%
3</strong
> # =%
2</ins
>',
7442 'set-
3': '
<ins
>uci set %
0.
<strong
>%
2</strong
>=%
3</ins
>',
7443 'set-
4': '
<var
><ins
>uci set %
0.%
2.%
3=
<strong
>%
4</strong
></ins
></var
>',
7444 'remove-
2': '
<del
>uci del %
0.
<strong
>%
2</strong
></del
>',
7445 'remove-
3': '
<var
><del
>uci del %
0.%
2.
<strong
>%
3</strong
></del
></var
>',
7446 'order-
3': '
<var
>uci reorder %
0.%
2=
<strong
>%
3</strong
></var
>',
7447 'list-add-
4': '
<var
><ins
>uci add_list %
0.%
2.%
3=
<strong
>%
4</strong
></ins
></var
>',
7448 'list-del-
4': '
<var
><del
>uci del_list %
0.%
2.%
3=
<strong
>%
4</strong
></del
></var
>',
7449 'rename-
3': '
<var
>uci rename %
0.%
2=
<strong
>%
3</strong
></var
>',
7450 'rename-
4': '
<var
>uci rename %
0.%
2.%
3=
<strong
>%
4</strong
></var
>'
7454 * Display the current changelog.
7456 * Open a modal dialog visualizing the currently staged UCI changes
7457 * and offer options to revert or apply the shown changes.
7460 * @memberof LuCI.ui.changes
7462 displayChanges: function() {
7463 var list = E('div', { 'class': 'uci-change-list' }),
7464 dlg = UI.prototype.showModal(_('Configuration') + ' / ' + _('Changes'), [
7465 E('div', { 'class': 'cbi-section' }, [
7466 E('strong', _('Legend:')),
7467 E('div', { 'class': 'uci-change-legend' }, [
7468 E('div', { 'class': 'uci-change-legend-label' }, [
7469 E('ins', '
&#
160;'), ' ', _('Section added') ]),
7470 E('div', { 'class': 'uci-change-legend-label' }, [
7471 E('del', '
&#
160;'), ' ', _('Section removed') ]),
7472 E('div', { 'class': 'uci-change-legend-label' }, [
7473 E('var', {}, E('ins', '
&#
160;')), ' ', _('Option changed') ]),
7474 E('div', { 'class': 'uci-change-legend-label' }, [
7475 E('var', {}, E('del', '
&#
160;')), ' ', _('Option removed') ])]),
7477 E('div', { 'class': 'right' }, [
7480 'click': UI.prototype.hideModal
7481 }, [ _('Dismiss') ]), ' ',
7483 'class': 'cbi-button cbi-button-positive important',
7484 'click': L.bind(this.apply, this, true)
7485 }, [ _('Save
& Apply') ]), ' ',
7487 'class': 'cbi-button cbi-button-reset',
7488 'click': L.bind(this.revert, this)
7489 }, [ _('Revert') ])])])
7492 for (var config in this.changes) {
7493 if (!this.changes.hasOwnProperty(config))
7496 list.appendChild(E('h5', '# /etc/config/%s'.format(config)));
7498 for (var i =
0, added = null; i
< this.changes[config].length; i++) {
7499 var chg = this.changes[config][i],
7500 tpl = this.changeTemplates['%s-%d'.format(chg[
0], chg.length)];
7502 list.appendChild(E(tpl.replace(/%([
01234])/g, function(m0, m1) {
7508 if (added != null
&& chg[
1] == added[
0])
7509 return '@' + added[
1] + '[-
1]';
7514 return
"'%h'".format(chg[
3].replace(/'/g,
"'\"'\
"'"));
7521 if (chg[
0] == 'add')
7522 added = [ chg[
1], chg[
2] ];
7526 list.appendChild(E('br'));
7527 dlg.classList.add('uci-dialog');
7531 displayStatus: function(type, content) {
7533 var message = UI.prototype.showModal('', '');
7535 message.classList.add('alert-message');
7536 DOMTokenList.prototype.add.apply(message.classList, type.split(/\s+/));
7539 dom.content(message, content);
7541 if (!this.was_polling) {
7542 this.was_polling = request.poll.active();
7543 request.poll.stop();
7547 UI.prototype.hideModal();
7549 if (this.was_polling)
7550 request.poll.start();
7555 rollback: function(checked) {
7557 this.displayStatus('warning spinning',
7558 E('p', _('Failed to confirm apply within %ds, waiting for rollback…')
7559 .format(L.env.apply_rollback)));
7561 var call = function(r, data, duration) {
7562 if (r.status ===
204) {
7563 UI.prototype.changes.displayStatus('warning', [
7564 E('h4', _('Configuration changes have been rolled back!')),
7565 E('p', _('The device could not be reached within %d seconds after applying the pending changes, which caused the configuration to be rolled back for safety reasons. If you believe that the configuration changes are correct nonetheless, perform an unchecked configuration apply. Alternatively, you can dismiss this warning and edit changes before attempting to apply again, or revert all pending changes to keep the currently working configuration state.').format(L.env.apply_rollback)),
7566 E('div', { 'class': 'right' }, [
7569 'click': L.bind(UI.prototype.changes.displayStatus, UI.prototype.changes, false)
7570 }, [ _('Dismiss') ]), ' ',
7572 'class': 'btn cbi-button-action important',
7573 'click': L.bind(UI.prototype.changes.revert, UI.prototype.changes)
7574 }, [ _('Revert changes') ]), ' ',
7576 'class': 'btn cbi-button-negative important',
7577 'click': L.bind(UI.prototype.changes.apply, UI.prototype.changes, false)
7578 }, [ _('Apply unchecked') ])
7585 var delay = isNaN(duration) ?
0 : Math.max(
1000 - duration,
0);
7586 window.setTimeout(function() {
7587 request.request(L.url('admin/uci/confirm'), {
7589 timeout: L.env.apply_timeout *
1000,
7590 query: { sid: L.env.sessionid, token: L.env.token }
7595 call({ status:
0 });
7598 this.displayStatus('warning', [
7599 E('h4', _('Device unreachable!')),
7600 E('p', _('Could not regain access to the device after applying the configuration changes. You might need to reconnect if you modified network related settings such as the IP address or wireless security credentials.'))
7606 confirm: function(checked, deadline, override_token) {
7608 var ts = Date.now();
7610 this.displayStatus('notice');
7613 this.confirm_auth = { token: override_token };
7615 var call = function(r, data, duration) {
7616 if (Date.now()
>= deadline) {
7617 window.clearTimeout(tt);
7618 UI.prototype.changes.rollback(checked);
7621 else if (r
&& (r.status ===
200 || r.status ===
204)) {
7622 document.dispatchEvent(new CustomEvent('uci-applied'));
7624 UI.prototype.changes.setIndicator(
0);
7625 UI.prototype.changes.displayStatus('notice',
7626 E('p', _('Configuration changes applied.')));
7628 window.clearTimeout(tt);
7629 window.setTimeout(function() {
7630 //UI.prototype.changes.displayStatus(false);
7631 window.location = window.location.href.split('#')[
0];
7632 }, L.env.apply_display *
1000);
7637 var delay = isNaN(duration) ?
0 : Math.max(
1000 - duration,
0);
7638 window.setTimeout(function() {
7639 request.request(L.url('admin/uci/confirm'), {
7641 timeout: L.env.apply_timeout *
1000,
7642 query: UI.prototype.changes.confirm_auth
7643 }).then(call, call);
7647 var tick = function() {
7648 var now = Date.now();
7650 UI.prototype.changes.displayStatus('notice spinning',
7651 E('p', _('Applying configuration changes… %ds')
7652 .format(Math.max(Math.floor((deadline - Date.now()) /
1000),
0))));
7654 if (now
>= deadline)
7657 tt = window.setTimeout(tick,
1000 - (now - ts));
7663 /* wait a few seconds for the settings to become effective */
7664 window.setTimeout(call, Math.max(L.env.apply_holdoff *
1000 - ((ts + L.env.apply_rollback *
1000) - deadline),
1));
7668 * Apply the staged configuration changes.
7670 * Start applying staged configuration changes and open a modal dialog
7671 * with a progress indication to prevent interaction with the view
7672 * during the apply process. The modal dialog will be automatically
7673 * closed and the current view reloaded once the apply process is
7677 * @memberof LuCI.ui.changes
7678 * @param {boolean} [checked=false]
7679 * Whether to perform a checked (`true`) configuration apply or an
7680 * unchecked (`false`) one.
7682 * In case of a checked apply, the configuration changes must be
7683 * confirmed within a specific time interval, otherwise the device
7684 * will begin to roll back the changes in order to restore the previous
7687 apply: function(checked) {
7688 this.displayStatus('notice spinning',
7689 E('p', _('Starting configuration apply…')));
7691 request.request(L.url('admin/uci', checked ? 'apply_rollback' : 'apply_unchecked'), {
7693 query: { sid: L.env.sessionid, token: L.env.token }
7694 }).then(function(r) {
7695 if (r.status === (checked ?
200 :
204)) {
7696 var tok = null; try { tok = r.json(); } catch(e) {}
7697 if (checked
&& tok !== null
&& typeof(tok) === 'object'
&& typeof(tok.token) === 'string')
7698 UI.prototype.changes.confirm_auth = tok;
7700 UI.prototype.changes.confirm(checked, Date.now() + L.env.apply_rollback *
1000);
7702 else if (checked
&& r.status ===
204) {
7703 UI.prototype.changes.displayStatus('notice',
7704 E('p', _('There are no changes to apply')));
7706 window.setTimeout(function() {
7707 UI.prototype.changes.displayStatus(false);
7708 }, L.env.apply_display *
1000);
7711 UI.prototype.changes.displayStatus('warning',
7712 E('p', _('Apply request failed with status
<code
>%h
</code
>')
7713 .format(r.responseText || r.statusText || r.status)));
7715 window.setTimeout(function() {
7716 UI.prototype.changes.displayStatus(false);
7717 }, L.env.apply_display *
1000);
7723 * Revert the staged configuration changes.
7725 * Start reverting staged configuration changes and open a modal dialog
7726 * with a progress indication to prevent interaction with the view
7727 * during the revert process. The modal dialog will be automatically
7728 * closed and the current view reloaded once the revert process is
7732 * @memberof LuCI.ui.changes
7734 revert: function() {
7735 this.displayStatus('notice spinning',
7736 E('p', _('Reverting configuration…')));
7738 request.request(L.url('admin/uci/revert'), {
7740 query: { sid: L.env.sessionid, token: L.env.token }
7741 }).then(function(r) {
7742 if (r.status ===
200) {
7743 document.dispatchEvent(new CustomEvent('uci-reverted'));
7745 UI.prototype.changes.setIndicator(
0);
7746 UI.prototype.changes.displayStatus('notice',
7747 E('p', _('Changes have been reverted.')));
7749 window.setTimeout(function() {
7750 //UI.prototype.changes.displayStatus(false);
7751 window.location = window.location.href.split('#')[
0];
7752 }, L.env.apply_display *
1000);
7755 UI.prototype.changes.displayStatus('warning',
7756 E('p', _('Revert request failed with status
<code
>%h
</code
>')
7757 .format(r.statusText || r.status)));
7759 window.setTimeout(function() {
7760 UI.prototype.changes.displayStatus(false);
7761 }, L.env.apply_display *
1000);
7768 * Add validation constraints to an input element.
7770 * Compile the given type expression and optional validator function into
7771 * a validation function and bind it to the specified input element events.
7773 * @param {Node} field
7774 * The DOM input element node to bind the validation constraints to.
7776 * @param {string} type
7777 * The datatype specification to describe validation constraints.
7778 * Refer to the `LuCI.validation` class documentation for details.
7780 * @param {boolean} [optional=false]
7781 * Specifies whether empty values are allowed (`true`) or not (`false`).
7782 * If an input element is not marked optional it must not be empty,
7783 * otherwise it will be marked as invalid.
7785 * @param {function} [vfunc]
7786 * Specifies a custom validation function which is invoked after the
7787 * other validation constraints are applied. The validation must return
7788 * `true` to accept the passed value. Any other return type is converted
7789 * to a string and treated as validation error message.
7791 * @param {...string} [events=blur, keyup]
7792 * The list of events to bind. Each received event will trigger a field
7793 * validation. If omitted, the `keyup` and `blur` events are bound by
7796 * @returns {function}
7797 * Returns the compiled validator function which can be used to manually
7798 * trigger field validation or to bind it to further events.
7800 * @see LuCI.validation
7802 addValidator: function(field, type, optional, vfunc /*, ... */) {
7806 var events = this.varargs(arguments,
3);
7807 if (events.length ==
0)
7808 events.push('blur', 'keyup');
7811 var cbiValidator = validation.create(field, type, optional, vfunc),
7812 validatorFn = cbiValidator.validate.bind(cbiValidator);
7814 for (var i =
0; i
< events.length; i++)
7815 field.addEventListener(events[i], validatorFn);
7825 * Create a pre-bound event handler function.
7827 * Generate and bind a function suitable for use in event handlers. The
7828 * generated function automatically disables the event source element
7829 * and adds an active indication to it by adding appropriate CSS classes.
7831 * It will also await any promises returned by the wrapped function and
7832 * re-enable the source element after the promises ran to completion.
7835 * The `this` context to use for the wrapped function.
7837 * @param {function|string} fn
7838 * Specifies the function to wrap. In case of a function value, the
7839 * function is used as-is. If a string is specified instead, it is looked
7840 * up in `ctx` to obtain the function to wrap. In both cases the bound
7841 * function will be invoked with `ctx` as `this` context
7843 * @param {...*} extra_args
7844 * Any further parameter as passed as-is to the bound event handler
7845 * function in the same order as passed to `createHandlerFn()`.
7847 * @returns {function|null}
7848 * Returns the pre-bound handler function which is suitable to be passed
7849 * to `addEventListener()`. Returns `null` if the given `fn` argument is
7850 * a string which could not be found in `ctx` or if `ctx[fn]` is not a
7851 * valid function value.
7853 createHandlerFn: function(ctx, fn /*, ... */) {
7854 if (typeof(fn) == 'string')
7857 if (typeof(fn) != 'function')
7860 var arg_offset = arguments.length -
2;
7862 return Function.prototype.bind.apply(function() {
7863 var t = arguments[arg_offset].currentTarget;
7865 t.classList.add('spinning');
7871 Promise.resolve(fn.apply(ctx, arguments)).finally(function() {
7872 t.classList.remove('spinning');
7875 }, this.varargs(arguments,
2, ctx));
7879 * Load specified view class path and set it up.
7881 * Transforms the given view path into a class name, requires it
7882 * using [LuCI.require()]{@link LuCI#require} and asserts that the
7883 * resulting class instance is a descendant of
7884 * [LuCI.view]{@link LuCI.view}.
7886 * By instantiating the view class, its corresponding contents are
7887 * rendered and included into the view area. Any runtime errors are
7888 * catched and rendered using [LuCI.error()]{@link LuCI#error}.
7890 * @param {string} path
7891 * The view path to render.
7893 * @returns {Promise
<LuCI.view
>}
7894 * Returns a promise resolving to the loaded view instance.
7896 instantiateView: function(path) {
7897 var className = 'view.%s'.format(path.replace(/\//g, '.'));
7899 return L.require(className).then(function(view) {
7900 if (!(view instanceof View))
7901 throw new TypeError('Loaded class %s is not a descendant of View'.format(className));
7904 }).catch(function(err) {
7905 dom.content(document.querySelector('#view'), null);
7912 AbstractElement: UIElement,
7915 Textfield: UITextfield,
7916 Textarea: UITextarea,
7917 Checkbox: UICheckbox,
7919 Dropdown: UIDropdown,
7920 DynamicList: UIDynamicList,
7921 Combobox: UICombobox,
7922 ComboButton: UIComboButton,
7923 Hiddenfield: UIHiddenfield,
7924 FileUpload: UIFileUpload
7940 Documentation generated by
<a href=
"https://github.com/jsdoc3/jsdoc">JSDoc
3.6.3</a> on Thu Aug
06 2020 17:
58:
02 GMT+
0200 (Central European Summer Time)
7944 <script>prettyPrint();
</script>
7945 <script src=
"scripts/jaguar.js"></script>