diff options
Diffstat (limited to 'modules/luci-base/htdocs')
6 files changed, 155 insertions, 13 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/form.js b/modules/luci-base/htdocs/luci-static/resources/form.js index 624bc2c2f8..c47b38d273 100644 --- a/modules/luci-base/htdocs/luci-static/resources/form.js +++ b/modules/luci-base/htdocs/luci-static/resources/form.js @@ -3920,6 +3920,135 @@ var CBIListValue = CBIValue.extend(/** @lends LuCI.form.ListValue.prototype */ { }); /** + * @class RichListValue + * @memberof LuCI.form + * @augments LuCI.form.ListValue + * @hideconstructor + * @classdesc + * + * The `RichListValue` class implements a simple static HTML select element + * allowing the user to choose a single value from a set of predefined choices. + * Each choice may contain a tertiary, more elaborate description. + * It builds upon the {@link LuCI.form.ListValue} widget. + * + * @param {LuCI.form.Map|LuCI.form.JSONMap} form + * The configuration form this section is added to. It is automatically passed + * by [option()]{@link LuCI.form.AbstractSection#option} or + * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the + * option to the section. + * + * @param {LuCI.form.AbstractSection} section + * The configuration section this option is added to. It is automatically passed + * by [option()]{@link LuCI.form.AbstractSection#option} or + * [taboption()]{@link LuCI.form.AbstractSection#taboption} when adding the + * option to the section. + * + * @param {string} option + * The name of the UCI option to map. + * + * @param {string} [title] + * The title caption of the option element. + * + * @param {string} [description] + * The description text of the option element. + */ +var CBIRichListValue = CBIListValue.extend(/** @lends LuCI.form.ListValue.prototype */ { + __name__: 'CBI.RichListValue', + + __init__: function() { + this.super('__init__', arguments); + this.widget = 'select'; + this.orientation = 'horizontal'; + this.deplist = []; + }, + + /** + * Set the orientation of the underlying radio or checkbox elements. + * + * May be one of `horizontal` or `vertical`. Only applies to non-select + * widget types. + * + * @name LuCI.form.RichListValue.prototype#orientation + * @type string + * @default horizontal + */ + + /** + * Set the size attribute of the underlying HTML select element. + * + * @name LuCI.form.RichListValue.prototype#size + * @type number + * @default null + */ + + /** + * Set the type of the underlying form controls. + * + * May be one of `select` or `radio`. If set to `select`, an HTML + * select element is rendered, otherwise a collection of `radio` + * elements is used. + * + * @name LuCI.form.RichListValue.prototype#widget + * @type string + * @default select + */ + + /** @private */ + renderWidget: function(section_id, option_index, cfgvalue) { + var choices = this.transformChoices(); + var widget = new ui.Dropdown((cfgvalue != null) ? cfgvalue : this.default, choices, { + id: this.cbid(section_id), + size: this.size, + sort: this.keylist, + widget: this.widget, + optional: this.optional, + orientation: this.orientation, + select_placeholder: this.select_placeholder || this.placeholder, + custom_placeholder: this.custom_placeholder || this.placeholder, + validate: L.bind(this.validate, this, section_id), + disabled: (this.readonly != null) ? this.readonly : this.map.readonly + }); + + return widget.render(); + }, + + /** + * Add a predefined choice to the form option. By adding one or more + * choices, the plain text input field is turned into a combobox widget + * which prompts the user to select a predefined choice, or to enter a + * custom value. + * + * @param {string} key + * The choice value to add. + * + * @param {Node|string} val + * The caption for the choice value. May be a DOM node, a document fragment + * or a plain text string. If omitted, the `key` value is used as caption. + * + * @param {Node|string} description + * The description text of the choice value. May be a DOM node, a document + * fragment or a plain text string. If omitted, the value element is + * implemented as a simple ListValue entry. + * + */ + value: function(value, title, description) { + if (description) { + CBIListValue.prototype.value.call(this, value, E([], [ + E('span', { 'class': 'hide-open' }, [ title ]), + E('div', { 'class': 'hide-close', 'style': 'min-width:25vw' }, [ + E('strong', [ title ]), + E('br'), + E('span', { 'style': 'white-space:normal' }, description) + ]) + ])); + } + else { + CBIListValue.prototype.value.call(this, value, title); + } + } +}); + +/** * @class FlagValue * @memberof LuCI.form * @augments LuCI.form.Value @@ -4116,6 +4245,14 @@ var CBIMultiValue = CBIDynamicList.extend(/** @lends LuCI.form.MultiValue.protot }, /** + * Allows custom value entry in addition to those already specified. + * + * @name LuCI.form.MultiValue.prototype#create + * @type boolean + * @default null + */ + + /** * Allows to specify the [display_items]{@link LuCI.ui.Dropdown.InitOptions} * property of the underlying dropdown widget. If omitted, the value of * the `size` property is used or `3` when `size` is unspecified as well. @@ -4146,6 +4283,7 @@ var CBIMultiValue = CBIDynamicList.extend(/** @lends LuCI.form.MultiValue.protot multiple: true, optional: this.optional || this.rmempty, select_placeholder: this.placeholder, + create: this.create, display_items: this.display_size || this.size || 3, dropdown_items: this.dropdown_size || this.size || -1, validate: L.bind(this.validate, this, section_id), @@ -4829,6 +4967,7 @@ return baseclass.extend(/** @lends LuCI.form.prototype */ { Value: CBIValue, DynamicList: CBIDynamicList, ListValue: CBIListValue, + RichListValue: CBIRichListValue, Flag: CBIFlagValue, MultiValue: CBIMultiValue, TextValue: CBITextValue, diff --git a/modules/luci-base/htdocs/luci-static/resources/luci.js b/modules/luci-base/htdocs/luci-static/resources/luci.js index ca0e80a82a..f462c46813 100644 --- a/modules/luci-base/htdocs/luci-static/resources/luci.js +++ b/modules/luci-base/htdocs/luci-static/resources/luci.js @@ -925,7 +925,7 @@ * @hideconstructor * @classdesc * - * The `Request.poll` class provides some convince wrappers around + * The `Request.poll` class provides some convenience wrappers around * {@link LuCI.poll} mainly to simplify registering repeating HTTP * request calls as polling functions. */ @@ -980,7 +980,7 @@ opts = Object.assign({}, options, { timeout: ival * 1000 - 5 }); var fn = function() { - return Request.request(url, options).then(function(res) { + return Request.request(url, opts).then(function(res) { if (!Poll.active()) return; diff --git a/modules/luci-base/htdocs/luci-static/resources/network.js b/modules/luci-base/htdocs/luci-static/resources/network.js index c504279eeb..3bd344a61e 100644 --- a/modules/luci-base/htdocs/luci-static/resources/network.js +++ b/modules/luci-base/htdocs/luci-static/resources/network.js @@ -2158,8 +2158,8 @@ Protocol = baseclass.extend(/** @lends LuCI.network.Protocol.prototype */ { var prefixes = [...v6_prefixes, ...v6_addresses]; if(prefixes.length && typeof(prefixes[0].valid) == 'number') { - var r = prefixes[0].valid; - return (r > 0 ? r : 0); + var r = prefixes[0].valid; + return (r > 0 ? r : 0); } } } @@ -3251,7 +3251,7 @@ Device = baseclass.extend(/** @lends LuCI.network.Device.prototype */ { * @returns {null|LuCI.network.Device} * Returns a `Network.Device` instance representing the parent device or * `null` when this device has no parent, as it is the case for e.g. - * ordinary ethernet interfaces. + * ordinary Ethernet interfaces. */ getParent: function() { if (this.dev.parent) @@ -3951,7 +3951,7 @@ WifiNetwork = baseclass.extend(/** @lends LuCI.network.WifiNetwork.prototype */ * * @property {number} inactive * The amount of milliseconds the peer has been inactive, e.g. due - * to powersave. + * to power-saving. * * @property {number} connected_time * The amount of milliseconds the peer is associated to this network. @@ -4001,7 +4001,7 @@ WifiNetwork = baseclass.extend(/** @lends LuCI.network.WifiNetwork.prototype */ * - `UNKNOWN` * * @property {number} [mesh local PS] - * The local powersafe mode for the peer link, may be an empty + * The local power-save mode for the peer link, may be an empty * string (`''`) or absent if not applicable or supported by * the driver. * @@ -4012,7 +4012,7 @@ WifiNetwork = baseclass.extend(/** @lends LuCI.network.WifiNetwork.prototype */ * - `UNKNOWN` * * @property {number} [mesh peer PS] - * The remote powersafe mode for the peer link, may be an empty + * The remote power-save mode for the peer link, may be an empty * string (`''`) or absent if not applicable or supported by * the driver. * @@ -4023,7 +4023,7 @@ WifiNetwork = baseclass.extend(/** @lends LuCI.network.WifiNetwork.prototype */ * - `UNKNOWN` * * @property {number} [mesh non-peer PS] - * The powersafe mode for all non-peer neighbours, may be an empty + * The power-save mode for all non-peer neighbours, may be an empty * string (`''`) or absent if not applicable or supported by the driver. * * The following modes are known: @@ -4317,7 +4317,7 @@ WifiNetwork = baseclass.extend(/** @lends LuCI.network.WifiNetwork.prototype */ }, /** - * Get the primary logical interface this wireless network is attached to. + * Get the primary logical interface this network is attached to. * * @returns {null|LuCI.network.Protocol} * Returns a `Network.Protocol` instance representing the logical @@ -4329,7 +4329,7 @@ WifiNetwork = baseclass.extend(/** @lends LuCI.network.WifiNetwork.prototype */ }, /** - * Get the logical interfaces this wireless network is attached to. + * Get the logical interfaces this network is attached to. * * @returns {Array<LuCI.network.Protocol>} * Returns an array of `Network.Protocol` instances representing the diff --git a/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js b/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js index d946d0e093..0ba07afcde 100644 --- a/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js +++ b/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js @@ -322,6 +322,9 @@ var CBIZoneForwards = form.DummyValue.extend({ if (!dzones.length) dzones.push(E('label', { 'class': 'zonebadge zonebadge-empty' }, E('strong', this.defaults.getForward()))); + else + dzones.push(E('label', { 'class': 'zonebadge zonebadge-empty' }, + E('strong', '%s %s'.format(this.defaults.getForward(), ('all others'))))); return E('div', { 'class': 'zone-forwards' }, [ E('div', { 'class': 'zone-src' }, this.renderZone(zone)), diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js index dec8f8aad3..1940959c85 100644 --- a/modules/luci-base/htdocs/luci-static/resources/ui.js +++ b/modules/luci-base/htdocs/luci-static/resources/ui.js @@ -1255,7 +1255,7 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ { sb.setAttribute('open', ''); var pv = ul.cloneNode(true); - pv.classList.add('preview'); + pv.classList.add('preview'); if (fl) fl.classList.add('cbi-dropdown-open'); diff --git a/modules/luci-base/htdocs/luci-static/resources/validation.js b/modules/luci-base/htdocs/luci-static/resources/validation.js index 5719031cb7..87f5f4b42c 100644 --- a/modules/luci-base/htdocs/luci-static/resources/validation.js +++ b/modules/luci-base/htdocs/luci-static/resources/validation.js @@ -394,7 +394,7 @@ var ValidatorFactory = baseclass.extend({ if (this.value.length <= 253) return this.assert( (this.value.match(/^[a-zA-Z0-9_]+$/) != null || - (this.value.match(/^[a-zA-Z0-9_][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$/) && + (this.value.match(/^[a-zA-Z0-9_][a-zA-Z0-9_\-.]*[a-zA-Z0-9]\.?$/) && this.value.match(/[^0-9.]/))) && (!strict || !this.value.match(/^_/)), _('valid hostname')); |