diff options
Diffstat (limited to 'modules/luci-base/htdocs/luci-static/resources/ui.js')
-rw-r--r-- | modules/luci-base/htdocs/luci-static/resources/ui.js | 115 |
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. |