summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/htdocs/luci-static
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-base/htdocs/luci-static')
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/firewall.js25
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/form.js34
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/luci.js28
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/network.js12
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/tools/prng.js18
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/ui.js28
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/validation.js31
7 files changed, 127 insertions, 49 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/firewall.js b/modules/luci-base/htdocs/luci-static/resources/firewall.js
index b1c7de4358..4fa4954ba6 100644
--- a/modules/luci-base/htdocs/luci-static/resources/firewall.js
+++ b/modules/luci-base/htdocs/luci-static/resources/firewall.js
@@ -57,21 +57,7 @@ function getColorForName(forName) {
else if (forName == 'wan')
return '#f09090';
- random.seed(parseInt(sfh(forName), 16));
-
- var r = random.get(128),
- g = random.get(128),
- min = 0,
- max = 128;
-
- if ((r + g) < 128)
- min = 128 - r - g;
- else
- max = 255 - r - g;
-
- var b = min + Math.floor(random.get() * (max - min));
-
- return '#%02x%02x%02x'.format(0xff - r, 0xff - g, 0xff - b);
+ return random.derive_color(forName);
}
@@ -106,7 +92,6 @@ Firewall = L.Class.extend({
z = uci.add('firewall', 'zone');
uci.set('firewall', z, 'name', name);
- uci.set('firewall', z, 'network', ' ');
uci.set('firewall', z, 'input', d.getInput() || 'DROP');
uci.set('firewall', z, 'output', d.getOutput() || 'DROP');
uci.set('firewall', z, 'forward', d.getForward() || 'DROP');
@@ -347,17 +332,17 @@ Zone = AbstractFirewallItem.extend({
return false;
newNetworks.push(network);
- this.set('network', newNetworks.join(' '));
+ this.set('network', newNetworks);
return true;
},
deleteNetwork: function(network) {
var oldNetworks = this.getNetworks(),
- newNetworks = oldNetworks.filter(function(net) { return net != network });
+ newNetworks = oldNetworks.filter(function(net) { return net != network });
if (newNetworks.length > 0)
- this.set('network', newNetworks.join(' '));
+ this.set('network', newNetworks);
else
this.set('network', null);
@@ -369,7 +354,7 @@ Zone = AbstractFirewallItem.extend({
},
clearNetworks: function() {
- this.set('network', ' ');
+ this.set('network', null);
},
getDevices: function() {
diff --git a/modules/luci-base/htdocs/luci-static/resources/form.js b/modules/luci-base/htdocs/luci-static/resources/form.js
index 1588bc7bfb..58a31dddb2 100644
--- a/modules/luci-base/htdocs/luci-static/resources/form.js
+++ b/modules/luci-base/htdocs/luci-static/resources/form.js
@@ -3602,13 +3602,47 @@ var CBIFlagValue = CBIValue.extend(/** @lends LuCI.form.FlagValue.prototype */ {
* @default 0
*/
+ /**
+ * Set a tooltip for the flag option.
+ *
+ * If set to a string, it will be used as-is as a tooltip.
+ *
+ * If set to a function, the function will be invoked and the return
+ * value will be shown as a tooltip. If the return value of the function
+ * is `null` no tooltip will be set.
+ *
+ * @name LuCI.form.TypedSection.prototype#tooltip
+ * @type string|function
+ * @default null
+ */
+
+ /**
+ * Set a tooltip icon.
+ *
+ * If set, this icon will be shown for the default one.
+ * This could also be a png icon from the resources directory.
+ *
+ * @name LuCI.form.TypedSection.prototype#tooltipicon
+ * @type string
+ * @default 'ℹ️';
+ */
+
/** @private */
renderWidget: function(section_id, option_index, cfgvalue) {
+ var tooltip = null;
+
+ if (typeof(this.tooltip) == 'function')
+ tooltip = this.tooltip.apply(this, [section_id]);
+ else if (typeof(this.tooltip) == 'string')
+ tooltip = (arguments.length > 1) ? ''.format.apply(this.tooltip, this.varargs(arguments, 1)) : this.tooltip;
+
var widget = new ui.Checkbox((cfgvalue != null) ? cfgvalue : this.default, {
id: this.cbid(section_id),
value_enabled: this.enabled,
value_disabled: this.disabled,
validate: L.bind(this.validate, this, section_id),
+ tooltip: tooltip,
+ tooltipicon: this.tooltipicon,
disabled: (this.readonly != null) ? this.readonly : this.map.readonly
});
diff --git a/modules/luci-base/htdocs/luci-static/resources/luci.js b/modules/luci-base/htdocs/luci-static/resources/luci.js
index faed3aa6d2..23853e2cc8 100644
--- a/modules/luci-base/htdocs/luci-static/resources/luci.js
+++ b/modules/luci-base/htdocs/luci-static/resources/luci.js
@@ -672,12 +672,12 @@
* 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.
+ * @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.
*/
/**
@@ -982,12 +982,13 @@
if (!Poll.active())
return;
+ var res_json = null;
try {
- callback(res, res.json(), res.duration);
- }
- catch (err) {
- callback(res, null, res.duration);
+ res_json = res.json();
}
+ catch (err) {}
+
+ callback(res, res_json, res.duration);
});
};
@@ -2971,7 +2972,12 @@
}).filter(function(e) {
return (e[1] != null);
}).sort(function(a, b) {
- return (a[1] > b[1]);
+ if (a[1] < b[1])
+ return -1;
+ else if (a[1] > b[1])
+ return 1;
+ else
+ return 0;
}).map(function(e) {
return e[0];
});
diff --git a/modules/luci-base/htdocs/luci-static/resources/network.js b/modules/luci-base/htdocs/luci-static/resources/network.js
index 1f749c593c..1e24915f97 100644
--- a/modules/luci-base/htdocs/luci-static/resources/network.js
+++ b/modules/luci-base/htdocs/luci-static/resources/network.js
@@ -1453,6 +1453,18 @@ Network = baseclass.extend(/** @lends LuCI.network.prototype */ {
}
}
+ rv.sort(function(a, b) {
+ if (a.metric != b.metric)
+ return (a.metric - b.metric);
+
+ if (a.interface < b.interface)
+ return -1;
+ else if (a.interface > b.interface)
+ return 1;
+
+ return 0;
+ });
+
return rv;
}, this));
},
diff --git a/modules/luci-base/htdocs/luci-static/resources/tools/prng.js b/modules/luci-base/htdocs/luci-static/resources/tools/prng.js
index 752dc75ce8..b916cc7792 100644
--- a/modules/luci-base/htdocs/luci-static/resources/tools/prng.js
+++ b/modules/luci-base/htdocs/luci-static/resources/tools/prng.js
@@ -89,5 +89,23 @@ return L.Class.extend({
}
return Math.floor(r * (u - l + 1)) + l;
+ },
+
+ derive_color: function(string) {
+ this.seed(parseInt(sfh(string), 16));
+
+ var r = this.get(128),
+ g = this.get(128),
+ min = 0,
+ max = 128;
+
+ if ((r + g) < 128)
+ min = 128 - r - g;
+ else
+ max = 255 - r - g;
+
+ var b = min + Math.floor(this.get() * (max - min));
+
+ return '#%02x%02x%02x'.format(0xff - r, 0xff - g, 0xff - b);
}
});
diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js
index 77074d5075..c8ebef6691 100644
--- a/modules/luci-base/htdocs/luci-static/resources/ui.js
+++ b/modules/luci-base/htdocs/luci-static/resources/ui.js
@@ -610,6 +610,22 @@ var UICheckbox = UIElement.extend(/** @lends LuCI.ui.Checkbox.prototype */ {
frameEl.appendChild(E('label', { 'for': id }));
+ if (this.options.tooltip != null) {
+ var icon = "⚠️";
+
+ if (this.options.tooltipicon != null)
+ icon = this.options.tooltipicon;
+
+ frameEl.appendChild(
+ E('label', { 'class': 'cbi-tooltip-container' },[
+ icon,
+ E('div', { 'class': 'cbi-tooltip' },
+ this.options.tooltip
+ )
+ ])
+ );
+ }
+
return this.bind(frameEl);
},
@@ -1344,6 +1360,8 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
/** @private */
toggleItem: function(sb, li, force_state) {
+ var ul = li.parentNode;
+
if (li.hasAttribute('unselectable'))
return;
@@ -1420,7 +1438,7 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
this.closeDropdown(sb, true);
}
- this.saveValues(sb, li.parentNode);
+ this.saveValues(sb, ul);
},
/** @private */
@@ -3597,9 +3615,11 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
this.setActiveTabId(panes[selected], selected);
}
- panes[selected].dispatchEvent(new CustomEvent('cbi-tab-active', {
- detail: { tab: panes[selected].getAttribute('data-tab') }
- }));
+ requestAnimationFrame(L.bind(function(pane) {
+ pane.dispatchEvent(new CustomEvent('cbi-tab-active', {
+ detail: { tab: pane.getAttribute('data-tab') }
+ }));
+ }, this, panes[selected]));
this.updateTabs(group);
},
diff --git a/modules/luci-base/htdocs/luci-static/resources/validation.js b/modules/luci-base/htdocs/luci-static/resources/validation.js
index d47392c239..0d2157bee0 100644
--- a/modules/luci-base/htdocs/luci-static/resources/validation.js
+++ b/modules/luci-base/htdocs/luci-static/resources/validation.js
@@ -272,18 +272,21 @@ var ValidatorFactory = baseclass.extend({
_('valid IPv6 prefix value (0-128)'));
},
- cidr: function() {
- return this.assert(this.apply('cidr4') || this.apply('cidr6'), _('valid IPv4 or IPv6 CIDR'));
+ cidr: function(negative) {
+ return this.assert(this.apply('cidr4', null, [negative]) || this.apply('cidr6', null, [negative]),
+ _('valid IPv4 or IPv6 CIDR'));
},
- cidr4: function() {
- var m = this.value.match(/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(\d{1,2})$/);
- return this.assert(m && this.factory.parseIPv4(m[1]) && this.apply('ip4prefix', m[2]), _('valid IPv4 CIDR'));
+ cidr4: function(negative) {
+ var m = this.value.match(/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(-)?(\d{1,2})$/);
+ return this.assert(m && this.factory.parseIPv4(m[1]) && (negative || !m[2]) && this.apply('ip4prefix', m[3]),
+ _('valid IPv4 CIDR'));
},
- cidr6: function() {
- var m = this.value.match(/^([0-9a-fA-F:.]+)\/(\d{1,3})$/);
- return this.assert(m && this.factory.parseIPv6(m[1]) && this.apply('ip6prefix', m[2]), _('valid IPv6 CIDR'));
+ cidr6: function(negative) {
+ var m = this.value.match(/^([0-9a-fA-F:.]+)\/(-)?(\d{1,3})$/);
+ return this.assert(m && this.factory.parseIPv6(m[1]) && (negative || !m[2]) && this.apply('ip6prefix', m[3]),
+ _('valid IPv6 CIDR'));
},
ipnet4: function() {
@@ -304,18 +307,18 @@ var ValidatorFactory = baseclass.extend({
return this.assert(!(!v6 || v6[0] || v6[1] || v6[2] || v6[3]), _('valid IPv6 host id'));
},
- ipmask: function() {
- return this.assert(this.apply('ipmask4') || this.apply('ipmask6'),
+ ipmask: function(negative) {
+ return this.assert(this.apply('ipmask4', null, [negative]) || this.apply('ipmask6', null, [negative]),
_('valid network in address/netmask notation'));
},
- ipmask4: function() {
- return this.assert(this.apply('cidr4') || this.apply('ipnet4') || this.apply('ip4addr'),
+ ipmask4: function(negative) {
+ return this.assert(this.apply('cidr4', null, [negative]) || this.apply('ipnet4') || this.apply('ip4addr'),
_('valid IPv4 network'));
},
- ipmask6: function() {
- return this.assert(this.apply('cidr6') || this.apply('ipnet6') || this.apply('ip6addr'),
+ ipmask6: function(negative) {
+ return this.assert(this.apply('cidr6', null, [negative]) || this.apply('ipnet6') || this.apply('ip6addr'),
_('valid IPv6 network'));
},