From c1f972df1bb9a54048b4e6243c32e3ee856dd176 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Wed, 6 Oct 2021 19:06:28 -1000 Subject: [PATCH] docs: remove static jsapi content It should be dynamically created by a CI rather than being updated manually. This should result to more accurate docs. Signed-off-by: Paul Spooren --- docs/jsapi/LuCI.baseclass.html | 4686 -------- docs/jsapi/LuCI.dom.html | 6244 ----------- docs/jsapi/LuCI.form.AbstractElement.html | 4233 -------- docs/jsapi/LuCI.form.AbstractSection.html | 6132 ----------- docs/jsapi/LuCI.form.AbstractValue.html | 6991 ------------ docs/jsapi/LuCI.form.ButtonValue.html | 7312 ------------- docs/jsapi/LuCI.form.DummyValue.html | 7249 ------------- docs/jsapi/LuCI.form.DynamicList.html | 7149 ------------- docs/jsapi/LuCI.form.FileUpload.html | 7360 ------------- docs/jsapi/LuCI.form.FlagValue.html | 7238 ------------- docs/jsapi/LuCI.form.GridSection.html | 6892 ------------ docs/jsapi/LuCI.form.HiddenValue.html | 7153 ------------- docs/jsapi/LuCI.form.JSONMap.html | 5812 ---------- docs/jsapi/LuCI.form.ListValue.html | 7298 ------------- docs/jsapi/LuCI.form.Map.html | 5791 ---------- docs/jsapi/LuCI.form.MultiValue.html | 7249 ------------- docs/jsapi/LuCI.form.NamedSection.html | 6396 ----------- docs/jsapi/LuCI.form.SectionValue.html | 7180 ------------- docs/jsapi/LuCI.form.TableSection.html | 7068 ------------ docs/jsapi/LuCI.form.TextValue.html | 7196 ------------- docs/jsapi/LuCI.form.TypedSection.html | 6553 ------------ docs/jsapi/LuCI.form.Value.html | 7255 ------------- docs/jsapi/LuCI.form.html | 3654 ------- docs/jsapi/LuCI.fs.html | 5831 ---------- docs/jsapi/LuCI.headers.html | 3859 ------- docs/jsapi/LuCI.html | 8054 -------------- docs/jsapi/LuCI.network.Device.html | 5804 ---------- docs/jsapi/LuCI.network.Hosts.html | 4785 --------- docs/jsapi/LuCI.network.Protocol.html | 8015 -------------- docs/jsapi/LuCI.network.WifiDevice.html | 5151 --------- docs/jsapi/LuCI.network.WifiNetwork.html | 7644 ------------- docs/jsapi/LuCI.network.html | 9499 ----------------- docs/jsapi/LuCI.poll.html | 4242 -------- docs/jsapi/LuCI.request.html | 5177 --------- docs/jsapi/LuCI.request.poll.html | 4361 -------- docs/jsapi/LuCI.response.html | 4319 -------- docs/jsapi/LuCI.rpc.html | 5650 ---------- docs/jsapi/LuCI.session.html | 4089 ------- docs/jsapi/LuCI.uci.html | 7137 ------------- docs/jsapi/LuCI.ui.AbstractElement.html | 5093 --------- docs/jsapi/LuCI.ui.Checkbox.html | 5205 --------- docs/jsapi/LuCI.ui.ComboButton.html | 5235 --------- docs/jsapi/LuCI.ui.Combobox.html | 5138 --------- docs/jsapi/LuCI.ui.Dropdown.html | 5936 ---------- docs/jsapi/LuCI.ui.DynamicList.html | 5313 --------- docs/jsapi/LuCI.ui.FileUpload.html | 5162 --------- docs/jsapi/LuCI.ui.Hiddenfield.html | 4916 --------- docs/jsapi/LuCI.ui.Select.html | 5265 --------- docs/jsapi/LuCI.ui.Textarea.html | 5214 --------- docs/jsapi/LuCI.ui.Textfield.html | 5142 --------- docs/jsapi/LuCI.ui.changes.html | 4096 ------- docs/jsapi/LuCI.ui.html | 6189 ----------- docs/jsapi/LuCI.ui.menu.html | 4143 ------- docs/jsapi/LuCI.ui.tabs.html | 3843 ------- docs/jsapi/LuCI.view.html | 4447 -------- docs/jsapi/LuCI.xhr.html | 4411 -------- docs/jsapi/README.md | 4 - docs/jsapi/fonts/OpenSans-Bold-webfont.eot | Bin 19544 -> 0 bytes docs/jsapi/fonts/OpenSans-Bold-webfont.svg | 1830 ---- docs/jsapi/fonts/OpenSans-Bold-webfont.woff | Bin 22432 -> 0 bytes .../fonts/OpenSans-BoldItalic-webfont.eot | Bin 20133 -> 0 bytes .../fonts/OpenSans-BoldItalic-webfont.svg | 1830 ---- .../fonts/OpenSans-BoldItalic-webfont.woff | Bin 23048 -> 0 bytes docs/jsapi/fonts/OpenSans-Italic-webfont.eot | Bin 20265 -> 0 bytes docs/jsapi/fonts/OpenSans-Italic-webfont.svg | 1830 ---- docs/jsapi/fonts/OpenSans-Italic-webfont.woff | Bin 23188 -> 0 bytes docs/jsapi/fonts/OpenSans-Light-webfont.eot | Bin 19514 -> 0 bytes docs/jsapi/fonts/OpenSans-Light-webfont.svg | 1831 ---- docs/jsapi/fonts/OpenSans-Light-webfont.woff | Bin 22248 -> 0 bytes .../fonts/OpenSans-LightItalic-webfont.eot | Bin 20535 -> 0 bytes .../fonts/OpenSans-LightItalic-webfont.svg | 1835 ---- .../fonts/OpenSans-LightItalic-webfont.woff | Bin 23400 -> 0 bytes docs/jsapi/fonts/OpenSans-Regular-webfont.eot | Bin 19836 -> 0 bytes docs/jsapi/fonts/OpenSans-Regular-webfont.svg | 1831 ---- .../jsapi/fonts/OpenSans-Regular-webfont.woff | Bin 22660 -> 0 bytes .../fonts/glyphicons-halflings-regular.eot | Bin 20290 -> 0 bytes .../fonts/glyphicons-halflings-regular.svg | 229 - .../fonts/glyphicons-halflings-regular.ttf | Bin 41236 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 23292 -> 0 bytes docs/jsapi/form.js.html | 7854 -------------- docs/jsapi/fs.js.html | 3885 ------- docs/jsapi/index.html | 3472 ------ docs/jsapi/luci.js.html | 6874 ------------ docs/jsapi/network.js.html | 7618 ------------- docs/jsapi/rpc.js.html | 3944 ------- docs/jsapi/scripts/bootstrap.min.js | 7 - docs/jsapi/scripts/jaguar.js | 1 - docs/jsapi/scripts/jquery.min.js | 6 - docs/jsapi/scripts/jquery.min.map | 1 - docs/jsapi/scripts/linenumber.js | 25 - .../scripts/prettify/Apache-License-2.0.txt | 202 - docs/jsapi/scripts/prettify/lang-css.js | 2 - docs/jsapi/scripts/prettify/prettify.js | 28 - docs/jsapi/scripts/underscore-min.js | 6 - docs/jsapi/scripts/underscore-min.map | 1 - docs/jsapi/styles/bootstrap.min.css | 7 - docs/jsapi/styles/jaguar.css | 1 - docs/jsapi/styles/jsdoc-default.css | 358 - docs/jsapi/styles/prettify-jsdoc.css | 111 - docs/jsapi/styles/prettify-tomorrow.css | 132 - docs/jsapi/uci.js.html | 4421 -------- docs/jsapi/ui.js.html | 7947 -------------- 102 files changed, 386579 deletions(-) delete mode 100644 docs/jsapi/LuCI.baseclass.html delete mode 100644 docs/jsapi/LuCI.dom.html delete mode 100644 docs/jsapi/LuCI.form.AbstractElement.html delete mode 100644 docs/jsapi/LuCI.form.AbstractSection.html delete mode 100644 docs/jsapi/LuCI.form.AbstractValue.html delete mode 100644 docs/jsapi/LuCI.form.ButtonValue.html delete mode 100644 docs/jsapi/LuCI.form.DummyValue.html delete mode 100644 docs/jsapi/LuCI.form.DynamicList.html delete mode 100644 docs/jsapi/LuCI.form.FileUpload.html delete mode 100644 docs/jsapi/LuCI.form.FlagValue.html delete mode 100644 docs/jsapi/LuCI.form.GridSection.html delete mode 100644 docs/jsapi/LuCI.form.HiddenValue.html delete mode 100644 docs/jsapi/LuCI.form.JSONMap.html delete mode 100644 docs/jsapi/LuCI.form.ListValue.html delete mode 100644 docs/jsapi/LuCI.form.Map.html delete mode 100644 docs/jsapi/LuCI.form.MultiValue.html delete mode 100644 docs/jsapi/LuCI.form.NamedSection.html delete mode 100644 docs/jsapi/LuCI.form.SectionValue.html delete mode 100644 docs/jsapi/LuCI.form.TableSection.html delete mode 100644 docs/jsapi/LuCI.form.TextValue.html delete mode 100644 docs/jsapi/LuCI.form.TypedSection.html delete mode 100644 docs/jsapi/LuCI.form.Value.html delete mode 100644 docs/jsapi/LuCI.form.html delete mode 100644 docs/jsapi/LuCI.fs.html delete mode 100644 docs/jsapi/LuCI.headers.html delete mode 100644 docs/jsapi/LuCI.html delete mode 100644 docs/jsapi/LuCI.network.Device.html delete mode 100644 docs/jsapi/LuCI.network.Hosts.html delete mode 100644 docs/jsapi/LuCI.network.Protocol.html delete mode 100644 docs/jsapi/LuCI.network.WifiDevice.html delete mode 100644 docs/jsapi/LuCI.network.WifiNetwork.html delete mode 100644 docs/jsapi/LuCI.network.html delete mode 100644 docs/jsapi/LuCI.poll.html delete mode 100644 docs/jsapi/LuCI.request.html delete mode 100644 docs/jsapi/LuCI.request.poll.html delete mode 100644 docs/jsapi/LuCI.response.html delete mode 100644 docs/jsapi/LuCI.rpc.html delete mode 100644 docs/jsapi/LuCI.session.html delete mode 100644 docs/jsapi/LuCI.uci.html delete mode 100644 docs/jsapi/LuCI.ui.AbstractElement.html delete mode 100644 docs/jsapi/LuCI.ui.Checkbox.html delete mode 100644 docs/jsapi/LuCI.ui.ComboButton.html delete mode 100644 docs/jsapi/LuCI.ui.Combobox.html delete mode 100644 docs/jsapi/LuCI.ui.Dropdown.html delete mode 100644 docs/jsapi/LuCI.ui.DynamicList.html delete mode 100644 docs/jsapi/LuCI.ui.FileUpload.html delete mode 100644 docs/jsapi/LuCI.ui.Hiddenfield.html delete mode 100644 docs/jsapi/LuCI.ui.Select.html delete mode 100644 docs/jsapi/LuCI.ui.Textarea.html delete mode 100644 docs/jsapi/LuCI.ui.Textfield.html delete mode 100644 docs/jsapi/LuCI.ui.changes.html delete mode 100644 docs/jsapi/LuCI.ui.html delete mode 100644 docs/jsapi/LuCI.ui.menu.html delete mode 100644 docs/jsapi/LuCI.ui.tabs.html delete mode 100644 docs/jsapi/LuCI.view.html delete mode 100644 docs/jsapi/LuCI.xhr.html delete mode 100644 docs/jsapi/README.md delete mode 100644 docs/jsapi/fonts/OpenSans-Bold-webfont.eot delete mode 100644 docs/jsapi/fonts/OpenSans-Bold-webfont.svg delete mode 100644 docs/jsapi/fonts/OpenSans-Bold-webfont.woff delete mode 100644 docs/jsapi/fonts/OpenSans-BoldItalic-webfont.eot delete mode 100644 docs/jsapi/fonts/OpenSans-BoldItalic-webfont.svg delete mode 100644 docs/jsapi/fonts/OpenSans-BoldItalic-webfont.woff delete mode 100644 docs/jsapi/fonts/OpenSans-Italic-webfont.eot delete mode 100644 docs/jsapi/fonts/OpenSans-Italic-webfont.svg delete mode 100644 docs/jsapi/fonts/OpenSans-Italic-webfont.woff delete mode 100644 docs/jsapi/fonts/OpenSans-Light-webfont.eot delete mode 100644 docs/jsapi/fonts/OpenSans-Light-webfont.svg delete mode 100644 docs/jsapi/fonts/OpenSans-Light-webfont.woff delete mode 100644 docs/jsapi/fonts/OpenSans-LightItalic-webfont.eot delete mode 100644 docs/jsapi/fonts/OpenSans-LightItalic-webfont.svg delete mode 100644 docs/jsapi/fonts/OpenSans-LightItalic-webfont.woff delete mode 100644 docs/jsapi/fonts/OpenSans-Regular-webfont.eot delete mode 100644 docs/jsapi/fonts/OpenSans-Regular-webfont.svg delete mode 100644 docs/jsapi/fonts/OpenSans-Regular-webfont.woff delete mode 100644 docs/jsapi/fonts/glyphicons-halflings-regular.eot delete mode 100644 docs/jsapi/fonts/glyphicons-halflings-regular.svg delete mode 100644 docs/jsapi/fonts/glyphicons-halflings-regular.ttf delete mode 100644 docs/jsapi/fonts/glyphicons-halflings-regular.woff delete mode 100644 docs/jsapi/form.js.html delete mode 100644 docs/jsapi/fs.js.html delete mode 100644 docs/jsapi/index.html delete mode 100644 docs/jsapi/luci.js.html delete mode 100644 docs/jsapi/network.js.html delete mode 100644 docs/jsapi/rpc.js.html delete mode 100644 docs/jsapi/scripts/bootstrap.min.js delete mode 100644 docs/jsapi/scripts/jaguar.js delete mode 100644 docs/jsapi/scripts/jquery.min.js delete mode 100644 docs/jsapi/scripts/jquery.min.map delete mode 100644 docs/jsapi/scripts/linenumber.js delete mode 100644 docs/jsapi/scripts/prettify/Apache-License-2.0.txt delete mode 100644 docs/jsapi/scripts/prettify/lang-css.js delete mode 100644 docs/jsapi/scripts/prettify/prettify.js delete mode 100644 docs/jsapi/scripts/underscore-min.js delete mode 100644 docs/jsapi/scripts/underscore-min.map delete mode 100644 docs/jsapi/styles/bootstrap.min.css delete mode 100644 docs/jsapi/styles/jaguar.css delete mode 100644 docs/jsapi/styles/jsdoc-default.css delete mode 100644 docs/jsapi/styles/prettify-jsdoc.css delete mode 100644 docs/jsapi/styles/prettify-tomorrow.css delete mode 100644 docs/jsapi/uci.js.html delete mode 100644 docs/jsapi/ui.js.html diff --git a/docs/jsapi/LuCI.baseclass.html b/docs/jsapi/LuCI.baseclass.html deleted file mode 100644 index cb83d23b6a..0000000000 --- a/docs/jsapi/LuCI.baseclass.html +++ /dev/null @@ -1,4686 +0,0 @@ - - - - - Class: baseclass - - - - - - - - - - - - - - - - - -
- - -
-

Class: baseclass

- - - - -
- -
-

- LuCI. - - baseclass -

- -

LuCI.baseclass is the abstract base class all LuCI classes inherit from.

-

It provides simple means to create subclasses of given classes and -implements prototypal inheritance.

- -
- -
-
- - - - -
-
-

- - new LuCI.baseclass() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - staticLuCI.baseclass.extend(properties){LuCI.baseclass} -

- - - - -
- - -
-
- - -
-

Extends this base class with the properties described in -properties and returns a new subclassed Class instance

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
properties - - -Object.<string, *> - - - - - -

An object describing the properties to add to the new -subclass.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.baseclass - - - Returns a new LuCI.baseclass sublassed from this class, extended -by the given properties and with its prototype set to this base -class to enable inheritance. The resulting value represents a -class constructor and can be instantiated with new.
- - - - -
- - - -
-
-

- - staticLuCI.baseclass.instantiate(params, new_args){LuCI.baseclass} -

- - - - -
- - -
-
- - -
-

Calls the class constructor using new with the given argument -array being passed as variadic parameters to the constructor.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -Array.<*> - - - - - - - - - - -

An array of arbitrary values which will be passed as arguments -to the constructor function.

new_args - - -* - - - - - - - optional - - - - - repeatable - - -

Specifies arguments to be passed to the subclass constructor -as-is in order to instantiate the new subclass.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.baseclass - - - Returns a new LuCI.baseclass instance extended by the given -properties with its prototype set to this base class to -enable inheritance.
- - - - -
- - - -
-
-

- - staticLuCI.baseclass.isSubclass(classValue){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether the given class value is a subclass of this class.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
classValue - - -LuCI.baseclass - - - - - -

The class object to test.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the given classValue is a subclass of this -class or false if the given value is not a valid class or not -a subclass of this class'.
- - - - -
- - - -
-
-

- - staticLuCI.baseclass.singleton(properties, new_args){LuCI.baseclass} -

- - - - -
- - -
-
- - -
-

Extends this base class with the properties described in -properties, instantiates the resulting subclass using -the additional optional arguments passed to this function -and returns the resulting subclassed Class instance.

-

This function serves as a convenience shortcut for -Class.extend() and subsequent -new.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
properties - - -Object.<string, *> - - - - - - - - - - -

An object describing the properties to add to the new -subclass.

new_args - - -* - - - - - - - optional - - - - - repeatable - - -

Specifies arguments to be passed to the subclass constructor -as-is in order to instantiate the new subclass.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.baseclass - - - Returns a new LuCI.baseclass instance extended by the given -properties with its prototype set to this base class to -enable inheritance.
- - - - -
- - - -
-
-

- - super(key, callArgs){*|null} -

- - - - -
- - -
-
- - -
-

Walks up the parent class chain and looks for a class member -called key in any of the parent classes this class inherits -from. Returns the member value of the superclass or calls the -member as function and returns its return value when the -optional callArgs array is given.

-

This function has two signatures and is sensitive to the -amount of arguments passed to it:

-
    -
  • super('key') - -Returns the value of key when found within one of the -parent classes.
  • -
  • super('key', ['arg1', 'arg2']) - -Calls the key() method with parameters arg1 and arg2 -when found within one of the parent classes.
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - - - - - - -

The name of the superclass member to retrieve.

callArgs - - -Array.<*> - - - - - - - optional - - - - - -

An optional array of function call parameters to use. When -this parameter is specified, the found member value is called -as function using the values of this array as arguments.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a ReferenceError when callArgs are specified and -the found member named by key is not a function value.

-
-
-
-
-
- Type -
-
- -ReferenceError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - null - - - Returns the value of the found member or the return value of -the call to the found method. Returns null when no member -was found in the parent class chain or when the call to the -superclass method returned null.
- - - - -
- - - -
-
-

- - varargs(args, offset, extra_args){Array.<*>} -

- - - - -
- - -
-
- - -
-

Extract all values from the given argument array beginning from -offset and prepend any further given optional parameters to -the beginning of the resulting array copy.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
args - - -Array.<*> - - - - - - - - - - -

The array to extract the values from.

offset - - -number - - - - - - - - - - -

The offset from which to extract the values. An offset of 0 -would copy all values till the end.

extra_args - - -* - - - - - - - optional - - - - - repeatable - - -

Extra arguments to add to prepend to the resultung array.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<*> - - - Returns a new array consisting of the optional extra arguments -and the values extracted from the args array beginning with -offset.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.dom.html b/docs/jsapi/LuCI.dom.html deleted file mode 100644 index d0a69d1c23..0000000000 --- a/docs/jsapi/LuCI.dom.html +++ /dev/null @@ -1,6244 +0,0 @@ - - - - - Class: dom - - - - - - - - - - - - - - - - - -
- - -
-

Class: dom

- - - - -
- -
-

- LuCI. - - dom -

- -

The dom class provides convenience method for creating and -manipulating DOM elements.

-

To import the class in views, use 'require dom', to import it in -external JavaScript, use L.require("dom").then(...).

- -
- -
-
- - - - -
-
-

- - new LuCI.dom() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - append(node, children){Node|null} -

- - - - -
- - -
-
- - -
-

Appends the given children data to the given node.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -* - - - - - - - - - - -

The Node argument to append the children to.

children - - -* - - - - - - - optional - - - - - -

The childrens to append to the given node.

-

When children is an array, then each item of the array -will be either appended as child element or text node, -depending on whether the item is a DOM Node instance or -some other non-null value. Non-Node, non-null values -will be converted to strings first before being passed as -argument to createTextNode().

-

When children is a function, it will be invoked with -the passed node argument as sole parameter and the append -function will be invoked again, with the given node argument -as first and the return value of the children function as -second parameter.

-

When children is is a DOM Node instance, it will be -appended to the given node.

-

When children is any other non-null value, it will be -converted to a string and appened to the innerHTML property -of the given node.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - null - - - Returns the last children Node appended to the node or null -if either the node argument was no valid DOM node or if the -children was null or didn't result in further DOM nodes.
- - - - -
- - - -
-
-

- - attr(node, key, val) -

- - - - -
- - -
-
- - -
-

Sets attributes or registers event listeners on element nodes.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -* - - - - - - - - - - -

The Node argument to set the attributes or add the event -listeners for. When the given node value is not a valid -DOM Node, the function returns and does nothing.

key - - -string -| - -Object.<string, *> - - - - - - - - - - -

Specifies either the attribute or event handler name to use, -or an object containing multiple key, value pairs which are -each added to the node as either attribute or event handler, -depending on the respective value.

val - - -* - - - - - - - optional - - - - - -

Specifies the attribute value or event handler function to add. -If the key parameter is an Object, this parameter will be -ignored.

-

When val is of type function, it will be registered as event -handler on the given node with the key parameter being the -event name.

-

When val is of type object, it will be serialized as JSON and -added as attribute to the given node, using the given key -as attribute name.

-

When val is of any other type, it will be added as attribute -to the given node as-is, with the underlying setAttribute() -call implicitely turning it into a string.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - bindClassInstance(node, inst){Class} -

- - - - -
- - -
-
- - -
-

Binds the given class instance ot the specified DOM Node.

-

This function uses the dom.data() facility to attach the -passed instance of a Class to a node. This is needed for -complex widget elements or similar where the corresponding -class instance responsible for the element must be retrieved -from DOM nodes obtained by querySelector() or similar means.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -Node - - - - - -

The DOM Node instance to bind the class to.

inst - - -Class - - - - - -

The Class instance to bind to the node.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError when the given instance argument isn't -a valid Class instance.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Class - - - Returns the bound class instance.
- - - - -
- - - -
-
-

- - callClassMethod(node, method, params){*|null} -

- - - - -
- - -
-
- - -
-

Finds a bound class instance on the given node itself or the -first bound instance on its closest parent node and invokes -the specified method name on the found class instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -Node - - - - - - - - - - -

The DOM Node instance to start from.

method - - -string - - - - - - - - - - -

The name of the method to invoke on the found class instance.

params - - -* - - - - - - - - - - repeatable - - -

Additional arguments to pass to the invoked method as-is.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - null - - - Returns the return value of the invoked method if a class -instance and method has been found. Returns null if either -no bound class instance could be found, or if the found -instance didn't have the requested method.
- - - - -
- - - -
-
-

- - content(node, children){Node|null} -

- - - - -
- - -
-
- - -
-

Replaces the content of the given node with the given children.

-

This function first removes any children of the given DOM -Node and then adds the given given children following the -rules outlined below.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -* - - - - - - - - - - -

The Node argument to replace the children of.

children - - -* - - - - - - - optional - - - - - -

The childrens to replace into the given node.

-

When children is an array, then each item of the array -will be either appended as child element or text node, -depending on whether the item is a DOM Node instance or -some other non-null value. Non-Node, non-null values -will be converted to strings first before being passed as -argument to createTextNode().

-

When children is a function, it will be invoked with -the passed node argument as sole parameter and the append -function will be invoked again, with the given node argument -as first and the return value of the children function as -second parameter.

-

When children is is a DOM Node instance, it will be -appended to the given node.

-

When children is any other non-null value, it will be -converted to a string and appened to the innerHTML property -of the given node.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - null - - - Returns the last children Node appended to the node or null -if either the node argument was no valid DOM node or if the -children was null or didn't result in further DOM nodes.
- - - - -
- - - -
-
-

- - create(html, attr, data){Node} -

- - - - -
- - -
-
- - -
-

Creates a new DOM Node from the given html, attr and -data parameters.

-

This function has multiple signatures, it can be either invoked -in the form create(html[, attr[, data]]) or in the form -create(html[, data]). The used variant is determined from the -type of the second argument.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
html - - -* - - - - - - - - - - -

Describes the node to create.

-

When the value of html is of type array, a DocumentFragment -node is created and each item of the array is first converted -to a DOM Node by passing it through create() and then added -as child to the fragment.

-

When the value of html is a DOM Node instance, no new -element will be created but the node will be used as-is.

-

When the value of html is a string starting with <, it will -be passed to dom.parse() and the resulting value is used.

-

When the value of html is any other string, it will be passed -to document.createElement() for creating a new DOM Node of -the given name.

attr - - -Object.<string, *> - - - - - - - optional - - - - - -

Specifies an Object of key, value pairs to set as attributes -or event handlers on the created node. Refer to -dom.attr() for details.

data - - -* - - - - - - - optional - - - - - -

Specifies children to append to the newly created element. -Refer to dom.append() for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an InvalidCharacterError when the given html -argument contained malformed markup (such as not escaped -& characters in XHTML mode) or when the given node name -in html contains characters which are not legal in DOM -element names, such as spaces.

-
-
-
-
-
- Type -
-
- -InvalidCharacterError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns the newly created Node.
- - - - -
- - - -
-
-

- - data(node, key, val){*} -

- - - - -
- - -
-
- - -
-

Attaches or detaches arbitrary data to and from a DOM Node.

-

This function is useful to attach non-string values or runtime -data that is not serializable to DOM nodes. To decouple data -from the DOM, values are not added directly to nodes, but -inserted into a registry instead which is then referenced by a -string key stored as data-idref attribute in the node.

-

This function has multiple signatures and is sensitive to the -number of arguments passed to it.

-
    -
  • dom.data(node) - -Fetches all data associated with the given node.
  • -
  • dom.data(node, key) - -Fetches a specific key associated with the given node.
  • -
  • dom.data(node, key, val) - -Sets a specific key to the given value associated with the -given node.
  • -
  • dom.data(node, null) - -Clears any data associated with the node.
  • -
  • dom.data(node, key, null) - -Clears the given key associated with the node.
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -Node - - - - - - - - - - -

The DOM Node instance to set or retrieve the data for.

key - - -string -| - -null - - - - - - - optional - - - - - -

This is either a string specifying the key to retrieve, or -null to unset the entire node data.

val - - -* -| - -null - - - - - - - optional - - - - - -

This is either a non-null value to set for a given key or -null to remove the given key from the specified node.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the get or set value, or null when no value could -be found.
- - - - -
- - - -
-
-

- - elem(e){boolean} -

- - - - -
- - -
-
- - -
-

Tests whether the given argument is a valid DOM Node.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
e - - -* - - - - - -

The value to test.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the value is a DOM Node, else false.
- - - - -
- - - -
-
-

- - findClassInstance(node){Class|null} -

- - - - -
- - -
-
- - -
-

Finds a bound class instance on the given node itself or the -first bound instance on its closest parent node.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -Node - - - - - -

The DOM Node instance to start from.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Class - | - - null - - - Returns the founds class instance if any or null if no bound -class could be found on the node itself or any of its parents.
- - - - -
- - - -
-
-

- - isEmpty(node, ignoreFn){boolean} -

- - - - -
- - -
-
- - -
-

Tests whether a given DOM Node instance is empty or appears -empty.

-

Any element child nodes which have the CSS class hidden set -or for which the optionally passed ignoreFn callback function -returns false are ignored.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -Node - - - - - - - - - - -

The DOM Node instance to test.

ignoreFn - - -LuCI.dom~ignoreCallbackFn - - - - - - - optional - - - - - -

Specifies an optional function which is invoked for each child -node to decide whether the child node should be ignored or not.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the node does not have any children or if -any children node either has a hidden CSS class or a false -result when testing it using the given ignoreFn.
- - - - -
- - - -
-
-

- - matches(node, selector){boolean} -

- - - - -
- - -
-
- - -
-

Tests whether a given Node matches the given query selector.

-

This function is a convenience wrapper around the standard -Node.matches("selector") function with the added benefit that -the node argument may be a non-Node value, in which case -this function simply returns false.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -* - - - - - - - - - - -

The Node argument to test the selector against.

selector - - -string - - - - - - - optional - - - - - -

The query selector expression to test against the given node.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the given node matches the specified selector -or false when the node argument is no valid DOM Node or the -selector didn't match.
- - - - -
- - - -
-
-

- - parent(node, selector){Node|null} -

- - - - -
- - -
-
- - -
-

Returns the closest parent node that matches the given query -selector expression.

-

This function is a convenience wrapper around the standard -Node.closest("selector") function with the added benefit that -the node argument may be a non-Node value, in which case -this function simply returns null.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -* - - - - - - - - - - -

The Node argument to find the closest parent for.

selector - - -string - - - - - - - optional - - - - - -

The query selector expression to test against each parent.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - null - - - Returns the closest parent node matching the selector or -null when the node argument is no valid DOM Node or the -selector didn't match any parent.
- - - - -
- - - -
-
-

- - parse(s){Node} -

- - - - -
- - -
-
- - -
-

Parses a given string as HTML and returns the first child node.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
s - - -string - - - - - -

A string containing an HTML fragment to parse. Note that only -the first result of the resulting structure is returned, so an -input value of <div>foo</div> <div>bar</div> will only return -the first div element node.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns the first DOM Node extracted from the HTML fragment or -null on parsing failures or if no element could be found.
- - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

- - ignoreCallbackFn(node){boolean} -

- - - - -
- - -
-
- - -
-

The ignore callback function is invoked by isEmpty() for each -child node to decide whether to ignore a child node or not.

-

When this function returns false, the node passed to it is -ignored, else not.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -Node - - - - - -

The child node to test.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Boolean indicating whether to ignore the node or not.
- - - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.AbstractElement.html b/docs/jsapi/LuCI.form.AbstractElement.html deleted file mode 100644 index 6e343d1fee..0000000000 --- a/docs/jsapi/LuCI.form.AbstractElement.html +++ /dev/null @@ -1,4233 +0,0 @@ - - - - - Class: AbstractElement - - - - - - - - - - - - - - - - - -
- - -
-

Class: AbstractElement

- - - - -
- -
-

- LuCI.form. - - AbstractElement -

- -

The AbstractElement class serves as abstract base for the different form -elements implemented by LuCI.form. It provides the common logic for -loading and rendering values, for nesting elements and for defining common -properties.

-

This class is private and not directly accessible by user code.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.AbstractElement() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - parse(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse this elements form input.

-

The parse() function recursively walks the form element tree and -triggers input value reading and validation for each encountered element.

-

Elements which are hidden due to unsatisified dependencies are skipped.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once this element's value and the values of -all child elements have been parsed. The returned promise is rejected -if any parsed values are not meeting the validation constraints of their -respective elements.
- - - - -
- - - -
-
-

- - abstractrender(){Node|Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Render the form element.

-

The render() function recursively walks the form element tree and -renders the markup for each element, returning the assembled DOM tree.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - Promise.<Node> - - - May return a DOM Node or a promise resolving to a DOM node containing -the form element's markup, including the markup of any child elements.
- - - - -
- - - -
-
-

- - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.AbstractSection.html b/docs/jsapi/LuCI.form.AbstractSection.html deleted file mode 100644 index 0d4d49f509..0000000000 --- a/docs/jsapi/LuCI.form.AbstractSection.html +++ /dev/null @@ -1,6132 +0,0 @@ - - - - - Class: AbstractSection - - - - - - - - - - - - - - - - - -
- - -
-

Class: AbstractSection

- - - - -
- -
-

- LuCI.form. - - AbstractSection -

- -

The AbstractSection class serves as abstract base for the different form -section styles implemented by LuCI.form. It provides the common logic for -enumerating underlying configuration section instances, for registering -form options and for handling tabs to segment child options.

-

This class is private and not directly accessible by user code.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.AbstractSection() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

readonlyparentoptionLuCI.form.AbstractValue

-
- - -
-
- -
-

Access the parent option container instance.

-

In case this section is nested within an option element container, -this property will hold a reference to the parent option instance.

-

If this section is not nested, the property is null.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - abstractcfgsections(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Enumerate the UCI section IDs covered by this form section element.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an InternalError exception if the function is not implemented.

-
-
-
-
-
- Type -
-
- -InternalError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of UCI section IDs covered by this form element. -The sections will be rendered in the same order as the returned array.
- - - - -
- - - -
-
-

- - cfgvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option configuration values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the configuration values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the configuration value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -configuration values or just a single configuration value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - abstractfilter(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Filter UCI section IDs to render.

-

The filter function is invoked for each UCI section ID of a given type -and controls whether the given UCI section is rendered or ignored by -the form section element.

-

The default implementation always returns true. User code or -classes extending AbstractSection may overwrite this function with -custom implementations.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The UCI section ID to test.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the given UCI section ID should be handled and -false when it should be ignored.
- - - - -
- - - -
-
-

- - formvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option widget input values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the widget input values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the widget input value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - getOption(option){null|LuCI.form.AbstractValue|Object.<string, LuCI.form.AbstractValue>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option objects.

-

This function is sensitive to the amount of arguments passed to it; -if no option name is specified, all options within this section are -returned as dictionary.

-

If an option name is supplied, this function returns the matching -LuCI.form.AbstractValue instance only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
option - - -string - - - - - - - optional - - - - - -

The name of the option object to obtain

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.form.AbstractValue - | - - Object.<string, LuCI.form.AbstractValue> - - - Returns either a dictionary of option names and their corresponding -option instance objects or just a single object instance value, -depending on the amount of passed arguments.
- - - - -
- - - -
-
-

- - getUIElement(section_id, option){null|LuCI.ui.AbstractElement|Object.<string, (null|LuCI.ui.AbstractElement)>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option LuCI.ui widget instances.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the LuCI.ui widget instances of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the LuCI.ui widget instance value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.ui.AbstractElement - | - - Object.<string, (null|LuCI.ui.AbstractElement)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - load(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Load the configuration covered by this section.

-

The load() function recursively walks the section element tree and -invokes the load function of each child option element.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been loaded. The promise may reject with an error if any of the child -elements load functions rejected with an error.
- - - - -
- - - -
-
-

- - option(optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to the section.

-

Note that taboption() -should be used instead if this form section element uses tabs.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - parse(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse this sections form input.

-

The parse() function recursively walks the section element tree and -triggers input value reading and validation for each encountered child -option element.

-

Options which are hidden due to unsatisified dependencies are skipped.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been parsed. The returned promise is rejected if any parsed values are -not meeting the validation constraints of their respective elements.
- - - - -
- - - -
-
-

- - inherited - - abstractrender(){Node|Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Render the form element.

-

The render() function recursively walks the form element tree and -renders the markup for each element, returning the assembled DOM tree.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - Promise.<Node> - - - May return a DOM Node or a promise resolving to a DOM node containing -the form element's markup, including the markup of any child elements.
- - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - tab(name, title, description) -

- - - - -
- - -
-
- - -
-

Add an option tab to the section.

-

The child option elements of a section may be divided into multiple -tabs to provide a better overview to the user.

-

Before options can be moved into a tab pane, the corresponding tab -has to be defined first, which is done by calling this function.

-

Note that once tabs are defined, user code must use the taboption() -method to add options to specific tabs. Option elements added by -option() will not be assigned to any tab and not be rendered in this -case.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - - - - - - -

The name of the tab to register. It may be freely chosen and just serves -as an identifier to differentiate tabs.

title - - -string - - - - - - - - - - -

The human readable caption of the tab.

description - - -string - - - - - - - optional - - - - - -

An additional description text for the corresponding tab pane. It is -displayed as text paragraph below the tab but before the tab pane -contents. If omitted, no description will be rendered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an exeption if a tab with the same name already exists.

-
-
-
-
-
- Type -
-
- -Error - - -
-
-
-
- - - - - - - -
- - - -
-
-

- - taboption(tabname, optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to a tab of the section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
tabname - - -string - - - - - - - - - - -

The name of the section tab to add the option element to.

optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
-
    -
  • - -
    -
    -
    -

    Throws a ReferenceError exception when the given tab name does not -exist.

    -
    -
    -
    -
    -
    - Type -
    -
    - -ReferenceError - - -
    -
    -
    -
    - -
  • - -
  • - -
    -
    -
    -

    Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

    -
    -
    -
    -
    -
    - Type -
    -
    - -TypeError - - -
    -
    -
    -
    - -
  • -
- - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.AbstractValue.html b/docs/jsapi/LuCI.form.AbstractValue.html deleted file mode 100644 index ec33a53399..0000000000 --- a/docs/jsapi/LuCI.form.AbstractValue.html +++ /dev/null @@ -1,6991 +0,0 @@ - - - - - Class: AbstractValue - - - - - - - - - - - - - - - - - -
- - -
-

Class: AbstractValue

- - - - -
- -
-

- LuCI.form. - - AbstractValue -

- -

The AbstractValue class serves as abstract base for the different form -option styles implemented by LuCI.form. It provides the common logic for -handling option input values, for dependencies among options and for -validation constraints that should be applied to entered values.

-

This class is private and not directly accessible by user code.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.AbstractValue() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - abstractrender(){Node|Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Render the form element.

-

The render() function recursively walks the form element tree and -renders the markup for each element, returning the assembled DOM tree.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - Promise.<Node> - - - May return a DOM Node or a promise resolving to a DOM node containing -the form element's markup, including the markup of any child elements.
- - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - abstractvalidate(section_id, value){*} -

- - - - -
- - -
-
- - -
-

Apply custom validation logic.

-

This method is invoked whenever incremental validation is performed on -the user input, e.g. on keyup or blur events.

-

The default implementation of this method does nothing and always -returns true. User code may overwrite this method to provide -additional validation logic which is not covered by data type -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

value - - -* - - - - - -

The value to validate

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - The method shall return true to accept the given value. Any other -return value is treated as failure, converted to a string and displayed -as error message to the user.
- - - - -
- - - -
-
-

- - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.ButtonValue.html b/docs/jsapi/LuCI.form.ButtonValue.html deleted file mode 100644 index c3e7b5335c..0000000000 --- a/docs/jsapi/LuCI.form.ButtonValue.html +++ /dev/null @@ -1,7312 +0,0 @@ - - - - - Class: ButtonValue - - - - - - - - - - - - - - - - - -
- - -
-

Class: ButtonValue

- - - - -
- -
-

- LuCI.form. - - ButtonValue -

- -

The DummyValue element wraps an LuCI.ui.Hiddenfield widget and -renders the underlying UCI option or default value as readonly text.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.ButtonValue(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

inputstylestring

-
- - -
-
- -
-

Override the button style class.

-

By setting this property, a specific cbi-button-* CSS class can be -selected to influence the style of the resulting button.

-

Suitable values which are implemented by most themes are positive, -negative and primary.

-

The default is null, means a neutral button styling is used.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

inputtitlestring function

-
- - -
-
- -
-

Override the rendered button caption.

-

By default, the option title - which is passed as fourth argument to the -constructor - is used as caption for the button element. When setting -this property to a string, it is used as String.format() pattern with -the underlying UCI section name passed as first format argument. When -set to a function, it is invoked passing the section ID as sole argument -and the resulting return value is converted to a string before being -used as button caption.

-

The default is null, means the option title is used as caption.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onclickfunction

-
- - -
-
- -
-

Override the button click action.

-

By default, the underlying UCI option (or default property) value is -copied into a hidden field tied to the button element and the save -action is triggered on the parent form element.

-

When this property is set to a function, it is invoked instead of -performing the default actions. The handler function will receive the -DOM click element as first and the underlying configuration section ID -as second argument.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - value(key, value) -

- - - - -
- - -
-
- - -
-

Add a predefined choice to the form option. By adding one or more -choices, the plain text input field is turned into a combobox widget -which prompts the user to select a predefined choice, or to enter a -custom value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.DummyValue.html b/docs/jsapi/LuCI.form.DummyValue.html deleted file mode 100644 index e2df4f55f3..0000000000 --- a/docs/jsapi/LuCI.form.DummyValue.html +++ /dev/null @@ -1,7249 +0,0 @@ - - - - - Class: DummyValue - - - - - - - - - - - - - - - - - -
- - -
-

Class: DummyValue

- - - - -
- -
-

- LuCI.form. - - DummyValue -

- -

The DummyValue element wraps an LuCI.ui.Hiddenfield widget and -renders the underlying UCI option or default value as readonly text.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.DummyValue(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

hrefstring

-
- - -
-
- -
-

Set an URL which is opened when clicking on the dummy value text.

-

By setting this property, the dummy value text is wrapped in an <a> -element with the property value used as href attribute.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

rawhtmlboolean

-
- - -
-
- -
-

Treat the UCI option value (or the default property value) as HTML.

-

By default, the value text is HTML escaped before being rendered as -text. In some cases it may be needed to actually interpret and render -HTML contents as-is. When set to true, HTML escaping is disabled.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - value(key, value) -

- - - - -
- - -
-
- - -
-

Add a predefined choice to the form option. By adding one or more -choices, the plain text input field is turned into a combobox widget -which prompts the user to select a predefined choice, or to enter a -custom value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.DynamicList.html b/docs/jsapi/LuCI.form.DynamicList.html deleted file mode 100644 index 2cb34a0c6b..0000000000 --- a/docs/jsapi/LuCI.form.DynamicList.html +++ /dev/null @@ -1,7149 +0,0 @@ - - - - - Class: DynamicList - - - - - - - - - - - - - - - - - -
- - -
-

Class: DynamicList

- - - - -
- -
-

- LuCI.form. - - DynamicList -

- -

The DynamicList class represents a multi value widget allowing the user -to enter multiple unique values, optionally selected from a set of -predefined choices. It builds upon the LuCI.ui.DynamicList widget.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.DynamicList(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - value(key, value) -

- - - - -
- - -
-
- - -
-

Add a predefined choice to the form option. By adding one or more -choices, the plain text input field is turned into a combobox widget -which prompts the user to select a predefined choice, or to enter a -custom value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.FileUpload.html b/docs/jsapi/LuCI.form.FileUpload.html deleted file mode 100644 index 182ded7dfe..0000000000 --- a/docs/jsapi/LuCI.form.FileUpload.html +++ /dev/null @@ -1,7360 +0,0 @@ - - - - - Class: FileUpload - - - - - - - - - - - - - - - - - -
- - -
-

Class: FileUpload

- - - - -
- -
-

- LuCI.form. - - FileUpload -

- -

The FileUpload element wraps an LuCI.ui.FileUpload widget and -offers the ability to browse, upload and select remote files.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.FileUpload(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

enable_removeboolean

-
- - -
-
- -
-

Toggle remote file delete functionality.

-

When set to true, the underlying widget provides a buttons which let -the user delete files from remote directories. Note that this is merely -a cosmetic feature, remote delete permissions are controlled by the -session ACL rules.

-

The default is true, means file removal buttons are displayed.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

enable_uploadboolean

-
- - -
-
- -
-

Toggle file upload functionality.

-

When set to true, the underlying widget provides a button which lets -the user select and upload local files to the remote system. -Note that this is merely a cosmetic feature, remote upload access is -controlled by the session ACL rules.

-

The default is true, means file upload functionality is displayed.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

root_directorystring

-
- - -
-
- -
-

Specify the root directory for file browsing.

-

This property defines the topmost directory the file browser widget may -navigate to, the UI will not allow browsing directories outside this -prefix. Note that this is merely a cosmetic feature, remote file access -and directory listing permissions are controlled by the session ACL -rules.

-

The default is /etc/luci-uploads.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • /etc/luci-uploads
- - - - - - - -
- - - -
- - - -
-
-

show_hiddenboolean

-
- - -
-
- -
-

Toggle display of hidden files.

-

Display hidden files when rendering the remote directory listing. -Note that this is merely a cosmetic feature, hidden files are always -included in received remote file listings.

-

The default is false, means hidden files are not displayed.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - value(key, value) -

- - - - -
- - -
-
- - -
-

Add a predefined choice to the form option. By adding one or more -choices, the plain text input field is turned into a combobox widget -which prompts the user to select a predefined choice, or to enter a -custom value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.FlagValue.html b/docs/jsapi/LuCI.form.FlagValue.html deleted file mode 100644 index a1a1c68955..0000000000 --- a/docs/jsapi/LuCI.form.FlagValue.html +++ /dev/null @@ -1,7238 +0,0 @@ - - - - - Class: FlagValue - - - - - - - - - - - - - - - - - -
- - -
-

Class: FlagValue

- - - - -
- -
-

- LuCI.form. - - FlagValue -

- -

The FlagValue element builds upon the LuCI.ui.Checkbox widget to -implement a simple checkbox element.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.FlagValue(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

disablednumber

-
- - -
-
- -
-

Sets the input value to use for the checkbox unchecked state.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • 0
- - - - - - - -
- - - -
- - - -
-
-

enablednumber

-
- - -
-
- -
-

Sets the input value to use for the checkbox checked state.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • 1
- - - - - - - -
- - - -
- - - -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the checked state of the underlying checkbox widget and return -either the enabled or the disabled property value, depending on -the checked state.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Query the checked state of the underlying checkbox widget and return -either a localized Yes or No string, depending on the checked state.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - value(key, value) -

- - - - -
- - -
-
- - -
-

Add a predefined choice to the form option. By adding one or more -choices, the plain text input field is turned into a combobox widget -which prompts the user to select a predefined choice, or to enter a -custom value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.GridSection.html b/docs/jsapi/LuCI.form.GridSection.html deleted file mode 100644 index 664658ae11..0000000000 --- a/docs/jsapi/LuCI.form.GridSection.html +++ /dev/null @@ -1,6892 +0,0 @@ - - - - - Class: GridSection - - - - - - - - - - - - - - - - - -
- - -
-

Class: GridSection

- - - - -
- -
-

- LuCI.form. - - GridSection -

- -

The GridSection class maps all or - if filter() is overwritten - a -subset of the underlying UCI configuration sections of a given type.

-

A grid section functions similar to a LuCI.form.TableSection but -supports tabbing in the modal overlay. Option elements added with -option() are shown in the table while -elements added with taboption() -are displayed in the modal popup.

-

Another important difference is that the table cells show a readonly text -preview of the corresponding option elements by default, unless the child -option element is explicitely made writable by setting the editable -property to true.

-

Additionally, the grid section honours a modalonly property of child -option elements. Refer to the AbstractValue -documentation for details.

-

Layout wise, a grid section looks mostly identical to table sections.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.GridSection(form, section_type, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by section().

section_type - - -string - - - - - - - - - - -

The type of the UCI section to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the form section element.

description - - -string - - - - - - - optional - - - - - -

The description text of the form section element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

addbtntitlestring function

-
- - -
-
- -
-

Override the caption used for the section add button at the bottom of -the section form element. If set to a string, it will be used as-is, -if set to a function, the function will be invoked and its return value -is used as caption, after converting it to a string. If this property -is not set, the default is Add.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

addremoveboolean

-
- - -
-
- -
-

If set to true, the user may add or remove instances from the form -section widget, otherwise only preexisting sections may be edited. -The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

anonymousboolean

-
- - -
-
- -
-

If set to true, mapped section instances are treated as anonymous -UCI sections, which means that section instance elements will be -rendered without title element and that no name is required when adding -new sections. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

exteditstring function

-
- - -
-
- -
-

Enables a per-section instance row Edit button which triggers a certain -action when clicked. If set to a string, the string value is used -as String.format() pattern with the name of the underlying UCI section -as first format argument. The result is then interpreted as URL which -LuCI will navigate to when the user clicks the edit button.

-

If set to a function, this function will be registered as click event -handler on the rendered edit button, receiving the section instance -name as first and the DOM click event as second argument.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

max_colsnumber

-
- - -
-
- -
-

Specify a maximum amount of columns to display. By default, one table -column is rendered for each child option of the form section element. -When this option is set to a positive number, then no more columns than -the given amount are rendered. When the number of child options exceeds -the specified amount, a More… button is rendered in the last column, -opening a modal dialog presenting all options elements in NamedSection -style when clicked.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

modaltitlestring function

-
- - -
-
- -
-

Override the per-section instance modal popup title caption shown when -clicking the More… button in a section specifying max_cols. If set -to a string, it will be used as String.format() pattern with the name -of the underlying UCI section as first argument, if set to a function, -the function will be invoked with the section name as first argument and -its return value is used as caption, after converting it to a string. -If this property is not set, the default is the name of the underlying -UCI configuration section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

nodescriptionsboolean

-
- - -
-
- -
-

If set to true, the header row with the options descriptions will -not be displayed. By default, descriptions row is automatically displayed -when at least one option has a description.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

readonlyparentoptionLuCI.form.AbstractValue

-
- - -
-
- -
-

Access the parent option container instance.

-

In case this section is nested within an option element container, -this property will hold a reference to the parent option instance.

-

If this section is not nested, the property is null.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

rowcolorsboolean

-
- - -
-
- -
-

If set to true, alternating cbi-rowstyle-1 and cbi-rowstyle-2 CSS -classes are added to the table row elements. Not all LuCI themes -implement these row style classes. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

sectiontitlestring function

-
- - -
-
- -
-

Override the per-section instance title caption shown in the first -column of the table unless anonymous is set to true. If set to a -string, it will be used as String.format() pattern with the name of -the underlying UCI section as first argument, if set to a function, the -function will be invoked with the section name as first argument and -its return value is used as caption, after converting it to a string. -If this property is not set, the default is the name of the underlying -UCI configuration section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

sortableboolean

-
- - -
-
- -
-

If set to true, a sort button is added to the last column, allowing -the user to reorder the section instances mapped by the section form -element.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

tabbedboolean

-
- - -
-
- -
-

When set to true, instead of rendering section instances one below -another, treat each instance as separate tab pane and render a tab menu -at the top of the form section element, allowing the user to switch -among instances. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the section IDs from. By -default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified. -The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - abstractaddModalOptions(modalSection, section_id, ev){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Add further options to the per-section instanced modal popup.

-

This function may be overwritten by user code to perform additional -setup steps before displaying the more options modal which is useful to -e.g. query additional data or to inject further option elements.

-

The default implementation of this function does nothing.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
modalSection - - -LuCI.form.NamedSection - - - - - -

The NamedSection instance about to be rendered in the modal popup.

section_id - - -string - - - - - -

The ID of the underlying UCI section the modal popup belongs to.

ev - - -Event - - - - - -

The DOM event emitted by clicking the More… button.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Return values of this function are ignored but if a promise is returned, -it is run to completion before the rendering is continued, allowing -custom logic to perform asynchroneous work before the modal dialog -is shown.
- - - - -
- - - -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option configuration values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the configuration values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the configuration value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -configuration values or just a single configuration value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - abstractfilter(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Filter UCI section IDs to render.

-

The filter function is invoked for each UCI section ID of a given type -and controls whether the given UCI section is rendered or ignored by -the form section element.

-

The default implementation always returns true. User code or -classes extending AbstractSection may overwrite this function with -custom implementations.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The UCI section ID to test.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the given UCI section ID should be handled and -false when it should be ignored.
- - - - -
- - - -
-
-

- - inherited - - formvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option widget input values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the widget input values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the widget input value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - getOption(option){null|LuCI.form.AbstractValue|Object.<string, LuCI.form.AbstractValue>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option objects.

-

This function is sensitive to the amount of arguments passed to it; -if no option name is specified, all options within this section are -returned as dictionary.

-

If an option name is supplied, this function returns the matching -LuCI.form.AbstractValue instance only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
option - - -string - - - - - - - optional - - - - - -

The name of the option object to obtain

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.form.AbstractValue - | - - Object.<string, LuCI.form.AbstractValue> - - - Returns either a dictionary of option names and their corresponding -option instance objects or just a single object instance value, -depending on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id, option){null|LuCI.ui.AbstractElement|Object.<string, (null|LuCI.ui.AbstractElement)>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option LuCI.ui widget instances.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the LuCI.ui widget instances of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the LuCI.ui widget instance value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.ui.AbstractElement - | - - Object.<string, (null|LuCI.ui.AbstractElement)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - load(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Load the configuration covered by this section.

-

The load() function recursively walks the section element tree and -invokes the load function of each child option element.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been loaded. The promise may reject with an error if any of the child -elements load functions rejected with an error.
- - - - -
- - - -
-
-

- - inherited - - option(optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to the section.

-

Note that taboption() -should be used instead if this form section element uses tabs.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - inherited - - parse(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse this sections form input.

-

The parse() function recursively walks the section element tree and -triggers input value reading and validation for each encountered child -option element.

-

Options which are hidden due to unsatisified dependencies are skipped.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been parsed. The returned promise is rejected if any parsed values are -not meeting the validation constraints of their respective elements.
- - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - tab(name, title, description) -

- - - - -
- - -
-
- - -
-

Add an option tab to the section.

-

The modal option elements of a grid section may be divided into multiple -tabs to provide a better overview to the user.

-

Before options can be moved into a tab pane, the corresponding tab -has to be defined first, which is done by calling this function.

-

Note that tabs are only effective in modal popups, options added with -option() will not be assigned to a specific tab and are rendered in -the table view only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - - - - - - -

The name of the tab to register. It may be freely chosen and just serves -as an identifier to differentiate tabs.

title - - -string - - - - - - - - - - -

The human readable caption of the tab.

description - - -string - - - - - - - optional - - - - - -

An additional description text for the corresponding tab pane. It is -displayed as text paragraph below the tab but before the tab pane -contents. If omitted, no description will be rendered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an exeption if a tab with the same name already exists.

-
-
-
-
-
- Type -
-
- -Error - - -
-
-
-
- - - - - - - -
- - - -
-
-

- - inherited - - taboption(tabname, optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to a tab of the section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
tabname - - -string - - - - - - - - - - -

The name of the section tab to add the option element to.

optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
-
    -
  • - -
    -
    -
    -

    Throws a ReferenceError exception when the given tab name does not -exist.

    -
    -
    -
    -
    -
    - Type -
    -
    - -ReferenceError - - -
    -
    -
    -
    - -
  • - -
  • - -
    -
    -
    -

    Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

    -
    -
    -
    -
    -
    - Type -
    -
    - -TypeError - - -
    -
    -
    -
    - -
  • -
- - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.HiddenValue.html b/docs/jsapi/LuCI.form.HiddenValue.html deleted file mode 100644 index 85362cdb73..0000000000 --- a/docs/jsapi/LuCI.form.HiddenValue.html +++ /dev/null @@ -1,7153 +0,0 @@ - - - - - Class: HiddenValue - - - - - - - - - - - - - - - - - -
- - -
-

Class: HiddenValue

- - - - -
- -
-

- LuCI.form. - - HiddenValue -

- -

The HiddenValue element wraps an LuCI.ui.Hiddenfield widget.

-

Hidden value widgets used to be necessary in legacy code which actually -submitted the underlying HTML form the server. With client side handling of -forms, there are more efficient ways to store hidden state data.

-

Since this widget has no visible content, the title and description values -of this form element should be set to null as well to avoid a broken or -distorted form layout when rendering the option element.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.HiddenValue(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - value(key, value) -

- - - - -
- - -
-
- - -
-

Add a predefined choice to the form option. By adding one or more -choices, the plain text input field is turned into a combobox widget -which prompts the user to select a predefined choice, or to enter a -custom value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.JSONMap.html b/docs/jsapi/LuCI.form.JSONMap.html deleted file mode 100644 index 17a0217d91..0000000000 --- a/docs/jsapi/LuCI.form.JSONMap.html +++ /dev/null @@ -1,5812 +0,0 @@ - - - - - Class: JSONMap - - - - - - - - - - - - - - - - - -
- - -
-

Class: JSONMap

- - - - -
- -
-

- LuCI.form. - - JSONMap -

- -

A JSONMap class functions similar to LuCI.form.Map -but uses a multidimensional JavaScript object instead of UCI configuration -as data source.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.JSONMap(data, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
data - - -Object.<string, (Object.<string, *>|Array.<Object.<string, *>>)> - - - - - - - - - - -

The JavaScript object to use as data source. Internally, the object is -converted into an UCI-like format. Its toplevel keys are treated like UCI -section types while the object or array-of-object values are treated as -section contents.

title - - -string - - - - - - - optional - - - - - -

The title caption of the form. A form title is usually rendered as separate -headline element before the actual form contents. If omitted, the -corresponding headline element will not be rendered.

description - - -string - - - - - - - optional - - - - - -

The description text of the form which is usually rendered as text -paragraph below the form title and before the actual form conents. -If omitted, the corresponding paragraph element will not be rendered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

readonlyboolean

-
- - -
-
- -
-

Toggle readonly state of the form.

-

If set to true, the Map instance is marked readonly and any form -option elements added to it will inherit the readonly state.

-

If left unset, the Map will test the access permission of the primary -uci configuration upon loading and mark the form readonly if no write -permissions are granted.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - chain(config) -

- - - - -
- - -
-
- - -
-

Tie another UCI configuration to the map.

-

By default, a map instance will only load the UCI configuration file -specified in the constructor but sometimes access to values from -further configuration files is required. This function allows for such -use cases by registering further UCI configuration files which are -needed by the map.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - -

The additional UCI configuration file to tie to the map. If the given -config already is in the list of required files, it will be ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - findElement(selector_or_attrname, attrvalue){Node|null} -

- - - - -
- - -
-
- - -
-

Find the first DOM node within this Map which matches the given search -parameters. This function is essentially a convenience wrapper around -findElements() which only returns the first found node.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, it is used as selector-expression -as-is. When two arguments are passed, the first argument is treated -as attribute name, the second one as attribute value to match.

-

As an example, map.findElement('input') would find the first <input> -node while map.findElement('type', 'text') would find the first DOM -node with a type="text" attribute.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
selector_or_attrname - - -string - - - - - - - - - - -

If invoked with only one parameter, this argument is a querySelector() -compatible selector expression. If invoked with two parameters, this -argument is the attribute name to filter for.

attrvalue - - -string - - - - - - - optional - - - - - -

In case the function is invoked with two parameters, this argument -specifies the attribute value to match.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an InternalError if more than two function parameters are -passed.

-
-
-
-
-
- Type -
-
- -InternalError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - null - - - Returns the first found DOM node or null if no element matched.
- - - - -
- - - -
-
-

- - inherited - - findElements(selector_or_attrname, attrvalue){NodeList} -

- - - - -
- - -
-
- - -
-

Find all DOM nodes within this Map which match the given search -parameters. This function is essentially a convenience wrapper around -querySelectorAll().

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, it is used as selector-expression -as-is. When two arguments are passed, the first argument is treated -as attribute name, the second one as attribute value to match.

-

As an example, map.findElements('input') would find all <input> -nodes while map.findElements('type', 'text') would find any DOM node -with a type="text" attribute.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
selector_or_attrname - - -string - - - - - - - - - - -

If invoked with only one parameter, this argument is a -querySelectorAll() compatible selector expression. If invoked with -two parameters, this argument is the attribute name to filter for.

attrvalue - - -string - - - - - - - optional - - - - - -

In case the function is invoked with two parameters, this argument -specifies the attribute value to match.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an InternalError if more than two function parameters are -passed.

-
-
-
-
-
- Type -
-
- -InternalError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - NodeList - - - Returns a (possibly empty) DOM NodeList containing the found DOM nodes.
- - - - -
- - - -
-
-

- - inherited - - load(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Load the configuration covered by this map.

-

The load() function first loads all referenced UCI configurations, -then it recursively walks the form element tree and invokes the -load function of each child element.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the entire form completed loading all -data. The promise may reject with an error if any configuration failed -to load or if any of the child elements load functions rejected with -an error.
- - - - -
- - - -
-
-

- - inherited - - lookupOption(name_or_id, section_id, config){Array.<LuCI.form.AbstractValue, string>|null} -

- - - - -
- - -
-
- - -
-

Find a form option element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name_or_id - - -string - - - - - - - - - - -

The name or the full ID of the option element to look up.

section_id - - -string - - - - - - - optional - - - - - -

The ID of the UCI section containing the option to look up. May be -omitted if a full ID is passed as first argument.

config - - -string - - - - - - - optional - - - - - -

The name of the UCI configuration the option instance is belonging to. -Defaults to the main UCI configuration of the map if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<LuCI.form.AbstractValue, string> - | - - null - - - Returns a two-element array containing the form option instance as -first item and the corresponding UCI section ID as second item. -Returns null if the option could not be found.
- - - - -
- - - -
-
-

- - inherited - - parse(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the form input values.

-

The parse() function recursively walks the form element tree and -triggers input value reading and validation for each child element.

-

Elements which are hidden due to unsatisified dependencies are skipped.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the entire form completed parsing all -input values. The returned promise is rejected if any parsed values are -not meeting the validation constraints of their respective elements.
- - - - -
- - - -
-
-

- - inherited - - render(){Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Render the form markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Node> - - - Returns a promise resolving to the toplevel form DOM node once the -rendering is complete.
- - - - -
- - - -
-
-

- - inherited - - reset(){Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Reset the form by re-rendering its contents. This will revert all -unsaved user inputs to their initial form state.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Node> - - - Returns a promise resolving to the toplevel form DOM node once the -re-rendering is complete.
- - - - -
- - - -
-
-

- - inherited - - save(cb, silent){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Save the form input values.

-

This function parses the current form, saves the resulting UCI changes, -reloads the UCI configuration data and redraws the form elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
cb - - -function - - - - - - - - - optional - - - - - -

An optional callback function that is invoked after the form is parsed -but before the changed UCI data is saved. This is useful to perform -additional data manipulation steps before saving the changes.

silent - - -boolean - - - - - - false - - - - - optional - - - - - -

If set to true, trigger an alert message to the user in case saving -the form data failes. Otherwise fail silently.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the entire save operation is complete. -The returned promise is rejected if any step of the save operation -failed.
- - - - -
- - - -
-
-

- - inherited - - section(sectionclass, classargs){LuCI.form.AbstractSection} -

- - - - -
- - -
-
- - -
-

Add a configuration section to the map.

-

LuCI forms follow the structure of the underlying UCI configurations, -means that a map, which represents a single UCI configuration, is -divided into multiple sections which in turn contain an arbitrary -number of options.

-

While UCI itself only knows two kinds of sections - named and anonymous -ones - the form class offers various flavors of form section elements -to present configuration sections in different ways. Refer to the -documentation of the different section classes for details.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
sectionclass - - -LuCI.form.AbstractSection - - - - - - - - - - -

The section class to use for rendering the configuration section. -Note that this value must be the class itself, not a class instance -obtained from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -string - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given section class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractSection - - - Returns the instantiated section class instance.
- - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.ListValue.html b/docs/jsapi/LuCI.form.ListValue.html deleted file mode 100644 index e173e5f9b9..0000000000 --- a/docs/jsapi/LuCI.form.ListValue.html +++ /dev/null @@ -1,7298 +0,0 @@ - - - - - Class: ListValue - - - - - - - - - - - - - - - - - -
- - -
-

Class: ListValue

- - - - -
- -
-

- LuCI.form. - - ListValue -

- -

The ListValue class implements a simple static HTML select element -allowing the user to chose a single value from a set of predefined choices. -It builds upon the LuCI.ui.Select widget.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.ListValue(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

orientationstring

-
- - -
-
- -
-

Set the orientation of the underlying radio or checkbox elements.

-

May be one of horizontal or vertical. Only applies to non-select -widget types.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • horizontal
- - - - - - - -
- - - -
- - - -
-
-

sizenumber

-
- - -
-
- -
-

Set the size attribute of the underlying HTML select element.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widgetstring

-
- - -
-
- -
-

Set the type of the underlying form controls.

-

May be one of select or radio. If set to select, an HTML -select element is rendered, otherwise a collection of radio -elements is used.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • select
- - - - - - - -
- - - -
- - - -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - value(key, value) -

- - - - -
- - -
-
- - -
-

Add a predefined choice to the form option. By adding one or more -choices, the plain text input field is turned into a combobox widget -which prompts the user to select a predefined choice, or to enter a -custom value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.Map.html b/docs/jsapi/LuCI.form.Map.html deleted file mode 100644 index 47afe794d6..0000000000 --- a/docs/jsapi/LuCI.form.Map.html +++ /dev/null @@ -1,5791 +0,0 @@ - - - - - Class: Map - - - - - - - - - - - - - - - - - -
- - -
-

Class: Map

- - - - -
- -
-

- LuCI.form. - - Map -

- -

The Map class represents one complete form. A form usually maps one UCI -configuraton file and is divided into multiple sections containing multiple -fields each.

-

It serves as main entry point into the LuCI.form for typical view code.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.Map(config, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - - - - - - -

The UCI configuration to map. It is automatically loaded along when the -resulting map instance.

title - - -string - - - - - - - optional - - - - - -

The title caption of the form. A form title is usually rendered as separate -headline element before the actual form contents. If omitted, the -corresponding headline element will not be rendered.

description - - -string - - - - - - - optional - - - - - -

The description text of the form which is usually rendered as text -paragraph below the form title and before the actual form conents. -If omitted, the corresponding paragraph element will not be rendered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

readonlyboolean

-
- - -
-
- -
-

Toggle readonly state of the form.

-

If set to true, the Map instance is marked readonly and any form -option elements added to it will inherit the readonly state.

-

If left unset, the Map will test the access permission of the primary -uci configuration upon loading and mark the form readonly if no write -permissions are granted.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - chain(config) -

- - - - -
- - -
-
- - -
-

Tie another UCI configuration to the map.

-

By default, a map instance will only load the UCI configuration file -specified in the constructor but sometimes access to values from -further configuration files is required. This function allows for such -use cases by registering further UCI configuration files which are -needed by the map.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - -

The additional UCI configuration file to tie to the map. If the given -config already is in the list of required files, it will be ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - findElement(selector_or_attrname, attrvalue){Node|null} -

- - - - -
- - -
-
- - -
-

Find the first DOM node within this Map which matches the given search -parameters. This function is essentially a convenience wrapper around -findElements() which only returns the first found node.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, it is used as selector-expression -as-is. When two arguments are passed, the first argument is treated -as attribute name, the second one as attribute value to match.

-

As an example, map.findElement('input') would find the first <input> -node while map.findElement('type', 'text') would find the first DOM -node with a type="text" attribute.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
selector_or_attrname - - -string - - - - - - - - - - -

If invoked with only one parameter, this argument is a querySelector() -compatible selector expression. If invoked with two parameters, this -argument is the attribute name to filter for.

attrvalue - - -string - - - - - - - optional - - - - - -

In case the function is invoked with two parameters, this argument -specifies the attribute value to match.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an InternalError if more than two function parameters are -passed.

-
-
-
-
-
- Type -
-
- -InternalError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - null - - - Returns the first found DOM node or null if no element matched.
- - - - -
- - - -
-
-

- - findElements(selector_or_attrname, attrvalue){NodeList} -

- - - - -
- - -
-
- - -
-

Find all DOM nodes within this Map which match the given search -parameters. This function is essentially a convenience wrapper around -querySelectorAll().

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, it is used as selector-expression -as-is. When two arguments are passed, the first argument is treated -as attribute name, the second one as attribute value to match.

-

As an example, map.findElements('input') would find all <input> -nodes while map.findElements('type', 'text') would find any DOM node -with a type="text" attribute.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
selector_or_attrname - - -string - - - - - - - - - - -

If invoked with only one parameter, this argument is a -querySelectorAll() compatible selector expression. If invoked with -two parameters, this argument is the attribute name to filter for.

attrvalue - - -string - - - - - - - optional - - - - - -

In case the function is invoked with two parameters, this argument -specifies the attribute value to match.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an InternalError if more than two function parameters are -passed.

-
-
-
-
-
- Type -
-
- -InternalError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - NodeList - - - Returns a (possibly empty) DOM NodeList containing the found DOM nodes.
- - - - -
- - - -
-
-

- - load(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Load the configuration covered by this map.

-

The load() function first loads all referenced UCI configurations, -then it recursively walks the form element tree and invokes the -load function of each child element.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the entire form completed loading all -data. The promise may reject with an error if any configuration failed -to load or if any of the child elements load functions rejected with -an error.
- - - - -
- - - -
-
-

- - lookupOption(name_or_id, section_id, config){Array.<LuCI.form.AbstractValue, string>|null} -

- - - - -
- - -
-
- - -
-

Find a form option element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name_or_id - - -string - - - - - - - - - - -

The name or the full ID of the option element to look up.

section_id - - -string - - - - - - - optional - - - - - -

The ID of the UCI section containing the option to look up. May be -omitted if a full ID is passed as first argument.

config - - -string - - - - - - - optional - - - - - -

The name of the UCI configuration the option instance is belonging to. -Defaults to the main UCI configuration of the map if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<LuCI.form.AbstractValue, string> - | - - null - - - Returns a two-element array containing the form option instance as -first item and the corresponding UCI section ID as second item. -Returns null if the option could not be found.
- - - - -
- - - -
-
-

- - parse(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the form input values.

-

The parse() function recursively walks the form element tree and -triggers input value reading and validation for each child element.

-

Elements which are hidden due to unsatisified dependencies are skipped.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the entire form completed parsing all -input values. The returned promise is rejected if any parsed values are -not meeting the validation constraints of their respective elements.
- - - - -
- - - -
-
-

- - render(){Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Render the form markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Node> - - - Returns a promise resolving to the toplevel form DOM node once the -rendering is complete.
- - - - -
- - - -
-
-

- - reset(){Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Reset the form by re-rendering its contents. This will revert all -unsaved user inputs to their initial form state.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Node> - - - Returns a promise resolving to the toplevel form DOM node once the -re-rendering is complete.
- - - - -
- - - -
-
-

- - save(cb, silent){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Save the form input values.

-

This function parses the current form, saves the resulting UCI changes, -reloads the UCI configuration data and redraws the form elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
cb - - -function - - - - - - - - - optional - - - - - -

An optional callback function that is invoked after the form is parsed -but before the changed UCI data is saved. This is useful to perform -additional data manipulation steps before saving the changes.

silent - - -boolean - - - - - - false - - - - - optional - - - - - -

If set to true, trigger an alert message to the user in case saving -the form data failes. Otherwise fail silently.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the entire save operation is complete. -The returned promise is rejected if any step of the save operation -failed.
- - - - -
- - - -
-
-

- - section(sectionclass, classargs){LuCI.form.AbstractSection} -

- - - - -
- - -
-
- - -
-

Add a configuration section to the map.

-

LuCI forms follow the structure of the underlying UCI configurations, -means that a map, which represents a single UCI configuration, is -divided into multiple sections which in turn contain an arbitrary -number of options.

-

While UCI itself only knows two kinds of sections - named and anonymous -ones - the form class offers various flavors of form section elements -to present configuration sections in different ways. Refer to the -documentation of the different section classes for details.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
sectionclass - - -LuCI.form.AbstractSection - - - - - - - - - - -

The section class to use for rendering the configuration section. -Note that this value must be the class itself, not a class instance -obtained from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -string - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given section class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractSection - - - Returns the instantiated section class instance.
- - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.MultiValue.html b/docs/jsapi/LuCI.form.MultiValue.html deleted file mode 100644 index b3d9896f39..0000000000 --- a/docs/jsapi/LuCI.form.MultiValue.html +++ /dev/null @@ -1,7249 +0,0 @@ - - - - - Class: MultiValue - - - - - - - - - - - - - - - - - -
- - -
-

Class: MultiValue

- - - - -
- -
-

- LuCI.form. - - MultiValue -

- -

The MultiValue class is a modified variant of the DynamicList element -which leverages the LuCI.ui.Dropdown widget to implement a multi -select dropdown element.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.MultiValue(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

display_sizenumber

-
- - -
-
- -
-

Allows to specify the display_items -property of the underlying dropdown widget. If omitted, the value of -the size property is used or 3 when size is unspecified as well.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
- -
- - -
-
- -
-

Allows to specify the dropdown_items -property of the underlying dropdown widget. If omitted, the value of -the size property is used or -1 when size is unspecified as well.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - value(key, value) -

- - - - -
- - -
-
- - -
-

Add a predefined choice to the form option. By adding one or more -choices, the plain text input field is turned into a combobox widget -which prompts the user to select a predefined choice, or to enter a -custom value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.NamedSection.html b/docs/jsapi/LuCI.form.NamedSection.html deleted file mode 100644 index d4a538c185..0000000000 --- a/docs/jsapi/LuCI.form.NamedSection.html +++ /dev/null @@ -1,6396 +0,0 @@ - - - - - Class: NamedSection - - - - - - - - - - - - - - - - - -
- - -
-

Class: NamedSection

- - - - -
- -
-

- LuCI.form. - - NamedSection -

- -

The NamedSection class maps exactly one UCI section instance which is -specified when constructing the class instance.

-

Layout and functionality wise, a named section is essentially a -TypedSection which allows exactly one section node.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.NamedSection(form, section_id, section_type, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by section().

section_id - - -string - - - - - - - - - - -

The name (ID) of the UCI section to map.

section_type - - -string - - - - - - - - - - -

The type of the UCI section to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the form section element.

description - - -string - - - - - - - optional - - - - - -

The description text of the form section element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

addremoveboolean

-
- - -
-
- -
-

If set to true, the user may remove or recreate the sole mapped -configuration instance from the form section widget, otherwise only a -preexisting section may be edited. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the section IDs from. By -default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified. -The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyparentoptionLuCI.form.AbstractValue

-
- - -
-
- -
-

Access the parent option container instance.

-

In case this section is nested within an option element container, -this property will hold a reference to the parent option instance.

-

If this section is not nested, the property is null.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - cfgsections(){Array.<string>} -

- - - - -
- - -
-
- - -
-

The NamedSection class overwrites the generic cfgsections() -implementation to return a one-element array containing the mapped -section ID as sole element. User code should not normally change this.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns a one-element array containing the mapped section ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option configuration values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the configuration values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the configuration value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -configuration values or just a single configuration value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - abstractfilter(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Filter UCI section IDs to render.

-

The filter function is invoked for each UCI section ID of a given type -and controls whether the given UCI section is rendered or ignored by -the form section element.

-

The default implementation always returns true. User code or -classes extending AbstractSection may overwrite this function with -custom implementations.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The UCI section ID to test.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the given UCI section ID should be handled and -false when it should be ignored.
- - - - -
- - - -
-
-

- - inherited - - formvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option widget input values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the widget input values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the widget input value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - getOption(option){null|LuCI.form.AbstractValue|Object.<string, LuCI.form.AbstractValue>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option objects.

-

This function is sensitive to the amount of arguments passed to it; -if no option name is specified, all options within this section are -returned as dictionary.

-

If an option name is supplied, this function returns the matching -LuCI.form.AbstractValue instance only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
option - - -string - - - - - - - optional - - - - - -

The name of the option object to obtain

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.form.AbstractValue - | - - Object.<string, LuCI.form.AbstractValue> - - - Returns either a dictionary of option names and their corresponding -option instance objects or just a single object instance value, -depending on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id, option){null|LuCI.ui.AbstractElement|Object.<string, (null|LuCI.ui.AbstractElement)>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option LuCI.ui widget instances.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the LuCI.ui widget instances of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the LuCI.ui widget instance value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.ui.AbstractElement - | - - Object.<string, (null|LuCI.ui.AbstractElement)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - load(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Load the configuration covered by this section.

-

The load() function recursively walks the section element tree and -invokes the load function of each child option element.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been loaded. The promise may reject with an error if any of the child -elements load functions rejected with an error.
- - - - -
- - - -
-
-

- - inherited - - option(optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to the section.

-

Note that taboption() -should be used instead if this form section element uses tabs.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - inherited - - parse(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse this sections form input.

-

The parse() function recursively walks the section element tree and -triggers input value reading and validation for each encountered child -option element.

-

Options which are hidden due to unsatisified dependencies are skipped.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been parsed. The returned promise is rejected if any parsed values are -not meeting the validation constraints of their respective elements.
- - - - -
- - - -
-
-

- - inherited - - render(){Node|Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Render the form element.

-

The render() function recursively walks the form element tree and -renders the markup for each element, returning the assembled DOM tree.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - Promise.<Node> - - - May return a DOM Node or a promise resolving to a DOM node containing -the form element's markup, including the markup of any child elements.
- - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - tab(name, title, description) -

- - - - -
- - -
-
- - -
-

Add an option tab to the section.

-

The child option elements of a section may be divided into multiple -tabs to provide a better overview to the user.

-

Before options can be moved into a tab pane, the corresponding tab -has to be defined first, which is done by calling this function.

-

Note that once tabs are defined, user code must use the taboption() -method to add options to specific tabs. Option elements added by -option() will not be assigned to any tab and not be rendered in this -case.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - - - - - - -

The name of the tab to register. It may be freely chosen and just serves -as an identifier to differentiate tabs.

title - - -string - - - - - - - - - - -

The human readable caption of the tab.

description - - -string - - - - - - - optional - - - - - -

An additional description text for the corresponding tab pane. It is -displayed as text paragraph below the tab but before the tab pane -contents. If omitted, no description will be rendered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an exeption if a tab with the same name already exists.

-
-
-
-
-
- Type -
-
- -Error - - -
-
-
-
- - - - - - - -
- - - -
-
-

- - inherited - - taboption(tabname, optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to a tab of the section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
tabname - - -string - - - - - - - - - - -

The name of the section tab to add the option element to.

optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
-
    -
  • - -
    -
    -
    -

    Throws a ReferenceError exception when the given tab name does not -exist.

    -
    -
    -
    -
    -
    - Type -
    -
    - -ReferenceError - - -
    -
    -
    -
    - -
  • - -
  • - -
    -
    -
    -

    Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

    -
    -
    -
    -
    -
    - Type -
    -
    - -TypeError - - -
    -
    -
    -
    - -
  • -
- - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.SectionValue.html b/docs/jsapi/LuCI.form.SectionValue.html deleted file mode 100644 index ab6844436b..0000000000 --- a/docs/jsapi/LuCI.form.SectionValue.html +++ /dev/null @@ -1,7180 +0,0 @@ - - - - - Class: SectionValue - - - - - - - - - - - - - - - - - -
- - -
-

Class: SectionValue

- - - - -
- -
-

- LuCI.form. - - SectionValue -

- -

The SectionValue widget embeds a form section element within an option -element container, allowing to nest form sections into other sections.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.SectionValue(form, section, option, subsection_class, class_args) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The internal name of the option element holding the section. Since a section -container element does not read or write any configuration itself, the name -is only used internally and does not need to relate to any underlying UCI -option name.

subsection_class - - -LuCI.form.AbstractSection - - - - - - - - - - -

The class to use for instantiating the nested section element. Note that -the class value itself is expected here, not a class instance obtained by -calling new. The given class argument must be a subclass of the -AbstractSection class.

class_args - - -* - - - - - - - optional - - - - - repeatable - - -

All further arguments are passed as-is to the subclass constructor. Refer -to the corresponding class constructor documentations for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

readonlysubsectionLuCI.form.AbstractSection

-
- - -
-
- -
-

Access the embedded section instance.

-

This property holds a reference to the instantiated nested section.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){null} -

- - - - -
- - -
-
- - -
-

Since the section container is not tied to any UCI configuration, -its cfgvalue() implementation will always return null.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - - -
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){null} -

- - - - -
- - -
-
- - -
-

Since the section container is not tied to any UCI configuration, -its formvalue() implementation will always return null.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - - -
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Since the section container is not tied to any UCI configuration, -its remove() implementation is a no-op.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - value(key, value) -

- - - - -
- - -
-
- - -
-

Since the section container is not rendering an own widget, -its value() implementation is a no-op.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Since the section container is not tied to any UCI configuration, -its write() implementation is a no-op.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.TableSection.html b/docs/jsapi/LuCI.form.TableSection.html deleted file mode 100644 index ba6fe9b88a..0000000000 --- a/docs/jsapi/LuCI.form.TableSection.html +++ /dev/null @@ -1,7068 +0,0 @@ - - - - - Class: TableSection - - - - - - - - - - - - - - - - - -
- - -
-

Class: TableSection

- - - - -
- -
-

- LuCI.form. - - TableSection -

- -

The TableSection class maps all or - if filter() is overwritten - a -subset of the underlying UCI configuration sections of a given type.

-

Layout wise, the configuration section instances mapped by the section -element (sometimes referred to as "section nodes") are rendered as rows -within an HTML table element, with an optional section remove button in the -last column and a section add button below the table, depending on the -value of the addremove property.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.TableSection(form, section_type, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by section().

section_type - - -string - - - - - - - - - - -

The type of the UCI section to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the form section element.

description - - -string - - - - - - - optional - - - - - -

The description text of the form section element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

addbtntitlestring function

-
- - -
-
- -
-

Override the caption used for the section add button at the bottom of -the section form element. If set to a string, it will be used as-is, -if set to a function, the function will be invoked and its return value -is used as caption, after converting it to a string. If this property -is not set, the default is Add.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

addremoveboolean

-
- - -
-
- -
-

If set to true, the user may add or remove instances from the form -section widget, otherwise only preexisting sections may be edited. -The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

anonymousboolean

-
- - -
-
- -
-

If set to true, mapped section instances are treated as anonymous -UCI sections, which means that section instance elements will be -rendered without title element and that no name is required when adding -new sections. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

exteditstring function

-
- - -
-
- -
-

Enables a per-section instance row Edit button which triggers a certain -action when clicked. If set to a string, the string value is used -as String.format() pattern with the name of the underlying UCI section -as first format argument. The result is then interpreted as URL which -LuCI will navigate to when the user clicks the edit button.

-

If set to a function, this function will be registered as click event -handler on the rendered edit button, receiving the section instance -name as first and the DOM click event as second argument.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

max_colsnumber

-
- - -
-
- -
-

Specify a maximum amount of columns to display. By default, one table -column is rendered for each child option of the form section element. -When this option is set to a positive number, then no more columns than -the given amount are rendered. When the number of child options exceeds -the specified amount, a More… button is rendered in the last column, -opening a modal dialog presenting all options elements in NamedSection -style when clicked.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

modaltitlestring function

-
- - -
-
- -
-

Override the per-section instance modal popup title caption shown when -clicking the More… button in a section specifying max_cols. If set -to a string, it will be used as String.format() pattern with the name -of the underlying UCI section as first argument, if set to a function, -the function will be invoked with the section name as first argument and -its return value is used as caption, after converting it to a string. -If this property is not set, the default is the name of the underlying -UCI configuration section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

nodescriptionsboolean

-
- - -
-
- -
-

If set to true, the header row with the options descriptions will -not be displayed. By default, descriptions row is automatically displayed -when at least one option has a description.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rowcolorsboolean

-
- - -
-
- -
-

If set to true, alternating cbi-rowstyle-1 and cbi-rowstyle-2 CSS -classes are added to the table row elements. Not all LuCI themes -implement these row style classes. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

sectiontitlestring function

-
- - -
-
- -
-

Override the per-section instance title caption shown in the first -column of the table unless anonymous is set to true. If set to a -string, it will be used as String.format() pattern with the name of -the underlying UCI section as first argument, if set to a function, the -function will be invoked with the section name as first argument and -its return value is used as caption, after converting it to a string. -If this property is not set, the default is the name of the underlying -UCI configuration section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

sortableboolean

-
- - -
-
- -
-

If set to true, a sort button is added to the last column, allowing -the user to reorder the section instances mapped by the section form -element.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the section IDs from. By -default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified. -The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

addbtntitlestring function

-
- - -
-
- -
-

Override the caption used for the section add button at the bottom of -the section form element. If set to a string, it will be used as-is, -if set to a function, the function will be invoked and its return value -is used as caption, after converting it to a string. If this property -is not set, the default is Add.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

addremoveboolean

-
- - -
-
- -
-

If set to true, the user may add or remove instances from the form -section widget, otherwise only preexisting sections may be edited. -The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

anonymousboolean

-
- - -
-
- -
-

If set to true, mapped section instances are treated as anonymous -UCI sections, which means that section instance elements will be -rendered without title element and that no name is required when adding -new sections. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

readonlyparentoptionLuCI.form.AbstractValue

-
- - -
-
- -
-

Access the parent option container instance.

-

In case this section is nested within an option element container, -this property will hold a reference to the parent option instance.

-

If this section is not nested, the property is null.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

tabbedboolean

-
- - -
-
- -
-

When set to true, instead of rendering section instances one below -another, treat each instance as separate tab pane and render a tab menu -at the top of the form section element, allowing the user to switch -among instances. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the section IDs from. By -default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified. -The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - abstractaddModalOptions(modalSection, section_id, ev){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Add further options to the per-section instanced modal popup.

-

This function may be overwritten by user code to perform additional -setup steps before displaying the more options modal which is useful to -e.g. query additional data or to inject further option elements.

-

The default implementation of this function does nothing.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
modalSection - - -LuCI.form.NamedSection - - - - - -

The NamedSection instance about to be rendered in the modal popup.

section_id - - -string - - - - - -

The ID of the underlying UCI section the modal popup belongs to.

ev - - -Event - - - - - -

The DOM event emitted by clicking the More… button.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Return values of this function are ignored but if a promise is returned, -it is run to completion before the rendering is continued, allowing -custom logic to perform asynchroneous work before the modal dialog -is shown.
- - - - -
- - - -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option configuration values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the configuration values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the configuration value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -configuration values or just a single configuration value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - abstractfilter(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Filter UCI section IDs to render.

-

The filter function is invoked for each UCI section ID of a given type -and controls whether the given UCI section is rendered or ignored by -the form section element.

-

The default implementation always returns true. User code or -classes extending AbstractSection may overwrite this function with -custom implementations.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The UCI section ID to test.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the given UCI section ID should be handled and -false when it should be ignored.
- - - - -
- - - -
-
-

- - inherited - - formvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option widget input values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the widget input values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the widget input value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - getOption(option){null|LuCI.form.AbstractValue|Object.<string, LuCI.form.AbstractValue>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option objects.

-

This function is sensitive to the amount of arguments passed to it; -if no option name is specified, all options within this section are -returned as dictionary.

-

If an option name is supplied, this function returns the matching -LuCI.form.AbstractValue instance only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
option - - -string - - - - - - - optional - - - - - -

The name of the option object to obtain

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.form.AbstractValue - | - - Object.<string, LuCI.form.AbstractValue> - - - Returns either a dictionary of option names and their corresponding -option instance objects or just a single object instance value, -depending on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id, option){null|LuCI.ui.AbstractElement|Object.<string, (null|LuCI.ui.AbstractElement)>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option LuCI.ui widget instances.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the LuCI.ui widget instances of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the LuCI.ui widget instance value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.ui.AbstractElement - | - - Object.<string, (null|LuCI.ui.AbstractElement)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - load(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Load the configuration covered by this section.

-

The load() function recursively walks the section element tree and -invokes the load function of each child option element.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been loaded. The promise may reject with an error if any of the child -elements load functions rejected with an error.
- - - - -
- - - -
-
-

- - inherited - - option(optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to the section.

-

Note that taboption() -should be used instead if this form section element uses tabs.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - inherited - - parse(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse this sections form input.

-

The parse() function recursively walks the section element tree and -triggers input value reading and validation for each encountered child -option element.

-

Options which are hidden due to unsatisified dependencies are skipped.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been parsed. The returned promise is rejected if any parsed values are -not meeting the validation constraints of their respective elements.
- - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - tab(name, title, description) -

- - - - -
- - -
-
- - -
-

The TableSection implementation does not support option tabbing, so -its implementation of tab() will always throw an exception when -invoked.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - - - - - - -

The name of the tab to register. It may be freely chosen and just serves -as an identifier to differentiate tabs.

title - - -string - - - - - - - - - - -

The human readable caption of the tab.

description - - -string - - - - - - - optional - - - - - -

An additional description text for the corresponding tab pane. It is -displayed as text paragraph below the tab but before the tab pane -contents. If omitted, no description will be rendered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
- -

Throws an exception when invoked.

- -
- - - - - - - -
- - - -
-
-

- - inherited - - taboption(tabname, optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to a tab of the section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
tabname - - -string - - - - - - - - - - -

The name of the section tab to add the option element to.

optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
-
    -
  • - -
    -
    -
    -

    Throws a ReferenceError exception when the given tab name does not -exist.

    -
    -
    -
    -
    -
    - Type -
    -
    - -ReferenceError - - -
    -
    -
    -
    - -
  • - -
  • - -
    -
    -
    -

    Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

    -
    -
    -
    -
    -
    - Type -
    -
    - -TypeError - - -
    -
    -
    -
    - -
  • -
- - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.TextValue.html b/docs/jsapi/LuCI.form.TextValue.html deleted file mode 100644 index 3e4c4f1238..0000000000 --- a/docs/jsapi/LuCI.form.TextValue.html +++ /dev/null @@ -1,7196 +0,0 @@ - - - - - Class: TextValue - - - - - - - - - - - - - - - - - -
- - -
-

Class: TextValue

- - - - -
- -
-

- LuCI.form. - - TextValue -

- -

The TextValue class implements a multi-line textarea input using -LuCI.ui.Textarea.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.TextValue(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

colsnumber

-
- - -
-
- -
-

Allows to specify the cols -property of the underlying textarea widget.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

monospaceboolean

-
- - -
-
- -
-

Enforces the use of a monospace font for the textarea contents when set -to true.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rowsnumber

-
- - -
-
- -
-

Allows to specify the rows -property of the underlying textarea widget.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

wrapnumber

-
- - -
-
- -
-

Allows to specify the wrap -property of the underlying textarea widget.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.TypedSection.html b/docs/jsapi/LuCI.form.TypedSection.html deleted file mode 100644 index e947b65056..0000000000 --- a/docs/jsapi/LuCI.form.TypedSection.html +++ /dev/null @@ -1,6553 +0,0 @@ - - - - - Class: TypedSection - - - - - - - - - - - - - - - - - -
- - -
-

Class: TypedSection

- - - - -
- -
-

- LuCI.form. - - TypedSection -

- -

The TypedSection class maps all or - if filter() is overwritten - a -subset of the underlying UCI configuration sections of a given type.

-

Layout wise, the configuration section instances mapped by the section -element (sometimes referred to as "section nodes") are stacked beneath -each other in a single column, with an optional section remove button next -to each section node and a section add button at the end, depending on the -value of the addremove property.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.TypedSection(form, section_type, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by section().

section_type - - -string - - - - - - - - - - -

The type of the UCI section to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the form section element.

description - - -string - - - - - - - optional - - - - - -

The description text of the form section element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

addbtntitlestring function

-
- - -
-
- -
-

Override the caption used for the section add button at the bottom of -the section form element. If set to a string, it will be used as-is, -if set to a function, the function will be invoked and its return value -is used as caption, after converting it to a string. If this property -is not set, the default is Add.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

addremoveboolean

-
- - -
-
- -
-

If set to true, the user may add or remove instances from the form -section widget, otherwise only preexisting sections may be edited. -The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

anonymousboolean

-
- - -
-
- -
-

If set to true, mapped section instances are treated as anonymous -UCI sections, which means that section instance elements will be -rendered without title element and that no name is required when adding -new sections. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

tabbedboolean

-
- - -
-
- -
-

When set to true, instead of rendering section instances one below -another, treat each instance as separate tab pane and render a tab menu -at the top of the form section element, allowing the user to switch -among instances. The default is false.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the section IDs from. By -default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified. -The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

readonlyparentoptionLuCI.form.AbstractValue

-
- - -
-
- -
-

Access the parent option container instance.

-

In case this section is nested within an option element container, -this property will hold a reference to the parent option instance.

-

If this section is not nested, the property is null.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cfgsections(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Enumerate the UCI section IDs covered by this form section element.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an InternalError exception if the function is not implemented.

-
-
-
-
-
- Type -
-
- -InternalError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of UCI section IDs covered by this form element. -The sections will be rendered in the same order as the returned array.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option configuration values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the configuration values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the configuration value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -configuration values or just a single configuration value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - abstractfilter(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Filter UCI section IDs to render.

-

The filter function is invoked for each UCI section ID of a given type -and controls whether the given UCI section is rendered or ignored by -the form section element.

-

The default implementation always returns true. User code or -classes extending AbstractSection may overwrite this function with -custom implementations.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The UCI section ID to test.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the given UCI section ID should be handled and -false when it should be ignored.
- - - - -
- - - -
-
-

- - inherited - - formvalue(section_id, option){null|string|Array.<string>|Object.<string, (null|string|Array.<string>)>} -

- - - - -
- - -
-
- - -
-

Query underlying option widget input values.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the widget input values of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the widget input value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - Object.<string, (null|string|Array.<string>)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - getOption(option){null|LuCI.form.AbstractValue|Object.<string, LuCI.form.AbstractValue>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option objects.

-

This function is sensitive to the amount of arguments passed to it; -if no option name is specified, all options within this section are -returned as dictionary.

-

If an option name is supplied, this function returns the matching -LuCI.form.AbstractValue instance only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
option - - -string - - - - - - - optional - - - - - -

The name of the option object to obtain

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.form.AbstractValue - | - - Object.<string, LuCI.form.AbstractValue> - - - Returns either a dictionary of option names and their corresponding -option instance objects or just a single object instance value, -depending on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id, option){null|LuCI.ui.AbstractElement|Object.<string, (null|LuCI.ui.AbstractElement)>} -

- - - - -
- - -
-
- - -
-

Obtain underlying option LuCI.ui widget instances.

-

This function is sensitive to the amount of arguments passed to it; -if only one argument is specified, the LuCI.ui widget instances of all -options within this section are returned as dictionary.

-

If both the section ID and an option name are supplied, this function -returns the LuCI.ui widget instance value of the specified option only.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - - - - - - -

The configuration section ID

option - - -string - - - - - - - optional - - - - - -

The name of the option to query

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.ui.AbstractElement - | - - Object.<string, (null|LuCI.ui.AbstractElement)> - - - Returns either a dictionary of option names and their corresponding -widget input values or just a single widget input value, depending -on the amount of passed arguments.
- - - - -
- - - -
-
-

- - inherited - - load(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Load the configuration covered by this section.

-

The load() function recursively walks the section element tree and -invokes the load function of each child option element.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been loaded. The promise may reject with an error if any of the child -elements load functions rejected with an error.
- - - - -
- - - -
-
-

- - inherited - - option(optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to the section.

-

Note that taboption() -should be used instead if this form section element uses tabs.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - inherited - - parse(){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse this sections form input.

-

The parse() function recursively walks the section element tree and -triggers input value reading and validation for each encountered child -option element.

-

Options which are hidden due to unsatisified dependencies are skipped.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the values of all child elements have -been parsed. The returned promise is rejected if any parsed values are -not meeting the validation constraints of their respective elements.
- - - - -
- - - -
-
-

- - inherited - - render(){Node|Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Render the form element.

-

The render() function recursively walks the form element tree and -renders the markup for each element, returning the assembled DOM tree.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - Promise.<Node> - - - May return a DOM Node or a promise resolving to a DOM node containing -the form element's markup, including the markup of any child elements.
- - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - tab(name, title, description) -

- - - - -
- - -
-
- - -
-

Add an option tab to the section.

-

The child option elements of a section may be divided into multiple -tabs to provide a better overview to the user.

-

Before options can be moved into a tab pane, the corresponding tab -has to be defined first, which is done by calling this function.

-

Note that once tabs are defined, user code must use the taboption() -method to add options to specific tabs. Option elements added by -option() will not be assigned to any tab and not be rendered in this -case.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - - - - - - -

The name of the tab to register. It may be freely chosen and just serves -as an identifier to differentiate tabs.

title - - -string - - - - - - - - - - -

The human readable caption of the tab.

description - - -string - - - - - - - optional - - - - - -

An additional description text for the corresponding tab pane. It is -displayed as text paragraph below the tab but before the tab pane -contents. If omitted, no description will be rendered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an exeption if a tab with the same name already exists.

-
-
-
-
-
- Type -
-
- -Error - - -
-
-
-
- - - - - - - -
- - - -
-
-

- - inherited - - taboption(tabname, optionclass, classargs){LuCI.form.AbstractValue} -

- - - - -
- - -
-
- - -
-

Add a configuration option widget to a tab of the section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
tabname - - -string - - - - - - - - - - -

The name of the section tab to add the option element to.

optionclass - - -LuCI.form.AbstractValue - - - - - - - - - - -

The option class to use for rendering the configuration option. Note -that this value must be the class itself, not a class instance obtained -from calling new. It must also be a class dervied from -LuCI.form.AbstractSection.

classargs - - -* - - - - - - - - - - repeatable - - -

Additional arguments which are passed as-is to the contructor of the -given option class. Refer to the class specific constructor -documentation for details.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
-
    -
  • - -
    -
    -
    -

    Throws a ReferenceError exception when the given tab name does not -exist.

    -
    -
    -
    -
    -
    - Type -
    -
    - -ReferenceError - - -
    -
    -
    -
    - -
  • - -
  • - -
    -
    -
    -

    Throws a TypeError exception in case the passed class value is not a -descendent of AbstractValue.

    -
    -
    -
    -
    -
    - Type -
    -
    - -TypeError - - -
    -
    -
    -
    - -
  • -
- - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.form.AbstractValue - - - Returns the instantiated option class instance.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.Value.html b/docs/jsapi/LuCI.form.Value.html deleted file mode 100644 index 87ffeed587..0000000000 --- a/docs/jsapi/LuCI.form.Value.html +++ /dev/null @@ -1,7255 +0,0 @@ - - - - - Class: Value - - - - - - - - - - - - - - - - - -
- - -
-

Class: Value

- - - - -
- -
-

- LuCI.form. - - Value -

- -

The Value class represents a simple one-line form input using the -LuCI.ui.Textfield or - in case choices are added - the -LuCI.ui.Combobox class as underlying widget.

- -
- -
-
- - - - -
-
-

- - new LuCI.form.Value(form, section, option, title, description) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
form - - -LuCI.form.Map -| - -LuCI.form.JSONMap - - - - - - - - - - -

The configuration form this section is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

section - - -LuCI.form.AbstractSection - - - - - - - - - - -

The configuration section this option is added to. It is automatically passed -by option() or -taboption() when adding the -option to the section.

option - - -string - - - - - - - - - - -

The name of the UCI option to map.

title - - -string - - - - - - - optional - - - - - -

The title caption of the option element.

description - - -string - - - - - - - optional - - - - - -

The description text of the option element.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - -

Members

- -
- -
-
-

passwordboolean

-
- - -
-
- -
-

If set to true, the field is rendered as password input, otherwise -as plain text input.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

placeholderstring

-
- - -
-
- -
-

Set a placeholder string to use when the input field is empty.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

datatypestring

-
- - -
-
- -
-

Specifies a datatype constraint expression to validate input values -against. Refer to LuCI.validation for details on the format.

-

If the user entered input does not match the datatype validation, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

default*

-
- - -
-
- -
-

Sets a default value to use when the underlying UCI option is not set.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

editableboolean

-
- - -
-
- -
-

Mark grid section option element as editable.

-

Options which are displayed in the table portion of a GridSection -instance are rendered as readonly text by default. By setting the -editable property of a child option element to true, that element -is rendered as full input widget within its cell instead of a text only -preview.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

modalonlyboolean

-
- - -
-
- -
-

Move grid section option element into the table, the modal popup or both.

-

If this property is null (the default), the option element is -displayed in both the table preview area and the per-section instance -modal popup of a grid section. When it is set to false the option -is only shown in the table but not the modal popup. When set to true, -the option is only visible in the modal popup but not the table.

-

This property has no effect on options that are not children of grid -section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

onchangefunction

-
- - -
-
- -
-

Register a custom value change handler.

-

If this property is set to a function value, the function is invoked -whenever the value of the underlying UI input element is changing.

-

The invoked handler function will receive the DOM click element as -first and the underlying configuration section ID as well as the input -value as second and third argument respectively.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

optionalboolean

-
- - -
-
- -
-

If set to true, the underlying ui input widget is allowed to be empty, -otherwise the option element is marked invalid when no value is entered -or selected by the user.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

readonlyboolean

-
- - -
-
- -
-

Make option element readonly.

-

This property defaults to the readonly state of the parent form element. -When set to true, the underlying widget is rendered in disabled state, -means its contents cannot be changed and the widget cannot be interacted -with.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • false
- - - - - - - -
- - - -
- - - -
-
-

rmemptyboolean

-
- - -
-
- -
-

If set to false, the underlying option value is retained upon saving -the form when the option element is disabled due to unsatisfied -dependency constraints.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • true
- - - - - - - -
- - - -
- - - -
-
-

uciconfigstring

-
- - -
-
- -
-

Override the UCI configuration name to read the option value from.

-

By default, the configuration name is inherited from the parent Map. -By setting this property, a deviating configuration may be specified.

-

The default is null, means inheriting from the parent form.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucioptionstring

-
- - -
-
- -
-

Override the UCI option name to read the value from.

-

By default, the elements name, which is passed as third argument to -the constructor, is used as UCI option name. By setting this property, -a deviating UCI option may be specified.

-

The default is null, means using the option element name.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

ucisectionstring

-
- - -
-
- -
-

Override the UCI section name to read the option value from.

-

By default, the section ID is inherited from the parent section element. -By setting this property, a deviating section may be specified.

-

The default is null, means inheriting from the parent section.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

validatefunction

-
- - -
-
- -
-

Specifies a custom validation function to test the user input for -validity. The validation function must return true to accept the -value. Any other return value type is converted to a string and -displayed to the user as validation error message.

-

If the user entered input does not pass the validation function, the -option element is marked as invalid.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- - - -
-
-

widthnumber string

-
- - -
-
- -
-

Override the cell width of a table or grid section child option.

-

If the property is set to a numeric value, it is treated as pixel width -which is set on the containing cell element of the option, essentially -forcing a certain column width. When the property is set to a string -value, it is applied as-is to the CSS width property.

-

This property has no effect on options that are not children of grid or -table section elements.

-
- - - -
- - - - - - - - - - - - - - - -
Default Value:
-
  • null
- - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - inherited - - append(element) -

- - - - -
- - -
-
- - -
-

Add another form element as children to this element.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
element - - -AbstractElement - - - - - -

The form element to add.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - cbid(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain the internal ID ("cbid") of the element instance.

-

Since each form section element may map multiple underlying -configuration sections, the configuration section ID is required to -form a fully qualified ID pointing to the specific element instance -within the given specific section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the element ID.
- - - - -
- - - -
-
-

- - inherited - - cfgvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the underlying configuration value.

-

The default implementation of this method returns the cached return -value of load(). It may be -overwritten by user code to obtain the configuration value in a -different way.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the configuration value.
- - - - -
- - - -
-
-

- - inherited - - depends(optionname_or_depends, optionvalue|RegExp) -

- - - - -
- - -
-
- - -
-

Add a dependency contraint to the option.

-

Dependency constraints allow making the presence of option elements -dependant on the current values of certain other options within the -same form. An option element with unsatisfied dependencies will be -hidden from the view and its current value is omitted when saving.

-

Multiple constraints (that is, multiple calls to depends()) are -treated as alternatives, forming a logical "or" expression.

-

By passing an object of name => value pairs as first argument, it is -possible to depend on multiple options simultaneously, allowing to form -a logical "and" expression.

-

Option names may be given in "dot notation" which allows to reference -option elements outside of the current form section. If a name without -dot is specified, it refers to an option within the same configuration -section. If specified as configname.sectionid.optionname, -options anywhere within the same form may be specified.

-

The object notation also allows for a number of special keys which are -not treated as option names but as modifiers to influence the dependency -constraint evaluation. The associated value of these special "tag" keys -is ignored. The recognized tags are:

-
    -
  • - !reverse
    - Invert the dependency, instead of requiring another option to be - equal to the dependency value, that option should not be - equal. -
  • -
  • - !contains
    - Instead of requiring an exact match, the dependency is considered - satisfied when the dependency value is contained within the option - value. -
  • -
  • - !default
    - The dependency is always satisfied -
  • -
-

Examples:

-
    -
  • - opt.depends("foo", "test")
    - Require the value of `foo` to be `test`. -
  • -
  • - opt.depends({ foo: "test" })
    - Equivalent to the previous example. -
  • -
  • - opt.depends({ foo: /test/ })
    - Require the value of `foo` to match the regular expression `/test/`. -
  • -
  • - opt.depends({ foo: "test", bar: "qrx" })
    - Require the value of `foo` to be `test` and the value of `bar` to be - `qrx`. -
  • -
  • - opt.depends({ foo: "test" })
    - opt.depends({ bar: "qrx" })

    - Require either foo to be set to test, - or the bar option to be qrx. -
  • -
  • - opt.depends("test.section1.foo", "bar")
    - Require the "foo" form option within the "section1" section to be - set to "bar". -
  • -
  • - opt.depends({ foo: "test", "!contains": true })
    - Require the "foo" option value to contain the substring "test". -
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
optionname_or_depends - - -string -| - -Object.<string, (string|RegExp)> - - - - - -

The name of the option to depend on or an object describing multiple -dependencies which must be satified (a logical "and" expression).

optionvalue|RegExp - - -string - - - - - -

When invoked with a plain option name as first argument, this parameter -specifies the expected value. In case an object is passed as first -argument, this parameter is ignored.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - formvalue(section_id){*} -

- - - - -
- - -
-
- - -
-

Query the current form input value.

-

The default implementation of this method returns the current input -value of the underlying LuCI.ui widget. -It may be overwritten by user code to handle input values differently.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the current input value.
- - - - -
- - - -
-
-

- - inherited - - getUIElement(section_id){LuCI.ui.AbstractElement|null} -

- - - - -
- - -
-
- - -
-

Obtain the underlying LuCI.ui element instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.ui.AbstractElement - | - - null - - - Returns the LuCI.ui element instance or null in case the form -option implementation does not use LuCI.ui widgets.
- - - - -
- - - -
-
-

- - inherited - - isActive(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the option element is currently active.

-

An element is active when it is not hidden due to unsatisfied dependency -constraints.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the option element currently is active, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - isValid(section_id){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the input value is currently valid.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value currently is valid, otherwise it -returns false.
- - - - -
- - - -
-
-

- - inherited - - load(section_id){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Load the underlying configuration value.

-

The default implementation of this method reads and returns the -underlying UCI option value (or the related JavaScript property for -JSONMap instances). It may be overwritten by user code to load data -from nonstandard sources.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Returns the configuration value to initialize the option element with. -The return value of this function is filtered through Promise.resolve() -so it may return promises if overridden by user code.
- - - - -
- - - -
-
-

- - inherited - - parse(section_id){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Parse the option element input.

-

The function is invoked when the parse() method has been invoked on -the parent form and triggers input value reading and validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving once the input value has been read and -validated or rejecting in case the input value does not meet the -validation constraints.
- - - - -
- - - -
-
-

- - inherited - - remove(section_id) -

- - - - -
- - -
-
- - -
-

Remove the corresponding value from the configuration.

-

This function is invoked upon saving the parent form when the option -element has been hidden due to unsatisfied dependencies or when the -user cleared the input value and the option is marked optional.

-

The default implementation simply removes the associated option from the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative removal logic, e.g. to retain the original value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - render(){Node|Promise.<Node>} -

- - - - -
- - -
-
- - -
-

Render the form element.

-

The render() function recursively walks the form element tree and -renders the markup for each element, returning the assembled DOM tree.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - Promise.<Node> - - - May return a DOM Node or a promise resolving to a DOM node containing -the form element's markup, including the markup of any child elements.
- - - - -
- - - -
-
-

- - inherited - - stripTags(input){string} -

- - - - -
- - -
-
- - -
-

Strip any HTML tags from the given input string.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
input - - -string - - - - - -

The input string to clean.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The cleaned input string with HTML removes removed.
- - - - -
- - - -
-
-

- - inherited - - textvalue(section_id){string} -

- - - - -
- - -
-
- - -
-

Obtain a textual input representation.

-

The default implementation of this method returns the HTML escaped -current input value of the underlying -LuCI.ui widget. User code or specific -option element implementations may overwrite this function to apply a -different logic, e.g. to return Yes or No depending on the checked -state of checkbox elements.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws a TypeError exception when no section_id was specified.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the text representation of the current input value.
- - - - -
- - - -
-
-

- - inherited - - titleFn(property, fmt_args){string|null} -

- - - - -
- - -
-
- - -
-

Format the given named property as title string.

-

This function looks up the given named property and formats its value -suitable for use as element caption or description string. It also -strips any HTML tags from the result.

-

If the property value is a string, it is passed to String.format() -along with any additional parameters passed to titleFn().

-

If the property value is a function, it is invoked with any additional -titleFn() parameters as arguments and the obtained return value is -converted to a string.

-

In all other cases, null is returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
property - - -string - - - - - - - - - - -

The name of the element property to use.

fmt_args - - -* - - - - - - - - - - repeatable - - -

Extra values to format the title string with.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The formatted title string or null if the property did not exist or -was neither a string nor a function.
- - - - -
- - - -
-
-

- - value(key, value) -

- - - - -
- - -
-
- - -
-

Add a predefined choice to the form option. By adding one or more -choices, the plain text input field is turned into a combobox widget -which prompts the user to select a predefined choice, or to enter a -custom value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The choice value to add.

value - - -Node -| - -string - - - - - -

The caption for the choice value. May be a DOM node, a document fragment -or a plain text string. If omitted, the key value is used as caption.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - write(section_id, formvalue) -

- - - - -
- - -
-
- - -
-

Write the current input value into the configuration.

-

This function is invoked upon saving the parent form when the option -element is valid and when its input value has been changed compared to -the initial value returned by -cfgvalue().

-

The default implementation simply sets the given input value in the -UCI configuration (or the associated JavaScript object property in -case of JSONMap forms). It may be overwritten by user code to -implement alternative save logic, e.g. to transform the input value -before it is written.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section_id - - -string - - - - - -

The configuration section ID

formvalue - - -string -| - -Array.<string> - - - - - -

The input value to write.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.form.html b/docs/jsapi/LuCI.form.html deleted file mode 100644 index d16fdf455a..0000000000 --- a/docs/jsapi/LuCI.form.html +++ /dev/null @@ -1,3654 +0,0 @@ - - - - - Class: form - - - - - - - - - - - - - - - - - -
- - -
-

Class: form

- - - - -
- -
-

- LuCI. - - form -

- -

The LuCI form class provides high level abstractions for creating creating -UCI- or JSON backed configurations forms.

-

To import the class in views, use 'require form', to import it in -external JavaScript, use L.require("form").then(...).

-

A typical form is created by first constructing a -LuCI.form.Map or LuCI.form.JSONMap instance using new and -by subsequently adding sections and options to it. Finally -render() is invoked on the instance to -assemble the HTML markup and insert it into the DOM.

-

Example:

-
-'use strict';
-'require form';
-
-var m, s, o;
-
-m = new form.Map('example', 'Example form',
-	'This is an example form mapping the contents of /etc/config/example');
-
-s = m.section(form.NamedSection, 'first_section', 'example', 'The first section',
-	'This sections maps "config example first_section" of /etc/config/example');
-
-o = s.option(form.Flag, 'some_bool', 'A checkbox option');
-
-o = s.option(form.ListValue, 'some_choice', 'A select element');
-o.value('choice1', 'The first choice');
-o.value('choice2', 'The second choice');
-
-m.render().then(function(node) {
-	document.body.appendChild(node);
-});
-
- -
- -
-
- - - - -
-
-

- - new LuCI.form() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - -

Classes

- -
-
AbstractElement
-
- -
AbstractSection
-
- -
AbstractValue
-
- -
ButtonValue
-
- -
DummyValue
-
- -
DynamicList
-
- -
FileUpload
-
- -
FlagValue
-
- -
GridSection
-
- -
HiddenValue
-
- -
JSONMap
-
- -
ListValue
-
- -
Map
-
- -
MultiValue
-
- -
NamedSection
-
- -
SectionValue
-
- -
TableSection
-
- -
TextValue
-
- -
TypedSection
-
- -
Value
-
-
- - - - - - - - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.fs.html b/docs/jsapi/LuCI.fs.html deleted file mode 100644 index 2787f35cac..0000000000 --- a/docs/jsapi/LuCI.fs.html +++ /dev/null @@ -1,5831 +0,0 @@ - - - - - Class: fs - - - - - - - - - - - - - - - - - -
- - -
-

Class: fs

- - - - -
- -
-

- LuCI. - - fs -

- -

Provides high level utilities to wrap file system related RPC calls. -To import the class in views, use 'require fs', to import it in -external JavaScript, use L.require("fs").then(...).

- -
- -
-
- - - - -
-
-

- - new LuCI.fs() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - exec(command, params, env){Promise.<LuCI.fs.FileExecResult>} -

- - - - -
- - -
-
- - -
-

Execute the specified command, optionally passing params and -environment variables.

-

Note: The command must be either the path to an executable, -or a basename without arguments in which case it will be searched -in $PATH. If specified, the values given in params will be passed -as arguments to the command.

-

The key/value pairs in the optional env table are translated to -setenv() calls prior to running the command.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
command - - -string - - - - - - - - - - -

The command to invoke.

params - - -Array.<string> - - - - - - - optional - - - - - -

The arguments to pass to the command.

env - - -Object.<string, string> - - - - - - - optional - - - - - -

Environment variables to set.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.fs.FileExecResult> - - - Returns a promise resolving to an object describing the execution -results or rejecting with an error stating the failure reason.
- - - - -
- - - -
-
-

- - exec_direct(command, params, type, latin1){Promise.<*>} -

- - - - -
- - -
-
- - -
-

Execute the specified command, bypassing ubus.

-

Note: The command must be either the path to an executable, -or a basename without arguments in which case it will be searched -in $PATH. If specified, the values given in params will be passed -as arguments to the command.

-

This function will invoke the requested commands through the cgi-io -helper applet at /cgi-bin/cgi-exec which bypasses the ubus rpc -transport. This is useful to fetch large command outputs which might -exceed the ubus message size limits or which contain binary data.

-

The cgi-io helper will enforce the same access permission rules as -the ubus based exec call.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
command - - -string - - - - - - - - - - - - -

The command to invoke.

params - - -Array.<string> - - - - - - - - - optional - - - - - -

The arguments to pass to the command.

type - - -string - - - - - - text - - - - - optional - - - - - -

The expected output type of the invoked program. Valid values are -text to interpret the output as string, json to parse the output -as JSON or blob to return the output as Blob instance.

latin1 - - -boolean - - - - - - false - - - - - optional - - - - - -

Whether to encode the command line as Latin1 instead of UTF-8. This -is usually not needed but can be useful for programs that cannot -handle UTF-8 input.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<*> - - - Returns a promise resolving with the command stdout output interpreted -according to the specified type or rejecting with an error stating the -failure reason.
- - - - -
- - - -
-
-

- - lines(path){Promise.<Array.<string>>} -

- - - - -
- - -
-
- - -
-

Read the contents of the given file, split it into lines, trim -leading and trailing white space of each line and return the -resulting array.

-

This function is guaranteed to not reject its promises, on failure, -an empty array will be returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
path - - -string - - - - - -

The file path to read.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<string>> - - - Returns a promise resolving to an array containing the stripped lines -of the given file or [] on failure.
- - - - -
- - - -
-
-

- - list(path){Promise.<Array.<LuCI.fs.FileStatEntry>>} -

- - - - -
- - -
-
- - -
-

Obtains a listing of the specified directory.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
path - - -string - - - - - -

The directory path to list.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.fs.FileStatEntry>> - - - Returns a promise resolving to an array of stat detail objects or -rejecting with an error stating the failure reason.
- - - - -
- - - -
-
-

- - read(path){Promise.<string>} -

- - - - -
- - -
-
- - -
-

Read the contents of the given file and return them. -Note: this function is unsuitable for obtaining binary data.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
path - - -string - - - - - -

The file path to read.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<string> - - - Returns a promise resolving to a string containing the file contents or -rejecting with an error stating the failure reason.
- - - - -
- - - -
-
-

- - read_direct(path, type){Promise.<*>} -

- - - - -
- - -
-
- - -
-

Read the contents of the given file and return them, bypassing ubus.

-

This function will read the requested file through the cgi-io -helper applet at /cgi-bin/cgi-download which bypasses the ubus rpc -transport. This is useful to fetch large file contents which might -exceed the ubus message size limits or which contain binary data.

-

The cgi-io helper will enforce the same access permission rules as -the ubus based read call.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
path - - -string - - - - - - - - - - - - -

The file path to read.

type - - -string - - - - - - text - - - - - optional - - - - - -

The expected type of read file contents. Valid values are text to -interpret the contents as string, json to parse the contents as JSON -or blob to return the contents as Blob instance.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<*> - - - Returns a promise resolving with the file contents interpreted according -to the specified type or rejecting with an error stating the failure -reason.
- - - - -
- - - -
-
-

- - remove(The){Promise.<number>} -

- - - - -
- - -
-
- - -
-

Unlink the given file.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
The - - -string - - - - - -

file path to remove.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<number> - - - Returns a promise resolving to 0 or rejecting with an error stating -the failure reason.
- - - - -
- - - -
-
-

- - stat(path){Promise.<LuCI.fs.FileStatEntry>} -

- - - - -
- - -
-
- - -
-

Return file stat information on the specified path.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
path - - -string - - - - - -

The filesystem path to stat.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.fs.FileStatEntry> - - - Returns a promise resolving to a stat detail object or -rejecting with an error stating the failure reason.
- - - - -
- - - -
-
-

- - trimmed(path){Promise.<string>} -

- - - - -
- - -
-
- - -
-

Read the contents of the given file, trim leading and trailing white -space and return the trimmed result. In case of errors, return an empty -string instead.

-

Note: this function is useful to read single-value files in /sys -or /proc.

-

This function is guaranteed to not reject its promises, on failure, -an empty string will be returned.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
path - - -string - - - - - -

The file path to read.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<string> - - - Returns a promise resolving to the file contents or the empty string -on failure.
- - - - -
- - - -
-
-

- - write(path, data, mode){Promise.<number>} -

- - - - -
- - -
-
- - -
-

Write the given data to the specified file path. -If the specified file path does not exist, it will be created, given -sufficient permissions.

-

Note: data will be converted to a string using String(data) or to -'' when it is null.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
path - - -string - - - - - - - - - - -

The file path to write to.

data - - -* - - - - - - - optional - - - - - -

The file data to write. If it is null, it will be set to an empty -string.

mode - - -number - - - - - - - optional - - - - - -

The permissions to use on file creation. Default is 420 (0644).

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<number> - - - Returns a promise resolving to 0 or rejecting with an error stating -the failure reason.
- - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.fs.FileExecResultObject

-
- - -
-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
code - - -number - - - - - - - -

The exit code of the invoked command

stdout - - -string - - - - - - <optional>
- - - -

The stdout produced by the command, if any

stderr - - -string - - - - - - <optional>
- - - -

The stderr produced by the command, if any

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

LuCI.fs.FileStatEntryObject

-
- - -
-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - -

Name of the directory entry

type - - -string - - - -

Type of the entry, one of block, char, directory, fifo, symlink, file, socket or unknown

size - - -number - - - -

Size in bytes

mode - - -number - - - -

Access permissions

atime - - -number - - - -

Last access time in seconds since epoch

mtime - - -number - - - -

Last modification time in seconds since epoch

ctime - - -number - - - -

Last change time in seconds since epoch

inode - - -number - - - -

Inode number

uid - - -number - - - -

Numeric owner id

gid - - -number - - - -

Numeric group id

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.headers.html b/docs/jsapi/LuCI.headers.html deleted file mode 100644 index 1296c12af9..0000000000 --- a/docs/jsapi/LuCI.headers.html +++ /dev/null @@ -1,3859 +0,0 @@ - - - - - Class: headers - - - - - - - - - - - - - - - - - -
- - -
-

Class: headers

- - - - -
- -
-

- LuCI. - - headers -

- -

The Headers class is an internal utility class exposed in HTTP -response objects using the response.headers property.

- -
- -
-
- - - - -
-
-

- - new LuCI.headers() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - get(name){string|null} -

- - - - -
- - -
-
- - -
-

Returns the value of the given header name. -Note: Header-Names are case-insensitive.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - -

The header name to read

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - The value of the given header name or null if the header isn't present.
- - - - -
- - - -
-
-

- - has(name){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether the given header name is present. -Note: Header-Names are case-insensitive.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - -

The header name to check

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the header name is present, false otherwise
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.html b/docs/jsapi/LuCI.html deleted file mode 100644 index 4247c34645..0000000000 --- a/docs/jsapi/LuCI.html +++ /dev/null @@ -1,8054 +0,0 @@ - - - - - Class: LuCI - - - - - - - - - - - - - - - - - -
- - -
-

Class: LuCI

- - - - -
- -
-

- LuCI -

- -

This is the LuCI base class. It is automatically instantiated and -accessible using the global L variable.

- -
- -
-
- - - - -
-
-

- - new LuCI(env) -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
env - - -Object - - - - - -

The environment settings to use for the LuCI runtime.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - -

Classes

- -
-
baseclass
-
- -
dom
-
- -
form
-
- -
fs
-
- -
headers
-
- -
network
-
- -
poll
-
- -
request
-
- -
response
-
- -
rpc
-
- -
session
-
- -
uci
-
- -
ui
-
- -
view
-
- -
xhr
-
-
- - - - - -

Members

- -
- -
-
-

Class

-
- - -
-
- -
-

Legacy L.Class class alias. New view code should use 'require baseclass'; -to request the LuCI.baseclass class.

-
- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

dom

-
- - -
-
- -
-

Legacy L.dom class alias. New view code should use 'require dom'; -to request the LuCI.dom class.

-
- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

env

-
- - -
-
- -
-

The env object holds environment settings used by LuCI, such -as request timeouts, base URLs etc.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

Poll

-
- - -
-
- -
-

Legacy L.Poll class alias. New view code should use 'require poll'; -to request the LuCI.poll class.

-
- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

Request

-
- - -
-
- -
-

Legacy L.Request class alias. New view code should use 'require request'; -to request the LuCI.request class.

-
- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

view

-
- - -
-
- -
-

Legacy L.view class alias. New view code should use 'require view'; -to request the LuCI.view class.

-
- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - bind(fn, self, args){function} -

- - - - -
- - -
-
- - -
-

Return a bound function using the given self as this context -and any further arguments as parameters to the bound function.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
fn - - -function - - - - - - - - - - -

The function to bind.

self - - -* - - - - - - - - - - -

The value to bind as this context to the specified function.

args - - -* - - - - - - - optional - - - - - repeatable - - -

Zero or more variable arguments which are bound to the function -as parameters.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - function - - - Returns the bound function.
- - - - -
- - - -
-
-

- - error(type, fmt, args) -

- - - - -
- - -
-
- - -
-

A wrapper around raise() which also renders -the error either as modal overlay when ui.js is already loaed -or directly into the view body.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
type - - -Error -| - -string - - - - - - Error - - - - - optional - - - - - -

Either a string specifying the type of the error to throw or an -existing Error instance to copy.

fmt - - -string - - - - - - Unspecified error - - - - - optional - - - - - -

A format string which is used to form the error message, together -with all subsequent optional arguments.

args - - -* - - - - - - - - - optional - - - - - repeatable - - -

Zero or more variable arguments to the supplied format string.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws the created error object with the captured stack trace -appended to the message and the type set to the given type -argument or copied from the given error instance.

-
-
-
-
-
- Type -
-
- -Error - - -
-
-
-
- - - - - - - -
- - - -
-
-

- - fspath(parts){string} -

- - - - -
- - -
-
- - -
-

Construct an absolute filesystem path relative to the server -document root.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
parts - - -string - - - - - - - optional - - - - - repeatable - - -

An array of parts to join into a path.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Return the joined path.
- - - - -
- - - -
-
-

- - get(url, args, cb){Promise.<null>} -

- - - - -
- - -
-
- - -
-

Issues a GET request to the given url and invokes the specified -callback function. The function is a wrapper around -Request.request().

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
url - - -string - - - - - - - - - - -

The URL to request.

args - - -Object.<string, string> - - - - - - - optional - - - - - -

Additional query string arguments to append to the URL.

cb - - -LuCI.requestCallbackFn - - - - - - - - - - -

The callback function to invoke when the request finishes.

- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<null> - - - Returns a promise resolving to null when concluded.
- - - - -
- - - -
-
-

- - halt(){boolean} -

- - - - -
- - -
-
- - -
-

Deprecated wrapper around Poll.stop().

-
- - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the polling loop has been stopped or false -when it didn't run to begin with.
- - - - -
- - - -
-
-

- - hasSystemFeature(feature, subfeature){boolean|null} -

- - - - -
- - -
-
- - -
-

Test whether a particular system feature is available, such as -hostapd SAE support or an installed firewall. The features are -queried once at the beginning of the LuCI session and cached in -SessionStorage throughout the lifetime of the associated tab or -browser window.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
feature - - -string - - - - - - - - - - -

The feature to test. For detailed list of known feature flags, -see /modules/luci-base/root/usr/libexec/rpcd/luci.

subfeature - - -string - - - - - - - optional - - - - - -

Some feature classes like hostapd provide sub-feature flags, -such as sae or 11w support. The subfeature argument can -be used to query these.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - | - - null - - - Return true if the queried feature (and sub-feature) is available -or false if the requested feature isn't present or known. -Return null when a sub-feature was queried for a feature which -has no sub-features.
- - - - -
- - - -
-
-

- - hasViewPermission(){boolean|null} -

- - - - -
- - -
-
- - -
-

Check whether a view has sufficient permissions.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - | - - null - - - Returns null if the current session has no permission at all to -load resources required by the view. Returns false if readonly -permissions are granted or true if at least one required ACL -group is granted with write permissions.
- - - - -
- - - -
-
-

- - isObject(val){boolean} -

- - - - -
- - -
-
- - -
-

Tests whether the passed argument is a JavaScript object. -This function is meant to be an object counterpart to the -standard Array.isArray() function.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
val - - -* - - - - - - - optional - - - - - -

The value to test

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the given value is of type object and -not null, else returns false.
- - - - -
- - - -
-
-

- - location(){string} -

- - - - -
- - -
-
- - -
-

Return the complete URL path to the current view.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the URL path to the current view.
- - - - -
- - - -
-
-

- - media(parts){string} -

- - - - -
- - -
-
- - -
-

Construct an URL path relative to the media resource path of the -LuCI ui (usually /luci-static/$theme_name).

-

The resulting URL is guaranteed to only contain the characters -a-z, A-Z, 0-9, _, ., %, ,, ;, and - as well -as / for the path separator.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
parts - - -Array.<string> - - - - - - - optional - - - - - -

An array of parts to join into an URL path. Parts may contain -slashes and any of the other characters mentioned above.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the resulting URL path.
- - - - -
- - - -
-
-

- - path(prefix, parts){string} -

- - - - -
- - -
-
- - -
-

Construct a relative URL path from the given prefix and parts. -The resulting URL is guaranteed to only contain the characters -a-z, A-Z, 0-9, _, ., %, ,, ;, and - as well -as / for the path separator.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
prefix - - -string - - - - - - - optional - - - - - -

The prefix to join the given parts with. If the prefix is -omitted, it defaults to an empty string.

parts - - -Array.<string> - - - - - - - optional - - - - - -

An array of parts to join into an URL path. Parts may contain -slashes and any of the other characters mentioned above.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Return the joined URL path.
- - - - -
- - - -
-
-

- - poll(interval, url, args, cb, post){function} -

- - - - -
- - -
-
- - -
-

Register a polling HTTP request that invokes the specified -callback function. The function is a wrapper around -Request.poll.add().

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
interval - - -number - - - - - - - - - - - - -

The poll interval to use. If set to a value less than or equal -to 0, it will default to the global poll interval configured -in LuCI.env.pollinterval.

url - - -string - - - - - - - - - - - - -

The URL to request.

args - - -Object.<string, string> - - - - - - - - - optional - - - - - -

Specifies additional arguments for the request. For GET requests, -the arguments are appended to the URL as query string, for POST -requests, they'll be added to the request body.

cb - - -LuCI.requestCallbackFn - - - - - - - - - - - - -

The callback function to invoke whenever a request finishes.

post - - -boolean - - - - - - false - - - - - optional - - - - - -

When set to false or not specified, poll requests will be made -using the GET method. When set to true, POST requests will be -issued. In case of POST requests, the request body will contain -an argument token with the current value of LuCI.env.token by -default, regardless of the parameters specified with args.

- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - function - - - Returns the internally created function that has been passed to -Request.poll.add(). This value can -be passed to Poll.remove() to remove the -polling request.
- - - - -
- - - -
-
-

- - post(url, args, cb){Promise.<null>} -

- - - - -
- - -
-
- - -
-

Issues a POST request to the given url and invokes the specified -callback function. The function is a wrapper around -Request.request(). The request is -sent using application/x-www-form-urlencoded encoding and will -contain a field token with the current value of LuCI.env.token -by default.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
url - - -string - - - - - - - - - - -

The URL to request.

args - - -Object.<string, string> - - - - - - - optional - - - - - -

Additional post arguments to append to the request body.

cb - - -LuCI.requestCallbackFn - - - - - - - - - - -

The callback function to invoke when the request finishes.

- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<null> - - - Returns a promise resolving to null when concluded.
- - - - -
- - - -
-
-

- - raise(type, fmt, args) -

- - - - -
- - -
-
- - -
-

Captures the current stack trace and throws an error of the -specified type as a new exception. Also logs the exception as -error to the debug console if it is available.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
type - - -Error -| - -string - - - - - - Error - - - - - optional - - - - - -

Either a string specifying the type of the error to throw or an -existing Error instance to copy.

fmt - - -string - - - - - - Unspecified error - - - - - optional - - - - - -

A format string which is used to form the error message, together -with all subsequent optional arguments.

args - - -* - - - - - - - - - optional - - - - - repeatable - - -

Zero or more variable arguments to the supplied format string.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws the created error object with the captured stack trace -appended to the message and the type set to the given type -argument or copied from the given error instance.

-
-
-
-
-
- Type -
-
- -Error - - -
-
-
-
- - - - - - - -
- - - -
-
-

- - require(name){Promise.<LuCI.baseclass>} -

- - - - -
- - -
-
- - -
-

Load an additional LuCI JavaScript class and its dependencies, -instantiate it and return the resulting class instance. Each -class is only loaded once. Subsequent attempts to load the same -class will return the already instantiated class.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - -

The name of the class to load in dotted notation. Dots will -be replaced by spaces and joined with the runtime-determined -base URL of LuCI.js to form an absolute URL to load the class -file from.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
-
    -
  • - -
    -
    -
    -

    Throws a DependencyError when the class to load includes -circular dependencies.

    -
    -
    -
    -
    -
    - Type -
    -
    - -DependencyError - - -
    -
    -
    -
    - -
  • - -
  • - -
    -
    -
    -

    Throws NetworkError when the underlying LuCI.request -call failed.

    -
    -
    -
    -
    -
    - Type -
    -
    - -NetworkError - - -
    -
    -
    -
    - -
  • - -
  • - -
    -
    -
    -

    Throws SyntaxError when the loaded class file code cannot -be interpreted by eval.

    -
    -
    -
    -
    -
    - Type -
    -
    - -SyntaxError - - -
    -
    -
    -
    - -
  • - -
  • - -
    -
    -
    -

    Throws TypeError when the class file could be loaded and -interpreted, but when invoking its code did not yield a valid -class instance.

    -
    -
    -
    -
    -
    - Type -
    -
    - -TypeError - - -
    -
    -
    -
    - -
  • -
- - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.baseclass> - - - Returns the instantiated class.
- - - - -
- - - -
-
-

- - resolveDefault(value, defvalue){Promise.<*>} -

- - - - -
- - -
-
- - -
-

Returns a promise resolving with either the given value or or with -the given default in case the input value is a rejecting promise.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -* - - - - - -

The value to resolve the promise with.

defvalue - - -* - - - - - -

The default value to resolve the promise with in case the given -input value is a rejecting promise.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<*> - - - Returns a new promise resolving either to the given input value or -to the given default value on error.
- - - - -
- - - -
-
-

- - resource(parts){string} -

- - - - -
- - -
-
- - -
-

Construct an URL path relative to the global static resource path -of the LuCI ui (usually /luci-static/resources).

-

The resulting URL is guaranteed to only contain the characters -a-z, A-Z, 0-9, _, ., %, ,, ;, and - as well -as / for the path separator.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
parts - - -Array.<string> - - - - - - - optional - - - - - -

An array of parts to join into an URL path. Parts may contain -slashes and any of the other characters mentioned above.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the resulting URL path.
- - - - -
- - - -
-
-

- - run(){boolean} -

- - - - -
- - -
-
- - -
-

Deprecated wrapper around Poll.start().

-
- - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the polling loop has been started or false -when it was already running.
- - - - -
- - - -
-
-

- - sortedKeys(obj, key, sortmode){Array.<string>} -

- - - - -
- - -
-
- - -
-

Return an array of sorted object keys, optionally sorted by -a different key or a different sorting mode.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
obj - - -object - - - - - - - - - - -

The object to extract the keys from. If the given value is -not an object, the function will return an empty array.

key - - -string - - - - - - - optional - - - - - -

Specifies the key to order by. This is mainly useful for -nested objects of objects or objects of arrays when sorting -shall not be performed by the primary object keys but by -some other key pointing to a value within the nested values.

sortmode - - -string - - - - - - - optional - - - - - -

May be either addr or num to override the natural -lexicographic sorting with a sorting suitable for IP/MAC style -addresses or numeric values respectively.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array containing the sorted keys of the given object.
- - - - -
- - - -
-
-

- - stop(entry){boolean} -

- - - - -
- - -
-
- - -
-

Deprecated wrapper around Poll.remove().

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
entry - - -function - - - - - -

The polling function to remove.

- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the function has been removed or false if -it could not be found.
- - - - -
- - - -
-
-

- - toArray(val){Array.<*>} -

- - - - -
- - -
-
- - -
-

Converts the given value to an array. If the given value is of -type array, it is returned as-is, values of type object are -returned as one-element array containing the object, empty -strings and null values are returned as empty array, all other -values are converted using String(), trimmed, split on white -space and returned as array.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
val - - -* - - - - - -

The value to convert into an array.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<*> - - - Returns the resulting array.
- - - - -
- - - -
-
-

- - url(parts){string} -

- - - - -
- - -
-
- - -
-

Construct an URL pathrelative to the script path of the server -side LuCI application (usually /cgi-bin/luci).

-

The resulting URL is guaranteed to only contain the characters -a-z, A-Z, 0-9, _, ., %, ,, ;, and - as well -as / for the path separator.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
parts - - -Array.<string> - - - - - - - optional - - - - - -

An array of parts to join into an URL path. Parts may contain -slashes and any of the other characters mentioned above.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the resulting URL path.
- - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

- - LuCI.requestCallbackFn(xhr, data, duration) -

- - - - -
- - -
-
- - -
-

The request callback function is invoked whenever an HTTP -reply to a request made using the L.get(), L.post() or -L.poll() function is timed out or received successfully.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
xhr - - -XMLHTTPRequest - - - - - -

The XMLHTTPRequest instance used to make the request.

data - - -* - - - - - -

The response JSON if the response could be parsed as such, -else null.

duration - - -number - - - - - -

The total duration of the request in milliseconds.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.network.Device.html b/docs/jsapi/LuCI.network.Device.html deleted file mode 100644 index d3b2cf9141..0000000000 --- a/docs/jsapi/LuCI.network.Device.html +++ /dev/null @@ -1,5804 +0,0 @@ - - - - - Class: Device - - - - - - - - - - - - - - - - - -
- - -
-

Class: Device

- - - - -
- -
-

- LuCI.network. - - Device -

- -

A Network.Device class instance represents an underlying Linux network -device and allows querying device details such as packet statistics or MTU.

- -
- -
-
- - - - -
-
-

- - new LuCI.network.Device() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - getBridgeID(){null|string} -

- - - - -
- - -
-
- - -
-

Get the bridge ID

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the ID of this network bridge or null if this network -device is not a Linux bridge.
- - - - -
- - - -
-
-

- - getBridgeSTP(){boolean} -

- - - - -
- - -
-
- - -
-

Get the bridge STP setting

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when this device is a Linux bridge and has stp -enabled, else false.
- - - - -
- - - -
-
-

- - getI18n(){string} -

- - - - -
- - -
-
- - -
-

Get a long description string for the device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns a string containing the type description and device name -for non-wifi devices or operation mode and ssid for wifi ones.
- - - - -
- - - -
-
-

- - getIP6Addrs(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Get the IPv6 addresses configured on the device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of IPv6 address strings.
- - - - -
- - - -
-
-

- - getIPAddrs(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Get the IPv4 addresses configured on the device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of IPv4 address strings.
- - - - -
- - - -
-
-

- - getMAC(){null|string} -

- - - - -
- - -
-
- - -
-

Get the MAC address of the device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the MAC address of the device or null if not applicable, -e.g. for non-ethernet tunnel devices.
- - - - -
- - - -
-
-

- - getMTU(){number} -

- - - - -
- - -
-
- - -
-

Get the MTU of the device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the MTU of the device.
- - - - -
- - - -
-
-

- - getName(){string} -

- - - - -
- - -
-
- - -
-

Get the name of the network device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the name of the device, e.g. eth0 or wlan0.
- - - - -
- - - -
-
-

- - getNetwork(){null|LuCI.network.Protocol} -

- - - - -
- - -
-
- - -
-

Get the primary logical interface this device is assigned to.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.network.Protocol - - - Returns a Network.Protocol instance representing the logical -interface this device is attached to or null if it is not -assigned to any logical interface.
- - - - -
- - - -
-
-

- - getNetworks(){Array.<LuCI.network.Protocol>} -

- - - - -
- - -
-
- - -
-

Get the logical interfaces this device is assigned to.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<LuCI.network.Protocol> - - - Returns an array of Network.Protocol instances representing the -logical interfaces this device is assigned to.
- - - - -
- - - -
-
-

- - getPorts(){null|Array.<LuCI.network.Device>} -

- - - - -
- - -
-
- - -
-

Get the associated bridge ports of the device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - Array.<LuCI.network.Device> - - - Returns an array of Network.Device instances representing the ports -(slave interfaces) of the bridge or null when this device isn't -a Linux bridge.
- - - - -
- - - -
-
-

- - getRXBytes(){number} -

- - - - -
- - -
-
- - -
-

Get the amount of received bytes.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the amount of bytes received by the network device.
- - - - -
- - - -
-
-

- - getRXPackets(){number} -

- - - - -
- - -
-
- - -
-

Get the amount of received packets.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the amount of packets received by the network device.
- - - - -
- - - -
-
-

- - getShortName(){string} -

- - - - -
- - -
-
- - -
-

Get a short description string for the device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the device name for non-wifi devices or a string containing -the operation mode and SSID for wifi devices.
- - - - -
- - - -
-
-

- - getTXBytes(){number} -

- - - - -
- - -
-
- - -
-

Get the amount of transmitted bytes.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the amount of bytes transmitted by the network device.
- - - - -
- - - -
-
-

- - getTXPackets(){number} -

- - - - -
- - -
-
- - -
-

Get the amount of transmitted packets.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the amount of packets transmitted by the network device.
- - - - -
- - - -
-
-

- - getType(){string} -

- - - - -
- - -
-
- - -
-

Get the type of the device..

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns a string describing the type of the network device: -
    -
  • alias if it is an abstract alias device (@ notation)
  • -
  • wifi if it is a wireless interface (e.g. wlan0)
  • -
  • bridge if it is a bridge device (e.g. br-lan)
  • -
  • tunnel if it is a tun or tap device (e.g. tun0)
  • -
  • vlan if it is a vlan device (e.g. eth0.1)
  • -
  • switch if it is a switch device (e.g.eth1 connected to switch0)
  • -
  • ethernet for all other device types
  • -
- - - - -
- - - -
-
-

- - getTypeI18n(){string} -

- - - - -
- - -
-
- - -
-

Get a string describing the device type.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns a string describing the type, e.g. "Wireless Adapter" or -"Bridge".
- - - - -
- - - -
-
-

- - getWifiNetwork(){null|LuCI.network.WifiNetwork} -

- - - - -
- - -
-
- - -
-

Get the related wireless network this device is related to.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.network.WifiNetwork - - - Returns a Network.WifiNetwork instance representing the wireless -network corresponding to this network device or null if this device -is not a wireless device.
- - - - -
- - - -
-
-

- - isBridge(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this device is a Linux bridge.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the network device is present and a Linux bridge, -else false.
- - - - -
- - - -
-
-

- - isBridgePort(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this device is part of a Linux bridge.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when this network device is part of a bridge, -else false.
- - - - -
- - - -
-
-

- - isUp(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this device is up.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the associated device is running pr false -when it is down or absent.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.network.Hosts.html b/docs/jsapi/LuCI.network.Hosts.html deleted file mode 100644 index d44e172c54..0000000000 --- a/docs/jsapi/LuCI.network.Hosts.html +++ /dev/null @@ -1,4785 +0,0 @@ - - - - - Class: Hosts - - - - - - - - - - - - - - - - - -
- - -
-

Class: Hosts

- - - - -
- -
-

- LuCI.network. - - Hosts -

- -

The LuCI.network.Hosts class encapsulates host information aggregated -from multiple sources and provides convenience functions to access the -host information by different criteria.

- -
- -
-
- - - - -
-
-

- - new LuCI.network.Hosts() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - getHostnameByIP6Addr(ipaddr){null|string} -

- - - - -
- - -
-
- - -
-

Lookup the hostname associated with the given IPv6 address.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ipaddr - - -string - - - - - -

The IPv6 address to lookup.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the hostname associated with the given IPv6 or null if -no matching host could be found or if no hostname is known for -the corresponding host.
- - - - -
- - - -
-
-

- - getHostnameByIPAddr(ipaddr){null|string} -

- - - - -
- - -
-
- - -
-

Lookup the hostname associated with the given IPv4 address.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ipaddr - - -string - - - - - -

The IPv4 address to lookup.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the hostname associated with the given IPv4 or null if -no matching host could be found or if no hostname is known for -the corresponding host.
- - - - -
- - - -
-
-

- - getHostnameByMACAddr(mac){null|string} -

- - - - -
- - -
-
- - -
-

Lookup the hostname associated with the given MAC address.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
mac - - -string - - - - - -

The MAC address to lookup.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the hostname associated with the given MAC or null if -no matching host could be found or if no hostname is known for -the corresponding host.
- - - - -
- - - -
-
-

- - getIP6AddrByMACAddr(mac){null|string} -

- - - - -
- - -
-
- - -
-

Lookup the IPv6 address associated with the given MAC address.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
mac - - -string - - - - - -

The MAC address to lookup.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the IPv6 address associated with the given MAC or null if -no matching host could be found or if no IPv6 address is known for -the corresponding host.
- - - - -
- - - -
-
-

- - getIPAddrByMACAddr(mac){null|string} -

- - - - -
- - -
-
- - -
-

Lookup the IPv4 address associated with the given MAC address.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
mac - - -string - - - - - -

The MAC address to lookup.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the IPv4 address associated with the given MAC or null if -no matching host could be found or if no IPv4 address is known for -the corresponding host.
- - - - -
- - - -
-
-

- - getMACAddrByIP6Addr(ipaddr){null|string} -

- - - - -
- - -
-
- - -
-

Lookup the MAC address associated with the given IPv6 address.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ipaddr - - -string - - - - - -

The IPv6 address to lookup.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the MAC address associated with the given IPv6 or null if -no matching host could be found or if no MAC address is known for -the corresponding host.
- - - - -
- - - -
-
-

- - getMACAddrByIPAddr(ipaddr){null|string} -

- - - - -
- - -
-
- - -
-

Lookup the MAC address associated with the given IPv4 address.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ipaddr - - -string - - - - - -

The IPv4 address to lookup.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the MAC address associated with the given IPv4 or null if -no matching host could be found or if no MAC address is known for -the corresponding host.
- - - - -
- - - -
-
-

- - getMACHints(preferIp6){Array.<Array.<string>>} -

- - - - -
- - -
-
- - -
-

Return an array of (MAC address, name hint) tuples sorted by -MAC address.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
preferIp6 - - -boolean - - - - - - false - - - - - optional - - - - - -

Whether to prefer IPv6 addresses (true) or IPv4 addresses (false) -as name hint when no hostname is known for a specific MAC address.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<Array.<string>> - - - Returns an array of arrays containing a name hint for each found -MAC address on the system. The array is sorted ascending by MAC. -Each item of the resulting array is a two element array with the -MAC being the first element and the name hint being the second -element. The name hint is either the hostname, an IPv4 or an IPv6 -address related to the MAC address. -If no hostname but both IPv4 and IPv6 addresses are known, the -preferIP6 flag specifies whether the IPv6 or the IPv4 address -is used as hint.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.network.Protocol.html b/docs/jsapi/LuCI.network.Protocol.html deleted file mode 100644 index 465b751a68..0000000000 --- a/docs/jsapi/LuCI.network.Protocol.html +++ /dev/null @@ -1,8015 +0,0 @@ - - - - - Class: Protocol - - - - - - - - - - - - - - - - - -
- - -
-

Class: Protocol

- - - - -
- -
-

- LuCI.network. - - Protocol -

- -

The Network.Protocol class serves as base for protocol specific -subclasses which describe logical UCI networks defined by config interface sections in /etc/config/network.

- -
- -
-
- - - - -
-
-

- - new LuCI.network.Protocol() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - addDevice(device){boolean} -

- - - - -
- - -
-
- - -
-

Add the given network device to the logical interface.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
device - - -LuCI.network.Protocol -| - -LuCI.network.Device -| - -LuCI.network.WifiDevice -| - -LuCI.network.WifiNetwork -| - -string - - - - - -

The object or device name to add to the logical interface. In case the -given argument is not a string, it is resolved though the -Network.getIfnameOf() function.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the device name has been added or false if any -argument was invalid, if the device was already part of the logical -interface or if the logical interface is virtual.
- - - - -
- - - -
-
-

- - containsDevice(device){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this logical interface contains the given device -object.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
device - - -LuCI.network.Protocol -| - -LuCI.network.Device -| - -LuCI.network.WifiDevice -| - -LuCI.network.WifiNetwork -| - -string - - - - - -

The object or device name to check. In case the given argument is not -a string, it is resolved though the -Network.getIfnameOf() function.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when this logical interface contains the given network -device or false if not.
- - - - -
- - - -
-
-

- - abstractdeleteConfiguration(){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

Cleanup related configuration entries.

-

This function will be invoked if an interface is about to be removed -from the configuration and is responsible for performing any required -cleanup tasks, such as unsetting uci entries in related configurations.

-

It should be overwritten by protocol specific subclasses.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - This function may return a promise which is awaited before the rest of -the configuration is removed. Any non-promise return value and any -resolved promise value is ignored. If the returned promise is rejected, -the interface removal will be aborted.
- - - - -
- - - -
-
-

- - deleteDevice(device){boolean} -

- - - - -
- - -
-
- - -
-

Remove the given network device from the logical interface.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
device - - -LuCI.network.Protocol -| - -LuCI.network.Device -| - -LuCI.network.WifiDevice -| - -LuCI.network.WifiNetwork -| - -string - - - - - -

The object or device name to remove from the logical interface. In case -the given argument is not a string, it is resolved though the -Network.getIfnameOf() function.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the device name has been added or false if any -argument was invalid, if the device was already part of the logical -interface or if the logical interface is virtual.
- - - - -
- - - -
-
-

- - get(opt){null|string|Array.<string>} -

- - - - -
- - -
-
- - -
-

Read the given UCI option value of this network.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
opt - - -string - - - - - -

The UCI option name to read.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - - - Returns the UCI option value or null if the requested option is -not found.
- - - - -
- - - -
-
-

- - getDevice(){LuCI.network.Device} -

- - - - -
- - -
-
- - -
-

Returns the Linux network device associated with this logical -interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.network.Device - - - Returns a Network.Device class instance representing the -expected Linux network device according to the configuration.
- - - - -
- - - -
-
-

- - getDevices(){null|Array.<LuCI.network.Device>} -

- - - - -
- - -
-
- - -
-

Returns a list of network sub-devices associated with this logical -interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - Array.<LuCI.network.Device> - - - Returns an array of of Network.Device class instances representing -the sub-devices attached to this logical interface or null if the -logical interface does not support sub-devices, e.g. because it is -virtual and not a bridge.
- - - - -
- - - -
-
-

- - getDNS6Addrs(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Query the IPv6 DNS servers associated with the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of IPv6 DNS servers registered by the remote -protocol backend.
- - - - -
- - - -
-
-

- - getDNSAddrs(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Query the IPv4 DNS servers associated with the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of IPv4 DNS servers registered by the remote -protocol backend.
- - - - -
- - - -
-
-

- - getErrors(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Query interface error messages published in ubus runtime state.

-

Interface errors are emitted by remote protocol handlers if the setup -of the underlying logical interface failed, e.g. due to bad -configuration or network connectivity issues.

-

This function will translate the found error codes to human readable -messages using the descriptions registered by -Network.registerErrorCode() -and fall back to "Unknown error (%s)" where %s is replaced by the -error code in case no translation can be found.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of translated interface error messages.
- - - - -
- - - -
-
-

- - getExpiry(){number} -

- - - - -
- - -
-
- - -
-

Get the logical interface expiry time in seconds.

-

For protocols that have a concept of a lease, such as DHCP or -DHCPv6, this function returns the remaining time in seconds -until the lease expires.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the amount of seconds until the lease expires or -1 -if it isn't applicable to the associated protocol.
- - - - -
- - - -
-
-

- - getGateway6Addr(){string} -

- - - - -
- - -
-
- - -
-

Query the gateway (nexthop) of the IPv6 default route associated with -this logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns a string containing the IPv6 nexthop address of the associated -default route or null if no default route was found.
- - - - -
- - - -
-
-

- - getGatewayAddr(){string} -

- - - - -
- - -
-
- - -
-

Query the gateway (nexthop) of the default route associated with -this logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns a string containing the IPv4 nexthop address of the associated -default route or null if no default route was found.
- - - - -
- - - -
-
-

- - abstractgetI18n(){string} -

- - - - -
- - -
-
- - -
-

Return a human readable description for the protcol, such as -Static address or DHCP client.

-

This function should be overwritten by subclasses.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the description string.
- - - - -
- - - -
-
-

- - getIfname(){null|string} -

- - - - -
- - -
-
- - -
-

Get the associared Linux network device of this network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the name of the associated network device or null if -it could not be determined.
- - - - -
- - - -
-
-

- - getIP6Addr(){null|string} -

- - - - -
- - -
-
- - -
-

Query the first (primary) IPv6 address of the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the primary IPv6 address registered by the protocol handler -in CIDR notation or null if no IPv6 addresses were set.
- - - - -
- - - -
-
-

- - getIP6Addrs(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Query all IPv6 addresses of the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of IPv6 addresses in CIDR notation which have been -registered by the protocol handler. The order of the resulting array -follows the order of the addresses in ubus runtime information.
- - - - -
- - - -
-
-

- - getIP6Prefix(){null|string} -

- - - - -
- - -
-
- - -
-

Query the routed IPv6 prefix associated with the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the routed IPv6 prefix registered by the remote protocol -handler or null if no prefix is present.
- - - - -
- - - -
-
-

- - getIPAddr(){null|string} -

- - - - -
- - -
-
- - -
-

Query the first (primary) IPv4 address of the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the primary IPv4 address registered by the protocol handler -or null if no IPv4 addresses were set.
- - - - -
- - - -
-
-

- - getIPAddrs(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Query all IPv4 addresses of the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of IPv4 addresses in CIDR notation which have been -registered by the protocol handler. The order of the resulting array -follows the order of the addresses in ubus runtime information.
- - - - -
- - - -
-
-

- - getL2Device(){LuCI.network.Device} -

- - - - -
- - -
-
- - -
-

Returns the layer 2 linux network device currently associated -with this logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.network.Device - - - Returns a Network.Device class instance representing the Linux -network device currently associated with the logical interface.
- - - - -
- - - -
-
-

- - getL3Device(){LuCI.network.Device} -

- - - - -
- - -
-
- - -
-

Returns the layer 3 linux network device currently associated -with this logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.network.Device - - - Returns a Network.Device class instance representing the Linux -network device currently associated with the logical interface.
- - - - -
- - - -
-
-

- - getMetric(){number} -

- - - - -
- - -
-
- - -
-

Get the metric value of the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the current metric value used for device and network -routes spawned by the associated logical interface.
- - - - -
- - - -
-
-

- - getName(){string} -

- - - - -
- - -
-
- - -
-

Get the name of the associated logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the logical interface name, such as lan or wan.
- - - - -
- - - -
-
-

- - getNetmask(){null|string} -

- - - - -
- - -
-
- - -
-

Query the first (primary) IPv4 netmask of the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the netmask of the primary IPv4 address registered by the -protocol handler or null if no IPv4 addresses were set.
- - - - -
- - - -
-
-

- - abstractgetOpkgPackage(){string} -

- - - - -
- - -
-
- - -
-

Get the name of the opkg package providing the protocol functionality.

-

This function should be overwritten by protocol specific subclasses.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the name of the opkg package required for the protocol to -function, e.g. odhcp6c for the dhcpv6 prototocol.
- - - - -
- - - -
-
-

- - abstractgetProtocol(){string} -

- - - - -
- - -
-
- - -
-

Get the name of this network protocol class.

-

This function will be overwritten by subclasses created by -Network.registerProtocol().

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the name of the network protocol implementation, e.g. -static or dhcp.
- - - - -
- - - -
-
-

- - getType(){null|string} -

- - - - -
- - -
-
- - -
-

Get the type of the underlying interface.

-

This function actually is a convenience wrapper around -proto.get("type") and is mainly used by other LuCI.network code -to check whether the interface is declared as bridge in UCI.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the value of the type option of the associated logical -interface or null if no type option is set.
- - - - -
- - - -
-
-

- - getUptime(){number} -

- - - - -
- - -
-
- - -
-

Get the uptime of the logical interface.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the uptime of the associated interface in seconds.
- - - - -
- - - -
-
-

- - getZoneName(){null|string} -

- - - - -
- - -
-
- - -
-

Get the requested firewall zone name of the logical interface.

-

Some protocol implementations request a specific firewall zone -to trigger inclusion of their resulting network devices into the -firewall rule set.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the requested firewall zone name as published in the -ubus runtime information or null if the remote protocol -handler didn't request a zone.
- - - - -
- - - -
-
-

- - isAlias(){null|string} -

- - - - -
- - -
-
- - -
-

Checks whether this interface is an alias interface.

-

Alias interfaces are interfaces layering on top of another interface -and are denoted by a special @interfacename notation in the -underlying ifname option.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the name of the parent interface if this logical interface -is an alias or null if it is not an alias interface.
- - - - -
- - - -
-
-

- - isBridge(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether the underlying logical interface is declared as bridge.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the interface is declared with option type bridge -and when the associated protocol implementation is not marked virtual -or false when the logical interface is no bridge.
- - - - -
- - - -
-
-

- - abstractisCreateable(ifname){Promise.<void>} -

- - - - -
- - -
-
- - -
-

Check function for the protocol handler if a new interface is createable.

-

This function should be overwritten by protocol specific subclasses.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ifname - - -string - - - - - -

The name of the interface to be created.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<void> - - - Returns a promise resolving if new interface is createable, else -rejects with an error message string.
- - - - -
- - - -
-
-

- - isDynamic(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this logical interface is dynamic.

-

A dynamic interface is an interface which has been created at runtime, -e.g. as sub-interface of another interface, but which is not backed by -any user configuration. Such dynamic interfaces cannot be edited but -only brought down or restarted.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns a boolean indicating whether this interface is dynamic (true) -or not (false).
- - - - -
- - - -
-
-

- - isEmpty(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this logical interface is "empty", meaning that ut -has no network devices attached.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if this logical interface is empty, else false.
- - - - -
- - - -
-
-

- - isFloating(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this protocol is "floating".

-

A "floating" protocol is a protocol which spawns its own interfaces -on demand, like a virtual one but which relies on an existinf lower -level interface to initiate the connection.

-

An example for such a protocol is "pppoe".

-

This function exists for backwards compatibility with older code -but should not be used anymore.

-
- - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns a boolean indicating whether this protocol is floating (true) -or not (false).
- - - - -
- - - -
-
-

- - abstractisInstalled(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether the protocol functionality is installed.

-

This function exists for compatibility with old code, it always -returns true.

-
- - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the protocol support is installed, else false.
- - - - -
- - - -
-
-

- - isUp(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this logical interface is configured and running.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the interface is active or false when it is not.
- - - - -
- - - -
-
-

- - isVirtual(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this protocol is "virtual".

-

A "virtual" protocol is a protocol which spawns its own interfaces -on demand instead of using existing physical interfaces.

-

Examples for virtual protocols are 6in4 which gre spawn tunnel -network device on startup, examples for non-virtual protcols are -dhcp or static which apply IP configuration to existing interfaces.

-

This function should be overwritten by subclasses.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns a boolean indicating whether the underlying protocol spawns -dynamic interfaces (true) or not (false).
- - - - -
- - - -
-
-

- - set(opt, val) -

- - - - -
- - -
-
- - -
-

Set the given UCI option of this network to the given value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
opt - - -string - - - - - -

The name of the UCI option to set.

val - - -null -| - -string -| - -Array.<string> - - - - - -

The value to set or null to remove the given option from the -configuration.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.network.WifiDevice.html b/docs/jsapi/LuCI.network.WifiDevice.html deleted file mode 100644 index fc20c640a2..0000000000 --- a/docs/jsapi/LuCI.network.WifiDevice.html +++ /dev/null @@ -1,5151 +0,0 @@ - - - - - Class: WifiDevice - - - - - - - - - - - - - - - - - -
- - -
-

Class: WifiDevice

- - - - -
- -
-

- LuCI.network. - - WifiDevice -

- -

A Network.WifiDevice class instance represents a wireless radio device -present on the system and provides wireless capability information as -well as methods for enumerating related wireless networks.

- -
- -
-
- - - - -
-
-

- - new LuCI.network.WifiDevice() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - addWifiNetwork(options){Promise.<(null|LuCI.network.WifiNetwork)>} -

- - - - -
- - -
-
- - -
-

Adds a new wireless network associated with this radio device to the -configuration and sets its options to the provided values.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object.<string, (string|Array.<string>)> - - - - - - - optional - - - - - -

The options to set for the newly added wireless network.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<(null|LuCI.network.WifiNetwork)> - - - Returns a promise resolving to a WifiNetwork instance describing -the newly added wireless network or null if the given options -were invalid.
- - - - -
- - - -
-
-

- - deleteWifiNetwork(network){Promise.<boolean>} -

- - - - -
- - -
-
- - -
-

Deletes the wireless network with the given name associated with this -radio device.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
network - - -string - - - - - -

The name of the wireless network to lookup. This may be either an uci -configuration section ID, a network ID in the form radio#.network# -or a Linux network device name like wlan0 which is resolved to the -corresponding configuration section through ubus runtime information.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<boolean> - - - Returns a promise resolving to true when the wireless network was -successfully deleted from the configuration or false when the given -network could not be found or if the found network was not associated -with this wireless radio device.
- - - - -
- - - -
-
-

- - get(opt){null|string|Array.<string>} -

- - - - -
- - -
-
- - -
-

Read the given UCI option value of this wireless device.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
opt - - -string - - - - - -

The UCI option name to read.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - - - Returns the UCI option value or null if the requested option is -not found.
- - - - -
- - - -
-
-

- - getHTModes(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Gets a list of supported htmodes.

-

The htmode values describe the wide-frequency options supported by -the wireless phy.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of valid htmode values for this radio. Currently -known mode values are: -
    -
  • HT20 - applicable to IEEE 802.11n, 20 MHz wide channels
  • -
  • HT40 - applicable to IEEE 802.11n, 40 MHz wide channels
  • -
  • VHT20 - applicable to IEEE 802.11ac, 20 MHz wide channels
  • -
  • VHT40 - applicable to IEEE 802.11ac, 40 MHz wide channels
  • -
  • VHT80 - applicable to IEEE 802.11ac, 80 MHz wide channels
  • -
  • VHT160 - applicable to IEEE 802.11ac, 160 MHz wide channels
  • -
- - - - -
- - - -
-
-

- - getHWModes(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Gets a list of supported hwmodes.

-

The hwmode values describe the frequency band and wireless standard -versions supported by the wireless phy.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of valid hwmode values for this radio. Currently -known mode values are: -
    -
  • a - Legacy 802.11a mode, 5 GHz, up to 54 Mbit/s
  • -
  • b - Legacy 802.11b mode, 2.4 GHz, up to 11 Mbit/s
  • -
  • g - Legacy 802.11g mode, 2.4 GHz, up to 54 Mbit/s
  • -
  • n - IEEE 802.11n mode, 2.4 or 5 GHz, up to 600 Mbit/s
  • -
  • ac - IEEE 802.11ac mode, 5 GHz, up to 6770 Mbit/s
  • -
- - - - -
- - - -
-
-

- - getI18n(){string} -

- - - - -
- - -
-
- - -
-

Get a string describing the wireless radio hardware.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the description string.
- - - - -
- - - -
-
-

- - getName(){string} -

- - - - -
- - -
-
- - -
-

Get the configuration name of this wireless radio.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the UCI section name (e.g. radio0) of the corresponding -radio configuration which also serves as unique logical identifier -for the wireless phy.
- - - - -
- - - -
-
-

- - getScanList(){Promise.<Array.<LuCI.network.WifiScanResult>>} -

- - - - -
- - -
-
- - -
-

Trigger a wireless scan on this radio device and obtain a list of -nearby networks.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.network.WifiScanResult>> - - - Returns a promise resolving to an array of scan result objects -describing the networks found in the vincinity.
- - - - -
- - - -
-
-

- - getWifiNetwork(network){Promise.<LuCI.network.WifiNetwork>} -

- - - - -
- - -
-
- - -
-

Get the wifi network of the given name belonging to this radio device

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
network - - -string - - - - - -

The name of the wireless network to lookup. This may be either an uci -configuration section ID, a network ID in the form radio#.network# -or a Linux network device name like wlan0 which is resolved to the -corresponding configuration section through ubus runtime information.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.network.WifiNetwork> - - - Returns a promise resolving to a Network.WifiNetwork instance -representing the wireless network and rejecting with null if -the given network could not be found or is not associated with -this radio device.
- - - - -
- - - -
-
-

- - getWifiNetworks(){Promise.<Array.<LuCI.network.WifiNetwork>>} -

- - - - -
- - -
-
- - -
-

Get all wireless networks associated with this wireless radio device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.network.WifiNetwork>> - - - Returns a promise resolving to an array of Network.WifiNetwork -instances respresenting the wireless networks associated with this -radio device.
- - - - -
- - - -
-
-

- - isDisabled(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this wireless radio is disabled.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the wireless radio is marked as disabled in ubus -runtime state or when the disabled option is set in the corresponding -UCI configuration.
- - - - -
- - - -
-
-

- - isUp(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the wireless radio is marked as up in the ubus -runtime state.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the radio device is up, else false.
- - - - -
- - - -
-
-

- - set(opt, val) -

- - - - -
- - -
-
- - -
-

Set the given UCI option of this network to the given value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
opt - - -string - - - - - -

The name of the UCI option to set.

val - - -null -| - -string -| - -Array.<string> - - - - - -

The value to set or null to remove the given option from the -configuration.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.network.WifiNetwork.html b/docs/jsapi/LuCI.network.WifiNetwork.html deleted file mode 100644 index f9e91e4a86..0000000000 --- a/docs/jsapi/LuCI.network.WifiNetwork.html +++ /dev/null @@ -1,7644 +0,0 @@ - - - - - Class: WifiNetwork - - - - - - - - - - - - - - - - - -
- - -
-

Class: WifiNetwork

- - - - -
- -
-

- LuCI.network. - - WifiNetwork -

- -

A Network.WifiNetwork instance represents a wireless network (vif) -configured on top of a radio device and provides functions for querying -the runtime state of the network. Most radio devices support multiple -such networks in parallel.

- -
- -
-
- - - - -
-
-

- - new LuCI.network.WifiNetwork() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - disconnectClient(mac, deauth, reason, ban_time){Promise.<number>} -

- - - - -
- - -
-
- - -
-

Forcibly disconnect the given client from the wireless network.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
mac - - -string - - - - - - - - - - - - -

The MAC address of the client to disconnect.

deauth - - -boolean - - - - - - false - - - - - optional - - - - - -

Specifies whether to deauthenticate (true) or disassociate (false) -the client.

reason - - -number - - - - - - 1 - - - - - optional - - - - - -

Specifies the IEEE 802.11 reason code to disassoc/deauth the client -with. Default is 1 which corresponds to Unspecified reason.

ban_time - - -number - - - - - - 0 - - - - - optional - - - - - -

Specifies the amount of milliseconds to ban the client from -reconnecting. By default, no ban time is set which allows the client -to reassociate / reauthenticate immediately.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<number> - - - Returns a promise resolving to the underlying ubus call result code -which is typically 0, even for not existing MAC addresses. -The promise might reject with an error in case invalid arguments -are passed.
- - - - -
- - - -
-
-

- - get(opt){null|string|Array.<string>} -

- - - - -
- - -
-
- - -
-

Read the given UCI option value of this wireless network.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
opt - - -string - - - - - -

The UCI option name to read.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - - - Returns the UCI option value or null if the requested option is -not found.
- - - - -
- - - -
-
-

- - getActiveBSSID(){string} -

- - - - -
- - -
-
- - -
-

Query the current BSSID from runtime information.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the current BSSID or Mesh ID as reported by ubus runtime -information.
- - - - -
- - - -
-
-

- - getActiveEncryption(){string} -

- - - - -
- - -
-
- - -
-

Query the current encryption settings from runtime information.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns a string describing the current encryption or - if the the -encryption state could not be found in ubus runtime information.
- - - - -
- - - -
-
-

- - getActiveMode(){string} -

- - - - -
- - -
-
- - -
-

Query the current operation mode from runtime information.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the human readable mode name as reported by ubus runtime -state. Possible returned values are: -
    -
  • Master
  • -
  • Ad-Hoc
  • -
  • Client
  • -
  • Monitor
  • -
  • Master (VLAN)
  • -
  • WDS
  • -
  • Mesh Point
  • -
  • P2P Client
  • -
  • P2P Go
  • -
  • Unknown
  • -
- - - - -
- - - -
-
-

- - getActiveModeI18n(){string} -

- - - - -
- - -
-
- - -
-

Query the current operation mode from runtime information as -translated string.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the translated, human readable mode name as reported by -ubus runtime state.
- - - - -
- - - -
-
-

- - getActiveSSID(){string} -

- - - - -
- - -
-
- - -
-

Query the current SSID from runtime information.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the current SSID or Mesh ID as reported by ubus runtime -information.
- - - - -
- - - -
-
-

- - getAssocList(){Promise.<Array.<LuCI.network.WifiPeerEntry>>} -

- - - - -
- - -
-
- - -
-

Fetch the list of associated peers.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.network.WifiPeerEntry>> - - - Returns a promise resolving to an array of wireless peers associated -with this network.
- - - - -
- - - -
-
-

- - getBitRate(){null|number} -

- - - - -
- - -
-
- - -
-

Query the current average bitrate of all peers associated to this -wireless network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - number - - - Returns the average bit rate among all peers associated to the network -as reported by ubus runtime information or null if the information -is not available.
- - - - -
- - - -
-
-

- - getBSSID(){null|string} -

- - - - -
- - -
-
- - -
-

Get the configured BSSID of the wireless network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the BSSID value or null if none has been specified.
- - - - -
- - - -
-
-

- - getChannel(){null|number} -

- - - - -
- - -
-
- - -
-

Query the current wireless channel.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - number - - - Returns the wireless channel as reported by ubus runtime information -or null if it cannot be determined.
- - - - -
- - - -
-
-

- - getCountryCode(){string} -

- - - - -
- - -
-
- - -
-

Query the current country code.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the wireless country code as reported by ubus runtime -information or 00 if it cannot be determined.
- - - - -
- - - -
-
-

- - getDevice(){LuCI.network.Device} -

- - - - -
- - -
-
- - -
-

Get the associated Linux network device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.network.Device - - - Returns a Network.Device instance representing the Linux network -device associted with this wireless network.
- - - - -
- - - -
-
-

- - getFrequency(){null|string} -

- - - - -
- - -
-
- - -
-

Query the current operating frequency of the wireless network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the current operating frequency of the network from ubus -runtime information in GHz or null if the information is not -available.
- - - - -
- - - -
-
-

- - getI18n(){string} -

- - - - -
- - -
-
- - -
-

Get a description string for this wireless network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns a string describing this network, consisting of the -term Wireless Network, followed by the active operation mode, -the SSID, BSSID or internal network ID and the Linux network device -name, depending on which information is available.
- - - - -
- - - -
-
-

- - getID(){string} -

- - - - -
- - -
-
- - -
-

Get the internal network ID of this wireless network.

-

The network ID is a LuCI specific identifer in the form -radio#.network# to identify wireless networks by their corresponding -radio and network index numbers.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the LuCI specific network ID.
- - - - -
- - - -
-
-

- - getIfname(){null|string} -

- - - - -
- - -
-
- - -
-

Get the Linux network device name.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the current Linux network device name as resolved from -ubus runtime information or null if this network has no -associated network device, e.g. when not configured or up.
- - - - -
- - - -
-
-

- - getMeshID(){null|string} -

- - - - -
- - -
-
- - -
-

Get the configured Mesh ID of the wireless network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the configured mesh ID value or null when this network -is not in mesh mode.
- - - - -
- - - -
-
-

- - getMode(){string} -

- - - - -
- - -
-
- - -
-

Get the configured operation mode of the wireless network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the configured operation mode. Possible values are: -
    -
  • ap - Master (Access Point) mode
  • -
  • sta - Station (client) mode
  • -
  • adhoc - Ad-Hoc (IBSS) mode
  • -
  • mesh - Mesh (IEEE 802.11s) mode
  • -
  • monitor - Monitor mode
  • -
- - - - -
- - - -
-
-

- - getName(){string} -

- - - - -
- - -
-
- - -
-

Get the configuration ID of this wireless network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the corresponding UCI section ID of the network.
- - - - -
- - - -
-
-

- - getNetwork(){null|LuCI.network.Protocol} -

- - - - -
- - -
-
- - -
-

Get the primary logical interface this wireless network is attached to.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.network.Protocol - - - Returns a Network.Protocol instance representing the logical -interface or null if this network is not attached to any logical -interface.
- - - - -
- - - -
-
-

- - getNetworkNames(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Get the names of the logical interfaces this wireless network is -attached to.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns an array of logical interface names.
- - - - -
- - - -
-
-

- - getNetworks(){Array.<LuCI.network.Protocol>} -

- - - - -
- - -
-
- - -
-

Get the logical interfaces this wireless network is attached to.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<LuCI.network.Protocol> - - - Returns an array of Network.Protocol instances representing the -logical interfaces this wireless network is attached to.
- - - - -
- - - -
-
-

- - getNoise(){number} -

- - - - -
- - -
-
- - -
-

Query the current radio noise floor.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the radio noise floor in dBm as reported by ubus runtime -information or 0 if it cannot be determined.
- - - - -
- - - -
-
-

- - getShortName(){string} -

- - - - -
- - -
-
- - -
-

Get a short description string for this wireless network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns a string describing this network, consisting of the -active operation mode, followed by either the SSID, BSSID or -internal network ID, depending on which information is available.
- - - - -
- - - -
-
-

- - getSignal(){null|number} -

- - - - -
- - -
-
- - -
-

Query the current wireless signal.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - number - - - Returns the wireless signal in dBm as reported by ubus runtime -information or null if it cannot be determined.
- - - - -
- - - -
-
-

- - getSignalLevel(){number} -

- - - - -
- - -
-
- - -
-

Calculate the current signal.

-
- - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the calculated signal level, which is the difference between -noise and signal (SNR), divided by 5.
- - - - -
- - - -
-
-

- - getSignalPercent(){number} -

- - - - -
- - -
-
- - -
-

Calculate the current signal quality percentage.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the calculated signal quality in percent. The value is -calculated from the quality and quality_max indicators reported -by ubus runtime state.
- - - - -
- - - -
-
-

- - getSSID(){null|string} -

- - - - -
- - -
-
- - -
-

Get the configured SSID of the wireless network.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the configured SSID value or null when this network is -in mesh mode.
- - - - -
- - - -
-
-

- - getTXPower(){null|number} -

- - - - -
- - -
-
- - -
-

Query the current radio TX power.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - number - - - Returns the wireless network transmit power in dBm as reported by -ubus runtime information or null if it cannot be determined.
- - - - -
- - - -
-
-

- - getTXPowerOffset(){number} -

- - - - -
- - -
-
- - -
-

Query the radio TX power offset.

-

Some wireless radios have a fixed power offset, e.g. due to the -use of external amplifiers.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - number - - - Returns the wireless network transmit power offset in dBm as reported -by ubus runtime information or 0 if there is no offset, or if it -cannot be determined.
- - - - -
- - - -
-
-

- - getWifiDevice(){null|LuCI.network.WifiDevice} -

- - - - -
- - -
-
- - -
-

Get the corresponding wifi radio device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.network.WifiDevice - - - Returns a Network.WifiDevice instance representing the corresponding -wifi radio device or null if the related radio device could not be -found.
- - - - -
- - - -
-
-

- - getWifiDeviceName(){null|string} -

- - - - -
- - -
-
- - -
-

Get the name of the corresponding wifi radio device.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the name of the radio device this network is configured on -or null if it cannot be determined.
- - - - -
- - - -
-
-

- - isClientDisconnectSupported(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether this wifi network supports deauthenticating clients.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when this wifi network instance supports forcibly -deauthenticating clients, otherwise false.
- - - - -
- - - -
-
-

- - isDisabled(){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether this wireless network is disabled.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the wireless radio is marked as disabled in ubus -runtime state or when the disabled option is set in the corresponding -UCI configuration.
- - - - -
- - - -
-
-

- - isUp(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the radio network is up.

-

This function actually queries the up state of the related radio -device and assumes this network to be up as well when the parent -radio is up. This is due to the fact that OpenWrt does not control -virtual interfaces individually but within one common hostapd -instance.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the network is up, else false.
- - - - -
- - - -
-
-

- - set(opt, val) -

- - - - -
- - -
-
- - -
-

Set the given UCI option of this network to the given value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
opt - - -string - - - - - -

The name of the UCI option to set.

val - - -null -| - -string -| - -Array.<string> - - - - - -

The value to set or null to remove the given option from the -configuration.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.network.html b/docs/jsapi/LuCI.network.html deleted file mode 100644 index 8760ded037..0000000000 --- a/docs/jsapi/LuCI.network.html +++ /dev/null @@ -1,9499 +0,0 @@ - - - - - Class: network - - - - - - - - - - - - - - - - - -
- - -
-

Class: network

- - - - -
- -
-

- LuCI. - - network -

- -

The LuCI.network class combines data from multiple ubus apis to -provide an abstraction of the current network configuration state.

-

It provides methods to enumerate interfaces and devices, to query -current configuration details and to manipulate settings.

- -
- -
-
- - - - -
-
-

- - new LuCI.network() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - -

Classes

- -
-
Device
-
- -
Hosts
-
- -
Protocol
-
- -
WifiDevice
-
- -
WifiNetwork
-
-
- - - - - - - -

Methods

- -
- -
-
-

- - addNetwork(name, options){Promise.<(null|LuCI.network.Protocol)>} -

- - - - -
- - -
-
- - -
-

Adds a new network of the given name and update it with the given -uci option values.

-

If a network with the given name already exist but is empty, then -this function will update its option, otherwise it will do nothing.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - - - - - - -

The name of the network to add. Must be in the format [a-zA-Z0-9_]+.

options - - -Object.<string, (string|Array.<string>)> - - - - - - - optional - - - - - -

An object of uci option values to set on the new network or to -update in an existing, empty network.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<(null|LuCI.network.Protocol)> - - - Returns a promise resolving to the Protocol subclass instance -describing the added network or resolving to null if the name -was invalid or if a non-empty network of the given name already -existed.
- - - - -
- - - -
-
-

- - addWifiNetwork(options){Promise.<(null|LuCI.network.WifiNetwork)>} -

- - - - -
- - -
-
- - -
-

Adds a new wireless network to the configuration and sets its options -to the provided values.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -Object.<string, (string|Array.<string>)> - - - - - -

The options to set for the newly added wireless network. This object -must at least contain a device property which is set to the radio -name the new network belongs to.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<(null|LuCI.network.WifiNetwork)> - - - Returns a promise resolving to a WifiNetwork instance describing -the newly added wireless network or null if the given options -were invalid or if the associated radio device could not be found.
- - - - -
- - - -
-
-

- - deleteNetwork(name){Promise.<boolean>} -

- - - - -
- - -
-
- - -
-

Deletes the given network and its references from the network and -firewall configuration.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - -

The name of the network to delete.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<boolean> - - - Returns a promise resolving to either true if the network and -references to it were successfully deleted from the configuration or -false if the given network could not be found.
- - - - -
- - - -
-
-

- - deleteWifiNetwork(netname){Promise.<boolean>} -

- - - - -
- - -
-
- - -
-

Deletes the given wireless network from the configuration.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
netname - - -string - - - - - -

The name of the network to remove. This may be either a -network ID in the form radio#.network# or a Linux network device -name like wlan0 which is resolved to the corresponding configuration -section through ubus runtime information.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<boolean> - - - Returns a promise resolving to true if the wireless network has been -successfully deleted from the configuration or false if it could not -be found.
- - - - -
- - - -
-
-

- - flushCache(){Promise.<Object>} -

- - - - -
- - -
-
- - -
-

Flushes the local network state cache and fetches updated information -from the remote ubus apis.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Object> - - - Returns a promise resolving to the internal network state object.
- - - - -
- - - -
-
-

- - formatWifiEncryption(encryption){null|string} -

- - - - -
- - -
-
- - -
-

Converts a given encryption entry -into a human readable string such as mixed WPA/WPA2 PSK (TKIP, CCMP) -or WPA3 SAE (CCMP).

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
encryption - - -LuCI.network.WifiEncryption - - - - - -

The wireless encryption entry to convert.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns the description string for the given encryption entry or -null if the given entry was invalid.
- - - - -
- - - -
-
-

- - getDevice(name){Promise.<(null|LuCI.network.Device)>} -

- - - - -
- - -
-
- - -
-

Get a Device instance describing the -given network device.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - -

The name of the network device to get, e.g. eth0 or br-lan.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<(null|LuCI.network.Device)> - - - Returns a promise resolving to the Device instance describing -the network device or null if the given device name could not -be found.
- - - - -
- - - -
-
-

- - getDevices(){Promise.<Array.<LuCI.network.Device>>} -

- - - - -
- - -
-
- - -
-

Get a sorted list of all found network devices.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.network.Device>> - - - Returns a promise resolving to a sorted array of Device class -instances describing the network devices found on the system.
- - - - -
- - - -
-
-

- - getDSLModemType(){Promise.<(null|string)>} -

- - - - -
- - -
-
- - -
-

Queries the internal DSL modem type from board information.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<(null|string)> - - - Returns a promise resolving to the type of the internal modem -(e.g. vdsl) or to null if no internal modem is present.
- - - - -
- - - -
-
-

- - getHostHints(){Promise.<LuCI.network.Hosts>} -

- - - - -
- - -
-
- - -
-

Queries aggregated information about known hosts.

-

This function aggregates information from various sources such as -DHCP lease databases, ARP and IPv6 neighbour entries, wireless -association list etc. and returns a Hosts -class instance describing the found hosts.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.network.Hosts> - - - Returns a Hosts instance describing host known on the system.
- - - - -
- - - -
-
-

- - getIfnameOf(obj){null|string} -

- - - - -
- - -
-
- - -
-

Obtains the the network device name of the given object.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
obj - - -LuCI.network.Protocol -| - -LuCI.network.Device -| - -LuCI.network.WifiDevice -| - -LuCI.network.WifiNetwork -| - -string - - - - - -

The object to get the device name from.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns a string containing the device name or null if the given -object could not be converted to a name.
- - - - -
- - - -
-
-

- - getNetwork(name){Promise.<(null|LuCI.network.Protocol)>} -

- - - - -
- - -
-
- - -
-

Get a Protocol instance describing -the network with the given name.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - -

The logical interface name of the network get, e.g. lan or wan.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<(null|LuCI.network.Protocol)> - - - Returns a promise resolving to a -Protocol subclass instance describing -the network or null if the network did not exist.
- - - - -
- - - -
-
-

- - getNetworks(){Promise.<Array.<LuCI.network.Protocol>>} -

- - - - -
- - -
-
- - -
-

Gets an array containing all known networks.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.network.Protocol>> - - - Returns a promise resolving to a name-sorted array of -Protocol subclass instances -describing all known networks.
- - - - -
- - - -
-
-

- - getProtocol(protoname, netname){null|LuCI.network.Protocol} -

- - - - -
- - -
-
- - -
-

Instantiates the given Protocol backend, -optionally using the given network name.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
protoname - - -string - - - - - - - - - - - - -

The protocol backend to use, e.g. static or dhcp.

netname - - -string - - - - - - __dummy__ - - - - - optional - - - - - -

The network name to use for the instantiated protocol. This should be -usually set to one of the interfaces described in /etc/config/network -but it is allowed to omit it, e.g. to query protocol capabilities -without the need for an existing interface.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - LuCI.network.Protocol - - - Returns the instantiated protocol backend class or null if the given -protocol isn't known.
- - - - -
- - - -
-
-

- - getProtocols(){Array.<LuCI.network.Protocol>} -

- - - - -
- - -
-
- - -
-

Obtains instances of all known Protocol -backend classes.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<LuCI.network.Protocol> - - - Returns an array of protocol class instances.
- - - - -
- - - -
-
-

- - getSwitchTopologies(){Promise.<Object.<string, LuCI.network.SwitchTopology>>} -

- - - - -
- - -
-
- - -
-

Returns the topologies of all swconfig switches found on the system.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Object.<string, LuCI.network.SwitchTopology>> - - - Returns a promise resolving to an object containing the topologies -of each switch. The object keys correspond to the name of the switches -such as switch0, the values are -SwitchTopology objects describing -the layout.
- - - - -
- - - -
-
-

- - getWAN6Networks(){Promise.<Array.<LuCI.network.Protocol>>} -

- - - - -
- - -
-
- - -
-

Get IPv6 wan networks.

-

This function looks up all networks having a default ::/0 route -and returns them as array.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.network.Protocol>> - - - Returns a promise resolving to an array of Protocol subclass -instances describing the found IPv6 default route interfaces.
- - - - -
- - - -
-
-

- - getWANNetworks(){Promise.<Array.<LuCI.network.Protocol>>} -

- - - - -
- - -
-
- - -
-

Get IPv4 wan networks.

-

This function looks up all networks having a default 0.0.0.0/0 route -and returns them as array.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.network.Protocol>> - - - Returns a promise resolving to an array of Protocol subclass -instances describing the found default route interfaces.
- - - - -
- - - -
-
-

- - getWifiDevice(devname){Promise.<(null|LuCI.network.WifiDevice)>} -

- - - - -
- - -
-
- - -
-

Get a WifiDevice instance describing -the given wireless radio.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
devname - - -string - - - - - -

The configuration name of the wireless radio to lookup, e.g. radio0 -for the first mac80211 phy on the system.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<(null|LuCI.network.WifiDevice)> - - - Returns a promise resolving to the WifiDevice instance describing -the underlying radio device or null if the wireless radio could not -be found.
- - - - -
- - - -
-
-

- - getWifiDevices(){Promise.<Array.<LuCI.network.WifiDevice>>} -

- - - - -
- - -
-
- - -
-

Obtain a list of all configured radio devices.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.network.WifiDevice>> - - - Returns a promise resolving to an array of WifiDevice instances -describing the wireless radios configured in the system. -The order of the array corresponds to the order of the radios in -the configuration.
- - - - -
- - - -
-
-

- - getWifiNetwork(netname){Promise.<(null|LuCI.network.WifiNetwork)>} -

- - - - -
- - -
-
- - -
-

Get a WifiNetwork instance describing -the given wireless network.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
netname - - -string - - - - - -

The name of the wireless network to lookup. This may be either an uci -configuration section ID, a network ID in the form radio#.network# -or a Linux network device name like wlan0 which is resolved to the -corresponding configuration section through ubus runtime information.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<(null|LuCI.network.WifiNetwork)> - - - Returns a promise resolving to the WifiNetwork instance describing -the wireless network or null if the corresponding network could not -be found.
- - - - -
- - - -
-
-

- - getWifiNetworks(){Promise.<Array.<LuCI.network.WifiNetwork>>} -

- - - - -
- - -
-
- - -
-

Get an array of all WifiNetwork -instances describing the wireless networks present on the system.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<LuCI.network.WifiNetwork>> - - - Returns a promise resolving to an array of WifiNetwork instances -describing the wireless networks. The array will be empty if no networks -are found.
- - - - -
- - - -
-
-

- - isIgnoredDevice(name){boolean} -

- - - - -
- - -
-
- - -
-

Test if a given network device name is in the list of patterns for -device names to ignore.

-

Ignored device names are usually Linux network devices which are -spawned implicitly by kernel modules such as tunl0 or hwsim0 -and which are unsuitable for use in network configuration.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - - - -

The device name to test.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the given name is in the ignore pattern list, -else returns false.
- - - - -
- - - -
-
-

- - maskToPrefix(netmask, v6){null|number} -

- - - - -
- - -
-
- - -
-

Converts the given netmask to a prefix size in bits.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
netmask - - -string - - - - - - - - - - - - -

The netmask to convert into a bit count.

v6 - - -boolean - - - - - - false - - - - - optional - - - - - -

Whether to parse the given netmask as IPv4 (false) or IPv6 (true) -address.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - number - - - Returns the number of prefix bits contained in the netmask or null -if the given netmask value was invalid.
- - - - -
- - - -
-
-

- - prefixToMask(bits, v6){null|string} -

- - - - -
- - -
-
- - -
-

Converts the given prefix size in bits to a netmask.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
bits - - -number - - - - - - - - - - - - -

The prefix size in bits.

v6 - - -boolean - - - - - - false - - - - - optional - - - - - -

Whether to convert the bits value into an IPv4 netmask (false) or -an IPv6 netmask (true).

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - - - Returns a string containing the netmask corresponding to the bit count -or null when the given amount of bits exceeds the maximum possible -value of 32 for IPv4 or 128 for IPv6.
- - - - -
- - - -
-
-

- - registerErrorCode(code, message){boolean} -

- - - - -
- - -
-
- - -
-

Registers a new human readable translation string for a Protocol -error code.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
code - - -string - - - - - -

The ubus protocol error code to register a translation for, e.g. -NO_DEVICE.

message - - -string - - - - - -

The message to use as translation for the given protocol error code.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the error code description has been added or false -if either the arguments were invalid or if there already was a -description for the given code.
- - - - -
- - - -
-
-

- - registerPatternVirtual(pat) -

- - - - -
- - -
-
- - -
-

Registers a new regular expression pattern to recognize -virtual interfaces.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
pat - - -RegExp - - - - - -

A RegExp instance to match a virtual interface name -such as 6in4-wan or tun0.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - registerProtocol(protoname, methods){LuCI.network.Protocol} -

- - - - -
- - -
-
- - -
-

Registers a new Protocol subclass -with the given methods and returns the resulting subclass value.

-

This functions internally calls -Class.extend() on the Network.Protocol -base class.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
protoname - - -string - - - - - -

The name of the new protocol to register.

methods - - -Object.<string, *> - - - - - -

The member methods and values of the new Protocol subclass to -be passed to Class.extend().

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.network.Protocol - - - Returns the new Protocol subclass.
- - - - -
- - - -
-
-

- - renameNetwork(oldName, newName){Promise.<boolean>} -

- - - - -
- - -
-
- - -
-

Rename the given network and its references to a new name.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
oldName - - -string - - - - - -

The current name of the network.

newName - - -string - - - - - -

The name to rename the network to, must be in the format -[a-z-A-Z0-9_]+.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<boolean> - - - Returns a promise resolving to either true if the network was -successfully renamed or false if the new name was invalid, if -a network with the new name already exists or if the network to -rename could not be found.
- - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.network.SwitchTopologyObject.<string, (Object|Array)>

-
- - -
-
- -
-

Describes an swconfig switch topology by specifying the CPU -connections and external port labels of a switch.

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
netdevs - - -Object.<number, string> - - - -

The netdevs property points to an object describing the CPU port -connections of the switch. The numeric key of the enclosed object is -the port number, the value contains the Linux network device name the -port is hardwired to.

ports - - -Array.<Object.<string, (boolean|number|string)>> - - - -

The ports property points to an array describing the populated -ports of the switch in the external label order. Each array item is -an object containg the following keys:

-
    -
  • num - the internal switch port number
  • -
  • label - the label of the port, e.g. LAN 1 or CPU (eth0)
  • -
  • device - the connected Linux network device name (CPU ports only)
  • -
  • tagged - a boolean indicating whether the port must be tagged to -function (CPU ports only)
  • -
- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

LuCI.network.WifiEncryptionObject.<string, (boolean|Array.<(number|string)>)>

-
- - -
-
- -
-

An encryption entry describes active wireless encryption settings -such as the used key management protocols, active ciphers and -protocol versions.

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
enabled - - -boolean - - - - - - - -

Specifies whether any kind of encryption, such as WEP or WPA is -enabled. If set to false, then no encryption is active and the -corresponding network is open.

wep - - -Array.<string> - - - - - - <optional>
- - - -

When the wep property exists, the network uses WEP encryption. -In this case, the property is set to an array of active WEP modes -which might be either open, shared or both.

wpa - - -Array.<number> - - - - - - <optional>
- - - -

When the wpa property exists, the network uses WPA security. -In this case, the property is set to an array containing the WPA -protocol versions used, e.g. [ 1, 2 ] for WPA/WPA2 mixed mode or -[ 3 ] for WPA3-SAE.

authentication - - -Array.<string> - - - - - - <optional>
- - - -

The authentication property only applies to WPA encryption and -is defined when the wpa property is set as well. It points to -an array of active authentication suites used by the network, e.g. -[ "psk" ] for a WPA(2)-PSK network or [ "psk", "sae" ] for -mixed WPA2-PSK/WPA3-SAE encryption.

ciphers - - -Array.<string> - - - - - - <optional>
- - - -

If either WEP or WPA encryption is active, then the ciphers -property will be set to an array describing the active encryption -ciphers used by the network, e.g. [ "tkip", "ccmp" ] for a -WPA/WPA2-PSK mixed network or [ "wep-40", "wep-104" ] for an -WEP network.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

LuCI.network.WifiPeerEntryObject.<string, (boolean|number|string|LuCI.network.WifiRateEntry)>

-
- - -
-
- -
-

A wireless peer entry describes the properties of a remote wireless -peer associated with a local network.

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
mac - - -string - - - - - - - -

The MAC address (BSSID).

signal - - -number - - - - - - - -

The received signal strength.

signal_avg - - -number - - - - - - <optional>
- - - -

The average signal strength if supported by the driver.

noise - - -number - - - - - - <optional>
- - - -

The current noise floor of the radio. May be 0 or absent if not -supported by the driver.

inactive - - -number - - - - - - - -

The amount of milliseconds the peer has been inactive, e.g. due -to powersave.

connected_time - - -number - - - - - - - -

The amount of milliseconds the peer is associated to this network.

thr - - -number - - - - - - <optional>
- - - -

The estimated throughput of the peer, May be 0 or absent if not -supported by the driver.

authorized - - -boolean - - - - - - - -

Specifies whether the peer is authorized to associate to this network.

authenticated - - -boolean - - - - - - - -

Specifies whether the peer completed authentication to this network.

preamble - - -string - - - - - - - -

The preamble mode used by the peer. May be long or short.

wme - - -boolean - - - - - - - -

Specifies whether the peer supports WME/WMM capabilities.

mfp - - -boolean - - - - - - - -

Specifies whether management frame protection is active.

tdls - - -boolean - - - - - - - -

Specifies whether TDLS is active.

mesh llid - - -number - - - - - - <optional>
- - - -

The mesh LLID, may be 0 or absent if not applicable or supported -by the driver.

mesh plid - - -number - - - - - - <optional>
- - - -

The mesh PLID, may be 0 or absent if not applicable or supported -by the driver.

mesh plink - - -string - - - - - - <optional>
- - - -

The mesh peer link state description, may be an empty string ('') -or absent if not applicable or supported by the driver.

-

The following states are known:

-
    -
  • LISTEN
  • -
  • OPN_SNT
  • -
  • OPN_RCVD
  • -
  • CNF_RCVD
  • -
  • ESTAB
  • -
  • HOLDING
  • -
  • BLOCKED
  • -
  • UNKNOWN
  • -
mesh local PS - - -number - - - - - - <optional>
- - - -

The local powersafe mode for the peer link, may be an empty -string ('') or absent if not applicable or supported by -the driver.

-

The following modes are known:

-
    -
  • ACTIVE (no power save)
  • -
  • LIGHT SLEEP
  • -
  • DEEP SLEEP
  • -
  • UNKNOWN
  • -
mesh peer PS - - -number - - - - - - <optional>
- - - -

The remote powersafe mode for the peer link, may be an empty -string ('') or absent if not applicable or supported by -the driver.

-

The following modes are known:

-
    -
  • ACTIVE (no power save)
  • -
  • LIGHT SLEEP
  • -
  • DEEP SLEEP
  • -
  • UNKNOWN
  • -
mesh non-peer PS - - -number - - - - - - <optional>
- - - -

The powersafe mode for all non-peer neigbours, may be an empty -string ('') or absent if not applicable or supported by the driver.

-

The following modes are known:

-
    -
  • ACTIVE (no power save)
  • -
  • LIGHT SLEEP
  • -
  • DEEP SLEEP
  • -
  • UNKNOWN
  • -
rx - - -LuCI.network.WifiRateEntry - - - - - - - -

Describes the receiving wireless rate from the peer.

tx - - -LuCI.network.WifiRateEntry - - - - - - - -

Describes the transmitting wireless rate to the peer.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

LuCI.network.WifiRateEntryObject.<string, (boolean|number)>

-
- - -
-
- -
-

A wireless rate entry describes the properties of a wireless -transmission rate to or from a peer.

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
drop_misc - - -number - - - - - - <optional>
- - - -

The amount of received misc. packages that have been dropped, e.g. -due to corruption or missing authentication. Only applicable to -receiving rates.

packets - - -number - - - - - - - -

The amount of packets that have been received or sent.

bytes - - -number - - - - - - - -

The amount of bytes that have been received or sent.

failed - - -number - - - - - - <optional>
- - - -

The amount of failed tranmission attempts. Only applicable to -transmit rates.

retries - - -number - - - - - - <optional>
- - - -

The amount of retried transmissions. Only applicable to transmit -rates.

is_ht - - -boolean - - - - - - - -

Specifies whether this rate is an HT (IEEE 802.11n) rate.

is_vht - - -boolean - - - - - - - -

Specifies whether this rate is an VHT (IEEE 802.11ac) rate.

mhz - - -number - - - - - - - -

The channel width in MHz used for the transmission.

rate - - -number - - - - - - - -

The bitrate in bit/s of the transmission.

mcs - - -number - - - - - - <optional>
- - - -

The MCS index of the used transmission rate. Only applicable to -HT or VHT rates.

40mhz - - -number - - - - - - <optional>
- - - -

Specifies whether the tranmission rate used 40MHz wide channel. -Only applicable to HT or VHT rates.

-

Note: this option exists for backwards compatibility only and its -use is discouraged. The mhz field should be used instead to -determine the channel width.

short_gi - - -boolean - - - - - - <optional>
- - - -

Specifies whether a short guard interval is used for the transmission. -Only applicable to HT or VHT rates.

nss - - -number - - - - - - <optional>
- - - -

Specifies the number of spatial streams used by the transmission. -Only applicable to VHT rates.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

LuCI.network.WifiScanResultObject.<string, (number|string|LuCI.network.WifiEncryption)>

-
- - -
-
- -
-

A wireless scan result object describes a neighbouring wireless -network found in the vincinity.

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ssid - - -string - - - -

The SSID / Mesh ID of the network.

bssid - - -string - - - -

The BSSID if the network.

mode - - -string - - - -

The operation mode of the network (Master, Ad-Hoc, Mesh Point).

channel - - -number - - - -

The wireless channel of the network.

signal - - -number - - - -

The received signal strength of the network in dBm.

quality - - -number - - - -

The numeric quality level of the signal, can be used in conjunction -with quality_max to calculate a quality percentage.

quality_max - - -number - - - -

The maximum possible quality level of the signal, can be used in -conjunction with quality to calculate a quality percentage.

encryption - - -LuCI.network.WifiEncryption - - - -

The encryption used by the wireless network.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.poll.html b/docs/jsapi/LuCI.poll.html deleted file mode 100644 index 7e958bcb26..0000000000 --- a/docs/jsapi/LuCI.poll.html +++ /dev/null @@ -1,4242 +0,0 @@ - - - - - Class: poll - - - - - - - - - - - - - - - - - -
- - -
-

Class: poll

- - - - -
- -
-

- LuCI. - - poll -

- -

The Poll class allows registering and unregistering poll actions, -as well as starting, stopping and querying the state of the polling -loop.

- -
- -
-
- - - - -
-
-

- - new LuCI.poll() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - active(){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the polling loop is running.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - -
    -
  • Returns true if polling is active, else false.
  • -
- - - - -
- - - -
-
-

- - add(fn, interval){boolean} -

- - - - -
- - -
-
- - -
-

Add a new operation to the polling loop. If the polling loop is not -already started at this point, it will be implicitely started.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
fn - - -function - - - - - -

The function to invoke on each poll interval.

interval - - -number - - - - - -

The poll interval in seconds.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws TypeError when an invalid interval was passed.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the function has been added or false if it -already is registered.
- - - - -
- - - -
-
-

- - remove(fn){boolean} -

- - - - -
- - -
-
- - -
-

Remove an operation from the polling loop. If no further operatons -are registered, the polling loop is implicitely stopped.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
fn - - -function - - - - - -

The function to remove.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws TypeError when the given argument isn't a function.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the function has been removed or false if it -wasn't found.
- - - - -
- - - -
-
-

- - start(){boolean} -

- - - - -
- - -
-
- - -
-

(Re)start the polling loop. Dispatches a custom poll-start event -to the document object upon successful start.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if polling has been started (or if no functions -where registered) or false when the polling loop already runs.
- - - - -
- - - -
-
-

- - stop(){boolean} -

- - - - -
- - -
-
- - -
-

Stop the polling loop. Dispatches a custom poll-stop event -to the document object upon successful stop.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if polling has been stopped or false if it din't -run to begin with.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.request.html b/docs/jsapi/LuCI.request.html deleted file mode 100644 index dc1ef17946..0000000000 --- a/docs/jsapi/LuCI.request.html +++ /dev/null @@ -1,5177 +0,0 @@ - - - - - Class: request - - - - - - - - - - - - - - - - - -
- - -
-

Class: request

- - - - -
- -
-

- LuCI. - - request -

- -

The Request class allows initiating HTTP requests and provides utilities -for dealing with responses.

- -
- -
-
- - - - -
-
-

- - new LuCI.request() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - -

Classes

- -
-
poll
-
-
- - - - - - - -

Methods

- -
- -
-
-

- - addInterceptor(interceptorFn){LuCI.request.interceptorFn} -

- - - - -
- - -
-
- - -
-

Register an HTTP response interceptor function. Interceptor -functions are useful to perform default actions on incoming HTTP -responses, such as checking for expired authentication or for -implementing request retries before returning a failure.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
interceptorFn - - -LuCI.request.interceptorFn - - - - - -

The interceptor function to register.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.request.interceptorFn - - - The registered function.
- - - - -
- - - -
-
-

- - expandURL(url){string} -

- - - - -
- - -
-
- - -
-

Turn the given relative URL into an absolute URL if necessary.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
url - - -string - - - - - -

The URL to convert.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The absolute URL derived from the given one, or the original URL -if it already was absolute.
- - - - -
- - - -
-
-

- - get(target, options){Promise.<LuCI.response>} -

- - - - -
- - -
-
- - -
-

Initiate an HTTP GET request to the given target.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
target - - -string - - - - - - - - - - -

The URL to request.

options - - -LuCI.request.RequestOptions - - - - - - - optional - - - - - -

Additional options to configure the request.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.response> - - - The resulting HTTP response.
- - - - -
- - - -
-
-

- - post(target, data, options){Promise.<LuCI.response>} -

- - - - -
- - -
-
- - -
-

Initiate an HTTP POST request to the given target.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
target - - -string - - - - - - - - - - -

The URL to request.

data - - -* - - - - - - - optional - - - - - -

The request data to send, see LuCI.request.RequestOptions for details.

options - - -LuCI.request.RequestOptions - - - - - - - optional - - - - - -

Additional options to configure the request.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.response> - - - The resulting HTTP response.
- - - - -
- - - -
-
-

- - removeInterceptor(interceptorFn){boolean} -

- - - - -
- - -
-
- - -
-

Remove an HTTP response interceptor function. The passed function -value must be the very same value that was used to register the -function.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
interceptorFn - - -LuCI.request.interceptorFn - - - - - -

The interceptor function to remove.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if any function has been removed, else false.
- - - - -
- - - -
-
-

- - request(target, options){Promise.<LuCI.response>} -

- - - - -
- - -
-
- - -
-

Initiate an HTTP request to the given target.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
target - - -string - - - - - - - - - - -

The URL to request.

options - - -LuCI.request.RequestOptions - - - - - - - optional - - - - - -

Additional options to configure the request.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.response> - - - The resulting HTTP response.
- - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

- - LuCI.request.interceptorFn(res) -

- - - - -
- - -
-
- - -
-

Interceptor functions are invoked whenever an HTTP reply is received, in the order -these functions have been registered.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
res - - -LuCI.response - - - - - -

The HTTP response object

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

LuCI.request.RequestOptionsObject

-
- - -
-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
method - - -string - - - - - - <optional>
- - - -
- - GET - -

The HTTP method to use, e.g. GET or POST.

query - - -Object.<string, (Object|string)> - - - - - - <optional>
- - - -
- -

Query string data to append to the URL. Non-string values of the -given object will be converted to JSON.

cache - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether the HTTP response may be retrieved from cache.

username - - -string - - - - - - <optional>
- - - -
- -

Provides a username for HTTP basic authentication.

password - - -string - - - - - - <optional>
- - - -
- -

Provides a password for HTTP basic authentication.

timeout - - -number - - - - - - <optional>
- - - -
- -

Specifies the request timeout in seconds.

credentials - - -boolean - - - - - - <optional>
- - - -
- - false - -

Whether to include credentials such as cookies in the request.

responseType - - -string - - - - - - <optional>
- - - -
- - text - -

Overrides the request response type. Valid values or text to -interpret the response as UTF-8 string or blob to handle the -response as binary Blob data.

content - - -* - - - - - - <optional>
- - - -
- -

Specifies the HTTP message body to send along with the request. -If the value is a function, it is invoked and the return value -used as content, if it is a FormData instance, it is used as-is, -if it is an object, it will be converted to JSON, in all other -cases it is converted to a string.

header - - -Object.<string, string> - - - - - - <optional>
- - - -
- -

Specifies HTTP headers to set for the request.

progress - - -function - - - - - - <optional>
- - - -
- -

An optional request callback function which receives ProgressEvent -instances as sole argument during the HTTP request transfer.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.request.poll.html b/docs/jsapi/LuCI.request.poll.html deleted file mode 100644 index ef83287f01..0000000000 --- a/docs/jsapi/LuCI.request.poll.html +++ /dev/null @@ -1,4361 +0,0 @@ - - - - - Class: poll - - - - - - - - - - - - - - - - - -
- - -
-

Class: poll

- - - - -
- -
-

- LuCI.request. - - poll -

- -

The Request.poll class provides some convience wrappers around -LuCI.poll mainly to simplify registering repeating HTTP -request calls as polling functions.

- -
- -
-
- - - - -
-
-

- - new LuCI.request.poll() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - active() -

- - - - -
- - -
-
- - -
-

Alias for LuCI.poll.active().

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - add(interval, url, options, callback){function} -

- - - - -
- - -
-
- - -
-

Register a repeating HTTP request with an optional callback -to invoke whenever a response for the request is received.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
interval - - -number - - - - - - - - - - -

The poll interval in seconds.

url - - -string - - - - - - - - - - -

The URL to request on each poll.

options - - -LuCI.request.RequestOptions - - - - - - - optional - - - - - -

Additional options to configure the request.

callback - - -LuCI.request.poll~callbackFn - - - - - - - optional - - - - - -

Callback function to -invoke for each HTTP reply.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws TypeError when an invalid interval was passed.

-
-
-
-
-
- Type -
-
- -TypeError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - function - - - Returns the internally created poll function.
- - - - -
- - - -
-
-

- - remove(entry){boolean} -

- - - - -
- - -
-
- - -
-

Remove a polling request that has been previously added using add(). -This function is essentially a wrapper around -LuCI.poll.remove().

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
entry - - -function - - - - - -

The poll function returned by add().

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if any function has been removed, else false.
- - - - -
- - - -
-
-

- - start() -

- - - - -
- - -
-
- - -
-

Alias for LuCI.poll.start().

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - stop() -

- - - - -
- - -
-
- - -
-

Alias for LuCI.poll.stop().

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

- - callbackFn(res, data, duration) -

- - - - -
- - -
-
- - -
-

The callback function is invoked whenever an HTTP reply to a -polled request is received or when the polled request timed -out.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
res - - -LuCI.response - - - - - -

The HTTP response object.

data - - -* - - - - - -

The response JSON if the response could be parsed as such, -else null.

duration - - -number - - - - - -

The total duration of the request in milliseconds.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.response.html b/docs/jsapi/LuCI.response.html deleted file mode 100644 index a7d483d76b..0000000000 --- a/docs/jsapi/LuCI.response.html +++ /dev/null @@ -1,4319 +0,0 @@ - - - - - Class: response - - - - - - - - - - - - - - - - - -
- - -
-

Class: response

- - - - -
- -
-

- LuCI. - - response -

- -

The Response class is an internal utility class representing HTTP responses.

- -
- -
-
- - - - -
-
-

- - new LuCI.response() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - -

Members

- -
- -
-
-

durationnumber

-
- - -
-
- -
-

The total duration of the HTTP request in milliseconds

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

headersLuCI.headers

-
- - -
-
- -
-

The HTTP headers of the response

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

okboolean

-
- - -
-
- -
-

Describes whether the response is successful (status codes 200..299) or not

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

statusnumber

-
- - -
-
- -
-

The numeric HTTP status code of the response

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

statusTextstring

-
- - -
-
- -
-

The HTTP status description message of the response

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

urlstring

-
- - -
-
- -
-

The final URL of the request, i.e. after following redirects.

-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - -

Methods

- -
- -
-
-

- - blob(){Blob} -

- - - - -
- - -
-
- - -
-

Access the response content as blob.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Blob - - - The response content as blob.
- - - - -
- - - -
-
-

- - clone(content){LuCI.response} -

- - - - -
- - -
-
- - -
-

Clones the given response object, optionally overriding the content -of the cloned instance.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
content - - -* - - - - - - - optional - - - - - -

Override the content of the cloned response. Object values will be -treated as JSON response data, all other types will be converted -using String() and treated as response text.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.response - - - The cloned Response instance.
- - - - -
- - - -
-
-

- - json(){*} -

- - - - -
- - -
-
- - -
-

Access the response content as JSON data.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws SyntaxError if the content isn't valid JSON.

-
-
-
-
-
- Type -
-
- -SyntaxError - - -
-
-
-
- - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - The parsed JSON data.
- - - - -
- - - -
-
-

- - text(){string} -

- - - - -
- - -
-
- - -
-

Access the response content as string.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - The response content.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.rpc.html b/docs/jsapi/LuCI.rpc.html deleted file mode 100644 index 976a3aab79..0000000000 --- a/docs/jsapi/LuCI.rpc.html +++ /dev/null @@ -1,5650 +0,0 @@ - - - - - Class: rpc - - - - - - - - - - - - - - - - - -
- - -
-

Class: rpc

- - - - -
- -
-

- LuCI. - - rpc -

- -

The LuCI.rpc class provides high level ubus JSON-RPC abstractions -and means for listing and invoking remove RPC methods.

- -
- -
-
- - - - -
-
-

- - new LuCI.rpc() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - addInterceptor(interceptorFn){LuCI.rpc~interceptorFn} -

- - - - -
- - -
-
- - -
-

Registers a new interceptor function.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
interceptorFn - - -LuCI.rpc~interceptorFn - - - - - -

The inteceptor function to register.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.rpc~interceptorFn - - - Returns the given function value.
- - - - -
- - - -
-
-

- - declare(options){LuCI.rpc~invokeFn} -

- - - - -
- - -
-
- - -
-

Describes a remote RPC call procedure and returns a function -implementing it.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
options - - -LuCI.rpc.DeclareOptions - - - - - -

If any object names are given, this function will return the method -signatures of each given object.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - LuCI.rpc~invokeFn - - - Returns a new function implementing the method call described in -options.
- - - - -
- - - -
-
-

- - getBaseURL(){string} -

- - - - -
- - -
-
- - -
-

Returns the current RPC base URL.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the RPC URL endpoint to issue requests against.
- - - - -
- - - -
-
-

- - getSessionID(){string} -

- - - - -
- - -
-
- - -
-

Returns the current RPC session id.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the 32 byte session ID string used for authenticating remote -requests.
- - - - -
- - - -
-
-

- - getStatusText(statusCode){string} -

- - - - -
- - -
-
- - -
-

Translates a numeric ubus error code into a human readable -description.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
statusCode - - -number - - - - - -

The numeric status code.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the textual description of the code.
- - - - -
- - - -
-
-

- - list(objectNames){Promise.<(Array.<string>|Object.<string, Object.<string, Object.<string, string>>>)>} -

- - - - -
- - -
-
- - -
-

Lists available remote ubus objects or the method signatures of -specific objects.

-

This function has two signatures and is sensitive to the number of -arguments passed to it:

-
    -
  • list() - -Returns an array containing the names of all remote ubus objects
  • -
  • list("objname", ...) -Returns method signatures for each given ubus object name.
  • -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
objectNames - - -string - - - - - - - optional - - - - - repeatable - - -

If any object names are given, this function will return the method -signatures of each given object.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<(Array.<string>|Object.<string, Object.<string, Object.<string, string>>>)> - - - When invoked without arguments, this function will return a promise -resolving to an array of ubus object names. When invoked with one or -more arguments, a promise resolving to an object describing the method -signatures of each requested ubus object name will be returned.
- - - - -
- - - -
-
-

- - removeInterceptor(interceptorFn){boolean} -

- - - - -
- - -
-
- - -
-

Removes a registered interceptor function.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
interceptorFn - - -LuCI.rpc~interceptorFn - - - - - -

The inteceptor function to remove.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the given function has been removed or false -if it has not been found.
- - - - -
- - - -
-
-

- - setBaseURL(sid) -

- - - - -
- - -
-
- - -
-

Set the RPC base URL to use.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
sid - - -string - - - - - -

Sets the RPC URL endpoint to issue requests against.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - setSessionID(sid) -

- - - - -
- - -
-
- - -
-

Set the RPC session id to use.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
sid - - -string - - - - - -

Sets the 32 byte session ID string used for authenticating remote -requests.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.rpc.DeclareOptionsObject

-
- - -
-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
object - - -string - - - - - - - - - -

The name of the remote ubus object to invoke.

method - - -string - - - - - - - - - -

The name of the remote ubus method to invoke.

params - - -Array.<string> - - - - - - <optional>
- - - -
- -

Lists the named parameters expected by the remote ubus RPC method. -The arguments passed to the resulting generated method call function -will be mapped to named parameters in the order they appear in this -array.

-

Extraneous parameters passed to the generated function will not be -sent to the remote procedure but are passed to the -filter function if one is specified.

-

Examples:

-
    -
  • params: [ "foo", "bar" ] - -When the resulting call function is invoked with fn(true, false), -the corresponding args object sent to the remote procedure will be -{ foo: true, bar: false }.
  • -
  • params: [ "test" ], filter: function(reply, args, extra) { ... } - -When the resultung generated function is invoked with -fn("foo", "bar", "baz") then { "test": "foo" } will be sent as -argument to the remote procedure and the filter function will be -invoked with filterFn(reply, [ "foo" ], "bar", "baz")
  • -
expect - - -Object.<string, *> - - - - - - <optional>
- - - -
- -

Describes the expected return data structure. The given object is -supposed to contain a single key selecting the value to use from -the returned ubus reply object. The value of the sole key within -the expect object is used to infer the expected type of the received -ubus reply data.

-

If the received data does not contain expect's key, or if the -type of the data differs from the type of the value in the expect -object, the expect object's value is returned as default instead.

-

The key in the expect object may be an empty string ('') in which -case the entire reply object is selected instead of one of its subkeys.

-

If the expect option is omitted, the received reply will be returned -as-is, regardless of its format or type.

-

Examples:

-
    -
  • expect: { '': { error: 'Invalid response' } } - -This requires the entire ubus reply to be a plain JavaScript -object. If the reply isn't an object but e.g. an array or a numeric -error code instead, it will get replaced with -{ error: 'Invalid response' } instead.
  • -
  • expect: { results: [] } - -This requires the received ubus reply to be an object containing -a key results with an array as value. If the received reply does -not contain such a key, or if reply.results points to a non-array -value, the empty array ([]) will be used instead.
  • -
  • expect: { success: false } - -This requires the received ubus reply to be an object containing -a key success with a boolean value. If the reply does not contain -success or if reply.success is not a boolean value, false will -be returned as default instead.
  • -
filter - - -LuCI.rpc~filterFn - - - - - - <optional>
- - - -
- -

Specfies an optional filter function which is invoked to transform the -received reply data before it is returned to the caller.

reject - - -boolean - - - - - - <optional>
- - - -
- - false - -

If set to true, non-zero ubus call status codes are treated as fatal -error and lead to the rejection of the call promise. The default -behaviour is to resolve with the call return code value instead.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

- - filterFn(data, args, extraArgs){*} -

- - - - -
- - -
-
- - -
-

The filter function is invoked to transform a received ubus RPC call -reply before returning it to the caller.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
data - - -* - - - - - - - - - - -

The received ubus reply data or a subset of it as described in the -expect option of the RPC call declaration. In case of remote call -errors, data is numeric ubus error code instead.

args - - -Array.<*> - - - - - - - - - - -

The arguments the RPC method has been invoked with.

extraArgs - - -* - - - - - - - - - - repeatable - - -

All extraneous arguments passed to the RPC method exceeding the number -of arguments describes in the RPC call declaration.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - The return value of the filter function will be returned to the caller -of the RPC method as-is.
- - - - -
- - - -
-
-

- - interceptorFn(msg, req){Promise.<*>|*} -

- - - - -
- - -
-
- - -
-

Registered interceptor functions are invoked before the standard reply -parsing and handling logic.

-

By returning rejected promises, interceptor functions can cause the -invocation function to fail, regardless of the received reply.

-

Interceptors may also modify their message argument in-place to -rewrite received replies before they're processed by the standard -response handling code.

-

A common use case for such functions is to detect failing RPC replies -due to expired authentication in order to trigger a new login.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
msg - - -* - - - - - -

The unprocessed, JSON decoded remote RPC method call reply.

-

Since interceptors run before the standard parsing logic, the reply -data is not verified for correctness or filtered according to -expect and filter specifications in the declarations.

req - - -Object - - - - - -

The related request object which is an extended variant of the -declaration object, allowing access to internals of the invocation -function such as filter, expect or params values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<*> - | - - * - - - Interceptor functions may return a promise to defer response -processing until some delayed work completed. Any values the returned -promise resolves to are ignored. -When the returned promise rejects with an error, the invocation -function will fail too, forwarding the error to the caller.
- - - - -
- - - -
-
-

- - invokeFn(params){Promise.<*>} -

- - - - -
- - -
-
- - -
-

The generated invocation function is returned by -rpc.declare() and encapsulates a single -RPC method call.

-

Calling this function will execute a remote ubus HTTP call request -using the arguments passed to it as arguments and return a promise -resolving to the received reply values.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
params - - -* - - - - - - - - - - repeatable - - -

The parameters to pass to the remote procedure call. The given -positional arguments will be named to named RPC parameters according -to the names specified in the params array of the method declaration.

-

Any additional parameters exceeding the amount of arguments in the -params declaration are passed as private extra arguments to the -declared filter function.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<*> - - - Returns a promise resolving to the result data of the remote ubus -RPC method invocation, optionally substituted and filtered according -to the expect and filter declarations.
- - - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.session.html b/docs/jsapi/LuCI.session.html deleted file mode 100644 index 298f6dbd50..0000000000 --- a/docs/jsapi/LuCI.session.html +++ /dev/null @@ -1,4089 +0,0 @@ - - - - - Class: session - - - - - - - - - - - - - - - - - -
- - -
-

Class: session

- - - - -
- -
-

- LuCI. - - session -

- -

The session class provides various session related functionality.

- -
- -
-
- - - - -
-
-

- - new LuCI.session() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - getID(){string} -

- - - - -
- - -
-
- - -
-

Retrieve the current session ID.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the current session ID.
- - - - -
- - - -
-
-

- - getLocalData(key){*} -

- - - - -
- - -
-
- - -
-

Retrieve data from the local session storage.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - - - optional - - - - - -

The key to retrieve from the session data store. If omitted, all -session data will be returned.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - - - Returns the stored session data or null if the given key wasn't -found.
- - - - -
- - - -
-
-

- - getToken(){string|null} -

- - - - -
- - -
-
- - -
-

Retrieve the current session token.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - Returns the current session token or null if not logged in.
- - - - -
- - - -
-
-

- - setLocalData(key, value){boolean} -

- - - - -
- - -
-
- - -
-

Set data in the local session storage.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
key - - -string - - - - - -

The key to set in the session data store.

value - - -* - - - - - -

The value to store. It will be internally converted to JSON before -being put in the session store.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the data could be stored or false on error.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.uci.html b/docs/jsapi/LuCI.uci.html deleted file mode 100644 index 81ef9cb020..0000000000 --- a/docs/jsapi/LuCI.uci.html +++ /dev/null @@ -1,7137 +0,0 @@ - - - - - Class: uci - - - - - - - - - - - - - - - - - -
- - -
-

Class: uci

- - - - -
- -
-

- LuCI. - - uci -

- -

The LuCI.uci class utilizes LuCI.rpc to declare low level -remote UCI ubus procedures and implements a local caching and data -manipulation layer on top to allow for synchroneous operations on -UCI configuration data.

- -
- -
-
- - - - -
-
-

- - new LuCI.uci() -

- - -
- uci.js, line 5 -
- -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - add(config, type, name){string} -

- - - - -
- - -
-
- - -
-

Adds a new section of the given type to the given configuration, -optionally named according to the given name.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - - - - - - -

The name of the configuration to add the section to.

type - - -string - - - - - - - - - - -

The type of the section to add.

name - - -string - - - - - - - optional - - - - - -

The name of the section to add. If the name is omitted, an anonymous -section will be added instead.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - Returns the section ID of the newly added section which is equivalent -to the given name for non-anonymous sections.
- - - - -
- - - -
-
-

- - apply(timeout){Promise.<number>} -

- - - - -
- - -
-
- - -
-

Instructs the remote ubus UCI api to commit all saved changes with -rollback protection and attempts to confirm the pending commit -operation to cancel the rollback timer.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
timeout - - -number - - - - - - 10 - - - - - optional - - - - - -

Override the confirmation timeout after which a rollback is triggered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<number> - - - Returns a promise resolving/rejecting with the ubus RPC status code.
- - - - -
- - - -
-
-

- - changes(){Promise.<Object.<string, Array.<LuCI.uci.ChangeRecord>>>} -

- - - - -
- - -
-
- - -
-

Fetches uncommitted UCI changes from the remote ubus RPC api.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Object.<string, Array.<LuCI.uci.ChangeRecord>>> - - - Returns a promise resolving to an object containing the configuration -names as keys and arrays of related change records as values.
- - - - -
- - - -
-
-

- - createSID(config){string} -

- - - - -
- - -
-
- - -
-

Generates a new, unique section ID for the given configuration.

-

Note that the generated ID is temporary, it will get replaced by an -identifier in the form cfgXXXXXX once the configuration is saved -by the remote ubus UCI api.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - -

The configuration to generate the new section ID for.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - - - A newly generated, unique section ID in the form newXXXXXX -where X denotes a hexadecimal digit.
- - - - -
- - - -
-
-

- - get(config, sid, option){null|string|Array.<string>|LuCI.uci.SectionObject} -

- - - - -
- - -
-
- - -
-

Gets the value of the given option within the specified section -of the given configuration or the entire section object if the -option name is omitted.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - - - - - - -

The name of the configuration to read the value from.

sid - - -string - - - - - - - - - - -

The name or ID of the section to read.

option - - -string - - - - - - - optional - - - - - -

The option name to read the value from. If the option name is -omitted or null, the entire section is returned instead.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - LuCI.uci.SectionObject - - -
    -
  • Returns a string containing the option value in case of a -plain UCI option.
  • -
  • Returns an array of strings containing the option values in -case of option pointing to an UCI list.
  • -
  • Returns a section object if -the option argument has been omitted or is null.
  • -
  • Returns null if the config, section or option has not been -found or if the corresponding configuration is not loaded.
  • -
- - - - -
- - - -
-
-

- - get_first(config, type, option){null|string|Array.<string>|LuCI.uci.SectionObject} -

- - - - -
- - -
-
- - -
-

Gets the value of the given option or the entire section object of -the first found section of the specified type or the first found -section of the entire configuration if no type is specfied.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - - - - - - -

The name of the configuration to read the value from.

type - - -string - - - - - - - optional - - - - - -

The type of the first section to find. If it is null, the first -section of the entire config is read, otherwise the first section -matching the given type.

option - - -string - - - - - - - optional - - - - - -

The option name to read the value from. If the option name is -omitted or null, the entire section is returned instead.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - null - | - - string - | - - Array.<string> - | - - LuCI.uci.SectionObject - - -
    -
  • Returns a string containing the option value in case of a -plain UCI option.
  • -
  • Returns an array of strings containing the option values in -case of option pointing to an UCI list.
  • -
  • Returns a section object if -the option argument has been omitted or is null.
  • -
  • Returns null if the config, section or option has not been -found or if the corresponding configuration is not loaded.
  • -
- - - - -
- - - -
-
-

- - load(config){Promise.<Array.<string>>} -

- - - - -
- - -
-
- - -
-

Loads the given UCI configurations from the remote ubus api.

-

Loaded configurations are cached and only loaded once. Subsequent -load operations of the same configurations will return the cached -data.

-

To force reloading a configuration, it has to be unloaded with -uci.unload() first.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string -| - -Array.<string> - - - - - -

The name of the configuration or an array of configuration -names to load.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Array.<string>> - - - Returns a promise resolving to the names of the configurations -that have been successfully loaded.
- - - - -
- - - -
-
-

- - move(config, sid1, sid2, after){boolean} -

- - - - -
- - -
-
- - -
-

Move the first specified section within the given configuration -before or after the second specified section.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
config - - -string - - - - - - - - - - - - -

The configuration to move the section within.

sid1 - - -string - - - - - - - - - - - - -

The ID of the section to move within the configuration.

sid2 - - -string - - - - - - - - - optional - - - - - -

The ID of the target section for the move operation. If the -after argument is false or not specified, the section named by -sid1 will be moved before this target section, if the after -argument is true, the sid1 section will be moved after this -section.

-

When the sid2 argument is null, the section specified by sid1 -is moved to the end of the configuration.

after - - -boolean - - - - - - false - - - - - optional - - - - - -

When true, the section sid1 is moved after the section sid2, -when false, the section sid1 is moved before sid2.

-

If sid2 is null, then this parameter has no effect and the section -sid1 is moved to the end of the configuration instead.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the section was successfully moved, or false -when either the section specified by sid1 or by sid2 is not found.
- - - - -
- - - -
-
-

- - remove(config, sid) -

- - - - -
- - -
-
- - -
-

Removes the section with the given ID from the given configuration.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - -

The name of the configuration to remove the section from.

sid - - -string - - - - - -

The ID of the section to remove.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - resolveSID(config, sid){string|null} -

- - - - -
- - -
-
- - -
-

Resolves a given section ID in extended notation to the internal -section ID value.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - -

The configuration to resolve the section ID for.

sid - - -string - - - - - -

The section ID to resolve. If the ID is in the form @typename[#], -it will get resolved to an internal anonymous ID in the forms -cfgXXXXXX/newXXXXXX or to the name of a section in case it points -to a named section. When the given ID is not in extended notation, -it will be returned as-is.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - null - - - Returns the resolved section ID or the original given ID if it was -not in extended notation. Returns null when an extended ID could -not be resolved to existing section ID.
- - - - -
- - - -
-
-

- - save(){Array.<string>} -

- - - - -
- - -
-
- - -
-

Submits all local configuration changes to the remove ubus api, -adds, removes and reorders remote sections as needed and reloads -all loaded configurations to resynchronize the local state with -the remote configuration values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<string> - - - Returns a promise resolving to an array of configuration names which -have been reloaded by the save operation.
- - - - -
- - - -
-
-

- - sections(config, type, cb){Array.<LuCI.uci.SectionObject>} -

- - - - -
- - -
-
- - -
-

Enumerates the sections of the given configuration, optionally -filtered by type.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - - - - - - -

The name of the configuration to enumerate the sections for.

type - - -string - - - - - - - optional - - - - - -

Enumerate only sections of the given type. If omitted, enumerate -all sections.

cb - - -LuCI.uci~sectionsFn - - - - - - - optional - - - - - -

An optional callback to invoke for each enumerated section.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<LuCI.uci.SectionObject> - - - Returns a sorted array of the section objects within the given -configuration, filtered by type of a type has been specified.
- - - - -
- - - -
-
-

- - set(config, sid, option, value) -

- - - - -
- - -
-
- - -
-

Sets the value of the given option within the specified section -of the given configuration.

-

If either config, section or option is null, or if option begins -with a dot, the function will do nothing.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - -

The name of the configuration to set the option value in.

sid - - -string - - - - - -

The name or ID of the section to set the option value in.

option - - -string - - - - - -

The option name to set the value for.

value - - -null -| - -string -| - -Array.<string> - - - - - -

The option value to set. If the value is null or an empty string, -the option will be removed, otherwise it will be set or overwritten -with the given value.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - set_first(config, type, option, value) -

- - - - -
- - -
-
- - -
-

Sets the value of the given option within the first found section -of the given configuration matching the specified type or within -the first section of the entire config when no type has is specified.

-

If either config, type or option is null, or if option begins -with a dot, the function will do nothing.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - - - - - - -

The name of the configuration to set the option value in.

type - - -string - - - - - - - optional - - - - - -

The type of the first section to find. If it is null, the first -section of the entire config is written to, otherwise the first -section matching the given type is used.

option - - -string - - - - - - - - - - -

The option name to set the value for.

value - - -null -| - -string -| - -Array.<string> - - - - - - - - - - -

The option value to set. If the value is null or an empty string, -the option will be removed, otherwise it will be set or overwritten -with the given value.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - unload(config) -

- - - - -
- - -
-
- - -
-

Unloads the given UCI configurations from the local cache.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string -| - -Array.<string> - - - - - -

The name of the configuration or an array of configuration -names to unload.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - unset(config, sid, option) -

- - - - -
- - -
-
- - -
-

Remove the given option within the specified section of the given -configuration.

-

This function is a convenience wrapper around -uci.set(config, section, option, null).

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - -

The name of the configuration to remove the option from.

sid - - -string - - - - - -

The name or ID of the section to remove the option from.

option - - -string - - - - - -

The name of the option to remove.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - unset_first(config, type, option) -

- - - - -
- - -
-
- - -
-

Removes the given option within the first found section of the given -configuration matching the specified type or within the first section -of the entire config when no type has is specified.

-

This function is a convenience wrapper around -uci.set_first(config, type, option, null).

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -string - - - - - - - - - - -

The name of the configuration to set the option value in.

type - - -string - - - - - - - optional - - - - - -

The type of the first section to find. If it is null, the first -section of the entire config is written to, otherwise the first -section matching the given type is used.

option - - -string - - - - - - - - - - -

The option name to set the value for.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.uci.ChangeRecordArray.<string>

-
- - -
-
- -
-

An UCI change record is a plain array containing the change operation -name as first element, the affected section ID as second argument -and an optional third and fourth argument whose meanings depend on -the operation.

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
0 - - -string - - - -

The operation name - may be one of add, set, remove, order, -list-add, list-del or rename.

1 - - -string - - - -

The section ID targeted by the operation.

2 - - -string - - - -

The meaning of the third element depends on the operation.

-
    -
  • For add it is type of the section that has been added
  • -
  • For set it either is the option name if a fourth element exists, -or the type of a named section which has been added when the change -entry only contains three elements.
  • -
  • For remove it contains the name of the option that has been -removed.
  • -
  • For order it specifies the new sort index of the section.
  • -
  • For list-add it contains the name of the list option a new value -has been added to.
  • -
  • For list-del it contains the name of the list option a value has -been removed from.
  • -
  • For rename it contains the name of the option that has been -renamed if a fourth element exists, else it contains the new name -a section has been renamed to if the change entry only contains -three elements.
  • -
4 - - -string - - - -

The meaning of the fourth element depends on the operation.

-
    -
  • For set it is the value an option has been set to.
  • -
  • For list-add it is the new value that has been added to a -list option.
  • -
  • For rename it is the new name of an option that has been -renamed.
  • -
- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

LuCI.uci.SectionObjectObject.<string, (boolean|number|string|Array.<string>)>

-
- - -
-
- -
-

A section object represents the options and their corresponding values -enclosed within a configuration section, as well as some additional -meta data such as sort indexes and internal ID.

-

Any internal metadata fields are prefixed with a dot which is isn't -an allowed character for normal option names.

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
.anonymous - - -boolean - - - -

The .anonymous property specifies whether the configuration is -anonymous (true) or named (false).

.index - - -number - - - -

The .index property specifes the sort order of the section.

.name - - -string - - - -

The .name property holds the name of the section object. It may be -either an anonymous ID in the form cfgXXXXXX or newXXXXXX with X -being a hexadecimal digit or a string holding the name of the section.

.type - - -string - - - -

The .type property contains the type of the corresponding uci -section.

* - - -string -| - -Array.<string> - - - -

A section object may contain an arbitrary number of further properties -representing the uci option enclosed in the section.

-

All option property names will be in the form [A-Za-z0-9_]+ and -either contain a string value or an array of strings, in case the -underlying option is an UCI list.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - -
-
-

- - sectionsFn(section, sid) -

- - - - -
- - -
-
- - -
-

The sections callback is invoked for each section found within -the given configuration and receives the section object and its -associated name as arguments.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
section - - -LuCI.uci.SectionObject - - - - - -

The section object.

sid - - -string - - - - - -

The name or ID of the section.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.AbstractElement.html b/docs/jsapi/LuCI.ui.AbstractElement.html deleted file mode 100644 index b76d2bb805..0000000000 --- a/docs/jsapi/LuCI.ui.AbstractElement.html +++ /dev/null @@ -1,5093 +0,0 @@ - - - - - Class: AbstractElement - - - - - - - - - - - - - - - - - -
- - -
-

Class: AbstractElement

- - - - -
- -
-

- LuCI.ui. - - AbstractElement -

- -

The AbstractElement class serves as abstract base for the different widgets -implemented by LuCI.ui. It provides the common logic for getting and -setting values, for checking the validity state and for wiring up required -events.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.AbstractElement. To import -it in external JavaScript, use L.require("ui").then(...) and access the -AbstractElement property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.AbstractElement() -

- - -
- ui.js, line 17 -
- -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - getValue(){string|Array.<string>|null} -

- - -
- ui.js, line 81 -
- -
- - -
-
- - -
-

Read the current value of the input widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - Array.<string> - | - - null - - - The current value of the input element. For simple inputs like text -fields or selects, the return value type will be a - possibly empty - -string. Complex widgets such as DynamicList instances may result in -an array of strings or null for unset values.
- - - - -
- - - -
-
-

- - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - render(){Node} -

- - - - -
- - -
-
- - -
-

Render the widget, setup event listeners and return resulting markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node or DocumentFragment containing the rendered -widget markup.
- - - - -
- - - -
-
-

- - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - setValue(value) -

- - -
- ui.js, line 99 -
- -
- - -
-
- - -
-

Set the current value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The value to set the input element to. For simple inputs like text -fields or selects, the value should be a - possibly empty - string. -Complex widgets such as DynamicList instances may accept string array -or null values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.AbstractElement.InitOptionsObject

-
- - -
-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
id - - -string - - - - - - <optional>
- - - -
- -

Specifies the widget ID to use. It will be used as HTML id attribute -on the toplevel widget DOM node.

name - - -string - - - - - - <optional>
- - - -
- -

Specifies the widget name which is set as HTML name attribute on the -corresponding <input> element.

optional - - -boolean - - - - - - <optional>
- - - -
- - true - -

Specifies whether the input field allows empty values.

datatype - - -string - - - - - - <optional>
- - - -
- - string - -

An expression describing the input data validation constraints. -It defaults to string which will allow any value. -See LuCI.validation for details on the expression format.

validator - - -function - - - - - - <optional>
- - - -
- -

Specifies a custom validator function which is invoked after the -standard validation constraints are checked. The function should return -true to accept the given input value. Any other return value type is -converted to a string and treated as validation error message.

disabled - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether the widget should be rendered in disabled state -(true) or not (false). Disabled widgets cannot be interacted with -and are displayed in a slightly faded style.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.Checkbox.html b/docs/jsapi/LuCI.ui.Checkbox.html deleted file mode 100644 index 66ede807fe..0000000000 --- a/docs/jsapi/LuCI.ui.Checkbox.html +++ /dev/null @@ -1,5205 +0,0 @@ - - - - - Class: Checkbox - - - - - - - - - - - - - - - - - -
- - -
-

Class: Checkbox

- - - - -
- -
-

- LuCI.ui. - - Checkbox -

- -

The Checkbox class implements a simple checkbox input field.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.Checkbox. To import it in -external JavaScript, use L.require("ui").then(...) and access the -Checkbox property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.Checkbox(value, options) -

- - - - -
- - -
-
- - -
-

Instantiate a checkbox widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string - - - - - - null - - - - - optional - - - - - -

The initial input value.

options - - -LuCI.ui.Checkbox.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the input.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - inherited - - getValue(){string|Array.<string>|null} -

- - - - -
- - -
-
- - -
-

Read the current value of the input widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - Array.<string> - | - - null - - - The current value of the input element. For simple inputs like text -fields or selects, the return value type will be a - possibly empty - -string. Complex widgets such as DynamicList instances may result in -an array of strings or null for unset values.
- - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - isChecked(){boolean} -

- - - - -
- - -
-
- - -
-

Test whether the checkbox is currently checked.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the checkbox is currently checked, otherwise false.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - render(){Node} -

- - - - -
- - -
-
- - -
-

Render the widget, setup event listeners and return resulting markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node or DocumentFragment containing the rendered -widget markup.
- - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setValue(value) -

- - - - -
- - -
-
- - -
-

Set the current value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The value to set the input element to. For simple inputs like text -fields or selects, the value should be a - possibly empty - string. -Complex widgets such as DynamicList instances may accept string array -or null values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.Checkbox.InitOptionsLuCI.ui.AbstractElement.InitOptions

-
- - -
-
- -
-

In addition to the AbstractElement.InitOptions -the following properties are recognized:

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
value_enabled - - -string - - - - - - <optional>
- - - -
- - 1 - -

Specifies the value corresponding to a checked checkbox.

value_disabled - - -string - - - - - - <optional>
- - - -
- - 0 - -

Specifies the value corresponding to an unchecked checkbox.

hiddenname - - -string - - - - - - <optional>
- - - -
- -

Specifies the HTML name attribute of the hidden input backing the -checkbox. This is a legacy property existing for compatibility reasons, -it is required for HTML based form submissions.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.ComboButton.html b/docs/jsapi/LuCI.ui.ComboButton.html deleted file mode 100644 index 70d72cebb3..0000000000 --- a/docs/jsapi/LuCI.ui.ComboButton.html +++ /dev/null @@ -1,5235 +0,0 @@ - - - - - Class: ComboButton - - - - - - - - - - - - - - - - - -
- - -
-

Class: ComboButton

- - - - -
- -
-

- LuCI.ui. - - ComboButton -

- -

The ComboButton class implements a button element which can be expanded -into a dropdown to chose from a set of different action choices.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.ComboButton. To import it in -external JavaScript, use L.require("ui").then(...) and access the -ComboButton property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.ComboButton(value, choices, options) -

- - - - -
- - -
-
- - -
-

Instantiate a combo button widget offering multiple action choices.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string -| - -Array.<string> - - - - - - null - - - - - optional - - - - - -

The initial input value(s).

choices - - -Object.<string, *> - - - - - - - - - - - - -

Object containing the selectable choices of the widget. The object keys -serve as values for the different choices while the values are used as -choice labels.

options - - -LuCI.ui.ComboButton.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the button.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - inherited - - addChoices(values, labels) -

- - - - -
- - -
-
- - -
-

Add new choices to the dropdown menu.

-

This function adds further choices to an existing dropdown menu, -ignoring choice values which are already present.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
values - - -Array.<string> - - - - - -

The choice values to add to the dropdown widget.

labels - - -Object.<string, *> - - - - - -

The choice label values to use when adding dropdown choices. If no -label is found for a particular choice value, the value itself is used -as label text. Choice labels may be any valid value accepted by -LuCI.dom#content.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - clearChoices(reset_value) -

- - - - -
- - -
-
- - -
-

Remove all existing choices from the dropdown menu.

-

This function removes all preexisting dropdown choices from the widget, -keeping only choices currently being selected unless reset_values is -given, in which case all choices and deselected and removed.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
reset_value - - -boolean - - - - - - false - - - - - optional - - - - - -

If set to true, deselect and remove selected choices as well instead -of keeping them.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - closeAllDropdowns() -

- - - - -
- - -
-
- - -
-

Close all open dropdown widgets in the current document.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.ComboButton.InitOptionsLuCI.ui.Dropdown.InitOptions

-
- - -
-
- -
-

ComboButtons support the same properties as -Dropdown.InitOptions but enforce -specific values for some properties and add aditional button specific -properties.

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
multiple - - -boolean - - - - - - - - - - false - -

Since ComboButtons never allow selecting multiple actions, this property -is forcibly set to false.

create - - -boolean - - - - - - - - - - false - -

Since ComboButtons never allow creating custom choices, this property -is forcibly set to false.

optional - - -boolean - - - - - - - - - - false - -

Since ComboButtons must always select one action, this property is -forcibly set to false.

classes - - -Object.<string, string> - - - - - - <optional>
- - - -
- -

Specifies a mapping of choice values to CSS class names. If an action -choice is selected by the user and if a corresponding entry exists in -the classes object, the class names corresponding to the selected -value are set on the button element.

-

This is useful to apply different button styles, such as colors, to the -combined button depending on the selected action.

click - - -function - - - - - - <optional>
- - - -
- -

Specifies a handler function to invoke when the user clicks the button. -This function will be called with the button DOM node as this context -and receive the DOM click event as first as well as the selected action -choice value as second argument.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.Combobox.html b/docs/jsapi/LuCI.ui.Combobox.html deleted file mode 100644 index 8ff47fc9fb..0000000000 --- a/docs/jsapi/LuCI.ui.Combobox.html +++ /dev/null @@ -1,5138 +0,0 @@ - - - - - Class: Combobox - - - - - - - - - - - - - - - - - -
- - -
-

Class: Combobox

- - - - -
- -
-

- LuCI.ui. - - Combobox -

- -

The Combobox class implements a rich, stylable dropdown menu which allows -to enter custom values. Historically, comboboxes used to be a dedicated -widget type in LuCI but nowadays they are direct aliases of dropdown widgets -with a set of enforced default properties for easier instantiation.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.Combobox. To import it in -external JavaScript, use L.require("ui").then(...) and access the -Combobox property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.Combobox(value, choices, options) -

- - - - -
- - -
-
- - -
-

Instantiate a rich dropdown choice widget allowing custom values.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string -| - -Array.<string> - - - - - - null - - - - - optional - - - - - -

The initial input value(s).

choices - - -Object.<string, *> - - - - - - - - - - - - -

Object containing the selectable choices of the widget. The object keys -serve as values for the different choices while the values are used as -choice labels.

options - - -LuCI.ui.Combobox.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the dropdown.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - inherited - - addChoices(values, labels) -

- - - - -
- - -
-
- - -
-

Add new choices to the dropdown menu.

-

This function adds further choices to an existing dropdown menu, -ignoring choice values which are already present.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
values - - -Array.<string> - - - - - -

The choice values to add to the dropdown widget.

labels - - -Object.<string, *> - - - - - -

The choice label values to use when adding dropdown choices. If no -label is found for a particular choice value, the value itself is used -as label text. Choice labels may be any valid value accepted by -LuCI.dom#content.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - clearChoices(reset_value) -

- - - - -
- - -
-
- - -
-

Remove all existing choices from the dropdown menu.

-

This function removes all preexisting dropdown choices from the widget, -keeping only choices currently being selected unless reset_values is -given, in which case all choices and deselected and removed.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
reset_value - - -boolean - - - - - - false - - - - - optional - - - - - -

If set to true, deselect and remove selected choices as well instead -of keeping them.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - closeAllDropdowns() -

- - - - -
- - -
-
- - -
-

Close all open dropdown widgets in the current document.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.Combobox.InitOptionsLuCI.ui.Dropdown.InitOptions

-
- - -
-
- -
-

Comboboxes support the same properties as -Dropdown.InitOptions but enforce -specific values for the following properties:

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
multiple - - -boolean - - - - - - false - -

Since Comboboxes never allow selecting multiple values, this property -is forcibly set to false.

create - - -boolean - - - - - - true - -

Since Comboboxes always allow custom choice values, this property is -forcibly set to true.

optional - - -boolean - - - - - - true - -

Since Comboboxes are always optional, this property is forcibly set to -true.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.Dropdown.html b/docs/jsapi/LuCI.ui.Dropdown.html deleted file mode 100644 index 83d71ead2f..0000000000 --- a/docs/jsapi/LuCI.ui.Dropdown.html +++ /dev/null @@ -1,5936 +0,0 @@ - - - - - Class: Dropdown - - - - - - - - - - - - - - - - - -
- - -
-

Class: Dropdown

- - - - -
- -
-

- LuCI.ui. - - Dropdown -

- -

The Dropdown class implements a rich, stylable dropdown menu which -supports non-text choice labels.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.Dropdown. To import it in -external JavaScript, use L.require("ui").then(...) and access the -Dropdown property of the class instance value.

- -
- -
-
- - - - -
-
- - - - - -
- - -
-
- - -
-

Instantiate a rich dropdown choice widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string -| - -Array.<string> - - - - - - null - - - - - optional - - - - - -

The initial input value(s).

choices - - -Object.<string, *> - - - - - - - - - - - - -

Object containing the selectable choices of the widget. The object keys -serve as values for the different choices while the values are used as -choice labels.

options - - -LuCI.ui.Dropdown.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the dropdown.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - addChoices(values, labels) -

- - - - -
- - -
-
- - -
-

Add new choices to the dropdown menu.

-

This function adds further choices to an existing dropdown menu, -ignoring choice values which are already present.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
values - - -Array.<string> - - - - - -

The choice values to add to the dropdown widget.

labels - - -Object.<string, *> - - - - - -

The choice label values to use when adding dropdown choices. If no -label is found for a particular choice value, the value itself is used -as label text. Choice labels may be any valid value accepted by -LuCI.dom#content.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - clearChoices(reset_value) -

- - - - -
- - -
-
- - -
-

Remove all existing choices from the dropdown menu.

-

This function removes all preexisting dropdown choices from the widget, -keeping only choices currently being selected unless reset_values is -given, in which case all choices and deselected and removed.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
reset_value - - -boolean - - - - - - false - - - - - optional - - - - - -

If set to true, deselect and remove selected choices as well instead -of keeping them.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - closeAllDropdowns() -

- - - - -
- - -
-
- - -
-

Close all open dropdown widgets in the current document.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - getValue(){string|Array.<string>|null} -

- - - - -
- - -
-
- - -
-

Read the current value of the input widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - Array.<string> - | - - null - - - The current value of the input element. For simple inputs like text -fields or selects, the return value type will be a - possibly empty - -string. Complex widgets such as DynamicList instances may result in -an array of strings or null for unset values.
- - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - render(){Node} -

- - - - -
- - -
-
- - -
-

Render the widget, setup event listeners and return resulting markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node or DocumentFragment containing the rendered -widget markup.
- - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setValue(value) -

- - - - -
- - -
-
- - -
-

Set the current value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The value to set the input element to. For simple inputs like text -fields or selects, the value should be a - possibly empty - string. -Complex widgets such as DynamicList instances may accept string array -or null values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.Dropdown.InitOptionsLuCI.ui.AbstractElement.InitOptions

-
- - -
-
- -
-

In addition to the AbstractElement.InitOptions -the following properties are recognized:

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
optional - - -boolean - - - - - - <optional>
- - - -
- - true - -

Specifies whether the dropdown selection is optional. In contrast to -other widgets, the optional constraint of dropdowns works differently; -instead of marking the widget invalid on empty values when set to false, -the user is not allowed to deselect all choices.

-

For single value dropdowns that means that no empty "please select" -choice is offered and for multi value dropdowns, the last selected choice -may not be deselected without selecting another choice first.

multiple - - -boolean - - - - - - <optional>
- - - -
- -

Specifies whether multiple choice values may be selected. It defaults -to true when an array is passed as input value to the constructor.

sort - - -boolean -| - -Array.<string> - - - - - - <optional>
- - - -
- - false - -

Specifies if and how to sort choice values. If set to true, the choice -values will be sorted alphabetically. If set to an array of strings, the -choice sort order is derived from the array.

select_placeholder - - -string - - - - - - <optional>
- - - -
- - -- Please choose -- - -

Specifies a placeholder text which is displayed when no choice is -selected yet.

custom_placeholder - - -string - - - - - - <optional>
- - - -
- - -- custom -- - -

Specifies a placeholder text which is displayed in the text input -field allowing to enter custom choice values. Only applicable if the -create option is set to true.

create - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether custom choices may be entered into the dropdown -widget.

create_query - - -string - - - - - - <optional>
- - - -
- - .create-item-input - -

Specifies a CSS selector expression used to find the input element -which is used to enter custom choice values. This should not normally -be used except by widgets derived from the Dropdown class.

create_template - - -string - - - - - - <optional>
- - - -
- - script[type="item-template"] - -

Specifies a CSS selector expression used to find an HTML element -serving as template for newly added custom choice values.

-

Any {{value}} placeholder string within the template elements text -content will be replaced by the user supplied choice value, the -resulting string is parsed as HTML and appended to the end of the -choice list. The template markup may specify one HTML element with a -data-label-placeholder attribute which is replaced by a matching -label value from the choices object or with the user supplied value -itself in case choices contains no matching choice label.

-

If the template element is not found or if no create_template selector -expression is specified, the default markup for newly created elements is -<li data-value="{{value}}"><span data-label-placeholder="true" /></li>.

create_markup - - -string - - - - - - <optional>
- - - -
- -

This property allows specifying the markup for custom choices directly -instead of referring to a template element through CSS selectors.

-

Apart from that it works exactly like create_template.

display_items - - -number - - - - - - <optional>
- - - -
- - 3 - -

Specifies the maximum amount of choice labels that should be shown in -collapsed dropdown state before further selected choices are cut off.

-

Only applicable when multiple is true.

dropdown_items - - -number - - - - - - <optional>
- - - -
- - -1 - -

Specifies the maximum amount of choices that should be shown when the -dropdown is open. If the amount of available choices exceeds this number, -the dropdown area must be scrolled to reach further items.

-

If set to -1, the dropdown menu will attempt to show all choice values -and only resort to scrolling if the amount of choices exceeds the available -screen space above and below the dropdown widget.

placeholder - - -string - - - - - - <optional>
- - - -
- -

This property serves as a shortcut to set both select_placeholder and -custom_placeholder. Either of these properties will fallback to -placeholder if not specified.

readonly - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether the custom choice input field should be rendered -readonly. Only applicable when create is true.

maxlength - - -number - - - - - - <optional>
- - - -
- -

Specifies the HTML maxlength attribute to set on the custom choice -<input> element. Note that this a legacy property that exists for -compatibility reasons. It is usually better to maxlength(N) validation -expression. Only applicable when create is true.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.DynamicList.html b/docs/jsapi/LuCI.ui.DynamicList.html deleted file mode 100644 index 9ceda34eaa..0000000000 --- a/docs/jsapi/LuCI.ui.DynamicList.html +++ /dev/null @@ -1,5313 +0,0 @@ - - - - - Class: DynamicList - - - - - - - - - - - - - - - - - -
- - -
-

Class: DynamicList

- - - - -
- -
-

- LuCI.ui. - - DynamicList -

- -

The DynamicList class implements a widget which allows the user to specify -an arbitrary amount of input values, either from free formed text input or -from a set of predefined choices.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.DynamicList. To import it in -external JavaScript, use L.require("ui").then(...) and access the -DynamicList property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.DynamicList(value, choices, options) -

- - - - -
- - -
-
- - -
-

Instantiate a dynamic list widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string -| - -Array.<string> - - - - - - null - - - - - optional - - - - - -

The initial input value(s).

choices - - -Object.<string, *> - - - - - - - - - optional - - - - - -

Object containing the selectable choices of the widget. The object keys -serve as values for the different choices while the values are used as -choice labels. If omitted, no default choices are presented to the user, -instead a plain text input field is rendered allowing the user to add -arbitrary values to the dynamic list.

options - - -LuCI.ui.DynamicList.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the dynamic list.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - addChoices(values, labels) -

- - - - -
- - -
-
- - -
-

Add new suggested choices to the dynamic list.

-

This function adds further choices to an existing dynamic list, -ignoring choice values which are already present.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
values - - -Array.<string> - - - - - -

The choice values to add to the dynamic lists suggestion dropdown.

labels - - -Object.<string, *> - - - - - -

The choice label values to use when adding suggested choices. If no -label is found for a particular choice value, the value itself is used -as label text. Choice labels may be any valid value accepted by -LuCI.dom#content.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - clearChoices() -

- - - - -
- - -
-
- - -
-

Remove all existing choices from the dynamic list.

-

This function removes all preexisting suggested choices from the widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - getValue(){string|Array.<string>|null} -

- - - - -
- - -
-
- - -
-

Read the current value of the input widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - Array.<string> - | - - null - - - The current value of the input element. For simple inputs like text -fields or selects, the return value type will be a - possibly empty - -string. Complex widgets such as DynamicList instances may result in -an array of strings or null for unset values.
- - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - render(){Node} -

- - - - -
- - -
-
- - -
-

Render the widget, setup event listeners and return resulting markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node or DocumentFragment containing the rendered -widget markup.
- - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setValue(value) -

- - - - -
- - -
-
- - -
-

Set the current value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The value to set the input element to. For simple inputs like text -fields or selects, the value should be a - possibly empty - string. -Complex widgets such as DynamicList instances may accept string array -or null values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.DynamicList.InitOptionsLuCI.ui.Dropdown.InitOptions

-
- - -
-
- -
-

In case choices are passed to the dynamic list contructor, the widget -supports the same properties as Dropdown.InitOptions -but enforces specific values for some dropdown properties.

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
multiple - - -boolean - - - - - - false - -

Since dynamic lists never allow selecting multiple choices when adding -another list item, this property is forcibly set to false.

optional - - -boolean - - - - - - true - -

Since dynamic lists use an embedded dropdown to present a list of -predefined choice values, the dropdown must be made optional to allow -it to remain unselected.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.FileUpload.html b/docs/jsapi/LuCI.ui.FileUpload.html deleted file mode 100644 index 38ce235281..0000000000 --- a/docs/jsapi/LuCI.ui.FileUpload.html +++ /dev/null @@ -1,5162 +0,0 @@ - - - - - Class: FileUpload - - - - - - - - - - - - - - - - - -
- - -
-

Class: FileUpload

- - - - -
- -
-

- LuCI.ui. - - FileUpload -

- -

The FileUpload class implements a widget which allows the user to upload, -browse, select and delete files beneath a predefined remote directory.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.FileUpload. To import it in -external JavaScript, use L.require("ui").then(...) and access the -FileUpload property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.FileUpload(value, options) -

- - - - -
- - -
-
- - -
-

Instantiate a file upload widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string -| - -Array.<string> - - - - - - null - - - - - optional - - - - - -

The initial input value.

options - - -LuCI.ui.DynamicList.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the file -upload control.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - inherited - - getValue(){string|Array.<string>|null} -

- - - - -
- - -
-
- - -
-

Read the current value of the input widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - Array.<string> - | - - null - - - The current value of the input element. For simple inputs like text -fields or selects, the return value type will be a - possibly empty - -string. Complex widgets such as DynamicList instances may result in -an array of strings or null for unset values.
- - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - render(){Node} -

- - - - -
- - -
-
- - -
-

Render the widget, setup event listeners and return resulting markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node or DocumentFragment containing the rendered -widget markup.
- - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setValue(value) -

- - - - -
- - -
-
- - -
-

Set the current value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The value to set the input element to. For simple inputs like text -fields or selects, the value should be a - possibly empty - string. -Complex widgets such as DynamicList instances may accept string array -or null values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.FileUpload.InitOptionsLuCI.ui.AbstractElement.InitOptions

-
- - -
-
- -
-

In addition to the AbstractElement.InitOptions -the following properties are recognized:

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
show_hidden - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether hidden files should be displayed when browsing remote -files. Note that this is not a security feature, hidden files are always -present in the remote file listings received, this option merely controls -whether they're displayed or not.

enable_upload - - -boolean - - - - - - <optional>
- - - -
- - true - -

Specifies whether the widget allows the user to upload files. If set to -false, only existing files may be selected. Note that this is not a -security feature. Whether file upload requests are accepted remotely -depends on the ACL setup for the current session. This option merely -controls whether the upload controls are rendered or not.

enable_remove - - -boolean - - - - - - <optional>
- - - -
- - true - -

Specifies whether the widget allows the user to delete remove files. -If set to false, existing files may not be removed. Note that this is -not a security feature. Whether file delete requests are accepted -remotely depends on the ACL setup for the current session. This option -merely controls whether the file remove controls are rendered or not.

root_directory - - -string - - - - - - <optional>
- - - -
- - /etc/luci-uploads - -

Specifies the remote directory the upload and file browsing actions take -place in. Browsing to directories outside of the root directory is -prevented by the widget. Note that this is not a security feature. -Whether remote directories are browseable or not solely depends on the -ACL setup for the current session.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.Hiddenfield.html b/docs/jsapi/LuCI.ui.Hiddenfield.html deleted file mode 100644 index cbba5efa47..0000000000 --- a/docs/jsapi/LuCI.ui.Hiddenfield.html +++ /dev/null @@ -1,4916 +0,0 @@ - - - - - Class: Hiddenfield - - - - - - - - - - - - - - - - - -
- - -
-

Class: Hiddenfield

- - - - -
- -
-

- LuCI.ui. - - Hiddenfield -

- -

The Hiddenfield class implements an HTML <input type="hidden"> field -which allows to store form data without exposing it to the user.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.Hiddenfield. To import it in -external JavaScript, use L.require("ui").then(...) and access the -Hiddenfield property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.Hiddenfield(value, options) -

- - - - -
- - -
-
- - -
-

Instantiate a hidden input field widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string -| - -Array.<string> - - - - - - null - - - - - optional - - - - - -

The initial input value.

options - - -LuCI.ui.AbstractElement.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the hidden input.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - inherited - - getValue(){string|Array.<string>|null} -

- - - - -
- - -
-
- - -
-

Read the current value of the input widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - Array.<string> - | - - null - - - The current value of the input element. For simple inputs like text -fields or selects, the return value type will be a - possibly empty - -string. Complex widgets such as DynamicList instances may result in -an array of strings or null for unset values.
- - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - render(){Node} -

- - - - -
- - -
-
- - -
-

Render the widget, setup event listeners and return resulting markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node or DocumentFragment containing the rendered -widget markup.
- - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setValue(value) -

- - - - -
- - -
-
- - -
-

Set the current value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The value to set the input element to. For simple inputs like text -fields or selects, the value should be a - possibly empty - string. -Complex widgets such as DynamicList instances may accept string array -or null values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.Select.html b/docs/jsapi/LuCI.ui.Select.html deleted file mode 100644 index 6d1d1bd68e..0000000000 --- a/docs/jsapi/LuCI.ui.Select.html +++ /dev/null @@ -1,5265 +0,0 @@ - - - - - Class: Select - - - - - - - - - - - - - - - - - -
- - -
-

Class: Select

- - - - -
- -
-

- LuCI.ui. - - Select -

- -

The Select class implements either a traditional HTML <select> element -or a group of checkboxes or radio buttons, depending on whether multiple -values are enabled or not.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.Select. To import it in -external JavaScript, use L.require("ui").then(...) and access the -Select property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.Select(value, choices, options) -

- - - - -
- - -
-
- - -
-

Instantiate a select dropdown or checkbox/radiobutton group.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string -| - -Array.<string> - - - - - - null - - - - - optional - - - - - -

The initial input value(s).

choices - - -Object.<string, string> - - - - - - - - - - - - -

Object containing the selectable choices of the widget. The object keys -serve as values for the different choices while the values are used as -choice labels.

options - - -LuCI.ui.Select.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the inputs.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - inherited - - getValue(){string|Array.<string>|null} -

- - - - -
- - -
-
- - -
-

Read the current value of the input widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - Array.<string> - | - - null - - - The current value of the input element. For simple inputs like text -fields or selects, the return value type will be a - possibly empty - -string. Complex widgets such as DynamicList instances may result in -an array of strings or null for unset values.
- - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - render(){Node} -

- - - - -
- - -
-
- - -
-

Render the widget, setup event listeners and return resulting markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node or DocumentFragment containing the rendered -widget markup.
- - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setValue(value) -

- - - - -
- - -
-
- - -
-

Set the current value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The value to set the input element to. For simple inputs like text -fields or selects, the value should be a - possibly empty - string. -Complex widgets such as DynamicList instances may accept string array -or null values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.Select.InitOptionsLuCI.ui.AbstractElement.InitOptions

-
- - -
-
- -
-

In addition to the AbstractElement.InitOptions -the following properties are recognized:

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
multiple - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether multiple choice values may be selected.

widget - - -string - - - - - - <optional>
- - - -
- - select - -

Specifies the kind of widget to render. May be either select or -individual. When set to select an HTML <select> element will be -used, otherwise a group of checkbox or radio button elements is created, -depending on the value of the multiple option.

orientation - - -string - - - - - - <optional>
- - - -
- - horizontal - -

Specifies whether checkbox / radio button groups should be rendered -in a horizontal or vertical manner. Does not apply to the select -widget type.

sort - - -boolean -| - -Array.<string> - - - - - - <optional>
- - - -
- - false - -

Specifies if and how to sort choice values. If set to true, the choice -values will be sorted alphabetically. If set to an array of strings, the -choice sort order is derived from the array.

size - - -number - - - - - - <optional>
- - - -
- -

Specifies the HTML size attribute to set on the <select> element. -Only applicable to the select widget type.

placeholder - - -string - - - - - - <optional>
- - - -
- - -- Please choose -- - -

Specifies a placeholder text which is displayed when no choice is -selected yet. Only applicable to the select widget type.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.Textarea.html b/docs/jsapi/LuCI.ui.Textarea.html deleted file mode 100644 index 1a87f6c8d1..0000000000 --- a/docs/jsapi/LuCI.ui.Textarea.html +++ /dev/null @@ -1,5214 +0,0 @@ - - - - - Class: Textarea - - - - - - - - - - - - - - - - - -
- - -
-

Class: Textarea

- - - - -
- -
-

- LuCI.ui. - - Textarea -

- -

The Textarea class implements a multiline text area input field.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.Textarea. To import it in -external JavaScript, use L.require("ui").then(...) and access the -Textarea property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.Textarea(value, options) -

- - - - -
- - -
-
- - -
-

Instantiate a textarea widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string - - - - - - null - - - - - optional - - - - - -

The initial input value.

options - - -LuCI.ui.Textarea.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the input.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - inherited - - getValue(){string|Array.<string>|null} -

- - - - -
- - -
-
- - -
-

Read the current value of the input widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - Array.<string> - | - - null - - - The current value of the input element. For simple inputs like text -fields or selects, the return value type will be a - possibly empty - -string. Complex widgets such as DynamicList instances may result in -an array of strings or null for unset values.
- - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - render(){Node} -

- - - - -
- - -
-
- - -
-

Render the widget, setup event listeners and return resulting markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node or DocumentFragment containing the rendered -widget markup.
- - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setValue(value) -

- - - - -
- - -
-
- - -
-

Set the current value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The value to set the input element to. For simple inputs like text -fields or selects, the value should be a - possibly empty - string. -Complex widgets such as DynamicList instances may accept string array -or null values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.Textarea.InitOptionsLuCI.ui.AbstractElement.InitOptions

-
- - -
-
- -
-

In addition to the AbstractElement.InitOptions -the following properties are recognized:

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
readonly - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether the input widget should be rendered readonly.

placeholder - - -string - - - - - - <optional>
- - - -
- -

Specifies the HTML placeholder attribute which is displayed when the -corresponding <textarea> element is empty.

monospace - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether a monospace font should be forced for the textarea -contents.

cols - - -number - - - - - - <optional>
- - - -
- -

Specifies the HTML cols attribute to set on the corresponding -<textarea> element.

rows - - -number - - - - - - <optional>
- - - -
- -

Specifies the HTML rows attribute to set on the corresponding -<textarea> element.

wrap - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether the HTML wrap attribute should be set.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.Textfield.html b/docs/jsapi/LuCI.ui.Textfield.html deleted file mode 100644 index 1e8f0b55a9..0000000000 --- a/docs/jsapi/LuCI.ui.Textfield.html +++ /dev/null @@ -1,5142 +0,0 @@ - - - - - Class: Textfield - - - - - - - - - - - - - - - - - -
- - -
-

Class: Textfield

- - - - -
- -
-

- LuCI.ui. - - Textfield -

- -

The Textfield class implements a standard single line text input field.

-

UI widget instances are usually not supposed to be created by view code -directly, instead they're implicitely created by LuCI.form when -instantiating CBI forms.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.Textfield. To import it in -external JavaScript, use L.require("ui").then(...) and access the -Textfield property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.Textfield(value, options) -

- - - - -
- - -
-
- - -
-

Instantiate a text input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
value - - -string - - - - - - null - - - - - optional - - - - - -

The initial input value.

options - - -LuCI.ui.Textfield.InitOptions - - - - - - - - - optional - - - - - -

Object describing the widget specific options to initialize the input.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - -

Extends

- - - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - inherited - - getValue(){string|Array.<string>|null} -

- - - - -
- - -
-
- - -
-

Read the current value of the input widget.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - string - | - - Array.<string> - | - - null - - - The current value of the input element. For simple inputs like text -fields or selects, the return value type will be a - possibly empty - -string. Complex widgets such as DynamicList instances may result in -an array of strings or null for unset values.
- - - - -
- - - -
-
-

- - inherited - - isChanged(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the input value was altered by the user.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the input value has been altered by the user or -false if it is unchaged. Note that if the user modifies the initial -value and changes it back to the original state, it is still reported -as changed.
- - - - -
- - - -
-
-

- - inherited - - isValid(){boolean} -

- - - - -
- - -
-
- - -
-

Check whether the current input value is valid.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the current input value is valid or false if it does -not meet the validation constraints.
- - - - -
- - - -
-
-

- - inherited - - registerEvents(targetNode, synevent, events) -

- - - - -
- - -
-
- - -
-

Dispatch a custom (synthetic) event in response to received events.

-

Sets up event handlers on the given target DOM node for the given event -names that dispatch a custom event of the given type to the widget root -DOM node.

-

The primary purpose of this function is to set up a series of custom -uniform standard events such as widget-update, validation-success, -validation-failure etc. which are triggered by various different -widget specific native DOM events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - -

Specifies the DOM node on which the native event listeners should be -registered.

synevent - - -string - - - - - -

The name of the custom event to dispatch to the widget root DOM node.

events - - -Array.<string> - - - - - -

The native DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - render(){Node} -

- - - - -
- - -
-
- - -
-

Render the widget, setup event listeners and return resulting markup.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node or DocumentFragment containing the rendered -widget markup.
- - - - -
- - - -
-
-

- - inherited - - setChangeEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may change the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to change completely, such as -change events in a select menu. In contrast to update events, such -change events will not trigger input value validation but they may cause -field dependencies to get re-evaluated and will mark the input widget -as dirty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setPlaceholder(value) -

- - - - -
- - -
-
- - -
-

Set the current placeholder value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The placeholder to set for the input element. Only applicable to text -inputs, not to radio buttons, selects or similar.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setUpdateEvents(targetNode, events) -

- - - - -
- - -
-
- - -
-

Setup listeners for native DOM events that may update the widget value.

-

Sets up event handlers on the given target DOM node for the given event -names which may cause the input value to update, such as keyup or -onclick events. In contrast to change events, such update events will -trigger input value validation.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
targetNode - - -Node - - - - - - - - - - -

Specifies the DOM node on which the event listeners should be registered.

events - - -string - - - - - - - - - - repeatable - - -

The DOM events for which event handlers should be registered.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - setValue(value) -

- - - - -
- - -
-
- - -
-

Set the current value of the input widget.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
value - - -string -| - -Array.<string> -| - -null - - - - - -

The value to set the input element to. For simple inputs like text -fields or selects, the value should be a - possibly empty - string. -Complex widgets such as DynamicList instances may accept string array -or null values.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - inherited - - triggerValidation() -

- - - - -
- - -
-
- - -
-

Force validation of the current input value.

-

Usually input validation is automatically triggered by various DOM events -bound to the input widget. In some cases it is required though to manually -trigger validation runs, e.g. when programmatically altering values.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.Textfield.InitOptionsLuCI.ui.AbstractElement.InitOptions

-
- - -
-
- -
-

In addition to the AbstractElement.InitOptions -the following properties are recognized:

-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDefaultDescription
password - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether the input should be rendered as concealed password field.

readonly - - -boolean - - - - - - <optional>
- - - -
- - false - -

Specifies whether the input widget should be rendered readonly.

maxlength - - -number - - - - - - <optional>
- - - -
- -

Specifies the HTML maxlength attribute to set on the corresponding -<input> element. Note that this a legacy property that exists for -compatibility reasons. It is usually better to maxlength(N) validation -expression.

placeholder - - -string - - - - - - <optional>
- - - -
- -

Specifies the HTML placeholder attribute which is displayed when the -corresponding <input> element is empty.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.changes.html b/docs/jsapi/LuCI.ui.changes.html deleted file mode 100644 index dff9edec45..0000000000 --- a/docs/jsapi/LuCI.ui.changes.html +++ /dev/null @@ -1,4096 +0,0 @@ - - - - - Class: changes - - - - - - - - - - - - - - - - - -
- - -
-

Class: changes

- - - - -
- -
-

- LuCI.ui. - - changes -

- -

The changes class encapsulates logic for visualizing, applying, -confirming and reverting staged UCI changesets.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.changes. To import it in -external JavaScript, use L.require("ui").then(...) and access the -changes property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.changes() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - apply(checked) -

- - - - -
- - -
-
- - -
-

Apply the staged configuration changes.

-

Start applying staged configuration changes and open a modal dialog -with a progress indication to prevent interaction with the view -during the apply process. The modal dialog will be automatically -closed and the current view reloaded once the apply process is -complete.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
checked - - -boolean - - - - - - false - - - - - optional - - - - - -

Whether to perform a checked (true) configuration apply or an -unchecked (false) one. -In case of a checked apply, the configuration changes must be -confirmed within a specific time interval, otherwise the device -will begin to roll back the changes in order to restore the previous -settings.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - displayChanges() -

- - - - -
- - -
-
- - -
-

Display the current changelog.

-

Open a modal dialog visualizing the currently staged UCI changes -and offer options to revert or apply the shown changes.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - renderChangeIndicator(changes) -

- - - - -
- - -
-
- - -
-

Update the change count indicator.

-

This function updates the UCI change count indicator from the given -UCI changeset structure.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
changes - - -Object.<string, Array.<LuCI.uci.ChangeRecord>> - - - - - -

The UCI changeset to count.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - revert() -

- - - - -
- - -
-
- - -
-

Revert the staged configuration changes.

-

Start reverting staged configuration changes and open a modal dialog -with a progress indication to prevent interaction with the view -during the revert process. The modal dialog will be automatically -closed and the current view reloaded once the revert process is -complete.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - setIndicator(numChanges) -

- - - - -
- - -
-
- - -
-

Set the change count indicator.

-

This function updates or hides the UCI change count indicator, -depending on the passed change count. When the count is greater -than 0, the change indicator is displayed or updated, otherwise it -is removed.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
numChanges - - -number - - - - - -

The number of changes to indicate.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.html b/docs/jsapi/LuCI.ui.html deleted file mode 100644 index 26cc0be867..0000000000 --- a/docs/jsapi/LuCI.ui.html +++ /dev/null @@ -1,6189 +0,0 @@ - - - - - Class: ui - - - - - - - - - - - - - - - - - -
- - -
-

Class: ui

- - - - -
- -
-

- LuCI. - - ui -

- -

Provides high level UI helper functionality. -To import the class in views, use 'require ui', to import it in -external JavaScript, use L.require("ui").then(...).

- -
- -
-
- - - - -
-
-

- - new LuCI.ui() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - -

Classes

- -
-
AbstractElement
-
- -
changes
-
- -
Checkbox
-
- -
Combobox
-
- -
ComboButton
-
- -
Dropdown
-
- -
DynamicList
-
- -
FileUpload
-
- -
Hiddenfield
-
- -
menu
-
- -
Select
-
- -
tabs
-
- -
Textarea
-
- -
Textfield
-
-
- - - - - - - -

Methods

- -
- -
-
-

- - addNotification(title, contents, classes){Node} -

- - - - -
- - -
-
- - -
-

Add a notification banner at the top of the current view.

-

A notification banner is an alert message usually displayed at the -top of the current view, spanning the entire availibe width. -Notification banners will stay in place until dismissed by the user. -Multiple banners may be shown at the same time.

-

Additional CSS class names may be passed to influence the appearence of -the banner. Valid values for the classes depend on the underlying theme.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
title - - -string - - - - - - - optional - - - - - -

The title of the notification banner. If null, no title element -will be rendered.

contents - - -* - - - - - - - - - - -

The contents to add to the notification banner. This should be a DOM -node or a document fragment in most cases. The value is passed as-is -to the dom.content() function - refer to its documentation for -applicable values.

classes - - -string - - - - - - - optional - - - - - repeatable - - -

A number of extra CSS class names which are set on the notification -banner element.

- - - -
- - - - - - - - - - - - - - - - - - - -
See:
-
-
    -
  • LuCI.dom.content
  • -
-
- - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node representing the notification banner element.
- - - - -
- - - -
-
-

- - addValidator(field, type, optional, vfunc, events){function} -

- - - - -
- - -
-
- - -
-

Add validation constraints to an input element.

-

Compile the given type expression and optional validator function into -a validation function and bind it to the specified input element events.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
field - - -Node - - - - - - - - - - - - -

The DOM input element node to bind the validation constraints to.

type - - -string - - - - - - - - - - - - -

The datatype specification to describe validation constraints. -Refer to the LuCI.validation class documentation for details.

optional - - -boolean - - - - - - false - - - - - optional - - - - - -

Specifies whether empty values are allowed (true) or not (false). -If an input element is not marked optional it must not be empty, -otherwise it will be marked as invalid.

vfunc - - -function - - - - - - - - - optional - - - - - -

Specifies a custom validation function which is invoked after the -other validation constraints are applied. The validation must return -true to accept the passed value. Any other return type is converted -to a string and treated as validation error message.

events - - -string - - - - - - blur, keyup - - - - - optional - - - - - repeatable - - -

The list of events to bind. Each received event will trigger a field -validation. If omitted, the keyup and blur events are bound by -default.

- - - -
- - - - - - - - - - - - - - - - - - - -
See:
-
-
    -
  • LuCI.validation
  • -
-
- - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - function - - - Returns the compiled validator function which can be used to manually -trigger field validation or to bind it to further events.
- - - - -
- - - -
-
-

- - awaitReconnect(hosts) -

- - - - -
- - -
-
- - -
-

Wait for device to come back online and reconnect to it.

-

Poll each given hostname or IP address and navigate to it as soon as -one of the addresses becomes reachable.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
hosts - - -string - - - - - - [window.location.host] - - - - - optional - - - - - repeatable - - -

The list of IP addresses and host names to check for reachability. -If omitted, the current value of window.location.host is used by -default.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - createHandlerFn(ctx, fn, extra_args){function|null} -

- - - - -
- - -
-
- - -
-

Create a pre-bound event handler function.

-

Generate and bind a function suitable for use in event handlers. The -generated function automatically disables the event source element -and adds an active indication to it by adding appropriate CSS classes.

-

It will also await any promises returned by the wrapped function and -re-enable the source element after the promises ran to completion.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ctx - - -* - - - - - - - - - - -

The this context to use for the wrapped function.

fn - - -function -| - -string - - - - - - - - - - -

Specifies the function to wrap. In case of a function value, the -function is used as-is. If a string is specified instead, it is looked -up in ctx to obtain the function to wrap. In both cases the bound -function will be invoked with ctx as this context

extra_args - - -* - - - - - - - - - - repeatable - - -

Any further parameter as passed as-is to the bound event handler -function in the same order as passed to createHandlerFn().

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - function - | - - null - - - Returns the pre-bound handler function which is suitable to be passed -to addEventListener(). Returns null if the given fn argument is -a string which could not be found in ctx or if ctx[fn] is not a -valid function value.
- - - - -
- - - -
-
-

- - hideIndicator(id){boolean} -

- - - - -
- - -
-
- - -
-

Remove an header area indicator.

-

This function removes the given indicator label from the header indicator -area. When the given indicator is not found, this function does nothing.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -string - - - - - -

The ID of the indicator to remove.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the indicator has been removed or false when the -requested indicator was not found.
- - - - -
- - - -
-
-

- - hideModal() -

- - - - -
- - -
-
- - -
-

Close the open modal overlay dialog.

-

This function will close an open modal dialog and restore the normal view -behaviour. It has no effect if no modal dialog is currently open.

-

Note that this function is stand-alone, it does not rely on this and -will not invoke other class functions so it suitable to be used as event -handler as-is without the need to bind it first.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - instantiateView(path){Promise.<LuCI.view>} -

- - - - -
- - -
-
- - -
-

Load specified view class path and set it up.

-

Transforms the given view path into a class name, requires it -using LuCI.require() and asserts that the -resulting class instance is a descendant of -LuCI.view.

-

By instantiating the view class, its corresponding contents are -rendered and included into the view area. Any runtime errors are -catched and rendered using LuCI.error().

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
path - - -string - - - - - -

The view path to render.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.view> - - - Returns a promise resolving to the loaded view instance.
- - - - -
- - - -
-
-

- - itemlist(node, items, separators){Node} -

- - - - -
- - -
-
- - -
-

Formats a series of label/value pairs into list-like markup.

-

This function transforms a flat array of alternating label and value -elements into a list-like markup, using the values in separators as -separators and appends the resulting nodes to the given parent DOM node.

-

Each label is suffixed with : and wrapped into a <strong> tag, the -<strong> element and the value corresponding to the label are -subsequently wrapped into a <span class="nowrap"> element.

-

The resulting <span> element tuples are joined by the given separators -to form the final markup which is appened to the given parent DOM node.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
node - - -Node - - - - - - - - - - - - -

The parent DOM node to append the markup to. Any previous child elements -will be removed.

items - - -Array.<*> - - - - - - - - - - - - -

An alternating array of labels and values. The label values will be -converted to plain strings, the values are used as-is and may be of -any type accepted by LuCI.dom.content().

separators - - -* -| - -Array.<*> - - - - - - [E('br')] - - - - - optional - - - - - -

A single value or an array of separator values to separate each -label/value pair with. The function will cycle through the separators -when joining the pairs. If omitted, the default separator is a sole HTML -<br> element. Separator values are used as-is and may be of any type -accepted by LuCI.dom.content().

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns the parent DOM node the formatted markup has been added to.
- - - - -
- - - -
-
-

- - pingDevice(proto, host){Promise.<Event>} -

- - - - -
- - -
-
- - -
-

Perform a device connectivity test.

-

Attempt to fetch a well known ressource from the remote device via HTTP -in order to test connectivity. This function is mainly useful to wait -for the router to come back online after a reboot or reconfiguration.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
proto - - -string - - - - - - http - - - - - optional - - - - - -

The protocol to use for fetching the resource. May be either http -(the default) or https.

host - - -string - - - - - - window.location.host - - - - - optional - - - - - -

Override the host address to probe. By default the current host as seen -in the address bar is probed.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<Event> - - - Returns a promise resolving to a load event in case the device is -reachable or rejecting with an error event in case it is not reachable -or rejecting with null when the connectivity check timed out.
- - - - -
- - - -
-
-

- - showIndicator(id, label, handler, style){boolean} -

- - - - -
- - -
-
- - -
-

Display or update an header area indicator.

-

An indicator is a small label displayed in the header area of the screen -providing few amounts of status information such as item counts or state -toggle indicators.

-

Multiple indicators may be shown at the same time and indicator labels -may be made clickable to display extended information or to initiate -further actions.

-

Indicators can either use a default active or a less accented inactive -style which is useful for indicators representing state toggles.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
id - - -string - - - - - - - - - - - - -

The ID of the indicator. If an indicator with the given ID already exists, -it is updated with the given label and style.

label - - -string - - - - - - - - - - - - -

The text to display in the indicator label.

handler - - -function - - - - - - - - - optional - - - - - -

A handler function to invoke when the indicator label is clicked/touched -by the user. If omitted, the indicator is not clickable/touchable.

-

Note that this parameter only applies to new indicators, when updating -existing labels it is ignored.

style - - -string - - - - - - active - - - - - optional - - - - - -

The indicator style to use. May be either active or inactive.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true when the indicator has been updated or false when no -changes were made.
- - - - -
- - - -
-
-

- - showModal(title, contents, classes){Node} -

- - - - -
- - -
-
- - -
-

Display a modal overlay dialog with the specified contents.

-

The modal overlay dialog covers the current view preventing interaction -with the underlying view contents. Only one modal dialog instance can -be opened. Invoking showModal() while a modal dialog is already open will -replace the open dialog with a new one having the specified contents.

-

Additional CSS class names may be passed to influence the appearence of -the dialog. Valid values for the classes depend on the underlying theme.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
title - - -string - - - - - - - optional - - - - - -

The title of the dialog. If null, no title element will be rendered.

contents - - -* - - - - - - - - - - -

The contents to add to the modal dialog. This should be a DOM node or -a document fragment in most cases. The value is passed as-is to the -dom.content() function - refer to its documentation for applicable -values.

classes - - -string - - - - - - - optional - - - - - repeatable - - -

A number of extra CSS class names which are set on the modal dialog -element.

- - - -
- - - - - - - - - - - - - - - - - - - -
See:
-
-
    -
  • LuCI.dom.content
  • -
-
- - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - - - Returns a DOM Node representing the modal dialog element.
- - - - -
- - - -
-
-

- - uploadFile(path, progessStatusNode){Promise.<LuCI.ui.FileUploadReply>} -

- - - - -
- - -
-
- - -
-

Display a modal file upload prompt.

-

This function opens a modal dialog prompting the user to select and -upload a file to a predefined remote destination path.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
path - - -string - - - - - - - - - - -

The remote file path to upload the local file to.

progessStatusNode - - -Node - - - - - - - optional - - - - - -

An optional DOM text node whose content text is set to the progress -percentage value during file upload.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.ui.FileUploadReply> - - - Returns a promise resolving to a file upload status object on success -or rejecting with an error in case the upload failed or has been -cancelled by the user.
- - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.FileUploadReplyObject

-
- - -
-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -string - - - -

Name of the uploaded file without directory components

size - - -number - - - -

Size of the uploaded file in bytes

checksum - - -string - - - -

The MD5 checksum of the received file data

sha256sum - - -string - - - -

The SHA256 checksum of the received file data

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.menu.html b/docs/jsapi/LuCI.ui.menu.html deleted file mode 100644 index 2b63fe159b..0000000000 --- a/docs/jsapi/LuCI.ui.menu.html +++ /dev/null @@ -1,4143 +0,0 @@ - - - - - Class: menu - - - - - - - - - - - - - - - - - -
- - -
-

Class: menu

- - - - -
- -
-

- LuCI.ui. - - menu -

- -

Handles menus.

- -
- -
-
- - - - -
-
- - - - - -
- - -
-
- - -
-

Handle menu.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - flushCache() -

- - - - -
- - -
-
- - -
-

Flush the internal menu cache to force loading a new structure on the -next page load.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - getChildren(node){Array.<LuCI.ui.menu.MenuNode>} -

- - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
node - - -LuCI.ui.menu.MenuNode - - - - - - - optional - - - - - -

The menu node to retrieve the children for. Defaults to the menu's -internal root node if omitted.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Array.<LuCI.ui.menu.MenuNode> - - - Returns an array of child menu nodes.
- - - - -
- - - -
-
-

- - load(){Promise.<LuCI.ui.menu.MenuNode>} -

- - - - -
- - -
-
- - -
-

Load and cache current menu tree.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<LuCI.ui.menu.MenuNode> - - - Returns a promise resolving to the root element of the menu tree.
- - - - -
- -
- - - -

Type Definitions

- -
- -
-
-

LuCI.ui.menu.MenuNodeObject

-
- - -
-
- - - -
- - -
Properties:
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeArgumentDescription
name - - -string - - - - - - - -

The internal name of the node, as used in the URL

order - - -number - - - - - - - -

The sort index of the menu node

title - - -string - - - - - - <optional>
- - - -

The title of the menu node, null if the node should be hidden

boolean - - -satisified - - - - - - - -

Boolean indicating whether the menu enries dependencies are satisfied

boolean - - -readonly - - - - - - <optional>
- - - -

Boolean indicating whether the menu entries underlying ACLs are readonly

children - - -Array.<LuCI.ui.menu.MenuNode> - - - - - - <optional>
- - - -

Array of child menu nodes.

- - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.ui.tabs.html b/docs/jsapi/LuCI.ui.tabs.html deleted file mode 100644 index e87d8b9665..0000000000 --- a/docs/jsapi/LuCI.ui.tabs.html +++ /dev/null @@ -1,3843 +0,0 @@ - - - - - Class: tabs - - - - - - - - - - - - - - - - - -
- - -
-

Class: tabs

- - - - -
- -
-

- LuCI.ui. - - tabs -

- -

The tabs class handles tab menu groups used throughout the view area. -It takes care of setting up tab groups, tracking their state and handling -related events.

-

This class is automatically instantiated as part of LuCI.ui. To use it -in views, use 'require ui' and refer to ui.tabs. To import it in -external JavaScript, use L.require("ui").then(...) and access the -tabs property of the class instance value.

- -
- -
-
- - - - -
-
-

- - new LuCI.ui.tabs() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - initTabGroup(panes) -

- - - - -
- - -
-
- - -
-

Initializes a new tab group from the given tab pane collection.

-

This function cycles through the given tab pane DOM nodes, extracts -their tab IDs, titles and active states, renders a corresponding -tab menu and prepends it to the tab panes common parent DOM node.

-

The tab menu labels will be set to the value of the data-tab-title -attribute of each corresponding pane. The last pane with the -data-tab-active attribute set to true will be selected by default.

-

If no pane is marked as active, the first one will be preselected.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
panes - - -Array.<Node> -| - -NodeList - - - - - -

A collection of tab panes to build a tab group menu for. May be a -plain array of DOM nodes or a NodeList collection, such as the result -of a querySelectorAll() call or the .childNodes property of a -DOM node.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - isEmptyPane(pane){boolean} -

- - - - -
- - -
-
- - -
-

Checks whether the given tab pane node is empty.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
pane - - -Node - - - - - -

The tab pane to check.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the pane is empty, else false.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.view.html b/docs/jsapi/LuCI.view.html deleted file mode 100644 index 1aac99ea0b..0000000000 --- a/docs/jsapi/LuCI.view.html +++ /dev/null @@ -1,4447 +0,0 @@ - - - - - Class: view - - - - - - - - - - - - - - - - - -
- - -
-

Class: view

- - - - -
- -
-

- LuCI. - - view -

- -

The view class forms the basis of views and provides a standard -set of methods to inherit from.

- -
- -
-
- - - - -
-
-

- - new LuCI.view() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - addFooter(){DocumentFragment} -

- - - - -
- - -
-
- - -
-

Renders a standard page action footer if any of the -handleSave(), handleSaveApply() or handleReset() -functions are defined.

-

The default implementation should be sufficient for most -views - it will render a standard page footer with action -buttons labeled Save, Save & Apply and Reset -triggering the handleSave(), handleSaveApply() and -handleReset() functions respectively.

-

When any of these handle*() functions is overwritten -with null by a view extending this class, the -corresponding button will not be rendered.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - DocumentFragment - - - Returns a DocumentFragment containing the footer bar -with buttons for each corresponding handle*() action -or an empty DocumentFragment if all three handle*() -methods are overwritten with null.
- - - - -
- - - -
-
-

- - handleReset(ev){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

The handleReset function is invoked when the user clicks -the Reset button in the page action footer.

-

The default implementation should be sufficient for most -views using form.Map() based forms - it -will iterate all forms present in the view and invoke -the Map.reset() method on each form.

-

Views not using Map instances or requiring other special -logic should overwrite handleReset() with a custom -implementation.

-

To disable the Reset page footer button, views extending -this base class should overwrite the handleReset function -with null.

-

The invocation of this function is wrapped by -Promise.resolve() so it may return Promises if needed.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ev - - -Event - - - - - -

The DOM event that triggered the function.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Any return values of this function are discarded, but -passed through Promise.resolve() to ensure that any -returned promise runs to completion before the button -is reenabled.
- - - - -
- - - -
-
-

- - handleSave(ev){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

The handleSave function is invoked when the user clicks -the Save button in the page action footer.

-

The default implementation should be sufficient for most -views using form.Map() based forms - it -will iterate all forms present in the view and invoke -the Map.save() method on each form.

-

Views not using Map instances or requiring other special -logic should overwrite handleSave() with a custom -implementation.

-

To disable the Save page footer button, views extending -this base class should overwrite the handleSave function -with null.

-

The invocation of this function is wrapped by -Promise.resolve() so it may return Promises if needed.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ev - - -Event - - - - - -

The DOM event that triggered the function.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Any return values of this function are discarded, but -passed through Promise.resolve() to ensure that any -returned promise runs to completion before the button -is reenabled.
- - - - -
- - - -
-
-

- - handleSaveApply(ev){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

The handleSaveApply function is invoked when the user clicks -the Save & Apply button in the page action footer.

-

The default implementation should be sufficient for most -views using form.Map() based forms - it -will first invoke -view.handleSave() and then -call ui.changes.apply() to start the -modal config apply and page reload flow.

-

Views not using Map instances or requiring other special -logic should overwrite handleSaveApply() with a custom -implementation.

-

To disable the Save & Apply page footer button, views -extending this base class should overwrite the -handleSaveApply function with null.

-

The invocation of this function is wrapped by -Promise.resolve() so it may return Promises if needed.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ev - - -Event - - - - - -

The DOM event that triggered the function.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - Any return values of this function are discarded, but -passed through Promise.resolve() to ensure that any -returned promise runs to completion before the button -is reenabled.
- - - - -
- - - -
-
-

- - abstractload(){*|Promise.<*>} -

- - - - -
- - -
-
- - -
-

The load function is invoked before the view is rendered.

-

The invocation of this function is wrapped by -Promise.resolve() so it may return Promises if needed.

-

The return value of the function (or the resolved values -of the promise returned by it) will be passed as first -argument to render().

-

This function is supposed to be overwritten by subclasses, -the default implementation does nothing.

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - * - | - - Promise.<*> - - - May return any value or a Promise resolving to any value.
- - - - -
- - - -
-
-

- - abstractrender(load_results){Node|Promise.<Node>} -

- - - - -
- - -
-
- - -
-

The render function is invoked after the -load() function and responsible -for setting up the view contents. It must return a DOM -Node or DocumentFragment holding the contents to -insert into the view area.

-

The invocation of this function is wrapped by -Promise.resolve() so it may return Promises if needed.

-

The return value of the function (or the resolved values -of the promise returned by it) will be inserted into the -main content area using -dom.append().

-

This function is supposed to be overwritten by subclasses, -the default implementation does nothing.

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
load_results - - -* -| - -null - - - - - -

This function will receive the return value of the -view.load() function as first -argument.

- - - -
- - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Node - | - - Promise.<Node> - - - Should return a DOM Node value or a Promise resolving -to a Node value.
- - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/LuCI.xhr.html b/docs/jsapi/LuCI.xhr.html deleted file mode 100644 index 776abbad2e..0000000000 --- a/docs/jsapi/LuCI.xhr.html +++ /dev/null @@ -1,4411 +0,0 @@ - - - - - Class: xhr - - - - - - - - - - - - - - - - - -
- - -
-

Class: xhr

- - - - -
- -
-

- LuCI. - - xhr -

- -

The LuCI.xhr class is a legacy compatibility shim for the -functionality formerly provided by xhr.js. It is registered as global -window.XHR symbol for compatibility with legacy code.

-

New code should use LuCI.request instead to implement HTTP -request handling.

- -
- -
-
- - - - -
-
-

- - new LuCI.xhr() -

- - - - -
- - -
-
- - - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-
-

- - abort() -

- - - - -
- - -
-
- - -
-

Ignored for backwards compatibility.

-

This function does nothing.

-
- - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - busy(){boolean} -

- - - - -
- - -
-
- - -
-

Checks the running state of the request.

-
- - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - boolean - - - Returns true if the request is still running or false if it -already completed.
- - - - -
- - - -
-
-

- - cancel() -

- - - - -
- - -
-
- - -
-

Cancels a running request.

-

This function does not actually cancel the underlying -XMLHTTPRequest request but it sets a flag which prevents the -invocation of the callback function when the request eventually -finishes or timed out.

-
- - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
- - - -
-
-

- - get(url, data, callback, timeout){Promise.<null>} -

- - - - -
- - -
-
- - -
-

This function is a legacy wrapper around -LuCI.get().

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
url - - -string - - - - - - - - - - -

The URL to request

data - - -Object - - - - - - - optional - - - - - -

Additional query string data

callback - - -LuCI.requestCallbackFn - - - - - - - optional - - - - - -

Callback function to invoke on completion

timeout - - -number - - - - - - - optional - - - - - -

Request timeout to use

- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<null> - - -
- - - - -
- - - -
-
-

- - post(url, data, callback, timeout){Promise.<null>} -

- - - - -
- - -
-
- - -
-

This function is a legacy wrapper around -LuCI.post().

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
url - - -string - - - - - - - - - - -

The URL to request

data - - -Object - - - - - - - optional - - - - - -

Additional data to append to the request body.

callback - - -LuCI.requestCallbackFn - - - - - - - optional - - - - - -

Callback function to invoke on completion

timeout - - -number - - - - - - - optional - - - - - -

Request timeout to use

- - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - - - -
Returns:
- - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - Promise.<null> - - -
- - - - -
- - - -
-
-

- - send_form() -

- - - - -
- - -
-
- - -
-

Existing for backwards compatibility.

-

This function simply throws an InternalError when invoked.

-
- - - - - - - - - -
- - - - - - - -
Deprecated
  • Yes
- - - - - - - - - - - - - - - -
- - - - - - - - - -
Throws:
- - - -
-
-
-

Throws an InternalError with the message Not implemented -when invoked.

-
-
-
-
-
- Type -
-
- -InternalError - - -
-
-
-
- - - - - - - -
- -
- - - - - - - -
- -
- - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/README.md b/docs/jsapi/README.md deleted file mode 100644 index 41dd17b641..0000000000 --- a/docs/jsapi/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# LuCI client side API documentation - -You can browse the JavaScript apis provided by LuCI here. A good starting point is the central -[luci.js class](LuCI.html). diff --git a/docs/jsapi/fonts/OpenSans-Bold-webfont.eot b/docs/jsapi/fonts/OpenSans-Bold-webfont.eot deleted file mode 100644 index 5d20d916338a5890a033952e2e07ba7380f5a7d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19544 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 diff --git a/docs/jsapi/fonts/OpenSans-Bold-webfont.svg b/docs/jsapi/fonts/OpenSans-Bold-webfont.svg deleted file mode 100644 index 3ed7be4bc5..0000000000 --- a/docs/jsapi/fonts/OpenSans-Bold-webfont.svg +++ /dev/null @@ -1,1830 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/jsapi/fonts/OpenSans-Bold-webfont.woff b/docs/jsapi/fonts/OpenSans-Bold-webfont.woff deleted file mode 100644 index 1205787b0ed50db71ebd4f8a7f85d106721ff258..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22432 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 ig3W - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/jsapi/fonts/OpenSans-BoldItalic-webfont.woff b/docs/jsapi/fonts/OpenSans-BoldItalic-webfont.woff deleted file mode 100644 index ed760c0628b6a0026041f5b8bba466a0471fd2e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23048 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/jsapi/fonts/OpenSans-Italic-webfont.woff b/docs/jsapi/fonts/OpenSans-Italic-webfont.woff deleted file mode 100644 index ff652e64356b538c001423b6aedefcf1ee66cd17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23188 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 diff --git a/docs/jsapi/fonts/OpenSans-Light-webfont.svg b/docs/jsapi/fonts/OpenSans-Light-webfont.svg deleted file mode 100644 index 11a472ca8a..0000000000 --- a/docs/jsapi/fonts/OpenSans-Light-webfont.svg +++ /dev/null @@ -1,1831 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/jsapi/fonts/OpenSans-Light-webfont.woff b/docs/jsapi/fonts/OpenSans-Light-webfont.woff deleted file mode 100644 index e786074813a27d0a7a249047832988d5bf0fe756..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22248 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 diff --git a/docs/jsapi/fonts/OpenSans-LightItalic-webfont.eot b/docs/jsapi/fonts/OpenSans-LightItalic-webfont.eot deleted file mode 100644 index 8f445929ffb03b50e98c2a2f7d831a0cb1b276a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20535 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 Z%0#`NexefPFV?Xj51H#Y#AC7WXn+Jg($4?@ diff --git a/docs/jsapi/fonts/OpenSans-LightItalic-webfont.svg b/docs/jsapi/fonts/OpenSans-LightItalic-webfont.svg deleted file mode 100644 index 431d7e3546..0000000000 --- a/docs/jsapi/fonts/OpenSans-LightItalic-webfont.svg +++ /dev/null @@ -1,1835 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/jsapi/fonts/OpenSans-LightItalic-webfont.woff b/docs/jsapi/fonts/OpenSans-LightItalic-webfont.woff deleted file mode 100644 index 43e8b9e6cc061ff17fd2903075cbde12715512b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23400 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
- - -
-

Source: form.js

- - - - -
-
-
'use strict';
-'require ui';
-'require uci';
-'require rpc';
-'require dom';
-'require baseclass';
-
-var scope = this;
-
-var callSessionAccess = rpc.declare({
-	object: 'session',
-	method: 'access',
-	params: [ 'scope', 'object', 'function' ],
-	expect: { 'access': false }
-});
-
-var CBIJSONConfig = baseclass.extend({
-	__init__: function(data) {
-		data = Object.assign({}, data);
-
-		this.data = {};
-
-		var num_sections = 0,
-		    section_ids = [];
-
-		for (var sectiontype in data) {
-			if (!data.hasOwnProperty(sectiontype))
-				continue;
-
-			if (Array.isArray(data[sectiontype])) {
-				for (var i = 0, index = 0; i < data[sectiontype].length; i++) {
-					var item = data[sectiontype][i],
-					    anonymous, name;
-
-					if (!L.isObject(item))
-						continue;
-
-					if (typeof(item['.name']) == 'string') {
-						name = item['.name'];
-						anonymous = false;
-					}
-					else {
-						name = sectiontype + num_sections;
-						anonymous = true;
-					}
-
-					if (!this.data.hasOwnProperty(name))
-						section_ids.push(name);
-
-					this.data[name] = Object.assign(item, {
-						'.index': num_sections++,
-						'.anonymous': anonymous,
-						'.name': name,
-						'.type': sectiontype
-					});
-				}
-			}
-			else if (L.isObject(data[sectiontype])) {
-				this.data[sectiontype] = Object.assign(data[sectiontype], {
-					'.anonymous': false,
-					'.name': sectiontype,
-					'.type': sectiontype
-				});
-
-				section_ids.push(sectiontype);
-				num_sections++;
-			}
-		}
-
-		section_ids.sort(L.bind(function(a, b) {
-			var indexA = (this.data[a]['.index'] != null) ? +this.data[a]['.index'] : 9999,
-			    indexB = (this.data[b]['.index'] != null) ? +this.data[b]['.index'] : 9999;
-
-			if (indexA != indexB)
-				return (indexA - indexB);
-
-			return (a > b);
-		}, this));
-
-		for (var i = 0; i < section_ids.length; i++)
-			this.data[section_ids[i]]['.index'] = i;
-	},
-
-	load: function() {
-		return Promise.resolve(this.data);
-	},
-
-	save: function() {
-		return Promise.resolve();
-	},
-
-	get: function(config, section, option) {
-		if (section == null)
-			return null;
-
-		if (option == null)
-			return this.data[section];
-
-		if (!this.data.hasOwnProperty(section))
-			return null;
-
-		var value = this.data[section][option];
-
-		if (Array.isArray(value))
-			return value;
-
-		if (value != null)
-			return String(value);
-
-		return null;
-	},
-
-	set: function(config, section, option, value) {
-		if (section == null || option == null || option.charAt(0) == '.')
-			return;
-
-		if (!this.data.hasOwnProperty(section))
-			return;
-
-		if (value == null)
-			delete this.data[section][option];
-		else if (Array.isArray(value))
-			this.data[section][option] = value;
-		else
-			this.data[section][option] = String(value);
-	},
-
-	unset: function(config, section, option) {
-		return this.set(config, section, option, null);
-	},
-
-	sections: function(config, sectiontype, callback) {
-		var rv = [];
-
-		for (var section_id in this.data)
-			if (sectiontype == null || this.data[section_id]['.type'] == sectiontype)
-				rv.push(this.data[section_id]);
-
-		rv.sort(function(a, b) { return a['.index'] - b['.index'] });
-
-		if (typeof(callback) == 'function')
-			for (var i = 0; i < rv.length; i++)
-				callback.call(this, rv[i], rv[i]['.name']);
-
-		return rv;
-	},
-
-	add: function(config, sectiontype, sectionname) {
-		var num_sections_type = 0, next_index = 0;
-
-		for (var name in this.data) {
-			num_sections_type += (this.data[name]['.type'] == sectiontype);
-			next_index = Math.max(next_index, this.data[name]['.index']);
-		}
-
-		var section_id = sectionname || sectiontype + num_sections_type;
-
-		if (!this.data.hasOwnProperty(section_id)) {
-			this.data[section_id] = {
-				'.name': section_id,
-				'.type': sectiontype,
-				'.anonymous': (sectionname == null),
-				'.index': next_index + 1
-			};
-		}
-
-		return section_id;
-	},
-
-	remove: function(config, section) {
-		if (this.data.hasOwnProperty(section))
-			delete this.data[section];
-	},
-
-	resolveSID: function(config, section_id) {
-		return section_id;
-	},
-
-	move: function(config, section_id1, section_id2, after) {
-		return uci.move.apply(this, [config, section_id1, section_id2, after]);
-	}
-});
-
-/**
- * @class AbstractElement
- * @memberof LuCI.form
- * @hideconstructor
- * @classdesc
- *
- * The `AbstractElement` class serves as abstract base for the different form
- * elements implemented by `LuCI.form`. It provides the common logic for
- * loading and rendering values, for nesting elements and for defining common
- * properties.
- *
- * This class is private and not directly accessible by user code.
- */
-var CBIAbstractElement = baseclass.extend(/** @lends LuCI.form.AbstractElement.prototype */ {
-	__init__: function(title, description) {
-		this.title = title || '';
-		this.description = description || '';
-		this.children = [];
-	},
-
-	/**
-	 * Add another form element as children to this element.
-	 *
-	 * @param {AbstractElement} element
-	 * The form element to add.
-	 */
-	append: function(obj) {
-		this.children.push(obj);
-	},
-
-	/**
-	 * Parse this elements form input.
-	 *
-	 * The `parse()` function recursively walks the form element tree and
-	 * triggers input value reading and validation for each encountered element.
-	 *
-	 * Elements which are hidden due to unsatisified dependencies are skipped.
-	 *
-	 * @returns {Promise<void>}
-	 * Returns a promise resolving once this element's value and the values of
-	 * all child elements have been parsed. The returned promise is rejected
-	 * if any parsed values are not meeting the validation constraints of their
-	 * respective elements.
-	 */
-	parse: function() {
-		var args = arguments;
-		this.children.forEach(function(child) {
-			child.parse.apply(child, args);
-		});
-	},
-
-	/**
-	 * Render the form element.
-	 *
-	 * The `render()` function recursively walks the form element tree and
-	 * renders the markup for each element, returning the assembled DOM tree.
-	 *
-	 * @abstract
-	 * @returns {Node|Promise<Node>}
-	 * May return a DOM Node or a promise resolving to a DOM node containing
-	 * the form element's markup, including the markup of any child elements.
-	 */
-	render: function() {
-		L.error('InternalError', 'Not implemented');
-	},
-
-	/** @private */
-	loadChildren: function(/* ... */) {
-		var tasks = [];
-
-		if (Array.isArray(this.children))
-			for (var i = 0; i < this.children.length; i++)
-				if (!this.children[i].disable)
-					tasks.push(this.children[i].load.apply(this.children[i], arguments));
-
-		return Promise.all(tasks);
-	},
-
-	/** @private */
-	renderChildren: function(tab_name /*, ... */) {
-		var tasks = [],
-		    index = 0;
-
-		if (Array.isArray(this.children))
-			for (var i = 0; i < this.children.length; i++)
-				if (tab_name === null || this.children[i].tab === tab_name)
-					if (!this.children[i].disable)
-						tasks.push(this.children[i].render.apply(
-							this.children[i], this.varargs(arguments, 1, index++)));
-
-		return Promise.all(tasks);
-	},
-
-	/**
-	 * Strip any HTML tags from the given input string.
-	 *
-	 * @param {string} input
-	 * The input string to clean.
-	 *
-	 * @returns {string}
-	 * The cleaned input string with HTML removes removed.
-	 */
-	stripTags: function(s) {
-		if (typeof(s) == 'string' && !s.match(/[<>]/))
-			return s;
-
-		var x = E('div', {}, s);
-		return x.textContent || x.innerText || '';
-	},
-
-	/**
-	 * Format the given named property as title string.
-	 *
-	 * This function looks up the given named property and formats its value
-	 * suitable for use as element caption or description string. It also
-	 * strips any HTML tags from the result.
-	 *
-	 * If the property value is a string, it is passed to `String.format()`
-	 * along with any additional parameters passed to `titleFn()`.
-	 *
-	 * If the property value is a function, it is invoked with any additional
-	 * `titleFn()` parameters as arguments and the obtained return value is
-	 * converted to a string.
-	 *
-	 * In all other cases, `null` is returned.
-	 *
-	 * @param {string} property
-	 * The name of the element property to use.
-	 *
-	 * @param {...*} fmt_args
-	 * Extra values to format the title string with.
-	 *
-	 * @returns {string|null}
-	 * The formatted title string or `null` if the property did not exist or
-	 * was neither a string nor a function.
-	 */
-	titleFn: function(attr /*, ... */) {
-		var s = null;
-
-		if (typeof(this[attr]) == 'function')
-			s = this[attr].apply(this, this.varargs(arguments, 1));
-		else if (typeof(this[attr]) == 'string')
-			s = (arguments.length > 1) ? ''.format.apply(this[attr], this.varargs(arguments, 1)) : this[attr];
-
-		if (s != null)
-			s = this.stripTags(String(s)).trim();
-
-		if (s == null || s == '')
-			return null;
-
-		return s;
-	}
-});
-
-/**
- * @constructor Map
- * @memberof LuCI.form
- * @augments LuCI.form.AbstractElement
- *
- * @classdesc
- *
- * The `Map` class represents one complete form. A form usually maps one UCI
- * configuraton file and is divided into multiple sections containing multiple
- * fields each.
- *
- * It serves as main entry point into the `LuCI.form` for typical view code.
- *
- * @param {string} config
- * The UCI configuration to map. It is automatically loaded along when the
- * resulting map instance.
- *
- * @param {string} [title]
- * The title caption of the form. A form title is usually rendered as separate
- * headline element before the actual form contents. If omitted, the
- * corresponding headline element will not be rendered.
- *
- * @param {string} [description]
- * The description text of the form which is usually rendered as text
- * paragraph below the form title and before the actual form conents.
- * If omitted, the corresponding paragraph element will not be rendered.
- */
-var CBIMap = CBIAbstractElement.extend(/** @lends LuCI.form.Map.prototype */ {
-	__init__: function(config /*, ... */) {
-		this.super('__init__', this.varargs(arguments, 1));
-
-		this.config = config;
-		this.parsechain = [ config ];
-		this.data = uci;
-	},
-
-	/**
-	 * Toggle readonly state of the form.
-	 *
-	 * If set to `true`, the Map instance is marked readonly and any form
-	 * option elements added to it will inherit the readonly state.
-	 *
-	 * If left unset, the Map will test the access permission of the primary
-	 * uci configuration upon loading and mark the form readonly if no write
-	 * permissions are granted.
-	 *
-	 * @name LuCI.form.Map.prototype#readonly
-	 * @type boolean
-	 */
-
-	/**
-	 * Find all DOM nodes within this Map which match the given search
-	 * parameters. This function is essentially a convenience wrapper around
-	 * `querySelectorAll()`.
-	 *
-	 * This function is sensitive to the amount of arguments passed to it;
-	 * if only one argument is specified, it is used as selector-expression
-	 * as-is. When two arguments are passed, the first argument is treated
-	 * as attribute name, the second one as attribute value to match.
-	 *
-	 * As an example, `map.findElements('input')` would find all `<input>`
-	 * nodes while `map.findElements('type', 'text')` would find any DOM node
-	 * with a `type="text"` attribute.
-	 *
-	 * @param {string} selector_or_attrname
-	 * If invoked with only one parameter, this argument is a
-	 * `querySelectorAll()` compatible selector expression. If invoked with
-	 * two parameters, this argument is the attribute name to filter for.
-	 *
-	 * @param {string} [attrvalue]
-	 * In case the function is invoked with two parameters, this argument
-	 * specifies the attribute value to match.
-	 *
-	 * @throws {InternalError}
-	 * Throws an `InternalError` if more than two function parameters are
-	 * passed.
-	 *
-	 * @returns {NodeList}
-	 * Returns a (possibly empty) DOM `NodeList` containing the found DOM nodes.
-	 */
-	findElements: function(/* ... */) {
-		var q = null;
-
-		if (arguments.length == 1)
-			q = arguments[0];
-		else if (arguments.length == 2)
-			q = '[%s="%s"]'.format(arguments[0], arguments[1]);
-		else
-			L.error('InternalError', 'Expecting one or two arguments to findElements()');
-
-		return this.root.querySelectorAll(q);
-	},
-
-	/**
-	 * Find the first DOM node within this Map which matches the given search
-	 * parameters. This function is essentially a convenience wrapper around
-	 * `findElements()` which only returns the first found node.
-	 *
-	 * This function is sensitive to the amount of arguments passed to it;
-	 * if only one argument is specified, it is used as selector-expression
-	 * as-is. When two arguments are passed, the first argument is treated
-	 * as attribute name, the second one as attribute value to match.
-	 *
-	 * As an example, `map.findElement('input')` would find the first `<input>`
-	 * node while `map.findElement('type', 'text')` would find the first DOM
-	 * node with a `type="text"` attribute.
-	 *
-	 * @param {string} selector_or_attrname
-	 * If invoked with only one parameter, this argument is a `querySelector()`
-	 * compatible selector expression. If invoked with two parameters, this
-	 * argument is the attribute name to filter for.
-	 *
-	 * @param {string} [attrvalue]
-	 * In case the function is invoked with two parameters, this argument
-	 * specifies the attribute value to match.
-	 *
-	 * @throws {InternalError}
-	 * Throws an `InternalError` if more than two function parameters are
-	 * passed.
-	 *
-	 * @returns {Node|null}
-	 * Returns the first found DOM node or `null` if no element matched.
-	 */
-	findElement: function(/* ... */) {
-		var res = this.findElements.apply(this, arguments);
-		return res.length ? res[0] : null;
-	},
-
-	/**
-	 * Tie another UCI configuration to the map.
-	 *
-	 * By default, a map instance will only load the UCI configuration file
-	 * specified in the constructor but sometimes access to values from
-	 * further configuration files is required. This function allows for such
-	 * use cases by registering further UCI configuration files which are
-	 * needed by the map.
-	 *
-	 * @param {string} config
-	 * The additional UCI configuration file to tie to the map. If the given
-	 * config already is in the list of required files, it will be ignored.
-	 */
-	chain: function(config) {
-		if (this.parsechain.indexOf(config) == -1)
-			this.parsechain.push(config);
-	},
-
-	/**
-	 * Add a configuration section to the map.
-	 *
-	 * LuCI forms follow the structure of the underlying UCI configurations,
-	 * means that a map, which represents a single UCI configuration, is
-	 * divided into multiple sections which in turn contain an arbitrary
-	 * number of options.
-	 *
-	 * While UCI itself only knows two kinds of sections - named and anonymous
-	 * ones - the form class offers various flavors of form section elements
-	 * to present configuration sections in different ways. Refer to the
-	 * documentation of the different section classes for details.
-	 *
-	 * @param {LuCI.form.AbstractSection} sectionclass
-	 * The section class to use for rendering the configuration section.
-	 * Note that this value must be the class itself, not a class instance
-	 * obtained from calling `new`. It must also be a class dervied from
-	 * `LuCI.form.AbstractSection`.
-	 *
-	 * @param {...string} classargs
-	 * Additional arguments which are passed as-is to the contructor of the
-	 * given section class. Refer to the class specific constructor
-	 * documentation for details.
-	 *
-	 * @returns {LuCI.form.AbstractSection}
-	 * Returns the instantiated section class instance.
-	 */
-	section: function(cbiClass /*, ... */) {
-		if (!CBIAbstractSection.isSubclass(cbiClass))
-			L.error('TypeError', 'Class must be a descendent of CBIAbstractSection');
-
-		var obj = cbiClass.instantiate(this.varargs(arguments, 1, this));
-		this.append(obj);
-		return obj;
-	},
-
-	/**
-	 * Load the configuration covered by this map.
-	 *
-	 * The `load()` function first loads all referenced UCI configurations,
-	 * then it recursively walks the form element tree and invokes the
-	 * load function of each child element.
-	 *
-	 * @returns {Promise<void>}
-	 * Returns a promise resolving once the entire form completed loading all
-	 * data. The promise may reject with an error if any configuration failed
-	 * to load or if any of the child elements load functions rejected with
-	 * an error.
-	 */
-	load: function() {
-		var doCheckACL = (!(this instanceof CBIJSONMap) && this.readonly == null),
-		    loadTasks = [ doCheckACL ? callSessionAccess('uci', this.config, 'write') : true ],
-		    configs = this.parsechain || [ this.config ];
-
-		loadTasks.push.apply(loadTasks, configs.map(L.bind(function(config, i) {
-			return i ? L.resolveDefault(this.data.load(config)) : this.data.load(config);
-		}, this)));
-
-		return Promise.all(loadTasks).then(L.bind(function(res) {
-			if (res[0] === false)
-				this.readonly = true;
-
-			return this.loadChildren();
-		}, this));
-	},
-
-	/**
-	 * Parse the form input values.
-	 *
-	 * The `parse()` function recursively walks the form element tree and
-	 * triggers input value reading and validation for each child element.
-	 *
-	 * Elements which are hidden due to unsatisified dependencies are skipped.
-	 *
-	 * @returns {Promise<void>}
-	 * Returns a promise resolving once the entire form completed parsing all
-	 * input values. The returned promise is rejected if any parsed values are
-	 * not meeting the validation constraints of their respective elements.
-	 */
-	parse: function() {
-		var tasks = [];
-
-		if (Array.isArray(this.children))
-			for (var i = 0; i < this.children.length; i++)
-				tasks.push(this.children[i].parse());
-
-		return Promise.all(tasks);
-	},
-
-	/**
-	 * Save the form input values.
-	 *
-	 * This function parses the current form, saves the resulting UCI changes,
-	 * reloads the UCI configuration data and redraws the form elements.
-	 *
-	 * @param {function} [cb]
-	 * An optional callback function that is invoked after the form is parsed
-	 * but before the changed UCI data is saved. This is useful to perform
-	 * additional data manipulation steps before saving the changes.
-	 *
-	 * @param {boolean} [silent=false]
-	 * If set to `true`, trigger an alert message to the user in case saving
-	 * the form data failes. Otherwise fail silently.
-	 *
-	 * @returns {Promise<void>}
-	 * Returns a promise resolving once the entire save operation is complete.
-	 * The returned promise is rejected if any step of the save operation
-	 * failed.
-	 */
-	save: function(cb, silent) {
-		this.checkDepends();
-
-		return this.parse()
-			.then(cb)
-			.then(this.data.save.bind(this.data))
-			.then(this.load.bind(this))
-			.catch(function(e) {
-				if (!silent) {
-					ui.showModal(_('Save error'), [
-						E('p', {}, [ _('An error occurred while saving the form:') ]),
-						E('p', {}, [ E('em', { 'style': 'white-space:pre' }, [ e.message ]) ]),
-						E('div', { 'class': 'right' }, [
-							E('button', { 'class': 'btn', 'click': ui.hideModal }, [ _('Dismiss') ])
-						])
-					]);
-				}
-
-				return Promise.reject(e);
-			}).then(this.renderContents.bind(this));
-	},
-
-	/**
-	 * Reset the form by re-rendering its contents. This will revert all
-	 * unsaved user inputs to their initial form state.
-	 *
-	 * @returns {Promise<Node>}
-	 * Returns a promise resolving to the toplevel form DOM node once the
-	 * re-rendering is complete.
-	 */
-	reset: function() {
-		return this.renderContents();
-	},
-
-	/**
-	 * Render the form markup.
-	 *
-	 * @returns {Promise<Node>}
-	 * Returns a promise resolving to the toplevel form DOM node once the
-	 * rendering is complete.
-	 */
-	render: function() {
-		return this.load().then(this.renderContents.bind(this));
-	},
-
-	/** @private */
-	renderContents: function() {
-		var mapEl = this.root || (this.root = E('div', {
-			'id': 'cbi-%s'.format(this.config),
-			'class': 'cbi-map',
-			'cbi-dependency-check': L.bind(this.checkDepends, this)
-		}));
-
-		dom.bindClassInstance(mapEl, this);
-
-		return this.renderChildren(null).then(L.bind(function(nodes) {
-			var initialRender = !mapEl.firstChild;
-
-			dom.content(mapEl, null);
-
-			if (this.title != null && this.title != '')
-				mapEl.appendChild(E('h2', { 'name': 'content' }, this.title));
-
-			if (this.description != null && this.description != '')
-				mapEl.appendChild(E('div', { 'class': 'cbi-map-descr' }, this.description));
-
-			if (this.tabbed)
-				dom.append(mapEl, E('div', { 'class': 'cbi-map-tabbed' }, nodes));
-			else
-				dom.append(mapEl, nodes);
-
-			if (!initialRender) {
-				mapEl.classList.remove('flash');
-
-				window.setTimeout(function() {
-					mapEl.classList.add('flash');
-				}, 1);
-			}
-
-			this.checkDepends();
-
-			var tabGroups = mapEl.querySelectorAll('.cbi-map-tabbed, .cbi-section-node-tabbed');
-
-			for (var i = 0; i < tabGroups.length; i++)
-				ui.tabs.initTabGroup(tabGroups[i].childNodes);
-
-			return mapEl;
-		}, this));
-	},
-
-	/**
-	 * Find a form option element instance.
-	 *
-	 * @param {string} name_or_id
-	 * The name or the full ID of the option element to look up.
-	 *
-	 * @param {string} [section_id]
-	 * The ID of the UCI section containing the option to look up. May be
-	 * omitted if a full ID is passed as first argument.
-	 *
-	 * @param {string} [config]
-	 * The name of the UCI configuration the option instance is belonging to.
-	 * Defaults to the main UCI configuration of the map if omitted.
-	 *
-	 * @returns {Array<LuCI.form.AbstractValue,string>|null}
-	 * Returns a two-element array containing the form option instance as
-	 * first item and the corresponding UCI section ID as second item.
-	 * Returns `null` if the option could not be found.
-	 */
-	lookupOption: function(name, section_id, config_name) {
-		var id, elem, sid, inst;
-
-		if (name.indexOf('.') > -1)
-			id = 'cbid.%s'.format(name);
-		else
-			id = 'cbid.%s.%s.%s'.format(config_name || this.config, section_id, name);
-
-		elem = this.findElement('data-field', id);
-		sid  = elem ? id.split(/\./)[2] : null;
-		inst = elem ? dom.findClassInstance(elem) : null;
-
-		return (inst instanceof CBIAbstractValue) ? [ inst, sid ] : null;
-	},
-
-	/** @private */
-	checkDepends: function(ev, n) {
-		var changed = false;
-
-		for (var i = 0, s = this.children[0]; (s = this.children[i]) != null; i++)
-			if (s.checkDepends(ev, n))
-				changed = true;
-
-		if (changed && (n || 0) < 10)
-			this.checkDepends(ev, (n || 10) + 1);
-
-		ui.tabs.updateTabs(ev, this.root);
-	},
-
-	/** @private */
-	isDependencySatisfied: function(depends, config_name, section_id) {
-		var def = false;
-
-		if (!Array.isArray(depends) || !depends.length)
-			return true;
-
-		for (var i = 0; i < depends.length; i++) {
-			var istat = true,
-			    reverse = depends[i]['!reverse'],
-			    contains = depends[i]['!contains'];
-
-			for (var dep in depends[i]) {
-				if (dep == '!reverse' || dep == '!contains') {
-					continue;
-				}
-				else if (dep == '!default') {
-					def = true;
-					istat = false;
-				}
-				else {
-					var res = this.lookupOption(dep, section_id, config_name),
-					    val = (res && res[0].isActive(res[1])) ? res[0].formvalue(res[1]) : null;
-
-					var equal = contains
-						? isContained(val, depends[i][dep])
-						: isEqual(val, depends[i][dep]);
-
-					istat = (istat && equal);
-				}
-			}
-
-			if (istat ^ reverse)
-				return true;
-		}
-
-		return def;
-	}
-});
-
-/**
- * @constructor JSONMap
- * @memberof LuCI.form
- * @augments LuCI.form.Map
- *
- * @classdesc
- *
- * A `JSONMap` class functions similar to [LuCI.form.Map]{@link LuCI.form.Map}
- * but uses a multidimensional JavaScript object instead of UCI configuration
- * as data source.
- *
- * @param {Object<string, Object<string, *>|Array<Object<string, *>>>} data
- * The JavaScript object to use as data source. Internally, the object is
- * converted into an UCI-like format. Its toplevel keys are treated like UCI
- * section types while the object or array-of-object values are treated as
- * section contents.
- *
- * @param {string} [title]
- * The title caption of the form. A form title is usually rendered as separate
- * headline element before the actual form contents. If omitted, the
- * corresponding headline element will not be rendered.
- *
- * @param {string} [description]
- * The description text of the form which is usually rendered as text
- * paragraph below the form title and before the actual form conents.
- * If omitted, the corresponding paragraph element will not be rendered.
- */
-var CBIJSONMap = CBIMap.extend(/** @lends LuCI.form.JSONMap.prototype */ {
-	__init__: function(data /*, ... */) {
-		this.super('__init__', this.varargs(arguments, 1, 'json'));
-
-		this.config = 'json';
-		this.parsechain = [ 'json' ];
-		this.data = new CBIJSONConfig(data);
-	}
-});
-
-/**
- * @class AbstractSection
- * @memberof LuCI.form
- * @augments LuCI.form.AbstractElement
- * @hideconstructor
- * @classdesc
- *
- * The `AbstractSection` class serves as abstract base for the different form
- * section styles implemented by `LuCI.form`. It provides the common logic for
- * enumerating underlying configuration section instances, for registering
- * form options and for handling tabs to segment child options.
- *
- * This class is private and not directly accessible by user code.
- */
-var CBIAbstractSection = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractSection.prototype */ {
-	__init__: function(map, sectionType /*, ... */) {
-		this.super('__init__', this.varargs(arguments, 2));
-
-		this.sectiontype = sectionType;
-		this.map = map;
-		this.config = map.config;
-
-		this.optional = true;
-		this.addremove = false;
-		this.dynamic = false;
-	},
-
-	/**
-	 * Access the parent option container instance.
-	 *
-	 * In case this section is nested within an option element container,
-	 * this property will hold a reference to the parent option instance.
-	 *
-	 * If this section is not nested, the property is `null`.
-	 *
-	 * @name LuCI.form.AbstractSection.prototype#parentoption
-	 * @type LuCI.form.AbstractValue
-	 * @readonly
-	 */
-
-	/**
-	 * Enumerate the UCI section IDs covered by this form section element.
-	 *
-	 * @abstract
-	 * @throws {InternalError}
-	 * Throws an `InternalError` exception if the function is not implemented.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of UCI section IDs covered by this form element.
-	 * The sections will be rendered in the same order as the returned array.
-	 */
-	cfgsections: function() {
-		L.error('InternalError', 'Not implemented');
-	},
-
-	/**
-	 * Filter UCI section IDs to render.
-	 *
-	 * The filter function is invoked for each UCI section ID of a given type
-	 * and controls whether the given UCI section is rendered or ignored by
-	 * the form section element.
-	 *
-	 * The default implementation always returns `true`. User code or
-	 * classes extending `AbstractSection` may overwrite this function with
-	 * custom implementations.
-	 *
-	 * @abstract
-	 * @param {string} section_id
-	 * The UCI section ID to test.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when the given UCI section ID should be handled and
-	 * `false` when it should be ignored.
-	 */
-	filter: function(section_id) {
-		return true;
-	},
-
-	/**
-	 * Load the configuration covered by this section.
-	 *
-	 * The `load()` function recursively walks the section element tree and
-	 * invokes the load function of each child option element.
-	 *
-	 * @returns {Promise<void>}
-	 * Returns a promise resolving once the values of all child elements have
-	 * been loaded. The promise may reject with an error if any of the child
-	 * elements load functions rejected with an error.
-	 */
-	load: function() {
-		var section_ids = this.cfgsections(),
-		    tasks = [];
-
-		if (Array.isArray(this.children))
-			for (var i = 0; i < section_ids.length; i++)
-				tasks.push(this.loadChildren(section_ids[i])
-					.then(Function.prototype.bind.call(function(section_id, set_values) {
-						for (var i = 0; i < set_values.length; i++)
-							this.children[i].cfgvalue(section_id, set_values[i]);
-					}, this, section_ids[i])));
-
-		return Promise.all(tasks);
-	},
-
-	/**
-	 * Parse this sections form input.
-	 *
-	 * The `parse()` function recursively walks the section element tree and
-	 * triggers input value reading and validation for each encountered child
-	 * option element.
-	 *
-	 * Options which are hidden due to unsatisified dependencies are skipped.
-	 *
-	 * @returns {Promise<void>}
-	 * Returns a promise resolving once the values of all child elements have
-	 * been parsed. The returned promise is rejected if any parsed values are
-	 * not meeting the validation constraints of their respective elements.
-	 */
-	parse: function() {
-		var section_ids = this.cfgsections(),
-		    tasks = [];
-
-		if (Array.isArray(this.children))
-			for (var i = 0; i < section_ids.length; i++)
-				for (var j = 0; j < this.children.length; j++)
-					tasks.push(this.children[j].parse(section_ids[i]));
-
-		return Promise.all(tasks);
-	},
-
-	/**
-	 * Add an option tab to the section.
-	 *
-	 * The child option elements of a section may be divided into multiple
-	 * tabs to provide a better overview to the user.
-	 *
-	 * Before options can be moved into a tab pane, the corresponding tab
-	 * has to be defined first, which is done by calling this function.
-	 *
-	 * Note that once tabs are defined, user code must use the `taboption()`
-	 * method to add options to specific tabs. Option elements added by
-	 * `option()` will not be assigned to any tab and not be rendered in this
-	 * case.
-	 *
-	 * @param {string} name
-	 * The name of the tab to register. It may be freely chosen and just serves
-	 * as an identifier to differentiate tabs.
-	 *
-	 * @param {string} title
-	 * The human readable caption of the tab.
-	 *
-	 * @param {string} [description]
-	 * An additional description text for the corresponding tab pane. It is
-	 * displayed as text paragraph below the tab but before the tab pane
-	 * contents. If omitted, no description will be rendered.
-	 *
-	 * @throws {Error}
-	 * Throws an exeption if a tab with the same `name` already exists.
-	 */
-	tab: function(name, title, description) {
-		if (this.tabs && this.tabs[name])
-			throw 'Tab already declared';
-
-		var entry = {
-			name: name,
-			title: title,
-			description: description,
-			children: []
-		};
-
-		this.tabs = this.tabs || [];
-		this.tabs.push(entry);
-		this.tabs[name] = entry;
-
-		this.tab_names = this.tab_names || [];
-		this.tab_names.push(name);
-	},
-
-	/**
-	 * Add a configuration option widget to the section.
-	 *
-	 * Note that [taboption()]{@link LuCI.form.AbstractSection#taboption}
-	 * should be used instead if this form section element uses tabs.
-	 *
-	 * @param {LuCI.form.AbstractValue} optionclass
-	 * The option class to use for rendering the configuration option. Note
-	 * that this value must be the class itself, not a class instance obtained
-	 * from calling `new`. It must also be a class dervied from
-	 * [LuCI.form.AbstractSection]{@link LuCI.form.AbstractSection}.
-	 *
-	 * @param {...*} classargs
-	 * Additional arguments which are passed as-is to the contructor of the
-	 * given option class. Refer to the class specific constructor
-	 * documentation for details.
-	 *
-	 * @throws {TypeError}
-	 * Throws a `TypeError` exception in case the passed class value is not a
-	 * descendent of `AbstractValue`.
-	 *
-	 * @returns {LuCI.form.AbstractValue}
-	 * Returns the instantiated option class instance.
-	 */
-	option: function(cbiClass /*, ... */) {
-		if (!CBIAbstractValue.isSubclass(cbiClass))
-			throw L.error('TypeError', 'Class must be a descendent of CBIAbstractValue');
-
-		var obj = cbiClass.instantiate(this.varargs(arguments, 1, this.map, this));
-		this.append(obj);
-		return obj;
-	},
-
-	/**
-	 * Add a configuration option widget to a tab of the section.
-	 *
-	 * @param {string} tabname
-	 * The name of the section tab to add the option element to.
-	 *
-	 * @param {LuCI.form.AbstractValue} optionclass
-	 * The option class to use for rendering the configuration option. Note
-	 * that this value must be the class itself, not a class instance obtained
-	 * from calling `new`. It must also be a class dervied from
-	 * [LuCI.form.AbstractSection]{@link LuCI.form.AbstractSection}.
-	 *
-	 * @param {...*} classargs
-	 * Additional arguments which are passed as-is to the contructor of the
-	 * given option class. Refer to the class specific constructor
-	 * documentation for details.
-	 *
-	 * @throws {ReferenceError}
-	 * Throws a `ReferenceError` exception when the given tab name does not
-	 * exist.
-	 *
-	 * @throws {TypeError}
-	 * Throws a `TypeError` exception in case the passed class value is not a
-	 * descendent of `AbstractValue`.
-	 *
-	 * @returns {LuCI.form.AbstractValue}
-	 * Returns the instantiated option class instance.
-	 */
-	taboption: function(tabName /*, ... */) {
-		if (!this.tabs || !this.tabs[tabName])
-			throw L.error('ReferenceError', 'Associated tab not declared');
-
-		var obj = this.option.apply(this, this.varargs(arguments, 1));
-		obj.tab = tabName;
-		this.tabs[tabName].children.push(obj);
-		return obj;
-	},
-
-	/**
-	 * Query underlying option configuration values.
-	 *
-	 * This function is sensitive to the amount of arguments passed to it;
-	 * if only one argument is specified, the configuration values of all
-	 * options within this section are returned as dictionary.
-	 *
-	 * If both the section ID and an option name are supplied, this function
-	 * returns the configuration value of the specified option only.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @param {string} [option]
-	 * The name of the option to query
-	 *
-	 * @returns {null|string|string[]|Object<string, null|string|string[]>}
-	 * Returns either a dictionary of option names and their corresponding
-	 * configuration values or just a single configuration value, depending
-	 * on the amount of passed arguments.
-	 */
-	cfgvalue: function(section_id, option) {
-		var rv = (arguments.length == 1) ? {} : null;
-
-		for (var i = 0, o; (o = this.children[i]) != null; i++)
-			if (rv)
-				rv[o.option] = o.cfgvalue(section_id);
-			else if (o.option == option)
-				return o.cfgvalue(section_id);
-
-		return rv;
-	},
-
-	/**
-	 * Query underlying option widget input values.
-	 *
-	 * This function is sensitive to the amount of arguments passed to it;
-	 * if only one argument is specified, the widget input values of all
-	 * options within this section are returned as dictionary.
-	 *
-	 * If both the section ID and an option name are supplied, this function
-	 * returns the widget input value of the specified option only.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @param {string} [option]
-	 * The name of the option to query
-	 *
-	 * @returns {null|string|string[]|Object<string, null|string|string[]>}
-	 * Returns either a dictionary of option names and their corresponding
-	 * widget input values or just a single widget input value, depending
-	 * on the amount of passed arguments.
-	 */
-	formvalue: function(section_id, option) {
-		var rv = (arguments.length == 1) ? {} : null;
-
-		for (var i = 0, o; (o = this.children[i]) != null; i++) {
-			var func = this.map.root ? this.children[i].formvalue : this.children[i].cfgvalue;
-
-			if (rv)
-				rv[o.option] = func.call(o, section_id);
-			else if (o.option == option)
-				return func.call(o, section_id);
-		}
-
-		return rv;
-	},
-
-	/**
-	 * Obtain underlying option LuCI.ui widget instances.
-	 *
-	 * This function is sensitive to the amount of arguments passed to it;
-	 * if only one argument is specified, the LuCI.ui widget instances of all
-	 * options within this section are returned as dictionary.
-	 *
-	 * If both the section ID and an option name are supplied, this function
-	 * returns the LuCI.ui widget instance value of the specified option only.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @param {string} [option]
-	 * The name of the option to query
-	 *
-	 * @returns {null|LuCI.ui.AbstractElement|Object<string, null|LuCI.ui.AbstractElement>}
-	 * Returns either a dictionary of option names and their corresponding
-	 * widget input values or just a single widget input value, depending
-	 * on the amount of passed arguments.
-	 */
-	getUIElement: function(section_id, option) {
-		var rv = (arguments.length == 1) ? {} : null;
-
-		for (var i = 0, o; (o = this.children[i]) != null; i++)
-			if (rv)
-				rv[o.option] = o.getUIElement(section_id);
-			else if (o.option == option)
-				return o.getUIElement(section_id);
-
-		return rv;
-	},
-
-	/**
-	 * Obtain underlying option objects.
-	 *
-	 * This function is sensitive to the amount of arguments passed to it;
-	 * if no option name is specified, all options within this section are
-	 * returned as dictionary.
-	 *
-	 * If an option name is supplied, this function returns the matching
-	 * LuCI.form.AbstractValue instance only.
-	 *
-	 * @param {string} [option]
-	 * The name of the option object to obtain
-	 *
-	 * @returns {null|LuCI.form.AbstractValue|Object<string, LuCI.form.AbstractValue>}
-	 * Returns either a dictionary of option names and their corresponding
-	 * option instance objects or just a single object instance value,
-	 * depending on the amount of passed arguments.
-	 */
-	getOption: function(option) {
-		var rv = (arguments.length == 0) ? {} : null;
-
-		for (var i = 0, o; (o = this.children[i]) != null; i++)
-			if (rv)
-				rv[o.option] = o;
-			else if (o.option == option)
-				return o;
-
-		return rv;
-	},
-
-	/** @private */
-	renderUCISection: function(section_id) {
-		var renderTasks = [];
-
-		if (!this.tabs)
-			return this.renderOptions(null, section_id);
-
-		for (var i = 0; i < this.tab_names.length; i++)
-			renderTasks.push(this.renderOptions(this.tab_names[i], section_id));
-
-		return Promise.all(renderTasks)
-			.then(this.renderTabContainers.bind(this, section_id));
-	},
-
-	/** @private */
-	renderTabContainers: function(section_id, nodes) {
-		var config_name = this.uciconfig || this.map.config,
-		    containerEls = E([]);
-
-		for (var i = 0; i < nodes.length; i++) {
-			var tab_name = this.tab_names[i],
-			    tab_data = this.tabs[tab_name],
-			    containerEl = E('div', {
-			    	'id': 'container.%s.%s.%s'.format(config_name, section_id, tab_name),
-			    	'data-tab': tab_name,
-			    	'data-tab-title': tab_data.title,
-			    	'data-tab-active': tab_name === this.selected_tab
-			    });
-
-			if (tab_data.description != null && tab_data.description != '')
-				containerEl.appendChild(
-					E('div', { 'class': 'cbi-tab-descr' }, tab_data.description));
-
-			containerEl.appendChild(nodes[i]);
-			containerEls.appendChild(containerEl);
-		}
-
-		return containerEls;
-	},
-
-	/** @private */
-	renderOptions: function(tab_name, section_id) {
-		var in_table = (this instanceof CBITableSection);
-		return this.renderChildren(tab_name, section_id, in_table).then(function(nodes) {
-			var optionEls = E([]);
-			for (var i = 0; i < nodes.length; i++)
-				optionEls.appendChild(nodes[i]);
-			return optionEls;
-		});
-	},
-
-	/** @private */
-	checkDepends: function(ev, n) {
-		var changed = false,
-		    sids = this.cfgsections();
-
-		for (var i = 0, sid = sids[0]; (sid = sids[i]) != null; i++) {
-			for (var j = 0, o = this.children[0]; (o = this.children[j]) != null; j++) {
-				var isActive = o.isActive(sid),
-				    isSatisified = o.checkDepends(sid);
-
-				if (isActive != isSatisified) {
-					o.setActive(sid, !isActive);
-					isActive = !isActive;
-					changed = true;
-				}
-
-				if (!n && isActive)
-					o.triggerValidation(sid);
-			}
-		}
-
-		return changed;
-	}
-});
-
-
-var isEqual = function(x, y) {
-	if (typeof(y) == 'object' && y instanceof RegExp)
-		return (x == null) ? false : y.test(x);
-
-	if (x != null && y != null && typeof(x) != typeof(y))
-		return false;
-
-	if ((x == null && y != null) || (x != null && y == null))
-		return false;
-
-	if (Array.isArray(x)) {
-		if (x.length != y.length)
-			return false;
-
-		for (var i = 0; i < x.length; i++)
-			if (!isEqual(x[i], y[i]))
-				return false;
-	}
-	else if (typeof(x) == 'object') {
-		for (var k in x) {
-			if (x.hasOwnProperty(k) && !y.hasOwnProperty(k))
-				return false;
-
-			if (!isEqual(x[k], y[k]))
-				return false;
-		}
-
-		for (var k in y)
-			if (y.hasOwnProperty(k) && !x.hasOwnProperty(k))
-				return false;
-	}
-	else if (x != y) {
-		return false;
-	}
-
-	return true;
-};
-
-var isContained = function(x, y) {
-	if (Array.isArray(x)) {
-		for (var i = 0; i < x.length; i++)
-			if (x[i] == y)
-				return true;
-	}
-	else if (L.isObject(x)) {
-		if (x.hasOwnProperty(y) && x[y] != null)
-			return true;
-	}
-	else if (typeof(x) == 'string') {
-		return (x.indexOf(y) > -1);
-	}
-
-	return false;
-};
-
-/**
- * @class AbstractValue
- * @memberof LuCI.form
- * @augments LuCI.form.AbstractElement
- * @hideconstructor
- * @classdesc
- *
- * The `AbstractValue` class serves as abstract base for the different form
- * option styles implemented by `LuCI.form`. It provides the common logic for
- * handling option input values, for dependencies among options and for
- * validation constraints that should be applied to entered values.
- *
- * This class is private and not directly accessible by user code.
- */
-var CBIAbstractValue = CBIAbstractElement.extend(/** @lends LuCI.form.AbstractValue.prototype */ {
-	__init__: function(map, section, option /*, ... */) {
-		this.super('__init__', this.varargs(arguments, 3));
-
-		this.section = section;
-		this.option = option;
-		this.map = map;
-		this.config = map.config;
-
-		this.deps = [];
-		this.initial = {};
-		this.rmempty = true;
-		this.default = null;
-		this.size = null;
-		this.optional = false;
-	},
-
-	/**
-	 * If set to `false`, the underlying option value is retained upon saving
-	 * the form when the option element is disabled due to unsatisfied
-	 * dependency constraints.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#rmempty
-	 * @type boolean
-	 * @default true
-	 */
-
-	/**
-	 * If set to `true`, the underlying ui input widget is allowed to be empty,
-	 * otherwise the option element is marked invalid when no value is entered
-	 * or selected by the user.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#optional
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Sets a default value to use when the underlying UCI option is not set.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#default
-	 * @type *
-	 * @default null
-	 */
-
-	/**
-	 * Specifies a datatype constraint expression to validate input values
-	 * against. Refer to {@link LuCI.validation} for details on the format.
-	 *
-	 * If the user entered input does not match the datatype validation, the
-	 * option element is marked as invalid.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#datatype
-	 * @type string
-	 * @default null
-	 */
-
-	/**
-	 * Specifies a custom validation function to test the user input for
-	 * validity. The validation function must return `true` to accept the
-	 * value. Any other return value type is converted to a string and
-	 * displayed to the user as validation error message.
-	 *
-	 * If the user entered input does not pass the validation function, the
-	 * option element is marked as invalid.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#validate
-	 * @type function
-	 * @default null
-	 */
-
-	/**
-	 * Override the UCI configuration name to read the option value from.
-	 *
-	 * By default, the configuration name is inherited from the parent Map.
-	 * By setting this property, a deviating configuration may be specified.
-	 *
-	 * The default is null, means inheriting from the parent form.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#uciconfig
-	 * @type string
-	 * @default null
-	 */
-
-	/**
-	 * Override the UCI section name to read the option value from.
-	 *
-	 * By default, the section ID is inherited from the parent section element.
-	 * By setting this property, a deviating section may be specified.
-	 *
-	 * The default is null, means inheriting from the parent section.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#ucisection
-	 * @type string
-	 * @default null
-	 */
-
-	/**
-	 * Override the UCI option name to read the value from.
-	 *
-	 * By default, the elements name, which is passed as third argument to
-	 * the constructor, is used as UCI option name. By setting this property,
-	 * a deviating UCI option may be specified.
-	 *
-	 * The default is null, means using the option element name.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#ucioption
-	 * @type string
-	 * @default null
-	 */
-
-	/**
-	 * Mark grid section option element as editable.
-	 *
-	 * Options which are displayed in the table portion of a `GridSection`
-	 * instance are rendered as readonly text by default. By setting the
-	 * `editable` property of a child option element to `true`, that element
-	 * is rendered as full input widget within its cell instead of a text only
-	 * preview.
-	 *
-	 * This property has no effect on options that are not children of grid
-	 * section elements.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#editable
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Move grid section option element into the table, the modal popup or both.
-	 *
-	 * If this property is `null` (the default), the option element is
-	 * displayed in both the table preview area and the per-section instance
-	 * modal popup of a grid section. When it is set to `false` the option
-	 * is only shown in the table but not the modal popup. When set to `true`,
-	 * the option is only visible in the modal popup but not the table.
-	 *
-	 * This property has no effect on options that are not children of grid
-	 * section elements.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#modalonly
-	 * @type boolean
-	 * @default null
-	 */
-
-	/**
-	 * Make option element readonly.
-	 *
-	 * This property defaults to the readonly state of the parent form element.
-	 * When set to `true`, the underlying widget is rendered in disabled state,
-	 * means its contents cannot be changed and the widget cannot be interacted
-	 * with.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#readonly
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Override the cell width of a table or grid section child option.
-	 *
-	 * If the property is set to a numeric value, it is treated as pixel width
-	 * which is set on the containing cell element of the option, essentially
-	 * forcing a certain column width. When the property is set to a string
-	 * value, it is applied as-is to the CSS `width` property.
-	 *
-	 * This property has no effect on options that are not children of grid or
-	 * table section elements.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#width
-	 * @type number|string
-	 * @default null
-	 */
-
-	/**
-	 * Register a custom value change handler.
-	 *
-	 * If this property is set to a function value, the function is invoked
-	 * whenever the value of the underlying UI input element is changing.
-	 *
-	 * The invoked handler function will receive the DOM click element as
-	 * first and the underlying configuration section ID as well as the input
-	 * value as second and third argument respectively.
-	 *
-	 * @name LuCI.form.AbstractValue.prototype#onchange
-	 * @type function
-	 * @default null
-	 */
-
-	/**
-	 * Add a dependency contraint to the option.
-	 *
-	 * Dependency constraints allow making the presence of option elements
-	 * dependant on the current values of certain other options within the
-	 * same form. An option element with unsatisfied dependencies will be
-	 * hidden from the view and its current value is omitted when saving.
-	 *
-	 * Multiple constraints (that is, multiple calls to `depends()`) are
-	 * treated as alternatives, forming a logical "or" expression.
-	 *
-	 * By passing an object of name => value pairs as first argument, it is
-	 * possible to depend on multiple options simultaneously, allowing to form
-	 * a logical "and" expression.
-	 *
-	 * Option names may be given in "dot notation" which allows to reference
-	 * option elements outside of the current form section. If a name without
-	 * dot is specified, it refers to an option within the same configuration
-	 * section. If specified as <code>configname.sectionid.optionname</code>,
-	 * options anywhere within the same form may be specified.
-	 *
-	 * The object notation also allows for a number of special keys which are
-	 * not treated as option names but as modifiers to influence the dependency
-	 * constraint evaluation. The associated value of these special "tag" keys
-	 * is ignored. The recognized tags are:
-	 *
-	 * <ul>
-	 *   <li>
-	 *    <code>!reverse</code><br>
-	 *    Invert the dependency, instead of requiring another option to be
-	 *    equal to the dependency value, that option should <em>not</em> be
-	 *    equal.
-	 *   </li>
-	 *   <li>
-	 *    <code>!contains</code><br>
-	 *    Instead of requiring an exact match, the dependency is considered
-	 *    satisfied when the dependency value is contained within the option
-	 *    value.
-	 *   </li>
-	 *   <li>
-	 *    <code>!default</code><br>
-	 *    The dependency is always satisfied
-	 *   </li>
-	 * </ul>
-	 *
-	 * Examples:
-	 *
-	 * <ul>
-	 *  <li>
-	 *   <code>opt.depends("foo", "test")</code><br>
-	 *   Require the value of `foo` to be `test`.
-	 *  </li>
-	 *  <li>
-	 *   <code>opt.depends({ foo: "test" })</code><br>
-	 *   Equivalent to the previous example.
-	 *  </li>
-	 *  <li>
-	 *   <code>opt.depends({ foo: /test/ })</code><br>
-	 *   Require the value of `foo` to match the regular expression `/test/`.
-	 *  </li>
-	 *  <li>
-	 *   <code>opt.depends({ foo: "test", bar: "qrx" })</code><br>
-	 *   Require the value of `foo` to be `test` and the value of `bar` to be
-	 *   `qrx`.
-	 *  </li>
-	 *  <li>
-	 *   <code>opt.depends({ foo: "test" })<br>
-	 *         opt.depends({ bar: "qrx" })</code><br>
-	 *   Require either <code>foo</code> to be set to <code>test</code>,
-	 *   <em>or</em> the <code>bar</code> option to be <code>qrx</code>.
-	 *  </li>
-	 *  <li>
-	 *   <code>opt.depends("test.section1.foo", "bar")</code><br>
-	 *   Require the "foo" form option within the "section1" section to be
-	 *   set to "bar".
-	 *  </li>
-	 *  <li>
-	 *   <code>opt.depends({ foo: "test", "!contains": true })</code><br>
-	 *   Require the "foo" option value to contain the substring "test".
-	 *  </li>
-	 * </ul>
-	 *
-	 * @param {string|Object<string, string|RegExp>} optionname_or_depends
-	 * The name of the option to depend on or an object describing multiple
-	 * dependencies which must be satified (a logical "and" expression).
-	 *
-	 * @param {string} optionvalue|RegExp
-	 * When invoked with a plain option name as first argument, this parameter
-	 * specifies the expected value. In case an object is passed as first
-	 * argument, this parameter is ignored.
-	 */
-	depends: function(field, value) {
-		var deps;
-
-		if (typeof(field) === 'string')
-			deps = {}, deps[field] = value;
-		else
-			deps = field;
-
-		this.deps.push(deps);
-	},
-
-	/** @private */
-	transformDepList: function(section_id, deplist) {
-		var list = deplist || this.deps,
-		    deps = [];
-
-		if (Array.isArray(list)) {
-			for (var i = 0; i < list.length; i++) {
-				var dep = {};
-
-				for (var k in list[i]) {
-					if (list[i].hasOwnProperty(k)) {
-						if (k.charAt(0) === '!')
-							dep[k] = list[i][k];
-						else if (k.indexOf('.') !== -1)
-							dep['cbid.%s'.format(k)] = list[i][k];
-						else
-							dep['cbid.%s.%s.%s'.format(
-								this.uciconfig || this.section.uciconfig || this.map.config,
-								this.ucisection || section_id,
-								k
-							)] = list[i][k];
-					}
-				}
-
-				for (var k in dep) {
-					if (dep.hasOwnProperty(k)) {
-						deps.push(dep);
-						break;
-					}
-				}
-			}
-		}
-
-		return deps;
-	},
-
-	/** @private */
-	transformChoices: function() {
-		if (!Array.isArray(this.keylist) || this.keylist.length == 0)
-			return null;
-
-		var choices = {};
-
-		for (var i = 0; i < this.keylist.length; i++)
-			choices[this.keylist[i]] = this.vallist[i];
-
-		return choices;
-	},
-
-	/** @private */
-	checkDepends: function(section_id) {
-		var config_name = this.uciconfig || this.section.uciconfig || this.map.config,
-		    active = this.map.isDependencySatisfied(this.deps, config_name, section_id);
-
-		if (active)
-			this.updateDefaultValue(section_id);
-
-		return active;
-	},
-
-	/** @private */
-	updateDefaultValue: function(section_id) {
-		if (!L.isObject(this.defaults))
-			return;
-
-		var config_name = this.uciconfig || this.section.uciconfig || this.map.config,
-		    cfgvalue = L.toArray(this.cfgvalue(section_id))[0],
-		    default_defval = null, satisified_defval = null;
-
-		for (var value in this.defaults) {
-			if (!this.defaults[value] || this.defaults[value].length == 0) {
-				default_defval = value;
-				continue;
-			}
-			else if (this.map.isDependencySatisfied(this.defaults[value], config_name, section_id)) {
-				satisified_defval = value;
-				break;
-			}
-		}
-
-		if (satisified_defval == null)
-			satisified_defval = default_defval;
-
-		var node = this.map.findElement('id', this.cbid(section_id));
-		if (node && node.getAttribute('data-changed') != 'true' && satisified_defval != null && cfgvalue == null)
-			dom.callClassMethod(node, 'setValue', satisified_defval);
-
-		this.default = satisified_defval;
-	},
-
-	/**
-	 * Obtain the internal ID ("cbid") of the element instance.
-	 *
-	 * Since each form section element may map multiple underlying
-	 * configuration sections, the configuration section ID is required to
-	 * form a fully qualified ID pointing to the specific element instance
-	 * within the given specific section.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @throws {TypeError}
-	 * Throws a `TypeError` exception when no `section_id` was specified.
-	 *
-	 * @returns {string}
-	 * Returns the element ID.
-	 */
-	cbid: function(section_id) {
-		if (section_id == null)
-			L.error('TypeError', 'Section ID required');
-
-		return 'cbid.%s.%s.%s'.format(
-			this.uciconfig || this.section.uciconfig || this.map.config,
-			section_id, this.option);
-	},
-
-	/**
-	 * Load the underlying configuration value.
-	 *
-	 * The default implementation of this method reads and returns the
-	 * underlying UCI option value (or the related JavaScript property for
-	 * `JSONMap` instances). It may be overwritten by user code to load data
-	 * from nonstandard sources.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @throws {TypeError}
-	 * Throws a `TypeError` exception when no `section_id` was specified.
-	 *
-	 * @returns {*|Promise<*>}
-	 * Returns the configuration value to initialize the option element with.
-	 * The return value of this function is filtered through `Promise.resolve()`
-	 * so it may return promises if overridden by user code.
-	 */
-	load: function(section_id) {
-		if (section_id == null)
-			L.error('TypeError', 'Section ID required');
-
-		return this.map.data.get(
-			this.uciconfig || this.section.uciconfig || this.map.config,
-			this.ucisection || section_id,
-			this.ucioption || this.option);
-	},
-
-	/**
-	 * Obtain the underlying `LuCI.ui` element instance.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @throws {TypeError}
-	 * Throws a `TypeError` exception when no `section_id` was specified.
-	 *
-	 * @return {LuCI.ui.AbstractElement|null}
-	 * Returns the `LuCI.ui` element instance or `null` in case the form
-	 * option implementation does not use `LuCI.ui` widgets.
-	 */
-	getUIElement: function(section_id) {
-		var node = this.map.findElement('id', this.cbid(section_id)),
-		    inst = node ? dom.findClassInstance(node) : null;
-		return (inst instanceof ui.AbstractElement) ? inst : null;
-	},
-
-	/**
-	 * Query the underlying configuration value.
-	 *
-	 * The default implementation of this method returns the cached return
-	 * value of [load()]{@link LuCI.form.AbstractValue#load}. It may be
-	 * overwritten by user code to obtain the configuration value in a
-	 * different way.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @throws {TypeError}
-	 * Throws a `TypeError` exception when no `section_id` was specified.
-	 *
-	 * @returns {*}
-	 * Returns the configuration value.
-	 */
-	cfgvalue: function(section_id, set_value) {
-		if (section_id == null)
-			L.error('TypeError', 'Section ID required');
-
-		if (arguments.length == 2) {
-			this.data = this.data || {};
-			this.data[section_id] = set_value;
-		}
-
-		return this.data ? this.data[section_id] : null;
-	},
-
-	/**
-	 * Query the current form input value.
-	 *
-	 * The default implementation of this method returns the current input
-	 * value of the underlying [LuCI.ui]{@link LuCI.ui.AbstractElement} widget.
-	 * It may be overwritten by user code to handle input values differently.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @throws {TypeError}
-	 * Throws a `TypeError` exception when no `section_id` was specified.
-	 *
-	 * @returns {*}
-	 * Returns the current input value.
-	 */
-	formvalue: function(section_id) {
-		var elem = this.getUIElement(section_id);
-		return elem ? elem.getValue() : null;
-	},
-
-	/**
-	 * Obtain a textual input representation.
-	 *
-	 * The default implementation of this method returns the HTML escaped
-	 * current input value of the underlying
-	 * [LuCI.ui]{@link LuCI.ui.AbstractElement} widget. User code or specific
-	 * option element implementations may overwrite this function to apply a
-	 * different logic, e.g. to return `Yes` or `No` depending on the checked
-	 * state of checkbox elements.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @throws {TypeError}
-	 * Throws a `TypeError` exception when no `section_id` was specified.
-	 *
-	 * @returns {string}
-	 * Returns the text representation of the current input value.
-	 */
-	textvalue: function(section_id) {
-		var cval = this.cfgvalue(section_id);
-
-		if (cval == null)
-			cval = this.default;
-
-		return (cval != null) ? '%h'.format(cval) : null;
-	},
-
-	/**
-	 * Apply custom validation logic.
-	 *
-	 * This method is invoked whenever incremental validation is performed on
-	 * the user input, e.g. on keyup or blur events.
-	 *
-	 * The default implementation of this method does nothing and always
-	 * returns `true`. User code may overwrite this method to provide
-	 * additional validation logic which is not covered by data type
-	 * constraints.
-	 *
-	 * @abstract
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @param {*} value
-	 * The value to validate
-	 *
-	 * @returns {*}
-	 * The method shall return `true` to accept the given value. Any other
-	 * return value is treated as failure, converted to a string and displayed
-	 * as error message to the user.
-	 */
-	validate: function(section_id, value) {
-		return true;
-	},
-
-	/**
-	 * Test whether the input value is currently valid.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @returns {boolean}
-	 * Returns `true` if the input value currently is valid, otherwise it
-	 * returns `false`.
-	 */
-	isValid: function(section_id) {
-		var elem = this.getUIElement(section_id);
-		return elem ? elem.isValid() : true;
-	},
-
-	/**
-	 * Test whether the option element is currently active.
-	 *
-	 * An element is active when it is not hidden due to unsatisfied dependency
-	 * constraints.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @returns {boolean}
-	 * Returns `true` if the option element currently is active, otherwise it
-	 * returns `false`.
-	 */
-	isActive: function(section_id) {
-		var field = this.map.findElement('data-field', this.cbid(section_id));
-		return (field != null && !field.classList.contains('hidden'));
-	},
-
-	/** @private */
-	setActive: function(section_id, active) {
-		var field = this.map.findElement('data-field', this.cbid(section_id));
-
-		if (field && field.classList.contains('hidden') == active) {
-			field.classList[active ? 'remove' : 'add']('hidden');
-
-			if (dom.matches(field.parentNode, '.td.cbi-value-field'))
-				field.parentNode.classList[active ? 'remove' : 'add']('inactive');
-
-			return true;
-		}
-
-		return false;
-	},
-
-	/** @private */
-	triggerValidation: function(section_id) {
-		var elem = this.getUIElement(section_id);
-		return elem ? elem.triggerValidation() : true;
-	},
-
-	/**
-	 * Parse the option element input.
-	 *
-	 * The function is invoked when the `parse()` method has been invoked on
-	 * the parent form and triggers input value reading and validation.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @returns {Promise<void>}
-	 * Returns a promise resolving once the input value has been read and
-	 * validated or rejecting in case the input value does not meet the
-	 * validation constraints.
-	 */
-	parse: function(section_id) {
-		var active = this.isActive(section_id),
-		    cval = this.cfgvalue(section_id),
-		    fval = active ? this.formvalue(section_id) : null;
-
-		if (active && !this.isValid(section_id)) {
-			var title = this.stripTags(this.title).trim();
-			return Promise.reject(new TypeError(_('Option "%s" contains an invalid input value.').format(title || this.option)));
-		}
-
-		if (fval != '' && fval != null) {
-			if (this.forcewrite || !isEqual(cval, fval))
-				return Promise.resolve(this.write(section_id, fval));
-		}
-		else {
-			if (!active || this.rmempty || this.optional) {
-				return Promise.resolve(this.remove(section_id));
-			}
-			else if (!isEqual(cval, fval)) {
-				var title = this.stripTags(this.title).trim();
-				return Promise.reject(new TypeError(_('Option "%s" must not be empty.').format(title || this.option)));
-			}
-		}
-
-		return Promise.resolve();
-	},
-
-	/**
-	 * Write the current input value into the configuration.
-	 *
-	 * This function is invoked upon saving the parent form when the option
-	 * element is valid and when its input value has been changed compared to
-	 * the initial value returned by
-	 * [cfgvalue()]{@link LuCI.form.AbstractValue#cfgvalue}.
-	 *
-	 * The default implementation simply sets the given input value in the
-	 * UCI configuration (or the associated JavaScript object property in
-	 * case of `JSONMap` forms). It may be overwritten by user code to
-	 * implement alternative save logic, e.g. to transform the input value
-	 * before it is written.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 *
-	 * @param {string|string[]}	formvalue
-	 * The input value to write.
-	 */
-	write: function(section_id, formvalue) {
-		return this.map.data.set(
-			this.uciconfig || this.section.uciconfig || this.map.config,
-			this.ucisection || section_id,
-			this.ucioption || this.option,
-			formvalue);
-	},
-
-	/**
-	 * Remove the corresponding value from the configuration.
-	 *
-	 * This function is invoked upon saving the parent form when the option
-	 * element has been hidden due to unsatisfied dependencies or when the
-	 * user cleared the input value and the option is marked optional.
-	 *
-	 * The default implementation simply removes the associated option from the
-	 * UCI configuration (or the associated JavaScript object property in
-	 * case of `JSONMap` forms). It may be overwritten by user code to
-	 * implement alternative removal logic, e.g. to retain the original value.
-	 *
-	 * @param {string} section_id
-	 * The configuration section ID
-	 */
-	remove: function(section_id) {
-		return this.map.data.unset(
-			this.uciconfig || this.section.uciconfig || this.map.config,
-			this.ucisection || section_id,
-			this.ucioption || this.option);
-	}
-});
-
-/**
- * @class TypedSection
- * @memberof LuCI.form
- * @augments LuCI.form.AbstractSection
- * @hideconstructor
- * @classdesc
- *
- * The `TypedSection` class maps all or - if `filter()` is overwritten - a
- * subset of the underlying UCI configuration sections of a given type.
- *
- * Layout wise, the configuration section instances mapped by the section
- * element (sometimes referred to as "section nodes") are stacked beneath
- * each other in a single column, with an optional section remove button next
- * to each section node and a section add button at the end, depending on the
- * value of the `addremove` property.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [section()]{@link LuCI.form.Map#section}.
- *
- * @param {string} section_type
- * The type of the UCI section to map.
- *
- * @param {string} [title]
- * The title caption of the form section element.
- *
- * @param {string} [description]
- * The description text of the form section element.
- */
-var CBITypedSection = CBIAbstractSection.extend(/** @lends LuCI.form.TypedSection.prototype */ {
-	__name__: 'CBI.TypedSection',
-
-	/**
-	 * If set to `true`, the user may add or remove instances from the form
-	 * section widget, otherwise only preexisting sections may be edited.
-	 * The default is `false`.
-	 *
-	 * @name LuCI.form.TypedSection.prototype#addremove
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * If set to `true`, mapped section instances are treated as anonymous
-	 * UCI sections, which means that section instance elements will be
-	 * rendered without title element and that no name is required when adding
-	 * new sections. The default is `false`.
-	 *
-	 * @name LuCI.form.TypedSection.prototype#anonymous
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * When set to `true`, instead of rendering section instances one below
-	 * another, treat each instance as separate tab pane and render a tab menu
-	 * at the top of the form section element, allowing the user to switch
-	 * among instances. The default is `false`.
-	 *
-	 * @name LuCI.form.TypedSection.prototype#tabbed
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Override the caption used for the section add button at the bottom of
-	 * the section form element. If set to a string, it will be used as-is,
-	 * if set to a function, the function will be invoked and its return value
-	 * is used as caption, after converting it to a string. If this property
-	 * is not set, the default is `Add`.
-	 *
-	 * @name LuCI.form.TypedSection.prototype#addbtntitle
-	 * @type string|function
-	 * @default null
-	 */
-
-	/**
-	 * Override the UCI configuration name to read the section IDs from. By
-	 * default, the configuration name is inherited from the parent `Map`.
-	 * By setting this property, a deviating configuration may be specified.
-	 * The default is `null`, means inheriting from the parent form.
-	 *
-	 * @name LuCI.form.TypedSection.prototype#uciconfig
-	 * @type string
-	 * @default null
-	 */
-
-	/** @override */
-	cfgsections: function() {
-		return this.map.data.sections(this.uciconfig || this.map.config, this.sectiontype)
-			.map(function(s) { return s['.name'] })
-			.filter(L.bind(this.filter, this));
-	},
-
-	/** @private */
-	handleAdd: function(ev, name) {
-		var config_name = this.uciconfig || this.map.config;
-
-		this.map.data.add(config_name, this.sectiontype, name);
-		return this.map.save(null, true);
-	},
-
-	/** @private */
-	handleRemove: function(section_id, ev) {
-		var config_name = this.uciconfig || this.map.config;
-
-		this.map.data.remove(config_name, section_id);
-		return this.map.save(null, true);
-	},
-
-	/** @private */
-	renderSectionAdd: function(extra_class) {
-		if (!this.addremove)
-			return E([]);
-
-		var createEl = E('div', { 'class': 'cbi-section-create' }),
-		    config_name = this.uciconfig || this.map.config,
-		    btn_title = this.titleFn('addbtntitle');
-
-		if (extra_class != null)
-			createEl.classList.add(extra_class);
-
-		if (this.anonymous) {
-			createEl.appendChild(E('button', {
-				'class': 'cbi-button cbi-button-add',
-				'title': btn_title || _('Add'),
-				'click': ui.createHandlerFn(this, 'handleAdd'),
-				'disabled': this.map.readonly || null
-			}, [ btn_title || _('Add') ]));
-		}
-		else {
-			var nameEl = E('input', {
-				'type': 'text',
-				'class': 'cbi-section-create-name',
-				'disabled': this.map.readonly || null
-			});
-
-			dom.append(createEl, [
-				E('div', {}, nameEl),
-				E('input', {
-					'class': 'cbi-button cbi-button-add',
-					'type': 'submit',
-					'value': btn_title || _('Add'),
-					'title': btn_title || _('Add'),
-					'click': ui.createHandlerFn(this, function(ev) {
-						if (nameEl.classList.contains('cbi-input-invalid'))
-							return;
-
-						return this.handleAdd(ev, nameEl.value);
-					}),
-					'disabled': this.map.readonly || null
-				})
-			]);
-
-			ui.addValidator(nameEl, 'uciname', true, 'blur', 'keyup');
-		}
-
-		return createEl;
-	},
-
-	/** @private */
-	renderSectionPlaceholder: function() {
-		return E([
-			E('em', _('This section contains no values yet')),
-			E('br'), E('br')
-		]);
-	},
-
-	/** @private */
-	renderContents: function(cfgsections, nodes) {
-		var section_id = null,
-		    config_name = this.uciconfig || this.map.config,
-		    sectionEl = E('div', {
-				'id': 'cbi-%s-%s'.format(config_name, this.sectiontype),
-				'class': 'cbi-section',
-				'data-tab': (this.map.tabbed && !this.parentoption) ? this.sectiontype : null,
-				'data-tab-title': (this.map.tabbed && !this.parentoption) ? this.title || this.sectiontype : null
-			});
-
-		if (this.title != null && this.title != '')
-			sectionEl.appendChild(E('legend', {}, this.title));
-
-		if (this.description != null && this.description != '')
-			sectionEl.appendChild(E('div', { 'class': 'cbi-section-descr' }, this.description));
-
-		for (var i = 0; i < nodes.length; i++) {
-			if (this.addremove) {
-				sectionEl.appendChild(
-					E('div', { 'class': 'cbi-section-remove right' },
-						E('button', {
-							'class': 'cbi-button',
-							'name': 'cbi.rts.%s.%s'.format(config_name, cfgsections[i]),
-							'data-section-id': cfgsections[i],
-							'click': ui.createHandlerFn(this, 'handleRemove', cfgsections[i]),
-							'disabled': this.map.readonly || null
-						}, [ _('Delete') ])));
-			}
-
-			if (!this.anonymous)
-				sectionEl.appendChild(E('h3', cfgsections[i].toUpperCase()));
-
-			sectionEl.appendChild(E('div', {
-				'id': 'cbi-%s-%s'.format(config_name, cfgsections[i]),
-				'class': this.tabs
-					? 'cbi-section-node cbi-section-node-tabbed' : 'cbi-section-node',
-				'data-section-id': cfgsections[i]
-			}, nodes[i]));
-		}
-
-		if (nodes.length == 0)
-			sectionEl.appendChild(this.renderSectionPlaceholder());
-
-		sectionEl.appendChild(this.renderSectionAdd());
-
-		dom.bindClassInstance(sectionEl, this);
-
-		return sectionEl;
-	},
-
-	/** @override */
-	render: function() {
-		var cfgsections = this.cfgsections(),
-		    renderTasks = [];
-
-		for (var i = 0; i < cfgsections.length; i++)
-			renderTasks.push(this.renderUCISection(cfgsections[i]));
-
-		return Promise.all(renderTasks).then(this.renderContents.bind(this, cfgsections));
-	}
-});
-
-/**
- * @class TableSection
- * @memberof LuCI.form
- * @augments LuCI.form.TypedSection
- * @hideconstructor
- * @classdesc
- *
- * The `TableSection` class maps all or - if `filter()` is overwritten - a
- * subset of the underlying UCI configuration sections of a given type.
- *
- * Layout wise, the configuration section instances mapped by the section
- * element (sometimes referred to as "section nodes") are rendered as rows
- * within an HTML table element, with an optional section remove button in the
- * last column and a section add button below the table, depending on the
- * value of the `addremove` property.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [section()]{@link LuCI.form.Map#section}.
- *
- * @param {string} section_type
- * The type of the UCI section to map.
- *
- * @param {string} [title]
- * The title caption of the form section element.
- *
- * @param {string} [description]
- * The description text of the form section element.
- */
-var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.prototype */ {
-	__name__: 'CBI.TableSection',
-
-	/**
-	 * If set to `true`, the user may add or remove instances from the form
-	 * section widget, otherwise only preexisting sections may be edited.
-	 * The default is `false`.
-	 *
-	 * @name LuCI.form.TableSection.prototype#addremove
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * If set to `true`, mapped section instances are treated as anonymous
-	 * UCI sections, which means that section instance elements will be
-	 * rendered without title element and that no name is required when adding
-	 * new sections. The default is `false`.
-	 *
-	 * @name LuCI.form.TableSection.prototype#anonymous
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Override the caption used for the section add button at the bottom of
-	 * the section form element. If set to a string, it will be used as-is,
-	 * if set to a function, the function will be invoked and its return value
-	 * is used as caption, after converting it to a string. If this property
-	 * is not set, the default is `Add`.
-	 *
-	 * @name LuCI.form.TableSection.prototype#addbtntitle
-	 * @type string|function
-	 * @default null
-	 */
-
-	/**
-	 * Override the per-section instance title caption shown in the first
-	 * column of the table unless `anonymous` is set to true. If set to a
-	 * string, it will be used as `String.format()` pattern with the name of
-	 * the underlying UCI section as first argument, if set to a function, the
-	 * function will be invoked with the section name as first argument and
-	 * its return value is used as caption, after converting it to a string.
-	 * If this property is not set, the default is the name of the underlying
-	 * UCI configuration section.
-	 *
-	 * @name LuCI.form.TableSection.prototype#sectiontitle
-	 * @type string|function
-	 * @default null
-	 */
-
-	/**
-	 * Override the per-section instance modal popup title caption shown when
-	 * clicking the `More…` button in a section specifying `max_cols`. If set
-	 * to a string, it will be used as `String.format()` pattern with the name
-	 * of the underlying UCI section as first argument, if set to a function,
-	 * the function will be invoked with the section name as first argument and
-	 * its return value is used as caption, after converting it to a string.
-	 * If this property is not set, the default is the name of the underlying
-	 * UCI configuration section.
-	 *
-	 * @name LuCI.form.TableSection.prototype#modaltitle
-	 * @type string|function
-	 * @default null
-	 */
-
-	/**
-	 * Override the UCI configuration name to read the section IDs from. By
-	 * default, the configuration name is inherited from the parent `Map`.
-	 * By setting this property, a deviating configuration may be specified.
-	 * The default is `null`, means inheriting from the parent form.
-	 *
-	 * @name LuCI.form.TableSection.prototype#uciconfig
-	 * @type string
-	 * @default null
-	 */
-
-	/**
-	 * Specify a maximum amount of columns to display. By default, one table
-	 * column is rendered for each child option of the form section element.
-	 * When this option is set to a positive number, then no more columns than
-	 * the given amount are rendered. When the number of child options exceeds
-	 * the specified amount, a `More…` button is rendered in the last column,
-	 * opening a modal dialog presenting all options elements in `NamedSection`
-	 * style when clicked.
-	 *
-	 * @name LuCI.form.TableSection.prototype#max_cols
-	 * @type number
-	 * @default null
-	 */
-
-	/**
-	 * If set to `true`, alternating `cbi-rowstyle-1` and `cbi-rowstyle-2` CSS
-	 * classes are added to the table row elements. Not all LuCI themes
-	 * implement these row style classes. The default is `false`.
-	 *
-	 * @name LuCI.form.TableSection.prototype#rowcolors
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Enables a per-section instance row `Edit` button which triggers a certain
-	 * action when clicked. If set to a string, the string value is used
-	 * as `String.format()` pattern with the name of the underlying UCI section
-	 * as first format argument. The result is then interpreted as URL which
-	 * LuCI will navigate to when the user clicks the edit button.
-	 *
-	 * If set to a function, this function will be registered as click event
-	 * handler on the rendered edit button, receiving the section instance
-	 * name as first and the DOM click event as second argument.
-	 *
-	 * @name LuCI.form.TableSection.prototype#extedit
-	 * @type string|function
-	 * @default null
-	 */
-
-	/**
-	 * If set to `true`, a sort button is added to the last column, allowing
-	 * the user to reorder the section instances mapped by the section form
-	 * element.
-	 *
-	 * @name LuCI.form.TableSection.prototype#sortable
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * If set to `true`, the header row with the options descriptions will
-	 * not be displayed. By default, descriptions row is automatically displayed
-	 * when at least one option has a description.
-	 *
-	 * @name LuCI.form.TableSection.prototype#nodescriptions
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * The `TableSection` implementation does not support option tabbing, so
-	 * its implementation of `tab()` will always throw an exception when
-	 * invoked.
-	 *
-	 * @override
-	 * @throws Throws an exception when invoked.
-	 */
-	tab: function() {
-		throw 'Tabs are not supported by TableSection';
-	},
-
-	/** @private */
-	renderContents: function(cfgsections, nodes) {
-		var section_id = null,
-		    config_name = this.uciconfig || this.map.config,
-		    max_cols = isNaN(this.max_cols) ? this.children.length : this.max_cols,
-		    has_more = max_cols < this.children.length,
-		    sectionEl = E('div', {
-				'id': 'cbi-%s-%s'.format(config_name, this.sectiontype),
-				'class': 'cbi-section cbi-tblsection',
-				'data-tab': (this.map.tabbed && !this.parentoption) ? this.sectiontype : null,
-				'data-tab-title': (this.map.tabbed && !this.parentoption) ? this.title || this.sectiontype : null
-			}),
-			tableEl = E('div', {
-				'class': 'table cbi-section-table'
-			});
-
-		if (this.title != null && this.title != '')
-			sectionEl.appendChild(E('h3', {}, this.title));
-
-		if (this.description != null && this.description != '')
-			sectionEl.appendChild(E('div', { 'class': 'cbi-section-descr' }, this.description));
-
-		tableEl.appendChild(this.renderHeaderRows(max_cols));
-
-		for (var i = 0; i < nodes.length; i++) {
-			var sectionname = this.titleFn('sectiontitle', cfgsections[i]);
-
-			if (sectionname == null)
-				sectionname = cfgsections[i];
-
-			var trEl = E('div', {
-				'id': 'cbi-%s-%s'.format(config_name, cfgsections[i]),
-				'class': 'tr cbi-section-table-row',
-				'data-sid': cfgsections[i],
-				'draggable': this.sortable ? true : null,
-				'mousedown': this.sortable ? L.bind(this.handleDragInit, this) : null,
-				'dragstart': this.sortable ? L.bind(this.handleDragStart, this) : null,
-				'dragover': this.sortable ? L.bind(this.handleDragOver, this) : null,
-				'dragenter': this.sortable ? L.bind(this.handleDragEnter, this) : null,
-				'dragleave': this.sortable ? L.bind(this.handleDragLeave, this) : null,
-				'dragend': this.sortable ? L.bind(this.handleDragEnd, this) : null,
-				'drop': this.sortable ? L.bind(this.handleDrop, this) : null,
-				'data-title': (sectionname && (!this.anonymous || this.sectiontitle)) ? sectionname : null,
-				'data-section-id': cfgsections[i]
-			});
-
-			if (this.extedit || this.rowcolors)
-				trEl.classList.add(!(tableEl.childNodes.length % 2)
-					? 'cbi-rowstyle-1' : 'cbi-rowstyle-2');
-
-			for (var j = 0; j < max_cols && nodes[i].firstChild; j++)
-				trEl.appendChild(nodes[i].firstChild);
-
-			trEl.appendChild(this.renderRowActions(cfgsections[i], has_more ? _('More…') : null));
-			tableEl.appendChild(trEl);
-		}
-
-		if (nodes.length == 0)
-			tableEl.appendChild(E('div', { 'class': 'tr cbi-section-table-row placeholder' },
-				E('div', { 'class': 'td' },
-					E('em', {}, _('This section contains no values yet')))));
-
-		sectionEl.appendChild(tableEl);
-
-		sectionEl.appendChild(this.renderSectionAdd('cbi-tblsection-create'));
-
-		dom.bindClassInstance(sectionEl, this);
-
-		return sectionEl;
-	},
-
-	/** @private */
-	renderHeaderRows: function(max_cols, has_action) {
-		var has_titles = false,
-		    has_descriptions = false,
-		    max_cols = isNaN(this.max_cols) ? this.children.length : this.max_cols,
-		    has_more = max_cols < this.children.length,
-		    anon_class = (!this.anonymous || this.sectiontitle) ? 'named' : 'anonymous',
-		    trEls = E([]);
-
-		for (var i = 0, opt; i < max_cols && (opt = this.children[i]) != null; i++) {
-			if (opt.modalonly)
-				continue;
-
-			has_titles = has_titles || !!opt.title;
-			has_descriptions = has_descriptions || !!opt.description;
-		}
-
-		if (has_titles) {
-			var trEl = E('div', {
-				'class': 'tr cbi-section-table-titles ' + anon_class,
-				'data-title': (!this.anonymous || this.sectiontitle) ? _('Name') : null
-			});
-
-			for (var i = 0, opt; i < max_cols && (opt = this.children[i]) != null; i++) {
-				if (opt.modalonly)
-					continue;
-
-				trEl.appendChild(E('div', {
-					'class': 'th cbi-section-table-cell',
-					'data-widget': opt.__name__
-				}));
-
-				if (opt.width != null)
-					trEl.lastElementChild.style.width =
-						(typeof(opt.width) == 'number') ? opt.width+'px' : opt.width;
-
-				if (opt.titleref)
-					trEl.lastElementChild.appendChild(E('a', {
-						'href': opt.titleref,
-						'class': 'cbi-title-ref',
-						'title': this.titledesc || _('Go to relevant configuration page')
-					}, opt.title));
-				else
-					dom.content(trEl.lastElementChild, opt.title);
-			}
-
-			if (this.sortable || this.extedit || this.addremove || has_more || has_action)
-				trEl.appendChild(E('div', {
-					'class': 'th cbi-section-table-cell cbi-section-actions'
-				}));
-
-			trEls.appendChild(trEl);
-		}
-
-		if (has_descriptions && !this.nodescriptions) {
-			var trEl = E('div', {
-				'class': 'tr cbi-section-table-descr ' + anon_class
-			});
-
-			for (var i = 0, opt; i < max_cols && (opt = this.children[i]) != null; i++) {
-				if (opt.modalonly)
-					continue;
-
-				trEl.appendChild(E('div', {
-					'class': 'th cbi-section-table-cell',
-					'data-widget': opt.__name__
-				}, opt.description));
-
-				if (opt.width != null)
-					trEl.lastElementChild.style.width =
-						(typeof(opt.width) == 'number') ? opt.width+'px' : opt.width;
-			}
-
-			if (this.sortable || this.extedit || this.addremove || has_more || has_action)
-				trEl.appendChild(E('div', {
-					'class': 'th cbi-section-table-cell cbi-section-actions'
-				}));
-
-			trEls.appendChild(trEl);
-		}
-
-		return trEls;
-	},
-
-	/** @private */
-	renderRowActions: function(section_id, more_label) {
-		var config_name = this.uciconfig || this.map.config;
-
-		if (!this.sortable && !this.extedit && !this.addremove && !more_label)
-			return E([]);
-
-		var tdEl = E('div', {
-			'class': 'td cbi-section-table-cell nowrap cbi-section-actions'
-		}, E('div'));
-
-		if (this.sortable) {
-			dom.append(tdEl.lastElementChild, [
-				E('div', {
-					'title': _('Drag to reorder'),
-					'class': 'btn cbi-button drag-handle center',
-					'style': 'cursor:move',
-					'disabled': this.map.readonly || null
-				}, '☰')
-			]);
-		}
-
-		if (this.extedit) {
-			var evFn = null;
-
-			if (typeof(this.extedit) == 'function')
-				evFn = L.bind(this.extedit, this);
-			else if (typeof(this.extedit) == 'string')
-				evFn = L.bind(function(sid, ev) {
-					location.href = this.extedit.format(sid);
-				}, this, section_id);
-
-			dom.append(tdEl.lastElementChild,
-				E('button', {
-					'title': _('Edit'),
-					'class': 'cbi-button cbi-button-edit',
-					'click': evFn
-				}, [ _('Edit') ])
-			);
-		}
-
-		if (more_label) {
-			dom.append(tdEl.lastElementChild,
-				E('button', {
-					'title': more_label,
-					'class': 'cbi-button cbi-button-edit',
-					'click': ui.createHandlerFn(this, 'renderMoreOptionsModal', section_id)
-				}, [ more_label ])
-			);
-		}
-
-		if (this.addremove) {
-			var btn_title = this.titleFn('removebtntitle', section_id);
-
-			dom.append(tdEl.lastElementChild,
-				E('button', {
-					'title': btn_title || _('Delete'),
-					'class': 'cbi-button cbi-button-remove',
-					'click': ui.createHandlerFn(this, 'handleRemove', section_id),
-					'disabled': this.map.readonly || null
-				}, [ btn_title || _('Delete') ])
-			);
-		}
-
-		return tdEl;
-	},
-
-	/** @private */
-	handleDragInit: function(ev) {
-		scope.dragState = { node: ev.target };
-	},
-
-	/** @private */
-	handleDragStart: function(ev) {
-		if (!scope.dragState || !scope.dragState.node.classList.contains('drag-handle')) {
-			scope.dragState = null;
-			ev.preventDefault();
-			return false;
-		}
-
-		scope.dragState.node = dom.parent(scope.dragState.node, '.tr');
-		ev.dataTransfer.setData('text', 'drag');
-		ev.target.style.opacity = 0.4;
-	},
-
-	/** @private */
-	handleDragOver: function(ev) {
-		var n = scope.dragState.targetNode,
-		    r = scope.dragState.rect,
-		    t = r.top + r.height / 2;
-
-		if (ev.clientY <= t) {
-			n.classList.remove('drag-over-below');
-			n.classList.add('drag-over-above');
-		}
-		else {
-			n.classList.remove('drag-over-above');
-			n.classList.add('drag-over-below');
-		}
-
-		ev.dataTransfer.dropEffect = 'move';
-		ev.preventDefault();
-		return false;
-	},
-
-	/** @private */
-	handleDragEnter: function(ev) {
-		scope.dragState.rect = ev.currentTarget.getBoundingClientRect();
-		scope.dragState.targetNode = ev.currentTarget;
-	},
-
-	/** @private */
-	handleDragLeave: function(ev) {
-		ev.currentTarget.classList.remove('drag-over-above');
-		ev.currentTarget.classList.remove('drag-over-below');
-	},
-
-	/** @private */
-	handleDragEnd: function(ev) {
-		var n = ev.target;
-
-		n.style.opacity = '';
-		n.classList.add('flash');
-		n.parentNode.querySelectorAll('.drag-over-above, .drag-over-below')
-			.forEach(function(tr) {
-				tr.classList.remove('drag-over-above');
-				tr.classList.remove('drag-over-below');
-			});
-	},
-
-	/** @private */
-	handleDrop: function(ev) {
-		var s = scope.dragState;
-
-		if (s.node && s.targetNode) {
-			var config_name = this.uciconfig || this.map.config,
-			    ref_node = s.targetNode,
-			    after = false;
-
-		    if (ref_node.classList.contains('drag-over-below')) {
-		    	ref_node = ref_node.nextElementSibling;
-		    	after = true;
-		    }
-
-		    var sid1 = s.node.getAttribute('data-sid'),
-		        sid2 = s.targetNode.getAttribute('data-sid');
-
-		    s.node.parentNode.insertBefore(s.node, ref_node);
-		    this.map.data.move(config_name, sid1, sid2, after);
-		}
-
-		scope.dragState = null;
-		ev.target.style.opacity = '';
-		ev.stopPropagation();
-		ev.preventDefault();
-		return false;
-	},
-
-	/** @private */
-	handleModalCancel: function(modalMap, ev) {
-		return Promise.resolve(ui.hideModal());
-	},
-
-	/** @private */
-	handleModalSave: function(modalMap, ev) {
-		return modalMap.save(null, true)
-			.then(L.bind(this.map.load, this.map))
-			.then(L.bind(this.map.reset, this.map))
-			.then(ui.hideModal)
-			.catch(function() {});
-	},
-
-	/**
-	 * Add further options to the per-section instanced modal popup.
-	 *
-	 * This function may be overwritten by user code to perform additional
-	 * setup steps before displaying the more options modal which is useful to
-	 * e.g. query additional data or to inject further option elements.
-	 *
-	 * The default implementation of this function does nothing.
-	 *
-	 * @abstract
-	 * @param {LuCI.form.NamedSection} modalSection
-	 * The `NamedSection` instance about to be rendered in the modal popup.
-	 *
-	 * @param {string} section_id
-	 * The ID of the underlying UCI section the modal popup belongs to.
-	 *
-	 * @param {Event} ev
-	 * The DOM event emitted by clicking the `More…` button.
-	 *
-	 * @returns {*|Promise<*>}
-	 * Return values of this function are ignored but if a promise is returned,
-	 * it is run to completion before the rendering is continued, allowing
-	 * custom logic to perform asynchroneous work before the modal dialog
-	 * is shown.
-	 */
-	addModalOptions: function(modalSection, section_id, ev) {
-
-	},
-
-	/** @private */
-	renderMoreOptionsModal: function(section_id, ev) {
-		var parent = this.map,
-		    title = parent.title,
-		    name = null,
-		    m = new CBIMap(this.map.config, null, null),
-		    s = m.section(CBINamedSection, section_id, this.sectiontype);
-
-		m.parent = parent;
-		m.readonly = parent.readonly;
-
-		s.tabs = this.tabs;
-		s.tab_names = this.tab_names;
-
-		if ((name = this.titleFn('modaltitle', section_id)) != null)
-			title = name;
-		else if ((name = this.titleFn('sectiontitle', section_id)) != null)
-			title = '%s - %s'.format(parent.title, name);
-		else if (!this.anonymous)
-			title = '%s - %s'.format(parent.title, section_id);
-
-		for (var i = 0; i < this.children.length; i++) {
-			var o1 = this.children[i];
-
-			if (o1.modalonly === false)
-				continue;
-
-			var o2 = s.option(o1.constructor, o1.option, o1.title, o1.description);
-
-			for (var k in o1) {
-				if (!o1.hasOwnProperty(k))
-					continue;
-
-				switch (k) {
-				case 'map':
-				case 'section':
-				case 'option':
-				case 'title':
-				case 'description':
-					continue;
-
-				default:
-					o2[k] = o1[k];
-				}
-			}
-		}
-
-		return Promise.resolve(this.addModalOptions(s, section_id, ev)).then(L.bind(m.render, m)).then(L.bind(function(nodes) {
-			ui.showModal(title, [
-				nodes,
-				E('div', { 'class': 'right' }, [
-					E('button', {
-						'class': 'btn',
-						'click': ui.createHandlerFn(this, 'handleModalCancel', m)
-					}, [ _('Dismiss') ]), ' ',
-					E('button', {
-						'class': 'cbi-button cbi-button-positive important',
-						'click': ui.createHandlerFn(this, 'handleModalSave', m),
-						'disabled': m.readonly || null
-					}, [ _('Save') ])
-				])
-			], 'cbi-modal');
-		}, this)).catch(L.error);
-	}
-});
-
-/**
- * @class GridSection
- * @memberof LuCI.form
- * @augments LuCI.form.TableSection
- * @hideconstructor
- * @classdesc
- *
- * The `GridSection` class maps all or - if `filter()` is overwritten - a
- * subset of the underlying UCI configuration sections of a given type.
- *
- * A grid section functions similar to a {@link LuCI.form.TableSection} but
- * supports tabbing in the modal overlay. Option elements added with
- * [option()]{@link LuCI.form.GridSection#option} are shown in the table while
- * elements added with [taboption()]{@link LuCI.form.GridSection#taboption}
- * are displayed in the modal popup.
- *
- * Another important difference is that the table cells show a readonly text
- * preview of the corresponding option elements by default, unless the child
- * option element is explicitely made writable by setting the `editable`
- * property to `true`.
- *
- * Additionally, the grid section honours a `modalonly` property of child
- * option elements. Refer to the [AbstractValue]{@link LuCI.form.AbstractValue}
- * documentation for details.
- *
- * Layout wise, a grid section looks mostly identical to table sections.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [section()]{@link LuCI.form.Map#section}.
- *
- * @param {string} section_type
- * The type of the UCI section to map.
- *
- * @param {string} [title]
- * The title caption of the form section element.
- *
- * @param {string} [description]
- * The description text of the form section element.
- */
-var CBIGridSection = CBITableSection.extend(/** @lends LuCI.form.GridSection.prototype */ {
-	/**
-	 * Add an option tab to the section.
-	 *
-	 * The modal option elements of a grid section may be divided into multiple
-	 * tabs to provide a better overview to the user.
-	 *
-	 * Before options can be moved into a tab pane, the corresponding tab
-	 * has to be defined first, which is done by calling this function.
-	 *
-	 * Note that tabs are only effective in modal popups, options added with
-	 * `option()` will not be assigned to a specific tab and are rendered in
-	 * the table view only.
-	 *
-	 * @param {string} name
-	 * The name of the tab to register. It may be freely chosen and just serves
-	 * as an identifier to differentiate tabs.
-	 *
-	 * @param {string} title
-	 * The human readable caption of the tab.
-	 *
-	 * @param {string} [description]
-	 * An additional description text for the corresponding tab pane. It is
-	 * displayed as text paragraph below the tab but before the tab pane
-	 * contents. If omitted, no description will be rendered.
-	 *
-	 * @throws {Error}
-	 * Throws an exeption if a tab with the same `name` already exists.
-	 */
-	tab: function(name, title, description) {
-		CBIAbstractSection.prototype.tab.call(this, name, title, description);
-	},
-
-	/** @private */
-	handleAdd: function(ev, name) {
-		var config_name = this.uciconfig || this.map.config,
-		    section_id = this.map.data.add(config_name, this.sectiontype, name);
-
-		this.addedSection = section_id;
-		return this.renderMoreOptionsModal(section_id);
-	},
-
-	/** @private */
-	handleModalSave: function(/* ... */) {
-		return this.super('handleModalSave', arguments)
-			.then(L.bind(function() { this.addedSection = null }, this));
-	},
-
-	/** @private */
-	handleModalCancel: function(/* ... */) {
-		var config_name = this.uciconfig || this.map.config;
-
-		if (this.addedSection != null) {
-			this.map.data.remove(config_name, this.addedSection);
-			this.addedSection = null;
-		}
-
-		return this.super('handleModalCancel', arguments);
-	},
-
-	/** @private */
-	renderUCISection: function(section_id) {
-		return this.renderOptions(null, section_id);
-	},
-
-	/** @private */
-	renderChildren: function(tab_name, section_id, in_table) {
-		var tasks = [], index = 0;
-
-		for (var i = 0, opt; (opt = this.children[i]) != null; i++) {
-			if (opt.disable || opt.modalonly)
-				continue;
-
-			if (opt.editable)
-				tasks.push(opt.render(index++, section_id, in_table));
-			else
-				tasks.push(this.renderTextValue(section_id, opt));
-		}
-
-		return Promise.all(tasks);
-	},
-
-	/** @private */
-	renderTextValue: function(section_id, opt) {
-		var title = this.stripTags(opt.title).trim(),
-		    descr = this.stripTags(opt.description).trim(),
-		    value = opt.textvalue(section_id);
-
-		return E('div', {
-			'class': 'td cbi-value-field',
-			'data-title': (title != '') ? title : null,
-			'data-description': (descr != '') ? descr : null,
-			'data-name': opt.option,
-			'data-widget': opt.typename || opt.__name__
-		}, (value != null) ? value : E('em', _('none')));
-	},
-
-	/** @private */
-	renderHeaderRows: function(section_id) {
-		return this.super('renderHeaderRows', [ NaN, true ]);
-	},
-
-	/** @private */
-	renderRowActions: function(section_id) {
-		return this.super('renderRowActions', [ section_id, _('Edit') ]);
-	},
-
-	/** @override */
-	parse: function() {
-		var section_ids = this.cfgsections(),
-		    tasks = [];
-
-		if (Array.isArray(this.children)) {
-			for (var i = 0; i < section_ids.length; i++) {
-				for (var j = 0; j < this.children.length; j++) {
-					if (!this.children[j].editable || this.children[j].modalonly)
-						continue;
-
-					tasks.push(this.children[j].parse(section_ids[i]));
-				}
-			}
-		}
-
-		return Promise.all(tasks);
-	}
-});
-
-/**
- * @class NamedSection
- * @memberof LuCI.form
- * @augments LuCI.form.AbstractSection
- * @hideconstructor
- * @classdesc
- *
- * The `NamedSection` class maps exactly one UCI section instance which is
- * specified when constructing the class instance.
- *
- * Layout and functionality wise, a named section is essentially a
- * `TypedSection` which allows exactly one section node.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [section()]{@link LuCI.form.Map#section}.
- *
- * @param {string} section_id
- * The name (ID) of the UCI section to map.
- *
- * @param {string} section_type
- * The type of the UCI section to map.
- *
- * @param {string} [title]
- * The title caption of the form section element.
- *
- * @param {string} [description]
- * The description text of the form section element.
- */
-var CBINamedSection = CBIAbstractSection.extend(/** @lends LuCI.form.NamedSection.prototype */ {
-	__name__: 'CBI.NamedSection',
-	__init__: function(map, section_id /*, ... */) {
-		this.super('__init__', this.varargs(arguments, 2, map));
-
-		this.section = section_id;
-	},
-
-	/**
-	 * If set to `true`, the user may remove or recreate the sole mapped
-	 * configuration instance from the form section widget, otherwise only a
-	 * preexisting section may be edited. The default is `false`.
-	 *
-	 * @name LuCI.form.NamedSection.prototype#addremove
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Override the UCI configuration name to read the section IDs from. By
-	 * default, the configuration name is inherited from the parent `Map`.
-	 * By setting this property, a deviating configuration may be specified.
-	 * The default is `null`, means inheriting from the parent form.
-	 *
-	 * @name LuCI.form.NamedSection.prototype#uciconfig
-	 * @type string
-	 * @default null
-	 */
-
-	/**
-	 * The `NamedSection` class overwrites the generic `cfgsections()`
-	 * implementation to return a one-element array containing the mapped
-	 * section ID as sole element. User code should not normally change this.
-	 *
-	 * @returns {string[]}
-	 * Returns a one-element array containing the mapped section ID.
-	 */
-	cfgsections: function() {
-		return [ this.section ];
-	},
-
-	/** @private */
-	handleAdd: function(ev) {
-		var section_id = this.section,
-		    config_name = this.uciconfig || this.map.config;
-
-		this.map.data.add(config_name, this.sectiontype, section_id);
-		return this.map.save(null, true);
-	},
-
-	/** @private */
-	handleRemove: function(ev) {
-		var section_id = this.section,
-		    config_name = this.uciconfig || this.map.config;
-
-		this.map.data.remove(config_name, section_id);
-		return this.map.save(null, true);
-	},
-
-	/** @private */
-	renderContents: function(data) {
-		var ucidata = data[0], nodes = data[1],
-		    section_id = this.section,
-		    config_name = this.uciconfig || this.map.config,
-		    sectionEl = E('div', {
-				'id': ucidata ? null : 'cbi-%s-%s'.format(config_name, section_id),
-				'class': 'cbi-section',
-				'data-tab': (this.map.tabbed && !this.parentoption) ? this.sectiontype : null,
-				'data-tab-title': (this.map.tabbed && !this.parentoption) ? this.title || this.sectiontype : null
-			});
-
-		if (typeof(this.title) === 'string' && this.title !== '')
-			sectionEl.appendChild(E('legend', {}, this.title));
-
-		if (typeof(this.description) === 'string' && this.description !== '')
-			sectionEl.appendChild(E('div', { 'class': 'cbi-section-descr' }, this.description));
-
-		if (ucidata) {
-			if (this.addremove) {
-				sectionEl.appendChild(
-					E('div', { 'class': 'cbi-section-remove right' },
-						E('button', {
-							'class': 'cbi-button',
-							'click': ui.createHandlerFn(this, 'handleRemove'),
-							'disabled': this.map.readonly || null
-						}, [ _('Delete') ])));
-			}
-
-			sectionEl.appendChild(E('div', {
-				'id': 'cbi-%s-%s'.format(config_name, section_id),
-				'class': this.tabs
-					? 'cbi-section-node cbi-section-node-tabbed' : 'cbi-section-node',
-				'data-section-id': section_id
-			}, nodes));
-		}
-		else if (this.addremove) {
-			sectionEl.appendChild(
-				E('button', {
-					'class': 'cbi-button cbi-button-add',
-					'click': ui.createHandlerFn(this, 'handleAdd'),
-					'disabled': this.map.readonly || null
-				}, [ _('Add') ]));
-		}
-
-		dom.bindClassInstance(sectionEl, this);
-
-		return sectionEl;
-	},
-
-	/** @override */
-	render: function() {
-		var config_name = this.uciconfig || this.map.config,
-		    section_id = this.section;
-
-		return Promise.all([
-			this.map.data.get(config_name, section_id),
-			this.renderUCISection(section_id)
-		]).then(this.renderContents.bind(this));
-	}
-});
-
-/**
- * @class Value
- * @memberof LuCI.form
- * @augments LuCI.form.AbstractValue
- * @hideconstructor
- * @classdesc
- *
- * The `Value` class represents a simple one-line form input using the
- * {@link LuCI.ui.Textfield} or - in case choices are added - the
- * {@link LuCI.ui.Combobox} class as underlying widget.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBIValue = CBIAbstractValue.extend(/** @lends LuCI.form.Value.prototype */ {
-	__name__: 'CBI.Value',
-
-	/**
-	 * If set to `true`, the field is rendered as password input, otherwise
-	 * as plain text input.
-	 *
-	 * @name LuCI.form.Value.prototype#password
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Set a placeholder string to use when the input field is empty.
-	 *
-	 * @name LuCI.form.Value.prototype#placeholder
-	 * @type string
-	 * @default null
-	 */
-
-	/**
-	 * Add a predefined choice to the form option. By adding one or more
-	 * choices, the plain text input field is turned into a combobox widget
-	 * which prompts the user to select a predefined choice, or to enter a
-	 * custom value.
-	 *
-	 * @param {string} key
-	 * The choice value to add.
-	 *
-	 * @param {Node|string} value
-	 * The caption for the choice value. May be a DOM node, a document fragment
-	 * or a plain text string. If omitted, the `key` value is used as caption.
-	 */
-	value: function(key, val) {
-		this.keylist = this.keylist || [];
-		this.keylist.push(String(key));
-
-		this.vallist = this.vallist || [];
-		this.vallist.push(dom.elem(val) ? val : String(val != null ? val : key));
-	},
-
-	/** @override */
-	render: function(option_index, section_id, in_table) {
-		return Promise.resolve(this.cfgvalue(section_id))
-			.then(this.renderWidget.bind(this, section_id, option_index))
-			.then(this.renderFrame.bind(this, section_id, in_table, option_index));
-	},
-
-	/** @private */
-	handleValueChange: function(section_id, state, ev) {
-		if (typeof(this.onchange) != 'function')
-			return;
-
-		var value = this.formvalue(section_id);
-
-		if (isEqual(value, state.previousValue))
-			return;
-
-		state.previousValue = value;
-		this.onchange.call(this, ev, section_id, value);
-	},
-
-	/** @private */
-	renderFrame: function(section_id, in_table, option_index, nodes) {
-		var config_name = this.uciconfig || this.section.uciconfig || this.map.config,
-		    depend_list = this.transformDepList(section_id),
-		    optionEl;
-
-		if (in_table) {
-			var title = this.stripTags(this.title).trim();
-			optionEl = E('div', {
-				'class': 'td cbi-value-field',
-				'data-title': (title != '') ? title : null,
-				'data-description': this.stripTags(this.description).trim(),
-				'data-name': this.option,
-				'data-widget': this.typename || (this.template ? this.template.replace(/^.+\//, '') : null) || this.__name__
-			}, E('div', {
-				'id': 'cbi-%s-%s-%s'.format(config_name, section_id, this.option),
-				'data-index': option_index,
-				'data-depends': depend_list,
-				'data-field': this.cbid(section_id)
-			}));
-		}
-		else {
-			optionEl = E('div', {
-				'class': 'cbi-value',
-				'id': 'cbi-%s-%s-%s'.format(config_name, section_id, this.option),
-				'data-index': option_index,
-				'data-depends': depend_list,
-				'data-field': this.cbid(section_id),
-				'data-name': this.option,
-				'data-widget': this.typename || (this.template ? this.template.replace(/^.+\//, '') : null) || this.__name__
-			});
-
-			if (this.last_child)
-				optionEl.classList.add('cbi-value-last');
-
-			if (typeof(this.title) === 'string' && this.title !== '') {
-				optionEl.appendChild(E('label', {
-					'class': 'cbi-value-title',
-					'for': 'widget.cbid.%s.%s.%s'.format(config_name, section_id, this.option),
-					'click': function(ev) {
-						var node = ev.currentTarget,
-						    elem = node.nextElementSibling.querySelector('#' + node.getAttribute('for')) || node.nextElementSibling.querySelector('[data-widget-id="' + node.getAttribute('for') + '"]');
-
-						if (elem) {
-							elem.click();
-							elem.focus();
-						}
-					}
-				},
-				this.titleref ? E('a', {
-					'class': 'cbi-title-ref',
-					'href': this.titleref,
-					'title': this.titledesc || _('Go to relevant configuration page')
-				}, this.title) : this.title));
-
-				optionEl.appendChild(E('div', { 'class': 'cbi-value-field' }));
-			}
-		}
-
-		if (nodes)
-			(optionEl.lastChild || optionEl).appendChild(nodes);
-
-		if (!in_table && typeof(this.description) === 'string' && this.description !== '')
-			dom.append(optionEl.lastChild || optionEl,
-				E('div', { 'class': 'cbi-value-description' }, this.description));
-
-		if (depend_list && depend_list.length)
-			optionEl.classList.add('hidden');
-
-		optionEl.addEventListener('widget-change',
-			L.bind(this.handleValueChange, this, section_id, {}));
-
-		optionEl.addEventListener('widget-change',
-			L.bind(this.map.checkDepends, this.map));
-
-		dom.bindClassInstance(optionEl, this);
-
-		return optionEl;
-	},
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var value = (cfgvalue != null) ? cfgvalue : this.default,
-		    choices = this.transformChoices(),
-		    widget;
-
-		if (choices) {
-			var placeholder = (this.optional || this.rmempty)
-				? E('em', _('unspecified')) : _('-- Please choose --');
-
-			widget = new ui.Combobox(Array.isArray(value) ? value.join(' ') : value, choices, {
-				id: this.cbid(section_id),
-				sort: this.keylist,
-				optional: this.optional || this.rmempty,
-				datatype: this.datatype,
-				select_placeholder: this.placeholder || placeholder,
-				validate: L.bind(this.validate, this, section_id),
-				disabled: (this.readonly != null) ? this.readonly : this.map.readonly
-			});
-		}
-		else {
-			widget = new ui.Textfield(Array.isArray(value) ? value.join(' ') : value, {
-				id: this.cbid(section_id),
-				password: this.password,
-				optional: this.optional || this.rmempty,
-				datatype: this.datatype,
-				placeholder: this.placeholder,
-				validate: L.bind(this.validate, this, section_id),
-				disabled: (this.readonly != null) ? this.readonly : this.map.readonly
-			});
-		}
-
-		return widget.render();
-	}
-});
-
-/**
- * @class DynamicList
- * @memberof LuCI.form
- * @augments LuCI.form.Value
- * @hideconstructor
- * @classdesc
- *
- * The `DynamicList` class represents a multi value widget allowing the user
- * to enter multiple unique values, optionally selected from a set of
- * predefined choices. It builds upon the {@link LuCI.ui.DynamicList} widget.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBIDynamicList = CBIValue.extend(/** @lends LuCI.form.DynamicList.prototype */ {
-	__name__: 'CBI.DynamicList',
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var value = (cfgvalue != null) ? cfgvalue : this.default,
-		    choices = this.transformChoices(),
-		    items = L.toArray(value);
-
-		var widget = new ui.DynamicList(items, choices, {
-			id: this.cbid(section_id),
-			sort: this.keylist,
-			optional: this.optional || this.rmempty,
-			datatype: this.datatype,
-			placeholder: this.placeholder,
-			validate: L.bind(this.validate, this, section_id),
-			disabled: (this.readonly != null) ? this.readonly : this.map.readonly
-		});
-
-		return widget.render();
-	},
-});
-
-/**
- * @class ListValue
- * @memberof LuCI.form
- * @augments LuCI.form.Value
- * @hideconstructor
- * @classdesc
- *
- * The `ListValue` class implements a simple static HTML select element
- * allowing the user to chose a single value from a set of predefined choices.
- * It builds upon the {@link LuCI.ui.Select} widget.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBIListValue = CBIValue.extend(/** @lends LuCI.form.ListValue.prototype */ {
-	__name__: 'CBI.ListValue',
-
-	__init__: function() {
-		this.super('__init__', arguments);
-		this.widget = 'select';
-		this.orientation = 'horizontal';
-		this.deplist = [];
-	},
-
-	/**
-	 * Set the size attribute of the underlying HTML select element.
-	 *
-	 * @name LuCI.form.ListValue.prototype#size
-	 * @type number
-	 * @default null
-	 */
-
-	/**
-	 * Set the type of the underlying form controls.
-	 *
-	 * May be one of `select` or `radio`. If set to `select`, an HTML
-	 * select element is rendered, otherwise a collection of `radio`
-	 * elements is used.
-	 *
-	 * @name LuCI.form.ListValue.prototype#widget
-	 * @type string
-	 * @default select
-	 */
-
-	/**
-	 * Set the orientation of the underlying radio or checkbox elements.
-	 *
-	 * May be one of `horizontal` or `vertical`. Only applies to non-select
-	 * widget types.
-	 *
-	 * @name LuCI.form.ListValue.prototype#orientation
-	 * @type string
-	 * @default horizontal
-	 */
-
-	 /** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var choices = this.transformChoices();
-		var widget = new ui.Select((cfgvalue != null) ? cfgvalue : this.default, choices, {
-			id: this.cbid(section_id),
-			size: this.size,
-			sort: this.keylist,
-			widget: this.widget,
-			optional: this.optional,
-			orientation: this.orientation,
-			placeholder: this.placeholder,
-			validate: L.bind(this.validate, this, section_id),
-			disabled: (this.readonly != null) ? this.readonly : this.map.readonly
-		});
-
-		return widget.render();
-	},
-});
-
-/**
- * @class FlagValue
- * @memberof LuCI.form
- * @augments LuCI.form.Value
- * @hideconstructor
- * @classdesc
- *
- * The `FlagValue` element builds upon the {@link LuCI.ui.Checkbox} widget to
- * implement a simple checkbox element.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBIFlagValue = CBIValue.extend(/** @lends LuCI.form.FlagValue.prototype */ {
-	__name__: 'CBI.FlagValue',
-
-	__init__: function() {
-		this.super('__init__', arguments);
-
-		this.enabled = '1';
-		this.disabled = '0';
-		this.default = this.disabled;
-	},
-
-	/**
-	 * Sets the input value to use for the checkbox checked state.
-	 *
-	 * @name LuCI.form.FlagValue.prototype#enabled
-	 * @type number
-	 * @default 1
-	 */
-
-	/**
-	 * Sets the input value to use for the checkbox unchecked state.
-	 *
-	 * @name LuCI.form.FlagValue.prototype#disabled
-	 * @type number
-	 * @default 0
-	 */
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var widget = new ui.Checkbox((cfgvalue != null) ? cfgvalue : this.default, {
-			id: this.cbid(section_id),
-			value_enabled: this.enabled,
-			value_disabled: this.disabled,
-			validate: L.bind(this.validate, this, section_id),
-			disabled: (this.readonly != null) ? this.readonly : this.map.readonly
-		});
-
-		return widget.render();
-	},
-
-	/**
-	 * Query the checked state of the underlying checkbox widget and return
-	 * either the `enabled` or the `disabled` property value, depending on
-	 * the checked state.
-	 *
-	 * @override
-	 */
-	formvalue: function(section_id) {
-		var elem = this.getUIElement(section_id),
-		    checked = elem ? elem.isChecked() : false;
-		return checked ? this.enabled : this.disabled;
-	},
-
-	/**
-	 * Query the checked state of the underlying checkbox widget and return
-	 * either a localized `Yes` or `No` string, depending on the checked state.
-	 *
-	 * @override
-	 */
-	textvalue: function(section_id) {
-		var cval = this.cfgvalue(section_id);
-
-		if (cval == null)
-			cval = this.default;
-
-		return (cval == this.enabled) ? _('Yes') : _('No');
-	},
-
-	/** @override */
-	parse: function(section_id) {
-		if (this.isActive(section_id)) {
-			var fval = this.formvalue(section_id);
-
-			if (!this.isValid(section_id)) {
-				var title = this.stripTags(this.title).trim();
-				return Promise.reject(new TypeError(_('Option "%s" contains an invalid input value.').format(title || this.option)));
-			}
-
-			if (fval == this.default && (this.optional || this.rmempty))
-				return Promise.resolve(this.remove(section_id));
-			else
-				return Promise.resolve(this.write(section_id, fval));
-		}
-		else {
-			return Promise.resolve(this.remove(section_id));
-		}
-	},
-});
-
-/**
- * @class MultiValue
- * @memberof LuCI.form
- * @augments LuCI.form.DynamicList
- * @hideconstructor
- * @classdesc
- *
- * The `MultiValue` class is a modified variant of the `DynamicList` element
- * which leverages the {@link LuCI.ui.Dropdown} widget to implement a multi
- * select dropdown element.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBIMultiValue = CBIDynamicList.extend(/** @lends LuCI.form.MultiValue.prototype */ {
-	__name__: 'CBI.MultiValue',
-
-	__init__: function() {
-		this.super('__init__', arguments);
-		this.placeholder = _('-- Please choose --');
-	},
-
-	/**
-	 * Allows to specify the [display_items]{@link LuCI.ui.Dropdown.InitOptions}
-	 * property of the underlying dropdown widget. If omitted, the value of
-	 * the `size` property is used or `3` when `size` is unspecified as well.
-	 *
-	 * @name LuCI.form.MultiValue.prototype#display_size
-	 * @type number
-	 * @default null
-	 */
-
-	/**
-	 * Allows to specify the [dropdown_items]{@link LuCI.ui.Dropdown.InitOptions}
-	 * property of the underlying dropdown widget. If omitted, the value of
-	 * the `size` property is used or `-1` when `size` is unspecified as well.
-	 *
-	 * @name LuCI.form.MultiValue.prototype#dropdown_size
-	 * @type number
-	 * @default null
-	 */
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var value = (cfgvalue != null) ? cfgvalue : this.default,
-		    choices = this.transformChoices();
-
-		var widget = new ui.Dropdown(L.toArray(value), choices, {
-			id: this.cbid(section_id),
-			sort: this.keylist,
-			multiple: true,
-			optional: this.optional || this.rmempty,
-			select_placeholder: this.placeholder,
-			display_items: this.display_size || this.size || 3,
-			dropdown_items: this.dropdown_size || this.size || -1,
-			validate: L.bind(this.validate, this, section_id),
-			disabled: (this.readonly != null) ? this.readonly : this.map.readonly
-		});
-
-		return widget.render();
-	},
-});
-
-/**
- * @class TextValue
- * @memberof LuCI.form
- * @augments LuCI.form.Value
- * @hideconstructor
- * @classdesc
- *
- * The `TextValue` class implements a multi-line textarea input using
- * {@link LuCI.ui.Textarea}.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBITextValue = CBIValue.extend(/** @lends LuCI.form.TextValue.prototype */ {
-	__name__: 'CBI.TextValue',
-
-	/** @ignore */
-	value: null,
-
-	/**
-	 * Enforces the use of a monospace font for the textarea contents when set
-	 * to `true`.
-	 *
-	 * @name LuCI.form.TextValue.prototype#monospace
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Allows to specify the [cols]{@link LuCI.ui.Textarea.InitOptions}
-	 * property of the underlying textarea widget.
-	 *
-	 * @name LuCI.form.TextValue.prototype#cols
-	 * @type number
-	 * @default null
-	 */
-
-	/**
-	 * Allows to specify the [rows]{@link LuCI.ui.Textarea.InitOptions}
-	 * property of the underlying textarea widget.
-	 *
-	 * @name LuCI.form.TextValue.prototype#rows
-	 * @type number
-	 * @default null
-	 */
-
-	/**
-	 * Allows to specify the [wrap]{@link LuCI.ui.Textarea.InitOptions}
-	 * property of the underlying textarea widget.
-	 *
-	 * @name LuCI.form.TextValue.prototype#wrap
-	 * @type number
-	 * @default null
-	 */
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var value = (cfgvalue != null) ? cfgvalue : this.default;
-
-		var widget = new ui.Textarea(value, {
-			id: this.cbid(section_id),
-			optional: this.optional || this.rmempty,
-			placeholder: this.placeholder,
-			monospace: this.monospace,
-			cols: this.cols,
-			rows: this.rows,
-			wrap: this.wrap,
-			validate: L.bind(this.validate, this, section_id),
-			disabled: (this.readonly != null) ? this.readonly : this.map.readonly
-		});
-
-		return widget.render();
-	}
-});
-
-/**
- * @class DummyValue
- * @memberof LuCI.form
- * @augments LuCI.form.Value
- * @hideconstructor
- * @classdesc
- *
- * The `DummyValue` element wraps an {@link LuCI.ui.Hiddenfield} widget and
- * renders the underlying UCI option or default value as readonly text.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBIDummyValue = CBIValue.extend(/** @lends LuCI.form.DummyValue.prototype */ {
-	__name__: 'CBI.DummyValue',
-
-	/**
-	 * Set an URL which is opened when clicking on the dummy value text.
-	 *
-	 * By setting this property, the dummy value text is wrapped in an `<a>`
-	 * element with the property value used as `href` attribute.
-	 *
-	 * @name LuCI.form.DummyValue.prototype#href
-	 * @type string
-	 * @default null
-	 */
-
-	/**
-	 * Treat the UCI option value (or the `default` property value) as HTML.
-	 *
-	 * By default, the value text is HTML escaped before being rendered as
-	 * text. In some cases it may be needed to actually interpret and render
-	 * HTML contents as-is. When set to `true`, HTML escaping is disabled.
-	 *
-	 * @name LuCI.form.DummyValue.prototype#rawhtml
-	 * @type boolean
-	 * @default null
-	 */
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var value = (cfgvalue != null) ? cfgvalue : this.default,
-		    hiddenEl = new ui.Hiddenfield(value, { id: this.cbid(section_id) }),
-		    outputEl = E('div');
-
-		if (this.href && !((this.readonly != null) ? this.readonly : this.map.readonly))
-			outputEl.appendChild(E('a', { 'href': this.href }));
-
-		dom.append(outputEl.lastChild || outputEl,
-			this.rawhtml ? value : [ value ]);
-
-		return E([
-			outputEl,
-			hiddenEl.render()
-		]);
-	},
-
-	/** @override */
-	remove: function() {},
-
-	/** @override */
-	write: function() {}
-});
-
-/**
- * @class ButtonValue
- * @memberof LuCI.form
- * @augments LuCI.form.Value
- * @hideconstructor
- * @classdesc
- *
- * The `DummyValue` element wraps an {@link LuCI.ui.Hiddenfield} widget and
- * renders the underlying UCI option or default value as readonly text.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBIButtonValue = CBIValue.extend(/** @lends LuCI.form.ButtonValue.prototype */ {
-	__name__: 'CBI.ButtonValue',
-
-	/**
-	 * Override the rendered button caption.
-	 *
-	 * By default, the option title - which is passed as fourth argument to the
-	 * constructor - is used as caption for the button element. When setting
-	 * this property to a string, it is used as `String.format()` pattern with
-	 * the underlying UCI section name passed as first format argument. When
-	 * set to a function, it is invoked passing the section ID as sole argument
-	 * and the resulting return value is converted to a string before being
-	 * used as button caption.
-	 *
-	 * The default is `null`, means the option title is used as caption.
-	 *
-	 * @name LuCI.form.ButtonValue.prototype#inputtitle
-	 * @type string|function
-	 * @default null
-	 */
-
-	/**
-	 * Override the button style class.
-	 *
-	 * By setting this property, a specific `cbi-button-*` CSS class can be
-	 * selected to influence the style of the resulting button.
-	 *
-	 * Suitable values which are implemented by most themes are `positive`,
-	 * `negative` and `primary`.
-	 *
-	 * The default is `null`, means a neutral button styling is used.
-	 *
-	 * @name LuCI.form.ButtonValue.prototype#inputstyle
-	 * @type string
-	 * @default null
-	 */
-
-	/**
-	 * Override the button click action.
-	 *
-	 * By default, the underlying UCI option (or default property) value is
-	 * copied into a hidden field tied to the button element and the save
-	 * action is triggered on the parent form element.
-	 *
-	 * When this property is set to a function, it is invoked instead of
-	 * performing the default actions. The handler function will receive the
-	 * DOM click element as first and the underlying configuration section ID
-	 * as second argument.
-	 *
-	 * @name LuCI.form.ButtonValue.prototype#onclick
-	 * @type function
-	 * @default null
-	 */
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var value = (cfgvalue != null) ? cfgvalue : this.default,
-		    hiddenEl = new ui.Hiddenfield(value, { id: this.cbid(section_id) }),
-		    outputEl = E('div'),
-		    btn_title = this.titleFn('inputtitle', section_id) || this.titleFn('title', section_id);
-
-		if (value !== false)
-			dom.content(outputEl, [
-				E('button', {
-					'class': 'cbi-button cbi-button-%s'.format(this.inputstyle || 'button'),
-					'click': ui.createHandlerFn(this, function(section_id, ev) {
-						if (this.onclick)
-							return this.onclick(ev, section_id);
-
-						ev.currentTarget.parentNode.nextElementSibling.value = value;
-						return this.map.save();
-					}, section_id),
-					'disabled': ((this.readonly != null) ? this.readonly : this.map.readonly) || null
-				}, [ btn_title ])
-			]);
-		else
-			dom.content(outputEl, ' - ');
-
-		return E([
-			outputEl,
-			hiddenEl.render()
-		]);
-	}
-});
-
-/**
- * @class HiddenValue
- * @memberof LuCI.form
- * @augments LuCI.form.Value
- * @hideconstructor
- * @classdesc
- *
- * The `HiddenValue` element wraps an {@link LuCI.ui.Hiddenfield} widget.
- *
- * Hidden value widgets used to be necessary in legacy code which actually
- * submitted the underlying HTML form the server. With client side handling of
- * forms, there are more efficient ways to store hidden state data.
- *
- * Since this widget has no visible content, the title and description values
- * of this form element should be set to `null` as well to avoid a broken or
- * distorted form layout when rendering the option element.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBIHiddenValue = CBIValue.extend(/** @lends LuCI.form.HiddenValue.prototype */ {
-	__name__: 'CBI.HiddenValue',
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var widget = new ui.Hiddenfield((cfgvalue != null) ? cfgvalue : this.default, {
-			id: this.cbid(section_id)
-		});
-
-		return widget.render();
-	}
-});
-
-/**
- * @class FileUpload
- * @memberof LuCI.form
- * @augments LuCI.form.Value
- * @hideconstructor
- * @classdesc
- *
- * The `FileUpload` element wraps an {@link LuCI.ui.FileUpload} widget and
- * offers the ability to browse, upload and select remote files.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The name of the UCI option to map.
- *
- * @param {string} [title]
- * The title caption of the option element.
- *
- * @param {string} [description]
- * The description text of the option element.
- */
-var CBIFileUpload = CBIValue.extend(/** @lends LuCI.form.FileUpload.prototype */ {
-	__name__: 'CBI.FileSelect',
-
-	__init__: function(/* ... */) {
-		this.super('__init__', arguments);
-
-		this.show_hidden = false;
-		this.enable_upload = true;
-		this.enable_remove = true;
-		this.root_directory = '/etc/luci-uploads';
-	},
-
-	/**
-	 * Toggle display of hidden files.
-	 *
-	 * Display hidden files when rendering the remote directory listing.
-	 * Note that this is merely a cosmetic feature, hidden files are always
-	 * included in received remote file listings.
-	 *
-	 * The default is `false`, means hidden files are not displayed.
-	 *
-	 * @name LuCI.form.FileUpload.prototype#show_hidden
-	 * @type boolean
-	 * @default false
-	 */
-
-	/**
-	 * Toggle file upload functionality.
-	 *
-	 * When set to `true`, the underlying widget provides a button which lets
-	 * the user select and upload local files to the remote system.
-	 * Note that this is merely a cosmetic feature, remote upload access is
-	 * controlled by the session ACL rules.
-	 *
-	 * The default is `true`, means file upload functionality is displayed.
-	 *
-	 * @name LuCI.form.FileUpload.prototype#enable_upload
-	 * @type boolean
-	 * @default true
-	 */
-
-	/**
-	 * Toggle remote file delete functionality.
-	 *
-	 * When set to `true`, the underlying widget provides a buttons which let
-	 * the user delete files from remote directories. Note that this is merely
-	 * a cosmetic feature, remote delete permissions are controlled by the
-	 * session ACL rules.
-	 *
-	 * The default is `true`, means file removal buttons are displayed.
-	 *
-	 * @name LuCI.form.FileUpload.prototype#enable_remove
-	 * @type boolean
-	 * @default true
-	 */
-
-	/**
-	 * Specify the root directory for file browsing.
-	 *
-	 * This property defines the topmost directory the file browser widget may
-	 * navigate to, the UI will not allow browsing directories outside this
-	 * prefix. Note that this is merely a cosmetic feature, remote file access
-	 * and directory listing permissions are controlled by the session ACL
-	 * rules.
-	 *
-	 * The default is `/etc/luci-uploads`.
-	 *
-	 * @name LuCI.form.FileUpload.prototype#root_directory
-	 * @type string
-	 * @default /etc/luci-uploads
-	 */
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		var browserEl = new ui.FileUpload((cfgvalue != null) ? cfgvalue : this.default, {
-			id: this.cbid(section_id),
-			name: this.cbid(section_id),
-			show_hidden: this.show_hidden,
-			enable_upload: this.enable_upload,
-			enable_remove: this.enable_remove,
-			root_directory: this.root_directory,
-			disabled: (this.readonly != null) ? this.readonly : this.map.readonly
-		});
-
-		return browserEl.render();
-	}
-});
-
-/**
- * @class SectionValue
- * @memberof LuCI.form
- * @augments LuCI.form.Value
- * @hideconstructor
- * @classdesc
- *
- * The `SectionValue` widget embeds a form section element within an option
- * element container, allowing to nest form sections into other sections.
- *
- * @param {LuCI.form.Map|LuCI.form.JSONMap} form
- * The configuration form this section is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {LuCI.form.AbstractSection} section
- * The configuration section this option is added to. It is automatically passed
- * by [option()]{@link LuCI.form.AbstractSection#option} or
- * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the
- * option to the section.
- *
- * @param {string} option
- * The internal name of the option element holding the section. Since a section
- * container element does not read or write any configuration itself, the name
- * is only used internally and does not need to relate to any underlying UCI
- * option name.
- *
- * @param {LuCI.form.AbstractSection} subsection_class
- * The class to use for instantiating the nested section element. Note that
- * the class value itself is expected here, not a class instance obtained by
- * calling `new`. The given class argument must be a subclass of the
- * `AbstractSection` class.
- *
- * @param {...*} [class_args]
- * All further arguments are passed as-is to the subclass constructor. Refer
- * to the corresponding class constructor documentations for details.
- */
-var CBISectionValue = CBIValue.extend(/** @lends LuCI.form.SectionValue.prototype */ {
-	__name__: 'CBI.ContainerValue',
-	__init__: function(map, section, option, cbiClass /*, ... */) {
-		this.super('__init__', [map, section, option]);
-
-		if (!CBIAbstractSection.isSubclass(cbiClass))
-			throw 'Sub section must be a descendent of CBIAbstractSection';
-
-		this.subsection = cbiClass.instantiate(this.varargs(arguments, 4, this.map));
-		this.subsection.parentoption = this;
-	},
-
-	/**
-	 * Access the embedded section instance.
-	 *
-	 * This property holds a reference to the instantiated nested section.
-	 *
-	 * @name LuCI.form.SectionValue.prototype#subsection
-	 * @type LuCI.form.AbstractSection
-	 * @readonly
-	 */
-
-	/** @override */
-	load: function(section_id) {
-		return this.subsection.load(section_id);
-	},
-
-	/** @override */
-	parse: function(section_id) {
-		return this.subsection.parse(section_id);
-	},
-
-	/** @private */
-	renderWidget: function(section_id, option_index, cfgvalue) {
-		return this.subsection.render(section_id);
-	},
-
-	/** @private */
-	checkDepends: function(section_id) {
-		this.subsection.checkDepends(section_id);
-		return CBIValue.prototype.checkDepends.apply(this, [ section_id ]);
-	},
-
-	/**
-	 * Since the section container is not rendering an own widget,
-	 * its `value()` implementation is a no-op.
-	 *
-	 * @override
-	 */
-	value: function() {},
-
-	/**
-	 * Since the section container is not tied to any UCI configuration,
-	 * its `write()` implementation is a no-op.
-	 *
-	 * @override
-	 */
-	write: function() {},
-
-	/**
-	 * Since the section container is not tied to any UCI configuration,
-	 * its `remove()` implementation is a no-op.
-	 *
-	 * @override
-	 */
-	remove: function() {},
-
-	/**
-	 * Since the section container is not tied to any UCI configuration,
-	 * its `cfgvalue()` implementation will always return `null`.
-	 *
-	 * @override
-	 * @returns {null}
-	 */
-	cfgvalue: function() { return null },
-
-	/**
-	 * Since the section container is not tied to any UCI configuration,
-	 * its `formvalue()` implementation will always return `null`.
-	 *
-	 * @override
-	 * @returns {null}
-	 */
-	formvalue: function() { return null }
-});
-
-/**
- * @class form
- * @memberof LuCI
- * @hideconstructor
- * @classdesc
- *
- * The LuCI form class provides high level abstractions for creating creating
- * UCI- or JSON backed configurations forms.
- *
- * To import the class in views, use `'require form'`, to import it in
- * external JavaScript, use `L.require("form").then(...)`.
- *
- * A typical form is created by first constructing a
- * {@link LuCI.form.Map} or {@link LuCI.form.JSONMap} instance using `new` and
- * by subsequently adding sections and options to it. Finally
- * [render()]{@link LuCI.form.Map#render} is invoked on the instance to
- * assemble the HTML markup and insert it into the DOM.
- *
- * Example:
- *
- * <pre>
- * 'use strict';
- * 'require form';
- *
- * var m, s, o;
- *
- * m = new form.Map('example', 'Example form',
- *	'This is an example form mapping the contents of /etc/config/example');
- *
- * s = m.section(form.NamedSection, 'first_section', 'example', 'The first section',
- * 	'This sections maps "config example first_section" of /etc/config/example');
- *
- * o = s.option(form.Flag, 'some_bool', 'A checkbox option');
- *
- * o = s.option(form.ListValue, 'some_choice', 'A select element');
- * o.value('choice1', 'The first choice');
- * o.value('choice2', 'The second choice');
- *
- * m.render().then(function(node) {
- * 	document.body.appendChild(node);
- * });
- * </pre>
- */
-return baseclass.extend(/** @lends LuCI.form.prototype */ {
-	Map: CBIMap,
-	JSONMap: CBIJSONMap,
-	AbstractSection: CBIAbstractSection,
-	AbstractValue: CBIAbstractValue,
-
-	TypedSection: CBITypedSection,
-	TableSection: CBITableSection,
-	GridSection: CBIGridSection,
-	NamedSection: CBINamedSection,
-
-	Value: CBIValue,
-	DynamicList: CBIDynamicList,
-	ListValue: CBIListValue,
-	Flag: CBIFlagValue,
-	MultiValue: CBIMultiValue,
-	TextValue: CBITextValue,
-	DummyValue: CBIDummyValue,
-	Button: CBIButtonValue,
-	HiddenValue: CBIHiddenValue,
-	FileUpload: CBIFileUpload,
-	SectionValue: CBISectionValue
-});
-
-
-
- - - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - diff --git a/docs/jsapi/fs.js.html b/docs/jsapi/fs.js.html deleted file mode 100644 index 3645a8bcc5..0000000000 --- a/docs/jsapi/fs.js.html +++ /dev/null @@ -1,3885 +0,0 @@ - - - - - Source: fs.js - - - - - - - - - - - - - - - - - -
- - -
-

Source: fs.js

- - - - -
-
-
'use strict';
-'require rpc';
-'require request';
-'require baseclass';
-
-/**
- * @typedef {Object} FileStatEntry
- * @memberof LuCI.fs
-
- * @property {string} name - Name of the directory entry
- * @property {string} type - Type of the entry, one of `block`, `char`, `directory`, `fifo`, `symlink`, `file`, `socket` or `unknown`
- * @property {number} size - Size in bytes
- * @property {number} mode - Access permissions
- * @property {number} atime - Last access time in seconds since epoch
- * @property {number} mtime - Last modification time in seconds since epoch
- * @property {number} ctime - Last change time in seconds since epoch
- * @property {number} inode - Inode number
- * @property {number} uid - Numeric owner id
- * @property {number} gid - Numeric group id
- */
-
-/**
- * @typedef {Object} FileExecResult
- * @memberof LuCI.fs
- *
- * @property {number} code - The exit code of the invoked command
- * @property {string} [stdout] - The stdout produced by the command, if any
- * @property {string} [stderr] - The stderr produced by the command, if any
- */
-
-var callFileList, callFileStat, callFileRead, callFileWrite, callFileRemove,
-    callFileExec, callFileMD5;
-
-callFileList = rpc.declare({
-	object: 'file',
-	method: 'list',
-	params: [ 'path' ]
-});
-
-callFileStat = rpc.declare({
-	object: 'file',
-	method: 'stat',
-	params: [ 'path' ]
-});
-
-callFileRead = rpc.declare({
-	object: 'file',
-	method: 'read',
-	params: [ 'path' ]
-});
-
-callFileWrite = rpc.declare({
-	object: 'file',
-	method: 'write',
-	params: [ 'path', 'data', 'mode' ]
-});
-
-callFileRemove = rpc.declare({
-	object: 'file',
-	method: 'remove',
-	params: [ 'path' ]
-});
-
-callFileExec = rpc.declare({
-	object: 'file',
-	method: 'exec',
-	params: [ 'command', 'params', 'env' ]
-});
-
-callFileMD5 = rpc.declare({
-	object: 'file',
-	method: 'md5',
-	params: [ 'path' ]
-});
-
-var rpcErrors = [
-	null,
-	'InvalidCommandError',
-	'InvalidArgumentError',
-	'MethodNotFoundError',
-	'NotFoundError',
-	'NoDataError',
-	'PermissionError',
-	'TimeoutError',
-	'UnsupportedError'
-];
-
-function handleRpcReply(expect, rc) {
-	if (typeof(rc) == 'number' && rc != 0) {
-		var e = new Error(rpc.getStatusText(rc)); e.name = rpcErrors[rc] || 'Error';
-		throw e;
-	}
-
-	if (expect) {
-		var type = Object.prototype.toString;
-
-		for (var key in expect) {
-			if (rc != null && key != '')
-				rc = rc[key];
-
-			if (rc == null || type.call(rc) != type.call(expect[key])) {
-				var e = new Error(_('Unexpected reply data format')); e.name = 'TypeError';
-				throw e;
-			}
-
-			break;
-		}
-	}
-
-	return rc;
-}
-
-function handleCgiIoReply(res) {
-	if (!res.ok || res.status != 200) {
-		var e = new Error(res.statusText);
-		switch (res.status) {
-		case 400:
-			e.name = 'InvalidArgumentError';
-			break;
-
-		case 403:
-			e.name = 'PermissionError';
-			break;
-
-		case 404:
-			e.name = 'NotFoundError';
-			break;
-
-		default:
-			e.name = 'Error';
-		}
-		throw e;
-	}
-
-	switch (this.type) {
-	case 'blob':
-		return res.blob();
-
-	case 'json':
-		return res.json();
-
-	default:
-		return res.text();
-	}
-}
-
-/**
- * @class fs
- * @memberof LuCI
- * @hideconstructor
- * @classdesc
- *
- * Provides high level utilities to wrap file system related RPC calls.
- * To import the class in views, use `'require fs'`, to import it in
- * external JavaScript, use `L.require("fs").then(...)`.
- */
-var FileSystem = baseclass.extend(/** @lends LuCI.fs.prototype */ {
-	/**
-	 * Obtains a listing of the specified directory.
-	 *
-	 * @param {string} path
-	 * The directory path to list.
-	 *
-	 * @returns {Promise<LuCI.fs.FileStatEntry[]>}
-	 * Returns a promise resolving to an array of stat detail objects or
-	 * rejecting with an error stating the failure reason.
-	 */
-	list: function(path) {
-		return callFileList(path).then(handleRpcReply.bind(this, { entries: [] }));
-	},
-
-	/**
-	 * Return file stat information on the specified path.
-	 *
-	 * @param {string} path
-	 * The filesystem path to stat.
-	 *
-	 * @returns {Promise<LuCI.fs.FileStatEntry>}
-	 * Returns a promise resolving to a stat detail object or
-	 * rejecting with an error stating the failure reason.
-	 */
-	stat: function(path) {
-		return callFileStat(path).then(handleRpcReply.bind(this, { '': {} }));
-	},
-
-	/**
-	 * Read the contents of the given file and return them.
-	 * Note: this function is unsuitable for obtaining binary data.
-	 *
-	 * @param {string} path
-	 * The file path to read.
-	 *
-	 * @returns {Promise<string>}
-	 * Returns a promise resolving to a string containing the file contents or
-	 * rejecting with an error stating the failure reason.
-	 */
-	read: function(path) {
-		return callFileRead(path).then(handleRpcReply.bind(this, { data: '' }));
-	},
-
-	/**
-	 * Write the given data to the specified file path.
-	 * If the specified file path does not exist, it will be created, given
-	 * sufficient permissions.
-	 *
-	 * Note: `data` will be converted to a string using `String(data)` or to
-	 * `''` when it is `null`.
-	 *
-	 * @param {string} path
-	 * The file path to write to.
-	 *
-	 * @param {*} [data]
-	 * The file data to write. If it is null, it will be set to an empty
-	 * string.
-	 *
-	 * @param {number} [mode]
-	 * The permissions to use on file creation. Default is 420 (0644).
-	 *
-	 * @returns {Promise<number>}
-	 * Returns a promise resolving to `0` or rejecting with an error stating
-	 * the failure reason.
-	 */
-	write: function(path, data, mode) {
-		data = (data != null) ? String(data) : '';
-		mode = (mode != null) ? mode : 420; // 0644
-		return callFileWrite(path, data, mode).then(handleRpcReply.bind(this, { '': 0 }));
-	},
-
-	/**
-	 * Unlink the given file.
-	 *
-	 * @param {string}
-	 * The file path to remove.
-	 *
-	 * @returns {Promise<number>}
-	 * Returns a promise resolving to `0` or rejecting with an error stating
-	 * the failure reason.
-	 */
-	remove: function(path) {
-		return callFileRemove(path).then(handleRpcReply.bind(this, { '': 0 }));
-	},
-
-	/**
-	 * Execute the specified command, optionally passing params and
-	 * environment variables.
-	 *
-	 * Note: The `command` must be either the path to an executable,
-	 * or a basename without arguments in which case it will be searched
-	 * in $PATH. If specified, the values given in `params` will be passed
-	 * as arguments to the command.
-	 *
-	 * The key/value pairs in the optional `env` table are translated to
-	 * `setenv()` calls prior to running the command.
-	 *
-	 * @param {string} command
-	 * The command to invoke.
-	 *
-	 * @param {string[]} [params]
-	 * The arguments to pass to the command.
-	 *
-	 * @param {Object.<string, string>} [env]
-	 * Environment variables to set.
-	 *
-	 * @returns {Promise<LuCI.fs.FileExecResult>}
-	 * Returns a promise resolving to an object describing the execution
-	 * results or rejecting with an error stating the failure reason.
-	 */
-	exec: function(command, params, env) {
-		if (!Array.isArray(params))
-			params = null;
-
-		if (!L.isObject(env))
-			env = null;
-
-		return callFileExec(command, params, env).then(handleRpcReply.bind(this, { '': {} }));
-	},
-
-	/**
-	 * Read the contents of the given file, trim leading and trailing white
-	 * space and return the trimmed result. In case of errors, return an empty
-	 * string instead.
-	 *
-	 * Note: this function is useful to read single-value files in `/sys`
-	 * or `/proc`.
-	 *
-	 * This function is guaranteed to not reject its promises, on failure,
-	 * an empty string will be returned.
-	 *
-	 * @param {string} path
-	 * The file path to read.
-	 *
-	 * @returns {Promise<string>}
-	 * Returns a promise resolving to the file contents or the empty string
-	 * on failure.
-	 */
-	trimmed: function(path) {
-		return L.resolveDefault(this.read(path), '').then(function(s) {
-			return s.trim();
-		});
-	},
-
-	/**
-	 * Read the contents of the given file, split it into lines, trim
-	 * leading and trailing white space of each line and return the
-	 * resulting array.
-	 *
-	 * This function is guaranteed to not reject its promises, on failure,
-	 * an empty array will be returned.
-	 *
-	 * @param {string} path
-	 * The file path to read.
-	 *
-	 * @returns {Promise<string[]>}
-	 * Returns a promise resolving to an array containing the stripped lines
-	 * of the given file or `[]` on failure.
-	 */
-	lines: function(path) {
-		return L.resolveDefault(this.read(path), '').then(function(s) {
-			var lines = [];
-
-			s = s.trim();
-
-			if (s != '') {
-				var l = s.split(/\n/);
-
-				for (var i = 0; i < l.length; i++)
-					lines.push(l[i].trim());
-			}
-
-			return lines;
-		});
-	},
-
-	/**
-	 * Read the contents of the given file and return them, bypassing ubus.
-	 *
-	 * This function will read the requested file through the cgi-io
-	 * helper applet at `/cgi-bin/cgi-download` which bypasses the ubus rpc
-	 * transport. This is useful to fetch large file contents which might
-	 * exceed the ubus message size limits or which contain binary data.
-	 *
-	 * The cgi-io helper will enforce the same access permission rules as
-	 * the ubus based read call.
-	 *
-	 * @param {string} path
-	 * The file path to read.
-	 *
-	 * @param {string} [type=text]
-	 * The expected type of read file contents. Valid values are `text` to
-	 * interpret the contents as string, `json` to parse the contents as JSON
-	 * or `blob` to return the contents as Blob instance.
-	 *
-	 * @returns {Promise<*>}
-	 * Returns a promise resolving with the file contents interpreted according
-	 * to the specified type or rejecting with an error stating the failure
-	 * reason.
-	 */
-	read_direct: function(path, type) {
-		var postdata = 'sessionid=%s&path=%s'
-			.format(encodeURIComponent(L.env.sessionid), encodeURIComponent(path));
-
-		return request.post(L.env.cgi_base + '/cgi-download', postdata, {
-			headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
-			responseType: (type == 'blob') ? 'blob' : 'text'
-		}).then(handleCgiIoReply.bind({ type: type }));
-	},
-
-	/**
-	 * Execute the specified command, bypassing ubus.
-	 *
-	 * Note: The `command` must be either the path to an executable,
-	 * or a basename without arguments in which case it will be searched
-	 * in $PATH. If specified, the values given in `params` will be passed
-	 * as arguments to the command.
-	 *
-	 * This function will invoke the requested commands through the cgi-io
-	 * helper applet at `/cgi-bin/cgi-exec` which bypasses the ubus rpc
-	 * transport. This is useful to fetch large command outputs which might
-	 * exceed the ubus message size limits or which contain binary data.
-	 *
-	 * The cgi-io helper will enforce the same access permission rules as
-	 * the ubus based exec call.
-	 *
-	 * @param {string} command
-	 * The command to invoke.
-	 *
-	 * @param {string[]} [params]
-	 * The arguments to pass to the command.
-	 *
-	 * @param {string} [type=text]
-	 * The expected output type of the invoked program. Valid values are
-	 * `text` to interpret the output as string, `json` to parse the output
-	 * as JSON or `blob` to return the output as Blob instance.
-	 *
-	 * @param {boolean} [latin1=false]
-	 * Whether to encode the command line as Latin1 instead of UTF-8. This
-	 * is usually not needed but can be useful for programs that cannot
-	 * handle UTF-8 input.
-	 *
-	 * @returns {Promise<*>}
-	 * Returns a promise resolving with the command stdout output interpreted
-	 * according to the specified type or rejecting with an error stating the
-	 * failure reason.
-	 */
-	exec_direct: function(command, params, type, latin1) {
-		var cmdstr = String(command)
-			.replace(/\\/g, '\\\\').replace(/(\s)/g, '\\$1');
-
-		if (Array.isArray(params))
-			for (var i = 0; i < params.length; i++)
-				cmdstr += ' ' + String(params[i])
-					.replace(/\\/g, '\\\\').replace(/(\s)/g, '\\$1');
-
-		if (latin1)
-			cmdstr = escape(cmdstr).replace(/\+/g, '%2b');
-		else
-			cmdstr = encodeURIComponent(cmdstr);
-
-		var postdata = 'sessionid=%s&command=%s'
-			.format(encodeURIComponent(L.env.sessionid), cmdstr);
-
-		return request.post(L.env.cgi_base + '/cgi-exec', postdata, {
-			headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
-			responseType: (type == 'blob') ? 'blob' : 'text'
-		}).then(handleCgiIoReply.bind({ type: type }));
-	}
-});
-
-return FileSystem;
-
-
-
- - - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - diff --git a/docs/jsapi/index.html b/docs/jsapi/index.html deleted file mode 100644 index a31218bee1..0000000000 --- a/docs/jsapi/index.html +++ /dev/null @@ -1,3472 +0,0 @@ - - - - - Index - - - - - - - - - - - - - - - - - -
- - -
-

Index

- - - - - - -

- - - - - - - - - - - - - -
-

LuCI client side API documentation

-

You can browse the JavaScript apis provided by LuCI here. A good starting point is the central -luci.js class.

-
- - - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - \ No newline at end of file diff --git a/docs/jsapi/luci.js.html b/docs/jsapi/luci.js.html deleted file mode 100644 index 725e97edfc..0000000000 --- a/docs/jsapi/luci.js.html +++ /dev/null @@ -1,6874 +0,0 @@ - - - - - Source: luci.js - - - - - - - - - - - - - - - - - -
- - -
-

Source: luci.js

- - - - -
-
-
/**
- * @class LuCI
- * @classdesc
- *
- * This is the LuCI base class. It is automatically instantiated and
- * accessible using the global `L` variable.
- *
- * @param {Object} env
- * The environment settings to use for the LuCI runtime.
- */
-
-(function(window, document, undefined) {
-	'use strict';
-
-	var env = {};
-
-	/* Object.assign polyfill for IE */
-	if (typeof Object.assign !== 'function') {
-		Object.defineProperty(Object, 'assign', {
-			value: function assign(target, varArgs) {
-				if (target == null)
-					throw new TypeError('Cannot convert undefined or null to object');
-
-				var to = Object(target);
-
-				for (var index = 1; index < arguments.length; index++)
-					if (arguments[index] != null)
-						for (var nextKey in arguments[index])
-							if (Object.prototype.hasOwnProperty.call(arguments[index], nextKey))
-								to[nextKey] = arguments[index][nextKey];
-
-				return to;
-			},
-			writable: true,
-			configurable: true
-		});
-	}
-
-	/* Promise.finally polyfill */
-	if (typeof Promise.prototype.finally !== 'function') {
-		Promise.prototype.finally = function(fn) {
-			var onFinally = function(cb) {
-				return Promise.resolve(fn.call(this)).then(cb);
-			};
-
-			return this.then(
-				function(result) { return onFinally.call(this, function() { return result }) },
-				function(reason) { return onFinally.call(this, function() { return Promise.reject(reason) }) }
-			);
-		};
-	}
-
-	/*
-	 * Class declaration and inheritance helper
-	 */
-
-	var toCamelCase = function(s) {
-		return s.replace(/(?:^|[\. -])(.)/g, function(m0, m1) { return m1.toUpperCase() });
-	};
-
-	/**
-	 * @class baseclass
-	 * @hideconstructor
-	 * @memberof LuCI
-	 * @classdesc
-	 *
-	 * `LuCI.baseclass` is the abstract base class all LuCI classes inherit from.
-	 *
-	 * It provides simple means to create subclasses of given classes and
-	 * implements prototypal inheritance.
-	 */
-	var superContext = {}, classIndex = 0, Class = Object.assign(function() {}, {
-		/**
-		 * Extends this base class with the properties described in
-		 * `properties` and returns a new subclassed Class instance
-		 *
-		 * @memberof LuCI.baseclass
-		 *
-		 * @param {Object<string, *>} properties
-		 * An object describing the properties to add to the new
-		 * subclass.
-		 *
-		 * @returns {LuCI.baseclass}
-		 * Returns a new LuCI.baseclass sublassed from this class, extended
-		 * by the given properties and with its prototype set to this base
-		 * class to enable inheritance. The resulting value represents a
-		 * class constructor and can be instantiated with `new`.
-		 */
-		extend: function(properties) {
-			var props = {
-				__id__: { value: classIndex },
-				__base__: { value: this.prototype },
-				__name__: { value: properties.__name__ || 'anonymous' + classIndex++ }
-			};
-
-			var ClassConstructor = function() {
-				if (!(this instanceof ClassConstructor))
-					throw new TypeError('Constructor must not be called without "new"');
-
-				if (Object.getPrototypeOf(this).hasOwnProperty('__init__')) {
-					if (typeof(this.__init__) != 'function')
-						throw new TypeError('Class __init__ member is not a function');
-
-					this.__init__.apply(this, arguments)
-				}
-				else {
-					this.super('__init__', arguments);
-				}
-			};
-
-			for (var key in properties)
-				if (!props[key] && properties.hasOwnProperty(key))
-					props[key] = { value: properties[key], writable: true };
-
-			ClassConstructor.prototype = Object.create(this.prototype, props);
-			ClassConstructor.prototype.constructor = ClassConstructor;
-			Object.assign(ClassConstructor, this);
-			ClassConstructor.displayName = toCamelCase(props.__name__.value + 'Class');
-
-			return ClassConstructor;
-		},
-
-		/**
-		 * Extends this base class with the properties described in
-		 * `properties`, instantiates the resulting subclass using
-		 * the additional optional arguments passed to this function
-		 * and returns the resulting subclassed Class instance.
-		 *
-		 * This function serves as a convenience shortcut for
-		 * {@link LuCI.baseclass.extend Class.extend()} and subsequent
-		 * `new`.
-		 *
-		 * @memberof LuCI.baseclass
-		 *
-		 * @param {Object<string, *>} properties
-		 * An object describing the properties to add to the new
-		 * subclass.
-		 *
-		 * @param {...*} [new_args]
-		 * Specifies arguments to be passed to the subclass constructor
-		 * as-is in order to instantiate the new subclass.
-		 *
-		 * @returns {LuCI.baseclass}
-		 * Returns a new LuCI.baseclass instance extended by the given
-		 * properties with its prototype set to this base class to
-		 * enable inheritance.
-		 */
-		singleton: function(properties /*, ... */) {
-			return Class.extend(properties)
-				.instantiate(Class.prototype.varargs(arguments, 1));
-		},
-
-		/**
-		 * Calls the class constructor using `new` with the given argument
-		 * array being passed as variadic parameters to the constructor.
-		 *
-		 * @memberof LuCI.baseclass
-		 *
-		 * @param {Array<*>} params
-		 * An array of arbitrary values which will be passed as arguments
-		 * to the constructor function.
-		 *
-		 * @param {...*} [new_args]
-		 * Specifies arguments to be passed to the subclass constructor
-		 * as-is in order to instantiate the new subclass.
-		 *
-		 * @returns {LuCI.baseclass}
-		 * Returns a new LuCI.baseclass instance extended by the given
-		 * properties with its prototype set to this base class to
-		 * enable inheritance.
-		 */
-		instantiate: function(args) {
-			return new (Function.prototype.bind.apply(this,
-				Class.prototype.varargs(args, 0, null)))();
-		},
-
-		/* unused */
-		call: function(self, method) {
-			if (typeof(this.prototype[method]) != 'function')
-				throw new ReferenceError(method + ' is not defined in class');
-
-			return this.prototype[method].apply(self, self.varargs(arguments, 1));
-		},
-
-		/**
-		 * Checks whether the given class value is a subclass of this class.
-		 *
-		 * @memberof LuCI.baseclass
-		 *
-		 * @param {LuCI.baseclass} classValue
-		 * The class object to test.
-		 *
-		 * @returns {boolean}
-		 * Returns `true` when the given `classValue` is a subclass of this
-		 * class or `false` if the given value is not a valid class or not
-		 * a subclass of this class'.
-		 */
-		isSubclass: function(classValue) {
-			return (classValue != null &&
-			        typeof(classValue) == 'function' &&
-			        classValue.prototype instanceof this);
-		},
-
-		prototype: {
-			/**
-			 * Extract all values from the given argument array beginning from
-			 * `offset` and prepend any further given optional parameters to
-			 * the beginning of the resulting array copy.
-			 *
-			 * @memberof LuCI.baseclass
-			 * @instance
-			 *
-			 * @param {Array<*>} args
-			 * The array to extract the values from.
-			 *
-			 * @param {number} offset
-			 * The offset from which to extract the values. An offset of `0`
-			 * would copy all values till the end.
-			 *
-			 * @param {...*} [extra_args]
-			 * Extra arguments to add to prepend to the resultung array.
-			 *
-			 * @returns {Array<*>}
-			 * Returns a new array consisting of the optional extra arguments
-			 * and the values extracted from the `args` array beginning with
-			 * `offset`.
-			 */
-			varargs: function(args, offset /*, ... */) {
-				return Array.prototype.slice.call(arguments, 2)
-					.concat(Array.prototype.slice.call(args, offset));
-			},
-
-			/**
-			 * Walks up the parent class chain and looks for a class member
-			 * called `key` in any of the parent classes this class inherits
-			 * from. Returns the member value of the superclass or calls the
-			 * member as function and returns its return value when the
-			 * optional `callArgs` array is given.
-			 *
-			 * This function has two signatures and is sensitive to the
-			 * amount of arguments passed to it:
-			 *  - `super('key')` -
-			 *    Returns the value of `key` when found within one of the
-			 *    parent classes.
-			 *  - `super('key', ['arg1', 'arg2'])` -
-			 *    Calls the `key()` method with parameters `arg1` and `arg2`
-			 *    when found within one of the parent classes.
-			 *
-			 * @memberof LuCI.baseclass
-			 * @instance
-			 *
-			 * @param {string} key
-			 * The name of the superclass member to retrieve.
-			 *
-			 * @param {Array<*>} [callArgs]
-			 * An optional array of function call parameters to use. When
-			 * this parameter is specified, the found member value is called
-			 * as function using the values of this array as arguments.
-			 *
-			 * @throws {ReferenceError}
-			 * Throws a `ReferenceError` when `callArgs` are specified and
-			 * the found member named by `key` is not a function value.
-			 *
-			 * @returns {*|null}
-			 * Returns the value of the found member or the return value of
-			 * the call to the found method. Returns `null` when no member
-			 * was found in the parent class chain or when the call to the
-			 * superclass method returned `null`.
-			 */
-			super: function(key, callArgs) {
-				if (key == null)
-					return null;
-
-				var slotIdx = this.__id__ + '.' + key,
-				    symStack = superContext[slotIdx],
-				    protoCtx = null;
-
-				for (protoCtx = Object.getPrototypeOf(symStack ? symStack[0] : Object.getPrototypeOf(this));
-				     protoCtx != null && !protoCtx.hasOwnProperty(key);
-				     protoCtx = Object.getPrototypeOf(protoCtx)) {}
-
-				if (protoCtx == null)
-					return null;
-
-				var res = protoCtx[key];
-
-				if (arguments.length > 1) {
-					if (typeof(res) != 'function')
-						throw new ReferenceError(key + ' is not a function in base class');
-
-					if (typeof(callArgs) != 'object')
-						callArgs = this.varargs(arguments, 1);
-
-					if (symStack)
-						symStack.unshift(protoCtx);
-					else
-						superContext[slotIdx] = [ protoCtx ];
-
-					res = res.apply(this, callArgs);
-
-					if (symStack && symStack.length > 1)
-						symStack.shift(protoCtx);
-					else
-						delete superContext[slotIdx];
-				}
-
-				return res;
-			},
-
-			/**
-			 * Returns a string representation of this class.
-			 *
-			 * @returns {string}
-			 * Returns a string representation of this class containing the
-			 * constructor functions `displayName` and describing the class
-			 * members and their respective types.
-			 */
-			toString: function() {
-				var s = '[' + this.constructor.displayName + ']', f = true;
-				for (var k in this) {
-					if (this.hasOwnProperty(k)) {
-						s += (f ? ' {\n' : '') + '  ' + k + ': ' + typeof(this[k]) + '\n';
-						f = false;
-					}
-				}
-				return s + (f ? '' : '}');
-			}
-		}
-	});
-
-
-	/**
-	 * @class headers
-	 * @memberof LuCI
-	 * @hideconstructor
-	 * @classdesc
-	 *
-	 * The `Headers` class is an internal utility class exposed in HTTP
-	 * response objects using the `response.headers` property.
-	 */
-	var Headers = Class.extend(/** @lends LuCI.headers.prototype */ {
-		__name__: 'LuCI.headers',
-		__init__: function(xhr) {
-			var hdrs = this.headers = {};
-			xhr.getAllResponseHeaders().split(/\r\n/).forEach(function(line) {
-				var m = /^([^:]+):(.*)$/.exec(line);
-				if (m != null)
-					hdrs[m[1].trim().toLowerCase()] = m[2].trim();
-			});
-		},
-
-		/**
-		 * Checks whether the given header name is present.
-		 * Note: Header-Names are case-insensitive.
-		 *
-		 * @instance
-		 * @memberof LuCI.headers
-		 * @param {string} name
-		 * The header name to check
-		 *
-		 * @returns {boolean}
-		 * Returns `true` if the header name is present, `false` otherwise
-		 */
-		has: function(name) {
-			return this.headers.hasOwnProperty(String(name).toLowerCase());
-		},
-
-		/**
-		 * Returns the value of the given header name.
-		 * Note: Header-Names are case-insensitive.
-		 *
-		 * @instance
-		 * @memberof LuCI.headers
-		 * @param {string} name
-		 * The header name to read
-		 *
-		 * @returns {string|null}
-		 * The value of the given header name or `null` if the header isn't present.
-		 */
-		get: function(name) {
-			var key = String(name).toLowerCase();
-			return this.headers.hasOwnProperty(key) ? this.headers[key] : null;
-		}
-	});
-
-	/**
-	 * @class response
-	 * @memberof LuCI
-	 * @hideconstructor
-	 * @classdesc
-	 *
-	 * The `Response` class is an internal utility class representing HTTP responses.
-	 */
-	var Response = Class.extend({
-		__name__: 'LuCI.response',
-		__init__: function(xhr, url, duration, headers, content) {
-			/**
-			 * Describes whether the response is successful (status codes `200..299`) or not
-			 * @instance
-			 * @memberof LuCI.response
-			 * @name ok
-			 * @type {boolean}
-			 */
-			this.ok = (xhr.status >= 200 && xhr.status <= 299);
-
-			/**
-			 * The numeric HTTP status code of the response
-			 * @instance
-			 * @memberof LuCI.response
-			 * @name status
-			 * @type {number}
-			 */
-			this.status = xhr.status;
-
-			/**
-			 * The HTTP status description message of the response
-			 * @instance
-			 * @memberof LuCI.response
-			 * @name statusText
-			 * @type {string}
-			 */
-			this.statusText = xhr.statusText;
-
-			/**
-			 * The HTTP headers of the response
-			 * @instance
-			 * @memberof LuCI.response
-			 * @name headers
-			 * @type {LuCI.headers}
-			 */
-			this.headers = (headers != null) ? headers : new Headers(xhr);
-
-			/**
-			 * The total duration of the HTTP request in milliseconds
-			 * @instance
-			 * @memberof LuCI.response
-			 * @name duration
-			 * @type {number}
-			 */
-			this.duration = duration;
-
-			/**
-			 * The final URL of the request, i.e. after following redirects.
-			 * @instance
-			 * @memberof LuCI.response
-			 * @name url
-			 * @type {string}
-			 */
-			this.url = url;
-
-			/* privates */
-			this.xhr = xhr;
-
-			if (content instanceof Blob) {
-				this.responseBlob = content;
-				this.responseJSON = null;
-				this.responseText = null;
-			}
-			else if (content != null && typeof(content) == 'object') {
-				this.responseBlob = null;
-				this.responseJSON = content;
-				this.responseText = null;
-			}
-			else if (content != null) {
-				this.responseBlob = null;
-				this.responseJSON = null;
-				this.responseText = String(content);
-			}
-			else {
-				this.responseJSON = null;
-
-				if (xhr.responseType == 'blob') {
-					this.responseBlob = xhr.response;
-					this.responseText = null;
-				}
-				else {
-					this.responseBlob = null;
-					this.responseText = xhr.responseText;
-				}
-			}
-		},
-
-		/**
-		 * Clones the given response object, optionally overriding the content
-		 * of the cloned instance.
-		 *
-		 * @instance
-		 * @memberof LuCI.response
-		 * @param {*} [content]
-		 * Override the content of the cloned response. Object values will be
-		 * treated as JSON response data, all other types will be converted
-		 * using `String()` and treated as response text.
-		 *
-		 * @returns {LuCI.response}
-		 * The cloned `Response` instance.
-		 */
-		clone: function(content) {
-			var copy = new Response(this.xhr, this.url, this.duration, this.headers, content);
-
-			copy.ok = this.ok;
-			copy.status = this.status;
-			copy.statusText = this.statusText;
-
-			return copy;
-		},
-
-		/**
-		 * Access the response content as JSON data.
-		 *
-		 * @instance
-		 * @memberof LuCI.response
-		 * @throws {SyntaxError}
-		 * Throws `SyntaxError` if the content isn't valid JSON.
-		 *
-		 * @returns {*}
-		 * The parsed JSON data.
-		 */
-		json: function() {
-			if (this.responseJSON == null)
-				this.responseJSON = JSON.parse(this.responseText);
-
-			return this.responseJSON;
-		},
-
-		/**
-		 * Access the response content as string.
-		 *
-		 * @instance
-		 * @memberof LuCI.response
-		 * @returns {string}
-		 * The response content.
-		 */
-		text: function() {
-			if (this.responseText == null && this.responseJSON != null)
-				this.responseText = JSON.stringify(this.responseJSON);
-
-			return this.responseText;
-		},
-
-		/**
-		 * Access the response content as blob.
-		 *
-		 * @instance
-		 * @memberof LuCI.response
-		 * @returns {Blob}
-		 * The response content as blob.
-		 */
-		blob: function() {
-			return this.responseBlob;
-		}
-	});
-
-
-	var requestQueue = [];
-
-	function isQueueableRequest(opt) {
-		if (!classes.rpc)
-			return false;
-
-		if (opt.method != 'POST' || typeof(opt.content) != 'object')
-			return false;
-
-		if (opt.nobatch === true)
-			return false;
-
-		var rpcBaseURL = Request.expandURL(classes.rpc.getBaseURL());
-
-		return (rpcBaseURL != null && opt.url.indexOf(rpcBaseURL) == 0);
-	}
-
-	function flushRequestQueue() {
-		if (!requestQueue.length)
-			return;
-
-		var reqopt = Object.assign({}, requestQueue[0][0], { content: [], nobatch: true }),
-		    batch = [];
-
-		for (var i = 0; i < requestQueue.length; i++) {
-			batch[i] = requestQueue[i];
-			reqopt.content[i] = batch[i][0].content;
-		}
-
-		requestQueue.length = 0;
-
-		Request.request(rpcBaseURL, reqopt).then(function(reply) {
-			var json = null, req = null;
-
-			try { json = reply.json() }
-			catch(e) { }
-
-			while ((req = batch.shift()) != null)
-				if (Array.isArray(json) && json.length)
-					req[2].call(reqopt, reply.clone(json.shift()));
-				else
-					req[1].call(reqopt, new Error('No related RPC reply'));
-		}).catch(function(error) {
-			var req = null;
-
-			while ((req = batch.shift()) != null)
-				req[1].call(reqopt, error);
-		});
-	}
-
-	/**
-	 * @class request
-	 * @memberof LuCI
-	 * @hideconstructor
-	 * @classdesc
-	 *
-	 * The `Request` class allows initiating HTTP requests and provides utilities
-	 * for dealing with responses.
-	 */
-	var Request = Class.singleton(/** @lends LuCI.request.prototype */ {
-		__name__: 'LuCI.request',
-
-		interceptors: [],
-
-		/**
-		 * Turn the given relative URL into an absolute URL if necessary.
-		 *
-		 * @instance
-		 * @memberof LuCI.request
-		 * @param {string} url
-		 * The URL to convert.
-		 *
-		 * @returns {string}
-		 * The absolute URL derived from the given one, or the original URL
-		 * if it already was absolute.
-		 */
-		expandURL: function(url) {
-			if (!/^(?:[^/]+:)?\/\//.test(url))
-				url = location.protocol + '//' + location.host + url;
-
-			return url;
-		},
-
-		/**
-		 * @typedef {Object} RequestOptions
-		 * @memberof LuCI.request
-		 *
-		 * @property {string} [method=GET]
-		 * The HTTP method to use, e.g. `GET` or `POST`.
-		 *
-		 * @property {Object<string, Object|string>} [query]
-		 * Query string data to append to the URL. Non-string values of the
-		 * given object will be converted to JSON.
-		 *
-		 * @property {boolean} [cache=false]
-		 * Specifies whether the HTTP response may be retrieved from cache.
-		 *
-		 * @property {string} [username]
-		 * Provides a username for HTTP basic authentication.
-		 *
-		 * @property {string} [password]
-		 * Provides a password for HTTP basic authentication.
-		 *
-		 * @property {number} [timeout]
-		 * Specifies the request timeout in seconds.
-		 *
-		 * @property {boolean} [credentials=false]
-		 * Whether to include credentials such as cookies in the request.
-		 *
-		 * @property {string} [responseType=text]
-		 * Overrides the request response type. Valid values or `text` to
-		 * interpret the response as UTF-8 string or `blob` to handle the
-		 * response as binary `Blob` data.
-		 *
-		 * @property {*} [content]
-		 * Specifies the HTTP message body to send along with the request.
-		 * If the value is a function, it is invoked and the return value
-		 * used as content, if it is a FormData instance, it is used as-is,
-		 * if it is an object, it will be converted to JSON, in all other
-		 * cases it is converted to a string.
-		 *
-	     * @property {Object<string, string>} [header]
-	     * Specifies HTTP headers to set for the request.
-	     *
-	     * @property {function} [progress]
-	     * An optional request callback function which receives ProgressEvent
-	     * instances as sole argument during the HTTP request transfer.
-		 */
-
-		/**
-		 * Initiate an HTTP request to the given target.
-		 *
-		 * @instance
-		 * @memberof LuCI.request
-		 * @param {string} target
-		 * The URL to request.
-		 *
-		 * @param {LuCI.request.RequestOptions} [options]
-		 * Additional options to configure the request.
-		 *
-		 * @returns {Promise<LuCI.response>}
-		 * The resulting HTTP response.
-		 */
-		request: function(target, options) {
-			var state = { xhr: new XMLHttpRequest(), url: this.expandURL(target), start: Date.now() },
-			    opt = Object.assign({}, options, state),
-			    content = null,
-			    contenttype = null,
-			    callback = this.handleReadyStateChange;
-
-			return new Promise(function(resolveFn, rejectFn) {
-				opt.xhr.onreadystatechange = callback.bind(opt, resolveFn, rejectFn);
-				opt.method = String(opt.method || 'GET').toUpperCase();
-
-				if ('query' in opt) {
-					var q = (opt.query != null) ? Object.keys(opt.query).map(function(k) {
-						if (opt.query[k] != null) {
-							var v = (typeof(opt.query[k]) == 'object')
-								? JSON.stringify(opt.query[k])
-								: String(opt.query[k]);
-
-							return '%s=%s'.format(encodeURIComponent(k), encodeURIComponent(v));
-						}
-						else {
-							return encodeURIComponent(k);
-						}
-					}).join('&') : '';
-
-					if (q !== '') {
-						switch (opt.method) {
-						case 'GET':
-						case 'HEAD':
-						case 'OPTIONS':
-							opt.url += ((/\?/).test(opt.url) ? '&' : '?') + q;
-							break;
-
-						default:
-							if (content == null) {
-								content = q;
-								contenttype = 'application/x-www-form-urlencoded';
-							}
-						}
-					}
-				}
-
-				if (!opt.cache)
-					opt.url += ((/\?/).test(opt.url) ? '&' : '?') + (new Date()).getTime();
-
-				if (isQueueableRequest(opt)) {
-					requestQueue.push([opt, rejectFn, resolveFn]);
-					requestAnimationFrame(flushRequestQueue);
-					return;
-				}
-
-				if ('username' in opt && 'password' in opt)
-					opt.xhr.open(opt.method, opt.url, true, opt.username, opt.password);
-				else
-					opt.xhr.open(opt.method, opt.url, true);
-
-				opt.xhr.responseType = opt.responseType || 'text';
-
-				if ('overrideMimeType' in opt.xhr)
-					opt.xhr.overrideMimeType('application/octet-stream');
-
-				if ('timeout' in opt)
-					opt.xhr.timeout = +opt.timeout;
-
-				if ('credentials' in opt)
-					opt.xhr.withCredentials = !!opt.credentials;
-
-				if (opt.content != null) {
-					switch (typeof(opt.content)) {
-					case 'function':
-						content = opt.content(xhr);
-						break;
-
-					case 'object':
-						if (!(opt.content instanceof FormData)) {
-							content = JSON.stringify(opt.content);
-							contenttype = 'application/json';
-						}
-						else {
-							content = opt.content;
-						}
-						break;
-
-					default:
-						content = String(opt.content);
-					}
-				}
-
-				if ('headers' in opt)
-					for (var header in opt.headers)
-						if (opt.headers.hasOwnProperty(header)) {
-							if (header.toLowerCase() != 'content-type')
-								opt.xhr.setRequestHeader(header, opt.headers[header]);
-							else
-								contenttype = opt.headers[header];
-						}
-
-				if ('progress' in opt && 'upload' in opt.xhr)
-					opt.xhr.upload.addEventListener('progress', opt.progress);
-
-				if (contenttype != null)
-					opt.xhr.setRequestHeader('Content-Type', contenttype);
-
-				try {
-					opt.xhr.send(content);
-				}
-				catch (e) {
-					rejectFn.call(opt, e);
-				}
-			});
-		},
-
-		handleReadyStateChange: function(resolveFn, rejectFn, ev) {
-			var xhr = this.xhr,
-			    duration = Date.now() - this.start;
-
-			if (xhr.readyState !== 4)
-				return;
-
-			if (xhr.status === 0 && xhr.statusText === '') {
-				if (duration >= this.timeout)
-					rejectFn.call(this, new Error('XHR request timed out'));
-				else
-					rejectFn.call(this, new Error('XHR request aborted by browser'));
-			}
-			else {
-				var response = new Response(
-					xhr, xhr.responseURL || this.url, duration);
-
-				Promise.all(Request.interceptors.map(function(fn) { return fn(response) }))
-					.then(resolveFn.bind(this, response))
-					.catch(rejectFn.bind(this));
-			}
-		},
-
-		/**
-		 * Initiate an HTTP GET request to the given target.
-		 *
-		 * @instance
-		 * @memberof LuCI.request
-		 * @param {string} target
-		 * The URL to request.
-		 *
-		 * @param {LuCI.request.RequestOptions} [options]
-		 * Additional options to configure the request.
-		 *
-		 * @returns {Promise<LuCI.response>}
-		 * The resulting HTTP response.
-		 */
-		get: function(url, options) {
-			return this.request(url, Object.assign({ method: 'GET' }, options));
-		},
-
-		/**
-		 * Initiate an HTTP POST request to the given target.
-		 *
-		 * @instance
-		 * @memberof LuCI.request
-		 * @param {string} target
-		 * The URL to request.
-		 *
-		 * @param {*} [data]
-		 * The request data to send, see {@link LuCI.request.RequestOptions} for details.
-		 *
-		 * @param {LuCI.request.RequestOptions} [options]
-		 * Additional options to configure the request.
-		 *
-		 * @returns {Promise<LuCI.response>}
-		 * The resulting HTTP response.
-		 */
-		post: function(url, data, options) {
-			return this.request(url, Object.assign({ method: 'POST', content: data }, options));
-		},
-
-		/**
-		 * Interceptor functions are invoked whenever an HTTP reply is received, in the order
-		 * these functions have been registered.
-		 * @callback LuCI.request.interceptorFn
-		 * @param {LuCI.response} res
-		 * The HTTP response object
-		 */
-
-		/**
-		 * Register an HTTP response interceptor function. Interceptor
-		 * functions are useful to perform default actions on incoming HTTP
-		 * responses, such as checking for expired authentication or for
-		 * implementing request retries before returning a failure.
-		 *
-		 * @instance
-		 * @memberof LuCI.request
-		 * @param {LuCI.request.interceptorFn} interceptorFn
-		 * The interceptor function to register.
-		 *
-		 * @returns {LuCI.request.interceptorFn}
-		 * The registered function.
-		 */
-		addInterceptor: function(interceptorFn) {
-			if (typeof(interceptorFn) == 'function')
-				this.interceptors.push(interceptorFn);
-			return interceptorFn;
-		},
-
-		/**
-		 * Remove an HTTP response interceptor function. The passed function
-		 * value must be the very same value that was used to register the
-		 * function.
-		 *
-		 * @instance
-		 * @memberof LuCI.request
-		 * @param {LuCI.request.interceptorFn} interceptorFn
-		 * The interceptor function to remove.
-		 *
-		 * @returns {boolean}
-		 * Returns `true` if any function has been removed, else `false`.
-		 */
-		removeInterceptor: function(interceptorFn) {
-			var oldlen = this.interceptors.length, i = oldlen;
-			while (i--)
-				if (this.interceptors[i] === interceptorFn)
-					this.interceptors.splice(i, 1);
-			return (this.interceptors.length < oldlen);
-		},
-
-		/**
-		 * @class
-		 * @memberof LuCI.request
-		 * @hideconstructor
-		 * @classdesc
-		 *
-		 * The `Request.poll` class provides some convience wrappers around
-		 * {@link LuCI.poll} mainly to simplify registering repeating HTTP
-		 * request calls as polling functions.
-		 */
-		poll: {
-			/**
-			 * The callback function is invoked whenever an HTTP reply to a
-			 * polled request is received or when the polled request timed
-			 * out.
-			 *
-			 * @callback LuCI.request.poll~callbackFn
-			 * @param {LuCI.response} res
-			 * The HTTP response object.
-			 *
-			 * @param {*} data
-			 * The response JSON if the response could be parsed as such,
-			 * else `null`.
-			 *
-			 * @param {number} duration
-			 * The total duration of the request in milliseconds.
-			 */
-
-			/**
-			 * Register a repeating HTTP request with an optional callback
-			 * to invoke whenever a response for the request is received.
-			 *
-			 * @instance
-			 * @memberof LuCI.request.poll
-			 * @param {number} interval
-			 * The poll interval in seconds.
-			 *
-			 * @param {string} url
-			 * The URL to request on each poll.
-			 *
-			 * @param {LuCI.request.RequestOptions} [options]
-			 * Additional options to configure the request.
-			 *
-			 * @param {LuCI.request.poll~callbackFn} [callback]
-			 * {@link LuCI.request.poll~callbackFn Callback} function to
-			 * invoke for each HTTP reply.
-			 *
-			 * @throws {TypeError}
-			 * Throws `TypeError` when an invalid interval was passed.
-			 *
-			 * @returns {function}
-			 * Returns the internally created poll function.
-			 */
-			add: function(interval, url, options, callback) {
-				if (isNaN(interval) || interval <= 0)
-					throw new TypeError('Invalid poll interval');
-
-				var ival = interval >>> 0,
-				    opts = Object.assign({}, options, { timeout: ival * 1000 - 5 });
-
-				var fn = function() {
-					return Request.request(url, options).then(function(res) {
-						if (!Poll.active())
-							return;
-
-						try {
-							callback(res, res.json(), res.duration);
-						}
-						catch (err) {
-							callback(res, null, res.duration);
-						}
-					});
-				};
-
-				return (Poll.add(fn, ival) ? fn : null);
-			},
-
-			/**
-			 * Remove a polling request that has been previously added using `add()`.
-			 * This function is essentially a wrapper around
-			 * {@link LuCI.poll.remove LuCI.poll.remove()}.
-			 *
-			 * @instance
-			 * @memberof LuCI.request.poll
-			 * @param {function} entry
-			 * The poll function returned by {@link LuCI.request.poll#add add()}.
-			 *
-			 * @returns {boolean}
-			 * Returns `true` if any function has been removed, else `false`.
-			 */
-			remove: function(entry) { return Poll.remove(entry) },
-
-			/**
-			  * Alias for {@link LuCI.poll.start LuCI.poll.start()}.
-			  *
-			  * @instance
-			  * @memberof LuCI.request.poll
-			  */
-			start: function() { return Poll.start() },
-
-			/**
-			  * Alias for {@link LuCI.poll.stop LuCI.poll.stop()}.
-			  *
-			  * @instance
-			  * @memberof LuCI.request.poll
-			  */
-			stop: function() { return Poll.stop() },
-
-			/**
-			  * Alias for {@link LuCI.poll.active LuCI.poll.active()}.
-			  *
-			  * @instance
-			  * @memberof LuCI.request.poll
-			  */
-			active: function() { return Poll.active() }
-		}
-	});
-
-	/**
-	 * @class poll
-	 * @memberof LuCI
-	 * @hideconstructor
-	 * @classdesc
-	 *
-	 * The `Poll` class allows registering and unregistering poll actions,
-	 * as well as starting, stopping and querying the state of the polling
-	 * loop.
-	 */
-	var Poll = Class.singleton(/** @lends LuCI.poll.prototype */ {
-		__name__: 'LuCI.poll',
-
-		queue: [],
-
-		/**
-		 * Add a new operation to the polling loop. If the polling loop is not
-		 * already started at this point, it will be implicitely started.
-		 *
-		 * @instance
-		 * @memberof LuCI.poll
-		 * @param {function} fn
-		 * The function to invoke on each poll interval.
-		 *
-		 * @param {number} interval
-		 * The poll interval in seconds.
-		 *
-		 * @throws {TypeError}
-		 * Throws `TypeError` when an invalid interval was passed.
-		 *
-		 * @returns {boolean}
-		 * Returns `true` if the function has been added or `false` if it
-		 * already is registered.
-		 */
-		add: function(fn, interval) {
-			if (interval == null || interval <= 0)
-				interval = env.pollinterval || null;
-
-			if (isNaN(interval) || typeof(fn) != 'function')
-				throw new TypeError('Invalid argument to LuCI.poll.add()');
-
-			for (var i = 0; i < this.queue.length; i++)
-				if (this.queue[i].fn === fn)
-					return false;
-
-			var e = {
-				r: true,
-				i: interval >>> 0,
-				fn: fn
-			};
-
-			this.queue.push(e);
-
-			if (this.tick != null && !this.active())
-				this.start();
-
-			return true;
-		},
-
-		/**
-		 * Remove an operation from the polling loop. If no further operatons
-		 * are registered, the polling loop is implicitely stopped.
-		 *
-		 * @instance
-		 * @memberof LuCI.poll
-		 * @param {function} fn
-		 * The function to remove.
-		 *
-		 * @throws {TypeError}
-		 * Throws `TypeError` when the given argument isn't a function.
-		 *
-		 * @returns {boolean}
-		 * Returns `true` if the function has been removed or `false` if it
-		 * wasn't found.
-		 */
-		remove: function(fn) {
-			if (typeof(fn) != 'function')
-				throw new TypeError('Invalid argument to LuCI.poll.remove()');
-
-			var len = this.queue.length;
-
-			for (var i = len; i > 0; i--)
-				if (this.queue[i-1].fn === fn)
-					this.queue.splice(i-1, 1);
-
-			if (!this.queue.length && this.stop())
-				this.tick = 0;
-
-			return (this.queue.length != len);
-		},
-
-		/**
-		 * (Re)start the polling loop. Dispatches a custom `poll-start` event
-		 * to the `document` object upon successful start.
-		 *
-		 * @instance
-		 * @memberof LuCI.poll
-		 * @returns {boolean}
-		 * Returns `true` if polling has been started (or if no functions
-		 * where registered) or `false` when the polling loop already runs.
-		 */
-		start: function() {
-			if (this.active())
-				return false;
-
-			this.tick = 0;
-
-			if (this.queue.length) {
-				this.timer = window.setInterval(this.step, 1000);
-				this.step();
-				document.dispatchEvent(new CustomEvent('poll-start'));
-			}
-
-			return true;
-		},
-
-		/**
-		 * Stop the polling loop. Dispatches a custom `poll-stop` event
-		 * to the `document` object upon successful stop.
-		 *
-		 * @instance
-		 * @memberof LuCI.poll
-		 * @returns {boolean}
-		 * Returns `true` if polling has been stopped or `false` if it din't
-		 * run to begin with.
-		 */
-		stop: function() {
-			if (!this.active())
-				return false;
-
-			document.dispatchEvent(new CustomEvent('poll-stop'));
-			window.clearInterval(this.timer);
-			delete this.timer;
-			delete this.tick;
-			return true;
-		},
-
-		/* private */
-		step: function() {
-			for (var i = 0, e = null; (e = Poll.queue[i]) != null; i++) {
-				if ((Poll.tick % e.i) != 0)
-					continue;
-
-				if (!e.r)
-					continue;
-
-				e.r = false;
-
-				Promise.resolve(e.fn()).finally((function() { this.r = true }).bind(e));
-			}
-
-			Poll.tick = (Poll.tick + 1) % Math.pow(2, 32);
-		},
-
-		/**
-		 * Test whether the polling loop is running.
-		 *
-		 * @instance
-		 * @memberof LuCI.poll
-		 * @returns {boolean} - Returns `true` if polling is active, else `false`.
-		 */
-		active: function() {
-			return (this.timer != null);
-		}
-	});
-
-	/**
-	 * @class dom
-	 * @memberof LuCI
-	 * @hideconstructor
-	 * @classdesc
-	 *
-	 * The `dom` class provides convenience method for creating and
-	 * manipulating DOM elements.
-	 *
-	 * To import the class in views, use `'require dom'`, to import it in
-	 * external JavaScript, use `L.require("dom").then(...)`.
-	 */
-	var DOM = Class.singleton(/** @lends LuCI.dom.prototype */ {
-		__name__: 'LuCI.dom',
-
-		/**
-		 * Tests whether the given argument is a valid DOM `Node`.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {*} e
-		 * The value to test.
-		 *
-		 * @returns {boolean}
-		 * Returns `true` if the value is a DOM `Node`, else `false`.
-		 */
-		elem: function(e) {
-			return (e != null && typeof(e) == 'object' && 'nodeType' in e);
-		},
-
-		/**
-		 * Parses a given string as HTML and returns the first child node.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {string} s
-		 * A string containing an HTML fragment to parse. Note that only
-		 * the first result of the resulting structure is returned, so an
-		 * input value of `<div>foo</div> <div>bar</div>` will only return
-		 * the first `div` element node.
-		 *
-		 * @returns {Node}
-		 * Returns the first DOM `Node` extracted from the HTML fragment or
-		 * `null` on parsing failures or if no element could be found.
-		 */
-		parse: function(s) {
-			var elem;
-
-			try {
-				domParser = domParser || new DOMParser();
-				elem = domParser.parseFromString(s, 'text/html').body.firstChild;
-			}
-			catch(e) {}
-
-			if (!elem) {
-				try {
-					dummyElem = dummyElem || document.createElement('div');
-					dummyElem.innerHTML = s;
-					elem = dummyElem.firstChild;
-				}
-				catch (e) {}
-			}
-
-			return elem || null;
-		},
-
-		/**
-		 * Tests whether a given `Node` matches the given query selector.
-		 *
-		 * This function is a convenience wrapper around the standard
-		 * `Node.matches("selector")` function with the added benefit that
-		 * the `node` argument may be a non-`Node` value, in which case
-		 * this function simply returns `false`.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {*} node
-		 * The `Node` argument to test the selector against.
-		 *
-		 * @param {string} [selector]
-		 * The query selector expression to test against the given node.
-		 *
-		 * @returns {boolean}
-		 * Returns `true` if the given node matches the specified selector
-		 * or `false` when the node argument is no valid DOM `Node` or the
-		 * selector didn't match.
-		 */
-		matches: function(node, selector) {
-			var m = this.elem(node) ? node.matches || node.msMatchesSelector : null;
-			return m ? m.call(node, selector) : false;
-		},
-
-		/**
-		 * Returns the closest parent node that matches the given query
-		 * selector expression.
-		 *
-		 * This function is a convenience wrapper around the standard
-		 * `Node.closest("selector")` function with the added benefit that
-		 * the `node` argument may be a non-`Node` value, in which case
-		 * this function simply returns `null`.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {*} node
-		 * The `Node` argument to find the closest parent for.
-		 *
-		 * @param {string} [selector]
-		 * The query selector expression to test against each parent.
-		 *
-		 * @returns {Node|null}
-		 * Returns the closest parent node matching the selector or
-		 * `null` when the node argument is no valid DOM `Node` or the
-		 * selector didn't match any parent.
-		 */
-		parent: function(node, selector) {
-			if (this.elem(node) && node.closest)
-				return node.closest(selector);
-
-			while (this.elem(node))
-				if (this.matches(node, selector))
-					return node;
-				else
-					node = node.parentNode;
-
-			return null;
-		},
-
-		/**
-		 * Appends the given children data to the given node.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {*} node
-		 * The `Node` argument to append the children to.
-		 *
-		 * @param {*} [children]
-		 * The childrens to append to the given node.
-		 *
-		 * When `children` is an array, then each item of the array
-		 * will be either appended as child element or text node,
-		 * depending on whether the item is a DOM `Node` instance or
-		 * some other non-`null` value. Non-`Node`, non-`null` values
-		 * will be converted to strings first before being passed as
-		 * argument to `createTextNode()`.
-		 *
-		 * When `children` is a function, it will be invoked with
-		 * the passed `node` argument as sole parameter and the `append`
-		 * function will be invoked again, with the given `node` argument
-		 * as first and the return value of the `children` function as
-		 * second parameter.
-		 *
-		 * When `children` is is a DOM `Node` instance, it will be
-		 * appended to the given `node`.
-		 *
-		 * When `children` is any other non-`null` value, it will be
-		 * converted to a string and appened to the `innerHTML` property
-		 * of the given `node`.
-		 *
-		 * @returns {Node|null}
-		 * Returns the last children `Node` appended to the node or `null`
-		 * if either the `node` argument was no valid DOM `node` or if the
-		 * `children` was `null` or didn't result in further DOM nodes.
-		 */
-		append: function(node, children) {
-			if (!this.elem(node))
-				return null;
-
-			if (Array.isArray(children)) {
-				for (var i = 0; i < children.length; i++)
-					if (this.elem(children[i]))
-						node.appendChild(children[i]);
-					else if (children !== null && children !== undefined)
-						node.appendChild(document.createTextNode('' + children[i]));
-
-				return node.lastChild;
-			}
-			else if (typeof(children) === 'function') {
-				return this.append(node, children(node));
-			}
-			else if (this.elem(children)) {
-				return node.appendChild(children);
-			}
-			else if (children !== null && children !== undefined) {
-				node.innerHTML = '' + children;
-				return node.lastChild;
-			}
-
-			return null;
-		},
-
-		/**
-		 * Replaces the content of the given node with the given children.
-		 *
-		 * This function first removes any children of the given DOM
-		 * `Node` and then adds the given given children following the
-		 * rules outlined below.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {*} node
-		 * The `Node` argument to replace the children of.
-		 *
-		 * @param {*} [children]
-		 * The childrens to replace into the given node.
-		 *
-		 * When `children` is an array, then each item of the array
-		 * will be either appended as child element or text node,
-		 * depending on whether the item is a DOM `Node` instance or
-		 * some other non-`null` value. Non-`Node`, non-`null` values
-		 * will be converted to strings first before being passed as
-		 * argument to `createTextNode()`.
-		 *
-		 * When `children` is a function, it will be invoked with
-		 * the passed `node` argument as sole parameter and the `append`
-		 * function will be invoked again, with the given `node` argument
-		 * as first and the return value of the `children` function as
-		 * second parameter.
-		 *
-		 * When `children` is is a DOM `Node` instance, it will be
-		 * appended to the given `node`.
-		 *
-		 * When `children` is any other non-`null` value, it will be
-		 * converted to a string and appened to the `innerHTML` property
-		 * of the given `node`.
-		 *
-		 * @returns {Node|null}
-		 * Returns the last children `Node` appended to the node or `null`
-		 * if either the `node` argument was no valid DOM `node` or if the
-		 * `children` was `null` or didn't result in further DOM nodes.
-		 */
-		content: function(node, children) {
-			if (!this.elem(node))
-				return null;
-
-			var dataNodes = node.querySelectorAll('[data-idref]');
-
-			for (var i = 0; i < dataNodes.length; i++)
-				delete this.registry[dataNodes[i].getAttribute('data-idref')];
-
-			while (node.firstChild)
-				node.removeChild(node.firstChild);
-
-			return this.append(node, children);
-		},
-
-		/**
-		 * Sets attributes or registers event listeners on element nodes.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {*} node
-		 * The `Node` argument to set the attributes or add the event
-		 * listeners for. When the given `node` value is not a valid
-		 * DOM `Node`, the function returns and does nothing.
-		 *
-		 * @param {string|Object<string, *>} key
-		 * Specifies either the attribute or event handler name to use,
-		 * or an object containing multiple key, value pairs which are
-		 * each added to the node as either attribute or event handler,
-		 * depending on the respective value.
-		 *
-		 * @param {*} [val]
-		 * Specifies the attribute value or event handler function to add.
-		 * If the `key` parameter is an `Object`, this parameter will be
-		 * ignored.
-		 *
-		 * When `val` is of type function, it will be registered as event
-		 * handler on the given `node` with the `key` parameter being the
-		 * event name.
-		 *
-		 * When `val` is of type object, it will be serialized as JSON and
-		 * added as attribute to the given `node`, using the given `key`
-		 * as attribute name.
-		 *
-		 * When `val` is of any other type, it will be added as attribute
-		 * to the given `node` as-is, with the underlying `setAttribute()`
-		 * call implicitely turning it into a string.
-		 */
-		attr: function(node, key, val) {
-			if (!this.elem(node))
-				return null;
-
-			var attr = null;
-
-			if (typeof(key) === 'object' && key !== null)
-				attr = key;
-			else if (typeof(key) === 'string')
-				attr = {}, attr[key] = val;
-
-			for (key in attr) {
-				if (!attr.hasOwnProperty(key) || attr[key] == null)
-					continue;
-
-				switch (typeof(attr[key])) {
-				case 'function':
-					node.addEventListener(key, attr[key]);
-					break;
-
-				case 'object':
-					node.setAttribute(key, JSON.stringify(attr[key]));
-					break;
-
-				default:
-					node.setAttribute(key, attr[key]);
-				}
-			}
-		},
-
-		/**
-		 * Creates a new DOM `Node` from the given `html`, `attr` and
-		 * `data` parameters.
-		 *
-		 * This function has multiple signatures, it can be either invoked
-		 * in the form `create(html[, attr[, data]])` or in the form
-		 * `create(html[, data])`. The used variant is determined from the
-		 * type of the second argument.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {*} html
-		 * Describes the node to create.
-		 *
-		 * When the value of `html` is of type array, a `DocumentFragment`
-		 * node is created and each item of the array is first converted
-		 * to a DOM `Node` by passing it through `create()` and then added
-		 * as child to the fragment.
-		 *
-		 * When the value of `html` is a DOM `Node` instance, no new
-		 * element will be created but the node will be used as-is.
-		 *
-		 * When the value of `html` is a string starting with `<`, it will
-		 * be passed to `dom.parse()` and the resulting value is used.
-		 *
-		 * When the value of `html` is any other string, it will be passed
-		 * to `document.createElement()` for creating a new DOM `Node` of
-		 * the given name.
-		 *
-		 * @param {Object<string, *>} [attr]
-		 * Specifies an Object of key, value pairs to set as attributes
-		 * or event handlers on the created node. Refer to
-		 * {@link LuCI.dom#attr dom.attr()} for details.
-		 *
-		 * @param {*} [data]
-		 * Specifies children to append to the newly created element.
-		 * Refer to {@link LuCI.dom#append dom.append()} for details.
-		 *
-		 * @throws {InvalidCharacterError}
-		 * Throws an `InvalidCharacterError` when the given `html`
-		 * argument contained malformed markup (such as not escaped
-		 * `&` characters in XHTML mode) or when the given node name
-		 * in `html` contains characters which are not legal in DOM
-		 * element names, such as spaces.
-		 *
-		 * @returns {Node}
-		 * Returns the newly created `Node`.
-		 */
-		create: function() {
-			var html = arguments[0],
-			    attr = arguments[1],
-			    data = arguments[2],
-			    elem;
-
-			if (!(attr instanceof Object) || Array.isArray(attr))
-				data = attr, attr = null;
-
-			if (Array.isArray(html)) {
-				elem = document.createDocumentFragment();
-				for (var i = 0; i < html.length; i++)
-					elem.appendChild(this.create(html[i]));
-			}
-			else if (this.elem(html)) {
-				elem = html;
-			}
-			else if (html.charCodeAt(0) === 60) {
-				elem = this.parse(html);
-			}
-			else {
-				elem = document.createElement(html);
-			}
-
-			if (!elem)
-				return null;
-
-			this.attr(elem, attr);
-			this.append(elem, data);
-
-			return elem;
-		},
-
-		registry: {},
-
-		/**
-		 * Attaches or detaches arbitrary data to and from a DOM `Node`.
-		 *
-		 * This function is useful to attach non-string values or runtime
-		 * data that is not serializable to DOM nodes. To decouple data
-		 * from the DOM, values are not added directly to nodes, but
-		 * inserted into a registry instead which is then referenced by a
-		 * string key stored as `data-idref` attribute in the node.
-		 *
-		 * This function has multiple signatures and is sensitive to the
-		 * number of arguments passed to it.
-		 *
-		 *  - `dom.data(node)` -
-		 *     Fetches all data associated with the given node.
-		 *  - `dom.data(node, key)` -
-		 *     Fetches a specific key associated with the given node.
-		 *  - `dom.data(node, key, val)` -
-		 *     Sets a specific key to the given value associated with the
-		 *     given node.
-		 *  - `dom.data(node, null)` -
-		 *     Clears any data associated with the node.
-		 *  - `dom.data(node, key, null)` -
-		 *     Clears the given key associated with the node.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {Node} node
-		 * The DOM `Node` instance to set or retrieve the data for.
-		 *
-		 * @param {string|null} [key]
-		 * This is either a string specifying the key to retrieve, or
-		 * `null` to unset the entire node data.
-		 *
-		 * @param {*|null} [val]
-		 * This is either a non-`null` value to set for a given key or
-		 * `null` to remove the given `key` from the specified node.
-		 *
-		 * @returns {*}
-		 * Returns the get or set value, or `null` when no value could
-		 * be found.
-		 */
-		data: function(node, key, val) {
-			if (!node || !node.getAttribute)
-				return null;
-
-			var id = node.getAttribute('data-idref');
-
-			/* clear all data */
-			if (arguments.length > 1 && key == null) {
-				if (id != null) {
-					node.removeAttribute('data-idref');
-					val = this.registry[id]
-					delete this.registry[id];
-					return val;
-				}
-
-				return null;
-			}
-
-			/* clear a key */
-			else if (arguments.length > 2 && key != null && val == null) {
-				if (id != null) {
-					val = this.registry[id][key];
-					delete this.registry[id][key];
-					return val;
-				}
-
-				return null;
-			}
-
-			/* set a key */
-			else if (arguments.length > 2 && key != null && val != null) {
-				if (id == null) {
-					do { id = Math.floor(Math.random() * 0xffffffff).toString(16) }
-					while (this.registry.hasOwnProperty(id));
-
-					node.setAttribute('data-idref', id);
-					this.registry[id] = {};
-				}
-
-				return (this.registry[id][key] = val);
-			}
-
-			/* get all data */
-			else if (arguments.length == 1) {
-				if (id != null)
-					return this.registry[id];
-
-				return null;
-			}
-
-			/* get a key */
-			else if (arguments.length == 2) {
-				if (id != null)
-					return this.registry[id][key];
-			}
-
-			return null;
-		},
-
-		/**
-		 * Binds the given class instance ot the specified DOM `Node`.
-		 *
-		 * This function uses the `dom.data()` facility to attach the
-		 * passed instance of a Class to a node. This is needed for
-		 * complex widget elements or similar where the corresponding
-		 * class instance responsible for the element must be retrieved
-		 * from DOM nodes obtained by `querySelector()` or similar means.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {Node} node
-		 * The DOM `Node` instance to bind the class to.
-		 *
-		 * @param {Class} inst
-		 * The Class instance to bind to the node.
-		 *
-		 * @throws {TypeError}
-		 * Throws a `TypeError` when the given instance argument isn't
-		 * a valid Class instance.
-		 *
-		 * @returns {Class}
-		 * Returns the bound class instance.
-		 */
-		bindClassInstance: function(node, inst) {
-			if (!(inst instanceof Class))
-				LuCI.prototype.error('TypeError', 'Argument must be a class instance');
-
-			return this.data(node, '_class', inst);
-		},
-
-		/**
-		 * Finds a bound class instance on the given node itself or the
-		 * first bound instance on its closest parent node.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {Node} node
-		 * The DOM `Node` instance to start from.
-		 *
-		 * @returns {Class|null}
-		 * Returns the founds class instance if any or `null` if no bound
-		 * class could be found on the node itself or any of its parents.
-		 */
-		findClassInstance: function(node) {
-			var inst = null;
-
-			do {
-				inst = this.data(node, '_class');
-				node = node.parentNode;
-			}
-			while (!(inst instanceof Class) && node != null);
-
-			return inst;
-		},
-
-		/**
-		 * Finds a bound class instance on the given node itself or the
-		 * first bound instance on its closest parent node and invokes
-		 * the specified method name on the found class instance.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {Node} node
-		 * The DOM `Node` instance to start from.
-		 *
-		 * @param {string} method
-		 * The name of the method to invoke on the found class instance.
-		 *
-		 * @param {...*} params
-		 * Additional arguments to pass to the invoked method as-is.
-		 *
-		 * @returns {*|null}
-		 * Returns the return value of the invoked method if a class
-		 * instance and method has been found. Returns `null` if either
-		 * no bound class instance could be found, or if the found
-		 * instance didn't have the requested `method`.
-		 */
-		callClassMethod: function(node, method /*, ... */) {
-			var inst = this.findClassInstance(node);
-
-			if (inst == null || typeof(inst[method]) != 'function')
-				return null;
-
-			return inst[method].apply(inst, inst.varargs(arguments, 2));
-		},
-
-		/**
-		 * The ignore callback function is invoked by `isEmpty()` for each
-		 * child node to decide whether to ignore a child node or not.
-		 *
-		 * When this function returns `false`, the node passed to it is
-		 * ignored, else not.
-		 *
-		 * @callback LuCI.dom~ignoreCallbackFn
-		 * @param {Node} node
-		 * The child node to test.
-		 *
-		 * @returns {boolean}
-		 * Boolean indicating whether to ignore the node or not.
-		 */
-
-		/**
-		 * Tests whether a given DOM `Node` instance is empty or appears
-		 * empty.
-		 *
-		 * Any element child nodes which have the CSS class `hidden` set
-		 * or for which the optionally passed `ignoreFn` callback function
-		 * returns `false` are ignored.
-		 *
-		 * @instance
-		 * @memberof LuCI.dom
-		 * @param {Node} node
-		 * The DOM `Node` instance to test.
-		 *
-		 * @param {LuCI.dom~ignoreCallbackFn} [ignoreFn]
-		 * Specifies an optional function which is invoked for each child
-		 * node to decide whether the child node should be ignored or not.
-		 *
-		 * @returns {boolean}
-		 * Returns `true` if the node does not have any children or if
-		 * any children node either has a `hidden` CSS class or a `false`
-		 * result when testing it using the given `ignoreFn`.
-		 */
-		isEmpty: function(node, ignoreFn) {
-			for (var child = node.firstElementChild; child != null; child = child.nextElementSibling)
-				if (!child.classList.contains('hidden') && (!ignoreFn || !ignoreFn(child)))
-					return false;
-
-			return true;
-		}
-	});
-
-	/**
-	 * @class session
-	 * @memberof LuCI
-	 * @hideconstructor
-	 * @classdesc
-	 *
-	 * The `session` class provides various session related functionality.
-	 */
-	var Session = Class.singleton(/** @lends LuCI.session.prototype */ {
-		__name__: 'LuCI.session',
-
-		/**
-		 * Retrieve the current session ID.
-		 *
-		 * @returns {string}
-		 * Returns the current session ID.
-		 */
-		getID: function() {
-			return env.sessionid || '00000000000000000000000000000000';
-		},
-
-		/**
-		 * Retrieve the current session token.
-		 *
-		 * @returns {string|null}
-		 * Returns the current session token or `null` if not logged in.
-		 */
-		getToken: function() {
-			return env.token || null;
-		},
-
-		/**
-		 * Retrieve data from the local session storage.
-		 *
-		 * @param {string} [key]
-		 * The key to retrieve from the session data store. If omitted, all
-		 * session data will be returned.
-		 *
-		 * @returns {*}
-		 * Returns the stored session data or `null` if the given key wasn't
-		 * found.
-		 */
-		getLocalData: function(key) {
-			try {
-				var sid = this.getID(),
-				    item = 'luci-session-store',
-				    data = JSON.parse(window.sessionStorage.getItem(item));
-
-				if (!LuCI.prototype.isObject(data) || !data.hasOwnProperty(sid)) {
-					data = {};
-					data[sid] = {};
-				}
-
-				if (key != null)
-					return data[sid].hasOwnProperty(key) ? data[sid][key] : null;
-
-				return data[sid];
-			}
-			catch (e) {
-				return (key != null) ? null : {};
-			}
-		},
-
-		/**
-		 * Set data in the local session storage.
-		 *
-		 * @param {string} key
-		 * The key to set in the session data store.
-		 *
-		 * @param {*} value
-		 * The value to store. It will be internally converted to JSON before
-		 * being put in the session store.
-		 *
-		 * @returns {boolean}
-		 * Returns `true` if the data could be stored or `false` on error.
-		 */
-		setLocalData: function(key, value) {
-			if (key == null)
-				return false;
-
-			try {
-				var sid = this.getID(),
-				    item = 'luci-session-store',
-				    data = JSON.parse(window.sessionStorage.getItem(item));
-
-				if (!LuCI.prototype.isObject(data) || !data.hasOwnProperty(sid)) {
-					data = {};
-					data[sid] = {};
-				}
-
-				if (value != null)
-					data[sid][key] = value;
-				else
-					delete data[sid][key];
-
-				window.sessionStorage.setItem(item, JSON.stringify(data));
-
-				return true;
-			}
-			catch (e) {
-				return false;
-			}
-		}
-	});
-
-	/**
-	 * @class view
-	 * @memberof LuCI
-	 * @hideconstructor
-	 * @classdesc
-	 *
-	 * The `view` class forms the basis of views and provides a standard
-	 * set of methods to inherit from.
-	 */
-	var View = Class.extend(/** @lends LuCI.view.prototype */ {
-		__name__: 'LuCI.view',
-
-		__init__: function() {
-			var vp = document.getElementById('view');
-
-			DOM.content(vp, E('div', { 'class': 'spinning' }, _('Loading view…')));
-
-			return Promise.resolve(this.load())
-				.then(LuCI.prototype.bind(this.render, this))
-				.then(LuCI.prototype.bind(function(nodes) {
-					var vp = document.getElementById('view');
-
-					DOM.content(vp, nodes);
-					DOM.append(vp, this.addFooter());
-				}, this)).catch(LuCI.prototype.error);
-		},
-
-		/**
-		 * The load function is invoked before the view is rendered.
-		 *
-		 * The invocation of this function is wrapped by
-		 * `Promise.resolve()` so it may return Promises if needed.
-		 *
-		 * The return value of the function (or the resolved values
-		 * of the promise returned by it) will be passed as first
-		 * argument to `render()`.
-		 *
-		 * This function is supposed to be overwritten by subclasses,
-		 * the default implementation does nothing.
-		 *
-		 * @instance
-		 * @abstract
-		 * @memberof LuCI.view
-		 *
-		 * @returns {*|Promise<*>}
-		 * May return any value or a Promise resolving to any value.
-		 */
-		load: function() {},
-
-		/**
-		 * The render function is invoked after the
-		 * {@link LuCI.view#load load()} function and responsible
-		 * for setting up the view contents. It must return a DOM
-		 * `Node` or `DocumentFragment` holding the contents to
-		 * insert into the view area.
-		 *
-		 * The invocation of this function is wrapped by
-		 * `Promise.resolve()` so it may return Promises if needed.
-		 *
-		 * The return value of the function (or the resolved values
-		 * of the promise returned by it) will be inserted into the
-		 * main content area using
-		 * {@link LuCI.dom#append dom.append()}.
-		 *
-		 * This function is supposed to be overwritten by subclasses,
-		 * the default implementation does nothing.
-		 *
-		 * @instance
-		 * @abstract
-		 * @memberof LuCI.view
-		 * @param {*|null} load_results
-		 * This function will receive the return value of the
-		 * {@link LuCI.view#load view.load()} function as first
-		 * argument.
-		 *
-		 * @returns {Node|Promise<Node>}
-		 * Should return a DOM `Node` value or a `Promise` resolving
-		 * to a `Node` value.
-		 */
-		render: function() {},
-
-		/**
-		 * The handleSave function is invoked when the user clicks
-		 * the `Save` button in the page action footer.
-		 *
-		 * The default implementation should be sufficient for most
-		 * views using {@link form#Map form.Map()} based forms - it
-		 * will iterate all forms present in the view and invoke
-		 * the {@link form#Map#save Map.save()} method on each form.
-		 *
-		 * Views not using `Map` instances or requiring other special
-		 * logic should overwrite `handleSave()` with a custom
-		 * implementation.
-		 *
-		 * To disable the `Save` page footer button, views extending
-		 * this base class should overwrite the `handleSave` function
-		 * with `null`.
-		 *
-		 * The invocation of this function is wrapped by
-		 * `Promise.resolve()` so it may return Promises if needed.
-		 *
-		 * @instance
-		 * @memberof LuCI.view
-		 * @param {Event} ev
-		 * The DOM event that triggered the function.
-		 *
-		 * @returns {*|Promise<*>}
-		 * Any return values of this function are discarded, but
-		 * passed through `Promise.resolve()` to ensure that any
-		 * returned promise runs to completion before the button
-		 * is reenabled.
-		 */
-		handleSave: function(ev) {
-			var tasks = [];
-
-			document.getElementById('maincontent')
-				.querySelectorAll('.cbi-map').forEach(function(map) {
-					tasks.push(DOM.callClassMethod(map, 'save'));
-				});
-
-			return Promise.all(tasks);
-		},
-
-		/**
-		 * The handleSaveApply function is invoked when the user clicks
-		 * the `Save & Apply` button in the page action footer.
-		 *
-		 * The default implementation should be sufficient for most
-		 * views using {@link form#Map form.Map()} based forms - it
-		 * will first invoke
-		 * {@link LuCI.view.handleSave view.handleSave()} and then
-		 * call {@link ui#changes#apply ui.changes.apply()} to start the
-		 * modal config apply and page reload flow.
-		 *
-		 * Views not using `Map` instances or requiring other special
-		 * logic should overwrite `handleSaveApply()` with a custom
-		 * implementation.
-		 *
-		 * To disable the `Save & Apply` page footer button, views
-		 * extending this base class should overwrite the
-		 * `handleSaveApply` function with `null`.
-		 *
-		 * The invocation of this function is wrapped by
-		 * `Promise.resolve()` so it may return Promises if needed.
-		 *
-		 * @instance
-		 * @memberof LuCI.view
-		 * @param {Event} ev
-		 * The DOM event that triggered the function.
-		 *
-		 * @returns {*|Promise<*>}
-		 * Any return values of this function are discarded, but
-		 * passed through `Promise.resolve()` to ensure that any
-		 * returned promise runs to completion before the button
-		 * is reenabled.
-		 */
-		handleSaveApply: function(ev, mode) {
-			return this.handleSave(ev).then(function() {
-				classes.ui.changes.apply(mode == '0');
-			});
-		},
-
-		/**
-		 * The handleReset function is invoked when the user clicks
-		 * the `Reset` button in the page action footer.
-		 *
-		 * The default implementation should be sufficient for most
-		 * views using {@link form#Map form.Map()} based forms - it
-		 * will iterate all forms present in the view and invoke
-		 * the {@link form#Map#save Map.reset()} method on each form.
-		 *
-		 * Views not using `Map` instances or requiring other special
-		 * logic should overwrite `handleReset()` with a custom
-		 * implementation.
-		 *
-		 * To disable the `Reset` page footer button, views extending
-		 * this base class should overwrite the `handleReset` function
-		 * with `null`.
-		 *
-		 * The invocation of this function is wrapped by
-		 * `Promise.resolve()` so it may return Promises if needed.
-		 *
-		 * @instance
-		 * @memberof LuCI.view
-		 * @param {Event} ev
-		 * The DOM event that triggered the function.
-		 *
-		 * @returns {*|Promise<*>}
-		 * Any return values of this function are discarded, but
-		 * passed through `Promise.resolve()` to ensure that any
-		 * returned promise runs to completion before the button
-		 * is reenabled.
-		 */
-		handleReset: function(ev) {
-			var tasks = [];
-
-			document.getElementById('maincontent')
-				.querySelectorAll('.cbi-map').forEach(function(map) {
-					tasks.push(DOM.callClassMethod(map, 'reset'));
-				});
-
-			return Promise.all(tasks);
-		},
-
-		/**
-		 * Renders a standard page action footer if any of the
-		 * `handleSave()`, `handleSaveApply()` or `handleReset()`
-		 * functions are defined.
-		 *
-		 * The default implementation should be sufficient for most
-		 * views - it will render a standard page footer with action
-		 * buttons labeled `Save`, `Save & Apply` and `Reset`
-		 * triggering the `handleSave()`, `handleSaveApply()` and
-		 * `handleReset()` functions respectively.
-		 *
-		 * When any of these `handle*()` functions is overwritten
-		 * with `null` by a view extending this class, the
-		 * corresponding button will not be rendered.
-		 *
-		 * @instance
-		 * @memberof LuCI.view
-		 * @returns {DocumentFragment}
-		 * Returns a `DocumentFragment` containing the footer bar
-		 * with buttons for each corresponding `handle*()` action
-		 * or an empty `DocumentFragment` if all three `handle*()`
-		 * methods are overwritten with `null`.
-		 */
-		addFooter: function() {
-			var footer = E([]),
-			    vp = document.getElementById('view'),
-			    hasmap = false,
-			    readonly = true;
-
-			vp.querySelectorAll('.cbi-map').forEach(function(map) {
-				var m = DOM.findClassInstance(map);
-				if (m) {
-					hasmap = true;
-
-					if (!m.readonly)
-						readonly = false;
-				}
-			});
-
-			if (!hasmap)
-				readonly = !LuCI.prototype.hasViewPermission();
-
-			var saveApplyBtn = this.handleSaveApply ? new classes.ui.ComboButton('0', {
-				0: [ _('Save & Apply') ],
-				1: [ _('Apply unchecked') ]
-			}, {
-				classes: {
-					0: 'btn cbi-button cbi-button-apply important',
-					1: 'btn cbi-button cbi-button-negative important'
-				},
-				click: classes.ui.createHandlerFn(this, 'handleSaveApply'),
-				disabled: readonly || null
-			}).render() : E([]);
-
-			if (this.handleSaveApply || this.handleSave || this.handleReset) {
-				footer.appendChild(E('div', { 'class': 'cbi-page-actions control-group' }, [
-					saveApplyBtn, ' ',
-					this.handleSave ? E('button', {
-						'class': 'cbi-button cbi-button-save',
-						'click': classes.ui.createHandlerFn(this, 'handleSave'),
-						'disabled': readonly || null
-					}, [ _('Save') ]) : '', ' ',
-					this.handleReset ? E('button', {
-						'class': 'cbi-button cbi-button-reset',
-						'click': classes.ui.createHandlerFn(this, 'handleReset'),
-						'disabled': readonly || null
-					}, [ _('Reset') ]) : ''
-				]));
-			}
-
-			return footer;
-		}
-	});
-
-
-	var dummyElem = null,
-	    domParser = null,
-	    originalCBIInit = null,
-	    rpcBaseURL = null,
-	    sysFeatures = null,
-	    preloadClasses = null;
-
-	/* "preload" builtin classes to make the available via require */
-	var classes = {
-		baseclass: Class,
-		dom: DOM,
-		poll: Poll,
-		request: Request,
-		session: Session,
-		view: View
-	};
-
-	var LuCI = Class.extend(/** @lends LuCI.prototype */ {
-		__name__: 'LuCI',
-		__init__: function(setenv) {
-
-			document.querySelectorAll('script[src*="/luci.js"]').forEach(function(s) {
-				if (setenv.base_url == null || setenv.base_url == '') {
-					var m = (s.getAttribute('src') || '').match(/^(.*)\/luci\.js(?:\?v=([^?]+))?$/);
-					if (m) {
-						setenv.base_url = m[1];
-						setenv.resource_version = m[2];
-					}
-				}
-			});
-
-			if (setenv.base_url == null)
-				this.error('InternalError', 'Cannot find url of luci.js');
-
-			setenv.cgi_base = setenv.scriptname.replace(/\/[^\/]+$/, '');
-
-			Object.assign(env, setenv);
-
-			var domReady = new Promise(function(resolveFn, rejectFn) {
-				document.addEventListener('DOMContentLoaded', resolveFn);
-			});
-
-			Promise.all([
-				domReady,
-				this.require('ui'),
-				this.require('rpc'),
-				this.require('form'),
-				this.probeRPCBaseURL()
-			]).then(this.setupDOM.bind(this)).catch(this.error);
-
-			originalCBIInit = window.cbi_init;
-			window.cbi_init = function() {};
-		},
-
-		/**
-		 * Captures the current stack trace and throws an error of the
-		 * specified type as a new exception. Also logs the exception as
-		 * error to the debug console if it is available.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {Error|string} [type=Error]
-		 * Either a string specifying the type of the error to throw or an
-		 * existing `Error` instance to copy.
-		 *
-		 * @param {string} [fmt=Unspecified error]
-		 * A format string which is used to form the error message, together
-		 * with all subsequent optional arguments.
-		 *
-		 * @param {...*} [args]
-		 * Zero or more variable arguments to the supplied format string.
-		 *
-		 * @throws {Error}
-		 * Throws the created error object with the captured stack trace
-		 * appended to the message and the type set to the given type
-		 * argument or copied from the given error instance.
-		 */
-		raise: function(type, fmt /*, ...*/) {
-			var e = null,
-			    msg = fmt ? String.prototype.format.apply(fmt, this.varargs(arguments, 2)) : null,
-			    stack = null;
-
-			if (type instanceof Error) {
-				e = type;
-
-				if (msg)
-					e.message = msg + ': ' + e.message;
-			}
-			else {
-				try { throw new Error('stacktrace') }
-				catch (e2) { stack = (e2.stack || '').split(/\n/) }
-
-				e = new (window[type || 'Error'] || Error)(msg || 'Unspecified error');
-				e.name = type || 'Error';
-			}
-
-			stack = (stack || []).map(function(frame) {
-				frame = frame.replace(/(.*?)@(.+):(\d+):(\d+)/g, 'at $1 ($2:$3:$4)').trim();
-				return frame ? '  ' + frame : '';
-			});
-
-			if (!/^  at /.test(stack[0]))
-				stack.shift();
-
-			if (/\braise /.test(stack[0]))
-				stack.shift();
-
-			if (/\berror /.test(stack[0]))
-				stack.shift();
-
-			if (stack.length)
-				e.message += '\n' + stack.join('\n');
-
-			if (window.console && console.debug)
-				console.debug(e);
-
-			throw e;
-		},
-
-		/**
-		 * A wrapper around {@link LuCI#raise raise()} which also renders
-		 * the error either as modal overlay when `ui.js` is already loaed
-		 * or directly into the view body.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {Error|string} [type=Error]
-		 * Either a string specifying the type of the error to throw or an
-		 * existing `Error` instance to copy.
-		 *
-		 * @param {string} [fmt=Unspecified error]
-		 * A format string which is used to form the error message, together
-		 * with all subsequent optional arguments.
-		 *
-		 * @param {...*} [args]
-		 * Zero or more variable arguments to the supplied format string.
-		 *
-		 * @throws {Error}
-		 * Throws the created error object with the captured stack trace
-		 * appended to the message and the type set to the given type
-		 * argument or copied from the given error instance.
-		 */
-		error: function(type, fmt /*, ...*/) {
-			try {
-				LuCI.prototype.raise.apply(LuCI.prototype,
-					Array.prototype.slice.call(arguments));
-			}
-			catch (e) {
-				if (!e.reported) {
-					if (classes.ui)
-						classes.ui.addNotification(e.name || _('Runtime error'),
-							E('pre', {}, e.message), 'danger');
-					else
-						DOM.content(document.querySelector('#maincontent'),
-							E('pre', { 'class': 'alert-message error' }, e.message));
-
-					e.reported = true;
-				}
-
-				throw e;
-			}
-		},
-
-		/**
-		 * Return a bound function using the given `self` as `this` context
-		 * and any further arguments as parameters to the bound function.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {function} fn
-		 * The function to bind.
-		 *
-		 * @param {*} self
-		 * The value to bind as `this` context to the specified function.
-		 *
-		 * @param {...*} [args]
-		 * Zero or more variable arguments which are bound to the function
-		 * as parameters.
-		 *
-		 * @returns {function}
-		 * Returns the bound function.
-		 */
-		bind: function(fn, self /*, ... */) {
-			return Function.prototype.bind.apply(fn, this.varargs(arguments, 2, self));
-		},
-
-		/**
-		 * Load an additional LuCI JavaScript class and its dependencies,
-		 * instantiate it and return the resulting class instance. Each
-		 * class is only loaded once. Subsequent attempts to load the same
-		 * class will return the already instantiated class.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {string} name
-		 * The name of the class to load in dotted notation. Dots will
-		 * be replaced by spaces and joined with the runtime-determined
-		 * base URL of LuCI.js to form an absolute URL to load the class
-		 * file from.
-		 *
-		 * @throws {DependencyError}
-		 * Throws a `DependencyError` when the class to load includes
-		 * circular dependencies.
-		 *
-		 * @throws {NetworkError}
-		 * Throws `NetworkError` when the underlying {@link LuCI.request}
-		 * call failed.
-		 *
-		 * @throws {SyntaxError}
-		 * Throws `SyntaxError` when the loaded class file code cannot
-		 * be interpreted by `eval`.
-		 *
-		 * @throws {TypeError}
-		 * Throws `TypeError` when the class file could be loaded and
-		 * interpreted, but when invoking its code did not yield a valid
-		 * class instance.
-		 *
-		 * @returns {Promise<LuCI.baseclass>}
-		 * Returns the instantiated class.
-		 */
-		require: function(name, from) {
-			var L = this, url = null, from = from || [];
-
-			/* Class already loaded */
-			if (classes[name] != null) {
-				/* Circular dependency */
-				if (from.indexOf(name) != -1)
-					LuCI.prototype.raise('DependencyError',
-						'Circular dependency: class "%s" depends on "%s"',
-						name, from.join('" which depends on "'));
-
-				return Promise.resolve(classes[name]);
-			}
-
-			url = '%s/%s.js%s'.format(env.base_url, name.replace(/\./g, '/'), (env.resource_version ? '?v=' + env.resource_version : ''));
-			from = [ name ].concat(from);
-
-			var compileClass = function(res) {
-				if (!res.ok)
-					LuCI.prototype.raise('NetworkError',
-						'HTTP error %d while loading class file "%s"', res.status, url);
-
-				var source = res.text(),
-				    requirematch = /^require[ \t]+(\S+)(?:[ \t]+as[ \t]+([a-zA-Z_]\S*))?$/,
-				    strictmatch = /^use[ \t]+strict$/,
-				    depends = [],
-				    args = '';
-
-				/* find require statements in source */
-				for (var i = 0, off = -1, prev = -1, quote = -1, comment = -1, esc = false; i < source.length; i++) {
-					var chr = source.charCodeAt(i);
-
-					if (esc) {
-						esc = false;
-					}
-					else if (comment != -1) {
-						if ((comment == 47 && chr == 10) || (comment == 42 && prev == 42 && chr == 47))
-							comment = -1;
-					}
-					else if ((chr == 42 || chr == 47) && prev == 47) {
-						comment = chr;
-					}
-					else if (chr == 92) {
-						esc = true;
-					}
-					else if (chr == quote) {
-						var s = source.substring(off, i),
-						    m = requirematch.exec(s);
-
-						if (m) {
-							var dep = m[1], as = m[2] || dep.replace(/[^a-zA-Z0-9_]/g, '_');
-							depends.push(LuCI.prototype.require(dep, from));
-							args += ', ' + as;
-						}
-						else if (!strictmatch.exec(s)) {
-							break;
-						}
-
-						off = -1;
-						quote = -1;
-					}
-					else if (quote == -1 && (chr == 34 || chr == 39)) {
-						off = i + 1;
-						quote = chr;
-					}
-
-					prev = chr;
-				}
-
-				/* load dependencies and instantiate class */
-				return Promise.all(depends).then(function(instances) {
-					var _factory, _class;
-
-					try {
-						_factory = eval(
-							'(function(window, document, L%s) { %s })\n\n//# sourceURL=%s\n'
-								.format(args, source, res.url));
-					}
-					catch (error) {
-						LuCI.prototype.raise('SyntaxError', '%s\n  in %s:%s',
-							error.message, res.url, error.lineNumber || '?');
-					}
-
-					_factory.displayName = toCamelCase(name + 'ClassFactory');
-					_class = _factory.apply(_factory, [window, document, L].concat(instances));
-
-					if (!Class.isSubclass(_class))
-					    LuCI.prototype.error('TypeError', '"%s" factory yields invalid constructor', name);
-
-					if (_class.displayName == 'AnonymousClass')
-						_class.displayName = toCamelCase(name + 'Class');
-
-					var ptr = Object.getPrototypeOf(L),
-					    parts = name.split(/\./),
-					    instance = new _class();
-
-					for (var i = 0; ptr && i < parts.length - 1; i++)
-						ptr = ptr[parts[i]];
-
-					if (ptr)
-						ptr[parts[i]] = instance;
-
-					classes[name] = instance;
-
-					return instance;
-				});
-			};
-
-			/* Request class file */
-			classes[name] = Request.get(url, { cache: true }).then(compileClass);
-
-			return classes[name];
-		},
-
-		/* DOM setup */
-		probeRPCBaseURL: function() {
-			if (rpcBaseURL == null)
-				rpcBaseURL = Session.getLocalData('rpcBaseURL');
-
-			if (rpcBaseURL == null) {
-				var rpcFallbackURL = this.url('admin/ubus');
-
-				rpcBaseURL = Request.get(env.ubuspath).then(function(res) {
-					return (rpcBaseURL = (res.status == 400) ? env.ubuspath : rpcFallbackURL);
-				}, function() {
-					return (rpcBaseURL = rpcFallbackURL);
-				}).then(function(url) {
-					Session.setLocalData('rpcBaseURL', url);
-					return url;
-				});
-			}
-
-			return Promise.resolve(rpcBaseURL);
-		},
-
-		probeSystemFeatures: function() {
-			if (sysFeatures == null)
-				sysFeatures = Session.getLocalData('features');
-
-			if (!this.isObject(sysFeatures)) {
-				sysFeatures = classes.rpc.declare({
-					object: 'luci',
-					method: 'getFeatures',
-					expect: { '': {} }
-				})().then(function(features) {
-					Session.setLocalData('features', features);
-					sysFeatures = features;
-
-					return features;
-				});
-			}
-
-			return Promise.resolve(sysFeatures);
-		},
-
-		probePreloadClasses: function() {
-			if (preloadClasses == null)
-				preloadClasses = Session.getLocalData('preload');
-
-			if (!Array.isArray(preloadClasses)) {
-				preloadClasses = this.resolveDefault(classes.rpc.declare({
-					object: 'file',
-					method: 'list',
-					params: [ 'path' ],
-					expect: { 'entries': [] }
-				})(this.fspath(this.resource('preload'))), []).then(function(entries) {
-					var classes = [];
-
-					for (var i = 0; i < entries.length; i++) {
-						if (entries[i].type != 'file')
-							continue;
-
-						var m = entries[i].name.match(/(.+)\.js$/);
-
-						if (m)
-							classes.push('preload.%s'.format(m[1]));
-					}
-
-					Session.setLocalData('preload', classes);
-					preloadClasses = classes;
-
-					return classes;
-				});
-			}
-
-			return Promise.resolve(preloadClasses);
-		},
-
-		/**
-		 * Test whether a particular system feature is available, such as
-		 * hostapd SAE support or an installed firewall. The features are
-		 * queried once at the beginning of the LuCI session and cached in
-		 * `SessionStorage` throughout the lifetime of the associated tab or
-		 * browser window.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {string} feature
-		 * The feature to test. For detailed list of known feature flags,
-		 * see `/modules/luci-base/root/usr/libexec/rpcd/luci`.
-		 *
-		 * @param {string} [subfeature]
-		 * Some feature classes like `hostapd` provide sub-feature flags,
-		 * such as `sae` or `11w` support. The `subfeature` argument can
-		 * be used to query these.
-		 *
-		 * @return {boolean|null}
-		 * Return `true` if the queried feature (and sub-feature) is available
-		 * or `false` if the requested feature isn't present or known.
-		 * Return `null` when a sub-feature was queried for a feature which
-		 * has no sub-features.
-		 */
-		hasSystemFeature: function() {
-			var ft = sysFeatures[arguments[0]];
-
-			if (arguments.length == 2)
-				return this.isObject(ft) ? ft[arguments[1]] : null;
-
-			return (ft != null && ft != false);
-		},
-
-		/* private */
-		notifySessionExpiry: function() {
-			Poll.stop();
-
-			classes.ui.showModal(_('Session expired'), [
-				E('div', { class: 'alert-message warning' },
-					_('A new login is required since the authentication session expired.')),
-				E('div', { class: 'right' },
-					E('div', {
-						class: 'btn primary',
-						click: function() {
-							var loc = window.location;
-							window.location = loc.protocol + '//' + loc.host + loc.pathname + loc.search;
-						}
-					}, _('To login…')))
-			]);
-
-			LuCI.prototype.raise('SessionError', 'Login session is expired');
-		},
-
-		/* private */
-		setupDOM: function(res) {
-			var domEv = res[0],
-			    uiClass = res[1],
-			    rpcClass = res[2],
-			    formClass = res[3],
-			    rpcBaseURL = res[4];
-
-			rpcClass.setBaseURL(rpcBaseURL);
-
-			rpcClass.addInterceptor(function(msg, req) {
-				if (!LuCI.prototype.isObject(msg) ||
-				    !LuCI.prototype.isObject(msg.error) ||
-				    msg.error.code != -32002)
-					return;
-
-				if (!LuCI.prototype.isObject(req) ||
-				    (req.object == 'session' && req.method == 'access'))
-					return;
-
-				return rpcClass.declare({
-					'object': 'session',
-					'method': 'access',
-					'params': [ 'scope', 'object', 'function' ],
-					'expect': { access: true }
-				})('uci', 'luci', 'read').catch(LuCI.prototype.notifySessionExpiry);
-			});
-
-			Request.addInterceptor(function(res) {
-				var isDenied = false;
-
-				if (res.status == 403 && res.headers.get('X-LuCI-Login-Required') == 'yes')
-					isDenied = true;
-
-				if (!isDenied)
-					return;
-
-				LuCI.prototype.notifySessionExpiry();
-			});
-
-			document.addEventListener('poll-start', function(ev) {
-				uiClass.showIndicator('poll-status', _('Refreshing'), function(ev) {
-					Request.poll.active() ? Request.poll.stop() : Request.poll.start();
-				});
-			});
-
-			document.addEventListener('poll-stop', function(ev) {
-				uiClass.showIndicator('poll-status', _('Paused'), null, 'inactive');
-			});
-
-			return Promise.all([
-				this.probeSystemFeatures(),
-				this.probePreloadClasses()
-			]).finally(LuCI.prototype.bind(function() {
-				var tasks = [];
-
-				if (Array.isArray(preloadClasses))
-					for (var i = 0; i < preloadClasses.length; i++)
-						tasks.push(this.require(preloadClasses[i]));
-
-				return Promise.all(tasks);
-			}, this)).finally(this.initDOM);
-		},
-
-		/* private */
-		initDOM: function() {
-			originalCBIInit();
-			Poll.start();
-			document.dispatchEvent(new CustomEvent('luci-loaded'));
-		},
-
-		/**
-		 * The `env` object holds environment settings used by LuCI, such
-		 * as request timeouts, base URLs etc.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 */
-		env: env,
-
-		/**
-		 * Construct an absolute filesystem path relative to the server
-		 * document root.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {...string} [parts]
-		 * An array of parts to join into a path.
-		 *
-		 * @return {string}
-		 * Return the joined path.
-		 */
-		fspath: function(/* ... */) {
-			var path = env.documentroot;
-
-			for (var i = 0; i < arguments.length; i++)
-				path += '/' + arguments[i];
-
-			var p = path.replace(/\/+$/, '').replace(/\/+/g, '/').split(/\//),
-			    res = [];
-
-			for (var i = 0; i < p.length; i++)
-				if (p[i] == '..')
-					res.pop();
-				else if (p[i] != '.')
-					res.push(p[i]);
-
-			return res.join('/');
-		},
-
-		/**
-		 * Construct a relative URL path from the given prefix and parts.
-		 * The resulting URL is guaranteed to only contain the characters
-		 * `a-z`, `A-Z`, `0-9`, `_`, `.`, `%`, `,`, `;`, and `-` as well
-		 * as `/` for the path separator.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {string} [prefix]
-		 * The prefix to join the given parts with. If the `prefix` is
-		 * omitted, it defaults to an empty string.
-		 *
-		 * @param {string[]} [parts]
-		 * An array of parts to join into an URL path. Parts may contain
-		 * slashes and any of the other characters mentioned above.
-		 *
-		 * @return {string}
-		 * Return the joined URL path.
-		 */
-		path: function(prefix, parts) {
-			var url = [ prefix || '' ];
-
-			for (var i = 0; i < parts.length; i++)
-				if (/^(?:[a-zA-Z0-9_.%,;-]+\/)*[a-zA-Z0-9_.%,;-]+$/.test(parts[i]))
-					url.push('/', parts[i]);
-
-			if (url.length === 1)
-				url.push('/');
-
-			return url.join('');
-		},
-
-		/**
-		 * Construct an URL  pathrelative to the script path of the server
-		 * side LuCI application (usually `/cgi-bin/luci`).
-		 *
-		 * The resulting URL is guaranteed to only contain the characters
-		 * `a-z`, `A-Z`, `0-9`, `_`, `.`, `%`, `,`, `;`, and `-` as well
-		 * as `/` for the path separator.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {string[]} [parts]
-		 * An array of parts to join into an URL path. Parts may contain
-		 * slashes and any of the other characters mentioned above.
-		 *
-		 * @return {string}
-		 * Returns the resulting URL path.
-		 */
-		url: function() {
-			return this.path(env.scriptname, arguments);
-		},
-
-		/**
-		 * Construct an URL path relative to the global static resource path
-		 * of the LuCI ui (usually `/luci-static/resources`).
-		 *
-		 * The resulting URL is guaranteed to only contain the characters
-		 * `a-z`, `A-Z`, `0-9`, `_`, `.`, `%`, `,`, `;`, and `-` as well
-		 * as `/` for the path separator.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {string[]} [parts]
-		 * An array of parts to join into an URL path. Parts may contain
-		 * slashes and any of the other characters mentioned above.
-		 *
-		 * @return {string}
-		 * Returns the resulting URL path.
-		 */
-		resource: function() {
-			return this.path(env.resource, arguments);
-		},
-
-		/**
-		 * Construct an URL path relative to the media resource path of the
-		 * LuCI ui (usually `/luci-static/$theme_name`).
-		 *
-		 * The resulting URL is guaranteed to only contain the characters
-		 * `a-z`, `A-Z`, `0-9`, `_`, `.`, `%`, `,`, `;`, and `-` as well
-		 * as `/` for the path separator.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {string[]} [parts]
-		 * An array of parts to join into an URL path. Parts may contain
-		 * slashes and any of the other characters mentioned above.
-		 *
-		 * @return {string}
-		 * Returns the resulting URL path.
-		 */
-		media: function() {
-			return this.path(env.media, arguments);
-		},
-
-		/**
-		 * Return the complete URL path to the current view.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @return {string}
-		 * Returns the URL path to the current view.
-		 */
-		location: function() {
-			return this.path(env.scriptname, env.requestpath);
-		},
-
-
-		/**
-		 * Tests whether the passed argument is a JavaScript object.
-		 * This function is meant to be an object counterpart to the
-		 * standard `Array.isArray()` function.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {*} [val]
-		 * The value to test
-		 *
-		 * @return {boolean}
-		 * Returns `true` if the given value is of type object and
-		 * not `null`, else returns `false`.
-		 */
-		isObject: function(val) {
-			return (val != null && typeof(val) == 'object');
-		},
-
-		/**
-		 * Return an array of sorted object keys, optionally sorted by
-		 * a different key or a different sorting mode.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {object} obj
-		 * The object to extract the keys from. If the given value is
-		 * not an object, the function will return an empty array.
-		 *
-		 * @param {string} [key]
-		 * Specifies the key to order by. This is mainly useful for
-		 * nested objects of objects or objects of arrays when sorting
-		 * shall not be performed by the primary object keys but by
-		 * some other key pointing to a value within the nested values.
-		 *
-		 * @param {string} [sortmode]
-		 * May be either `addr` or `num` to override the natural
-		 * lexicographic sorting with a sorting suitable for IP/MAC style
-		 * addresses or numeric values respectively.
-		 *
-		 * @return {string[]}
-		 * Returns an array containing the sorted keys of the given object.
-		 */
-		sortedKeys: function(obj, key, sortmode) {
-			if (obj == null || typeof(obj) != 'object')
-				return [];
-
-			return Object.keys(obj).map(function(e) {
-				var v = (key != null) ? obj[e][key] : e;
-
-				switch (sortmode) {
-				case 'addr':
-					v = (v != null) ? v.replace(/(?:^|[.:])([0-9a-fA-F]{1,4})/g,
-						function(m0, m1) { return ('000' + m1.toLowerCase()).substr(-4) }) : null;
-					break;
-
-				case 'num':
-					v = (v != null) ? +v : null;
-					break;
-				}
-
-				return [ e, v ];
-			}).filter(function(e) {
-				return (e[1] != null);
-			}).sort(function(a, b) {
-				return (a[1] > b[1]);
-			}).map(function(e) {
-				return e[0];
-			});
-		},
-
-		/**
-		 * Converts the given value to an array. If the given value is of
-		 * type array, it is returned as-is, values of type object are
-		 * returned as one-element array containing the object, empty
-		 * strings and `null` values are returned as empty array, all other
-		 * values are converted using `String()`, trimmed, split on white
-		 * space and returned as array.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {*} val
-		 * The value to convert into an array.
-		 *
-		 * @return {Array<*>}
-		 * Returns the resulting array.
-		 */
-		toArray: function(val) {
-			if (val == null)
-				return [];
-			else if (Array.isArray(val))
-				return val;
-			else if (typeof(val) == 'object')
-				return [ val ];
-
-			var s = String(val).trim();
-
-			if (s == '')
-				return [];
-
-			return s.split(/\s+/);
-		},
-
-		/**
-		 * Returns a promise resolving with either the given value or or with
-		 * the given default in case the input value is a rejecting promise.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {*} value
-		 * The value to resolve the promise with.
-		 *
-		 * @param {*} defvalue
-		 * The default value to resolve the promise with in case the given
-		 * input value is a rejecting promise.
-		 *
-		 * @returns {Promise<*>}
-		 * Returns a new promise resolving either to the given input value or
-		 * to the given default value on error.
-		 */
-		resolveDefault: function(value, defvalue) {
-			return Promise.resolve(value).catch(function() { return defvalue });
-		},
-
-		/**
-		 * The request callback function is invoked whenever an HTTP
-		 * reply to a request made using the `L.get()`, `L.post()` or
-		 * `L.poll()` function is timed out or received successfully.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @callback LuCI.requestCallbackFn
-		 * @param {XMLHTTPRequest} xhr
-		 * The XMLHTTPRequest instance used to make the request.
-		 *
-		 * @param {*} data
-		 * The response JSON if the response could be parsed as such,
-		 * else `null`.
-		 *
-		 * @param {number} duration
-		 * The total duration of the request in milliseconds.
-		 */
-
-		/**
-		 * Issues a GET request to the given url and invokes the specified
-		 * callback function. The function is a wrapper around
-		 * {@link LuCI.request#request Request.request()}.
-		 *
-		 * @deprecated
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {string} url
-		 * The URL to request.
-		 *
-		 * @param {Object<string, string>} [args]
-		 * Additional query string arguments to append to the URL.
-		 *
-		 * @param {LuCI.requestCallbackFn} cb
-		 * The callback function to invoke when the request finishes.
-		 *
-		 * @return {Promise<null>}
-		 * Returns a promise resolving to `null` when concluded.
-		 */
-		get: function(url, args, cb) {
-			return this.poll(null, url, args, cb, false);
-		},
-
-		/**
-		 * Issues a POST request to the given url and invokes the specified
-		 * callback function. The function is a wrapper around
-		 * {@link LuCI.request#request Request.request()}. The request is
-		 * sent using `application/x-www-form-urlencoded` encoding and will
-		 * contain a field `token` with the current value of `LuCI.env.token`
-		 * by default.
-		 *
-		 * @deprecated
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {string} url
-		 * The URL to request.
-		 *
-		 * @param {Object<string, string>} [args]
-		 * Additional post arguments to append to the request body.
-		 *
-		 * @param {LuCI.requestCallbackFn} cb
-		 * The callback function to invoke when the request finishes.
-		 *
-		 * @return {Promise<null>}
-		 * Returns a promise resolving to `null` when concluded.
-		 */
-		post: function(url, args, cb) {
-			return this.poll(null, url, args, cb, true);
-		},
-
-		/**
-		 * Register a polling HTTP request that invokes the specified
-		 * callback function. The function is a wrapper around
-		 * {@link LuCI.request.poll#add Request.poll.add()}.
-		 *
-		 * @deprecated
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {number} interval
-		 * The poll interval to use. If set to a value less than or equal
-		 * to `0`, it will default to the global poll interval configured
-		 * in `LuCI.env.pollinterval`.
-		 *
-		 * @param {string} url
-		 * The URL to request.
-		 *
-		 * @param {Object<string, string>} [args]
-		 * Specifies additional arguments for the request. For GET requests,
-		 * the arguments are appended to the URL as query string, for POST
-		 * requests, they'll be added to the request body.
-		 *
-		 * @param {LuCI.requestCallbackFn} cb
-		 * The callback function to invoke whenever a request finishes.
-		 *
-		 * @param {boolean} [post=false]
-		 * When set to `false` or not specified, poll requests will be made
-		 * using the GET method. When set to `true`, POST requests will be
-		 * issued. In case of POST requests, the request body will contain
-		 * an argument `token` with the current value of `LuCI.env.token` by
-		 * default, regardless of the parameters specified with `args`.
-		 *
-		 * @return {function}
-		 * Returns the internally created function that has been passed to
-		 * {@link LuCI.request.poll#add Request.poll.add()}. This value can
-		 * be passed to {@link LuCI.poll.remove Poll.remove()} to remove the
-		 * polling request.
-		 */
-		poll: function(interval, url, args, cb, post) {
-			if (interval !== null && interval <= 0)
-				interval = env.pollinterval;
-
-			var data = post ? { token: env.token } : null,
-			    method = post ? 'POST' : 'GET';
-
-			if (!/^(?:\/|\S+:\/\/)/.test(url))
-				url = this.url(url);
-
-			if (args != null)
-				data = Object.assign(data || {}, args);
-
-			if (interval !== null)
-				return Request.poll.add(interval, url, { method: method, query: data }, cb);
-			else
-				return Request.request(url, { method: method, query: data })
-					.then(function(res) {
-						var json = null;
-						if (/^application\/json\b/.test(res.headers.get('Content-Type')))
-							try { json = res.json() } catch(e) {}
-						cb(res.xhr, json, res.duration);
-					});
-		},
-
-		/**
-		 * Check whether a view has sufficient permissions.
-		 *
-		 * @return {boolean|null}
-		 * Returns `null` if the current session has no permission at all to
-		 * load resources required by the view. Returns `false` if readonly
-		 * permissions are granted or `true` if at least one required ACL
-		 * group is granted with write permissions.
-		 */
-		hasViewPermission: function() {
-			if (!this.isObject(env.nodespec) || !env.nodespec.satisfied)
-			    return null;
-
-			return !env.nodespec.readonly;
-		},
-
-		/**
-		 * Deprecated wrapper around {@link LuCI.poll.remove Poll.remove()}.
-		 *
-		 * @deprecated
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @param {function} entry
-		 * The polling function to remove.
-		 *
-		 * @return {boolean}
-		 * Returns `true` when the function has been removed or `false` if
-		 * it could not be found.
-		 */
-		stop: function(entry) { return Poll.remove(entry) },
-
-		/**
-		 * Deprecated wrapper around {@link LuCI.poll.stop Poll.stop()}.
-		 *
-		 * @deprecated
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @return {boolean}
-		 * Returns `true` when the polling loop has been stopped or `false`
-		 * when it didn't run to begin with.
-		 */
-		halt: function() { return Poll.stop() },
-
-		/**
-		 * Deprecated wrapper around {@link LuCI.poll.start Poll.start()}.
-		 *
-		 * @deprecated
-		 * @instance
-		 * @memberof LuCI
-		 *
-		 * @return {boolean}
-		 * Returns `true` when the polling loop has been started or `false`
-		 * when it was already running.
-		 */
-		run: function() { return Poll.start() },
-
-		/**
-		 * Legacy `L.dom` class alias. New view code should use `'require dom';`
-		 * to request the `LuCI.dom` class.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 * @deprecated
-		 */
-		dom: DOM,
-
-		/**
-		 * Legacy `L.view` class alias. New view code should use `'require view';`
-		 * to request the `LuCI.view` class.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 * @deprecated
-		 */
-		view: View,
-
-		/**
-		 * Legacy `L.Poll` class alias. New view code should use `'require poll';`
-		 * to request the `LuCI.poll` class.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 * @deprecated
-		 */
-		Poll: Poll,
-
-		/**
-		 * Legacy `L.Request` class alias. New view code should use `'require request';`
-		 * to request the `LuCI.request` class.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 * @deprecated
-		 */
-		Request: Request,
-
-		/**
-		 * Legacy `L.Class` class alias. New view code should use `'require baseclass';`
-		 * to request the `LuCI.baseclass` class.
-		 *
-		 * @instance
-		 * @memberof LuCI
-		 * @deprecated
-		 */
-		Class: Class
-	});
-
-	/**
-	 * @class xhr
-	 * @memberof LuCI
-	 * @deprecated
-	 * @classdesc
-	 *
-	 * The `LuCI.xhr` class is a legacy compatibility shim for the
-	 * functionality formerly provided by `xhr.js`. It is registered as global
-	 * `window.XHR` symbol for compatibility with legacy code.
-	 *
-	 * New code should use {@link LuCI.request} instead to implement HTTP
-	 * request handling.
-	 */
-	var XHR = Class.extend(/** @lends LuCI.xhr.prototype */ {
-		__name__: 'LuCI.xhr',
-		__init__: function() {
-			if (window.console && console.debug)
-				console.debug('Direct use XHR() is deprecated, please use L.Request instead');
-		},
-
-		_response: function(cb, res, json, duration) {
-			if (this.active)
-				cb(res, json, duration);
-			delete this.active;
-		},
-
-		/**
-		 * This function is a legacy wrapper around
-		 * {@link LuCI#get LuCI.get()}.
-		 *
-		 * @instance
-		 * @deprecated
-		 * @memberof LuCI.xhr
-		 *
-		 * @param {string} url
-		 * The URL to request
-		 *
-		 * @param {Object} [data]
-		 * Additional query string data
-		 *
-		 * @param {LuCI.requestCallbackFn} [callback]
-		 * Callback function to invoke on completion
-		 *
-		 * @param {number} [timeout]
-		 * Request timeout to use
-		 *
-		 * @return {Promise<null>}
-		 */
-		get: function(url, data, callback, timeout) {
-			this.active = true;
-			LuCI.prototype.get(url, data, this._response.bind(this, callback), timeout);
-		},
-
-		/**
-		 * This function is a legacy wrapper around
-		 * {@link LuCI#post LuCI.post()}.
-		 *
-		 * @instance
-		 * @deprecated
-		 * @memberof LuCI.xhr
-		 *
-		 * @param {string} url
-		 * The URL to request
-		 *
-		 * @param {Object} [data]
-		 * Additional data to append to the request body.
-		 *
-		 * @param {LuCI.requestCallbackFn} [callback]
-		 * Callback function to invoke on completion
-		 *
-		 * @param {number} [timeout]
-		 * Request timeout to use
-		 *
-		 * @return {Promise<null>}
-		 */
-		post: function(url, data, callback, timeout) {
-			this.active = true;
-			LuCI.prototype.post(url, data, this._response.bind(this, callback), timeout);
-		},
-
-		/**
-		 * Cancels a running request.
-		 *
-		 * This function does not actually cancel the underlying
-		 * `XMLHTTPRequest` request but it sets a flag which prevents the
-		 * invocation of the callback function when the request eventually
-		 * finishes or timed out.
-		 *
-		 * @instance
-		 * @deprecated
-		 * @memberof LuCI.xhr
-		 */
-		cancel: function() { delete this.active },
-
-		/**
-		 * Checks the running state of the request.
-		 *
-		 * @instance
-		 * @deprecated
-		 * @memberof LuCI.xhr
-		 *
-		 * @returns {boolean}
-		 * Returns `true` if the request is still running or `false` if it
-		 * already completed.
-		 */
-		busy: function() { return (this.active === true) },
-
-		/**
-		 * Ignored for backwards compatibility.
-		 *
-		 * This function does nothing.
-		 *
-		 * @instance
-		 * @deprecated
-		 * @memberof LuCI.xhr
-		 */
-		abort: function() {},
-
-		/**
-		 * Existing for backwards compatibility.
-		 *
-		 * This function simply throws an `InternalError` when invoked.
-		 *
-		 * @instance
-		 * @deprecated
-		 * @memberof LuCI.xhr
-		 *
-		 * @throws {InternalError}
-		 * Throws an `InternalError` with the message `Not implemented`
-		 * when invoked.
-		 */
-		send_form: function() { LuCI.prototype.error('InternalError', 'Not implemented') },
-	});
-
-	XHR.get = function() { return LuCI.prototype.get.apply(LuCI.prototype, arguments) };
-	XHR.post = function() { return LuCI.prototype.post.apply(LuCI.prototype, arguments) };
-	XHR.poll = function() { return LuCI.prototype.poll.apply(LuCI.prototype, arguments) };
-	XHR.stop = Request.poll.remove.bind(Request.poll);
-	XHR.halt = Request.poll.stop.bind(Request.poll);
-	XHR.run = Request.poll.start.bind(Request.poll);
-	XHR.running = Request.poll.active.bind(Request.poll);
-
-	window.XHR = XHR;
-	window.LuCI = LuCI;
-})(window, document);
-
-
-
- - - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - diff --git a/docs/jsapi/network.js.html b/docs/jsapi/network.js.html deleted file mode 100644 index 19b6166bc8..0000000000 --- a/docs/jsapi/network.js.html +++ /dev/null @@ -1,7618 +0,0 @@ - - - - - Source: network.js - - - - - - - - - - - - - - - - - -
- - -
-

Source: network.js

- - - - -
-
-
'use strict';
-'require uci';
-'require rpc';
-'require validation';
-'require baseclass';
-'require firewall';
-
-var proto_errors = {
-	CONNECT_FAILED:			_('Connection attempt failed'),
-	INVALID_ADDRESS:		_('IP address is invalid'),
-	INVALID_GATEWAY:		_('Gateway address is invalid'),
-	INVALID_LOCAL_ADDRESS:	_('Local IP address is invalid'),
-	MISSING_ADDRESS:		_('IP address is missing'),
-	MISSING_PEER_ADDRESS:	_('Peer address is missing'),
-	NO_DEVICE:				_('Network device is not present'),
-	NO_IFACE:				_('Unable to determine device name'),
-	NO_IFNAME:				_('Unable to determine device name'),
-	NO_WAN_ADDRESS:			_('Unable to determine external IP address'),
-	NO_WAN_LINK:			_('Unable to determine upstream interface'),
-	PEER_RESOLVE_FAIL:		_('Unable to resolve peer host name'),
-	PIN_FAILED:				_('PIN code rejected')
-};
-
-var iface_patterns_ignore = [
-	/^wmaster\d+/,
-	/^wifi\d+/,
-	/^hwsim\d+/,
-	/^imq\d+/,
-	/^ifb\d+/,
-	/^mon\.wlan\d+/,
-	/^sit\d+/,
-	/^gre\d+/,
-	/^gretap\d+/,
-	/^ip6gre\d+/,
-	/^ip6tnl\d+/,
-	/^tunl\d+/,
-	/^lo$/
-];
-
-var iface_patterns_wireless = [
-	/^wlan\d+/,
-	/^wl\d+/,
-	/^ath\d+/,
-	/^\w+\.network\d+/
-];
-
-var iface_patterns_virtual = [ ];
-
-var callLuciNetworkDevices = rpc.declare({
-	object: 'luci-rpc',
-	method: 'getNetworkDevices',
-	expect: { '': {} }
-});
-
-var callLuciWirelessDevices = rpc.declare({
-	object: 'luci-rpc',
-	method: 'getWirelessDevices',
-	expect: { '': {} }
-});
-
-var callLuciBoardJSON = rpc.declare({
-	object: 'luci-rpc',
-	method: 'getBoardJSON'
-});
-
-var callLuciHostHints = rpc.declare({
-	object: 'luci-rpc',
-	method: 'getHostHints',
-	expect: { '': {} }
-});
-
-var callIwinfoAssoclist = rpc.declare({
-	object: 'iwinfo',
-	method: 'assoclist',
-	params: [ 'device', 'mac' ],
-	expect: { results: [] }
-});
-
-var callIwinfoScan = rpc.declare({
-	object: 'iwinfo',
-	method: 'scan',
-	params: [ 'device' ],
-	nobatch: true,
-	expect: { results: [] }
-});
-
-var callNetworkInterfaceDump = rpc.declare({
-	object: 'network.interface',
-	method: 'dump',
-	expect: { 'interface': [] }
-});
-
-var callNetworkProtoHandlers = rpc.declare({
-	object: 'network',
-	method: 'get_proto_handlers',
-	expect: { '': {} }
-});
-
-var _init = null,
-    _state = null,
-    _protocols = {},
-    _protospecs = {};
-
-function getProtocolHandlers(cache) {
-	return callNetworkProtoHandlers().then(function(protos) {
-		/* Register "none" protocol */
-		if (!protos.hasOwnProperty('none'))
-			Object.assign(protos, { none: { no_device: false } });
-
-		/* Hack: emulate relayd protocol */
-		if (!protos.hasOwnProperty('relay') && L.hasSystemFeature('relayd'))
-			Object.assign(protos, { relay: { no_device: true } });
-
-		Object.assign(_protospecs, protos);
-
-		return Promise.all(Object.keys(protos).map(function(p) {
-			return Promise.resolve(L.require('protocol.%s'.format(p))).catch(function(err) {
-				if (L.isObject(err) && err.name != 'NetworkError')
-					L.error(err);
-			});
-		})).then(function() {
-			return protos;
-		});
-	}).catch(function() {
-		return {};
-	});
-}
-
-function getWifiStateBySid(sid) {
-	var s = uci.get('wireless', sid);
-
-	if (s != null && s['.type'] == 'wifi-iface') {
-		for (var radioname in _state.radios) {
-			for (var i = 0; i < _state.radios[radioname].interfaces.length; i++) {
-				var netstate = _state.radios[radioname].interfaces[i];
-
-				if (typeof(netstate.section) != 'string')
-					continue;
-
-				var s2 = uci.get('wireless', netstate.section);
-
-				if (s2 != null && s['.type'] == s2['.type'] && s['.name'] == s2['.name']) {
-					if (s2['.anonymous'] == false && netstate.section.charAt(0) == '@')
-						return null;
-
-					return [ radioname, _state.radios[radioname], netstate ];
-				}
-			}
-		}
-	}
-
-	return null;
-}
-
-function getWifiStateByIfname(ifname) {
-	for (var radioname in _state.radios) {
-		for (var i = 0; i < _state.radios[radioname].interfaces.length; i++) {
-			var netstate = _state.radios[radioname].interfaces[i];
-
-			if (typeof(netstate.ifname) != 'string')
-				continue;
-
-			if (netstate.ifname == ifname)
-				return [ radioname, _state.radios[radioname], netstate ];
-		}
-	}
-
-	return null;
-}
-
-function isWifiIfname(ifname) {
-	for (var i = 0; i < iface_patterns_wireless.length; i++)
-		if (iface_patterns_wireless[i].test(ifname))
-			return true;
-
-	return false;
-}
-
-function getWifiSidByNetid(netid) {
-	var m = /^(\w+)\.network(\d+)$/.exec(netid);
-	if (m) {
-		var sections = uci.sections('wireless', 'wifi-iface');
-		for (var i = 0, n = 0; i < sections.length; i++) {
-			if (sections[i].device != m[1])
-				continue;
-
-			if (++n == +m[2])
-				return sections[i]['.name'];
-		}
-	}
-
-	return null;
-}
-
-function getWifiSidByIfname(ifname) {
-	var sid = getWifiSidByNetid(ifname);
-
-	if (sid != null)
-		return sid;
-
-	var res = getWifiStateByIfname(ifname);
-
-	if (res != null && L.isObject(res[2]) && typeof(res[2].section) == 'string')
-		return res[2].section;
-
-	return null;
-}
-
-function getWifiNetidBySid(sid) {
-	var s = uci.get('wireless', sid);
-	if (s != null && s['.type'] == 'wifi-iface') {
-		var radioname = s.device;
-		if (typeof(s.device) == 'string') {
-			var i = 0, netid = null, sections = uci.sections('wireless', 'wifi-iface');
-			for (var i = 0, n = 0; i < sections.length; i++) {
-				if (sections[i].device != s.device)
-					continue;
-
-				n++;
-
-				if (sections[i]['.name'] != s['.name'])
-					continue;
-
-				return [ '%s.network%d'.format(s.device, n), s.device ];
-			}
-
-		}
-	}
-
-	return null;
-}
-
-function getWifiNetidByNetname(name) {
-	var sections = uci.sections('wireless', 'wifi-iface');
-	for (var i = 0; i < sections.length; i++) {
-		if (typeof(sections[i].network) != 'string')
-			continue;
-
-		var nets = sections[i].network.split(/\s+/);
-		for (var j = 0; j < nets.length; j++) {
-			if (nets[j] != name)
-				continue;
-
-			return getWifiNetidBySid(sections[i]['.name']);
-		}
-	}
-
-	return null;
-}
-
-function isVirtualIfname(ifname) {
-	for (var i = 0; i < iface_patterns_virtual.length; i++)
-		if (iface_patterns_virtual[i].test(ifname))
-			return true;
-
-	return false;
-}
-
-function isIgnoredIfname(ifname) {
-	for (var i = 0; i < iface_patterns_ignore.length; i++)
-		if (iface_patterns_ignore[i].test(ifname))
-			return true;
-
-	return false;
-}
-
-function appendValue(config, section, option, value) {
-	var values = uci.get(config, section, option),
-	    isArray = Array.isArray(values),
-	    rv = false;
-
-	if (isArray == false)
-		values = L.toArray(values);
-
-	if (values.indexOf(value) == -1) {
-		values.push(value);
-		rv = true;
-	}
-
-	uci.set(config, section, option, isArray ? values : values.join(' '));
-
-	return rv;
-}
-
-function removeValue(config, section, option, value) {
-	var values = uci.get(config, section, option),
-	    isArray = Array.isArray(values),
-	    rv = false;
-
-	if (isArray == false)
-		values = L.toArray(values);
-
-	for (var i = values.length - 1; i >= 0; i--) {
-		if (values[i] == value) {
-			values.splice(i, 1);
-			rv = true;
-		}
-	}
-
-	if (values.length > 0)
-		uci.set(config, section, option, isArray ? values : values.join(' '));
-	else
-		uci.unset(config, section, option);
-
-	return rv;
-}
-
-function prefixToMask(bits, v6) {
-	var w = v6 ? 128 : 32,
-	    m = [];
-
-	if (bits > w)
-		return null;
-
-	for (var i = 0; i < w / 16; i++) {
-		var b = Math.min(16, bits);
-		m.push((0xffff << (16 - b)) & 0xffff);
-		bits -= b;
-	}
-
-	if (v6)
-		return String.prototype.format.apply('%x:%x:%x:%x:%x:%x:%x:%x', m).replace(/:0(?::0)+$/, '::');
-	else
-		return '%d.%d.%d.%d'.format(m[0] >>> 8, m[0] & 0xff, m[1] >>> 8, m[1] & 0xff);
-}
-
-function maskToPrefix(mask, v6) {
-	var m = v6 ? validation.parseIPv6(mask) : validation.parseIPv4(mask);
-
-	if (!m)
-		return null;
-
-	var bits = 0;
-
-	for (var i = 0, z = false; i < m.length; i++) {
-		z = z || !m[i];
-
-		while (!z && (m[i] & (v6 ? 0x8000 : 0x80))) {
-			m[i] = (m[i] << 1) & (v6 ? 0xffff : 0xff);
-			bits++;
-		}
-
-		if (m[i])
-			return null;
-	}
-
-	return bits;
-}
-
-function initNetworkState(refresh) {
-	if (_state == null || refresh) {
-		_init = _init || Promise.all([
-			L.resolveDefault(callNetworkInterfaceDump(), []),
-			L.resolveDefault(callLuciBoardJSON(), {}),
-			L.resolveDefault(callLuciNetworkDevices(), {}),
-			L.resolveDefault(callLuciWirelessDevices(), {}),
-			L.resolveDefault(callLuciHostHints(), {}),
-			getProtocolHandlers(),
-			L.resolveDefault(uci.load('network')),
-			L.resolveDefault(uci.load('wireless')),
-			L.resolveDefault(uci.load('luci'))
-		]).then(function(data) {
-			var netifd_ifaces = data[0],
-			    board_json    = data[1],
-			    luci_devs     = data[2];
-
-			var s = {
-				isTunnel: {}, isBridge: {}, isSwitch: {}, isWifi: {},
-				ifaces: netifd_ifaces, radios: data[3], hosts: data[4],
-				netdevs: {}, bridges: {}, switches: {}, hostapd: {}
-			};
-
-			for (var name in luci_devs) {
-				var dev = luci_devs[name];
-
-				if (isVirtualIfname(name))
-					s.isTunnel[name] = true;
-
-				if (!s.isTunnel[name] && isIgnoredIfname(name))
-					continue;
-
-				s.netdevs[name] = s.netdevs[name] || {
-					idx:      dev.ifindex,
-					name:     name,
-					rawname:  name,
-					flags:    dev.flags,
-					stats:    dev.stats,
-					macaddr:  dev.mac,
-					type:     dev.type,
-					mtu:      dev.mtu,
-					qlen:     dev.qlen,
-					wireless: dev.wireless,
-					ipaddrs:  [],
-					ip6addrs: []
-				};
-
-				if (Array.isArray(dev.ipaddrs))
-					for (var i = 0; i < dev.ipaddrs.length; i++)
-						s.netdevs[name].ipaddrs.push(dev.ipaddrs[i].address + '/' + dev.ipaddrs[i].netmask);
-
-				if (Array.isArray(dev.ip6addrs))
-					for (var i = 0; i < dev.ip6addrs.length; i++)
-						s.netdevs[name].ip6addrs.push(dev.ip6addrs[i].address + '/' + dev.ip6addrs[i].netmask);
-			}
-
-			for (var name in luci_devs) {
-				var dev = luci_devs[name];
-
-				if (!dev.bridge)
-					continue;
-
-				var b = {
-					name:    name,
-					id:      dev.id,
-					stp:     dev.stp,
-					ifnames: []
-				};
-
-				for (var i = 0; dev.ports && i < dev.ports.length; i++) {
-					var subdev = s.netdevs[dev.ports[i]];
-
-					if (subdev == null)
-						continue;
-
-					b.ifnames.push(subdev);
-					subdev.bridge = b;
-				}
-
-				s.bridges[name] = b;
-				s.isBridge[name] = true;
-			}
-
-			if (L.isObject(board_json.switch)) {
-				for (var switchname in board_json.switch) {
-					var layout = board_json.switch[switchname],
-					    netdevs = {},
-					    nports = {},
-					    ports = [],
-					    pnum = null,
-					    role = null;
-
-					if (L.isObject(layout) && Array.isArray(layout.ports)) {
-						for (var i = 0, port; (port = layout.ports[i]) != null; i++) {
-							if (typeof(port) == 'object' && typeof(port.num) == 'number' &&
-								(typeof(port.role) == 'string' || typeof(port.device) == 'string')) {
-								var spec = {
-									num:   port.num,
-									role:  port.role || 'cpu',
-									index: (port.index != null) ? port.index : port.num
-								};
-
-								if (port.device != null) {
-									spec.device = port.device;
-									spec.tagged = spec.need_tag;
-									netdevs[port.num] = port.device;
-								}
-
-								ports.push(spec);
-
-								if (port.role != null)
-									nports[port.role] = (nports[port.role] || 0) + 1;
-							}
-						}
-
-						ports.sort(function(a, b) {
-							if (a.role != b.role)
-								return (a.role < b.role) ? -1 : 1;
-
-							return (a.index - b.index);
-						});
-
-						for (var i = 0, port; (port = ports[i]) != null; i++) {
-							if (port.role != role) {
-								role = port.role;
-								pnum = 1;
-							}
-
-							if (role == 'cpu')
-								port.label = 'CPU (%s)'.format(port.device);
-							else if (nports[role] > 1)
-								port.label = '%s %d'.format(role.toUpperCase(), pnum++);
-							else
-								port.label = role.toUpperCase();
-
-							delete port.role;
-							delete port.index;
-						}
-
-						s.switches[switchname] = {
-							ports: ports,
-							netdevs: netdevs
-						};
-					}
-				}
-			}
-
-			if (L.isObject(board_json.dsl) && L.isObject(board_json.dsl.modem)) {
-				s.hasDSLModem = board_json.dsl.modem;
-			}
-
-			_init = null;
-
-			var objects = [];
-
-			if (L.isObject(s.radios))
-				for (var radio in s.radios)
-					if (L.isObject(s.radios[radio]) && Array.isArray(s.radios[radio].interfaces))
-						for (var i = 0; i < s.radios[radio].interfaces.length; i++)
-							if (L.isObject(s.radios[radio].interfaces[i]) && s.radios[radio].interfaces[i].ifname)
-								objects.push('hostapd.%s'.format(s.radios[radio].interfaces[i].ifname));
-
-			return (objects.length ? L.resolveDefault(rpc.list.apply(rpc, objects), {}) : Promise.resolve({})).then(function(res) {
-				for (var k in res) {
-					var m = k.match(/^hostapd\.(.+)$/);
-					if (m)
-						s.hostapd[m[1]] = res[k];
-				}
-
-				return (_state = s);
-			});
-		});
-	}
-
-	return (_state != null ? Promise.resolve(_state) : _init);
-}
-
-function ifnameOf(obj) {
-	if (obj instanceof Protocol)
-		return obj.getIfname();
-	else if (obj instanceof Device)
-		return obj.getName();
-	else if (obj instanceof WifiDevice)
-		return obj.getName();
-	else if (obj instanceof WifiNetwork)
-		return obj.getIfname();
-	else if (typeof(obj) == 'string')
-		return obj.replace(/:.+$/, '');
-
-	return null;
-}
-
-function networkSort(a, b) {
-	return a.getName() > b.getName();
-}
-
-function deviceSort(a, b) {
-	var typeWeigth = { wifi: 2, alias: 3 },
-        weightA = typeWeigth[a.getType()] || 1,
-        weightB = typeWeigth[b.getType()] || 1;
-
-    if (weightA != weightB)
-    	return weightA - weightB;
-
-	return a.getName() > b.getName();
-}
-
-function formatWifiEncryption(enc) {
-	if (!L.isObject(enc))
-		return null;
-
-	if (!enc.enabled)
-		return 'None';
-
-	var ciphers = Array.isArray(enc.ciphers)
-		? enc.ciphers.map(function(c) { return c.toUpperCase() }) : [ 'NONE' ];
-
-	if (Array.isArray(enc.wep)) {
-		var has_open = false,
-		    has_shared = false;
-
-		for (var i = 0; i < enc.wep.length; i++)
-			if (enc.wep[i] == 'open')
-				has_open = true;
-			else if (enc.wep[i] == 'shared')
-				has_shared = true;
-
-		if (has_open && has_shared)
-			return 'WEP Open/Shared (%s)'.format(ciphers.join(', '));
-		else if (has_open)
-			return 'WEP Open System (%s)'.format(ciphers.join(', '));
-		else if (has_shared)
-			return 'WEP Shared Auth (%s)'.format(ciphers.join(', '));
-
-		return 'WEP';
-	}
-
-	if (Array.isArray(enc.wpa)) {
-		var versions = [],
-		    suites = Array.isArray(enc.authentication)
-			? enc.authentication.map(function(a) { return a.toUpperCase() }) : [ 'NONE' ];
-
-		for (var i = 0; i < enc.wpa.length; i++)
-			switch (enc.wpa[i]) {
-			case 1:
-				versions.push('WPA');
-				break;
-
-			default:
-				versions.push('WPA%d'.format(enc.wpa[i]));
-				break;
-			}
-
-		if (versions.length > 1)
-			return 'mixed %s %s (%s)'.format(versions.join('/'), suites.join(', '), ciphers.join(', '));
-
-		return '%s %s (%s)'.format(versions[0], suites.join(', '), ciphers.join(', '));
-	}
-
-	return 'Unknown';
-}
-
-function enumerateNetworks() {
-	var uciInterfaces = uci.sections('network', 'interface'),
-	    networks = {};
-
-	for (var i = 0; i < uciInterfaces.length; i++)
-		networks[uciInterfaces[i]['.name']] = this.instantiateNetwork(uciInterfaces[i]['.name']);
-
-	for (var i = 0; i < _state.ifaces.length; i++)
-		if (networks[_state.ifaces[i].interface] == null)
-			networks[_state.ifaces[i].interface] =
-				this.instantiateNetwork(_state.ifaces[i].interface, _state.ifaces[i].proto);
-
-	var rv = [];
-
-	for (var network in networks)
-		if (networks.hasOwnProperty(network))
-			rv.push(networks[network]);
-
-	rv.sort(networkSort);
-
-	return rv;
-}
-
-
-var Hosts, Network, Protocol, Device, WifiDevice, WifiNetwork;
-
-/**
- * @class network
- * @memberof LuCI
- * @hideconstructor
- * @classdesc
- *
- * The `LuCI.network` class combines data from multiple `ubus` apis to
- * provide an abstraction of the current network configuration state.
- *
- * It provides methods to enumerate interfaces and devices, to query
- * current configuration details and to manipulate settings.
- */
-Network = baseclass.extend(/** @lends LuCI.network.prototype */ {
-	/**
-	 * Converts the given prefix size in bits to a netmask.
-	 *
-	 * @method
-	 *
-	 * @param {number} bits
-	 * The prefix size in bits.
-	 *
-	 * @param {boolean} [v6=false]
-	 * Whether to convert the bits value into an IPv4 netmask (`false`) or
-	 * an IPv6 netmask (`true`).
-	 *
-	 * @returns {null|string}
-	 * Returns a string containing the netmask corresponding to the bit count
-	 * or `null` when the given amount of bits exceeds the maximum possible
-	 * value of `32` for IPv4 or `128` for IPv6.
-	 */
-	prefixToMask: prefixToMask,
-
-	/**
-	 * Converts the given netmask to a prefix size in bits.
-	 *
-	 * @method
-	 *
-	 * @param {string} netmask
-	 * The netmask to convert into a bit count.
-	 *
-	 * @param {boolean} [v6=false]
-	 * Whether to parse the given netmask as IPv4 (`false`) or IPv6 (`true`)
-	 * address.
-	 *
-	 * @returns {null|number}
-	 * Returns the number of prefix bits contained in the netmask or `null`
-	 * if the given netmask value was invalid.
-	 */
-	maskToPrefix: maskToPrefix,
-
-	/**
-	 * An encryption entry describes active wireless encryption settings
-	 * such as the used key management protocols, active ciphers and
-	 * protocol versions.
-	 *
-	 * @typedef {Object<string, boolean|Array<number|string>>} LuCI.network.WifiEncryption
-	 * @memberof LuCI.network
-	 *
-	 * @property {boolean} enabled
-	 * Specifies whether any kind of encryption, such as `WEP` or `WPA` is
-	 * enabled. If set to `false`, then no encryption is active and the
-	 * corresponding network is open.
-	 *
-	 * @property {string[]} [wep]
-	 * When the `wep` property exists, the network uses WEP encryption.
-	 * In this case, the property is set to an array of active WEP modes
-	 * which might be either `open`, `shared` or both.
-	 *
-	 * @property {number[]} [wpa]
-	 * When the `wpa` property exists, the network uses WPA security.
-	 * In this case, the property is set to an array containing the WPA
-	 * protocol versions used, e.g. `[ 1, 2 ]` for WPA/WPA2 mixed mode or
-	 * `[ 3 ]` for WPA3-SAE.
-	 *
-	 * @property {string[]} [authentication]
-	 * The `authentication` property only applies to WPA encryption and
-	 * is defined when the `wpa` property is set as well. It points to
-	 * an array of active authentication suites used by the network, e.g.
-	 * `[ "psk" ]` for a WPA(2)-PSK network or `[ "psk", "sae" ]` for
-	 * mixed WPA2-PSK/WPA3-SAE encryption.
-	 *
-	 * @property {string[]} [ciphers]
-	 * If either WEP or WPA encryption is active, then the `ciphers`
-	 * property will be set to an array describing the active encryption
-	 * ciphers used by the network, e.g. `[ "tkip", "ccmp" ]` for a
-	 * WPA/WPA2-PSK mixed network or `[ "wep-40", "wep-104" ]` for an
-	 * WEP network.
-	 */
-
-	/**
-	 * Converts a given {@link LuCI.network.WifiEncryption encryption entry}
-	 * into a human readable string such as `mixed WPA/WPA2 PSK (TKIP, CCMP)`
-	 * or `WPA3 SAE (CCMP)`.
-	 *
-	 * @method
-	 *
-	 * @param {LuCI.network.WifiEncryption} encryption
-	 * The wireless encryption entry to convert.
-	 *
-	 * @returns {null|string}
-	 * Returns the description string for the given encryption entry or
-	 * `null` if the given entry was invalid.
-	 */
-	formatWifiEncryption: formatWifiEncryption,
-
-	/**
-	 * Flushes the local network state cache and fetches updated information
-	 * from the remote `ubus` apis.
-	 *
-	 * @returns {Promise<Object>}
-	 * Returns a promise resolving to the internal network state object.
-	 */
-	flushCache: function() {
-		initNetworkState(true);
-		return _init;
-	},
-
-	/**
-	 * Instantiates the given {@link LuCI.network.Protocol Protocol} backend,
-	 * optionally using the given network name.
-	 *
-	 * @param {string} protoname
-	 * The protocol backend to use, e.g. `static` or `dhcp`.
-	 *
-	 * @param {string} [netname=__dummy__]
-	 * The network name to use for the instantiated protocol. This should be
-	 * usually set to one of the interfaces described in /etc/config/network
-	 * but it is allowed to omit it, e.g. to query protocol capabilities
-	 * without the need for an existing interface.
-	 *
-	 * @returns {null|LuCI.network.Protocol}
-	 * Returns the instantiated protocol backend class or `null` if the given
-	 * protocol isn't known.
-	 */
-	getProtocol: function(protoname, netname) {
-		var v = _protocols[protoname];
-		if (v != null)
-			return new v(netname || '__dummy__');
-
-		return null;
-	},
-
-	/**
-	 * Obtains instances of all known {@link LuCI.network.Protocol Protocol}
-	 * backend classes.
-	 *
-	 * @returns {Array<LuCI.network.Protocol>}
-	 * Returns an array of protocol class instances.
-	 */
-	getProtocols: function() {
-		var rv = [];
-
-		for (var protoname in _protocols)
-			rv.push(new _protocols[protoname]('__dummy__'));
-
-		return rv;
-	},
-
-	/**
-	 * Registers a new {@link LuCI.network.Protocol Protocol} subclass
-	 * with the given methods and returns the resulting subclass value.
-	 *
-	 * This functions internally calls
-	 * {@link LuCI.Class.extend Class.extend()} on the `Network.Protocol`
-	 * base class.
-	 *
-	 * @param {string} protoname
-	 * The name of the new protocol to register.
-	 *
-	 * @param {Object<string, *>} methods
-	 * The member methods and values of the new `Protocol` subclass to
-	 * be passed to {@link LuCI.Class.extend Class.extend()}.
-	 *
-	 * @returns {LuCI.network.Protocol}
-	 * Returns the new `Protocol` subclass.
-	 */
-	registerProtocol: function(protoname, methods) {
-		var spec = L.isObject(_protospecs) ? _protospecs[protoname] : null;
-		var proto = Protocol.extend(Object.assign({
-			getI18n: function() {
-				return protoname;
-			},
-
-			isFloating: function() {
-				return false;
-			},
-
-			isVirtual: function() {
-				return (L.isObject(spec) && spec.no_device == true);
-			},
-
-			renderFormOptions: function(section) {
-
-			}
-		}, methods, {
-			__init__: function(name) {
-				this.sid = name;
-			},
-
-			getProtocol: function() {
-				return protoname;
-			}
-		}));
-
-		_protocols[protoname] = proto;
-
-		return proto;
-	},
-
-	/**
-	 * Registers a new regular expression pattern to recognize
-	 * virtual interfaces.
-	 *
-	 * @param {RegExp} pat
-	 * A `RegExp` instance to match a virtual interface name
-	 * such as `6in4-wan` or `tun0`.
-	 */
-	registerPatternVirtual: function(pat) {
-		iface_patterns_virtual.push(pat);
-	},
-
-	/**
-	 * Registers a new human readable translation string for a `Protocol`
-	 * error code.
-	 *
-	 * @param {string} code
-	 * The `ubus` protocol error code to register a translation for, e.g.
-	 * `NO_DEVICE`.
-	 *
-	 * @param {string} message
-	 * The message to use as translation for the given protocol error code.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` if the error code description has been added or `false`
-	 * if either the arguments were invalid or if there already was a
-	 * description for the given code.
-	 */
-	registerErrorCode: function(code, message) {
-		if (typeof(code) == 'string' &&
-		    typeof(message) == 'string' &&
-		    !proto_errors.hasOwnProperty(code)) {
-			proto_errors[code] = message;
-			return true;
-		}
-
-		return false;
-	},
-
-	/**
-	 * Adds a new network of the given name and update it with the given
-	 * uci option values.
-	 *
-	 * If a network with the given name already exist but is empty, then
-	 * this function will update its option, otherwise it will do nothing.
-	 *
-	 * @param {string} name
-	 * The name of the network to add. Must be in the format `[a-zA-Z0-9_]+`.
-	 *
-	 * @param {Object<string, string|string[]>} [options]
-	 * An object of uci option values to set on the new network or to
-	 * update in an existing, empty network.
-	 *
-	 * @returns {Promise<null|LuCI.network.Protocol>}
-	 * Returns a promise resolving to the `Protocol` subclass instance
-	 * describing the added network or resolving to `null` if the name
-	 * was invalid or if a non-empty network of the given name already
-	 * existed.
-	 */
-	addNetwork: function(name, options) {
-		return this.getNetwork(name).then(L.bind(function(existingNetwork) {
-			if (name != null && /^[a-zA-Z0-9_]+$/.test(name) && existingNetwork == null) {
-				var sid = uci.add('network', 'interface', name);
-
-				if (sid != null) {
-					if (L.isObject(options))
-						for (var key in options)
-							if (options.hasOwnProperty(key))
-								uci.set('network', sid, key, options[key]);
-
-					return this.instantiateNetwork(sid);
-				}
-			}
-			else if (existingNetwork != null && existingNetwork.isEmpty()) {
-				if (L.isObject(options))
-					for (var key in options)
-						if (options.hasOwnProperty(key))
-							existingNetwork.set(key, options[key]);
-
-				return existingNetwork;
-			}
-		}, this));
-	},
-
-	/**
-	 * Get a {@link LuCI.network.Protocol Protocol} instance describing
-	 * the network with the given name.
-	 *
-	 * @param {string} name
-	 * The logical interface name of the network get, e.g. `lan` or `wan`.
-	 *
-	 * @returns {Promise<null|LuCI.network.Protocol>}
-	 * Returns a promise resolving to a
-	 * {@link LuCI.network.Protocol Protocol} subclass instance describing
-	 * the network or `null` if the network did not exist.
-	 */
-	getNetwork: function(name) {
-		return initNetworkState().then(L.bind(function() {
-			var section = (name != null) ? uci.get('network', name) : null;
-
-			if (section != null && section['.type'] == 'interface') {
-				return this.instantiateNetwork(name);
-			}
-			else if (name != null) {
-				for (var i = 0; i < _state.ifaces.length; i++)
-					if (_state.ifaces[i].interface == name)
-						return this.instantiateNetwork(name, _state.ifaces[i].proto);
-			}
-
-			return null;
-		}, this));
-	},
-
-	/**
-	 * Gets an array containing all known networks.
-	 *
-	 * @returns {Promise<Array<LuCI.network.Protocol>>}
-	 * Returns a promise resolving to a name-sorted array of
-	 * {@link LuCI.network.Protocol Protocol} subclass instances
-	 * describing all known networks.
-	 */
-	getNetworks: function() {
-		return initNetworkState().then(L.bind(enumerateNetworks, this));
-	},
-
-	/**
-	 * Deletes the given network and its references from the network and
-	 * firewall configuration.
-	 *
-	 * @param {string} name
-	 * The name of the network to delete.
-	 *
-	 * @returns {Promise<boolean>}
-	 * Returns a promise resolving to either `true` if the network and
-	 * references to it were successfully deleted from the configuration or
-	 * `false` if the given network could not be found.
-	 */
-	deleteNetwork: function(name) {
-		var requireFirewall = Promise.resolve(L.require('firewall')).catch(function() {}),
-		    network = this.instantiateNetwork(name);
-
-		return Promise.all([ requireFirewall, initNetworkState() ]).then(function(res) {
-			var uciInterface = uci.get('network', name),
-			    firewall = res[0];
-
-			if (uciInterface != null && uciInterface['.type'] == 'interface') {
-				return Promise.resolve(network ? network.deleteConfiguration() : null).then(function() {
-					uci.remove('network', name);
-
-					uci.sections('luci', 'ifstate', function(s) {
-						if (s.interface == name)
-							uci.remove('luci', s['.name']);
-					});
-
-					uci.sections('network', 'alias', function(s) {
-						if (s.interface == name)
-							uci.remove('network', s['.name']);
-					});
-
-					uci.sections('network', 'route', function(s) {
-						if (s.interface == name)
-							uci.remove('network', s['.name']);
-					});
-
-					uci.sections('network', 'route6', function(s) {
-						if (s.interface == name)
-							uci.remove('network', s['.name']);
-					});
-
-					uci.sections('wireless', 'wifi-iface', function(s) {
-						var networks = L.toArray(s.network).filter(function(network) { return network != name });
-
-						if (networks.length > 0)
-							uci.set('wireless', s['.name'], 'network', networks.join(' '));
-						else
-							uci.unset('wireless', s['.name'], 'network');
-					});
-
-					if (firewall)
-						return firewall.deleteNetwork(name).then(function() { return true });
-
-					return true;
-				}).catch(function() {
-					return false;
-				});
-			}
-
-			return false;
-		});
-	},
-
-	/**
-	 * Rename the given network and its references to a new name.
-	 *
-	 * @param {string} oldName
-	 * The current name of the network.
-	 *
-	 * @param {string} newName
-	 * The name to rename the network to, must be in the format
-	 * `[a-z-A-Z0-9_]+`.
-	 *
-	 * @returns {Promise<boolean>}
-	 * Returns a promise resolving to either `true` if the network was
-	 * successfully renamed or `false` if the new name was invalid, if
-	 * a network with the new name already exists or if the network to
-	 * rename could not be found.
-	 */
-	renameNetwork: function(oldName, newName) {
-		return initNetworkState().then(function() {
-			if (newName == null || !/^[a-zA-Z0-9_]+$/.test(newName) || uci.get('network', newName) != null)
-				return false;
-
-			var oldNetwork = uci.get('network', oldName);
-
-			if (oldNetwork == null || oldNetwork['.type'] != 'interface')
-				return false;
-
-			var sid = uci.add('network', 'interface', newName);
-
-			for (var key in oldNetwork)
-				if (oldNetwork.hasOwnProperty(key) && key.charAt(0) != '.')
-					uci.set('network', sid, key, oldNetwork[key]);
-
-			uci.sections('luci', 'ifstate', function(s) {
-				if (s.interface == oldName)
-					uci.set('luci', s['.name'], 'interface', newName);
-			});
-
-			uci.sections('network', 'alias', function(s) {
-				if (s.interface == oldName)
-					uci.set('network', s['.name'], 'interface', newName);
-			});
-
-			uci.sections('network', 'route', function(s) {
-				if (s.interface == oldName)
-					uci.set('network', s['.name'], 'interface', newName);
-			});
-
-			uci.sections('network', 'route6', function(s) {
-				if (s.interface == oldName)
-					uci.set('network', s['.name'], 'interface', newName);
-			});
-
-			uci.sections('wireless', 'wifi-iface', function(s) {
-				var networks = L.toArray(s.network).map(function(network) { return (network == oldName ? newName : network) });
-
-				if (networks.length > 0)
-					uci.set('wireless', s['.name'], 'network', networks.join(' '));
-			});
-
-			uci.remove('network', oldName);
-
-			return true;
-		});
-	},
-
-	/**
-	 * Get a {@link LuCI.network.Device Device} instance describing the
-	 * given network device.
-	 *
-	 * @param {string} name
-	 * The name of the network device to get, e.g. `eth0` or `br-lan`.
-	 *
-	 * @returns {Promise<null|LuCI.network.Device>}
-	 * Returns a promise resolving to the `Device` instance describing
-	 * the network device or `null` if the given device name could not
-	 * be found.
-	 */
-	getDevice: function(name) {
-		return initNetworkState().then(L.bind(function() {
-			if (name == null)
-				return null;
-
-			if (_state.netdevs.hasOwnProperty(name) || isWifiIfname(name))
-				return this.instantiateDevice(name);
-
-			var netid = getWifiNetidBySid(name);
-			if (netid != null)
-				return this.instantiateDevice(netid[0]);
-
-			return null;
-		}, this));
-	},
-
-	/**
-	 * Get a sorted list of all found network devices.
-	 *
-	 * @returns {Promise<Array<LuCI.network.Device>>}
-	 * Returns a promise resolving to a sorted array of `Device` class
-	 * instances describing the network devices found on the system.
-	 */
-	getDevices: function() {
-		return initNetworkState().then(L.bind(function() {
-			var devices = {};
-
-			/* find simple devices */
-			var uciInterfaces = uci.sections('network', 'interface');
-			for (var i = 0; i < uciInterfaces.length; i++) {
-				var ifnames = L.toArray(uciInterfaces[i].ifname);
-
-				for (var j = 0; j < ifnames.length; j++) {
-					if (ifnames[j].charAt(0) == '@')
-						continue;
-
-					if (isIgnoredIfname(ifnames[j]) || isVirtualIfname(ifnames[j]) || isWifiIfname(ifnames[j]))
-						continue;
-
-					devices[ifnames[j]] = this.instantiateDevice(ifnames[j]);
-				}
-			}
-
-			for (var ifname in _state.netdevs) {
-				if (devices.hasOwnProperty(ifname))
-					continue;
-
-				if (isIgnoredIfname(ifname) || isWifiIfname(ifname))
-					continue;
-
-				if (_state.netdevs[ifname].wireless)
-					continue;
-
-				devices[ifname] = this.instantiateDevice(ifname);
-			}
-
-			/* find VLAN devices */
-			var uciSwitchVLANs = uci.sections('network', 'switch_vlan');
-			for (var i = 0; i < uciSwitchVLANs.length; i++) {
-				if (typeof(uciSwitchVLANs[i].ports) != 'string' ||
-				    typeof(uciSwitchVLANs[i].device) != 'string' ||
-				    !_state.switches.hasOwnProperty(uciSwitchVLANs[i].device))
-					continue;
-
-				var ports = uciSwitchVLANs[i].ports.split(/\s+/);
-				for (var j = 0; j < ports.length; j++) {
-					var m = ports[j].match(/^(\d+)([tu]?)$/);
-					if (m == null)
-						continue;
-
-					var netdev = _state.switches[uciSwitchVLANs[i].device].netdevs[m[1]];
-					if (netdev == null)
-						continue;
-
-					if (!devices.hasOwnProperty(netdev))
-						devices[netdev] = this.instantiateDevice(netdev);
-
-					_state.isSwitch[netdev] = true;
-
-					if (m[2] != 't')
-						continue;
-
-					var vid = uciSwitchVLANs[i].vid || uciSwitchVLANs[i].vlan;
-					    vid = (vid != null ? +vid : null);
-
-					if (vid == null || vid < 0 || vid > 4095)
-						continue;
-
-					var vlandev = '%s.%d'.format(netdev, vid);
-
-					if (!devices.hasOwnProperty(vlandev))
-						devices[vlandev] = this.instantiateDevice(vlandev);
-
-					_state.isSwitch[vlandev] = true;
-				}
-			}
-
-			/* find wireless interfaces */
-			var uciWifiIfaces = uci.sections('wireless', 'wifi-iface'),
-			    networkCount = {};
-
-			for (var i = 0; i < uciWifiIfaces.length; i++) {
-				if (typeof(uciWifiIfaces[i].device) != 'string')
-					continue;
-
-				networkCount[uciWifiIfaces[i].device] = (networkCount[uciWifiIfaces[i].device] || 0) + 1;
-
-				var netid = '%s.network%d'.format(uciWifiIfaces[i].device, networkCount[uciWifiIfaces[i].device]);
-
-				devices[netid] = this.instantiateDevice(netid);
-			}
-
-			/* find uci declared devices */
-			var uciDevices = uci.sections('network', 'device');
-
-			for (var i = 0; i < uciDevices.length; i++) {
-				var type = uciDevices[i].type,
-				    name = uciDevices[i].name;
-
-				if (!type || !name || devices.hasOwnProperty(name))
-					continue;
-
-				if (type == 'bridge')
-					_state.isBridge[name] = true;
-
-				devices[name] = this.instantiateDevice(name);
-			}
-
-			var rv = [];
-
-			for (var netdev in devices)
-				if (devices.hasOwnProperty(netdev))
-					rv.push(devices[netdev]);
-
-			rv.sort(deviceSort);
-
-			return rv;
-		}, this));
-	},
-
-	/**
-	 * Test if a given network device name is in the list of patterns for
-	 * device names to ignore.
-	 *
-	 * Ignored device names are usually Linux network devices which are
-	 * spawned implicitly by kernel modules such as `tunl0` or `hwsim0`
-	 * and which are unsuitable for use in network configuration.
-	 *
-	 * @param {string} name
-	 * The device name to test.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` if the given name is in the ignore pattern list,
-	 * else returns `false`.
-	 */
-	isIgnoredDevice: function(name) {
-		return isIgnoredIfname(name);
-	},
-
-	/**
-	 * Get a {@link LuCI.network.WifiDevice WifiDevice} instance describing
-	 * the given wireless radio.
-	 *
-	 * @param {string} devname
-	 * The configuration name of the wireless radio to lookup, e.g. `radio0`
-	 * for the first mac80211 phy on the system.
-	 *
-	 * @returns {Promise<null|LuCI.network.WifiDevice>}
-	 * Returns a promise resolving to the `WifiDevice` instance describing
-	 * the underlying radio device or `null` if the wireless radio could not
-	 * be found.
-	 */
-	getWifiDevice: function(devname) {
-		return initNetworkState().then(L.bind(function() {
-			var existingDevice = uci.get('wireless', devname);
-
-			if (existingDevice == null || existingDevice['.type'] != 'wifi-device')
-				return null;
-
-			return this.instantiateWifiDevice(devname, _state.radios[devname] || {});
-		}, this));
-	},
-
-	/**
-	 * Obtain a list of all configured radio devices.
-	 *
-	 * @returns {Promise<Array<LuCI.network.WifiDevice>>}
-	 * Returns a promise resolving to an array of `WifiDevice` instances
-	 * describing the wireless radios configured in the system.
-	 * The order of the array corresponds to the order of the radios in
-	 * the configuration.
-	 */
-	getWifiDevices: function() {
-		return initNetworkState().then(L.bind(function() {
-			var uciWifiDevices = uci.sections('wireless', 'wifi-device'),
-			    rv = [];
-
-			for (var i = 0; i < uciWifiDevices.length; i++) {
-				var devname = uciWifiDevices[i]['.name'];
-				rv.push(this.instantiateWifiDevice(devname, _state.radios[devname] || {}));
-			}
-
-			return rv;
-		}, this));
-	},
-
-	/**
-	 * Get a {@link LuCI.network.WifiNetwork WifiNetwork} instance describing
-	 * the given wireless network.
-	 *
-	 * @param {string} netname
-	 * The name of the wireless network to lookup. This may be either an uci
-	 * configuration section ID, a network ID in the form `radio#.network#`
-	 * or a Linux network device name like `wlan0` which is resolved to the
-	 * corresponding configuration section through `ubus` runtime information.
-	 *
-	 * @returns {Promise<null|LuCI.network.WifiNetwork>}
-	 * Returns a promise resolving to the `WifiNetwork` instance describing
-	 * the wireless network or `null` if the corresponding network could not
-	 * be found.
-	 */
-	getWifiNetwork: function(netname) {
-		return initNetworkState()
-			.then(L.bind(this.lookupWifiNetwork, this, netname));
-	},
-
-	/**
-	 * Get an array of all {@link LuCI.network.WifiNetwork WifiNetwork}
-	 * instances describing the wireless networks present on the system.
-	 *
-	 * @returns {Promise<Array<LuCI.network.WifiNetwork>>}
-	 * Returns a promise resolving to an array of `WifiNetwork` instances
-	 * describing the wireless networks. The array will be empty if no networks
-	 * are found.
-	 */
-	getWifiNetworks: function() {
-		return initNetworkState().then(L.bind(function() {
-			var wifiIfaces = uci.sections('wireless', 'wifi-iface'),
-			    rv = [];
-
-			for (var i = 0; i < wifiIfaces.length; i++)
-				rv.push(this.lookupWifiNetwork(wifiIfaces[i]['.name']));
-
-			rv.sort(function(a, b) {
-				return (a.getID() > b.getID());
-			});
-
-			return rv;
-		}, this));
-	},
-
-	/**
-	 * Adds a new wireless network to the configuration and sets its options
-	 * to the provided values.
-	 *
-	 * @param {Object<string, string|string[]>} options
-	 * The options to set for the newly added wireless network. This object
-	 * must at least contain a `device` property which is set to the radio
-	 * name the new network belongs to.
-	 *
-	 * @returns {Promise<null|LuCI.network.WifiNetwork>}
-	 * Returns a promise resolving to a `WifiNetwork` instance describing
-	 * the newly added wireless network or `null` if the given options
-	 * were invalid or if the associated radio device could not be found.
-	 */
-	addWifiNetwork: function(options) {
-		return initNetworkState().then(L.bind(function() {
-			if (options == null ||
-			    typeof(options) != 'object' ||
-			    typeof(options.device) != 'string')
-			    return null;
-
-			var existingDevice = uci.get('wireless', options.device);
-			if (existingDevice == null || existingDevice['.type'] != 'wifi-device')
-				return null;
-
-			/* XXX: need to add a named section (wifinet#) here */
-			var sid = uci.add('wireless', 'wifi-iface');
-			for (var key in options)
-				if (options.hasOwnProperty(key))
-					uci.set('wireless', sid, key, options[key]);
-
-			var radioname = existingDevice['.name'],
-			    netid = getWifiNetidBySid(sid) || [];
-
-			return this.instantiateWifiNetwork(sid, radioname, _state.radios[radioname], netid[0], null);
-		}, this));
-	},
-
-	/**
-	 * Deletes the given wireless network from the configuration.
-	 *
-	 * @param {string} netname
-	 * The name of the network to remove. This may be either a
-	 * network ID in the form `radio#.network#` or a Linux network device
-	 * name like `wlan0` which is resolved to the corresponding configuration
-	 * section through `ubus` runtime information.
-	 *
-	 * @returns {Promise<boolean>}
-	 * Returns a promise resolving to `true` if the wireless network has been
-	 * successfully deleted from the configuration or `false` if it could not
-	 * be found.
-	 */
-	deleteWifiNetwork: function(netname) {
-		return initNetworkState().then(L.bind(function() {
-			var sid = getWifiSidByIfname(netname);
-
-			if (sid == null)
-				return false;
-
-			uci.remove('wireless', sid);
-			return true;
-		}, this));
-	},
-
-	/* private */
-	getStatusByRoute: function(addr, mask) {
-		return initNetworkState().then(L.bind(function() {
-			var rv = [];
-
-			for (var i = 0; i < _state.ifaces.length; i++) {
-				if (!Array.isArray(_state.ifaces[i].route))
-					continue;
-
-				for (var j = 0; j < _state.ifaces[i].route.length; j++) {
-					if (typeof(_state.ifaces[i].route[j]) != 'object' ||
-					    typeof(_state.ifaces[i].route[j].target) != 'string' ||
-					    typeof(_state.ifaces[i].route[j].mask) != 'number')
-					    continue;
-
-					if (_state.ifaces[i].route[j].table)
-						continue;
-
-					if (_state.ifaces[i].route[j].target != addr ||
-					    _state.ifaces[i].route[j].mask != mask)
-					    continue;
-
-					rv.push(_state.ifaces[i]);
-				}
-			}
-
-			return rv;
-		}, this));
-	},
-
-	/* private */
-	getStatusByAddress: function(addr) {
-		return initNetworkState().then(L.bind(function() {
-			var rv = [];
-
-			for (var i = 0; i < _state.ifaces.length; i++) {
-				if (Array.isArray(_state.ifaces[i]['ipv4-address']))
-					for (var j = 0; j < _state.ifaces[i]['ipv4-address'].length; j++)
-						if (typeof(_state.ifaces[i]['ipv4-address'][j]) == 'object' &&
-						    _state.ifaces[i]['ipv4-address'][j].address == addr)
-							return _state.ifaces[i];
-
-				if (Array.isArray(_state.ifaces[i]['ipv6-address']))
-					for (var j = 0; j < _state.ifaces[i]['ipv6-address'].length; j++)
-						if (typeof(_state.ifaces[i]['ipv6-address'][j]) == 'object' &&
-						    _state.ifaces[i]['ipv6-address'][j].address == addr)
-							return _state.ifaces[i];
-
-				if (Array.isArray(_state.ifaces[i]['ipv6-prefix-assignment']))
-					for (var j = 0; j < _state.ifaces[i]['ipv6-prefix-assignment'].length; j++)
-						if (typeof(_state.ifaces[i]['ipv6-prefix-assignment'][j]) == 'object' &&
-							typeof(_state.ifaces[i]['ipv6-prefix-assignment'][j]['local-address']) == 'object' &&
-						    _state.ifaces[i]['ipv6-prefix-assignment'][j]['local-address'].address == addr)
-							return _state.ifaces[i];
-			}
-
-			return null;
-		}, this));
-	},
-
-	/**
-	 * Get IPv4 wan networks.
-	 *
-	 * This function looks up all networks having a default `0.0.0.0/0` route
-	 * and returns them as array.
-	 *
-	 * @returns {Promise<Array<LuCI.network.Protocol>>}
-	 * Returns a promise resolving to an array of `Protocol` subclass
-	 * instances describing the found default route interfaces.
-	 */
-	getWANNetworks: function() {
-		return this.getStatusByRoute('0.0.0.0', 0).then(L.bind(function(statuses) {
-			var rv = [], seen = {};
-
-			for (var i = 0; i < statuses.length; i++) {
-				if (!seen.hasOwnProperty(statuses[i].interface)) {
-					rv.push(this.instantiateNetwork(statuses[i].interface, statuses[i].proto));
-					seen[statuses[i].interface] = true;
-				}
-			}
-
-			return rv;
-		}, this));
-	},
-
-	/**
-	 * Get IPv6 wan networks.
-	 *
-	 * This function looks up all networks having a default `::/0` route
-	 * and returns them as array.
-	 *
-	 * @returns {Promise<Array<LuCI.network.Protocol>>}
-	 * Returns a promise resolving to an array of `Protocol` subclass
-	 * instances describing the found IPv6 default route interfaces.
-	 */
-	getWAN6Networks: function() {
-		return this.getStatusByRoute('::', 0).then(L.bind(function(statuses) {
-			var rv = [], seen = {};
-
-			for (var i = 0; i < statuses.length; i++) {
-				if (!seen.hasOwnProperty(statuses[i].interface)) {
-					rv.push(this.instantiateNetwork(statuses[i].interface, statuses[i].proto));
-					seen[statuses[i].interface] = true;
-				}
-			}
-
-			return rv;
-		}, this));
-	},
-
-	/**
-	 * Describes an swconfig switch topology by specifying the CPU
-	 * connections and external port labels of a switch.
-	 *
-	 * @typedef {Object<string, Object|Array>} SwitchTopology
-	 * @memberof LuCI.network
-	 *
-	 * @property {Object<number, string>} netdevs
-	 * The `netdevs` property points to an object describing the CPU port
-	 * connections of the switch. The numeric key of the enclosed object is
-	 * the port number, the value contains the Linux network device name the
-	 * port is hardwired to.
-	 *
-	 * @property {Array<Object<string, boolean|number|string>>} ports
-	 * The `ports` property points to an array describing the populated
-	 * ports of the switch in the external label order. Each array item is
-	 * an object containg the following keys:
-	 *  - `num` - the internal switch port number
-	 *  - `label` - the label of the port, e.g. `LAN 1` or `CPU (eth0)`
-	 *  - `device` - the connected Linux network device name (CPU ports only)
-	 *  - `tagged` - a boolean indicating whether the port must be tagged to
-	 *     function (CPU ports only)
-	 */
-
-	/**
-	 * Returns the topologies of all swconfig switches found on the system.
-	 *
-	 * @returns {Promise<Object<string, LuCI.network.SwitchTopology>>}
-	 * Returns a promise resolving to an object containing the topologies
-	 * of each switch. The object keys correspond to the name of the switches
-	 * such as `switch0`, the values are
-	 * {@link LuCI.network.SwitchTopology SwitchTopology} objects describing
-	 * the layout.
-	 */
-	getSwitchTopologies: function() {
-		return initNetworkState().then(function() {
-			return _state.switches;
-		});
-	},
-
-	/* private */
-	instantiateNetwork: function(name, proto) {
-		if (name == null)
-			return null;
-
-		proto = (proto == null ? uci.get('network', name, 'proto') : proto);
-
-		var protoClass = _protocols[proto] || Protocol;
-		return new protoClass(name);
-	},
-
-	/* private */
-	instantiateDevice: function(name, network, extend) {
-		if (extend != null)
-			return new (Device.extend(extend))(name, network);
-
-		return new Device(name, network);
-	},
-
-	/* private */
-	instantiateWifiDevice: function(radioname, radiostate) {
-		return new WifiDevice(radioname, radiostate);
-	},
-
-	/* private */
-	instantiateWifiNetwork: function(sid, radioname, radiostate, netid, netstate, hostapd) {
-		return new WifiNetwork(sid, radioname, radiostate, netid, netstate, hostapd);
-	},
-
-	/* private */
-	lookupWifiNetwork: function(netname) {
-		var sid, res, netid, radioname, radiostate, netstate;
-
-		sid = getWifiSidByNetid(netname);
-
-		if (sid != null) {
-			res        = getWifiStateBySid(sid);
-			netid      = netname;
-			radioname  = res ? res[0] : null;
-			radiostate = res ? res[1] : null;
-			netstate   = res ? res[2] : null;
-		}
-		else {
-			res = getWifiStateByIfname(netname);
-
-			if (res != null) {
-				radioname  = res[0];
-				radiostate = res[1];
-				netstate   = res[2];
-				sid        = netstate.section;
-				netid      = L.toArray(getWifiNetidBySid(sid))[0];
-			}
-			else {
-				res = getWifiStateBySid(netname);
-
-				if (res != null) {
-					radioname  = res[0];
-					radiostate = res[1];
-					netstate   = res[2];
-					sid        = netname;
-					netid      = L.toArray(getWifiNetidBySid(sid))[0];
-				}
-				else {
-					res = getWifiNetidBySid(netname);
-
-					if (res != null) {
-						netid     = res[0];
-						radioname = res[1];
-						sid       = netname;
-					}
-				}
-			}
-		}
-
-		return this.instantiateWifiNetwork(sid || netname, radioname,
-			radiostate, netid, netstate,
-			netstate ? _state.hostapd[netstate.ifname] : null);
-	},
-
-	/**
-	 * Obtains the the network device name of the given object.
-	 *
-	 * @param {LuCI.network.Protocol|LuCI.network.Device|LuCI.network.WifiDevice|LuCI.network.WifiNetwork|string} obj
-	 * The object to get the device name from.
-	 *
-	 * @returns {null|string}
-	 * Returns a string containing the device name or `null` if the given
-	 * object could not be converted to a name.
-	 */
-	getIfnameOf: function(obj) {
-		return ifnameOf(obj);
-	},
-
-	/**
-	 * Queries the internal DSL modem type from board information.
-	 *
-	 * @returns {Promise<null|string>}
-	 * Returns a promise resolving to the type of the internal modem
-	 * (e.g. `vdsl`) or to `null` if no internal modem is present.
-	 */
-	getDSLModemType: function() {
-		return initNetworkState().then(function() {
-			return _state.hasDSLModem ? _state.hasDSLModem.type : null;
-		});
-	},
-
-	/**
-	 * Queries aggregated information about known hosts.
-	 *
-	 * This function aggregates information from various sources such as
-	 * DHCP lease databases, ARP and IPv6 neighbour entries, wireless
-	 * association list etc. and returns a {@link LuCI.network.Hosts Hosts}
-	 * class instance describing the found hosts.
-	 *
-	 * @returns {Promise<LuCI.network.Hosts>}
-	 * Returns a `Hosts` instance describing host known on the system.
-	 */
-	getHostHints: function() {
-		return initNetworkState().then(function() {
-			return new Hosts(_state.hosts);
-		});
-	}
-});
-
-/**
- * @class
- * @memberof LuCI.network
- * @hideconstructor
- * @classdesc
- *
- * The `LuCI.network.Hosts` class encapsulates host information aggregated
- * from multiple sources and provides convenience functions to access the
- * host information by different criteria.
- */
-Hosts = baseclass.extend(/** @lends LuCI.network.Hosts.prototype */ {
-	__init__: function(hosts) {
-		this.hosts = hosts;
-	},
-
-	/**
-	 * Lookup the hostname associated with the given MAC address.
-	 *
-	 * @param {string} mac
-	 * The MAC address to lookup.
-	 *
-	 * @returns {null|string}
-	 * Returns the hostname associated with the given MAC or `null` if
-	 * no matching host could be found or if no hostname is known for
-	 * the corresponding host.
-	 */
-	getHostnameByMACAddr: function(mac) {
-		return this.hosts[mac] ? this.hosts[mac].name : null;
-	},
-
-	/**
-	 * Lookup the IPv4 address associated with the given MAC address.
-	 *
-	 * @param {string} mac
-	 * The MAC address to lookup.
-	 *
-	 * @returns {null|string}
-	 * Returns the IPv4 address associated with the given MAC or `null` if
-	 * no matching host could be found or if no IPv4 address is known for
-	 * the corresponding host.
-	 */
-	getIPAddrByMACAddr: function(mac) {
-		return this.hosts[mac] ? this.hosts[mac].ipv4 : null;
-	},
-
-	/**
-	 * Lookup the IPv6 address associated with the given MAC address.
-	 *
-	 * @param {string} mac
-	 * The MAC address to lookup.
-	 *
-	 * @returns {null|string}
-	 * Returns the IPv6 address associated with the given MAC or `null` if
-	 * no matching host could be found or if no IPv6 address is known for
-	 * the corresponding host.
-	 */
-	getIP6AddrByMACAddr: function(mac) {
-		return this.hosts[mac] ? this.hosts[mac].ipv6 : null;
-	},
-
-	/**
-	 * Lookup the hostname associated with the given IPv4 address.
-	 *
-	 * @param {string} ipaddr
-	 * The IPv4 address to lookup.
-	 *
-	 * @returns {null|string}
-	 * Returns the hostname associated with the given IPv4 or `null` if
-	 * no matching host could be found or if no hostname is known for
-	 * the corresponding host.
-	 */
-	getHostnameByIPAddr: function(ipaddr) {
-		for (var mac in this.hosts)
-			if (this.hosts[mac].ipv4 == ipaddr && this.hosts[mac].name != null)
-				return this.hosts[mac].name;
-		return null;
-	},
-
-	/**
-	 * Lookup the MAC address associated with the given IPv4 address.
-	 *
-	 * @param {string} ipaddr
-	 * The IPv4 address to lookup.
-	 *
-	 * @returns {null|string}
-	 * Returns the MAC address associated with the given IPv4 or `null` if
-	 * no matching host could be found or if no MAC address is known for
-	 * the corresponding host.
-	 */
-	getMACAddrByIPAddr: function(ipaddr) {
-		for (var mac in this.hosts)
-			if (this.hosts[mac].ipv4 == ipaddr)
-				return mac;
-		return null;
-	},
-
-	/**
-	 * Lookup the hostname associated with the given IPv6 address.
-	 *
-	 * @param {string} ipaddr
-	 * The IPv6 address to lookup.
-	 *
-	 * @returns {null|string}
-	 * Returns the hostname associated with the given IPv6 or `null` if
-	 * no matching host could be found or if no hostname is known for
-	 * the corresponding host.
-	 */
-	getHostnameByIP6Addr: function(ip6addr) {
-		for (var mac in this.hosts)
-			if (this.hosts[mac].ipv6 == ip6addr && this.hosts[mac].name != null)
-				return this.hosts[mac].name;
-		return null;
-	},
-
-	/**
-	 * Lookup the MAC address associated with the given IPv6 address.
-	 *
-	 * @param {string} ipaddr
-	 * The IPv6 address to lookup.
-	 *
-	 * @returns {null|string}
-	 * Returns the MAC address associated with the given IPv6 or `null` if
-	 * no matching host could be found or if no MAC address is known for
-	 * the corresponding host.
-	 */
-	getMACAddrByIP6Addr: function(ip6addr) {
-		for (var mac in this.hosts)
-			if (this.hosts[mac].ipv6 == ip6addr)
-				return mac;
-		return null;
-	},
-
-	/**
-	 * Return an array of (MAC address, name hint) tuples sorted by
-	 * MAC address.
-	 *
-	 * @param {boolean} [preferIp6=false]
-	 * Whether to prefer IPv6 addresses (`true`) or IPv4 addresses (`false`)
-	 * as name hint when no hostname is known for a specific MAC address.
-	 *
-	 * @returns {Array<Array<string>>}
-	 * Returns an array of arrays containing a name hint for each found
-	 * MAC address on the system. The array is sorted ascending by MAC.
-	 *
-	 * Each item of the resulting array is a two element array with the
-	 * MAC being the first element and the name hint being the second
-	 * element. The name hint is either the hostname, an IPv4 or an IPv6
-	 * address related to the MAC address.
-	 *
-	 * If no hostname but both IPv4 and IPv6 addresses are known, the
-	 * `preferIP6` flag specifies whether the IPv6 or the IPv4 address
-	 * is used as hint.
-	 */
-	getMACHints: function(preferIp6) {
-		var rv = [];
-		for (var mac in this.hosts) {
-			var hint = this.hosts[mac].name ||
-				this.hosts[mac][preferIp6 ? 'ipv6' : 'ipv4'] ||
-				this.hosts[mac][preferIp6 ? 'ipv4' : 'ipv6'];
-
-			rv.push([mac, hint]);
-		}
-		return rv.sort(function(a, b) { return a[0] > b[0] });
-	}
-});
-
-/**
- * @class
- * @memberof LuCI.network
- * @hideconstructor
- * @classdesc
- *
- * The `Network.Protocol` class serves as base for protocol specific
- * subclasses which describe logical UCI networks defined by `config
- * interface` sections in `/etc/config/network`.
- */
-Protocol = baseclass.extend(/** @lends LuCI.network.Protocol.prototype */ {
-	__init__: function(name) {
-		this.sid = name;
-	},
-
-	_get: function(opt) {
-		var val = uci.get('network', this.sid, opt);
-
-		if (Array.isArray(val))
-			return val.join(' ');
-
-		return val || '';
-	},
-
-	_ubus: function(field) {
-		for (var i = 0; i < _state.ifaces.length; i++) {
-			if (_state.ifaces[i].interface != this.sid)
-				continue;
-
-			return (field != null ? _state.ifaces[i][field] : _state.ifaces[i]);
-		}
-	},
-
-	/**
-	 * Read the given UCI option value of this network.
-	 *
-	 * @param {string} opt
-	 * The UCI option name to read.
-	 *
-	 * @returns {null|string|string[]}
-	 * Returns the UCI option value or `null` if the requested option is
-	 * not found.
-	 */
-	get: function(opt) {
-		return uci.get('network', this.sid, opt);
-	},
-
-	/**
-	 * Set the given UCI option of this network to the given value.
-	 *
-	 * @param {string} opt
-	 * The name of the UCI option to set.
-	 *
-	 * @param {null|string|string[]} val
-	 * The value to set or `null` to remove the given option from the
-	 * configuration.
-	 */
-	set: function(opt, val) {
-		return uci.set('network', this.sid, opt, val);
-	},
-
-	/**
-	 * Get the associared Linux network device of this network.
-	 *
-	 * @returns {null|string}
-	 * Returns the name of the associated network device or `null` if
-	 * it could not be determined.
-	 */
-	getIfname: function() {
-		var ifname;
-
-		if (this.isFloating())
-			ifname = this._ubus('l3_device');
-		else
-			ifname = this._ubus('device') || this._ubus('l3_device');
-
-		if (ifname != null)
-			return ifname;
-
-		var res = getWifiNetidByNetname(this.sid);
-		return (res != null ? res[0] : null);
-	},
-
-	/**
-	 * Get the name of this network protocol class.
-	 *
-	 * This function will be overwritten by subclasses created by
-	 * {@link LuCI.network#registerProtocol Network.registerProtocol()}.
-	 *
-	 * @abstract
-	 * @returns {string}
-	 * Returns the name of the network protocol implementation, e.g.
-	 * `static` or `dhcp`.
-	 */
-	getProtocol: function() {
-		return null;
-	},
-
-	/**
-	 * Return a human readable description for the protcol, such as
-	 * `Static address` or `DHCP client`.
-	 *
-	 * This function should be overwritten by subclasses.
-	 *
-	 * @abstract
-	 * @returns {string}
-	 * Returns the description string.
-	 */
-	getI18n: function() {
-		switch (this.getProtocol()) {
-		case 'none':   return _('Unmanaged');
-		case 'static': return _('Static address');
-		case 'dhcp':   return _('DHCP client');
-		default:       return _('Unknown');
-		}
-	},
-
-	/**
-	 * Get the type of the underlying interface.
-	 *
-	 * This function actually is a convenience wrapper around
-	 * `proto.get("type")` and is mainly used by other `LuCI.network` code
-	 * to check whether the interface is declared as bridge in UCI.
-	 *
-	 * @returns {null|string}
-	 * Returns the value of the `type` option of the associated logical
-	 * interface or `null` if no `type` option is set.
-	 */
-	getType: function() {
-		return this._get('type');
-	},
-
-	/**
-	 * Get the name of the associated logical interface.
-	 *
-	 * @returns {string}
-	 * Returns the logical interface name, such as `lan` or `wan`.
-	 */
-	getName: function() {
-		return this.sid;
-	},
-
-	/**
-	 * Get the uptime of the logical interface.
-	 *
-	 * @returns {number}
-	 * Returns the uptime of the associated interface in seconds.
-	 */
-	getUptime: function() {
-		return this._ubus('uptime') || 0;
-	},
-
-	/**
-	 * Get the logical interface expiry time in seconds.
-	 *
-	 * For protocols that have a concept of a lease, such as DHCP or
-	 * DHCPv6, this function returns the remaining time in seconds
-	 * until the lease expires.
-	 *
-	 * @returns {number}
-	 * Returns the amount of seconds until the lease expires or `-1`
-	 * if it isn't applicable to the associated protocol.
-	 */
-	getExpiry: function() {
-		var u = this._ubus('uptime'),
-		    d = this._ubus('data');
-
-		if (typeof(u) == 'number' && d != null &&
-		    typeof(d) == 'object' && typeof(d.leasetime) == 'number') {
-			var r = d.leasetime - (u % d.leasetime);
-			return (r > 0 ? r : 0);
-		}
-
-		return -1;
-	},
-
-	/**
-	 * Get the metric value of the logical interface.
-	 *
-	 * @returns {number}
-	 * Returns the current metric value used for device and network
-	 * routes spawned by the associated logical interface.
-	 */
-	getMetric: function() {
-		return this._ubus('metric') || 0;
-	},
-
-	/**
-	 * Get the requested firewall zone name of the logical interface.
-	 *
-	 * Some protocol implementations request a specific firewall zone
-	 * to trigger inclusion of their resulting network devices into the
-	 * firewall rule set.
-	 *
-	 * @returns {null|string}
-	 * Returns the requested firewall zone name as published in the
-	 * `ubus` runtime information or `null` if the remote protocol
-	 * handler didn't request a zone.
-	 */
-	getZoneName: function() {
-		var d = this._ubus('data');
-
-		if (L.isObject(d) && typeof(d.zone) == 'string')
-			return d.zone;
-
-		return null;
-	},
-
-	/**
-	 * Query the first (primary) IPv4 address of the logical interface.
-	 *
-	 * @returns {null|string}
-	 * Returns the primary IPv4 address registered by the protocol handler
-	 * or `null` if no IPv4 addresses were set.
-	 */
-	getIPAddr: function() {
-		var addrs = this._ubus('ipv4-address');
-		return ((Array.isArray(addrs) && addrs.length) ? addrs[0].address : null);
-	},
-
-	/**
-	 * Query all IPv4 addresses of the logical interface.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of IPv4 addresses in CIDR notation which have been
-	 * registered by the protocol handler. The order of the resulting array
-	 * follows the order of the addresses in `ubus` runtime information.
-	 */
-	getIPAddrs: function() {
-		var addrs = this._ubus('ipv4-address'),
-		    rv = [];
-
-		if (Array.isArray(addrs))
-			for (var i = 0; i < addrs.length; i++)
-				rv.push('%s/%d'.format(addrs[i].address, addrs[i].mask));
-
-		return rv;
-	},
-
-	/**
-	 * Query the first (primary) IPv4 netmask of the logical interface.
-	 *
-	 * @returns {null|string}
-	 * Returns the netmask of the primary IPv4 address registered by the
-	 * protocol handler or `null` if no IPv4 addresses were set.
-	 */
-	getNetmask: function() {
-		var addrs = this._ubus('ipv4-address');
-		if (Array.isArray(addrs) && addrs.length)
-			return prefixToMask(addrs[0].mask, false);
-	},
-
-	/**
-	 * Query the gateway (nexthop) of the default route associated with
-	 * this logical interface.
-	 *
-	 * @returns {string}
-	 * Returns a string containing the IPv4 nexthop address of the associated
-	 * default route or `null` if no default route was found.
-	 */
-	getGatewayAddr: function() {
-		var routes = this._ubus('route');
-
-		if (Array.isArray(routes))
-			for (var i = 0; i < routes.length; i++)
-				if (typeof(routes[i]) == 'object' &&
-				    routes[i].target == '0.0.0.0' &&
-				    routes[i].mask == 0)
-				    return routes[i].nexthop;
-
-		return null;
-	},
-
-	/**
-	 * Query the IPv4 DNS servers associated with the logical interface.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of IPv4 DNS servers registered by the remote
-	 * protocol backend.
-	 */
-	getDNSAddrs: function() {
-		var addrs = this._ubus('dns-server'),
-		    rv = [];
-
-		if (Array.isArray(addrs))
-			for (var i = 0; i < addrs.length; i++)
-				if (!/:/.test(addrs[i]))
-					rv.push(addrs[i]);
-
-		return rv;
-	},
-
-	/**
-	 * Query the first (primary) IPv6 address of the logical interface.
-	 *
-	 * @returns {null|string}
-	 * Returns the primary IPv6 address registered by the protocol handler
-	 * in CIDR notation or `null` if no IPv6 addresses were set.
-	 */
-	getIP6Addr: function() {
-		var addrs = this._ubus('ipv6-address');
-
-		if (Array.isArray(addrs) && L.isObject(addrs[0]))
-			return '%s/%d'.format(addrs[0].address, addrs[0].mask);
-
-		addrs = this._ubus('ipv6-prefix-assignment');
-
-		if (Array.isArray(addrs) && L.isObject(addrs[0]) && L.isObject(addrs[0]['local-address']))
-			return '%s/%d'.format(addrs[0]['local-address'].address, addrs[0]['local-address'].mask);
-
-		return null;
-	},
-
-	/**
-	 * Query all IPv6 addresses of the logical interface.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of IPv6 addresses in CIDR notation which have been
-	 * registered by the protocol handler. The order of the resulting array
-	 * follows the order of the addresses in `ubus` runtime information.
-	 */
-	getIP6Addrs: function() {
-		var addrs = this._ubus('ipv6-address'),
-		    rv = [];
-
-		if (Array.isArray(addrs))
-			for (var i = 0; i < addrs.length; i++)
-				if (L.isObject(addrs[i]))
-					rv.push('%s/%d'.format(addrs[i].address, addrs[i].mask));
-
-		addrs = this._ubus('ipv6-prefix-assignment');
-
-		if (Array.isArray(addrs))
-			for (var i = 0; i < addrs.length; i++)
-				if (L.isObject(addrs[i]) && L.isObject(addrs[i]['local-address']))
-					rv.push('%s/%d'.format(addrs[i]['local-address'].address, addrs[i]['local-address'].mask));
-
-		return rv;
-	},
-
-	/**
-	 * Query the gateway (nexthop) of the IPv6 default route associated with
-	 * this logical interface.
-	 *
-	 * @returns {string}
-	 * Returns a string containing the IPv6 nexthop address of the associated
-	 * default route or `null` if no default route was found.
-	 */
-	getGateway6Addr: function() {
-		var routes = this._ubus('route');
-
-		if (Array.isArray(routes))
-			for (var i = 0; i < routes.length; i++)
-				if (typeof(routes[i]) == 'object' &&
-				    routes[i].target == '::' &&
-				    routes[i].mask == 0)
-				    return routes[i].nexthop;
-
-		return null;
-	},
-
-	/**
-	 * Query the IPv6 DNS servers associated with the logical interface.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of IPv6 DNS servers registered by the remote
-	 * protocol backend.
-	 */
-	getDNS6Addrs: function() {
-		var addrs = this._ubus('dns-server'),
-		    rv = [];
-
-		if (Array.isArray(addrs))
-			for (var i = 0; i < addrs.length; i++)
-				if (/:/.test(addrs[i]))
-					rv.push(addrs[i]);
-
-		return rv;
-	},
-
-	/**
-	 * Query the routed IPv6 prefix associated with the logical interface.
-	 *
-	 * @returns {null|string}
-	 * Returns the routed IPv6 prefix registered by the remote protocol
-	 * handler or `null` if no prefix is present.
-	 */
-	getIP6Prefix: function() {
-		var prefixes = this._ubus('ipv6-prefix');
-
-		if (Array.isArray(prefixes) && L.isObject(prefixes[0]))
-			return '%s/%d'.format(prefixes[0].address, prefixes[0].mask);
-
-		return null;
-	},
-
-	/**
-	 * Query interface error messages published in `ubus` runtime state.
-	 *
-	 * Interface errors are emitted by remote protocol handlers if the setup
-	 * of the underlying logical interface failed, e.g. due to bad
-	 * configuration or network connectivity issues.
-	 *
-	 * This function will translate the found error codes to human readable
-	 * messages using the descriptions registered by
-	 * {@link LuCI.network#registerErrorCode Network.registerErrorCode()}
-	 * and fall back to `"Unknown error (%s)"` where `%s` is replaced by the
-	 * error code in case no translation can be found.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of translated interface error messages.
-	 */
-	getErrors: function() {
-		var errors = this._ubus('errors'),
-		    rv = null;
-
-		if (Array.isArray(errors)) {
-			for (var i = 0; i < errors.length; i++) {
-				if (!L.isObject(errors[i]) || typeof(errors[i].code) != 'string')
-					continue;
-
-				rv = rv || [];
-				rv.push(proto_errors[errors[i].code] || _('Unknown error (%s)').format(errors[i].code));
-			}
-		}
-
-		return rv;
-	},
-
-	/**
-	 * Checks whether the underlying logical interface is declared as bridge.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when the interface is declared with `option type bridge`
-	 * and when the associated protocol implementation is not marked virtual
-	 * or `false` when the logical interface is no bridge.
-	 */
-	isBridge: function() {
-		return (!this.isVirtual() && this.getType() == 'bridge');
-	},
-
-	/**
-	 * Get the name of the opkg package providing the protocol functionality.
-	 *
-	 * This function should be overwritten by protocol specific subclasses.
-	 *
-	 * @abstract
-	 *
-	 * @returns {string}
-	 * Returns the name of the opkg package required for the protocol to
-	 * function, e.g. `odhcp6c` for the `dhcpv6` prototocol.
-	 */
-	getOpkgPackage: function() {
-		return null;
-	},
-
-	/**
-	 * Check function for the protocol handler if a new interface is createable.
-	 *
-	 * This function should be overwritten by protocol specific subclasses.
-	 *
-	 * @abstract
-	 *
-	 * @param {string} ifname
-	 * The name of the interface to be created.
-	 *
-	 * @returns {Promise<void>}
-	 * Returns a promise resolving if new interface is createable, else
-	 * rejects with an error message string.
-	 */
-	isCreateable: function(ifname) {
-		return Promise.resolve(null);
-	},
-
-	/**
-	 * Checks whether the protocol functionality is installed.
-	 *
-	 * This function exists for compatibility with old code, it always
-	 * returns `true`.
-	 *
-	 * @deprecated
-	 * @abstract
-	 *
-	 * @returns {boolean}
-	 * Returns `true` if the protocol support is installed, else `false`.
-	 */
-	isInstalled: function() {
-		return true;
-	},
-
-	/**
-	 * Checks whether this protocol is "virtual".
-	 *
-	 * A "virtual" protocol is a protocol which spawns its own interfaces
-	 * on demand instead of using existing physical interfaces.
-	 *
-	 * Examples for virtual protocols are `6in4` which `gre` spawn tunnel
-	 * network device on startup, examples for non-virtual protcols are
-	 * `dhcp` or `static` which apply IP configuration to existing interfaces.
-	 *
-	 * This function should be overwritten by subclasses.
-	 *
-	 * @returns {boolean}
-	 * Returns a boolean indicating whether the underlying protocol spawns
-	 * dynamic interfaces (`true`) or not (`false`).
-	 */
-	isVirtual: function() {
-		return false;
-	},
-
-	/**
-	 * Checks whether this protocol is "floating".
-	 *
-	 * A "floating" protocol is a protocol which spawns its own interfaces
-	 * on demand, like a virtual one but which relies on an existinf lower
-	 * level interface to initiate the connection.
-	 *
-	 * An example for such a protocol is "pppoe".
-	 *
-	 * This function exists for backwards compatibility with older code
-	 * but should not be used anymore.
-	 *
-	 * @deprecated
-	 * @returns {boolean}
-	 * Returns a boolean indicating whether this protocol is floating (`true`)
-	 * or not (`false`).
-	 */
-	isFloating: function() {
-		return false;
-	},
-
-	/**
-	 * Checks whether this logical interface is dynamic.
-	 *
-	 * A dynamic interface is an interface which has been created at runtime,
-	 * e.g. as sub-interface of another interface, but which is not backed by
-	 * any user configuration. Such dynamic interfaces cannot be edited but
-	 * only brought down or restarted.
-	 *
-	 * @returns {boolean}
-	 * Returns a boolean indicating whether this interface is dynamic (`true`)
-	 * or not (`false`).
-	 */
-	isDynamic: function() {
-		return (this._ubus('dynamic') == true);
-	},
-
-	/**
-	 * Checks whether this interface is an alias interface.
-	 *
-	 * Alias interfaces are interfaces layering on top of another interface
-	 * and are denoted by a special `@interfacename` notation in the
-	 * underlying `ifname` option.
-	 *
-	 * @returns {null|string}
-	 * Returns the name of the parent interface if this logical interface
-	 * is an alias or `null` if it is not an alias interface.
-	 */
-	isAlias: function() {
-		var ifnames = L.toArray(uci.get('network', this.sid, 'ifname')),
-		    parent = null;
-
-		for (var i = 0; i < ifnames.length; i++)
-			if (ifnames[i].charAt(0) == '@')
-				parent = ifnames[i].substr(1);
-			else if (parent != null)
-				parent = null;
-
-		return parent;
-	},
-
-	/**
-	 * Checks whether this logical interface is "empty", meaning that ut
-	 * has no network devices attached.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` if this logical interface is empty, else `false`.
-	 */
-	isEmpty: function() {
-		if (this.isFloating())
-			return false;
-
-		var empty = true,
-		    ifname = this._get('ifname');
-
-		if (ifname != null && ifname.match(/\S+/))
-			empty = false;
-
-		if (empty == true && getWifiNetidBySid(this.sid) != null)
-			empty = false;
-
-		return empty;
-	},
-
-	/**
-	 * Checks whether this logical interface is configured and running.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when the interface is active or `false` when it is not.
-	 */
-	isUp: function() {
-		return (this._ubus('up') == true);
-	},
-
-	/**
-	 * Add the given network device to the logical interface.
-	 *
-	 * @param {LuCI.network.Protocol|LuCI.network.Device|LuCI.network.WifiDevice|LuCI.network.WifiNetwork|string} device
-	 * The object or device name to add to the logical interface. In case the
-	 * given argument is not a string, it is resolved though the
-	 * {@link LuCI.network#getIfnameOf Network.getIfnameOf()} function.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` if the device name has been added or `false` if any
-	 * argument was invalid, if the device was already part of the logical
-	 * interface or if the logical interface is virtual.
-	 */
-	addDevice: function(ifname) {
-		ifname = ifnameOf(ifname);
-
-		if (ifname == null || this.isFloating())
-			return false;
-
-		var wif = getWifiSidByIfname(ifname);
-
-		if (wif != null)
-			return appendValue('wireless', wif, 'network', this.sid);
-
-		return appendValue('network', this.sid, 'ifname', ifname);
-	},
-
-	/**
-	 * Remove the given network device from the logical interface.
-	 *
-	 * @param {LuCI.network.Protocol|LuCI.network.Device|LuCI.network.WifiDevice|LuCI.network.WifiNetwork|string} device
-	 * The object or device name to remove from the logical interface. In case
-	 * the given argument is not a string, it is resolved though the
-	 * {@link LuCI.network#getIfnameOf Network.getIfnameOf()} function.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` if the device name has been added or `false` if any
-	 * argument was invalid, if the device was already part of the logical
-	 * interface or if the logical interface is virtual.
-	 */
-	deleteDevice: function(ifname) {
-		var rv = false;
-
-		ifname = ifnameOf(ifname);
-
-		if (ifname == null || this.isFloating())
-			return false;
-
-		var wif = getWifiSidByIfname(ifname);
-
-		if (wif != null)
-			rv = removeValue('wireless', wif, 'network', this.sid);
-
-		if (removeValue('network', this.sid, 'ifname', ifname))
-			rv = true;
-
-		return rv;
-	},
-
-	/**
-	 * Returns the Linux network device associated with this logical
-	 * interface.
-	 *
-	 * @returns {LuCI.network.Device}
-	 * Returns a `Network.Device` class instance representing the
-	 * expected Linux network device according to the configuration.
-	 */
-	getDevice: function() {
-		if (this.isVirtual()) {
-			var ifname = '%s-%s'.format(this.getProtocol(), this.sid);
-			_state.isTunnel[this.getProtocol() + '-' + this.sid] = true;
-			return Network.prototype.instantiateDevice(ifname, this);
-		}
-		else if (this.isBridge()) {
-			var ifname = 'br-%s'.format(this.sid);
-			_state.isBridge[ifname] = true;
-			return new Device(ifname, this);
-		}
-		else {
-			var ifnames = L.toArray(uci.get('network', this.sid, 'ifname'));
-
-			for (var i = 0; i < ifnames.length; i++) {
-				var m = ifnames[i].match(/^([^:/]+)/);
-				return ((m && m[1]) ? Network.prototype.instantiateDevice(m[1], this) : null);
-			}
-
-			ifname = getWifiNetidByNetname(this.sid);
-
-			return (ifname != null ? Network.prototype.instantiateDevice(ifname[0], this) : null);
-		}
-	},
-
-	/**
-	 * Returns the layer 2 linux network device currently associated
-	 * with this logical interface.
-	 *
-	 * @returns {LuCI.network.Device}
-	 * Returns a `Network.Device` class instance representing the Linux
-	 * network device currently associated with the logical interface.
-	 */
-	getL2Device: function() {
-		var ifname = this._ubus('device');
-		return (ifname != null ? Network.prototype.instantiateDevice(ifname, this) : null);
-	},
-
-	/**
-	 * Returns the layer 3 linux network device currently associated
-	 * with this logical interface.
-	 *
-	 * @returns {LuCI.network.Device}
-	 * Returns a `Network.Device` class instance representing the Linux
-	 * network device currently associated with the logical interface.
-	 */
-	getL3Device: function() {
-		var ifname = this._ubus('l3_device');
-		return (ifname != null ? Network.prototype.instantiateDevice(ifname, this) : null);
-	},
-
-	/**
-	 * Returns a list of network sub-devices associated with this logical
-	 * interface.
-	 *
-	 * @returns {null|Array<LuCI.network.Device>}
-	 * Returns an array of of `Network.Device` class instances representing
-	 * the sub-devices attached to this logical interface or `null` if the
-	 * logical interface does not support sub-devices, e.g. because it is
-	 * virtual and not a bridge.
-	 */
-	getDevices: function() {
-		var rv = [];
-
-		if (!this.isBridge() && !(this.isVirtual() && !this.isFloating()))
-			return null;
-
-		var ifnames = L.toArray(uci.get('network', this.sid, 'ifname'));
-
-		for (var i = 0; i < ifnames.length; i++) {
-			if (ifnames[i].charAt(0) == '@')
-				continue;
-
-			var m = ifnames[i].match(/^([^:/]+)/);
-			if (m != null)
-				rv.push(Network.prototype.instantiateDevice(m[1], this));
-		}
-
-		var uciWifiIfaces = uci.sections('wireless', 'wifi-iface');
-
-		for (var i = 0; i < uciWifiIfaces.length; i++) {
-			if (typeof(uciWifiIfaces[i].device) != 'string')
-				continue;
-
-			var networks = L.toArray(uciWifiIfaces[i].network);
-
-			for (var j = 0; j < networks.length; j++) {
-				if (networks[j] != this.sid)
-					continue;
-
-				var netid = getWifiNetidBySid(uciWifiIfaces[i]['.name']);
-
-				if (netid != null)
-					rv.push(Network.prototype.instantiateDevice(netid[0], this));
-			}
-		}
-
-		rv.sort(deviceSort);
-
-		return rv;
-	},
-
-	/**
-	 * Checks whether this logical interface contains the given device
-	 * object.
-	 *
-	 * @param {LuCI.network.Protocol|LuCI.network.Device|LuCI.network.WifiDevice|LuCI.network.WifiNetwork|string} device
-	 * The object or device name to check. In case the given argument is not
-	 * a string, it is resolved though the
-	 * {@link LuCI.network#getIfnameOf Network.getIfnameOf()} function.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when this logical interface contains the given network
-	 * device or `false` if not.
-	 */
-	containsDevice: function(ifname) {
-		ifname = ifnameOf(ifname);
-
-		if (ifname == null)
-			return false;
-		else if (this.isVirtual() && '%s-%s'.format(this.getProtocol(), this.sid) == ifname)
-			return true;
-		else if (this.isBridge() && 'br-%s'.format(this.sid) == ifname)
-			return true;
-
-		var ifnames = L.toArray(uci.get('network', this.sid, 'ifname'));
-
-		for (var i = 0; i < ifnames.length; i++) {
-			var m = ifnames[i].match(/^([^:/]+)/);
-			if (m != null && m[1] == ifname)
-				return true;
-		}
-
-		var wif = getWifiSidByIfname(ifname);
-
-		if (wif != null) {
-			var networks = L.toArray(uci.get('wireless', wif, 'network'));
-
-			for (var i = 0; i < networks.length; i++)
-				if (networks[i] == this.sid)
-					return true;
-		}
-
-		return false;
-	},
-
-	/**
-	 * Cleanup related configuration entries.
-	 *
-	 * This function will be invoked if an interface is about to be removed
-	 * from the configuration and is responsible for performing any required
-	 * cleanup tasks, such as unsetting uci entries in related configurations.
-	 *
-	 * It should be overwritten by protocol specific subclasses.
-	 *
-	 * @abstract
-	 *
-	 * @returns {*|Promise<*>}
-	 * This function may return a promise which is awaited before the rest of
-	 * the configuration is removed. Any non-promise return value and any
-	 * resolved promise value is ignored. If the returned promise is rejected,
-	 * the interface removal will be aborted.
-	 */
-	deleteConfiguration: function() {}
-});
-
-/**
- * @class
- * @memberof LuCI.network
- * @hideconstructor
- * @classdesc
- *
- * A `Network.Device` class instance represents an underlying Linux network
- * device and allows querying device details such as packet statistics or MTU.
- */
-Device = baseclass.extend(/** @lends LuCI.network.Device.prototype */ {
-	__init__: function(ifname, network) {
-		var wif = getWifiSidByIfname(ifname);
-
-		if (wif != null) {
-			var res = getWifiStateBySid(wif) || [],
-			    netid = getWifiNetidBySid(wif) || [];
-
-			this.wif    = new WifiNetwork(wif, res[0], res[1], netid[0], res[2], { ifname: ifname });
-			this.ifname = this.wif.getIfname();
-		}
-
-		this.ifname  = this.ifname || ifname;
-		this.dev     = _state.netdevs[this.ifname];
-		this.network = network;
-	},
-
-	_devstate: function(/* ... */) {
-		var rv = this.dev;
-
-		for (var i = 0; i < arguments.length; i++)
-			if (L.isObject(rv))
-				rv = rv[arguments[i]];
-			else
-				return null;
-
-		return rv;
-	},
-
-	/**
-	 * Get the name of the network device.
-	 *
-	 * @returns {string}
-	 * Returns the name of the device, e.g. `eth0` or `wlan0`.
-	 */
-	getName: function() {
-		return (this.wif != null ? this.wif.getIfname() : this.ifname);
-	},
-
-	/**
-	 * Get the MAC address of the device.
-	 *
-	 * @returns {null|string}
-	 * Returns the MAC address of the device or `null` if not applicable,
-	 * e.g. for non-ethernet tunnel devices.
-	 */
-	getMAC: function() {
-		var mac = this._devstate('macaddr');
-		return mac ? mac.toUpperCase() : null;
-	},
-
-	/**
-	 * Get the MTU of the device.
-	 *
-	 * @returns {number}
-	 * Returns the MTU of the device.
-	 */
-	getMTU: function() {
-		return this._devstate('mtu');
-	},
-
-	/**
-	 * Get the IPv4 addresses configured on the device.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of IPv4 address strings.
-	 */
-	getIPAddrs: function() {
-		var addrs = this._devstate('ipaddrs');
-		return (Array.isArray(addrs) ? addrs : []);
-	},
-
-	/**
-	 * Get the IPv6 addresses configured on the device.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of IPv6 address strings.
-	 */
-	getIP6Addrs: function() {
-		var addrs = this._devstate('ip6addrs');
-		return (Array.isArray(addrs) ? addrs : []);
-	},
-
-	/**
-	 * Get the type of the device..
-	 *
-	 * @returns {string}
-	 * Returns a string describing the type of the network device:
-	 *  - `alias` if it is an abstract alias device (`@` notation)
-	 *  - `wifi` if it is a wireless interface (e.g. `wlan0`)
-	 *  - `bridge` if it is a bridge device (e.g. `br-lan`)
-	 *  - `tunnel` if it is a tun or tap device (e.g. `tun0`)
-	 *  - `vlan` if it is a vlan device (e.g. `eth0.1`)
-	 *  - `switch` if it is a switch device (e.g.`eth1` connected to switch0)
-	 *  - `ethernet` for all other device types
-	 */
-	getType: function() {
-		if (this.ifname != null && this.ifname.charAt(0) == '@')
-			return 'alias';
-		else if (this.wif != null || isWifiIfname(this.ifname))
-			return 'wifi';
-		else if (_state.isBridge[this.ifname])
-			return 'bridge';
-		else if (_state.isTunnel[this.ifname])
-			return 'tunnel';
-		else if (this.ifname.indexOf('.') > -1)
-			return 'vlan';
-		else if (_state.isSwitch[this.ifname])
-			return 'switch';
-		else
-			return 'ethernet';
-	},
-
-	/**
-	 * Get a short description string for the device.
-	 *
-	 * @returns {string}
-	 * Returns the device name for non-wifi devices or a string containing
-	 * the operation mode and SSID for wifi devices.
-	 */
-	getShortName: function() {
-		if (this.wif != null)
-			return this.wif.getShortName();
-
-		return this.ifname;
-	},
-
-	/**
-	 * Get a long description string for the device.
-	 *
-	 * @returns {string}
-	 * Returns a string containing the type description and device name
-	 * for non-wifi devices or operation mode and ssid for wifi ones.
-	 */
-	getI18n: function() {
-		if (this.wif != null) {
-			return '%s: %s "%s"'.format(
-				_('Wireless Network'),
-				this.wif.getActiveMode(),
-				this.wif.getActiveSSID() || this.wif.getActiveBSSID() || this.wif.getID() || '?');
-		}
-
-		return '%s: "%s"'.format(this.getTypeI18n(), this.getName());
-	},
-
-	/**
-	 * Get a string describing the device type.
-	 *
-	 * @returns {string}
-	 * Returns a string describing the type, e.g. "Wireless Adapter" or
-	 * "Bridge".
-	 */
-	getTypeI18n: function() {
-		switch (this.getType()) {
-		case 'alias':
-			return _('Alias Interface');
-
-		case 'wifi':
-			return _('Wireless Adapter');
-
-		case 'bridge':
-			return _('Bridge');
-
-		case 'switch':
-			return _('Ethernet Switch');
-
-		case 'vlan':
-			return (_state.isSwitch[this.ifname] ? _('Switch VLAN') : _('Software VLAN'));
-
-		case 'tunnel':
-			return _('Tunnel Interface');
-
-		default:
-			return _('Ethernet Adapter');
-		}
-	},
-
-	/**
-	 * Get the associated bridge ports of the device.
-	 *
-	 * @returns {null|Array<LuCI.network.Device>}
-	 * Returns an array of `Network.Device` instances representing the ports
-	 * (slave interfaces) of the bridge or `null` when this device isn't
-	 * a Linux bridge.
-	 */
-	getPorts: function() {
-		var br = _state.bridges[this.ifname],
-		    rv = [];
-
-		if (br == null || !Array.isArray(br.ifnames))
-			return null;
-
-		for (var i = 0; i < br.ifnames.length; i++)
-			rv.push(Network.prototype.instantiateDevice(br.ifnames[i].name));
-
-		rv.sort(deviceSort);
-
-		return rv;
-	},
-
-	/**
-	 * Get the bridge ID
-	 *
-	 * @returns {null|string}
-	 * Returns the ID of this network bridge or `null` if this network
-	 * device is not a Linux bridge.
-	 */
-	getBridgeID: function() {
-		var br = _state.bridges[this.ifname];
-		return (br != null ? br.id : null);
-	},
-
-	/**
-	 * Get the bridge STP setting
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when this device is a Linux bridge and has `stp`
-	 * enabled, else `false`.
-	 */
-	getBridgeSTP: function() {
-		var br = _state.bridges[this.ifname];
-		return (br != null ? !!br.stp : false);
-	},
-
-	/**
-	 * Checks whether this device is up.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when the associated device is running pr `false`
-	 * when it is down or absent.
-	 */
-	isUp: function() {
-		var up = this._devstate('flags', 'up');
-
-		if (up == null)
-			up = (this.getType() == 'alias');
-
-		return up;
-	},
-
-	/**
-	 * Checks whether this device is a Linux bridge.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when the network device is present and a Linux bridge,
-	 * else `false`.
-	 */
-	isBridge: function() {
-		return (this.getType() == 'bridge');
-	},
-
-	/**
-	 * Checks whether this device is part of a Linux bridge.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when this network device is part of a bridge,
-	 * else `false`.
-	 */
-	isBridgePort: function() {
-		return (this._devstate('bridge') != null);
-	},
-
-	/**
-	 * Get the amount of transmitted bytes.
-	 *
-	 * @returns {number}
-	 * Returns the amount of bytes transmitted by the network device.
-	 */
-	getTXBytes: function() {
-		var stat = this._devstate('stats');
-		return (stat != null ? stat.tx_bytes || 0 : 0);
-	},
-
-	/**
-	 * Get the amount of received bytes.
-	 *
-	 * @returns {number}
-	 * Returns the amount of bytes received by the network device.
-	 */
-	getRXBytes: function() {
-		var stat = this._devstate('stats');
-		return (stat != null ? stat.rx_bytes || 0 : 0);
-	},
-
-	/**
-	 * Get the amount of transmitted packets.
-	 *
-	 * @returns {number}
-	 * Returns the amount of packets transmitted by the network device.
-	 */
-	getTXPackets: function() {
-		var stat = this._devstate('stats');
-		return (stat != null ? stat.tx_packets || 0 : 0);
-	},
-
-	/**
-	 * Get the amount of received packets.
-	 *
-	 * @returns {number}
-	 * Returns the amount of packets received by the network device.
-	 */
-	getRXPackets: function() {
-		var stat = this._devstate('stats');
-		return (stat != null ? stat.rx_packets || 0 : 0);
-	},
-
-	/**
-	 * Get the primary logical interface this device is assigned to.
-	 *
-	 * @returns {null|LuCI.network.Protocol}
-	 * Returns a `Network.Protocol` instance representing the logical
-	 * interface this device is attached to or `null` if it is not
-	 * assigned to any logical interface.
-	 */
-	getNetwork: function() {
-		return this.getNetworks()[0];
-	},
-
-	/**
-	 * Get the logical interfaces this device is assigned to.
-	 *
-	 * @returns {Array<LuCI.network.Protocol>}
-	 * Returns an array of `Network.Protocol` instances representing the
-	 * logical interfaces this device is assigned to.
-	 */
-	getNetworks: function() {
-		if (this.networks == null) {
-			this.networks = [];
-
-			var networks = enumerateNetworks.apply(L.network);
-
-			for (var i = 0; i < networks.length; i++)
-				if (networks[i].containsDevice(this.ifname) || networks[i].getIfname() == this.ifname)
-					this.networks.push(networks[i]);
-
-			this.networks.sort(networkSort);
-		}
-
-		return this.networks;
-	},
-
-	/**
-	 * Get the related wireless network this device is related to.
-	 *
-	 * @returns {null|LuCI.network.WifiNetwork}
-	 * Returns a `Network.WifiNetwork` instance representing the wireless
-	 * network corresponding to this network device or `null` if this device
-	 * is not a wireless device.
-	 */
-	getWifiNetwork: function() {
-		return (this.wif != null ? this.wif : null);
-	}
-});
-
-/**
- * @class
- * @memberof LuCI.network
- * @hideconstructor
- * @classdesc
- *
- * A `Network.WifiDevice` class instance represents a wireless radio device
- * present on the system and provides wireless capability information as
- * well as methods for enumerating related wireless networks.
- */
-WifiDevice = baseclass.extend(/** @lends LuCI.network.WifiDevice.prototype */ {
-	__init__: function(name, radiostate) {
-		var uciWifiDevice = uci.get('wireless', name);
-
-		if (uciWifiDevice != null &&
-		    uciWifiDevice['.type'] == 'wifi-device' &&
-		    uciWifiDevice['.name'] != null) {
-			this.sid    = uciWifiDevice['.name'];
-		}
-
-		this.sid    = this.sid || name;
-		this._ubusdata = {
-			radio: name,
-			dev:   radiostate
-		};
-	},
-
-	/* private */
-	ubus: function(/* ... */) {
-		var v = this._ubusdata;
-
-		for (var i = 0; i < arguments.length; i++)
-			if (L.isObject(v))
-				v = v[arguments[i]];
-			else
-				return null;
-
-		return v;
-	},
-
-	/**
-	 * Read the given UCI option value of this wireless device.
-	 *
-	 * @param {string} opt
-	 * The UCI option name to read.
-	 *
-	 * @returns {null|string|string[]}
-	 * Returns the UCI option value or `null` if the requested option is
-	 * not found.
-	 */
-	get: function(opt) {
-		return uci.get('wireless', this.sid, opt);
-	},
-
-	/**
-	 * Set the given UCI option of this network to the given value.
-	 *
-	 * @param {string} opt
-	 * The name of the UCI option to set.
-	 *
-	 * @param {null|string|string[]} val
-	 * The value to set or `null` to remove the given option from the
-	 * configuration.
-	 */
-	set: function(opt, value) {
-		return uci.set('wireless', this.sid, opt, value);
-	},
-
-	/**
-	 * Checks whether this wireless radio is disabled.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when the wireless radio is marked as disabled in `ubus`
-	 * runtime state or when the `disabled` option is set in the corresponding
-	 * UCI configuration.
-	 */
-	isDisabled: function() {
-		return this.ubus('dev', 'disabled') || this.get('disabled') == '1';
-	},
-
-	/**
-	 * Get the configuration name of this wireless radio.
-	 *
-	 * @returns {string}
-	 * Returns the UCI section name (e.g. `radio0`) of the corresponding
-	 * radio configuration which also serves as unique logical identifier
-	 * for the wireless phy.
-	 */
-	getName: function() {
-		return this.sid;
-	},
-
-	/**
-	 * Gets a list of supported hwmodes.
-	 *
-	 * The hwmode values describe the frequency band and wireless standard
-	 * versions supported by the wireless phy.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of valid hwmode values for this radio. Currently
-	 * known mode values are:
-	 *  - `a` - Legacy 802.11a mode, 5 GHz, up to 54 Mbit/s
-	 *  - `b` - Legacy 802.11b mode, 2.4 GHz, up to 11 Mbit/s
-	 *  - `g` - Legacy 802.11g mode, 2.4 GHz, up to 54 Mbit/s
-	 *  - `n` - IEEE 802.11n mode, 2.4 or 5 GHz, up to 600 Mbit/s
-	 *  - `ac` - IEEE 802.11ac mode, 5 GHz, up to 6770 Mbit/s
-	 */
-	getHWModes: function() {
-		var hwmodes = this.ubus('dev', 'iwinfo', 'hwmodes');
-		return Array.isArray(hwmodes) ? hwmodes : [ 'b', 'g' ];
-	},
-
-	/**
-	 * Gets a list of supported htmodes.
-	 *
-	 * The htmode values describe the wide-frequency options supported by
-	 * the wireless phy.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of valid htmode values for this radio. Currently
-	 * known mode values are:
-	 *  - `HT20` - applicable to IEEE 802.11n, 20 MHz wide channels
-	 *  - `HT40` - applicable to IEEE 802.11n, 40 MHz wide channels
-	 *  - `VHT20` - applicable to IEEE 802.11ac, 20 MHz wide channels
-	 *  - `VHT40` - applicable to IEEE 802.11ac, 40 MHz wide channels
-	 *  - `VHT80` - applicable to IEEE 802.11ac, 80 MHz wide channels
-	 *  - `VHT160` - applicable to IEEE 802.11ac, 160 MHz wide channels
-	 */
-	getHTModes: function() {
-		var htmodes = this.ubus('dev', 'iwinfo', 'htmodes');
-		return (Array.isArray(htmodes) && htmodes.length) ? htmodes : null;
-	},
-
-	/**
-	 * Get a string describing the wireless radio hardware.
-	 *
-	 * @returns {string}
-	 * Returns the description string.
-	 */
-	getI18n: function() {
-		var hw = this.ubus('dev', 'iwinfo', 'hardware'),
-		    type = L.isObject(hw) ? hw.name : null;
-
-		if (this.ubus('dev', 'iwinfo', 'type') == 'wl')
-			type = 'Broadcom';
-
-		var hwmodes = this.getHWModes(),
-		    modestr = '';
-
-		hwmodes.sort(function(a, b) {
-			return (a.length != b.length ? a.length > b.length : a > b);
-		});
-
-		modestr = hwmodes.join('');
-
-		return '%s 802.11%s Wireless Controller (%s)'.format(type || 'Generic', modestr, this.getName());
-	},
-
-	/**
-	 * A wireless scan result object describes a neighbouring wireless
-	 * network found in the vincinity.
-	 *
-	 * @typedef {Object<string, number|string|LuCI.network.WifiEncryption>} WifiScanResult
-	 * @memberof LuCI.network
-	 *
-	 * @property {string} ssid
-	 * The SSID / Mesh ID of the network.
-	 *
-	 * @property {string} bssid
-	 * The BSSID if the network.
-	 *
-	 * @property {string} mode
-	 * The operation mode of the network (`Master`, `Ad-Hoc`, `Mesh Point`).
-	 *
-	 * @property {number} channel
-	 * The wireless channel of the network.
-	 *
-	 * @property {number} signal
-	 * The received signal strength of the network in dBm.
-	 *
-	 * @property {number} quality
-	 * The numeric quality level of the signal, can be used in conjunction
-	 * with `quality_max` to calculate a quality percentage.
-	 *
-	 * @property {number} quality_max
-	 * The maximum possible quality level of the signal, can be used in
-	 * conjunction with `quality` to calculate a quality percentage.
-	 *
-	 * @property {LuCI.network.WifiEncryption} encryption
-	 * The encryption used by the wireless network.
-	 */
-
-	/**
-	 * Trigger a wireless scan on this radio device and obtain a list of
-	 * nearby networks.
-	 *
-	 * @returns {Promise<Array<LuCI.network.WifiScanResult>>}
-	 * Returns a promise resolving to an array of scan result objects
-	 * describing the networks found in the vincinity.
-	 */
-	getScanList: function() {
-		return callIwinfoScan(this.sid);
-	},
-
-	/**
-	 * Check whether the wireless radio is marked as up in the `ubus`
-	 * runtime state.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when the radio device is up, else `false`.
-	 */
-	isUp: function() {
-		if (L.isObject(_state.radios[this.sid]))
-			return (_state.radios[this.sid].up == true);
-
-		return false;
-	},
-
-	/**
-	 * Get the wifi network of the given name belonging to this radio device
-	 *
-	 * @param {string} network
-	 * The name of the wireless network to lookup. This may be either an uci
-	 * configuration section ID, a network ID in the form `radio#.network#`
-	 * or a Linux network device name like `wlan0` which is resolved to the
-	 * corresponding configuration section through `ubus` runtime information.
-	 *
-	 * @returns {Promise<LuCI.network.WifiNetwork>}
-	 * Returns a promise resolving to a `Network.WifiNetwork` instance
-	 * representing the wireless network and rejecting with `null` if
-	 * the given network could not be found or is not associated with
-	 * this radio device.
-	 */
-	getWifiNetwork: function(network) {
-		return Network.prototype.getWifiNetwork(network).then(L.bind(function(networkInstance) {
-			var uciWifiIface = (networkInstance.sid ? uci.get('wireless', networkInstance.sid) : null);
-
-			if (uciWifiIface == null || uciWifiIface['.type'] != 'wifi-iface' || uciWifiIface.device != this.sid)
-				return Promise.reject();
-
-			return networkInstance;
-		}, this));
-	},
-
-	/**
-	 * Get all wireless networks associated with this wireless radio device.
-	 *
-	 * @returns {Promise<Array<LuCI.network.WifiNetwork>>}
-	 * Returns a promise resolving to an array of `Network.WifiNetwork`
-	 * instances respresenting the wireless networks associated with this
-	 * radio device.
-	 */
-	getWifiNetworks: function() {
-		return Network.prototype.getWifiNetworks().then(L.bind(function(networks) {
-			var rv = [];
-
-			for (var i = 0; i < networks.length; i++)
-				if (networks[i].getWifiDeviceName() == this.getName())
-					rv.push(networks[i]);
-
-			return rv;
-		}, this));
-	},
-
-	/**
-	 * Adds a new wireless network associated with this radio device to the
-	 * configuration and sets its options to the provided values.
-	 *
-	 * @param {Object<string, string|string[]>} [options]
-	 * The options to set for the newly added wireless network.
-	 *
-	 * @returns {Promise<null|LuCI.network.WifiNetwork>}
-	 * Returns a promise resolving to a `WifiNetwork` instance describing
-	 * the newly added wireless network or `null` if the given options
-	 * were invalid.
-	 */
-	addWifiNetwork: function(options) {
-		if (!L.isObject(options))
-			options = {};
-
-		options.device = this.sid;
-
-		return Network.prototype.addWifiNetwork(options);
-	},
-
-	/**
-	 * Deletes the wireless network with the given name associated with this
-	 * radio device.
-	 *
-	 * @param {string} network
-	 * The name of the wireless network to lookup. This may be either an uci
-	 * configuration section ID, a network ID in the form `radio#.network#`
-	 * or a Linux network device name like `wlan0` which is resolved to the
-	 * corresponding configuration section through `ubus` runtime information.
-	 *
-	 * @returns {Promise<boolean>}
-	 * Returns a promise resolving to `true` when the wireless network was
-	 * successfully deleted from the configuration or `false` when the given
-	 * network could not be found or if the found network was not associated
-	 * with this wireless radio device.
-	 */
-	deleteWifiNetwork: function(network) {
-		var sid = null;
-
-		if (network instanceof WifiNetwork) {
-			sid = network.sid;
-		}
-		else {
-			var uciWifiIface = uci.get('wireless', network);
-
-			if (uciWifiIface == null || uciWifiIface['.type'] != 'wifi-iface')
-				sid = getWifiSidByIfname(network);
-		}
-
-		if (sid == null || uci.get('wireless', sid, 'device') != this.sid)
-			return Promise.resolve(false);
-
-		uci.delete('wireless', network);
-
-		return Promise.resolve(true);
-	}
-});
-
-/**
- * @class
- * @memberof LuCI.network
- * @hideconstructor
- * @classdesc
- *
- * A `Network.WifiNetwork` instance represents a wireless network (vif)
- * configured on top of a radio device and provides functions for querying
- * the runtime state of the network. Most radio devices support multiple
- * such networks in parallel.
- */
-WifiNetwork = baseclass.extend(/** @lends LuCI.network.WifiNetwork.prototype */ {
-	__init__: function(sid, radioname, radiostate, netid, netstate, hostapd) {
-		this.sid    = sid;
-		this.netid  = netid;
-		this._ubusdata = {
-			hostapd: hostapd,
-			radio:   radioname,
-			dev:     radiostate,
-			net:     netstate
-		};
-	},
-
-	ubus: function(/* ... */) {
-		var v = this._ubusdata;
-
-		for (var i = 0; i < arguments.length; i++)
-			if (L.isObject(v))
-				v = v[arguments[i]];
-			else
-				return null;
-
-		return v;
-	},
-
-	/**
-	 * Read the given UCI option value of this wireless network.
-	 *
-	 * @param {string} opt
-	 * The UCI option name to read.
-	 *
-	 * @returns {null|string|string[]}
-	 * Returns the UCI option value or `null` if the requested option is
-	 * not found.
-	 */
-	get: function(opt) {
-		return uci.get('wireless', this.sid, opt);
-	},
-
-	/**
-	 * Set the given UCI option of this network to the given value.
-	 *
-	 * @param {string} opt
-	 * The name of the UCI option to set.
-	 *
-	 * @param {null|string|string[]} val
-	 * The value to set or `null` to remove the given option from the
-	 * configuration.
-	 */
-	set: function(opt, value) {
-		return uci.set('wireless', this.sid, opt, value);
-	},
-
-	/**
-	 * Checks whether this wireless network is disabled.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when the wireless radio is marked as disabled in `ubus`
-	 * runtime state or when the `disabled` option is set in the corresponding
-	 * UCI configuration.
-	 */
-	isDisabled: function() {
-		return this.ubus('dev', 'disabled') || this.get('disabled') == '1';
-	},
-
-	/**
-	 * Get the configured operation mode of the wireless network.
-	 *
-	 * @returns {string}
-	 * Returns the configured operation mode. Possible values are:
-	 *  - `ap` - Master (Access Point) mode
-	 *  - `sta` - Station (client) mode
-	 *  - `adhoc` - Ad-Hoc (IBSS) mode
-	 *  - `mesh` - Mesh (IEEE 802.11s) mode
-	 *  - `monitor` - Monitor mode
-	 */
-	getMode: function() {
-		return this.ubus('net', 'config', 'mode') || this.get('mode') || 'ap';
-	},
-
-	/**
-	 * Get the configured SSID of the wireless network.
-	 *
-	 * @returns {null|string}
-	 * Returns the configured SSID value or `null` when this network is
-	 * in mesh mode.
-	 */
-	getSSID: function() {
-		if (this.getMode() == 'mesh')
-			return null;
-
-		return this.ubus('net', 'config', 'ssid') || this.get('ssid');
-	},
-
-	/**
-	 * Get the configured Mesh ID of the wireless network.
-	 *
-	 * @returns {null|string}
-	 * Returns the configured mesh ID value or `null` when this network
-	 * is not in mesh mode.
-	 */
-	getMeshID: function() {
-		if (this.getMode() != 'mesh')
-			return null;
-
-		return this.ubus('net', 'config', 'mesh_id') || this.get('mesh_id');
-	},
-
-	/**
-	 * Get the configured BSSID of the wireless network.
-	 *
-	 * @returns {null|string}
-	 * Returns the BSSID value or `null` if none has been specified.
-	 */
-	getBSSID: function() {
-		return this.ubus('net', 'config', 'bssid') || this.get('bssid');
-	},
-
-	/**
-	 * Get the names of the logical interfaces this wireless network is
-	 * attached to.
-	 *
-	 * @returns {string[]}
-	 * Returns an array of logical interface names.
-	 */
-	getNetworkNames: function() {
-		return L.toArray(this.ubus('net', 'config', 'network') || this.get('network'));
-	},
-
-	/**
-	 * Get the internal network ID of this wireless network.
-	 *
-	 * The network ID is a LuCI specific identifer in the form
-	 * `radio#.network#` to identify wireless networks by their corresponding
-	 * radio and network index numbers.
-	 *
-	 * @returns {string}
-	 * Returns the LuCI specific network ID.
-	 */
-	getID: function() {
-		return this.netid;
-	},
-
-	/**
-	 * Get the configuration ID of this wireless network.
-	 *
-	 * @returns {string}
-	 * Returns the corresponding UCI section ID of the network.
-	 */
-	getName: function() {
-		return this.sid;
-	},
-
-	/**
-	 * Get the Linux network device name.
-	 *
-	 * @returns {null|string}
-	 * Returns the current Linux network device name as resolved from
-	 * `ubus` runtime information or `null` if this network has no
-	 * associated network device, e.g. when not configured or up.
-	 */
-	getIfname: function() {
-		var ifname = this.ubus('net', 'ifname') || this.ubus('net', 'iwinfo', 'ifname');
-
-		if (ifname == null || ifname.match(/^(wifi|radio)\d/))
-			ifname = this.netid;
-
-		return ifname;
-	},
-
-	/**
-	 * Get the name of the corresponding wifi radio device.
-	 *
-	 * @returns {null|string}
-	 * Returns the name of the radio device this network is configured on
-	 * or `null` if it cannot be determined.
-	 */
-	getWifiDeviceName: function() {
-		return this.ubus('radio') || this.get('device');
-	},
-
-	/**
-	 * Get the corresponding wifi radio device.
-	 *
-	 * @returns {null|LuCI.network.WifiDevice}
-	 * Returns a `Network.WifiDevice` instance representing the corresponding
-	 * wifi radio device or `null` if the related radio device could not be
-	 * found.
-	 */
-	getWifiDevice: function() {
-		var radioname = this.getWifiDeviceName();
-
-		if (radioname == null)
-			return Promise.reject();
-
-		return Network.prototype.getWifiDevice(radioname);
-	},
-
-	/**
-	 * Check whether the radio network is up.
-	 *
-	 * This function actually queries the up state of the related radio
-	 * device and assumes this network to be up as well when the parent
-	 * radio is up. This is due to the fact that OpenWrt does not control
-	 * virtual interfaces individually but within one common hostapd
-	 * instance.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when the network is up, else `false`.
-	 */
-	isUp: function() {
-		var device = this.getDevice();
-
-		if (device == null)
-			return false;
-
-		return device.isUp();
-	},
-
-	/**
-	 * Query the current operation mode from runtime information.
-	 *
-	 * @returns {string}
-	 * Returns the human readable mode name as reported by `ubus` runtime
-	 * state. Possible returned values are:
-	 *  - `Master`
-	 *  - `Ad-Hoc`
-	 *  - `Client`
-	 *  - `Monitor`
-	 *  - `Master (VLAN)`
-	 *  - `WDS`
-	 *  - `Mesh Point`
-	 *  - `P2P Client`
-	 *  - `P2P Go`
-	 *  - `Unknown`
-	 */
-	getActiveMode: function() {
-		var mode = this.ubus('net', 'iwinfo', 'mode') || this.ubus('net', 'config', 'mode') || this.get('mode') || 'ap';
-
-		switch (mode) {
-		case 'ap':      return 'Master';
-		case 'sta':     return 'Client';
-		case 'adhoc':   return 'Ad-Hoc';
-		case 'mesh':    return 'Mesh';
-		case 'monitor': return 'Monitor';
-		default:        return mode;
-		}
-	},
-
-	/**
-	 * Query the current operation mode from runtime information as
-	 * translated string.
-	 *
-	 * @returns {string}
-	 * Returns the translated, human readable mode name as reported by
-	 *`ubus` runtime state.
-	 */
-	getActiveModeI18n: function() {
-		var mode = this.getActiveMode();
-
-		switch (mode) {
-		case 'Master':  return _('Master');
-		case 'Client':  return _('Client');
-		case 'Ad-Hoc':  return _('Ad-Hoc');
-		case 'Mash':    return _('Mesh');
-		case 'Monitor': return _('Monitor');
-		default:        return mode;
-		}
-	},
-
-	/**
-	 * Query the current SSID from runtime information.
-	 *
-	 * @returns {string}
-	 * Returns the current SSID or Mesh ID as reported by `ubus` runtime
-	 * information.
-	 */
-	getActiveSSID: function() {
-		return this.ubus('net', 'iwinfo', 'ssid') || this.ubus('net', 'config', 'ssid') || this.get('ssid');
-	},
-
-	/**
-	 * Query the current BSSID from runtime information.
-	 *
-	 * @returns {string}
-	 * Returns the current BSSID or Mesh ID as reported by `ubus` runtime
-	 * information.
-	 */
-	getActiveBSSID: function() {
-		return this.ubus('net', 'iwinfo', 'bssid') || this.ubus('net', 'config', 'bssid') || this.get('bssid');
-	},
-
-	/**
-	 * Query the current encryption settings from runtime information.
-	 *
-	 * @returns {string}
-	 * Returns a string describing the current encryption or `-` if the the
-	 * encryption state could not be found in `ubus` runtime information.
-	 */
-	getActiveEncryption: function() {
-		return formatWifiEncryption(this.ubus('net', 'iwinfo', 'encryption')) || '-';
-	},
-
-	/**
-	 * A wireless peer entry describes the properties of a remote wireless
-	 * peer associated with a local network.
-	 *
-	 * @typedef {Object<string, boolean|number|string|LuCI.network.WifiRateEntry>} WifiPeerEntry
-	 * @memberof LuCI.network
-	 *
-	 * @property {string} mac
-	 * The MAC address (BSSID).
-	 *
-	 * @property {number} signal
-	 * The received signal strength.
-	 *
-	 * @property {number} [signal_avg]
-	 * The average signal strength if supported by the driver.
-	 *
-	 * @property {number} [noise]
-	 * The current noise floor of the radio. May be `0` or absent if not
-	 * supported by the driver.
-	 *
-	 * @property {number} inactive
-	 * The amount of milliseconds the peer has been inactive, e.g. due
-	 * to powersave.
-	 *
-	 * @property {number} connected_time
-	 * The amount of milliseconds the peer is associated to this network.
-	 *
-	 * @property {number} [thr]
-	 * The estimated throughput of the peer, May be `0` or absent if not
-	 * supported by the driver.
-	 *
-	 * @property {boolean} authorized
-	 * Specifies whether the peer is authorized to associate to this network.
-	 *
-	 * @property {boolean} authenticated
-	 * Specifies whether the peer completed authentication to this network.
-	 *
-	 * @property {string} preamble
-	 * The preamble mode used by the peer. May be `long` or `short`.
-	 *
-	 * @property {boolean} wme
-	 * Specifies whether the peer supports WME/WMM capabilities.
-	 *
-	 * @property {boolean} mfp
-	 * Specifies whether management frame protection is active.
-	 *
-	 * @property {boolean} tdls
-	 * Specifies whether TDLS is active.
-	 *
-	 * @property {number} [mesh llid]
-	 * The mesh LLID, may be `0` or absent if not applicable or supported
-	 * by the driver.
-	 *
-	 * @property {number} [mesh plid]
-	 * The mesh PLID, may be `0` or absent if not applicable or supported
-	 * by the driver.
-	 *
-	 * @property {string} [mesh plink]
-	 * The mesh peer link state description, may be an empty string (`''`)
-	 * or absent if not applicable or supported by the driver.
-	 *
-	 * The following states are known:
-	 *  - `LISTEN`
-	 *  - `OPN_SNT`
-	 *  - `OPN_RCVD`
-	 *  - `CNF_RCVD`
-	 *  - `ESTAB`
-	 *  - `HOLDING`
-	 *  - `BLOCKED`
-	 *  - `UNKNOWN`
-	 *
-	 * @property {number} [mesh local PS]
-	 * The local powersafe mode for the peer link, may be an empty
-	 * string (`''`) or absent if not applicable or supported by
-	 * the driver.
-	 *
-	 * The following modes are known:
-	 *  - `ACTIVE` (no power save)
-	 *  - `LIGHT SLEEP`
-	 *  - `DEEP SLEEP`
-	 *  - `UNKNOWN`
-	 *
-	 * @property {number} [mesh peer PS]
-	 * The remote powersafe mode for the peer link, may be an empty
-	 * string (`''`) or absent if not applicable or supported by
-	 * the driver.
-	 *
-	 * The following modes are known:
-	 *  - `ACTIVE` (no power save)
-	 *  - `LIGHT SLEEP`
-	 *  - `DEEP SLEEP`
-	 *  - `UNKNOWN`
-	 *
-	 * @property {number} [mesh non-peer PS]
-	 * The powersafe mode for all non-peer neigbours, may be an empty
-	 * string (`''`) or absent if not applicable or supported by the driver.
-	 *
-	 * The following modes are known:
-	 *  - `ACTIVE` (no power save)
-	 *  - `LIGHT SLEEP`
-	 *  - `DEEP SLEEP`
-	 *  - `UNKNOWN`
-	 *
-	 * @property {LuCI.network.WifiRateEntry} rx
-	 * Describes the receiving wireless rate from the peer.
-	 *
-	 * @property {LuCI.network.WifiRateEntry} tx
-	 * Describes the transmitting wireless rate to the peer.
-	 */
-
-	/**
-	 * A wireless rate entry describes the properties of a wireless
-	 * transmission rate to or from a peer.
-	 *
-	 * @typedef {Object<string, boolean|number>} WifiRateEntry
-	 * @memberof LuCI.network
-	 *
-	 * @property {number} [drop_misc]
-	 * The amount of received misc. packages that have been dropped, e.g.
-	 * due to corruption or missing authentication. Only applicable to
-	 * receiving rates.
-	 *
-	 * @property {number} packets
-	 * The amount of packets that have been received or sent.
-	 *
-	 * @property {number} bytes
-	 * The amount of bytes that have been received or sent.
-	 *
-	 * @property {number} [failed]
-	 * The amount of failed tranmission attempts. Only applicable to
-	 * transmit rates.
-	 *
-	 * @property {number} [retries]
-	 * The amount of retried transmissions. Only applicable to transmit
-	 * rates.
-	 *
-	 * @property {boolean} is_ht
-	 * Specifies whether this rate is an HT (IEEE 802.11n) rate.
-	 *
-	 * @property {boolean} is_vht
-	 * Specifies whether this rate is an VHT (IEEE 802.11ac) rate.
-	 *
-	 * @property {number} mhz
-	 * The channel width in MHz used for the transmission.
-	 *
-	 * @property {number} rate
-	 * The bitrate in bit/s of the transmission.
-	 *
-	 * @property {number} [mcs]
-	 * The MCS index of the used transmission rate. Only applicable to
-	 * HT or VHT rates.
-	 *
-	 * @property {number} [40mhz]
-	 * Specifies whether the tranmission rate used 40MHz wide channel.
-	 * Only applicable to HT or VHT rates.
-	 *
-	 * Note: this option exists for backwards compatibility only and its
-	 * use is discouraged. The `mhz` field should be used instead to
-	 * determine the channel width.
-	 *
-	 * @property {boolean} [short_gi]
-	 * Specifies whether a short guard interval is used for the transmission.
-	 * Only applicable to HT or VHT rates.
-	 *
-	 * @property {number} [nss]
-	 * Specifies the number of spatial streams used by the transmission.
-	 * Only applicable to VHT rates.
-	 */
-
-	/**
-	 * Fetch the list of associated peers.
-	 *
-	 * @returns {Promise<Array<LuCI.network.WifiPeerEntry>>}
-	 * Returns a promise resolving to an array of wireless peers associated
-	 * with this network.
-	 */
-	getAssocList: function() {
-		return callIwinfoAssoclist(this.getIfname());
-	},
-
-	/**
-	 * Query the current operating frequency of the wireless network.
-	 *
-	 * @returns {null|string}
-	 * Returns the current operating frequency of the network from `ubus`
-	 * runtime information in GHz or `null` if the information is not
-	 * available.
-	 */
-	getFrequency: function() {
-		var freq = this.ubus('net', 'iwinfo', 'frequency');
-
-		if (freq != null && freq > 0)
-			return '%.03f'.format(freq / 1000);
-
-		return null;
-	},
-
-	/**
-	 * Query the current average bitrate of all peers associated to this
-	 * wireless network.
-	 *
-	 * @returns {null|number}
-	 * Returns the average bit rate among all peers associated to the network
-	 * as reported by `ubus` runtime information or `null` if the information
-	 * is not available.
-	 */
-	getBitRate: function() {
-		var rate = this.ubus('net', 'iwinfo', 'bitrate');
-
-		if (rate != null && rate > 0)
-			return (rate / 1000);
-
-		return null;
-	},
-
-	/**
-	 * Query the current wireless channel.
-	 *
-	 * @returns {null|number}
-	 * Returns the wireless channel as reported by `ubus` runtime information
-	 * or `null` if it cannot be determined.
-	 */
-	getChannel: function() {
-		return this.ubus('net', 'iwinfo', 'channel') || this.ubus('dev', 'config', 'channel') || this.get('channel');
-	},
-
-	/**
-	 * Query the current wireless signal.
-	 *
-	 * @returns {null|number}
-	 * Returns the wireless signal in dBm as reported by `ubus` runtime
-	 * information or `null` if it cannot be determined.
-	 */
-	getSignal: function() {
-		return this.ubus('net', 'iwinfo', 'signal') || 0;
-	},
-
-	/**
-	 * Query the current radio noise floor.
-	 *
-	 * @returns {number}
-	 * Returns the radio noise floor in dBm as reported by `ubus` runtime
-	 * information or `0` if it cannot be determined.
-	 */
-	getNoise: function() {
-		return this.ubus('net', 'iwinfo', 'noise') || 0;
-	},
-
-	/**
-	 * Query the current country code.
-	 *
-	 * @returns {string}
-	 * Returns the wireless country code as reported by `ubus` runtime
-	 * information or `00` if it cannot be determined.
-	 */
-	getCountryCode: function() {
-		return this.ubus('net', 'iwinfo', 'country') || this.ubus('dev', 'config', 'country') || '00';
-	},
-
-	/**
-	 * Query the current radio TX power.
-	 *
-	 * @returns {null|number}
-	 * Returns the wireless network transmit power in dBm as reported by
-	 * `ubus` runtime information or `null` if it cannot be determined.
-	 */
-	getTXPower: function() {
-		return this.ubus('net', 'iwinfo', 'txpower');
-	},
-
-	/**
-	 * Query the radio TX power offset.
-	 *
-	 * Some wireless radios have a fixed power offset, e.g. due to the
-	 * use of external amplifiers.
-	 *
-	 * @returns {number}
-	 * Returns the wireless network transmit power offset in dBm as reported
-	 * by `ubus` runtime information or `0` if there is no offset, or if it
-	 * cannot be determined.
-	 */
-	getTXPowerOffset: function() {
-		return this.ubus('net', 'iwinfo', 'txpower_offset') || 0;
-	},
-
-	/**
-	 * Calculate the current signal.
-	 *
-	 * @deprecated
-	 * @returns {number}
-	 * Returns the calculated signal level, which is the difference between
-	 * noise and signal (SNR), divided by 5.
-	 */
-	getSignalLevel: function(signal, noise) {
-		if (this.getActiveBSSID() == '00:00:00:00:00:00')
-			return -1;
-
-		signal = signal || this.getSignal();
-		noise  = noise  || this.getNoise();
-
-		if (signal < 0 && noise < 0) {
-			var snr = -1 * (noise - signal);
-			return Math.floor(snr / 5);
-		}
-
-		return 0;
-	},
-
-	/**
-	 * Calculate the current signal quality percentage.
-	 *
-	 * @returns {number}
-	 * Returns the calculated signal quality in percent. The value is
-	 * calculated from the `quality` and `quality_max` indicators reported
-	 * by `ubus` runtime state.
-	 */
-	getSignalPercent: function() {
-		var qc = this.ubus('net', 'iwinfo', 'quality') || 0,
-		    qm = this.ubus('net', 'iwinfo', 'quality_max') || 0;
-
-		if (qc > 0 && qm > 0)
-			return Math.floor((100 / qm) * qc);
-
-		return 0;
-	},
-
-	/**
-	 * Get a short description string for this wireless network.
-	 *
-	 * @returns {string}
-	 * Returns a string describing this network, consisting of the
-	 * active operation mode, followed by either the SSID, BSSID or
-	 * internal network ID, depending on which information is available.
-	 */
-	getShortName: function() {
-		return '%s "%s"'.format(
-			this.getActiveModeI18n(),
-			this.getActiveSSID() || this.getActiveBSSID() || this.getID());
-	},
-
-	/**
-	 * Get a description string for this wireless network.
-	 *
-	 * @returns {string}
-	 * Returns a string describing this network, consisting of the
-	 * term `Wireless Network`, followed by the active operation mode,
-	 * the SSID, BSSID or internal network ID and the Linux network device
-	 * name, depending on which information is available.
-	 */
-	getI18n: function() {
-		return '%s: %s "%s" (%s)'.format(
-			_('Wireless Network'),
-			this.getActiveModeI18n(),
-			this.getActiveSSID() || this.getActiveBSSID() || this.getID(),
-			this.getIfname());
-	},
-
-	/**
-	 * Get the primary logical interface this wireless network is attached to.
-	 *
-	 * @returns {null|LuCI.network.Protocol}
-	 * Returns a `Network.Protocol` instance representing the logical
-	 * interface or `null` if this network is not attached to any logical
-	 * interface.
-	 */
-	getNetwork: function() {
-		return this.getNetworks()[0];
-	},
-
-	/**
-	 * Get the logical interfaces this wireless network is attached to.
-	 *
-	 * @returns {Array<LuCI.network.Protocol>}
-	 * Returns an array of `Network.Protocol` instances representing the
-	 * logical interfaces this wireless network is attached to.
-	 */
-	getNetworks: function() {
-		var networkNames = this.getNetworkNames(),
-		    networks = [];
-
-		for (var i = 0; i < networkNames.length; i++) {
-			var uciInterface = uci.get('network', networkNames[i]);
-
-			if (uciInterface == null || uciInterface['.type'] != 'interface')
-				continue;
-
-			networks.push(Network.prototype.instantiateNetwork(networkNames[i]));
-		}
-
-		networks.sort(networkSort);
-
-		return networks;
-	},
-
-	/**
-	 * Get the associated Linux network device.
-	 *
-	 * @returns {LuCI.network.Device}
-	 * Returns a `Network.Device` instance representing the Linux network
-	 * device associted with this wireless network.
-	 */
-	getDevice: function() {
-		return Network.prototype.instantiateDevice(this.getIfname());
-	},
-
-	/**
-	 * Check whether this wifi network supports deauthenticating clients.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` when this wifi network instance supports forcibly
-	 * deauthenticating clients, otherwise `false`.
-	 */
-	isClientDisconnectSupported: function() {
-		return L.isObject(this.ubus('hostapd', 'del_client'));
-	},
-
-	/**
-	 * Forcibly disconnect the given client from the wireless network.
-	 *
-	 * @param {string} mac
-	 * The MAC address of the client to disconnect.
-	 *
-	 * @param {boolean} [deauth=false]
-	 * Specifies whether to deauthenticate (`true`) or disassociate (`false`)
-	 * the client.
-	 *
-	 * @param {number} [reason=1]
-	 * Specifies the IEEE 802.11 reason code to disassoc/deauth the client
-	 * with. Default is `1` which corresponds to `Unspecified reason`.
-	 *
-	 * @param {number} [ban_time=0]
-	 * Specifies the amount of milliseconds to ban the client from
-	 * reconnecting. By default, no ban time is set which allows the client
-	 * to reassociate / reauthenticate immediately.
-	 *
-	 * @returns {Promise<number>}
-	 * Returns a promise resolving to the underlying ubus call result code
-	 * which is typically `0`, even for not existing MAC addresses.
-	 * The promise might reject with an error in case invalid arguments
-	 * are passed.
-	 */
-	disconnectClient: function(mac, deauth, reason, ban_time) {
-		if (reason == null || reason == 0)
-			reason = 1;
-
-		if (ban_time == 0)
-			ban_time = null;
-
-		return rpc.declare({
-			object: 'hostapd.%s'.format(this.getIfname()),
-			method: 'del_client',
-			params: [ 'addr', 'deauth', 'reason', 'ban_time' ]
-		})(mac, deauth, reason, ban_time);
-	}
-});
-
-return Network;
-
-
-
- - - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - diff --git a/docs/jsapi/rpc.js.html b/docs/jsapi/rpc.js.html deleted file mode 100644 index 6668e4635a..0000000000 --- a/docs/jsapi/rpc.js.html +++ /dev/null @@ -1,3944 +0,0 @@ - - - - - Source: rpc.js - - - - - - - - - - - - - - - - - -
- - -
-

Source: rpc.js

- - - - -
-
-
'use strict';
-'require baseclass';
-'require request';
-
-var rpcRequestID = 1,
-    rpcSessionID = L.env.sessionid || '00000000000000000000000000000000',
-    rpcBaseURL = L.url('admin/ubus'),
-    rpcInterceptorFns = [];
-
-/**
- * @class rpc
- * @memberof LuCI
- * @hideconstructor
- * @classdesc
- *
- * The `LuCI.rpc` class provides high level ubus JSON-RPC abstractions
- * and means for listing and invoking remove RPC methods.
- */
-return baseclass.extend(/** @lends LuCI.rpc.prototype */ {
-	/* privates */
-	call: function(req, cb, nobatch) {
-		var q = '';
-
-		if (Array.isArray(req)) {
-			if (req.length == 0)
-				return Promise.resolve([]);
-
-			for (var i = 0; i < req.length; i++)
-				if (req[i].params)
-					q += '%s%s.%s'.format(
-						q ? ';' : '/',
-						req[i].params[1],
-						req[i].params[2]
-					);
-		}
-		else if (req.params) {
-			q += '/%s.%s'.format(req.params[1], req.params[2]);
-		}
-
-		return request.post(rpcBaseURL + q, req, {
-			timeout: (L.env.rpctimeout || 20) * 1000,
-			nobatch: nobatch,
-			credentials: true
-		}).then(cb, cb);
-	},
-
-	parseCallReply: function(req, res) {
-		var msg = null;
-
-		if (res instanceof Error)
-			return req.reject(res);
-
-		try {
-			if (!res.ok)
-				L.raise('RPCError', 'RPC call to %s/%s failed with HTTP error %d: %s',
-					req.object, req.method, res.status, res.statusText || '?');
-
-			msg = res.json();
-		}
-		catch (e) {
-			return req.reject(e);
-		}
-
-		/*
-		 * The interceptor args are intentionally swapped.
-		 * Response is passed as first arg to align with Request class interceptors
-		 */
-		Promise.all(rpcInterceptorFns.map(function(fn) { return fn(msg, req) }))
-			.then(this.handleCallReply.bind(this, req, msg))
-			.catch(req.reject);
-	},
-
-	handleCallReply: function(req, msg) {
-		var type = Object.prototype.toString,
-		    ret = null;
-
-		try {
-			/* verify message frame */
-			if (!L.isObject(msg) || msg.jsonrpc != '2.0')
-				L.raise('RPCError', 'RPC call to %s/%s returned invalid message frame',
-					req.object, req.method);
-
-			/* check error condition */
-			if (L.isObject(msg.error) && msg.error.code && msg.error.message)
-				L.raise('RPCError', 'RPC call to %s/%s failed with error %d: %s',
-					req.object, req.method, msg.error.code, msg.error.message || '?');
-		}
-		catch (e) {
-			return req.reject(e);
-		}
-
-		if (!req.object && !req.method) {
-			ret = msg.result;
-		}
-		else if (Array.isArray(msg.result)) {
-			if (req.raise && msg.result[0] !== 0)
-				L.raise('RPCError', 'RPC call to %s/%s failed with ubus code %d: %s',
-					req.object, req.method, msg.result[0], this.getStatusText(msg.result[0]));
-
-			ret = (msg.result.length > 1) ? msg.result[1] : msg.result[0];
-		}
-
-		if (req.expect) {
-			for (var key in req.expect) {
-				if (ret != null && key != '')
-					ret = ret[key];
-
-				if (ret == null || type.call(ret) != type.call(req.expect[key]))
-					ret = req.expect[key];
-
-				break;
-			}
-		}
-
-		/* apply filter */
-		if (typeof(req.filter) == 'function') {
-			req.priv[0] = ret;
-			req.priv[1] = req.params;
-			ret = req.filter.apply(this, req.priv);
-		}
-
-		req.resolve(ret);
-	},
-
-	/**
-	 * Lists available remote ubus objects or the method signatures of
-	 * specific objects.
-	 *
-	 * This function has two signatures and is sensitive to the number of
-	 * arguments passed to it:
-	 *  - `list()` -
-	 *    Returns an array containing the names of all remote `ubus` objects
-	 *  - `list("objname", ...)`
-	 *    Returns method signatures for each given `ubus` object name.
-	 *
-	 * @param {...string} [objectNames]
-	 * If any object names are given, this function will return the method
-	 * signatures of each given object.
-	 *
-	 * @returns {Promise<Array<string>|Object<string, Object<string, Object<string, string>>>>}
-	 * When invoked without arguments, this function will return a promise
-	 * resolving to an array of `ubus` object names. When invoked with one or
-	 * more arguments, a promise resolving to an object describing the method
-	 * signatures of each requested `ubus` object name will be returned.
-	 */
-	list: function() {
-		var msg = {
-			jsonrpc: '2.0',
-			id:      rpcRequestID++,
-			method:  'list',
-			params:  arguments.length ? this.varargs(arguments) : undefined
-		};
-
-		return new Promise(L.bind(function(resolveFn, rejectFn) {
-			/* store request info */
-			var req = {
-				resolve: resolveFn,
-				reject:  rejectFn
-			};
-
-			/* call rpc */
-			this.call(msg, this.parseCallReply.bind(this, req));
-		}, this));
-	},
-
-	/**
-	 * @typedef {Object} DeclareOptions
-	 * @memberof LuCI.rpc
-	 *
-	 * @property {string} object
-	 * The name of the remote `ubus` object to invoke.
-	 *
-	 * @property {string} method
-	 * The name of the remote `ubus` method to invoke.
-	 *
-	 * @property {string[]} [params]
-	 * Lists the named parameters expected by the remote `ubus` RPC method.
-	 * The arguments passed to the resulting generated method call function
-	 * will be mapped to named parameters in the order they appear in this
-	 * array.
-	 *
-	 * Extraneous parameters passed to the generated function will not be
-	 * sent to the remote procedure but are passed to the
-	 * {@link LuCI.rpc~filterFn filter function} if one is specified.
-	 *
-	 * Examples:
-	 *  - `params: [ "foo", "bar" ]` -
-	 *    When the resulting call function is invoked with `fn(true, false)`,
-	 *    the corresponding args object sent to the remote procedure will be
-	 *    `{ foo: true, bar: false }`.
-	 *  - `params: [ "test" ], filter: function(reply, args, extra) { ... }` -
-	 *    When the resultung generated function is invoked with
-	 *    `fn("foo", "bar", "baz")` then `{ "test": "foo" }` will be sent as
-	 *    argument to the remote procedure and the filter function will be
-	 *    invoked with `filterFn(reply, [ "foo" ], "bar", "baz")`
-	 *
-	 * @property {Object<string,*>} [expect]
-	 * Describes the expected return data structure. The given object is
-	 * supposed to contain a single key selecting the value to use from
-	 * the returned `ubus` reply object. The value of the sole key within
-	 * the `expect` object is used to infer the expected type of the received
-	 * `ubus` reply data.
-	 *
-	 * If the received data does not contain `expect`'s key, or if the
-	 * type of the data differs from the type of the value in the expect
-	 * object, the expect object's value is returned as default instead.
-	 *
-	 * The key in the `expect` object may be an empty string (`''`) in which
-	 * case the entire reply object is selected instead of one of its subkeys.
-	 *
-	 * If the `expect` option is omitted, the received reply will be returned
-	 * as-is, regardless of its format or type.
-	 *
-	 * Examples:
-	 *  - `expect: { '': { error: 'Invalid response' } }` -
-	 *    This requires the entire `ubus` reply to be a plain JavaScript
-	 *    object. If the reply isn't an object but e.g. an array or a numeric
-	 *    error code instead, it will get replaced with
-	 *    `{ error: 'Invalid response' }` instead.
-	 *  - `expect: { results: [] }` -
-	 *    This requires the received `ubus` reply to be an object containing
-	 *    a key `results` with an array as value. If the received reply does
-	 *    not contain such a key, or if `reply.results` points to a non-array
-	 *    value, the empty array (`[]`) will be used instead.
-	 *  - `expect: { success: false }` -
-	 *    This requires the received `ubus` reply to be an object containing
-	 *    a key `success` with a boolean value. If the reply does not contain
-	 *    `success` or if `reply.success` is not a boolean value, `false` will
-	 *    be returned as default instead.
-	 *
-	 * @property {LuCI.rpc~filterFn} [filter]
-	 * Specfies an optional filter function which is invoked to transform the
-	 * received reply data before it is returned to the caller.
-	 *
-	 * @property {boolean} [reject=false]
-	 * If set to `true`, non-zero ubus call status codes are treated as fatal
-	 * error and lead to the rejection of the call promise. The default
-	 * behaviour is to resolve with the call return code value instead.
-	 */
-
-	/**
-	 * The filter function is invoked to transform a received `ubus` RPC call
-	 * reply before returning it to the caller.
-	 *
-	 * @callback LuCI.rpc~filterFn
-	 *
-	 * @param {*} data
-	 * The received `ubus` reply data or a subset of it as described in the
-	 * `expect` option of the RPC call declaration. In case of remote call
-	 * errors, `data` is numeric `ubus` error code instead.
-	 *
-	 * @param {Array<*>} args
-	 * The arguments the RPC method has been invoked with.
-	 *
-	 * @param {...*} extraArgs
-	 * All extraneous arguments passed to the RPC method exceeding the number
-	 * of arguments describes in the RPC call declaration.
-	 *
-	 * @return {*}
-	 * The return value of the filter function will be returned to the caller
-	 * of the RPC method as-is.
-	 */
-
-	/**
-	 * The generated invocation function is returned by
-	 * {@link LuCI.rpc#declare rpc.declare()} and encapsulates a single
-	 * RPC method call.
-	 *
-	 * Calling this function will execute a remote `ubus` HTTP call request
-	 * using the arguments passed to it as arguments and return a promise
-	 * resolving to the received reply values.
-	 *
-	 * @callback LuCI.rpc~invokeFn
-	 *
-	 * @param {...*} params
-	 * The parameters to pass to the remote procedure call. The given
-	 * positional arguments will be named to named RPC parameters according
-	 * to the names specified in the `params` array of the method declaration.
-	 *
-	 * Any additional parameters exceeding the amount of arguments in the
-	 * `params` declaration are passed as private extra arguments to the
-	 * declared filter function.
-	 *
-	 * @return {Promise<*>}
-	 * Returns a promise resolving to the result data of the remote `ubus`
-	 * RPC method invocation, optionally substituted and filtered according
-	 * to the `expect` and `filter` declarations.
-	 */
-
-	/**
-	 * Describes a remote RPC call procedure and returns a function
-	 * implementing it.
-	 *
-	 * @param {LuCI.rpc.DeclareOptions} options
-	 * If any object names are given, this function will return the method
-	 * signatures of each given object.
-	 *
-	 * @returns {LuCI.rpc~invokeFn}
-	 * Returns a new function implementing the method call described in
-	 * `options`.
-	 */
-	declare: function(options) {
-		return Function.prototype.bind.call(function(rpc, options) {
-			var args = this.varargs(arguments, 2);
-			return new Promise(function(resolveFn, rejectFn) {
-				/* build parameter object */
-				var p_off = 0;
-				var params = { };
-				if (Array.isArray(options.params))
-					for (p_off = 0; p_off < options.params.length; p_off++)
-						params[options.params[p_off]] = args[p_off];
-
-				/* all remaining arguments are private args */
-				var priv = [ undefined, undefined ];
-				for (; p_off < args.length; p_off++)
-					priv.push(args[p_off]);
-
-				/* store request info */
-				var req = {
-					expect:  options.expect,
-					filter:  options.filter,
-					resolve: resolveFn,
-					reject:  rejectFn,
-					params:  params,
-					priv:    priv,
-					object:  options.object,
-					method:  options.method,
-					raise:   options.reject
-				};
-
-				/* build message object */
-				var msg = {
-					jsonrpc: '2.0',
-					id:      rpcRequestID++,
-					method:  'call',
-					params:  [
-						rpcSessionID,
-						options.object,
-						options.method,
-						params
-					]
-				};
-
-				/* call rpc */
-				rpc.call(msg, rpc.parseCallReply.bind(rpc, req), options.nobatch);
-			});
-		}, this, this, options);
-	},
-
-	/**
-	 * Returns the current RPC session id.
-	 *
-	 * @returns {string}
-	 * Returns the 32 byte session ID string used for authenticating remote
-	 * requests.
-	 */
-	getSessionID: function() {
-		return rpcSessionID;
-	},
-
-	/**
-	 * Set the RPC session id to use.
-	 *
-	 * @param {string} sid
-	 * Sets the 32 byte session ID string used for authenticating remote
-	 * requests.
-	 */
-	setSessionID: function(sid) {
-		rpcSessionID = sid;
-	},
-
-	/**
-	 * Returns the current RPC base URL.
-	 *
-	 * @returns {string}
-	 * Returns the RPC URL endpoint to issue requests against.
-	 */
-	getBaseURL: function() {
-		return rpcBaseURL;
-	},
-
-	/**
-	 * Set the RPC base URL to use.
-	 *
-	 * @param {string} sid
-	 * Sets the RPC URL endpoint to issue requests against.
-	 */
-	setBaseURL: function(url) {
-		rpcBaseURL = url;
-	},
-
-	/**
-	 * Translates a numeric `ubus` error code into a human readable
-	 * description.
-	 *
-	 * @param {number} statusCode
-	 * The numeric status code.
-	 *
-	 * @returns {string}
-	 * Returns the textual description of the code.
-	 */
-	getStatusText: function(statusCode) {
-		switch (statusCode) {
-		case 0: return _('Command OK');
-		case 1: return _('Invalid command');
-		case 2: return _('Invalid argument');
-		case 3: return _('Method not found');
-		case 4: return _('Resource not found');
-		case 5: return _('No data received');
-		case 6: return _('Permission denied');
-		case 7: return _('Request timeout');
-		case 8: return _('Not supported');
-		case 9: return _('Unspecified error');
-		case 10: return _('Connection lost');
-		default: return _('Unknown error code');
-		}
-	},
-
-	/**
-	 * Registered interceptor functions are invoked before the standard reply
-	 * parsing and handling logic.
-	 *
-	 * By returning rejected promises, interceptor functions can cause the
-	 * invocation function to fail, regardless of the received reply.
-	 *
-	 * Interceptors may also modify their message argument in-place to
-	 * rewrite received replies before they're processed by the standard
-	 * response handling code.
-	 *
-	 * A common use case for such functions is to detect failing RPC replies
-	 * due to expired authentication in order to trigger a new login.
-	 *
-	 * @callback LuCI.rpc~interceptorFn
-	 *
-	 * @param {*} msg
-	 * The unprocessed, JSON decoded remote RPC method call reply.
-	 *
-	 * Since interceptors run before the standard parsing logic, the reply
-	 * data is not verified for correctness or filtered according to
-	 * `expect` and `filter` specifications in the declarations.
-	 *
-	 * @param {Object} req
-	 * The related request object which is an extended variant of the
-	 * declaration object, allowing access to internals of the invocation
-	 * function such as `filter`, `expect` or `params` values.
-	 *
-	 * @return {Promise<*>|*}
-	 * Interceptor functions may return a promise to defer response
-	 * processing until some delayed work completed. Any values the returned
-	 * promise resolves to are ignored.
-	 *
-	 * When the returned promise rejects with an error, the invocation
-	 * function will fail too, forwarding the error to the caller.
-	 */
-
-	/**
-	 * Registers a new interceptor function.
-	 *
-	 * @param {LuCI.rpc~interceptorFn} interceptorFn
-	 * The inteceptor function to register.
-	 *
-	 * @returns {LuCI.rpc~interceptorFn}
-	 * Returns the given function value.
-	 */
-	addInterceptor: function(interceptorFn) {
-		if (typeof(interceptorFn) == 'function')
-			rpcInterceptorFns.push(interceptorFn);
-		return interceptorFn;
-	},
-
-	/**
-	 * Removes a registered interceptor function.
-	 *
-	 * @param {LuCI.rpc~interceptorFn} interceptorFn
-	 * The inteceptor function to remove.
-	 *
-	 * @returns {boolean}
-	 * Returns `true` if the given function has been removed or `false`
-	 * if it has not been found.
-	 */
-	removeInterceptor: function(interceptorFn) {
-		var oldlen = rpcInterceptorFns.length, i = oldlen;
-		while (i--)
-			if (rpcInterceptorFns[i] === interceptorFn)
-				rpcInterceptorFns.splice(i, 1);
-		return (rpcInterceptorFns.length < oldlen);
-	}
-});
-
-
-
- - - - - - - - -
- Documentation generated by JSDoc 3.6.3 on Thu Aug 06 2020 17:58:02 GMT+0200 (Central European Summer Time) -
-
-
- - - - diff --git a/docs/jsapi/scripts/bootstrap.min.js b/docs/jsapi/scripts/bootstrap.min.js deleted file mode 100644 index 1a6258efcb..0000000000 --- a/docs/jsapi/scripts/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.0.3 (http://getbootstrap.com) - * Copyright 2013 Twitter, Inc. - * Licensed under http://www.apache.org/licenses/LICENSE-2.0 - */ - -if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]'),b=!0;if(a.length){var c=this.$element.find("input");"radio"===c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?b=!1:a.find(".active").removeClass("active")),b&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}b&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); \ No newline at end of file diff --git a/docs/jsapi/scripts/jaguar.js b/docs/jsapi/scripts/jaguar.js deleted file mode 100644 index 466e2c4058..0000000000 --- a/docs/jsapi/scripts/jaguar.js +++ /dev/null @@ -1 +0,0 @@ -(function(){var e=0;var t;var n=document.getElementById("source-code");if(n){var i=config.linenums;if(i){n=n.getElementsByTagName("ol")[0];t=Array.prototype.slice.apply(n.children);t=t.map(function(t){e++;t.id="line"+e})}else{n=n.getElementsByTagName("code")[0];t=n.innerHTML.split("\n");t=t.map(function(t){e++;return''+t});n.innerHTML=t.join("\n")}}})();$(function(){$("#search").on("keyup",function(e){var t=$(this).val();var n=$(".navigation");if(t){var i=new RegExp(t,"i");n.find("li, .itemMembers").hide();n.find("li").each(function(e,t){var n=$(t);if(n.data("name")&&i.test(n.data("name"))){n.show();n.closest(".itemMembers").show();n.closest(".item").show()}})}else{n.find(".item, .itemMembers").show()}n.find(".list").scrollTop(0)});$(".navigation").on("click",".title",function(e){$(this).parent().find(".itemMembers").toggle()});var e=$(".page-title").data("filename").replace(/\.[a-z]+$/,"");var t=$('.navigation .item[data-name*="'+e+'"]:eq(0)');if(t.length){t.remove().prependTo(".navigation .list").show().find(".itemMembers").show()}var n=function(){var e=$(window).height();var t=$(".navigation");t.height(e).find(".list").height(e-133)};$(window).on("resize",n);n();if(config.disqus){$(window).on("load",function(){var e=config.disqus;var t=document.createElement("script");t.type="text/javascript";t.async=true;t.src="http://"+e+".disqus.com/embed.js";(document.getElementsByTagName("head")[0]||document.getElementsByTagName("body")[0]).appendChild(t);var n=document.createElement("script");n.async=true;n.type="text/javascript";n.src="http://"+e+".disqus.com/count.js";document.getElementsByTagName("BODY")[0].appendChild(n)})}}); \ No newline at end of file diff --git a/docs/jsapi/scripts/jquery.min.js b/docs/jsapi/scripts/jquery.min.js deleted file mode 100644 index 9a85bd3462..0000000000 --- a/docs/jsapi/scripts/jquery.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! jQuery v2.0.3 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license -//@ sourceMappingURL=jquery.min.map -*/ -(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t) -};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("

)CdQ3F!eKyF|9D2V!F-rhUpJ8J+l7g0OBBVM#THTI&O8)>EGR%u6Gd9D9pm5!S}%&6DxW}^f|7=Y zPoO3(pTZY#?(7(|!5}5Nn!D%DotZmlW)?smSMcEE<^aT$6gw#LlwubPI9BYTffL0! zyu-EPCnz{Y#ZR&1d{F!hr_NW!&#~mXis$jseXDo@U)-kR7sMBeUt-T&RQw9By@BF9 z3f?cpmw4m-R{RHncaC**(V--ipJ<~6LkW2fi6RVfh%vcYt9@z>&M0LBSf-Q|Et8wU zCt43_*JB)mHR71wb`K@~5Cizwp{`A2uuJ^_Bcl3k{7ree$8&@l?;^2nagS+NqCDBfkB?pJws=PbK~+A7|2 z{gCDJKI-i%m4LD$n{WIwWR|c+NRy`C1#)1sSBI7FiH6z-QkhY&Q_|%I3exQ zQ`X1M?cZH4^M&BSyr;2z$+^SZUMA*0001Z+HKHROw(}?!13=vX`$@Br+fGR zZ%e`5O6%Txi$Yrz0gF{}p>fY>OnlS0Uevf}oDXW;D{d2gcE<2)oFcV80@g$H)63L{HN*d{8kVzKVW(;E)$9N_%kx5Ku3R9WJbY?JW^G#k0Wdx>E$NBBVtKRLiL?sA*s%w`TdsNz1=+~FRNdB8&+@iBD0 zXFTC4C-8-Cwv(4U=LLQ~^Oa4^rG|OTr5?ItoaPMYxxh`%a*kVU z;HYGAjq6;IY{`*awo0DlOMw(hkrYdb(O28l;MYvSx*ChcQW4f^QL5UdE3HbqvbxB$pfSg`>Cj#;?~00;nMAg}==M6d%RaIhCe zARtS)01i=0um)3FSgr#ump{<1pq_<0a34Kp8x=7I1^|9 diff --git a/docs/jsapi/fonts/OpenSans-Regular-webfont.eot b/docs/jsapi/fonts/OpenSans-Regular-webfont.eot deleted file mode 100644 index 6bbc3cf58cb011a6b4bf3cb1612ce212608f7274..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19836 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/jsapi/fonts/OpenSans-Regular-webfont.woff b/docs/jsapi/fonts/OpenSans-Regular-webfont.woff deleted file mode 100644 index e231183dce4c7b452afc9e7799586fd285e146f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22660 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 ML;wL%uV=LY00kR;TmS$7 diff --git a/docs/jsapi/fonts/glyphicons-halflings-regular.eot b/docs/jsapi/fonts/glyphicons-halflings-regular.eot deleted file mode 100644 index 423bd5d3a20b804f596e04e5cd02fb4f16cfcbc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20290 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/jsapi/fonts/glyphicons-halflings-regular.ttf b/docs/jsapi/fonts/glyphicons-halflings-regular.ttf deleted file mode 100644 index a498ef4e7c8b556fc36f580c5ff524025bb11c84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41236 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 - - - - Source: form.js - - - - - - - - - - - - - - - - - -