summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/htdocs/luci-static/resources/ui.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-base/htdocs/luci-static/resources/ui.js')
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/ui.js115
1 files changed, 61 insertions, 54 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js
index 2e697aa190..5502dfed25 100644
--- a/modules/luci-base/htdocs/luci-static/resources/ui.js
+++ b/modules/luci-base/htdocs/luci-static/resources/ui.js
@@ -26,7 +26,7 @@ var modalDiv = null,
* events.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -134,7 +134,7 @@ var UIElement = baseclass.extend(/** @lends LuCI.ui.AbstractElement.prototype */
* @memberof LuCI.ui.AbstractElement
* @returns {boolean}
* Returns `true` if the input value has been altered by the user or
- * `false` if it is unchaged. Note that if the user modifies the initial
+ * `false` if it is unchanged. Note that if the user modifies the initial
* value and changes it back to the original state, it is still reported
* as changed.
*/
@@ -316,7 +316,7 @@ var UIElement = baseclass.extend(/** @lends LuCI.ui.AbstractElement.prototype */
* The `Textfield` class implements a standard single line text input field.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -441,7 +441,7 @@ var UITextfield = UIElement.extend(/** @lends LuCI.ui.Textfield.prototype */ {
* The `Textarea` class implements a multiline text area input field.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -557,7 +557,7 @@ var UITextarea = UIElement.extend(/** @lends LuCI.ui.Textarea.prototype */ {
* The `Checkbox` class implements a simple checkbox input field.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -696,7 +696,7 @@ var UICheckbox = UIElement.extend(/** @lends LuCI.ui.Checkbox.prototype */ {
* values are enabled or not.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -726,7 +726,7 @@ var UISelect = UIElement.extend(/** @lends LuCI.ui.Select.prototype */ {
* @property {boolean} [multiple=false]
* Specifies whether multiple choice values may be selected.
*
- * @property {string} [widget=select]
+ * @property {"select"|"individual"} [widget=select]
* Specifies the kind of widget to render. May be either `select` or
* `individual`. When set to `select` an HTML `<select>` element will be
* used, otherwise a group of checkbox or radio button elements is created,
@@ -904,7 +904,7 @@ var UISelect = UIElement.extend(/** @lends LuCI.ui.Select.prototype */ {
* supports non-text choice labels.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -1988,7 +1988,7 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
* with a set of enforced default properties for easier instantiation.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -2055,7 +2055,7 @@ var UICombobox = UIDropdown.extend(/** @lends LuCI.ui.Combobox.prototype */ {
* into a dropdown to chose from a set of different action choices.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -2078,7 +2078,7 @@ var UIComboButton = UIDropdown.extend(/** @lends LuCI.ui.ComboButton.prototype *
/**
* ComboButtons support the same properties as
* [Dropdown.InitOptions]{@link LuCI.ui.Dropdown.InitOptions} but enforce
- * specific values for some properties and add aditional button specific
+ * specific values for some properties and add additional button specific
* properties.
*
* @typedef {LuCI.ui.Dropdown.InitOptions} InitOptions
@@ -2172,7 +2172,7 @@ var UIComboButton = UIDropdown.extend(/** @lends LuCI.ui.ComboButton.prototype *
* from a set of predefined choices.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -2195,7 +2195,7 @@ var UIComboButton = UIDropdown.extend(/** @lends LuCI.ui.ComboButton.prototype *
*/
var UIDynamicList = UIElement.extend(/** @lends LuCI.ui.DynamicList.prototype */ {
/**
- * In case choices are passed to the dynamic list contructor, the widget
+ * In case choices are passed to the dynamic list constructor, the widget
* supports the same properties as [Dropdown.InitOptions]{@link LuCI.ui.Dropdown.InitOptions}
* but enforces specific values for some dropdown properties.
*
@@ -2527,7 +2527,7 @@ var UIDynamicList = UIElement.extend(/** @lends LuCI.ui.DynamicList.prototype */
* which allows to store form data without exposing it to the user.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -2593,7 +2593,7 @@ var UIHiddenfield = UIElement.extend(/** @lends LuCI.ui.Hiddenfield.prototype */
* browse, select and delete files beneath a predefined remote directory.
*
* UI widget instances are usually not supposed to be created by view code
- * directly, instead they're implicitely created by `LuCI.form` when
+ * directly, instead they're implicitly created by `LuCI.form` when
* instantiating CBI forms.
*
* This class is automatically instantiated as part of `LuCI.ui`. To use it
@@ -2638,9 +2638,9 @@ var UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */ {
*
* @property {string} [root_directory=/etc/luci-uploads]
* Specifies the remote directory the upload and file browsing actions take
- * place in. Browsing to directories outside of the root directory is
+ * place in. Browsing to directories outside the root directory is
* prevented by the widget. Note that this is not a security feature.
- * Whether remote directories are browseable or not solely depends on the
+ * Whether remote directories are browsable or not solely depends on the
* ACL setup for the current session.
*/
__init__: function(value, options) {
@@ -3085,7 +3085,7 @@ var UIMenu = baseclass.singleton(/** @lends LuCI.ui.menu.prototype */ {
* @property {string} name - The internal name of the node, as used in the URL
* @property {number} order - The sort index of the menu node
* @property {string} [title] - The title of the menu node, `null` if the node should be hidden
- * @property {satisified} boolean - Boolean indicating whether the menu enries dependencies are satisfied
+ * @property {satisfied} boolean - Boolean indicating whether the menu entries dependencies are satisfied
* @property {readonly} [boolean] - Boolean indicating whether the menu entries underlying ACLs are readonly
* @property {LuCI.ui.menu.MenuNode[]} [children] - Array of child menu nodes.
*/
@@ -3233,6 +3233,17 @@ var UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ {
if (!Array.isArray(data))
return;
+ this.data = data;
+ this.placeholder = placeholder;
+
+ var n = 0,
+ rows = this.node.querySelectorAll('tr, .tr'),
+ trows = [],
+ headings = [].slice.call(this.node.firstElementChild.querySelectorAll('th, .th')),
+ captionClasses = this.options.captionClasses,
+ trTag = (rows[0] && rows[0].nodeName == 'DIV') ? 'div' : 'tr',
+ tdTag = (headings[0] && headings[0].nodeName == 'DIV') ? 'div' : 'td';
+
if (sorting) {
var list = data.map(L.bind(function(row) {
return [ this.deriveSortKey(row[sorting[0]], sorting[0]), row ];
@@ -3249,18 +3260,14 @@ var UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ {
list.forEach(function(item) {
data.push(item[1]);
});
- }
- this.data = data;
- this.placeholder = placeholder;
-
- var n = 0,
- rows = this.node.querySelectorAll('tr, .tr'),
- trows = [],
- headings = [].slice.call(this.node.firstElementChild.querySelectorAll('th, .th')),
- captionClasses = this.options.captionClasses,
- trTag = (rows[0] && rows[0].nodeName == 'DIV') ? 'div' : 'tr',
- tdTag = (headings[0] && headings[0].nodeName == 'DIV') ? 'div' : 'td';
+ headings.forEach(function(th, i) {
+ if (i == sorting[0])
+ th.setAttribute('data-sort-direction', sorting[1] ? 'desc' : 'asc');
+ else
+ th.removeAttribute('data-sort-direction');
+ });
+ }
data.forEach(function(row) {
trows[n] = E(trTag, { 'class': 'tr' });
@@ -3324,6 +3331,7 @@ var UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ {
if (!headrow)
return;
+ options.id = node.id;
options.classes = [].slice.call(node.classList).filter(function(c) { return c != 'table' });
options.sortable = [];
options.captionClasses = [];
@@ -3422,8 +3430,11 @@ var UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ {
if (this.sortState)
return this.sortState;
+ if (!this.options.id)
+ return null;
+
var page = document.body.getAttribute('data-page'),
- key = page + '.' + this.id,
+ key = page + '.' + this.options.id,
state = session.getLocalData('tablesort');
if (L.isObject(state) && Array.isArray(state[key]))
@@ -3440,7 +3451,7 @@ var UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ {
return;
var page = document.body.getAttribute('data-page'),
- key = page + '.' + this.id,
+ key = page + '.' + this.options.id,
state = session.getLocalData('tablesort');
if (!L.isObject(state))
@@ -3456,19 +3467,15 @@ var UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ {
if (!ev.target.matches('th[data-sortable-row]'))
return;
- var th = ev.target,
- direction = (th.getAttribute('data-sort-direction') == 'asc'),
- index = 0;
+ var index, direction;
- this.node.firstElementChild.querySelectorAll('th').forEach(function(other_th, i) {
- if (other_th !== th)
- other_th.removeAttribute('data-sort-direction');
- else
+ this.node.firstElementChild.querySelectorAll('th, .th').forEach(function(th, i) {
+ if (th === ev.target) {
index = i;
+ direction = th.getAttribute('data-sort-direction') == 'asc';
+ }
});
- th.setAttribute('data-sort-direction', direction ? 'desc' : 'asc');
-
this.setActiveSortState(index, direction);
this.update(this.data, this.placeholder);
}
@@ -3527,7 +3534,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
* be opened. Invoking showModal() while a modal dialog is already open will
* replace the open dialog with a new one having the specified contents.
*
- * Additional CSS class names may be passed to influence the appearence of
+ * Additional CSS class names may be passed to influence the appearance of
* the dialog. Valid values for the classes depend on the underlying theme.
*
* @see LuCI.dom.content
@@ -3535,7 +3542,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
* @param {string} [title]
* The title of the dialog. If `null`, no title element will be rendered.
*
- * @param {*} contents
+ * @param {*} children
* The contents to add to the modal dialog. This should be a DOM node or
* a document fragment in most cases. The value is passed as-is to the
* `dom.content()` function - refer to its documentation for applicable
@@ -3659,11 +3666,11 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
* Add a notification banner at the top of the current view.
*
* A notification banner is an alert message usually displayed at the
- * top of the current view, spanning the entire availibe width.
+ * top of the current view, spanning the entire available width.
* Notification banners will stay in place until dismissed by the user.
* Multiple banners may be shown at the same time.
*
- * Additional CSS class names may be passed to influence the appearence of
+ * Additional CSS class names may be passed to influence the appearance of
* the banner. Valid values for the classes depend on the underlying theme.
*
* @see LuCI.dom.content
@@ -3672,7 +3679,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
* The title of the notification banner. If `null`, no title element
* will be rendered.
*
- * @param {*} contents
+ * @param {*} children
* The contents to add to the notification banner. This should be a DOM
* node or a document fragment in most cases. The value is passed as-is
* to the `dom.content()` function - refer to its documentation for
@@ -3723,7 +3730,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
},
/**
- * Display or update an header area indicator.
+ * Display or update a header area indicator.
*
* An indicator is a small label displayed in the header area of the screen
* providing few amounts of status information such as item counts or state
@@ -3750,7 +3757,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
* Note that this parameter only applies to new indicators, when updating
* existing labels it is ignored.
*
- * @param {string} [style=active]
+ * @param {"active"|"inactive"} [style=active]
* The indicator style to use. May be either `active` or `inactive`.
*
* @returns {boolean}
@@ -3793,7 +3800,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
},
/**
- * Remove an header area indicator.
+ * Remove a header area indicator.
*
* This function removes the given indicator label from the header indicator
* area. When the given indicator is not found, this function does nothing.
@@ -3827,7 +3834,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
* subsequently wrapped into a `<span class="nowrap">` element.
*
* The resulting `<span>` element tuples are joined by the given separators
- * to form the final markup which is appened to the given parent DOM node.
+ * to form the final markup which is appended to the given parent DOM node.
*
* @param {Node} node
* The parent DOM node to append the markup to. Any previous child elements
@@ -4154,7 +4161,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
* @param {string} path
* The remote file path to upload the local file to.
*
- * @param {Node} [progessStatusNode]
+ * @param {Node} [progressStatusNode]
* An optional DOM text node whose content text is set to the progress
* percentage value during file upload.
*
@@ -4268,7 +4275,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
/**
* Perform a device connectivity test.
*
- * Attempt to fetch a well known ressource from the remote device via HTTP
+ * Attempt to fetch a well known resource from the remote device via HTTP
* in order to test connectivity. This function is mainly useful to wait
* for the router to come back online after a reboot or reconfiguration.
*
@@ -4276,7 +4283,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
* The protocol to use for fetching the resource. May be either `http`
* (the default) or `https`.
*
- * @param {string} [host=window.location.host]
+ * @param {string} [ipaddr=window.location.host]
* Override the host address to probe. By default the current host as seen
* in the address bar is probed.
*
@@ -4365,7 +4372,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
*
* @instance
* @memberof LuCI.ui.changes
- * @param {number} numChanges
+ * @param {number} n
* The number of changes to indicate.
*/
setIndicator: function(n) {
@@ -4906,7 +4913,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
*
* By instantiating the view class, its corresponding contents are
* rendered and included into the view area. Any runtime errors are
- * catched and rendered using [LuCI.error()]{@link LuCI#error}.
+ * caught and rendered using [LuCI.error()]{@link LuCI#error}.
*
* @param {string} path
* The view path to render.