summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/htdocs
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-base/htdocs')
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/form.js139
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/luci.js4
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/network.js18
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/tools/widgets.js3
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/ui.js2
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/validation.js2
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'));