From: Jo-Philipp Wich Date: Tue, 5 Nov 2019 08:33:40 +0000 (+0100) Subject: documentation: add JS api docs X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=3942789dc62d6a0e7fcfb0a935bfe5c8d372245b;p=oweals%2Fluci.git documentation: add JS api docs Signed-off-by: Jo-Philipp Wich (cherry picked from commit d9452d1157aef6b8752fac0f4ed1e0b9221abb31) --- diff --git a/documentation/jsapi/LuCI.Class.html b/documentation/jsapi/LuCI.Class.html new file mode 100644 index 000000000..7b5c3a8f7 --- /dev/null +++ b/documentation/jsapi/LuCI.Class.html @@ -0,0 +1,1409 @@ + + + + + JSDoc: Class: Class + + + + + + + + + + +
+ +

Class: Class

+ + + + + + +
+ +
+ +

+ LuCI.Class

+ +

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

+

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

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

(static) extend(properties) → {LuCI.Class}

+ + + + + + +
+

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

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
properties + + +Object.<string, *> + + + +

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

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a new LuCI.Class 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.

+
+ + + +
+
+ Type +
+
+ +LuCI.Class + + +
+
+ + + + + + + + + + + + + +

(static) instantiate(params, …new_argsopt) → {LuCI.Class}

+ + + + + + +
+

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

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a new LuCI.Class instance extended by the given +properties with its prototype set to this base class to +enable inheritance.

+
+ + + +
+
+ Type +
+
+ +LuCI.Class + + +
+
+ + + + + + + + + + + + + +

(static) isSubclass(classValue) → {boolean}

+ + + + + + +
+

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

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
classValue + + +LuCI.Class + + + +

The class object to test.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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'.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

(static) singleton(properties, …new_argsopt) → {LuCI.Class}

+ + + + + + +
+

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a new LuCI.Class instance extended by the given +properties with its prototype set to this base class to +enable inheritance.

+
+ + + +
+
+ Type +
+
+ +LuCI.Class + + +
+
+ + + + + + + + + + + + + +

