WebUI: prefer for loop over Array.forEach method

The `for` loop can do everything `forEach` can and doesn't need a closure.
This commit is contained in:
Chocobo1
2025-08-24 18:34:10 +08:00
parent 2be052e9c4
commit 6ac0c5a8b8
12 changed files with 58 additions and 59 deletions

View File

@@ -70,6 +70,7 @@ export default [
"Stylistic/quote-props": ["error", "consistent-as-needed"], "Stylistic/quote-props": ["error", "consistent-as-needed"],
"Stylistic/semi": "error", "Stylistic/semi": "error",
"Stylistic/spaced-comment": ["error", "always", { exceptions: ["*"] }], "Stylistic/spaced-comment": ["error", "always", { exceptions: ["*"] }],
"Unicorn/no-array-for-each": "error",
"Unicorn/no-zero-fractions": "error", "Unicorn/no-zero-fractions": "error",
"Unicorn/prefer-number-properties": "error", "Unicorn/prefer-number-properties": "error",
"Unicorn/switch-case-braces": ["error", "avoid"] "Unicorn/switch-case-braces": ["error", "avoid"]

View File

@@ -161,11 +161,8 @@
*/ */
fileRenamer.onChanged = (matchedRows) => { fileRenamer.onChanged = (matchedRows) => {
// Clear renamed column // Clear renamed column
document for (const span of document.querySelectorAll("span[id^='filesTablefileRenamed']"))
.querySelectorAll("span[id^='filesTablefileRenamed']") span.textContent = "";
.forEach((span) => {
span.textContent = "";
});
// Update renamed column for matched rows // Update renamed column for matched rows
for (let i = 0; i < matchedRows.length; ++i) { for (let i = 0; i < matchedRows.length; ++i) {
@@ -312,14 +309,14 @@
const rootNode = new window.qBittorrent.FileTree.FolderNode(); const rootNode = new window.qBittorrent.FileTree.FolderNode();
rootNode.autoCalculateCheckedState = false; rootNode.autoCalculateCheckedState = false;
rows.forEach((row) => { for (const row of rows) {
const pathItems = row.path.split(window.qBittorrent.Filesystem.PathSeparator); const pathItems = row.path.split(window.qBittorrent.Filesystem.PathSeparator);
pathItems.pop(); // remove last item (i.e. file name) pathItems.pop(); // remove last item (i.e. file name)
let parent = rootNode; let parent = rootNode;
pathItems.forEach((folderName) => { for (const folderName of pathItems) {
if (folderName === ".unwanted") if (folderName === ".unwanted")
return; continue;
let folderNode = null; let folderNode = null;
if (parent.children !== null) { if (parent.children !== null) {
@@ -349,7 +346,7 @@
} }
parent = folderNode; parent = folderNode;
}); }
const childNode = new window.qBittorrent.FileTree.FileNode(); const childNode = new window.qBittorrent.FileTree.FileNode();
childNode.rowId = rowId; childNode.rowId = rowId;
@@ -362,7 +359,7 @@
parent.addChild(childNode); parent.addChild(childNode);
++rowId; ++rowId;
}); }
bulkRenameFilesTable.populateTable(rootNode); bulkRenameFilesTable.populateTable(rootNode);
bulkRenameFilesTable.updateTable(false); bulkRenameFilesTable.updateTable(false);

View File

@@ -583,7 +583,8 @@ window.addEventListener("DOMContentLoaded", (event) => {
if (!categoryList) if (!categoryList)
return; return;
[...categoryList.children].forEach((el) => { el.remove(); }); for (const el of [...categoryList.children])
el.remove();
const categoryItemTemplate = document.getElementById("categoryFilterItem"); const categoryItemTemplate = document.getElementById("categoryFilterItem");
@@ -704,7 +705,8 @@ window.addEventListener("DOMContentLoaded", (event) => {
if (tagFilterList === null) if (tagFilterList === null)
return; return;
[...tagFilterList.children].forEach((el) => { el.remove(); }); for (const el of [...tagFilterList.children])
el.remove();
const tagItemTemplate = document.getElementById("tagFilterItem"); const tagItemTemplate = document.getElementById("tagFilterItem");
@@ -757,7 +759,8 @@ window.addEventListener("DOMContentLoaded", (event) => {
if (trackerFilterList === null) if (trackerFilterList === null)
return; return;
[...trackerFilterList.children].forEach((el) => { el.remove(); }); for (const el of [...trackerFilterList.children])
el.remove();
const trackerItemTemplate = document.getElementById("trackerFilterItem"); const trackerItemTemplate = document.getElementById("trackerFilterItem");

View File

@@ -166,8 +166,10 @@ window.qBittorrent.ContextMenu ??= (() => {
} }
searchAndAddTargets() { searchAndAddTargets() {
if (this.options.targets.length > 0) if (this.options.targets.length > 0) {
document.querySelectorAll(this.options.targets).forEach((target) => { this.addTarget(target); }); for (const target of document.querySelectorAll(this.options.targets))
this.addTarget(target);
}
} }
triggerMenu(e, el) { triggerMenu(e, el) {
@@ -327,7 +329,7 @@ window.qBittorrent.ContextMenu ??= (() => {
const categoryCount = new Map(); const categoryCount = new Map();
const selectedRows = torrentsTable.selectedRowsIds(); const selectedRows = torrentsTable.selectedRowsIds();
selectedRows.forEach((item, index) => { for (const item of selectedRows) {
const data = torrentsTable.getRow(item).full_data; const data = torrentsTable.getRow(item).full_data;
if (data["seq_dl"] !== true) if (data["seq_dl"] !== true)
@@ -373,7 +375,7 @@ window.qBittorrent.ContextMenu ??= (() => {
const torrentCategory = data["category"]; const torrentCategory = data["category"];
const count = categoryCount.get(torrentCategory); const count = categoryCount.get(torrentCategory);
categoryCount.set(torrentCategory, ((count !== undefined) ? (count + 1) : 1)); categoryCount.set(torrentCategory, ((count !== undefined) ? (count + 1) : 1));
}); }
// hide renameFiles when more than 1 torrent is selected // hide renameFiles when more than 1 torrent is selected
if (selectedRows.length === 1) { if (selectedRows.length === 1) {
@@ -459,7 +461,9 @@ window.qBittorrent.ContextMenu ??= (() => {
updateCategoriesSubMenu(categories) { updateCategoriesSubMenu(categories) {
const contextCategoryList = document.getElementById("contextCategoryList"); const contextCategoryList = document.getElementById("contextCategoryList");
[...contextCategoryList.children].forEach((el) => { el.remove(); });
for (const el of [...contextCategoryList.children])
el.remove();
const createMenuItem = (text, imgURL, clickFn) => { const createMenuItem = (text, imgURL, clickFn) => {
const anchor = document.createElement("a"); const anchor = document.createElement("a");

View File

@@ -603,10 +603,10 @@ window.qBittorrent.DynamicTable ??= (() => {
const val = LocalPreferences.get(`columns_order_${this.dynamicTableDivId}`); const val = LocalPreferences.get(`columns_order_${this.dynamicTableDivId}`);
if ((val === null) || (val === undefined)) if ((val === null) || (val === undefined))
return; return;
val.split(",").forEach((v) => { for (const v of val.split(",")) {
if ((v in this.columns) && (!columnsOrder.contains(v))) if ((v in this.columns) && (!columnsOrder.contains(v)))
columnsOrder.push(v); columnsOrder.push(v);
}); }
for (let i = 0; i < this.columns.length; ++i) { for (let i = 0; i < this.columns.length; ++i) {
if (!columnsOrder.contains(this.columns[i].name)) if (!columnsOrder.contains(this.columns[i].name))
@@ -2474,9 +2474,8 @@ window.qBittorrent.DynamicTable ??= (() => {
populateTable(root) { populateTable(root) {
this.fileTree.setRoot(root); this.fileTree.setRoot(root);
root.children.forEach((node) => { for (const node of root.children)
this.#addNodeToTable(node, 0, root); this.#addNodeToTable(node, 0, root);
});
} }
#addNodeToTable(node, depth, parent) { #addNodeToTable(node, depth, parent) {
@@ -2490,9 +2489,8 @@ window.qBittorrent.DynamicTable ??= (() => {
rowId: node.rowId, rowId: node.rowId,
}); });
node.children.forEach((child) => { for (const child of node.children)
this.#addNodeToTable(child, depth + 1, node); this.#addNodeToTable(child, depth + 1, node);
});
} }
getRoot() { getRoot() {

View File

@@ -725,9 +725,8 @@ window.qBittorrent.Search ??= (() => {
if (prevSearchPluginsResponse !== responseJSON) { if (prevSearchPluginsResponse !== responseJSON) {
prevSearchPluginsResponse = responseJSON; prevSearchPluginsResponse = responseJSON;
searchPlugins.length = 0; searchPlugins.length = 0;
responseJSON.forEach((plugin) => { for (const plugin of responseJSON)
searchPlugins.push(plugin); searchPlugins.push(plugin);
});
const pluginOptions = []; const pluginOptions = [];
pluginOptions.push(createOption("QBT_TR(Only enabled)QBT_TR[CONTEXT=SearchEngineWidget]", "enabled")); pluginOptions.push(createOption("QBT_TR(Only enabled)QBT_TR[CONTEXT=SearchEngineWidget]", "enabled"));

View File

@@ -92,15 +92,13 @@ window.qBittorrent.TorrentContent ??= (() => {
fileIds.push(node.fileId); fileIds.push(node.fileId);
if (node.isFolder) { if (node.isFolder) {
node.children.forEach((child) => { for (const child of node.children)
getChildFiles(child); getChildFiles(child);
});
} }
}; };
node.children.forEach((child) => { for (const child of node.children)
getChildFiles(child); getChildFiles(child);
});
return { return {
rowIds: rowIds, rowIds: rowIds,
@@ -228,7 +226,7 @@ window.qBittorrent.TorrentContent ??= (() => {
if (checkbox.state === TriState.Checked) { if (checkbox.state === TriState.Checked) {
setCheckboxUnchecked(checkbox); setCheckboxUnchecked(checkbox);
torrentFilesTable.rows.forEach((row) => { for (const row of torrentFilesTable.rows) {
const rowId = row.rowId; const rowId = row.rowId;
const node = torrentFilesTable.getNode(rowId); const node = torrentFilesTable.getNode(rowId);
const fileId = node.fileId; const fileId = node.fileId;
@@ -237,11 +235,11 @@ window.qBittorrent.TorrentContent ??= (() => {
rowIds.push(rowId); rowIds.push(rowId);
fileIds.push(fileId); fileIds.push(fileId);
} }
}); }
} }
else { else {
setCheckboxChecked(checkbox); setCheckboxChecked(checkbox);
torrentFilesTable.rows.forEach((row) => { for (const row of torrentFilesTable.rows) {
const rowId = row.rowId; const rowId = row.rowId;
const node = torrentFilesTable.getNode(rowId); const node = torrentFilesTable.getNode(rowId);
const fileId = node.fileId; const fileId = node.fileId;
@@ -250,7 +248,7 @@ window.qBittorrent.TorrentContent ??= (() => {
rowIds.push(rowId); rowIds.push(rowId);
fileIds.push(fileId); fileIds.push(fileId);
} }
}); }
} }
if (rowIds.length > 0) { if (rowIds.length > 0) {
@@ -332,14 +330,14 @@ window.qBittorrent.TorrentContent ??= (() => {
const rootNode = new window.qBittorrent.FileTree.FolderNode(); const rootNode = new window.qBittorrent.FileTree.FolderNode();
rows.forEach((row) => { for (const row of rows) {
const pathItems = row.fileName.split(window.qBittorrent.Filesystem.PathSeparator); const pathItems = row.fileName.split(window.qBittorrent.Filesystem.PathSeparator);
pathItems.pop(); // remove last item (i.e. file name) pathItems.pop(); // remove last item (i.e. file name)
let parent = rootNode; let parent = rootNode;
pathItems.forEach((folderName) => { for (const folderName of pathItems) {
if (folderName === ".unwanted") if (folderName === ".unwanted")
return; continue;
let folderNode = null; let folderNode = null;
if (parent.children !== null) { if (parent.children !== null) {
@@ -366,7 +364,7 @@ window.qBittorrent.TorrentContent ??= (() => {
} }
parent = folderNode; parent = folderNode;
}); }
const isChecked = row.checked ? TriState.Checked : TriState.Unchecked; const isChecked = row.checked ? TriState.Checked : TriState.Unchecked;
const childNode = new window.qBittorrent.FileTree.FileNode(); const childNode = new window.qBittorrent.FileTree.FileNode();
@@ -383,7 +381,7 @@ window.qBittorrent.TorrentContent ??= (() => {
parent.addChild(childNode); parent.addChild(childNode);
++rowId; ++rowId;
}); }
torrentFilesTable.populateTable(rootNode); torrentFilesTable.populateTable(rootNode);
torrentFilesTable.updateTable(); torrentFilesTable.updateTable();
@@ -399,21 +397,19 @@ window.qBittorrent.TorrentContent ??= (() => {
const rowIds = []; const rowIds = [];
const fileIds = []; const fileIds = [];
selectedRows.forEach((rowId) => { for (const rowId of selectedRows) {
rowIds.push(rowId); rowIds.push(rowId);
fileIds.push(Number(torrentFilesTable.getRowFileId(rowId))); fileIds.push(Number(torrentFilesTable.getRowFileId(rowId)));
}); }
const uniqueRowIds = new Set(); const uniqueRowIds = new Set();
const uniqueFileIds = new Set(); const uniqueFileIds = new Set();
for (let i = 0; i < rowIds.length; ++i) { for (let i = 0; i < rowIds.length; ++i) {
const rows = getAllChildren(rowIds[i], fileIds[i]); const rows = getAllChildren(rowIds[i], fileIds[i]);
rows.rowIds.forEach((rowId) => { for (const rowId of rows.rowIds)
uniqueRowIds.add(rowId); uniqueRowIds.add(rowId);
}); for (const fileId of rows.fileIds)
rows.fileIds.forEach((fileId) => {
uniqueFileIds.add(fileId); uniqueFileIds.add(fileId);
});
} }
setFilePriority([...uniqueRowIds.keys()], [...uniqueFileIds.keys()], priority); setFilePriority([...uniqueRowIds.keys()], [...uniqueFileIds.keys()], priority);

View File

@@ -210,9 +210,8 @@
menu: "logTableMenu", menu: "logTableMenu",
actions: { actions: {
Clear: () => { Clear: () => {
tableInfo[currentSelectedTab].instance.selectedRowsIds().forEach((rowId) => { for (const rowId of tableInfo[currentSelectedTab].instance.selectedRowsIds())
tableInfo[currentSelectedTab].instance.removeRow(rowId); tableInfo[currentSelectedTab].instance.removeRow(rowId);
});
updateLabelCount(); updateLabelCount();
} }

View File

@@ -2144,7 +2144,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
// Advanced Tab // Advanced Tab
const updateNetworkInterfaces = (default_iface, default_iface_name) => { const updateNetworkInterfaces = (default_iface, default_iface_name) => {
[...document.getElementById("networkInterface").children].forEach((el) => { el.remove(); }); for (const el of [...document.getElementById("networkInterface").children])
el.remove();
fetch("api/v2/app/networkInterfaceList", { fetch("api/v2/app/networkInterfaceList", {
method: "GET", method: "GET",
@@ -2165,15 +2166,15 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
ifaces.push({ name: default_iface_name || default_iface, value: default_iface }); ifaces.push({ name: default_iface_name || default_iface, value: default_iface });
document.getElementById("networkInterface").options.add(new Option("QBT_TR(Any interface)QBT_TR[CONTEXT=OptionsDialog]", "")); document.getElementById("networkInterface").options.add(new Option("QBT_TR(Any interface)QBT_TR[CONTEXT=OptionsDialog]", ""));
ifaces.forEach((item, index) => { for (const item of ifaces)
document.getElementById("networkInterface").options.add(new Option(item.name, item.value)); document.getElementById("networkInterface").options.add(new Option(item.name, item.value));
});
document.getElementById("networkInterface").value = default_iface; document.getElementById("networkInterface").value = default_iface;
}); });
}; };
const updateInterfaceAddresses = (iface, default_addr) => { const updateInterfaceAddresses = (iface, default_addr) => {
[...document.getElementById("optionalIPAddressToBind").children].forEach((el) => { el.remove(); }); for (const el of [...document.getElementById("optionalIPAddressToBind").children])
el.remove();
const url = new URL("api/v2/app/networkInterfaceAddressList", window.location); const url = new URL("api/v2/app/networkInterfaceAddressList", window.location);
url.search = new URLSearchParams({ url.search = new URLSearchParams({
@@ -2196,9 +2197,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
document.getElementById("optionalIPAddressToBind").options.add(new Option("QBT_TR(All addresses)QBT_TR[CONTEXT=OptionDialog]", "")); document.getElementById("optionalIPAddressToBind").options.add(new Option("QBT_TR(All addresses)QBT_TR[CONTEXT=OptionDialog]", ""));
document.getElementById("optionalIPAddressToBind").options.add(new Option("QBT_TR(All IPv4 addresses)QBT_TR[CONTEXT=OptionDialog]", "0.0.0.0")); document.getElementById("optionalIPAddressToBind").options.add(new Option("QBT_TR(All IPv4 addresses)QBT_TR[CONTEXT=OptionDialog]", "0.0.0.0"));
document.getElementById("optionalIPAddressToBind").options.add(new Option("QBT_TR(All IPv6 addresses)QBT_TR[CONTEXT=OptionDialog]", "::")); document.getElementById("optionalIPAddressToBind").options.add(new Option("QBT_TR(All IPv6 addresses)QBT_TR[CONTEXT=OptionDialog]", "::"));
addresses.forEach((item, index) => { for (const item of addresses)
document.getElementById("optionalIPAddressToBind").options.add(new Option(item, item)); document.getElementById("optionalIPAddressToBind").options.add(new Option(item, item));
});
document.getElementById("optionalIPAddressToBind").value = default_addr; document.getElementById("optionalIPAddressToBind").value = default_addr;
}); });
}; };

View File

@@ -233,7 +233,8 @@
feedsToUpdate.add(row); feedsToUpdate.add(row);
} }
} }
feedsToUpdate.forEach((feed) => refreshFeed(feed.full_data.dataUid)); for (const feed of feedsToUpdate)
refreshFeed(feed.full_data.dataUid);
}, },
markRead: markSelectedAsRead, markRead: markSelectedAsRead,
rename: (el) => { rename: (el) => {
@@ -424,7 +425,8 @@
}; };
const clearDetails = () => { const clearDetails = () => {
[...document.getElementById("rssDetailsView").children].forEach((el) => { el.remove(); }); for (const el of [...document.getElementById("rssDetailsView").children])
el.remove();
}; };
const showDetails = (feedUid, articleID) => { const showDetails = (feedUid, articleID) => {

View File

@@ -789,14 +789,14 @@ Supports the formats: S01E01, 1x1, 2017.12.31 and 31.12.2017 (Date formats also
rssDownloaderFeedSelectionTable.clear(); rssDownloaderFeedSelectionTable.clear();
let rowID = -1; let rowID = -1;
feedList.forEach((feed) => { for (const feed of feedList) {
rssDownloaderFeedSelectionTable.updateRowData({ rssDownloaderFeedSelectionTable.updateRowData({
rowId: ++rowID, rowId: ++rowID,
checked: rulesList[ruleName].affectedFeeds.contains(feed.url), checked: rulesList[ruleName].affectedFeeds.contains(feed.url),
name: feed.name, name: feed.name,
url: feed.url url: feed.url
}); });
}); }
rssDownloaderFeedSelectionTable.updateTable(false); rssDownloaderFeedSelectionTable.updateTable(false);
updateMatchingArticles(ruleName); updateMatchingArticles(ruleName);
} }

View File

@@ -91,7 +91,7 @@
if (!confirm("QBT_TR(Are you sure you want to delete selected tasks?)QBT_TR[CONTEXT=TorrentCreator]")) if (!confirm("QBT_TR(Are you sure you want to delete selected tasks?)QBT_TR[CONTEXT=TorrentCreator]"))
return; return;
selectedTasks.forEach(task => { for (const task of selectedTasks) {
fetch("api/v2/torrentcreator/deleteTask", { fetch("api/v2/torrentcreator/deleteTask", {
method: "POST", method: "POST",
body: new URLSearchParams({ body: new URLSearchParams({
@@ -100,7 +100,7 @@
}).then((response) => { }).then((response) => {
load(); load();
}); });
}); }
}, },
exportTorrent: exportTorrents, exportTorrent: exportTorrents,
}, },