diff --git a/src/webui/www/eslint.config.mjs b/src/webui/www/eslint.config.mjs index 24487323d..4aa12988b 100644 --- a/src/webui/www/eslint.config.mjs +++ b/src/webui/www/eslint.config.mjs @@ -70,6 +70,7 @@ export default [ "Stylistic/quote-props": ["error", "consistent-as-needed"], "Stylistic/semi": "error", "Stylistic/spaced-comment": ["error", "always", { exceptions: ["*"] }], + "Unicorn/no-array-for-each": "error", "Unicorn/no-zero-fractions": "error", "Unicorn/prefer-number-properties": "error", "Unicorn/switch-case-braces": ["error", "avoid"] diff --git a/src/webui/www/private/rename_files.html b/src/webui/www/private/rename_files.html index 6e6385d6e..f178e6999 100644 --- a/src/webui/www/private/rename_files.html +++ b/src/webui/www/private/rename_files.html @@ -161,11 +161,8 @@ */ fileRenamer.onChanged = (matchedRows) => { // Clear renamed column - document - .querySelectorAll("span[id^='filesTablefileRenamed']") - .forEach((span) => { - span.textContent = ""; - }); + for (const span of document.querySelectorAll("span[id^='filesTablefileRenamed']")) + span.textContent = ""; // Update renamed column for matched rows for (let i = 0; i < matchedRows.length; ++i) { @@ -312,14 +309,14 @@ const rootNode = new window.qBittorrent.FileTree.FolderNode(); rootNode.autoCalculateCheckedState = false; - rows.forEach((row) => { + for (const row of rows) { const pathItems = row.path.split(window.qBittorrent.Filesystem.PathSeparator); pathItems.pop(); // remove last item (i.e. file name) let parent = rootNode; - pathItems.forEach((folderName) => { + for (const folderName of pathItems) { if (folderName === ".unwanted") - return; + continue; let folderNode = null; if (parent.children !== null) { @@ -349,7 +346,7 @@ } parent = folderNode; - }); + } const childNode = new window.qBittorrent.FileTree.FileNode(); childNode.rowId = rowId; @@ -362,7 +359,7 @@ parent.addChild(childNode); ++rowId; - }); + } bulkRenameFilesTable.populateTable(rootNode); bulkRenameFilesTable.updateTable(false); diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index 28a137924..6866ba6c4 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -583,7 +583,8 @@ window.addEventListener("DOMContentLoaded", (event) => { if (!categoryList) return; - [...categoryList.children].forEach((el) => { el.remove(); }); + for (const el of [...categoryList.children]) + el.remove(); const categoryItemTemplate = document.getElementById("categoryFilterItem"); @@ -704,7 +705,8 @@ window.addEventListener("DOMContentLoaded", (event) => { if (tagFilterList === null) return; - [...tagFilterList.children].forEach((el) => { el.remove(); }); + for (const el of [...tagFilterList.children]) + el.remove(); const tagItemTemplate = document.getElementById("tagFilterItem"); @@ -757,7 +759,8 @@ window.addEventListener("DOMContentLoaded", (event) => { if (trackerFilterList === null) return; - [...trackerFilterList.children].forEach((el) => { el.remove(); }); + for (const el of [...trackerFilterList.children]) + el.remove(); const trackerItemTemplate = document.getElementById("trackerFilterItem"); diff --git a/src/webui/www/private/scripts/contextmenu.js b/src/webui/www/private/scripts/contextmenu.js index a80b2a9db..9eef499bf 100644 --- a/src/webui/www/private/scripts/contextmenu.js +++ b/src/webui/www/private/scripts/contextmenu.js @@ -166,8 +166,10 @@ window.qBittorrent.ContextMenu ??= (() => { } searchAndAddTargets() { - if (this.options.targets.length > 0) - document.querySelectorAll(this.options.targets).forEach((target) => { this.addTarget(target); }); + if (this.options.targets.length > 0) { + for (const target of document.querySelectorAll(this.options.targets)) + this.addTarget(target); + } } triggerMenu(e, el) { @@ -327,7 +329,7 @@ window.qBittorrent.ContextMenu ??= (() => { const categoryCount = new Map(); const selectedRows = torrentsTable.selectedRowsIds(); - selectedRows.forEach((item, index) => { + for (const item of selectedRows) { const data = torrentsTable.getRow(item).full_data; if (data["seq_dl"] !== true) @@ -373,7 +375,7 @@ window.qBittorrent.ContextMenu ??= (() => { const torrentCategory = data["category"]; const count = categoryCount.get(torrentCategory); categoryCount.set(torrentCategory, ((count !== undefined) ? (count + 1) : 1)); - }); + } // hide renameFiles when more than 1 torrent is selected if (selectedRows.length === 1) { @@ -459,7 +461,9 @@ window.qBittorrent.ContextMenu ??= (() => { updateCategoriesSubMenu(categories) { 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 anchor = document.createElement("a"); diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index 8ac518e11..86dbf7ee7 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -603,10 +603,10 @@ window.qBittorrent.DynamicTable ??= (() => { const val = LocalPreferences.get(`columns_order_${this.dynamicTableDivId}`); if ((val === null) || (val === undefined)) return; - val.split(",").forEach((v) => { + for (const v of val.split(",")) { if ((v in this.columns) && (!columnsOrder.contains(v))) columnsOrder.push(v); - }); + } for (let i = 0; i < this.columns.length; ++i) { if (!columnsOrder.contains(this.columns[i].name)) @@ -2474,9 +2474,8 @@ window.qBittorrent.DynamicTable ??= (() => { populateTable(root) { this.fileTree.setRoot(root); - root.children.forEach((node) => { + for (const node of root.children) this.#addNodeToTable(node, 0, root); - }); } #addNodeToTable(node, depth, parent) { @@ -2490,9 +2489,8 @@ window.qBittorrent.DynamicTable ??= (() => { rowId: node.rowId, }); - node.children.forEach((child) => { + for (const child of node.children) this.#addNodeToTable(child, depth + 1, node); - }); } getRoot() { diff --git a/src/webui/www/private/scripts/search.js b/src/webui/www/private/scripts/search.js index e7e484c52..0d5a2913d 100644 --- a/src/webui/www/private/scripts/search.js +++ b/src/webui/www/private/scripts/search.js @@ -725,9 +725,8 @@ window.qBittorrent.Search ??= (() => { if (prevSearchPluginsResponse !== responseJSON) { prevSearchPluginsResponse = responseJSON; searchPlugins.length = 0; - responseJSON.forEach((plugin) => { + for (const plugin of responseJSON) searchPlugins.push(plugin); - }); const pluginOptions = []; pluginOptions.push(createOption("QBT_TR(Only enabled)QBT_TR[CONTEXT=SearchEngineWidget]", "enabled")); diff --git a/src/webui/www/private/scripts/torrent-content.js b/src/webui/www/private/scripts/torrent-content.js index 37a216b96..dd1b61e22 100644 --- a/src/webui/www/private/scripts/torrent-content.js +++ b/src/webui/www/private/scripts/torrent-content.js @@ -92,15 +92,13 @@ window.qBittorrent.TorrentContent ??= (() => { fileIds.push(node.fileId); if (node.isFolder) { - node.children.forEach((child) => { + for (const child of node.children) getChildFiles(child); - }); } }; - node.children.forEach((child) => { + for (const child of node.children) getChildFiles(child); - }); return { rowIds: rowIds, @@ -228,7 +226,7 @@ window.qBittorrent.TorrentContent ??= (() => { if (checkbox.state === TriState.Checked) { setCheckboxUnchecked(checkbox); - torrentFilesTable.rows.forEach((row) => { + for (const row of torrentFilesTable.rows) { const rowId = row.rowId; const node = torrentFilesTable.getNode(rowId); const fileId = node.fileId; @@ -237,11 +235,11 @@ window.qBittorrent.TorrentContent ??= (() => { rowIds.push(rowId); fileIds.push(fileId); } - }); + } } else { setCheckboxChecked(checkbox); - torrentFilesTable.rows.forEach((row) => { + for (const row of torrentFilesTable.rows) { const rowId = row.rowId; const node = torrentFilesTable.getNode(rowId); const fileId = node.fileId; @@ -250,7 +248,7 @@ window.qBittorrent.TorrentContent ??= (() => { rowIds.push(rowId); fileIds.push(fileId); } - }); + } } if (rowIds.length > 0) { @@ -332,14 +330,14 @@ window.qBittorrent.TorrentContent ??= (() => { const rootNode = new window.qBittorrent.FileTree.FolderNode(); - rows.forEach((row) => { + for (const row of rows) { const pathItems = row.fileName.split(window.qBittorrent.Filesystem.PathSeparator); pathItems.pop(); // remove last item (i.e. file name) let parent = rootNode; - pathItems.forEach((folderName) => { + for (const folderName of pathItems) { if (folderName === ".unwanted") - return; + continue; let folderNode = null; if (parent.children !== null) { @@ -366,7 +364,7 @@ window.qBittorrent.TorrentContent ??= (() => { } parent = folderNode; - }); + } const isChecked = row.checked ? TriState.Checked : TriState.Unchecked; const childNode = new window.qBittorrent.FileTree.FileNode(); @@ -383,7 +381,7 @@ window.qBittorrent.TorrentContent ??= (() => { parent.addChild(childNode); ++rowId; - }); + } torrentFilesTable.populateTable(rootNode); torrentFilesTable.updateTable(); @@ -399,21 +397,19 @@ window.qBittorrent.TorrentContent ??= (() => { const rowIds = []; const fileIds = []; - selectedRows.forEach((rowId) => { + for (const rowId of selectedRows) { rowIds.push(rowId); fileIds.push(Number(torrentFilesTable.getRowFileId(rowId))); - }); + } const uniqueRowIds = new Set(); const uniqueFileIds = new Set(); for (let i = 0; i < rowIds.length; ++i) { const rows = getAllChildren(rowIds[i], fileIds[i]); - rows.rowIds.forEach((rowId) => { + for (const rowId of rows.rowIds) uniqueRowIds.add(rowId); - }); - rows.fileIds.forEach((fileId) => { + for (const fileId of rows.fileIds) uniqueFileIds.add(fileId); - }); } setFilePriority([...uniqueRowIds.keys()], [...uniqueFileIds.keys()], priority); diff --git a/src/webui/www/private/views/log.html b/src/webui/www/private/views/log.html index a1fc55472..052e50390 100644 --- a/src/webui/www/private/views/log.html +++ b/src/webui/www/private/views/log.html @@ -210,9 +210,8 @@ menu: "logTableMenu", actions: { Clear: () => { - tableInfo[currentSelectedTab].instance.selectedRowsIds().forEach((rowId) => { + for (const rowId of tableInfo[currentSelectedTab].instance.selectedRowsIds()) tableInfo[currentSelectedTab].instance.removeRow(rowId); - }); updateLabelCount(); } diff --git a/src/webui/www/private/views/preferences.html b/src/webui/www/private/views/preferences.html index 2ccbdec83..581de9651 100644 --- a/src/webui/www/private/views/preferences.html +++ b/src/webui/www/private/views/preferences.html @@ -2144,7 +2144,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD // Advanced Tab 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", { 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 }); 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").value = default_iface; }); }; 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); 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 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]", "::")); - addresses.forEach((item, index) => { + for (const item of addresses) document.getElementById("optionalIPAddressToBind").options.add(new Option(item, item)); - }); document.getElementById("optionalIPAddressToBind").value = default_addr; }); }; diff --git a/src/webui/www/private/views/rss.html b/src/webui/www/private/views/rss.html index 57a92d3ed..62b73289f 100644 --- a/src/webui/www/private/views/rss.html +++ b/src/webui/www/private/views/rss.html @@ -233,7 +233,8 @@ feedsToUpdate.add(row); } } - feedsToUpdate.forEach((feed) => refreshFeed(feed.full_data.dataUid)); + for (const feed of feedsToUpdate) + refreshFeed(feed.full_data.dataUid); }, markRead: markSelectedAsRead, rename: (el) => { @@ -424,7 +425,8 @@ }; const clearDetails = () => { - [...document.getElementById("rssDetailsView").children].forEach((el) => { el.remove(); }); + for (const el of [...document.getElementById("rssDetailsView").children]) + el.remove(); }; const showDetails = (feedUid, articleID) => { diff --git a/src/webui/www/private/views/rssDownloader.html b/src/webui/www/private/views/rssDownloader.html index f6ec41d2d..02368ea4f 100644 --- a/src/webui/www/private/views/rssDownloader.html +++ b/src/webui/www/private/views/rssDownloader.html @@ -789,14 +789,14 @@ Supports the formats: S01E01, 1x1, 2017.12.31 and 31.12.2017 (Date formats also rssDownloaderFeedSelectionTable.clear(); let rowID = -1; - feedList.forEach((feed) => { + for (const feed of feedList) { rssDownloaderFeedSelectionTable.updateRowData({ rowId: ++rowID, checked: rulesList[ruleName].affectedFeeds.contains(feed.url), name: feed.name, url: feed.url }); - }); + } rssDownloaderFeedSelectionTable.updateTable(false); updateMatchingArticles(ruleName); } diff --git a/src/webui/www/private/views/torrentcreator.html b/src/webui/www/private/views/torrentcreator.html index 8d24feec0..514c9e020 100644 --- a/src/webui/www/private/views/torrentcreator.html +++ b/src/webui/www/private/views/torrentcreator.html @@ -91,7 +91,7 @@ if (!confirm("QBT_TR(Are you sure you want to delete selected tasks?)QBT_TR[CONTEXT=TorrentCreator]")) return; - selectedTasks.forEach(task => { + for (const task of selectedTasks) { fetch("api/v2/torrentcreator/deleteTask", { method: "POST", body: new URLSearchParams({ @@ -100,7 +100,7 @@ }).then((response) => { load(); }); - }); + } }, exportTorrent: exportTorrents, },