super(key, callArgsopt) → {*|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.
  • +
+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+

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

+
+
+
+
+
+
+ Type +
+
+ +ReferenceError + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +* +| + +null + + +
+
+ + + + + + + + + + + + + +

varargs(args, offset, …extra_argsopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a new array consisting of the optional extra arguments +and the values extracted from the args array beginning with +offset.

+
+ + + +
+
+ Type +
+
+ +Array.<*> + + +
+
+ + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Headers.html b/documentation/jsapi/LuCI.Headers.html new file mode 100644 index 000000000..a63017bcf --- /dev/null +++ b/documentation/jsapi/LuCI.Headers.html @@ -0,0 +1,489 @@ + + + + + JSDoc: Class: Headers + + + + + + + + + + +
+ +

Class: Headers

+ + + + + + +
+ +
+ +

+ LuCI.Headers

+ +

The Headers class is an internal utility class exposed in HTTP +response objects using the response.headers property.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

get(name) → {string|null}

+ + + + + + +
+

Returns the value of the given header name. +Note: Header-Names are case-insensitive.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + +

The header name to read

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

The value of the given header name or null if the header isn't present.

+
+ + + +
+
+ Type +
+
+ +string +| + +null + + +
+
+ + + + + + + + + + + + + +

has(name) → {boolean}

+ + + + + + +
+

Checks whether the given header name is present. +Note: Header-Names are case-insensitive.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + +

The header name to check

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if the header name is present, false otherwise

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Network.Device.html b/documentation/jsapi/LuCI.Network.Device.html new file mode 100644 index 000000000..0236f8c50 --- /dev/null +++ b/documentation/jsapi/LuCI.Network.Device.html @@ -0,0 +1,2626 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

getBridgeID() → {null|string}

+ + + + + + +
+

Get the bridge ID

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the ID of this network bridge or null if this network +device is not a Linux bridge.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getBridgeSTP() → {boolean}

+ + + + + + +
+

Get the bridge STP setting

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when this device is a Linux bridge and has stp +enabled, else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

getI18n() → {string}

+ + + + + + +
+

Get a long description string for the device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a string containing the type description and device name +for non-wifi devices or operation mode and ssid for wifi ones.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getIP6Addrs() → {Array.<string>}

+ + + + + + +
+

Get the IPv6 addresses configured on the device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array of IPv6 address strings.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getIPAddrs() → {Array.<string>}

+ + + + + + +
+

Get the IPv4 addresses configured on the device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array of IPv4 address strings.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getMAC() → {null|string}

+ + + + + + +
+

Get the MAC address of the device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the MAC address of the device or null if not applicable, +e.g. for non-ethernet tunnel devices.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getMTU() → {number}

+ + + + + + +
+

Get the MTU of the device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the MTU of the device.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getName() → {string}

+ + + + + + +
+

Get the name of the network device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the name of the device, e.g. eth0 or wlan0.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getNetwork() → {null|LuCI.Network.Protocol}

+ + + + + + +
+

Get the primary logical interface this device is assigned to.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +LuCI.Network.Protocol + + +
+
+ + + + + + + + + + + + + +

getNetworks() → {Array.<LuCI.Network.Protocol>}

+ + + + + + +
+

Get the logical interfaces this device is assigned to.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array of Network.Protocol instances representing the +logical interfaces this device is assigned to.

+
+ + + +
+
+ Type +
+
+ +Array.<LuCI.Network.Protocol> + + +
+
+ + + + + + + + + + + + + +

getPorts() → {null|Array.<LuCI.Network.Device>}

+ + + + + + +
+

Get the associated bridge ports of the device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +Array.<LuCI.Network.Device> + + +
+
+ + + + + + + + + + + + + +

getRXBytes() → {number}

+ + + + + + +
+

Get the amount of received bytes.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the amount of bytes received by the network device.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getRXPackets() → {number}

+ + + + + + +
+

Get the amount of received packets.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the amount of packets received by the network device.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getShortName() → {string}

+ + + + + + +
+

Get a short description string for the device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the device name for non-wifi devices or a string containing +the operation mode and SSID for wifi devices.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getTXBytes() → {number}

+ + + + + + +
+

Get the amount of transmitted bytes.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the amount of bytes transmitted by the network device.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getTXPackets() → {number}

+ + + + + + +
+

Get the amount of transmitted packets.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the amount of packets transmitted by the network device.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getType() → {string}

+ + + + + + +
+

Get the type of the device..

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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
  • +
+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getTypeI18n() → {string}

+ + + + + + +
+

Get a string describing the device type.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a string describing the type, e.g. "Wireless Adapter" or +"Bridge".

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getWifiNetwork() → {null|LuCI.Network.WifiNetwork}

+ + + + + + +
+

Get the related wireless network this device is related to.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a Network.WifiNetwork instance representing the wireless +network corresponding to this network device or null if this device +is not a wireless device.

+
+ + + +
+
+ Type +
+
+ +null +| + +LuCI.Network.WifiNetwork + + +
+
+ + + + + + + + + + + + + +

isBridge() → {boolean}

+ + + + + + +
+

Checks whether this device is a Linux bridge.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when the network device is present and a Linux bridge, +else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

isBridgePort() → {boolean}

+ + + + + + +
+

Checks whether this device is part of a Linux bridge.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when this network device is part of a bridge, +else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

isUp() → {boolean}

+ + + + + + +
+

Checks whether this device is up.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when the associated device is running pr false +when it is down or absent.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Network.Hosts.html b/documentation/jsapi/LuCI.Network.Hosts.html new file mode 100644 index 000000000..f98641bb7 --- /dev/null +++ b/documentation/jsapi/LuCI.Network.Hosts.html @@ -0,0 +1,1504 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

getHostnameByIP6Addr(ipaddr) → {null|string}

+ + + + + + +
+

Lookup the hostname associated with the given IPv6 address.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
ipaddr + + +string + + + +

The IPv6 address to lookup.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getHostnameByIPAddr(ipaddr) → {null|string}

+ + + + + + +
+

Lookup the hostname associated with the given IPv4 address.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
ipaddr + + +string + + + +

The IPv4 address to lookup.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getHostnameByMACAddr(mac) → {null|string}

+ + + + + + +
+

Lookup the hostname associated with the given MAC address.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
mac + + +string + + + +

The MAC address to lookup.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getIP6AddrByMACAddr(mac) → {null|string}

+ + + + + + +
+

Lookup the IPv6 address associated with the given MAC address.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
mac + + +string + + + +

The MAC address to lookup.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getIPAddrByMACAddr(mac) → {null|string}

+ + + + + + +
+

Lookup the IPv4 address associated with the given MAC address.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
mac + + +string + + + +

The MAC address to lookup.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getMACAddrByIP6Addr(ipaddr) → {null|string}

+ + + + + + +
+

Lookup the MAC address associated with the given IPv6 address.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
ipaddr + + +string + + + +

The IPv6 address to lookup.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getMACAddrByIPAddr(ipaddr) → {null|string}

+ + + + + + +
+

Lookup the MAC address associated with the given IPv4 address.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
ipaddr + + +string + + + +

The IPv4 address to lookup.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getMACHints(preferIp6opt) → {Array.<Array.<string>>}

+ + + + + + +
+

Return an array of (MAC address, name hint) tuples sorted by +MAC address.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
preferIp6 + + +boolean + + + + + + <optional>
+ + + + + +
+ + false + +

Whether to prefer IPv6 addresses (true) or IPv4 addresses (false) +as name hint when no hostname is known for a specific MAC address.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Array.<Array.<string>> + + +
+
+ + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Network.Protocol.html b/documentation/jsapi/LuCI.Network.Protocol.html new file mode 100644 index 000000000..e23801a32 --- /dev/null +++ b/documentation/jsapi/LuCI.Network.Protocol.html @@ -0,0 +1,4767 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

addDevice(device) → {boolean}

+ + + + + + +
+

Add the given network device to the logical interface.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

containsDevice(device) → {boolean}

+ + + + + + +
+

Checks whether this logical interface contains the given device +object.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when this logical interface contains the given network +device or false if not.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

deleteDevice(device) → {boolean}

+ + + + + + +
+

Remove the given network device from the logical interface.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

get(opt) → {null|string|Array.<string>}

+ + + + + + +
+

Read the given UCI option value of this network.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
opt + + +string + + + +

The UCI option name to read.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the UCI option value or null if the requested option is +not found.

+
+ + + +
+
+ Type +
+
+ +null +| + +string +| + +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getDevice() → {LuCI.Network.Device}

+ + + + + + +
+

Returns the Linux network device associated with this logical +interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a Network.Device class instance representing the +expected Linux network device according to the configuration.

+
+ + + +
+
+ Type +
+
+ +LuCI.Network.Device + + +
+
+ + + + + + + + + + + + + +

getDevices() → {null|Array.<LuCI.Network.Device>}

+ + + + + + +
+

Returns a list of network sub-devices associated with this logical +interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +Array.<LuCI.Network.Device> + + +
+
+ + + + + + + + + + + + + +

getDNS6Addrs() → {Array.<string>}

+ + + + + + +
+

Query the IPv6 DNS servers associated with the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array of IPv6 DNS servers registered by the remote +protocol backend.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getDNSAddrs() → {Array.<string>}

+ + + + + + +
+

Query the IPv4 DNS servers associated with the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array of IPv4 DNS servers registered by the remote +protocol backend.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array of translated interface error messages.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the amount of seconds until the lease expires or -1 +if it isn't applicable to the associated protocol.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getGateway6Addr() → {string}

+ + + + + + +
+

Query the gateway (nexthop) of the IPv6 default route associated with +this logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a string containing the IPv6 nexthop address of the associated +default route or null if no default route was found.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getGatewayAddr() → {string}

+ + + + + + +
+

Query the gateway (nexthop) of the default route associated with +this logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a string containing the IPv4 nexthop address of the associated +default route or null if no default route was found.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

(abstract) getI18n() → {string}

+ + + + + + +
+

Return a human readable description for the protcol, such as +Static address or DHCP client.

+

This function should be overwritten by subclasses.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the description string.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getIfname() → {null|string}

+ + + + + + +
+

Get the associared Linux network device of this network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the name of the associated network device or null if +it could not be determined.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getIP6Addr() → {null|string}

+ + + + + + +
+

Query the first (primary) IPv6 address of the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the primary IPv6 address registered by the protocol handler +in CIDR notation or null if no IPv6 addresses were set.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getIP6Addrs() → {Array.<string>}

+ + + + + + +
+

Query all IPv6 addresses of the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getIP6Prefix() → {null|string}

+ + + + + + +
+

Query the routed IPv6 prefix associated with the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the routed IPv6 prefix registered by the remote protocol +handler or null if no prefix is present.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getIPAddr() → {null|string}

+ + + + + + +
+

Query the first (primary) IPv4 address of the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the primary IPv4 address registered by the protocol handler +or null if no IPv4 addresses were set.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getIPAddrs() → {Array.<string>}

+ + + + + + +
+

Query all IPv4 addresses of the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getL2Device() → {LuCI.Network.Device}

+ + + + + + +
+

Returns the layer 2 linux network device currently associated +with this logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a Network.Device class instance representing the Linux +network device currently associated with the logical interface.

+
+ + + +
+
+ Type +
+
+ +LuCI.Network.Device + + +
+
+ + + + + + + + + + + + + +

getL3Device() → {LuCI.Network.Device}

+ + + + + + +
+

Returns the layer 3 linux network device currently associated +with this logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a Network.Device class instance representing the Linux +network device currently associated with the logical interface.

+
+ + + +
+
+ Type +
+
+ +LuCI.Network.Device + + +
+
+ + + + + + + + + + + + + +

getMetric() → {number}

+ + + + + + +
+

Get the metric value of the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the current metric value used for device and network +routes spawned by the associated logical interface.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getName() → {string}

+ + + + + + +
+

Get the name of the associated logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the logical interface name, such as lan or wan.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getNetmask() → {null|string}

+ + + + + + +
+

Query the first (primary) IPv4 netmask of the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the netmask of the primary IPv4 address registered by the +protocol handler or null if no IPv4 addresses were set.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

(abstract) getOpkgPackage() → {string}

+ + + + + + +
+

Get the name of the opkg package providing the protocol functionality.

+

This function should be overwritten by protocol specific subclasses.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the name of the opkg package required for the protocol to +function, e.g. odhcp6c for the dhcpv6 prototocol.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

(abstract) getProtocol() → {string}

+ + + + + + +
+

Get the name of this network protocol class.

+

This function will be overwritten by subclasses created by +Network.registerProtocol().

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the name of the network protocol implementation, e.g. +static or dhcp.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the value of the type option of the associated logical +interface or null if no type option is set.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getUptime() → {number}

+ + + + + + +
+

Get the uptime of the logical interface.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the uptime of the associated interface in seconds.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the name of the parent interface if this logical interface +is an alias or null if it is not an alias interface.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

isBridge() → {boolean}

+ + + + + + +
+

Checks whether the underlying logical interface is declared as bridge.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a boolean indicating whether this interface is dynamic (true) +or not (false).

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

isEmpty() → {boolean}

+ + + + + + +
+

Checks whether this logical interface is "empty", meaning that ut +has no network devices attached.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if this logical interface is empty, else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

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
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a boolean indicating whether this protocol is floating (true) +or not (false).

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

(abstract) isInstalled() → {boolean}

+ + + + + + +
+

Checks whether the protocol functionality is installed.

+

This function exists for compatibility with old code, it always +returns true.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if the protocol support is installed, else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

isUp() → {boolean}

+ + + + + + +
+

Checks whether this logical interface is configured and running.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when the interface is active or false when it is not.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a boolean indicating whether the underlying protocol spawns +dynamic interfaces (true) or not (false).

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

set(opt, val)

+ + + + + + +
+

Set the given UCI option of this network to the given value.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Network.WifiDevice.html b/documentation/jsapi/LuCI.Network.WifiDevice.html new file mode 100644 index 000000000..b050c68bc --- /dev/null +++ b/documentation/jsapi/LuCI.Network.WifiDevice.html @@ -0,0 +1,1915 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

addWifiNetwork(optionsopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
options + + +Object.<string, (string|Array.<string>)> + + + + + + <optional>
+ + + + + +

The options to set for the newly added wireless network.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to a WifiNetwork instance describing +the newly added wireless network or null if the given options +were invalid.

+
+ + + +
+
+ Type +
+
+ +Promise.<(null|LuCI.Network.WifiNetwork)> + + +
+
+ + + + + + + + + + + + + +

deleteWifiNetwork(network) → {Promise.<boolean>}

+ + + + + + +
+

Deletes the wireless network with the given name associated with this +radio device.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<boolean> + + +
+
+ + + + + + + + + + + + + +

get(opt) → {null|string|Array.<string>}

+ + + + + + +
+

Read the given UCI option value of this wireless device.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
opt + + +string + + + +

The UCI option name to read.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the UCI option value or null if the requested option is +not found.

+
+ + + +
+
+ Type +
+
+ +null +| + +string +| + +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getHTModes() → {Array.<string>}

+ + + + + + +
+

Gets a list of supported htmodes.

+

The htmode values describe the wide-frequency options supported by +the wireless phy.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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
  • +
+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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
  • +
+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getI18n() → {string}

+ + + + + + +
+

Get a string describing the wireless radio hardware.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the description string.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getName() → {string}

+ + + + + + +
+

Get the configuration name of this wireless radio.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the UCI section name (e.g. radio0) of the corresponding +radio configuration which also serves as unique logical identifier +for the wireless phy.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getScanList() → {Promise.<Array.<LuCI.Network.WifiScanResult>>}

+ + + + + + +
+

Trigger a wireless scan on this radio device and obtain a list of +nearby networks.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an array of scan result objects +describing the networks found in the vincinity.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<LuCI.Network.WifiScanResult>> + + +
+
+ + + + + + + + + + + + + +

getWifiNetwork(network) → {Promise.<LuCI.Network.WifiNetwork>}

+ + + + + + +
+

Get the wifi network of the given name belonging to this radio device

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<LuCI.Network.WifiNetwork> + + +
+
+ + + + + + + + + + + + + +

getWifiNetworks() → {Promise.<Array.<LuCI.Network.WifiNetwork>>}

+ + + + + + +
+

Get all wireless networks associated with this wireless radio device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an array of Network.WifiNetwork +instances respresenting the wireless networks associated with this +radio device.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<LuCI.Network.WifiNetwork>> + + +
+
+ + + + + + + + + + + + + +

isDisabled() → {boolean}

+ + + + + + +
+

Checks whether this wireless radio is disabled.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

isUp() → {boolean}

+ + + + + + +
+

Check whether the wireless radio is marked as up in the ubus +runtime state.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when the radio device is up, else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

set(opt, val)

+ + + + + + +
+

Set the given UCI option of this network to the given value.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Network.WifiNetwork.html b/documentation/jsapi/LuCI.Network.WifiNetwork.html new file mode 100644 index 000000000..62e43aa5e --- /dev/null +++ b/documentation/jsapi/LuCI.Network.WifiNetwork.html @@ -0,0 +1,4239 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

get(opt) → {null|string|Array.<string>}

+ + + + + + +
+

Read the given UCI option value of this wireless network.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
opt + + +string + + + +

The UCI option name to read.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the UCI option value or null if the requested option is +not found.

+
+ + + +
+
+ Type +
+
+ +null +| + +string +| + +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getActiveBSSID() → {string}

+ + + + + + +
+

Query the current BSSID from runtime information.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the current BSSID or Mesh ID as reported by ubus runtime +information.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getActiveEncryption() → {string}

+ + + + + + +
+

Query the current encryption settings from runtime information.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a string describing the current encryption or - if the the +encryption state could not be found in ubus runtime information.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getActiveMode() → {string}

+ + + + + + +
+

Query the current operation mode from runtime information.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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
  • +
+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getActiveModeI18n() → {string}

+ + + + + + +
+

Query the current operation mode from runtime information as +translated string.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the translated, human readable mode name as reported by +ubus runtime state.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getActiveSSID() → {string}

+ + + + + + +
+

Query the current SSID from runtime information.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the current SSID or Mesh ID as reported by ubus runtime +information.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getAssocList() → {Promise.<Array.<LuCI.Network.WifiPeerEntry>>}

+ + + + + + +
+

Fetch the list of associated peers.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an array of wireless peers associated +with this network.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<LuCI.Network.WifiPeerEntry>> + + +
+
+ + + + + + + + + + + + + +

getBitRate() → {null|number}

+ + + + + + +
+

Query the current average bitrate of all peers associated to this +wireless network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +number + + +
+
+ + + + + + + + + + + + + +

getBSSID() → {null|string}

+ + + + + + +
+

Get the configured BSSID of the wireless network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the BSSID value or null if none has been specified.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getChannel() → {null|number}

+ + + + + + +
+

Query the current wireless channel.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the wireless channel as reported by ubus runtime information +or null if it cannot be determined.

+
+ + + +
+
+ Type +
+
+ +null +| + +number + + +
+
+ + + + + + + + + + + + + +

getCountryCode() → {string}

+ + + + + + +
+

Query the current country code.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the wireless country code as reported by ubus runtime +information or 00 if it cannot be determined.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getDevice() → {LuCI.Network.Device}

+ + + + + + +
+

Get the associated Linux network device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a Network.Device instance representing the Linux network +device associted with this wireless network.

+
+ + + +
+
+ Type +
+
+ +LuCI.Network.Device + + +
+
+ + + + + + + + + + + + + +

getFrequency() → {null|string}

+ + + + + + +
+

Query the current operating frequency of the wireless network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the current operating frequency of the network from ubus +runtime information in GHz or null if the information is not +available.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getI18n() → {string}

+ + + + + + +
+

Get a description string for this wireless network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the LuCI specific network ID.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getIfname() → {null|string}

+ + + + + + +
+

Get the Linux network device name.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getMeshID() → {null|string}

+ + + + + + +
+

Get the configured Mesh ID of the wireless network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the configured mesh ID value or null when this network +is not in mesh mode.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getMode() → {string}

+ + + + + + +
+

Get the configured operation mode of the wireless network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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
  • +
+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getName() → {string}

+ + + + + + +
+

Get the configuration ID of this wireless network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the corresponding UCI section ID of the network.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getNetwork() → {null|LuCI.Network.Protocol}

+ + + + + + +
+

Get the primary logical interface this wireless network is attached to.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a Network.Protocol instance representing the logical +interface or null if this network is not attached to any logical +interface.

+
+ + + +
+
+ Type +
+
+ +null +| + +LuCI.Network.Protocol + + +
+
+ + + + + + + + + + + + + +

getNetworkNames() → {Array.<string>}

+ + + + + + +
+

Get the names of the logical interfaces this wireless network is +attached to.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array of logical interface names.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

getNetworks() → {Array.<LuCI.Network.Protocol>}

+ + + + + + +
+

Get the logical interfaces this wireless network is attached to.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array of Network.Protocol instances representing the +logical interfaces this wireless network is attached to.

+
+ + + +
+
+ Type +
+
+ +Array.<LuCI.Network.Protocol> + + +
+
+ + + + + + + + + + + + + +

getNoise() → {number}

+ + + + + + +
+

Query the current radio noise floor.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the radio noise floor in dBm as reported by ubus runtime +information or 0 if it cannot be determined.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getShortName() → {string}

+ + + + + + +
+

Get a short description string for this wireless network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getSignal() → {null|number}

+ + + + + + +
+

Query the current wireless signal.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the wireless signal in dBm as reported by ubus runtime +information or null if it cannot be determined.

+
+ + + +
+
+ Type +
+
+ +null +| + +number + + +
+
+ + + + + + + + + + + + + +

getSignalLevel() → {number}

+ + + + + + +
+

Calculate the current signal.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the calculated signal level, which is the difference between +noise and signal (SNR), divided by 5.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getSignalPercent() → {number}

+ + + + + + +
+

Calculate the current signal quality percentage.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the calculated signal quality in percent. The value is +calculated from the quality and quality_max indicators reported +by ubus runtime state.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getSSID() → {null|string}

+ + + + + + +
+

Get the configured SSID of the wireless network.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the configured SSID value or null when this network is +in mesh mode.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getTXPower() → {null|number}

+ + + + + + +
+

Query the current radio TX power.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the wireless network transmit power in dBm as reported by +ubus runtime information or null if it cannot be determined.

+
+ + + +
+
+ Type +
+
+ +null +| + +number + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + + + + + +

getWifiDevice() → {null|LuCI.Network.WifiDevice}

+ + + + + + +
+

Get the corresponding wifi radio device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a Network.WifiDevice instance representing the corresponding +wifi radio device or null if the related radio device could not be +found.

+
+ + + +
+
+ Type +
+
+ +null +| + +LuCI.Network.WifiDevice + + +
+
+ + + + + + + + + + + + + +

getWifiDeviceName() → {null|string}

+ + + + + + +
+

Get the name of the corresponding wifi radio device.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the name of the radio device this network is configured on +or null if it cannot be determined.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

isDisabled() → {boolean}

+ + + + + + +
+

Checks whether this wireless network is disabled.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when the network is up, else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

set(opt, val)

+ + + + + + +
+

Set the given UCI option of this network to the given value.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Network.html b/documentation/jsapi/LuCI.Network.html new file mode 100644 index 000000000..d0ab9f2c9 --- /dev/null +++ b/documentation/jsapi/LuCI.Network.html @@ -0,0 +1,6529 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +

Classes

+ +
+
Device
+
+ +
Hosts
+
+ +
Protocol
+
+ +
WifiDevice
+
+ +
WifiNetwork
+
+
+ + + + + + + + + + + +

Methods

+ + + + + + + +

addNetwork(name, optionsopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<(null|LuCI.Network.Protocol)> + + +
+
+ + + + + + + + + + + + + +

addWifiNetwork(options) → {Promise.<(null|LuCI.Network.WifiNetwork)>}

+ + + + + + +
+

Adds a new wireless network to the configuration and sets its options +to the provided values.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<(null|LuCI.Network.WifiNetwork)> + + +
+
+ + + + + + + + + + + + + +

deleteNetwork(name) → {Promise.<boolean>}

+ + + + + + +
+

Deletes the given network and its references from the network and +firewall configuration.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + +

The name of the network to delete.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<boolean> + + +
+
+ + + + + + + + + + + + + +

deleteWifiNetwork(netname) → {Promise.<boolean>}

+ + + + + + +
+

Deletes the given wireless network from the configuration.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<boolean> + + +
+
+ + + + + + + + + + + + + +

flushCache() → {Promise.<Object>}

+ + + + + + +
+

Flushes the local network state cache and fetches updated information +from the remote ubus apis.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to the internal network state object.

+
+ + + +
+
+ Type +
+
+ +Promise.<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).

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
encryption + + +LuCI.Network.WifiEncryption + + + +

The wireless encryption entry to convert.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the description string for the given encryption entry or +null if the given entry was invalid.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getDevice(name) → {Promise.<(null|LuCI.Network.Device)>}

+ + + + + + +
+

Get a Device instance describing the +given network device.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + +

The name of the network device to get, e.g. eth0 or br-lan.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to the Device instance describing +the network device or null if the given device name could not +be found.

+
+ + + +
+
+ Type +
+
+ +Promise.<(null|LuCI.Network.Device)> + + +
+
+ + + + + + + + + + + + + +

getDevices() → {Promise.<Array.<LuCI.Network.Device>>}

+ + + + + + +
+

Get a sorted list of all found network devices.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to a sorted array of Device class +instances describing the network devices found on the system.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<LuCI.Network.Device>> + + +
+
+ + + + + + + + + + + + + +

getDSLModemType() → {Promise.<(null|string)>}

+ + + + + + +
+

Queries the internal DSL modem type from board information.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to the type of the internal modem +(e.g. vdsl) or to null if no internal modem is present.

+
+ + + +
+
+ Type +
+
+ +Promise.<(null|string)> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a Hosts instance describing host known on the system.

+
+ + + +
+
+ Type +
+
+ +Promise.<LuCI.Network.Hosts> + + +
+
+ + + + + + + + + + + + + +

getIfnameOf(obj) → {null|string}

+ + + + + + +
+

Obtains the the network device name of the given object.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
obj + + +LuCI.Network.Protocol +| + +LuCI.Network.Device +| + +LuCI.Network.WifiDevice +| + +LuCI.Network.WifiNetwork +| + +string + + + +

The object to get the device name from.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a string containing the device name or null if the given +object could not be converted to a name.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

getNetwork(name) → {Promise.<(null|LuCI.Network.Protocol)>}

+ + + + + + +
+

Get a Protocol instance describing +the network with the given name.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + +

The logical interface name of the network get, e.g. lan or wan.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to a +Protocol subclass instance describing +the network or null if the network did not exist.

+
+ + + +
+
+ Type +
+
+ +Promise.<(null|LuCI.Network.Protocol)> + + +
+
+ + + + + + + + + + + + + +

getNetworks() → {Promise.<Array.<LuCI.Network.Protocol>>}

+ + + + + + +
+

Gets an array containing all known networks.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to a name-sorted array of +Protocol subclass instances +describing all known networks.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<LuCI.Network.Protocol>> + + +
+
+ + + + + + + + + + + + + +

getProtocol(protoname, netnameopt) → {null|LuCI.Network.Protocol}

+ + + + + + +
+

Instantiates the given Protocol backend, +optionally using the given network name.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
protoname + + +string + + + + + + + + + + + +

The protocol backend to use, e.g. static or dhcp.

netname + + +string + + + + + + <optional>
+ + + + + +
+ + __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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the instantiated protocol backend class or null if the given +protocol isn't known.

+
+ + + +
+
+ Type +
+
+ +null +| + +LuCI.Network.Protocol + + +
+
+ + + + + + + + + + + + + +

getProtocols() → {Array.<LuCI.Network.Protocol>}

+ + + + + + +
+

Obtains instances of all known Protocol +backend classes.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array of protocol class instances.

+
+ + + +
+
+ Type +
+
+ +Array.<LuCI.Network.Protocol> + + +
+
+ + + + + + + + + + + + + +

getSwitchTopologies() → {Promise.<Object.<string, LuCI.Network.SwitchTopology>>}

+ + + + + + +
+

Returns the topologies of all swconfig switches found on the system.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<Object.<string, LuCI.Network.SwitchTopology>> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an array of Protocol subclass +instances describing the found IPv6 default route interfaces.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<LuCI.Network.Protocol>> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an array of Protocol subclass +instances describing the found default route interfaces.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<LuCI.Network.Protocol>> + + +
+
+ + + + + + + + + + + + + +

getWifiDevice(devname) → {Promise.<(null|LuCI.Network.WifiDevice)>}

+ + + + + + +
+

Get a WifiDevice instance describing +the given wireless radio.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
devname + + +string + + + +

The configuration name of the wireless radio to lookup, e.g. radio0 +for the first mac80211 phy on the system.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to the WifiDevice instance describing +the underlying radio device or null if the wireless radio could not +be found.

+
+ + + +
+
+ Type +
+
+ +Promise.<(null|LuCI.Network.WifiDevice)> + + +
+
+ + + + + + + + + + + + + +

getWifiDevices() → {Promise.<Array.<LuCI.Network.WifiDevice>>}

+ + + + + + +
+

Obtain a list of all configured radio devices.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<LuCI.Network.WifiDevice>> + + +
+
+ + + + + + + + + + + + + +

getWifiNetwork(netname) → {Promise.<(null|LuCI.Network.WifiNetwork)>}

+ + + + + + +
+

Get a WifiNetwork instance describing +the given wireless network.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to the WifiNetwork instance describing +the wireless network or null if the corresponding network could not +be found.

+
+ + + +
+
+ Type +
+
+ +Promise.<(null|LuCI.Network.WifiNetwork)> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + +

The device name to test.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if the given name is in the ignore pattern list, +else returns false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

maskToPrefix(netmask, v6opt) → {null|number}

+ + + + + + +
+

Converts the given netmask to a prefix size in bits.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
netmask + + +string + + + + + + + + + + + +

The netmask to convert into a bit count.

v6 + + +boolean + + + + + + <optional>
+ + + + + +
+ + false + +

Whether to parse the given netmask as IPv4 (false) or IPv6 (true) +address.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the number of prefix bits contained in the netmask or null +if the given netmask value was invalid.

+
+ + + +
+
+ Type +
+
+ +null +| + +number + + +
+
+ + + + + + + + + + + + + +

prefixToMask(bits, v6opt) → {null|string}

+ + + + + + +
+

Converts the given prefix size in bits to a netmask.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
bits + + +number + + + + + + + + + + + +

The prefix size in bits.

v6 + + +boolean + + + + + + <optional>
+ + + + + +
+ + false + +

Whether to convert the bits value into an IPv4 netmask (false) or +an IPv6 netmask (true).

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +null +| + +string + + +
+
+ + + + + + + + + + + + + +

registerErrorCode(code, message) → {boolean}

+ + + + + + +
+

Registers a new human readable translation string for a Protocol +error code.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

registerPatternVirtual(pat)

+ + + + + + +
+

Registers a new regular expression pattern to recognize +virtual interfaces.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pat + + +RegExp + + + +

A RegExp instance to match a virtual interface name +such as 6in4-wan or tun0.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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().

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the new Protocol subclass.

+
+ + + +
+
+ Type +
+
+ +LuCI.Network.Protocol + + +
+
+ + + + + + + + + + + + + +

renameNetwork(oldName, newName) → {Promise.<boolean>}

+ + + + + + +
+

Rename the given network and its references to a new name.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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_]+.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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 +
+
+ +Promise.<boolean> + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

SwitchTopology

+ + + + +
+

Describes an swconfig switch topology by specifying the CPU +connections and external port labels of a switch.

+
+ + + +
Type:
+
    +
  • + +Object.<string, (Object|Array)> + + +
  • +
+ + + + + +
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)
  • +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

WifiEncryption

+ + + + +
+

An encryption entry describes active wireless encryption settings +such as the used key management protocols, active ciphers and +protocol versions.

+
+ + + +
Type:
+
    +
  • + +Object.<string, (boolean|Array.<(number|string)>)> + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

WifiPeerEntry

+ + + + +
+

A wireless peer entry describes the properties of a remote wireless +peer associated with a local network.

+
+ + + +
Type:
+ + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

WifiRateEntry

+ + + + +
+

A wireless rate entry describes the properties of a wireless +transmission rate to or from a peer.

+
+ + + +
Type:
+
    +
  • + +Object.<string, (boolean|number)> + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

WifiScanResult

+ + + + +
+

A wireless scan result object describes a neighbouring wireless +network found in the vincinity.

+
+ + + +
Type:
+ + + + + + +
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.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Poll.html b/documentation/jsapi/LuCI.Poll.html new file mode 100644 index 000000000..195fdc991 --- /dev/null +++ b/documentation/jsapi/LuCI.Poll.html @@ -0,0 +1,906 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

active() → {boolean}

+ + + + + + +
+

Test whether the polling loop is running.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • Returns true if polling is active, else false.
  • +
+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
fn + + +function + + + +

The function to invoke on each poll interval.

interval + + +number + + + +

The poll interval in seconds.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+

Throws TypeError when an invalid interval was passed.

+
+
+
+
+
+
+ Type +
+
+ +TypeError + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+

Returns true if the function has been added or false if it +already is registered.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

remove(fn) → {boolean}

+ + + + + + +
+

Remove an operation from the polling loop. If no further operatons +are registered, the polling loop is implicitely stopped.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
fn + + +function + + + +

The function to remove.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+

Throws TypeError when the given argument isn't a function.

+
+
+
+
+
+
+ Type +
+
+ +TypeError + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+

Returns true if the function has been removed or false if it +wasn't found.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

start() → {boolean}

+ + + + + + +
+

(Re)start the polling loop. Dispatches a custom poll-start event +to the document object upon successful start.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if polling has been started (or if no functions +where registered) or false when the polling loop already runs.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

stop() → {boolean}

+ + + + + + +
+

Stop the polling loop. Dispatches a custom poll-stop event +to the document object upon successful stop.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if polling has been stopped or false if it din't +run to begin with.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Request.html b/documentation/jsapi/LuCI.Request.html new file mode 100644 index 000000000..2028b406f --- /dev/null +++ b/documentation/jsapi/LuCI.Request.html @@ -0,0 +1,1900 @@ + + + + + JSDoc: Class: Request + + + + + + + + + + +
+ +

Class: Request

+ + + + + + +
+ +
+ +

+ LuCI.Request

+ +

The Request class allows initiating HTTP requests and provides utilities +for dealing with responses.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
interceptorFn + + +LuCI.Request.interceptorFn + + + +

The interceptor function to register.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

The registered function.

+
+ + + +
+
+ Type +
+
+ +LuCI.Request.interceptorFn + + +
+
+ + + + + + + + + + + + + +

expandURL(url) → {string}

+ + + + + + +
+

Turn the given relative URL into an absolute URL if necessary.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
url + + +string + + + +

The URL to convert.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

The absolute URL derived from the given one, or the original URL +if it already was absolute.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

get(target, optionsopt) → {Promise.<LuCI.Response>}

+ + + + + + +
+

Initiate an HTTP GET request to the given target.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
target + + +string + + + + + + + + + +

The URL to request.

options + + +LuCI.Request.RequestOptions + + + + + + <optional>
+ + + + + +

Additional options to configure the request.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

The resulting HTTP response.

+
+ + + +
+
+ Type +
+
+ +Promise.<LuCI.Response> + + +
+
+ + + + + + + + + + + + + +

post(target, dataopt, optionsopt) → {Promise.<LuCI.Response>}

+ + + + + + +
+

Initiate an HTTP POST request to the given target.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

The resulting HTTP response.

+
+ + + +
+
+ Type +
+
+ +Promise.<LuCI.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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
interceptorFn + + +LuCI.Request.interceptorFn + + + +

The interceptor function to remove.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if any function has been removed, else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

request(target, optionsopt) → {Promise.<LuCI.Response>}

+ + + + + + +
+

Initiate an HTTP request to the given target.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
target + + +string + + + + + + + + + +

The URL to request.

options + + +LuCI.Request.RequestOptions + + + + + + <optional>
+ + + + + +

Additional options to configure the request.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

The resulting HTTP response.

+
+ + + +
+
+ Type +
+
+ +Promise.<LuCI.Response> + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + + + + + +

interceptorFn(res)

+ + + + + + +
+

Interceptor functions are invoked whenever an HTTP reply is received, in the order +these functions have been registered.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
res + + +LuCI.Response + + + +

The HTTP response object

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +

RequestOptions

+ + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
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.

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.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Request.poll.html b/documentation/jsapi/LuCI.Request.poll.html new file mode 100644 index 000000000..06c700dc4 --- /dev/null +++ b/documentation/jsapi/LuCI.Request.poll.html @@ -0,0 +1,1079 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

active()

+ + + + + + +
+

Alias for LuCI.Poll.active().

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

add(interval, url, optionsopt, callbackopt) → {function}

+ + + + + + +
+

Register a repeating HTTP request with an optional callback +to invoke whenever a response for the request is received.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+

Throws TypeError when an invalid interval was passed.

+
+
+
+
+
+
+ Type +
+
+ +TypeError + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+

Returns the internally created poll function.

+
+ + + +
+
+ Type +
+
+ +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().

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
entry + + +function + + + +

The poll function returned by add().

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if any function has been removed, else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

start()

+ + + + + + +
+

Alias for LuCI.Poll.start().

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

stop()

+ + + + + + +
+

Alias for LuCI.Poll.stop().

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.Response.html b/documentation/jsapi/LuCI.Response.html new file mode 100644 index 000000000..fea8f79d9 --- /dev/null +++ b/documentation/jsapi/LuCI.Response.html @@ -0,0 +1,1024 @@ + + + + + JSDoc: Class: Response + + + + + + + + + + +
+ +

Class: Response

+ + + + + + +
+ +
+ +

+ LuCI.Response

+ +

The Response class is an internal utility class representing HTTP responses.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +

Members

+ + + +

duration :number

+ + + + +
+

The total duration of the HTTP request in milliseconds

+
+ + + +
Type:
+
    +
  • + +number + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

headers :LuCI.Headers

+ + + + +
+

The HTTP headers of the response

+
+ + + +
Type:
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

ok :boolean

+ + + + +
+

Describes whether the response is successful (status codes 200..299) or not

+
+ + + +
Type:
+
    +
  • + +boolean + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

status :number

+ + + + +
+

The numeric HTTP status code of the response

+
+ + + +
Type:
+
    +
  • + +number + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

statusText :string

+ + + + +
+

The HTTP status description message of the response

+
+ + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

url :string

+ + + + +
+

The final URL of the request, i.e. after following redirects.

+
+ + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +

Methods

+ + + + + + + +

clone(contentopt) → {LuCI.Response}

+ + + + + + +
+

Clones the given response object, optionally overriding the content +of the cloned instance.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

The cloned Response instance.

+
+ + + +
+
+ Type +
+
+ +LuCI.Response + + +
+
+ + + + + + + + + + + + + +

json() → {*}

+ + + + + + +
+

Access the response content as JSON data.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+

Throws SyntaxError if the content isn't valid JSON.

+
+
+
+
+
+
+ Type +
+
+ +SyntaxError + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+

The parsed JSON data.

+
+ + + +
+
+ Type +
+
+ +* + + +
+
+ + + + + + + + + + + + + +

text() → {string}

+ + + + + + +
+

Access the response content as string.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

The response content.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.XHR.html b/documentation/jsapi/LuCI.XHR.html new file mode 100644 index 000000000..b82f2a0fb --- /dev/null +++ b/documentation/jsapi/LuCI.XHR.html @@ -0,0 +1,1134 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + +

Constructor

+ + + +

new XHR()

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

abort()

+ + + + + + +
+

Ignored for backwards compatibility.

+

This function does nothing.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

busy() → {boolean}

+ + + + + + +
+

Checks the running state of the request.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if the request is still running or false if it +already completed.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

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
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

get(url, dataopt, callbackopt, timeoutopt) → {Promise.<null>}

+ + + + + + +
+

This function is a legacy wrapper around +LuCI.get().

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<null> + + +
+
+ + + + + + + + + + + + + +

post(url, dataopt, callbackopt, timeoutopt) → {Promise.<null>}

+ + + + + + +
+

This function is a legacy wrapper around +LuCI.post().

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<null> + + +
+
+ + + + + + + + + + + + + +

send_form()

+ + + + + + +
+

Existing for backwards compatibility.

+

This function simply throws an InternalError when invoked.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+

Throws an InternalError with the message Not implemented +when invoked.

+
+
+
+
+
+
+ Type +
+
+ +InternalError + + +
+
+
+
+
+ + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.dom.html b/documentation/jsapi/LuCI.dom.html new file mode 100644 index 000000000..b98c8f0a6 --- /dev/null +++ b/documentation/jsapi/LuCI.dom.html @@ -0,0 +1,3135 @@ + + + + + JSDoc: Class: dom + + + + + + + + + + +
+ +

Class: dom

+ + + + + + +
+ +
+ +

+ LuCI.dom

+ +

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

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

append(node, childrenopt) → {Node|null}

+ + + + + + +
+

Appends the given children data to the given node.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Node +| + +null + + +
+
+ + + + + + + + + + + + + +

attr(node, key, valopt)

+ + + + + + +
+

Sets attributes or registers event listeners on element nodes.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
node + + +Node + + + +

The DOM Node instance to bind the class to.

inst + + +Class + + + +

The Class instance to bind to the node.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+

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

+
+
+
+
+
+
+ Type +
+
+ +TypeError + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+

Returns the bound class instance.

+
+ + + +
+
+ Type +
+
+ +Class + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +* +| + +null + + +
+
+ + + + + + + + + + + + + +

content(node, childrenopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Node +| + +null + + +
+
+ + + + + + + + + + + + + +

create(html, attropt, dataopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
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:
+ + +
+

Returns the newly created Node.

+
+ + + +
+
+ Type +
+
+ +Node + + +
+
+ + + + + + + + + + + + + +

data(node, keyopt, valopt) → {*}

+ + + + + + +
+

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.
  • +
+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the get or set value, or null when no value could +be found.

+
+ + + +
+
+ Type +
+
+ +* + + +
+
+ + + + + + + + + + + + + +

elem(e) → {boolean}

+ + + + + + +
+

Tests whether the given argument is a valid DOM Node.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
e + + +* + + + +

The value to test.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if the value is a DOM Node, else false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

findClassInstance(node) → {Class|null}

+ + + + + + +
+

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

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
node + + +Node + + + +

The DOM Node instance to start from.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Class +| + +null + + +
+
+ + + + + + + + + + + + + +

isEmpty(node, ignoreFnopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

matches(node, selectoropt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
node + + +* + + + + + + + + + +

The Node argument to test the selector against.

selector + + +string + + + + + + <optional>
+ + + + + +

The query selector expression to test against the given node.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

parent(node, selectoropt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
node + + +* + + + + + + + + + +

The Node argument to find the closest parent for.

selector + + +string + + + + + + <optional>
+ + + + + +

The query selector expression to test against each parent.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Node +| + +null + + +
+
+ + + + + + + + + + + + + +

parse(s) → {Node}

+ + + + + + +
+

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

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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

+
+ + + +
+
+ Type +
+
+ +Node + + +
+
+ + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
node + + +Node + + + +

The child node to test.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Boolean indicating whether to ignore the node or not.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.fs.html b/documentation/jsapi/LuCI.fs.html new file mode 100644 index 000000000..abae649cb --- /dev/null +++ b/documentation/jsapi/LuCI.fs.html @@ -0,0 +1,2143 @@ + + + + + JSDoc: 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(...).

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

exec(command, paramsopt, envopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an object describing the execution +results or rejecting with an error stating the failure reason.

+
+ + + +
+
+ Type +
+
+ +Promise.<LuCI.fs.FileExecResult> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
path + + +string + + + +

The file path to read.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an array containing the stripped lines +of the given file or [] on failure.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<string>> + + +
+
+ + + + + + + + + + + + + +

list(path) → {Promise.<Array.<LuCI.fs.FileStatEntry>>}

+ + + + + + +
+

Obtains a listing of the specified directory.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
path + + +string + + + +

The directory path to list.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an array of stat detail objects or +rejecting with an error stating the failure reason.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<LuCI.fs.FileStatEntry>> + + +
+
+ + + + + + + + + + + + + +

read(path) → {Promise.<string>}

+ + + + + + +
+

Read the contents of the given file and return them. +Note: this function is unsuitable for obtaining binary data.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
path + + +string + + + +

The file path to read.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to a string containing the file contents or +rejecting with an error stating the failure reason.

+
+ + + +
+
+ Type +
+
+ +Promise.<string> + + +
+
+ + + + + + + + + + + + + +

remove(The) → {Promise.<number>}

+ + + + + + +
+

Unlink the given file.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
The + + +string + + + +

file path to remove.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to 0 or rejecting with an error stating +the failure reason.

+
+ + + +
+
+ Type +
+
+ +Promise.<number> + + +
+
+ + + + + + + + + + + + + +

stat(path) → {Promise.<LuCI.fs.FileStatEntry>}

+ + + + + + +
+

Return file stat information on the specified path.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
path + + +string + + + +

The filesystem path to stat.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to a stat detail object or +rejecting with an error stating the failure reason.

+
+ + + +
+
+ Type +
+
+ +Promise.<LuCI.fs.FileStatEntry> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
path + + +string + + + +

The file path to read.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to the file contents or the empty string +on failure.

+
+ + + +
+
+ Type +
+
+ +Promise.<string> + + +
+
+ + + + + + + + + + + + + +

write(path, dataopt, modeopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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).

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to 0 or rejecting with an error stating +the failure reason.

+
+ + + +
+
+ Type +
+
+ +Promise.<number> + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + +

FileExecResult

+ + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

FileStatEntry

+ + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
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

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.html b/documentation/jsapi/LuCI.html new file mode 100644 index 000000000..44f899b35 --- /dev/null +++ b/documentation/jsapi/LuCI.html @@ -0,0 +1,4436 @@ + + + + + JSDoc: Class: LuCI + + + + + + + + + + +
+ +

Class: LuCI

+ + + + + + +
+ +
+ +

LuCI(env)

+ +

This is the LuCI base class. It is automatically instantiated and +accessible using the global L variable.

+ + +
+ +
+
+ + + + +

Constructor

+ + + +

new LuCI(env)

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object + + + +

The environment settings to use for the LuCI runtime.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +

Classes

+ +
+
Class
+
+ +
dom
+
+ +
fs
+
+ +
Headers
+
+ +
Network
+
+ +
Poll
+
+ +
Request
+
+ +
Response
+
+ +
rpc
+
+ +
uci
+
+ +
view
+
+ +
XHR
+
+
+ + + + + + + + + +

Members

+ + + +

env

+ + + + +
+

The env object holds environment settings used by LuCI, such +as request timeouts, base URLs etc.

+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + +

Methods

+ + + + + + + +

bind(fn, self, …argsopt) → {function}

+ + + + + + +
+

Return a bound function using the given self as this context +and any further arguments as parameters to the bound function.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the bound function.

+
+ + + +
+
+ Type +
+
+ +function + + +
+
+ + + + + + + + + + + + + +

error(typeopt, fmtopt, …argsopt)

+ + + + + + +
+

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
type + + +Error +| + +string + + + + + + <optional>
+ + + + + +
+ + Error + +

Either a string specifying the type of the error to throw or an +existing Error instance to copy.

fmt + + +string + + + + + + <optional>
+ + + + + +
+ + Unspecified error + +

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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
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 + + +
+
+
+
+
+ + + + + + + + + + + + + + + + +

get(url, argsopt, 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().

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to null when concluded.

+
+ + + +
+
+ Type +
+
+ +Promise.<null> + + +
+
+ + + + + + + + + + + + + +

halt() → {boolean}

+ + + + + + +
+

Deprecated wrapper around Poll.stop().

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when the polling loop has been stopped or false +when it didn't run to begin with.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

hasSystemFeature(feature, subfeatureopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +boolean +| + +null + + +
+
+ + + + + + + + + + + + + +

isObject(valopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
val + + +* + + + + + + <optional>
+ + + + + +

The value to test

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if the given value is of type object and +not null, else returns false.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

location() → {string}

+ + + + + + +
+

Return the complete URL path to the current view.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the URL path to the current view.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

path(prefixopt, partsopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Return the joined URL path.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

poll(interval, url, argsopt, cb, postopt) → {function}

+ + + + + + +
+

Register a polling HTTP request that invokes the specified +callback function. The function is a wrapper around +Request.poll.add().

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
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 + + + + + + <optional>
+ + + + + +
+ + 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.

+ + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +function + + +
+
+ + + + + + + + + + + + + +

post(url, argsopt, 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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to null when concluded.

+
+ + + +
+
+ Type +
+
+ +Promise.<null> + + +
+
+ + + + + + + + + + + + + +

raise(typeopt, fmtopt, …argsopt)

+ + + + + + +
+

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
type + + +Error +| + +string + + + + + + <optional>
+ + + + + +
+ + Error + +

Either a string specifying the type of the error to throw or an +existing Error instance to copy.

fmt + + +string + + + + + + <optional>
+ + + + + +
+ + Unspecified error + +

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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
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#Class>}

+ + + + + + +
+

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + +
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:
+ + +
+

Returns the instantiated class.

+
+ + + +
+
+ Type +
+
+ +Promise.<LuCI#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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a new promise resolving either to the given input value or +to the given default value on error.

+
+ + + +
+
+ Type +
+
+ +Promise.<*> + + +
+
+ + + + + + + + + + + + + +

resource(partsopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the resulting URL path.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

run() → {boolean}

+ + + + + + +
+

Deprecated wrapper around Poll.start().

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when the polling loop has been started or false +when it was already running.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

sortedKeys(obj, keyopt, sortmodeopt) → {Array.<string>}

+ + + + + + +
+

Return an array of sorted object keys, optionally sorted by +a different key or a different sorting mode.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns an array containing the sorted keys of the given object.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

stop(entry) → {boolean}

+ + + + + + +
+

Deprecated wrapper around Poll.remove().

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
entry + + +function + + + +

The polling function to remove.

+ + + + + + +
+ + + + + + + + + + + + + + + + +
Deprecated:
  • Yes
+ + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when the function has been removed or false if +it could not be found.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
val + + +* + + + +

The value to convert into an array.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the resulting array.

+
+ + + +
+
+ Type +
+
+ +Array.<*> + + +
+
+ + + + + + + + + + + + + +

url(partsopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the resulting URL path.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + +

Type Definitions

+ + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.rpc.html b/documentation/jsapi/LuCI.rpc.html new file mode 100644 index 000000000..9d548f3ad --- /dev/null +++ b/documentation/jsapi/LuCI.rpc.html @@ -0,0 +1,2414 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

addInterceptor(interceptorFn) → {LuCI.rpc~interceptorFn}

+ + + + + + +
+

Registers a new interceptor function.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
interceptorFn + + +LuCI.rpc~interceptorFn + + + +

The inteceptor function to register.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the given function value.

+
+ + + +
+
+ Type +
+
+ +LuCI.rpc~interceptorFn + + +
+
+ + + + + + + + + + + + + +

declare(options) → {LuCI.rpc~invokeFn}

+ + + + + + +
+

Describes a remote RPC call procedure and returns a function +implementing it.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +LuCI.rpc.DeclareOptions + + + +

If any object names are given, this function will return the method +signatures of each given object.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a new function implementing the method call described in +options.

+
+ + + +
+
+ Type +
+
+ +LuCI.rpc~invokeFn + + +
+
+ + + + + + + + + + + + + +

getBaseURL() → {string}

+ + + + + + +
+

Returns the current RPC base URL.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the RPC URL endpoint to issue requests against.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getSessionID() → {string}

+ + + + + + +
+

Returns the current RPC session id.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the 32 byte session ID string used for authenticating remote +requests.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

getStatusText(statusCode) → {string}

+ + + + + + +
+

Translates a numeric ubus error code into a human readable +description.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
statusCode + + +number + + + +

The numeric status code.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the textual description of the code.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

list(…objectNamesopt) → {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.
  • +
+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
objectNames + + +string + + + + + + <optional>
+ + + + + + <repeatable>
+ +

If any object names are given, this function will return the method +signatures of each given object.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<(Array.<string>|Object.<string, Object.<string, Object.<string, string>>>)> + + +
+
+ + + + + + + + + + + + + +

removeInterceptor(interceptorFn) → {boolean}

+ + + + + + +
+

Removes a registered interceptor function.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
interceptorFn + + +LuCI.rpc~interceptorFn + + + +

The inteceptor function to remove.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true if the given function has been removed or false +if it has not been found.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

setBaseURL(sid)

+ + + + + + +
+

Set the RPC base URL to use.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
sid + + +string + + + +

Sets the RPC URL endpoint to issue requests against.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

setSessionID(sid)

+ + + + + + +
+

Set the RPC session id to use.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
sid + + +string + + + +

Sets the 32 byte session ID string used for authenticating remote +requests.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Type Definitions

+ + + +

DeclareOptions

+ + + + + + +
Type:
+
    +
  • + +Object + + +
  • +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + +

filterFn(data, args, …extraArgs) → {*}

+ + + + + + +
+

The filter function is invoked to transform a received ubus RPC call +reply before returning it to the caller.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

The return value of the filter function will be returned to the caller +of the RPC method as-is.

+
+ + + +
+
+ Type +
+
+ +* + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<*> +| + +* + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +Promise.<*> + + +
+
+ + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.uci.html b/documentation/jsapi/LuCI.uci.html new file mode 100644 index 000000000..8a0e3e98f --- /dev/null +++ b/documentation/jsapi/LuCI.uci.html @@ -0,0 +1,4176 @@ + + + + + JSDoc: 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.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

Methods

+ + + + + + + +

add(config, type, nameopt) → {string}

+ + + + + + +
+

Adds a new section of the given type to the given configuration, +optionally named according to the given name.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns the section ID of the newly added section which is equivalent +to the given name for non-anonymous sections.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

apply(timeoutopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
timeout + + +number + + + + + + <optional>
+ + + + + +
+ + 10 + +

Override the confirmation timeout after which a rollback is triggered.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving/rejecting with the ubus RPC status code.

+
+ + + +
+
+ Type +
+
+ +Promise.<number> + + +
+
+ + + + + + + + + + + + + +

changes() → {Promise.<Object.<string, Array.<LuCI.uci.ChangeRecord>>>}

+ + + + + + +
+

Fetches uncommitted UCI changes from the remote ubus RPC api.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an object containing the configuration +names as keys and arrays of related change records as values.

+
+ + + +
+
+ Type +
+
+ +Promise.<Object.<string, Array.<LuCI.uci.ChangeRecord>>> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
config + + +string + + + +

The configuration to generate the new section ID for.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

A newly generated, unique section ID in the form newXXXXXX +where X denotes a hexadecimal digit.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + + + + +

get(config, sid, optionopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • 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.
  • +
+
+ + + +
+
+ Type +
+
+ +null +| + +string +| + +Array.<string> +| + +LuCI.uci.SectionObject + + +
+
+ + + + + + + + + + + + + +

get_first(config, typeopt, optionopt) → {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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+
    +
  • 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.
  • +
+
+ + + +
+
+ Type +
+
+ +null +| + +string +| + +Array.<string> +| + +LuCI.uci.SectionObject + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
config + + +string +| + +Array.<string> + + + +

The name of the configuration or an array of configuration +names to load.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to the names of the configurations +that have been successfully loaded.

+
+ + + +
+
+ Type +
+
+ +Promise.<Array.<string>> + + +
+
+ + + + + + + + + + + + + +

move(config, sid1, sid2opt, afteropt) → {boolean}

+ + + + + + +
+

Move the first specified section within the given configuration +before or after the second specified section.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
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 + + + + + + <optional>
+ + + + + +
+ + false + +

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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns true when the section was successfully moved, or false +when either the section specified by sid1 or by sid2 is not found.

+
+ + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + + + + + +

remove(config, sid)

+ + + + + + +
+

Removes the section with the given ID from the given configuration.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
config + + +string + + + +

The name of the configuration to remove the section from.

sid + + +string + + + +

The ID of the section to remove.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

resolveSID(config, sid) → {string|null}

+ + + + + + +
+

Resolves a given section ID in extended notation to the internal +section ID value.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +string +| + +null + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a promise resolving to an array of configuration names which +have been reloaded by the save operation.

+
+ + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + + +

sections(config, typeopt, cbopt) → {Array.<LuCI.uci.SectionObject>}

+ + + + + + +
+

Enumerates the sections of the given configuration, optionally +filtered by type.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Returns a sorted array of the section objects within the given +configuration, filtered by type of a type has been specified.

+
+ + + +
+
+ Type +
+
+ +Array.<LuCI.uci.SectionObject> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

set_first(config, typeopt, 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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

unload(config)

+ + + + + + +
+

Unloads the given UCI configurations from the local cache.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
config + + +string +| + +Array.<string> + + + +

The name of the configuration or an array of configuration +names to unload.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

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).

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

unset_first(config, typeopt, 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).

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
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.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +

Type Definitions

+ + + +

ChangeRecord

+ + + + +
+

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.

+
+ + + +
Type:
+
    +
  • + +Array.<string> + + +
  • +
+ + + + + +
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.
  • +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + +

SectionObject

+ + + + +
+

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.

+
+ + + +
Type:
+
    +
  • + +Object.<string, (boolean|number|string|Array.<string>)> + + +
  • +
+ + + + + +
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.

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
section + + +LuCI.uci.SectionObject + + + +

The section object.

sid + + +string + + + +

The name or ID of the section.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/LuCI.view.html b/documentation/jsapi/LuCI.view.html new file mode 100644 index 000000000..4a7209ceb --- /dev/null +++ b/documentation/jsapi/LuCI.view.html @@ -0,0 +1,1125 @@ + + + + + JSDoc: Class: view + + + + + + + + + + +
+ +

Class: view

+ + + + + + +
+ +
+ +

+ LuCI.view

+ +

The view class forms the basis of views and provides a standard +set of methods to inherit from.

+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +

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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +DocumentFragment + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
ev + + +Event + + + +

The DOM event that triggered the function.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +* +| + +Promise.<*> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
ev + + +Event + + + +

The DOM event that triggered the function.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +* +| + +Promise.<*> + + +
+
+ + + + + + + + + + + + + +

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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
ev + + +Event + + + +

The DOM event that triggered the function.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

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.

+
+ + + +
+
+ Type +
+
+ +* +| + +Promise.<*> + + +
+
+ + + + + + + + + + + + + +

(abstract) load() → {*|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.

+
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

May return any value or a Promise resolving to any value.

+
+ + + +
+
+ Type +
+
+ +* +| + +Promise.<*> + + +
+
+ + + + + + + + + + + + + +

(abstract) render(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.

+
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
load_results + + +* +| + +null + + + +

This function will receive the return value of the +view.load() function as first +argument.

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + +
+

Should return a DOM Node value or a Promise resolving +to a Node value.

+
+ + + +
+
+ Type +
+
+ +Node +| + +Promise.<Node> + + +
+
+ + + + + + + + + + + + + +
+ +
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/fonts/OpenSans-Bold-webfont.eot b/documentation/jsapi/fonts/OpenSans-Bold-webfont.eot new file mode 100644 index 000000000..5d20d9163 Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-Bold-webfont.eot differ diff --git a/documentation/jsapi/fonts/OpenSans-Bold-webfont.svg b/documentation/jsapi/fonts/OpenSans-Bold-webfont.svg new file mode 100644 index 000000000..3ed7be4bc --- /dev/null +++ b/documentation/jsapi/fonts/OpenSans-Bold-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/jsapi/fonts/OpenSans-Bold-webfont.woff b/documentation/jsapi/fonts/OpenSans-Bold-webfont.woff new file mode 100644 index 000000000..1205787b0 Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-Bold-webfont.woff differ diff --git a/documentation/jsapi/fonts/OpenSans-BoldItalic-webfont.eot b/documentation/jsapi/fonts/OpenSans-BoldItalic-webfont.eot new file mode 100644 index 000000000..1f639a15f Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-BoldItalic-webfont.eot differ diff --git a/documentation/jsapi/fonts/OpenSans-BoldItalic-webfont.svg b/documentation/jsapi/fonts/OpenSans-BoldItalic-webfont.svg new file mode 100644 index 000000000..6a2607b9d --- /dev/null +++ b/documentation/jsapi/fonts/OpenSans-BoldItalic-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/jsapi/fonts/OpenSans-BoldItalic-webfont.woff b/documentation/jsapi/fonts/OpenSans-BoldItalic-webfont.woff new file mode 100644 index 000000000..ed760c062 Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-BoldItalic-webfont.woff differ diff --git a/documentation/jsapi/fonts/OpenSans-Italic-webfont.eot b/documentation/jsapi/fonts/OpenSans-Italic-webfont.eot new file mode 100644 index 000000000..0c8a0ae06 Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-Italic-webfont.eot differ diff --git a/documentation/jsapi/fonts/OpenSans-Italic-webfont.svg b/documentation/jsapi/fonts/OpenSans-Italic-webfont.svg new file mode 100644 index 000000000..e1075dcc2 --- /dev/null +++ b/documentation/jsapi/fonts/OpenSans-Italic-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/jsapi/fonts/OpenSans-Italic-webfont.woff b/documentation/jsapi/fonts/OpenSans-Italic-webfont.woff new file mode 100644 index 000000000..ff652e643 Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-Italic-webfont.woff differ diff --git a/documentation/jsapi/fonts/OpenSans-Light-webfont.eot b/documentation/jsapi/fonts/OpenSans-Light-webfont.eot new file mode 100644 index 000000000..14868406a Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-Light-webfont.eot differ diff --git a/documentation/jsapi/fonts/OpenSans-Light-webfont.svg b/documentation/jsapi/fonts/OpenSans-Light-webfont.svg new file mode 100644 index 000000000..11a472ca8 --- /dev/null +++ b/documentation/jsapi/fonts/OpenSans-Light-webfont.svg @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/jsapi/fonts/OpenSans-Light-webfont.woff b/documentation/jsapi/fonts/OpenSans-Light-webfont.woff new file mode 100644 index 000000000..e78607481 Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-Light-webfont.woff differ diff --git a/documentation/jsapi/fonts/OpenSans-LightItalic-webfont.eot b/documentation/jsapi/fonts/OpenSans-LightItalic-webfont.eot new file mode 100644 index 000000000..8f445929f Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-LightItalic-webfont.eot differ diff --git a/documentation/jsapi/fonts/OpenSans-LightItalic-webfont.svg b/documentation/jsapi/fonts/OpenSans-LightItalic-webfont.svg new file mode 100644 index 000000000..431d7e354 --- /dev/null +++ b/documentation/jsapi/fonts/OpenSans-LightItalic-webfont.svg @@ -0,0 +1,1835 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/jsapi/fonts/OpenSans-LightItalic-webfont.woff b/documentation/jsapi/fonts/OpenSans-LightItalic-webfont.woff new file mode 100644 index 000000000..43e8b9e6c Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-LightItalic-webfont.woff differ diff --git a/documentation/jsapi/fonts/OpenSans-Regular-webfont.eot b/documentation/jsapi/fonts/OpenSans-Regular-webfont.eot new file mode 100644 index 000000000..6bbc3cf58 Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-Regular-webfont.eot differ diff --git a/documentation/jsapi/fonts/OpenSans-Regular-webfont.svg b/documentation/jsapi/fonts/OpenSans-Regular-webfont.svg new file mode 100644 index 000000000..25a395234 --- /dev/null +++ b/documentation/jsapi/fonts/OpenSans-Regular-webfont.svg @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/documentation/jsapi/fonts/OpenSans-Regular-webfont.woff b/documentation/jsapi/fonts/OpenSans-Regular-webfont.woff new file mode 100644 index 000000000..e231183dc Binary files /dev/null and b/documentation/jsapi/fonts/OpenSans-Regular-webfont.woff differ diff --git a/documentation/jsapi/fs.js.html b/documentation/jsapi/fs.js.html new file mode 100644 index 000000000..3ee1af8e6 --- /dev/null +++ b/documentation/jsapi/fs.js.html @@ -0,0 +1,350 @@ + + + + + JSDoc: Source: fs.js + + + + + + + + + + +
+ +

Source: fs.js

+ + + + + + +
+
+
'use strict';
+'require rpc';
+
+/**
+ * @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;
+}
+
+/**
+ * @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 = L.Class.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;
+		});
+	}
+});
+
+return FileSystem;
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + diff --git a/documentation/jsapi/index.html b/documentation/jsapi/index.html new file mode 100644 index 000000000..d6997c8d8 --- /dev/null +++ b/documentation/jsapi/index.html @@ -0,0 +1,90 @@ + + + + + JSDoc: Home + + + + + + + + + + +
+ +

Home

+ + + + + + + + +

+ + + + + + + + + + + + + + + +
+

OpenWrt luci feed

+

Translation status

+

Description

+

This is the OpenWrt "luci"-feed containing LuCI - OpenWrt Configuration Interface.

+

Usage

+

This feed is enabled by default. Your feeds.conf.default (or feeds.conf) should contain a line like:

+
src-git luci https://github.com/openwrt/luci.git
+
+

To install all its package definitions, run:

+
./scripts/feeds update luci
+./scripts/feeds install -a -p luci
+
+

API Reference

+

You can browse the generated API documentation directly on Github.

+

Development

+

Documentation for developing and extending LuCI can be found in the Wiki

+

License

+

See LICENSE file.

+

Package Guidelines

+

See CONTRIBUTING.md file.

+

Translation status

+

Translation status

+
+ + + + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + \ No newline at end of file diff --git a/documentation/jsapi/luci.js.html b/documentation/jsapi/luci.js.html new file mode 100644 index 000000000..7cad32ce5 --- /dev/null +++ b/documentation/jsapi/luci.js.html @@ -0,0 +1,3125 @@ + + + + + JSDoc: 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';
+
+	/* 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 Class
+	 * @hideconstructor
+	 * @memberof LuCI
+	 * @classdesc
+	 *
+	 * `LuCI.Class` 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 = null, Class = Object.assign(function() {}, {
+		/**
+		 * Extends this base class with the properties described in
+		 * `properties` and returns a new subclassed Class instance
+		 *
+		 * @memberof LuCI.Class
+		 *
+		 * @param {Object<string, *>} properties
+		 * An object describing the properties to add to the new
+		 * subclass.
+		 *
+		 * @returns {LuCI.Class}
+		 * Returns a new LuCI.Class 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 = {
+				__base__: { value: this.prototype },
+				__name__: { value: properties.__name__ || 'anonymous' }
+			};
+
+			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.Class.extend Class.extend()} and subsequent
+		 * `new`.
+		 *
+		 * @memberof LuCI.Class
+		 *
+		 * @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.Class}
+		 * Returns a new LuCI.Class 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.Class
+		 *
+		 * @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.Class}
+		 * Returns a new LuCI.Class 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.Class
+		 *
+		 * @param {LuCI.Class} 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.Class
+			 * @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.Class
+			 * @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) {
+				for (superContext = Object.getPrototypeOf(superContext ||
+				                                          Object.getPrototypeOf(this));
+				     superContext && !superContext.hasOwnProperty(key);
+				     superContext = Object.getPrototypeOf(superContext)) { }
+
+				if (!superContext)
+					return null;
+
+				var res = superContext[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);
+
+					res = res.apply(this, callArgs);
+				}
+
+				superContext = null;
+
+				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
+	 * @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.XHR.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
+	 * @memberof LuCI
+	 * @hideconstructor
+	 * @classdesc
+	 *
+	 * The `Response` class is an internal utility class representing HTTP responses.
+	 */
+	var Response = Class.extend({
+		__name__: 'LuCI.XHR.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 != null && typeof(content) == 'object') {
+				this.responseJSON = content;
+				this.responseText = null;
+			}
+			else if (content != null) {
+				this.responseJSON = null;
+				this.responseText = String(content);
+			}
+			else {
+				this.responseJSON = 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;
+		}
+	});
+
+
+	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
+	 * @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 {*} [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 = '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
+	 * @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 = window.L ? window.L.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);
+		}
+	});
+
+
+	var dummyElem = null,
+	    domParser = null,
+	    originalCBIInit = null,
+	    rpcBaseURL = null,
+	    sysFeatures = null,
+	    classes = {};
+
+	var LuCI = Class.extend(/** @lends LuCI.prototype */ {
+		__name__: 'LuCI',
+		__init__: function(env) {
+
+			document.querySelectorAll('script[src*="/luci.js"]').forEach(function(s) {
+				if (env.base_url == null || env.base_url == '') {
+					var m = (s.getAttribute('src') || '').match(/^(.*)\/luci\.js(?:\?v=([^?]+))?$/);
+					if (m) {
+						env.base_url = m[1];
+						env.resource_version = m[2];
+					}
+				}
+			});
+
+			if (env.base_url == null)
+				this.error('InternalError', 'Cannot find url of luci.js');
+
+			Object.assign(this.env, env);
+
+			document.addEventListener('poll-start', function(ev) {
+				document.querySelectorAll('[id^="xhr_poll_status"]').forEach(function(e) {
+					e.style.display = (e.id == 'xhr_poll_status_off') ? 'none' : '';
+				});
+			});
+
+			document.addEventListener('poll-stop', function(ev) {
+				document.querySelectorAll('[id^="xhr_poll_status"]').forEach(function(e) {
+					e.style.display = (e.id == 'xhr_poll_status_on') ? 'none' : '';
+				});
+			});
+
+			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 {
+				L.raise.apply(L, Array.prototype.slice.call(arguments));
+			}
+			catch (e) {
+				if (!e.reported) {
+					if (L.ui)
+						L.ui.addNotification(e.name || _('Runtime error'),
+							E('pre', {}, e.message), 'danger');
+					else
+						L.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#Class>}
+		 * 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)
+					L.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(L.env.base_url, name.replace(/\./g, '/'), (L.env.resource_version ? '?v=' + L.env.resource_version : ''));
+			from = [ name ].concat(from);
+
+			var compileClass = function(res) {
+				if (!res.ok)
+					L.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, quote = -1, esc = false; i < source.length; i++) {
+					var chr = source.charCodeAt(i);
+
+					if (esc) {
+						esc = false;
+					}
+					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(L.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;
+					}
+				}
+
+				/* 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) {
+						L.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))
+					    L.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) {
+				try {
+					rpcBaseURL = window.sessionStorage.getItem('rpcBaseURL');
+				}
+				catch (e) { }
+			}
+
+			if (rpcBaseURL == null) {
+				var rpcFallbackURL = this.url('admin/ubus');
+
+				rpcBaseURL = Request.get('/ubus/').then(function(res) {
+					return (rpcBaseURL = (res.status == 400) ? '/ubus/' : rpcFallbackURL);
+				}, function() {
+					return (rpcBaseURL = rpcFallbackURL);
+				}).then(function(url) {
+					try {
+						window.sessionStorage.setItem('rpcBaseURL', url);
+					}
+					catch (e) { }
+
+					return url;
+				});
+			}
+
+			return Promise.resolve(rpcBaseURL);
+		},
+
+		probeSystemFeatures: function() {
+			var sessionid = classes.rpc.getSessionID();
+
+			if (sysFeatures == null) {
+				try {
+					var data = JSON.parse(window.sessionStorage.getItem('sysFeatures'));
+
+					if (this.isObject(data) && this.isObject(data[sessionid]))
+						sysFeatures = data[sessionid];
+				}
+				catch (e) {}
+			}
+
+			if (!this.isObject(sysFeatures)) {
+				sysFeatures = classes.rpc.declare({
+					object: 'luci',
+					method: 'getFeatures',
+					expect: { '': {} }
+				})().then(function(features) {
+					try {
+						var data = {};
+						    data[sessionid] = features;
+
+						window.sessionStorage.setItem('sysFeatures', JSON.stringify(data));
+					}
+					catch (e) {}
+
+					sysFeatures = features;
+
+					return features;
+				});
+			}
+
+			return Promise.resolve(sysFeatures);
+		},
+
+		/**
+		 * 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();
+
+			L.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…')))
+			]);
+
+			L.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 (!L.isObject(msg) || !L.isObject(msg.error) || msg.error.code != -32002)
+					return;
+
+				if (!L.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(L.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;
+
+				L.notifySessionExpiry();
+			});
+
+			return this.probeSystemFeatures().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: {},
+
+		/**
+		 * 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(this.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(this.env.resource, 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(this.env.scriptname, this.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 = this.env.pollinterval;
+
+			var data = post ? { token: this.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);
+					});
+		},
+
+		/**
+		 * 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() },
+
+
+		/**
+		 * @class
+		 * @memberof LuCI
+		 * @hideconstructor
+		 * @classdesc
+		 *
+		 * The `dom` class provides convenience method for creating and
+		 * manipulating DOM elements.
+		 */
+		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) {
+				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))
+					L.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;
+			}
+		}),
+
+		Poll: Poll,
+		Class: Class,
+		Request: Request,
+
+		/**
+		 * @class
+		 * @memberof LuCI
+		 * @hideconstructor
+		 * @classdesc
+		 *
+		 * The `view` class forms the basis of views and provides a standard
+		 * set of methods to inherit from.
+		 */
+		view: Class.extend(/* @lends LuCI.view.prototype */ {
+			__name__: 'LuCI.View',
+
+			__init__: function() {
+				var vp = document.getElementById('view');
+
+				L.dom.content(vp, E('div', { 'class': 'spinning' }, _('Loading view…')));
+
+				return Promise.resolve(this.load())
+					.then(L.bind(this.render, this))
+					.then(L.bind(function(nodes) {
+						var vp = document.getElementById('view');
+
+						L.dom.content(vp, nodes);
+						L.dom.append(vp, this.addFooter());
+					}, this)).catch(L.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(L.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) {
+				return this.handleSave(ev).then(function() {
+					L.ui.changes.apply(true);
+				});
+			},
+
+			/**
+			 * 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(L.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([]);
+
+				if (this.handleSaveApply || this.handleSave || this.handleReset) {
+					footer.appendChild(E('div', { 'class': 'cbi-page-actions' }, [
+						this.handleSaveApply ? E('button', {
+							'class': 'cbi-button cbi-button-apply',
+							'click': L.ui.createHandlerFn(this, 'handleSaveApply')
+						}, [ _('Save & Apply') ]) : '', ' ',
+						this.handleSave ? E('button', {
+							'class': 'cbi-button cbi-button-save',
+							'click': L.ui.createHandlerFn(this, 'handleSave')
+						}, [ _('Save') ]) : '', ' ',
+						this.handleReset ? E('button', {
+							'class': 'cbi-button cbi-button-reset',
+							'click': L.ui.createHandlerFn(this, 'handleReset')
+						}, [ _('Reset') ]) : ''
+					]));
+				}
+
+				return footer;
+			}
+		})
+	});
+
+	/**
+	 * @class
+	 * @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;
+			L.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;
+			L.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() { L.error('InternalError', 'Not implemented') },
+	});
+
+	XHR.get = function() { return window.L.get.apply(window.L, arguments) };
+	XHR.post = function() { return window.L.post.apply(window.L, arguments) };
+	XHR.poll = function() { return window.L.poll.apply(window.L, 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 Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + diff --git a/documentation/jsapi/network.js.html b/documentation/jsapi/network.js.html new file mode 100644 index 000000000..e06633357 --- /dev/null +++ b/documentation/jsapi/network.js.html @@ -0,0 +1,4038 @@ + + + + + JSDoc: Source: network.js + + + + + + + + + + +
+ +

Source: network.js

+ + + + + + +
+
+
'use strict';
+'require uci';
+'require rpc';
+'require validation';
+
+var proto_errors = {
+	CONNECT_FAILED:			_('Connection attempt failed'),
+	INVALID_ADDRESS:		_('IP address in 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'))
+			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(),
+			uci.load(['network', 'wireless', '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: {}
+			};
+
+			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,
+					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;
+
+			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
+ * @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 = L.Class.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() {});
+
+		return Promise.all([ requireFirewall, initNetworkState() ]).then(function() {
+			var uciInterface = uci.get('network', name);
+
+			if (uciInterface != null && uciInterface['.type'] == 'interface') {
+				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 (L.firewall)
+					return L.firewall.deleteNetwork(name).then(function() { return true });
+
+				return true;
+			}
+
+			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) || isVirtualIfname(ifname) || isWifiIfname(ifname))
+					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);
+			}
+
+			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) {
+		var sid, res, netid, radioname, radiostate, netstate;
+
+		return initNetworkState().then(L.bind(function() {
+			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);
+		}, 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 = [];
+
+			for (var i = 0; i < statuses.length; i++)
+				rv.push(this.instantiateNetwork(statuses[i].interface, statuses[i].proto));
+
+			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 = [];
+
+			for (var i = 0; i < statuses.length; i++)
+				rv.push(this.instantiateNetwork(statuses[i].interface, statuses[i].proto));
+
+			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) {
+		return new WifiNetwork(sid, radioname, radiostate, netid, netstate);
+	},
+
+	/**
+	 * 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 = L.Class.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 = L.Class.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;
+	},
+
+	/**
+	 * 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 L.network.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]) ? L.network.instantiateDevice(m[1], this) : null);
+			}
+
+			ifname = getWifiNetidByNetname(this.sid);
+
+			return (ifname != null ? L.network.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 ? L.network.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 ? L.network.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(L.network.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(L.network.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;
+	}
+});
+
+/**
+ * @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 = L.Class.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(L.network.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 = L.Class.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 L.network.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() {
+		var uciWifiIfaces = uci.sections('wireless', 'wifi-iface'),
+		    tasks = [];
+
+		for (var i = 0; i < uciWifiIfaces.length; i++)
+			if (uciWifiIfaces[i].device == this.sid)
+				tasks.push(L.network.getWifiNetwork(uciWifiIfaces[i]['.name']));
+
+		return Promise.all(tasks);
+	},
+
+	/**
+	 * 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 L.network.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 = L.Class.extend(/** @lends LuCI.Network.WifiNetwork.prototype */ {
+	__init__: function(sid, radioname, radiostate, netid, netstate) {
+		this.sid    = sid;
+		this.netid  = netid;
+		this._ubusdata = {
+			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 L.network.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(L.network.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 L.network.instantiateDevice(this.getIfname());
+	}
+});
+
+return Network;
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + diff --git a/documentation/jsapi/rpc.js.html b/documentation/jsapi/rpc.js.html new file mode 100644 index 000000000..ca068f31b --- /dev/null +++ b/documentation/jsapi/rpc.js.html @@ -0,0 +1,528 @@ + + + + + JSDoc: Source: rpc.js + + + + + + + + + + +
+ +

Source: rpc.js

+ + + + + + +
+
+
'use strict';
+
+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 L.Class.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 L.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)) {
+			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.
+	 *
+	 */
+
+	/**
+	 * 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
+				};
+
+				/* 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 Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + diff --git a/documentation/jsapi/scripts/linenumber.js b/documentation/jsapi/scripts/linenumber.js new file mode 100644 index 000000000..4354785ce --- /dev/null +++ b/documentation/jsapi/scripts/linenumber.js @@ -0,0 +1,25 @@ +/*global document */ +(() => { + const source = document.getElementsByClassName('prettyprint source linenums'); + let i = 0; + let lineNumber = 0; + let lineId; + let lines; + let totalLines; + let anchorHash; + + if (source && source[0]) { + anchorHash = document.location.hash.substring(1); + lines = source[0].getElementsByTagName('li'); + totalLines = lines.length; + + for (; i < totalLines; i++) { + lineNumber++; + lineId = `line${lineNumber}`; + lines[i].id = lineId; + if (lineId === anchorHash) { + lines[i].className += ' selected'; + } + } + } +})(); diff --git a/documentation/jsapi/scripts/prettify/Apache-License-2.0.txt b/documentation/jsapi/scripts/prettify/Apache-License-2.0.txt new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/documentation/jsapi/scripts/prettify/Apache-License-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/documentation/jsapi/scripts/prettify/lang-css.js b/documentation/jsapi/scripts/prettify/lang-css.js new file mode 100644 index 000000000..041e1f590 --- /dev/null +++ b/documentation/jsapi/scripts/prettify/lang-css.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", +/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/documentation/jsapi/scripts/prettify/prettify.js b/documentation/jsapi/scripts/prettify/prettify.js new file mode 100644 index 000000000..eef5ad7e6 --- /dev/null +++ b/documentation/jsapi/scripts/prettify/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p th:last-child { border-right: 1px solid #ddd; } + +.ancestors, .attribs { color: #999; } +.ancestors a, .attribs a +{ + color: #999 !important; + text-decoration: none; +} + +.clear +{ + clear: both; +} + +.important +{ + font-weight: bold; + color: #950B02; +} + +.yes-def { + text-indent: -1000px; +} + +.type-signature { + color: #aaa; +} + +.name, .signature { + font-family: Consolas, Monaco, 'Andale Mono', monospace; +} + +.details { margin-top: 14px; border-left: 2px solid #DDD; } +.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } +.details dd { margin-left: 70px; } +.details ul { margin: 0; } +.details ul { list-style-type: none; } +.details li { margin-left: 30px; padding-top: 6px; } +.details pre.prettyprint { margin: 0 } +.details .object-value { padding-top: 0; } + +.description { + margin-bottom: 1em; + margin-top: 1em; +} + +.code-caption +{ + font-style: italic; + font-size: 107%; + margin: 0; +} + +.source +{ + border: 1px solid #ddd; + width: 80%; + overflow: auto; +} + +.prettyprint.source { + width: inherit; +} + +.source code +{ + font-size: 100%; + line-height: 18px; + display: block; + padding: 4px 12px; + margin: 0; + background-color: #fff; + color: #4D4E53; +} + +.prettyprint code span.line +{ + display: inline-block; +} + +.prettyprint.linenums +{ + padding-left: 70px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.prettyprint.linenums ol +{ + padding-left: 0; +} + +.prettyprint.linenums li +{ + border-left: 3px #ddd solid; +} + +.prettyprint.linenums li.selected, +.prettyprint.linenums li.selected * +{ + background-color: lightyellow; +} + +.prettyprint.linenums li * +{ + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.params .name, .props .name, .name code { + color: #4D4E53; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 100%; +} + +.params td.description > p:first-child, +.props td.description > p:first-child +{ + margin-top: 0; + padding-top: 0; +} + +.params td.description > p:last-child, +.props td.description > p:last-child +{ + margin-bottom: 0; + padding-bottom: 0; +} + +.disabled { + color: #454545; +} diff --git a/documentation/jsapi/styles/prettify-jsdoc.css b/documentation/jsapi/styles/prettify-jsdoc.css new file mode 100644 index 000000000..5a2526e37 --- /dev/null +++ b/documentation/jsapi/styles/prettify-jsdoc.css @@ -0,0 +1,111 @@ +/* JSDoc prettify.js theme */ + +/* plain text */ +.pln { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* string content */ +.str { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a keyword */ +.kwd { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a comment */ +.com { + font-weight: normal; + font-style: italic; +} + +/* a type name */ +.typ { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a literal value */ +.lit { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* punctuation */ +.pun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp open bracket */ +.opn { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp close bracket */ +.clo { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a markup tag name */ +.tag { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute name */ +.atn { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute value */ +.atv { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a declaration */ +.dec { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a variable name */ +.var { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a function name */ +.fun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; +} diff --git a/documentation/jsapi/styles/prettify-tomorrow.css b/documentation/jsapi/styles/prettify-tomorrow.css new file mode 100644 index 000000000..b6f92a78d --- /dev/null +++ b/documentation/jsapi/styles/prettify-tomorrow.css @@ -0,0 +1,132 @@ +/* Tomorrow Theme */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* Pretty printing styles. Used with prettify.js. */ +/* SPAN elements with the classes below are added by prettyprint. */ +/* plain text */ +.pln { + color: #4d4d4c; } + +@media screen { + /* string content */ + .str { + color: #718c00; } + + /* a keyword */ + .kwd { + color: #8959a8; } + + /* a comment */ + .com { + color: #8e908c; } + + /* a type name */ + .typ { + color: #4271ae; } + + /* a literal value */ + .lit { + color: #f5871f; } + + /* punctuation */ + .pun { + color: #4d4d4c; } + + /* lisp open bracket */ + .opn { + color: #4d4d4c; } + + /* lisp close bracket */ + .clo { + color: #4d4d4c; } + + /* a markup tag name */ + .tag { + color: #c82829; } + + /* a markup attribute name */ + .atn { + color: #f5871f; } + + /* a markup attribute value */ + .atv { + color: #3e999f; } + + /* a declaration */ + .dec { + color: #f5871f; } + + /* a variable name */ + .var { + color: #c82829; } + + /* a function name */ + .fun { + color: #4271ae; } } +/* Use higher contrast and text-weight for printable form. */ +@media print, projection { + .str { + color: #060; } + + .kwd { + color: #006; + font-weight: bold; } + + .com { + color: #600; + font-style: italic; } + + .typ { + color: #404; + font-weight: bold; } + + .lit { + color: #044; } + + .pun, .opn, .clo { + color: #440; } + + .tag { + color: #006; + font-weight: bold; } + + .atn { + color: #404; } + + .atv { + color: #060; } } +/* Style */ +/* +pre.prettyprint { + background: white; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 12px; + line-height: 1.5; + border: 1px solid #ccc; + padding: 10px; } +*/ + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; } + +/* IE indents via margin-left */ +li.L0, +li.L1, +li.L2, +li.L3, +li.L4, +li.L5, +li.L6, +li.L7, +li.L8, +li.L9 { + /* */ } + +/* Alternate shading for lines */ +li.L1, +li.L3, +li.L5, +li.L7, +li.L9 { + /* */ } diff --git a/documentation/jsapi/uci.js.html b/documentation/jsapi/uci.js.html new file mode 100644 index 000000000..d61010f0e --- /dev/null +++ b/documentation/jsapi/uci.js.html @@ -0,0 +1,994 @@ + + + + + JSDoc: Source: uci.js + + + + + + + + + + +
+ +

Source: uci.js

+ + + + + + +
+
+
'use strict';
+'require rpc';
+
+/**
+ * @class uci
+ * @memberof LuCI
+ * @hideconstructor
+ * @classdesc
+ *
+ * The `LuCI.uci` class utilizes {@link 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.
+ */
+return L.Class.extend(/** @lends LuCI.uci.prototype */ {
+	__init__: function() {
+		this.state = {
+			newidx:  0,
+			values:  { },
+			creates: { },
+			changes: { },
+			deletes: { },
+			reorder: { }
+		};
+
+		this.loaded = {};
+	},
+
+	callLoad: rpc.declare({
+		object: 'uci',
+		method: 'get',
+		params: [ 'config' ],
+		expect: { values: { } }
+	}),
+
+
+	callOrder: rpc.declare({
+		object: 'uci',
+		method: 'order',
+		params: [ 'config', 'sections' ]
+	}),
+
+	callAdd: rpc.declare({
+		object: 'uci',
+		method: 'add',
+		params: [ 'config', 'type', 'name', 'values' ],
+		expect: { section: '' }
+	}),
+
+	callSet: rpc.declare({
+		object: 'uci',
+		method: 'set',
+		params: [ 'config', 'section', 'values' ]
+	}),
+
+	callDelete: rpc.declare({
+		object: 'uci',
+		method: 'delete',
+		params: [ 'config', 'section', 'options' ]
+	}),
+
+	callApply: rpc.declare({
+		object: 'uci',
+		method: 'apply',
+		params: [ 'timeout', 'rollback' ]
+	}),
+
+	callConfirm: rpc.declare({
+		object: 'uci',
+		method: 'confirm'
+	}),
+
+
+	/**
+	 * 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.
+	 *
+	 * @param {string} config
+	 * The configuration to generate the new section ID for.
+	 *
+	 * @returns {string}
+	 * A newly generated, unique section ID in the form `newXXXXXX`
+	 * where `X` denotes a hexadecimal digit.
+	 */
+	createSID: function(conf) {
+		var v = this.state.values,
+		    n = this.state.creates,
+		    sid;
+
+		do {
+			sid = "new%06x".format(Math.random() * 0xFFFFFF);
+		} while ((n[conf] && n[conf][sid]) || (v[conf] && v[conf][sid]));
+
+		return sid;
+	},
+
+	/**
+	 * Resolves a given section ID in extended notation to the internal
+	 * section ID value.
+	 *
+	 * @param {string} config
+	 * The configuration to resolve the section ID for.
+	 *
+	 * @param {string} sid
+	 * 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 {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.
+	 */
+	resolveSID: function(conf, sid) {
+		if (typeof(sid) != 'string')
+			return sid;
+
+		var m = /^@([a-zA-Z0-9_-]+)\[(-?[0-9]+)\]$/.exec(sid);
+
+		if (m) {
+			var type = m[1],
+			    pos = +m[2],
+			    sections = this.sections(conf, type),
+			    section = sections[pos >= 0 ? pos : sections.length + pos];
+
+			return section ? section['.name'] : null;
+		}
+
+		return sid;
+	},
+
+	/* private */
+	reorderSections: function() {
+		var v = this.state.values,
+		    n = this.state.creates,
+		    r = this.state.reorder,
+		    tasks = [];
+
+		if (Object.keys(r).length === 0)
+			return Promise.resolve();
+
+		/*
+		 gather all created and existing sections, sort them according
+		 to their index value and issue an uci order call
+		*/
+		for (var c in r) {
+			var o = [ ];
+
+			if (n[c])
+				for (var s in n[c])
+					o.push(n[c][s]);
+
+			for (var s in v[c])
+				o.push(v[c][s]);
+
+			if (o.length > 0) {
+				o.sort(function(a, b) {
+					return (a['.index'] - b['.index']);
+				});
+
+				var sids = [ ];
+
+				for (var i = 0; i < o.length; i++)
+					sids.push(o[i]['.name']);
+
+				tasks.push(this.callOrder(c, sids));
+			}
+		}
+
+		this.state.reorder = { };
+		return Promise.all(tasks);
+	},
+
+	/* private */
+	loadPackage: function(packageName) {
+		if (this.loaded[packageName] == null)
+			return (this.loaded[packageName] = this.callLoad(packageName));
+
+		return Promise.resolve(this.loaded[packageName]);
+	},
+
+	/**
+	 * 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
+	 * {@link LuCI.uci#unload uci.unload()} first.
+	 *
+	 * @param {string|string[]} config
+	 * The name of the configuration or an array of configuration
+	 * names to load.
+	 *
+	 * @returns {Promise<string[]>}
+	 * Returns a promise resolving to the names of the configurations
+	 * that have been successfully loaded.
+	 */
+	load: function(packages) {
+		var self = this,
+		    pkgs = [ ],
+		    tasks = [];
+
+		if (!Array.isArray(packages))
+			packages = [ packages ];
+
+		for (var i = 0; i < packages.length; i++)
+			if (!self.state.values[packages[i]]) {
+				pkgs.push(packages[i]);
+				tasks.push(self.loadPackage(packages[i]));
+			}
+
+		return Promise.all(tasks).then(function(responses) {
+			for (var i = 0; i < responses.length; i++)
+				self.state.values[pkgs[i]] = responses[i];
+
+			if (responses.length)
+				document.dispatchEvent(new CustomEvent('uci-loaded'));
+
+			return pkgs;
+		});
+	},
+
+	/**
+	 * Unloads the given UCI configurations from the local cache.
+	 *
+	 * @param {string|string[]} config
+	 * The name of the configuration or an array of configuration
+	 * names to unload.
+	 */
+	unload: function(packages) {
+		if (!Array.isArray(packages))
+			packages = [ packages ];
+
+		for (var i = 0; i < packages.length; i++) {
+			delete this.state.values[packages[i]];
+			delete this.state.creates[packages[i]];
+			delete this.state.changes[packages[i]];
+			delete this.state.deletes[packages[i]];
+
+			delete this.loaded[packages[i]];
+		}
+	},
+
+	/**
+	 * Adds a new section of the given type to the given configuration,
+	 * optionally named according to the given name.
+	 *
+	 * @param {string} config
+	 * The name of the configuration to add the section to.
+	 *
+	 * @param {string} type
+	 * The type of the section to add.
+	 *
+	 * @param {string} [name]
+	 * The name of the section to add. If the name is omitted, an anonymous
+	 * section will be added instead.
+	 *
+	 * @returns {string}
+	 * Returns the section ID of the newly added section which is equivalent
+	 * to the given name for non-anonymous sections.
+	 */
+	add: function(conf, type, name) {
+		var n = this.state.creates,
+		    sid = name || this.createSID(conf);
+
+		if (!n[conf])
+			n[conf] = { };
+
+		n[conf][sid] = {
+			'.type':      type,
+			'.name':      sid,
+			'.create':    name,
+			'.anonymous': !name,
+			'.index':     1000 + this.state.newidx++
+		};
+
+		return sid;
+	},
+
+	/**
+	 * Removes the section with the given ID from the given configuration.
+	 *
+	 * @param {string} config
+	 * The name of the configuration to remove the section from.
+	 *
+	 * @param {string} sid
+	 * The ID of the section to remove.
+	 */
+	remove: function(conf, sid) {
+		var n = this.state.creates,
+		    c = this.state.changes,
+		    d = this.state.deletes;
+
+		/* requested deletion of a just created section */
+		if (n[conf] && n[conf][sid]) {
+			delete n[conf][sid];
+		}
+		else {
+			if (c[conf])
+				delete c[conf][sid];
+
+			if (!d[conf])
+				d[conf] = { };
+
+			d[conf][sid] = true;
+		}
+	},
+
+	/**
+	 * 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.
+	 *
+	 * @typedef {Object<string, boolean|number|string|string[]>} SectionObject
+	 * @memberof LuCI.uci
+	 *
+	 * @property {boolean} .anonymous
+	 * The `.anonymous` property specifies whether the configuration is
+	 * anonymous (`true`) or named (`false`).
+	 *
+	 * @property {number} .index
+	 * The `.index` property specifes the sort order of the section.
+	 *
+	 * @property {string} .name
+	 * 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.
+	 *
+	 * @property {string} .type
+	 * The `.type` property contains the type of the corresponding uci
+	 * section.
+	 *
+	 * @property {string|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.
+	 */
+
+	/**
+	 * The sections callback is invoked for each section found within
+	 * the given configuration and receives the section object and its
+	 * associated name as arguments.
+	 *
+	 * @callback LuCI.uci~sectionsFn
+	 *
+	 * @param {LuCI.uci.SectionObject} section
+	 * The section object.
+	 *
+	 * @param {string} sid
+	 * The name or ID of the section.
+	 */
+
+	/**
+	 * Enumerates the sections of the given configuration, optionally
+	 * filtered by type.
+	 *
+	 * @param {string} config
+	 * The name of the configuration to enumerate the sections for.
+	 *
+	 * @param {string} [type]
+	 * Enumerate only sections of the given type. If omitted, enumerate
+	 * all sections.
+	 *
+	 * @param {LuCI.uci~sectionsFn} [cb]
+	 * An optional callback to invoke for each enumerated section.
+	 *
+	 * @returns {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.
+	 */
+	sections: function(conf, type, cb) {
+		var sa = [ ],
+		    v = this.state.values[conf],
+		    n = this.state.creates[conf],
+		    c = this.state.changes[conf],
+		    d = this.state.deletes[conf];
+
+		if (!v)
+			return sa;
+
+		for (var s in v)
+			if (!d || d[s] !== true)
+				if (!type || v[s]['.type'] == type)
+					sa.push(Object.assign({ }, v[s], c ? c[s] : undefined));
+
+		if (n)
+			for (var s in n)
+				if (!type || n[s]['.type'] == type)
+					sa.push(Object.assign({ }, n[s]));
+
+		sa.sort(function(a, b) {
+			return a['.index'] - b['.index'];
+		});
+
+		for (var i = 0; i < sa.length; i++)
+			sa[i]['.index'] = i;
+
+		if (typeof(cb) == 'function')
+			for (var i = 0; i < sa.length; i++)
+				cb.call(this, sa[i], sa[i]['.name']);
+
+		return sa;
+	},
+
+	/**
+	 * 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.
+	 *
+	 * @param {string} config
+	 * The name of the configuration to read the value from.
+	 *
+	 * @param {string} sid
+	 * The name or ID of the section to read.
+	 *
+	 * @param {string} [option]
+	 * The option name to read the value from. If the option name is
+	 * omitted or `null`, the entire section is returned instead.
+	 *
+	 * @returns {null|string|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 {@link LuCI.uci.SectionObject 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: function(conf, sid, opt) {
+		var v = this.state.values,
+		    n = this.state.creates,
+		    c = this.state.changes,
+		    d = this.state.deletes;
+
+		sid = this.resolveSID(conf, sid);
+
+		if (sid == null)
+			return null;
+
+		/* requested option in a just created section */
+		if (n[conf] && n[conf][sid]) {
+			if (!n[conf])
+				return undefined;
+
+			if (opt == null)
+				return n[conf][sid];
+
+			return n[conf][sid][opt];
+		}
+
+		/* requested an option value */
+		if (opt != null) {
+			/* check whether option was deleted */
+			if (d[conf] && d[conf][sid]) {
+				if (d[conf][sid] === true)
+					return undefined;
+
+				for (var i = 0; i < d[conf][sid].length; i++)
+					if (d[conf][sid][i] == opt)
+						return undefined;
+			}
+
+			/* check whether option was changed */
+			if (c[conf] && c[conf][sid] && c[conf][sid][opt] != null)
+				return c[conf][sid][opt];
+
+			/* return base value */
+			if (v[conf] && v[conf][sid])
+				return v[conf][sid][opt];
+
+			return undefined;
+		}
+
+		/* requested an entire section */
+		if (v[conf])
+			return v[conf][sid];
+
+		return undefined;
+	},
+
+	/**
+	 * 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.
+	 *
+	 * @param {string} config
+	 * The name of the configuration to set the option value in.
+	 *
+	 * @param {string} sid
+	 * The name or ID of the section to set the option value in.
+	 *
+	 * @param {string} option
+	 * The option name to set the value for.
+	 *
+	 * @param {null|string|string[]} value
+	 * 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: function(conf, sid, opt, val) {
+		var v = this.state.values,
+		    n = this.state.creates,
+		    c = this.state.changes,
+		    d = this.state.deletes;
+
+		sid = this.resolveSID(conf, sid);
+
+		if (sid == null || opt == null || opt.charAt(0) == '.')
+			return;
+
+		if (n[conf] && n[conf][sid]) {
+			if (val != null)
+				n[conf][sid][opt] = val;
+			else
+				delete n[conf][sid][opt];
+		}
+		else if (val != null && val !== '') {
+			/* do not set within deleted section */
+			if (d[conf] && d[conf][sid] === true)
+				return;
+
+			/* only set in existing sections */
+			if (!v[conf] || !v[conf][sid])
+				return;
+
+			if (!c[conf])
+				c[conf] = {};
+
+			if (!c[conf][sid])
+				c[conf][sid] = {};
+
+			/* undelete option */
+			if (d[conf] && d[conf][sid])
+				d[conf][sid] = d[conf][sid].filter(function(o) { return o !== opt });
+
+			c[conf][sid][opt] = val;
+		}
+		else {
+			/* only delete in existing sections */
+			if (!(v[conf] && v[conf][sid] && v[conf][sid].hasOwnProperty(opt)) &&
+			    !(c[conf] && c[conf][sid] && c[conf][sid].hasOwnProperty(opt)))
+			    return;
+
+			if (!d[conf])
+				d[conf] = { };
+
+			if (!d[conf][sid])
+				d[conf][sid] = [ ];
+
+			if (d[conf][sid] !== true)
+				d[conf][sid].push(opt);
+		}
+	},
+
+	/**
+	 * 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)`.
+	 *
+	 * @param {string} config
+	 * The name of the configuration to remove the option from.
+	 *
+	 * @param {string} sid
+	 * The name or ID of the section to remove the option from.
+	 *
+	 * @param {string} option
+	 * The name of the option to remove.
+	 */
+	unset: function(conf, sid, opt) {
+		return this.set(conf, sid, opt, null);
+	},
+
+	/**
+	 * 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.
+	 *
+	 * @param {string} config
+	 * The name of the configuration to read the value from.
+	 *
+	 * @param {string} [type]
+	 * 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.
+	 *
+	 * @param {string} [option]
+	 * The option name to read the value from. If the option name is
+	 * omitted or `null`, the entire section is returned instead.
+	 *
+	 * @returns {null|string|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 {@link LuCI.uci.SectionObject 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: function(conf, type, opt) {
+		var sid = null;
+
+		this.sections(conf, type, function(s) {
+			if (sid == null)
+				sid = s['.name'];
+		});
+
+		return this.get(conf, sid, opt);
+	},
+
+	/**
+	 * 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.
+	 *
+	 * @param {string} config
+	 * The name of the configuration to set the option value in.
+	 *
+	 * @param {string} [type]
+	 * 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.
+	 *
+	 * @param {string} option
+	 * The option name to set the value for.
+	 *
+	 * @param {null|string|string[]} value
+	 * 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: function(conf, type, opt, val) {
+		var sid = null;
+
+		this.sections(conf, type, function(s) {
+			if (sid == null)
+				sid = s['.name'];
+		});
+
+		return this.set(conf, sid, opt, val);
+	},
+
+	/**
+	 * 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)`.
+	 *
+	 * @param {string} config
+	 * The name of the configuration to set the option value in.
+	 *
+	 * @param {string} [type]
+	 * 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.
+	 *
+	 * @param {string} option
+	 * The option name to set the value for.
+	 */
+	unset_first: function(conf, type, opt) {
+		return this.set_first(conf, type, opt, null);
+	},
+
+	/**
+	 * Move the first specified section within the given configuration
+	 * before or after the second specified section.
+	 *
+	 * @param {string} config
+	 * The configuration to move the section within.
+	 *
+	 * @param {string} sid1
+	 * The ID of the section to move within the configuration.
+	 *
+	 * @param {string} [sid2]
+	 * 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.
+	 *
+	 * @param {boolean} [after=false]
+	 * 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 {boolean}
+	 * Returns `true` when the section was successfully moved, or `false`
+	 * when either the section specified by `sid1` or by `sid2` is not found.
+	 */
+	move: function(conf, sid1, sid2, after) {
+		var sa = this.sections(conf),
+		    s1 = null, s2 = null;
+
+		sid1 = this.resolveSID(conf, sid1);
+		sid2 = this.resolveSID(conf, sid2);
+
+		for (var i = 0; i < sa.length; i++) {
+			if (sa[i]['.name'] != sid1)
+				continue;
+
+			s1 = sa[i];
+			sa.splice(i, 1);
+			break;
+		}
+
+		if (s1 == null)
+			return false;
+
+		if (sid2 == null) {
+			sa.push(s1);
+		}
+		else {
+			for (var i = 0; i < sa.length; i++) {
+				if (sa[i]['.name'] != sid2)
+					continue;
+
+				s2 = sa[i];
+				sa.splice(i + !!after, 0, s1);
+				break;
+			}
+
+			if (s2 == null)
+				return false;
+		}
+
+		for (var i = 0; i < sa.length; i++)
+			this.get(conf, sa[i]['.name'])['.index'] = i;
+
+		this.state.reorder[conf] = true;
+
+		return true;
+	},
+
+	/**
+	 * 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 {string[]}
+	 * Returns a promise resolving to an array of configuration names which
+	 * have been reloaded by the save operation.
+	 */
+	save: function() {
+		var v = this.state.values,
+		    n = this.state.creates,
+		    c = this.state.changes,
+		    d = this.state.deletes,
+		    r = this.state.reorder,
+		    self = this,
+		    snew = [ ],
+		    pkgs = { },
+		    tasks = [];
+
+		if (n)
+			for (var conf in n) {
+				for (var sid in n[conf]) {
+					var r = {
+						config: conf,
+						values: { }
+					};
+
+					for (var k in n[conf][sid]) {
+						if (k == '.type')
+							r.type = n[conf][sid][k];
+						else if (k == '.create')
+							r.name = n[conf][sid][k];
+						else if (k.charAt(0) != '.')
+							r.values[k] = n[conf][sid][k];
+					}
+
+					snew.push(n[conf][sid]);
+					tasks.push(self.callAdd(r.config, r.type, r.name, r.values));
+				}
+
+				pkgs[conf] = true;
+			}
+
+		if (c)
+			for (var conf in c) {
+				for (var sid in c[conf])
+					tasks.push(self.callSet(conf, sid, c[conf][sid]));
+
+				pkgs[conf] = true;
+			}
+
+		if (d)
+			for (var conf in d) {
+				for (var sid in d[conf]) {
+					var o = d[conf][sid];
+					tasks.push(self.callDelete(conf, sid, (o === true) ? null : o));
+				}
+
+				pkgs[conf] = true;
+			}
+
+		if (r)
+			for (var conf in r)
+				pkgs[conf] = true;
+
+		return Promise.all(tasks).then(function(responses) {
+			/*
+			 array "snew" holds references to the created uci sections,
+			 use it to assign the returned names of the new sections
+			*/
+			for (var i = 0; i < snew.length; i++)
+				snew[i]['.name'] = responses[i];
+
+			return self.reorderSections();
+		}).then(function() {
+			pkgs = Object.keys(pkgs);
+
+			self.unload(pkgs);
+
+			return self.load(pkgs);
+		});
+	},
+
+	/**
+	 * 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.
+	 *
+	 * @param {number} [timeout=10]
+	 * Override the confirmation timeout after which a rollback is triggered.
+	 *
+	 * @returns {Promise<number>}
+	 * Returns a promise resolving/rejecting with the `ubus` RPC status code.
+	 */
+	apply: function(timeout) {
+		var self = this,
+		    date = new Date();
+
+		if (typeof(timeout) != 'number' || timeout < 1)
+			timeout = 10;
+
+		return self.callApply(timeout, true).then(function(rv) {
+			if (rv != 0)
+				return Promise.reject(rv);
+
+			var try_deadline = date.getTime() + 1000 * timeout;
+			var try_confirm = function() {
+				return self.callConfirm().then(function(rv) {
+					if (rv != 0) {
+						if (date.getTime() < try_deadline)
+							window.setTimeout(try_confirm, 250);
+						else
+							return Promise.reject(rv);
+					}
+
+					return rv;
+				});
+			};
+
+			window.setTimeout(try_confirm, 1000);
+		});
+	},
+
+	/**
+	 * 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.
+	 *
+	 * @typedef {string[]} ChangeRecord
+	 * @memberof LuCI.uci
+	 *
+	 * @property {string} 0
+	 * The operation name - may be one of `add`, `set`, `remove`, `order`,
+	 * `list-add`, `list-del` or `rename`.
+	 *
+	 * @property {string} 1
+	 * The section ID targeted by the operation.
+	 *
+	 * @property {string} 2
+	 * 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.
+	 *
+	 * @property {string} 4
+	 * 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.
+	 */
+
+	/**
+	 * Fetches uncommitted UCI changes from the remote `ubus` RPC api.
+	 *
+	 * @method
+	 * @returns {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.
+	 */
+	changes: rpc.declare({
+		object: 'uci',
+		method: 'changes',
+		expect: { changes: { } }
+	})
+});
+
+
+
+ + + + +
+ + + +
+ +
+ Documentation generated by JSDoc 3.6.3 on Tue Nov 05 2019 09:33:05 GMT+0100 (Central European Standard Time) +
+ + + + + diff --git a/jsdoc.conf.json b/jsdoc.conf.json new file mode 100644 index 000000000..87a5b603f --- /dev/null +++ b/jsdoc.conf.json @@ -0,0 +1,22 @@ +{ + "tags": { + "allowUnknownTags": true, + "dictionaries": ["jsdoc","closure"] + }, + "source": { + "include": ["modules/luci-base/htdocs/luci-static/resources"], + "includePattern": ".+\\.js(doc|x)?$" + }, + "plugins": [ + "plugins/markdown" + ], + "templates": { + "cleverLinks": true, + "monospaceLinks": true + }, + "opts": { + "destination": "documentation/jsapi", + "recurse": true, + "readme": "README.md" + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..30ad4264b --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "scripts": { + "doc": "jsdoc -c jsdoc.conf.json" + }, + "devDependencies": { + "jsdoc": "^3.6.3" + } +}