luci-base: js linting fixes

Signed-off-by: Paul Donald <newtwen+github@gmail.com>
This commit is contained in:
Paul Donald
2026-02-14 19:02:34 +01:00
parent 92381c3ca2
commit 394d92e042
7 changed files with 84 additions and 115 deletions

View File

@@ -309,7 +309,7 @@ function cbi_init() {
nodes = document.querySelectorAll('[data-strings]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
var str = JSON.parse(node.getAttribute('data-strings'));
for (var key in str) {
for (var key2 in str[key]) {
@@ -321,30 +321,30 @@ function cbi_init() {
nodes = document.querySelectorAll('[data-depends]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
var index = parseInt(node.getAttribute('data-index'), 10);
var depends = JSON.parse(node.getAttribute('data-depends'));
if (!isNaN(index) && depends.length > 0) {
for (var alt = 0; alt < depends.length; alt++)
for (let alt = 0; alt < depends.length; alt++)
cbi_d_add(node, depends[alt], index);
}
}
nodes = document.querySelectorAll('[data-update]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
var events = node.getAttribute('data-update').split(' ');
for (var j = 0, event; (event = events[j]) !== undefined; j++)
for (let j = 0, event; (event = events[j]) !== undefined; j++)
node.addEventListener(event, cbi_d_update);
}
nodes = document.querySelectorAll('[data-choices]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
var choices = JSON.parse(node.getAttribute('data-choices')),
for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
let choices = JSON.parse(node.getAttribute('data-choices')),
options = {};
for (var j = 0; j < choices[0].length; j++)
for (let j = 0; j < choices[0].length; j++)
options[choices[0][j]] = choices[1][j];
var def = (node.getAttribute('data-optional') === 'true')
@@ -364,19 +364,19 @@ function cbi_init() {
nodes = document.querySelectorAll('[data-dynlist]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
var choices = JSON.parse(node.getAttribute('data-dynlist')),
for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
let choices = JSON.parse(node.getAttribute('data-dynlist')),
values = JSON.parse(node.getAttribute('data-values') || '[]'),
options = null;
if (choices[0] && choices[0].length) {
options = {};
for (var j = 0; j < choices[0].length; j++)
for (let j = 0; j < choices[0].length; j++)
options[choices[0][j]] = choices[1][j];
}
var dl = new L.ui.DynamicList(values, options, {
let dl = new L.ui.DynamicList(values, options, {
name: node.getAttribute('data-prefix'),
sort: choices[0],
datatype: choices[2],
@@ -384,14 +384,14 @@ function cbi_init() {
placeholder: node.getAttribute('data-placeholder')
});
var n = dl.render();
let n = dl.render();
n.addEventListener('cbi-dynlist-change', cbi_d_update);
node.parentNode.replaceChild(n, node);
}
nodes = document.querySelectorAll('[data-type]');
for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
cbi_validate_field(node, node.getAttribute('data-optional') === 'true',
node.getAttribute('data-type'));
}
@@ -401,7 +401,7 @@ function cbi_init() {
});
document.querySelectorAll('.cbi-section-remove > input[name^="cbi.rts"]').forEach(function(i) {
var handler = function(ev) {
let handler = function(ev) {
var bits = this.name.split(/\./),
section = document.getElementById('cbi-' + bits[2] + '-' + bits[3]);
@@ -415,7 +415,7 @@ function cbi_init() {
var tasks = [];
document.querySelectorAll('[data-ui-widget]').forEach(function(node) {
var args = JSON.parse(node.getAttribute('data-ui-widget') || '[]'),
let args = JSON.parse(node.getAttribute('data-ui-widget') || '[]'),
widget = new (Function.prototype.bind.apply(L.ui[args[0]], args)),
markup = widget.render();
@@ -562,7 +562,7 @@ function cbi_row_swap(elem, up, store)
node.classList.remove('cbi-rowstyle-2');
node.classList.add((n++ % 2) ? 'cbi-rowstyle-2' : 'cbi-rowstyle-1');
if (/-([^\-]+)$/.test(node.id))
if (/-([^-]+)$/.test(node.id))
ids.push(RegExp.$1);
}
}
@@ -675,7 +675,7 @@ String.prototype.format = function()
var re = /^(([^%]*)%('.|0|\x20)?(-)?(\d+)?(\.\d+)?(%|b|c|d|u|f|o|s|x|X|q|h|j|t|m))/;
var a = b = [], numSubstitutions = 0, numMatches = 0;
while (a = re.exec(str)) {
while ((a = re.exec(str)) !== null) {
var m = a[1];
var leftpart = a[2], pPad = a[3], pJustify = a[4], pMinLength = a[5];
var pPrecision = a[6], pType = a[7];
@@ -810,7 +810,7 @@ String.prototype.format = function()
if (pMinLength) {
subst = subst.toString();
for (var i = subst.length; i < pMinLength; i++)
for (let i = subst.length; i < pMinLength; i++)
if (pJustify == '-')
subst = subst + ' ';
else
@@ -895,13 +895,6 @@ if (!window.requestAnimationFrame) {
*/
function isElem(e) { return L.dom.elem(e) }
/**
* Parse an HTML string into a DOM element.
* @param {string} s - HTML string.
* @returns {HTMLElement} Parsed DOM element.
*/
function toElem(s) { return L.dom.parse(s) }
/**
* Test whether node matches a CSS selector.
* @param {Node} node - Node to test.
@@ -960,28 +953,6 @@ function cbi_update_table(table, data, placeholder) {
t.update(data, placeholder);
}
/**
* Show a modal dialog with the given title and children content.
* @deprecated
* @param {string} title - Title of the modal.
* @param {HTMLElement|Array<HTMLElement>} children - Content of the modal.
* @returns {Promise} Promise that resolves when modal shown or when closed depending on L.showModal.
*/
function showModal(title, children)
{
return L.showModal(title, children);
}
/**
* Hide any currently shown modal dialog.
* @deprecated
* @returns {*} Return value forwarded from L.hideModal.
*/
function hideModal()
{
return L.hideModal();
}
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('validation-failure', function(ev) {

View File

@@ -143,11 +143,11 @@ Firewall = L.Class.extend({
getZones: function() {
return initFirewallState().then(function() {
var sections = uci.sections('firewall', 'zone'),
zones = [];
const sections = uci.sections('firewall', 'zone');
const zones = [];
for (var i = 0; i < sections.length; i++)
zones.push(new Zone(sections[i]['.name']));
for (let s of sections)
zones.push(new Zone(s['.name']));
zones.sort(function(a, b) { return a.getName() > b.getName() });
@@ -157,11 +157,11 @@ Firewall = L.Class.extend({
getZoneByNetwork: function(network) {
return initFirewallState().then(function() {
var sections = uci.sections('firewall', 'zone');
const sections = uci.sections('firewall', 'zone');
for (var i = 0; i < sections.length; i++)
if (L.toArray(sections[i].network).indexOf(network) != -1)
return new Zone(sections[i]['.name']);
for (let s of sections)
if (L.toArray(s.network).indexOf(network) != -1)
return new Zone(s['.name']);
return null;
});
@@ -169,8 +169,8 @@ Firewall = L.Class.extend({
deleteZone: function(name) {
return initFirewallState().then(function() {
var section = uci.get('firewall', name),
found = false;
const section = uci.get('firewall', name);
let found = false;
if (section != null && section['.type'] == 'zone') {
found = true;
@@ -178,28 +178,28 @@ Firewall = L.Class.extend({
uci.remove('firewall', section['.name']);
}
else if (name != null) {
var sections = uci.sections('firewall', 'zone');
const sections = uci.sections('firewall', 'zone');
for (var i = 0; i < sections.length; i++) {
if (sections[i].name != name)
for (let s of sections) {
if (s.name != name)
continue;
found = true;
uci.remove('firewall', sections[i]['.name']);
uci.remove('firewall', s['.name']);
}
}
if (found == true) {
sections = uci.sections('firewall');
const sections = uci.sections('firewall');
for (var i = 0; i < sections.length; i++) {
if (sections[i]['.type'] != 'rule' &&
sections[i]['.type'] != 'redirect' &&
sections[i]['.type'] != 'forwarding')
for (let s of sections) {
if (s['.type'] != 'rule' &&
s['.type'] != 'redirect' &&
s['.type'] != 'forwarding')
continue;
if (sections[i].src == name || sections[i].dest == name)
uci.remove('firewall', sections[i]['.name']);
if (s.src == name || s.dest == name)
uci.remove('firewall', s['.name']);
}
}
@@ -215,31 +215,31 @@ Firewall = L.Class.extend({
if (lookupZone(newName) != null)
return false;
var sections = uci.sections('firewall', 'zone'),
found = false;
const sections = uci.sections('firewall', 'zone');
let found = false;
for (var i = 0; i < sections.length; i++) {
if (sections[i].name != oldName)
for (let s of sections) {
if (s.name != oldName)
continue;
uci.set('firewall', sections[i]['.name'], 'name', newName);
uci.set('firewall', s['.name'], 'name', newName);
found = true;
}
if (found == true) {
sections = uci.sections('firewall');
const sections = uci.sections('firewall');
for (var i = 0; i < sections.length; i++) {
if (sections[i]['.type'] != 'rule' &&
sections[i]['.type'] != 'redirect' &&
sections[i]['.type'] != 'forwarding')
for (let s of sections) {
if (s['.type'] != 'rule' &&
s['.type'] != 'redirect' &&
s['.type'] != 'forwarding')
continue;
if (sections[i].src == oldName)
uci.set('firewall', sections[i]['.name'], 'src', newName);
if (s.src == oldName)
uci.set('firewall', s['.name'], 'src', newName);
if (sections[i].dest == oldName)
uci.set('firewall', sections[i]['.name'], 'dest', newName);
if (s.dest == oldName)
uci.set('firewall', s['.name'], 'dest', newName);
}
}

View File

@@ -308,7 +308,7 @@ const CBIAbstractElement = baseclass.extend(/** @lends LuCI.form.AbstractElement
* entities decoded.
*/
stripTags(s) {
if (typeof(s) == 'string' && !s.match(/[<>\&]/))
if (typeof(s) == 'string' && !s.match(/[<>&]/))
return s;
const x = dom.elem(s) ? s : dom.parse(`<div>${s}</div>`);
@@ -3657,7 +3657,7 @@ const CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection
index = i;
});
ev.currentTarget.parentNode.querySelectorAll('tr.cbi-section-table-row').forEach(L.bind((tr, i) => {
ev.currentTarget.parentNode.querySelectorAll('tr.cbi-section-table-row').forEach(L.bind((tr) => {
const sid = tr.getAttribute('data-sid');
const opt = tr.childNodes[index].getAttribute('data-name');
let val = this.cfgvalue(sid, opt);

View File

@@ -99,19 +99,19 @@ var rpcErrors = [
*/
function handleRpcReply(expect, rc) {
if (typeof(rc) == 'number' && rc != 0) {
var e = new Error(rpc.getStatusText(rc)); e.name = rpcErrors[rc] || 'Error';
let e = new Error(rpc.getStatusText(rc)); e.name = rpcErrors[rc] || 'Error';
throw e;
}
if (expect) {
var type = Object.prototype.toString;
const type = Object.prototype.toString;
for (var key in expect) {
for (let key in expect) {
if (rc != null && key != '')
rc = rc[key];
if (rc == null || type.call(rc) != type.call(expect[key])) {
var e = new Error(_('Unexpected reply data format')); e.name = 'TypeError';
let e = new Error(_('Unexpected reply data format')); e.name = 'TypeError';
throw e;
}

View File

@@ -20,7 +20,7 @@
* Class declaration and inheritance helper
*/
const toCamelCase = s => s.replace(/(?:^|[\. -])(.)/g, (m0, m1) => m1.toUpperCase());
const toCamelCase = s => s.replace(/(?:^|[. -])(.)/g, (m0, m1) => m1.toUpperCase());
/**
* @class
@@ -2261,7 +2261,7 @@
if (setenv.base_url == null)
this.error('InternalError', 'Cannot find url of luci.js');
setenv.cgi_base = setenv.scriptname.replace(/\/[^\/]+$/, '');
setenv.cgi_base = setenv.scriptname.replace(/\/[^/]+$/, '');
Object.assign(env, setenv);

View File

@@ -925,7 +925,7 @@ const UISelect = UIElement.extend(/** @lends LuCI.ui.Select.prototype */ {
return;
}
const radioEls = frameEl.querySelectorAll('input[type="radio"]');
const radioEls = this.node.querySelectorAll('input[type="radio"]');
for (let i = 0; i < radioEls.length; i++)
radioEls[i].checked = (radioEls[i].value == value);
}
@@ -1165,7 +1165,7 @@ const UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
const ul = sb.querySelector('ul');
const more = sb.appendChild(E('span', { class: 'more', tabindex: -1 }, '···'));
const open = sb.appendChild(E('span', { class: 'open', tabindex: -1 }, '▾'));
sb.appendChild(E('span', { class: 'open', tabindex: -1 }, '▾'));
const canary = sb.appendChild(E('div'));
const create = sb.querySelector(this.options.create_query);
let ndisplay = this.options.display_items;
@@ -1296,7 +1296,6 @@ const UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
* @param {Node} sb
*/
openDropdown(sb) {
const st = window.getComputedStyle(sb, null);
const ul = sb.querySelector('ul');
const li = ul.querySelectorAll('li');
const fl = findParent(sb, '.cbi-value-field');
@@ -2492,7 +2491,6 @@ const UIDynamicList = UIElement.extend(/** @lends LuCI.ui.DynamicList.prototype
});
dl.addEventListener('touchstart', (e) => {
const touch = e.touches[0];
const target = e.target.closest('.item');
if (target) {
draggedItem = target;
@@ -3245,7 +3243,7 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
canonicalizePath(path) {
return path.replace(/\/{2,}/g, '/') // Collapse multiple slashes
.replace(/\/\.(\/|$)/g, '/') // Remove `/.`
.replace(/[^\/]+\/\.\.(\/|$)/g, '/') // Resolve `/..`
.replace(/[^/]+\/\.\.(\/|$)/g, '/') // Resolve `/..`
.replace(/\/$/g, (m, o, s) => s.length > 1 ? '' : '/'); // Remove trailing `/` only if not root
},
@@ -3377,7 +3375,7 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
* @returns {Promise}
*/
handleDelete(path, fileStat, ev) {
const parent = path.replace(/\/[^\/]+$/, '') ?? '/';
const parent = path.replace(/\/[^/]+$/, '') ?? '/';
const name = path.replace(/^.+\//, '');
let msg;
@@ -3436,7 +3434,7 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
const nameinput = ev.target.parentNode.querySelector('input[type="text"]');
const uploadbtn = ev.target.parentNode.querySelector('button.cbi-button-save');
nameinput.value = ev.target.value.replace(/^.+[\/\\]/, '');
nameinput.value = ev.target.value.replace(/^.+[/\\]/, '');
uploadbtn.disabled = false;
}
}),
@@ -3653,7 +3651,7 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
handleFileBrowser(ev) {
const button = ev.target;
const browser = button.nextElementSibling;
let path = this.stat ? this.stat.path.replace(/\/[^\/]+$/, '') : (this.options.initial_directory ?? this.options.root_directory);
let path = this.stat ? this.stat.path.replace(/\/[^/]+$/, '') : (this.options.initial_directory ?? this.options.root_directory);
if (path.indexOf(this.options.root_directory) != 0)
path = this.options.root_directory;
@@ -3864,8 +3862,8 @@ const UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ {
const trow = table.appendChild(E('tr', { 'class': 'tr placeholder' }));
const td = trow.appendChild(E('td', { 'class': 'td' }, placeholder));
if (typeof(captionClasses) == 'object')
DOMTokenList.prototype.add.apply(td.classList, L.toArray(captionClasses[0]));
if (typeof(options.captionClasses) == 'object')
DOMTokenList.prototype.add.apply(td.classList, L.toArray(options.captionClasses[0]));
}
DOMTokenList.prototype.add.apply(table.classList, L.toArray(options.classes));
@@ -4600,7 +4598,6 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
for (let i = 0; i < items.length; i += 2) {
if (items[i+1] !== null && items[i+1] !== undefined) {
const sep = separators[(i/2) % separators.length];
const cld = [];
children.push(E('span', { class: 'nowrap' }, [
items[i] ? E('strong', `${items[i]}: `) : '',
@@ -4695,13 +4692,14 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
const menu = E('ul', { 'class': 'cbi-tabmenu' });
const group = panes[0].parentNode;
const groupId = +group.getAttribute('data-tab-group');
let selected = null;
if (group.getAttribute('data-initialized') === 'true')
return;
for (let i = 0, pane; pane = panes[i]; i++) {
let pane;
for (let i = 0; i < panes.length; i++) {
pane = panes[i];
const name = pane.getAttribute('data-tab');
const title = pane.getAttribute('data-tab-title');
const active = pane.getAttribute('data-tab-active') === 'true';
@@ -4810,7 +4808,8 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
*/
getActiveTabId(pane) {
const path = this.getPathForPane(pane);
return +this.getActiveTabState().paths[path] ?? 0;
const p = +(this.getActiveTabState().paths[path]);
return p ?? 0;
},
/**
@@ -4872,7 +4871,6 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
const name = tab.getAttribute('data-tab');
const menu = tab.parentNode;
const group = menu.nextElementSibling;
const groupId = +group.getAttribute('data-tab-group');
let index = 0;
ev.preventDefault();
@@ -5090,7 +5088,7 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
for (let i = 0; i < 2; i++)
for (let j = 0; j < ipaddrs.length; j++)
tasks.push(this.pingDevice(i ? 'https' : 'http', ipaddrs[j])
.then(ev => { reachable = ev.target.src.replace(/^(https?:\/\/[^\/]+).*$/, '$1/') }, () => {}));
.then(ev => { reachable = ev.target.src.replace(/^(https?:\/\/[^/]+).*$/, '$1/') }, () => {}));
return Promise.all(tasks).then(() => {
if (reachable) {

View File

@@ -375,18 +375,18 @@ const ValidatorFactory = baseclass.extend({
_('valid IPv6 network'));
},
iprange(negative) {
return this.assert(this.apply('iprange4', null, [negative]) || this.apply('iprange6', null, [negative]),
iprange() {
return this.assert(this.apply('iprange4', null, []) || this.apply('iprange6', null, []),
_('valid IP address range'));
},
iprange4(negative) {
iprange4() {
const m = this.value.split('-');
return this.assert(m.length == 2 && arrayle(this.factory.parseIPv4(m[0]), this.factory.parseIPv4(m[1])),
_('valid IPv4 address range'));
},
iprange6(negative) {
iprange6() {
const m = this.value.split('-');
return this.assert(m.length == 2 && arrayle(this.factory.parseIPv6(m[0]), this.factory.parseIPv6(m[1])),
_('valid IPv6 address range'));
@@ -449,8 +449,8 @@ const ValidatorFactory = baseclass.extend({
},
ipaddrport(bracket) {
const m4 = this.value.match(/^([^\[\]:]+):(\d+)$/);
const m6 = this.value.match((bracket == 1) ? /^\[(.+)\]:(\d+)$/ : /^([^\[\]]+):(\d+)$/);
const m4 = this.value.match(/^([^[\]:]+):(\d+)$/);
const m6 = this.value.match((bracket == 1) ? /^\[(.+)\]:(\d+)$/ : /^([^[\]]+):(\d+)$/);
if (m4)
return this.assert(this.apply('ip4addr', m4[1], [true]) && this.apply('port', m4[2]),
@@ -495,7 +495,7 @@ const ValidatorFactory = baseclass.extend({
if (v == '.' || v == '..')
return this.assert(false, _('valid network device name, not "." or ".."'));
return this.assert(v.match(/^[^:\/%\s]{1,15}$/), _('valid network device name between 1 and 15 characters not containing ":", "/", "%" or spaces'));
return this.assert(v.match(/^[^:/%\s]{1,15}$/), _('valid network device name between 1 and 15 characters not containing ":", "/", "%" or spaces'));
},
range(min, max) {
@@ -591,7 +591,7 @@ const ValidatorFactory = baseclass.extend({
},
phonedigit() {
return this.assert(this.value.match(/^[0-9\*#!\.]+$/),
return this.assert(this.value.match(/^[0-9*#!.]+$/),
_('valid phone digit (0-9, "*", "#", "!" or ".")'));
},