diff --git a/src/webui/www/eslint.config.mjs b/src/webui/www/eslint.config.mjs index 4aa12988b..5d78ea107 100644 --- a/src/webui/www/eslint.config.mjs +++ b/src/webui/www/eslint.config.mjs @@ -71,6 +71,7 @@ export default [ "Stylistic/semi": "error", "Stylistic/spaced-comment": ["error", "always", { exceptions: ["*"] }], "Unicorn/no-array-for-each": "error", + "Unicorn/no-for-loop": "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 6363755cf..015c9a7e3 100644 --- a/src/webui/www/private/rename_files.html +++ b/src/webui/www/private/rename_files.html @@ -167,8 +167,7 @@ span.textContent = ""; // Update renamed column for matched rows - for (let i = 0; i < matchedRows.length; ++i) { - const row = matchedRows[i]; + for (const row of matchedRows) { const element = document.getElementById(`filesTablefileRenamed${row.rowId}`); if (element === null) continue; diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index 002083d3c..4b3ac11a7 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -175,8 +175,7 @@ window.qBittorrent.Client ??= (() => { const uploadTorrentFiles = (files) => { const fileNames = []; const formData = new FormData(); - for (let i = 0; i < files.length; ++i) { - const file = files[i]; + for (const [i, file] of files.entries()) { fileNames.push(file.name); // send dummy file name as file name won't be used and may not be encoded properly formData.append("file", file, i); @@ -193,8 +192,7 @@ window.qBittorrent.Client ??= (() => { } const json = await response.json(); - for (let i = 0; i < json.length; ++i) { - const metadata = json[i]; + for (const [i, metadata] of json.entries()) { const title = metadata.name || fileNames[i]; const hash = metadata.infohash_v2 || metadata.infohash_v1; createAddTorrentWindow(title, hash, metadata); diff --git a/src/webui/www/private/scripts/contextmenu.js b/src/webui/www/private/scripts/contextmenu.js index 9eef499bf..339dc6466 100644 --- a/src/webui/www/private/scripts/contextmenu.js +++ b/src/webui/www/private/scripts/contextmenu.js @@ -106,8 +106,7 @@ window.qBittorrent.ContextMenu ??= (() => { // position the sub-menu const uls = this.menu.getElementsByTagName("ul"); - for (let i = 0; i < uls.length; ++i) { - const ul = uls[i]; + for (const ul of uls) { if (ul.classList.contains("scrollableMenu")) ul.style.maxHeight = `${scrollableMenuMaxHeight}px`; const rectParent = ul.parentNode.getBoundingClientRect(); @@ -536,9 +535,7 @@ window.qBittorrent.ContextMenu ??= (() => { const sortedTags = [...tags.keys()]; sortedTags.sort(window.qBittorrent.Misc.naturalSortCollator.compare); - for (let i = 0; i < sortedTags.length; ++i) { - const tagName = sortedTags[i]; - + for (const [i, tagName] of sortedTags.entries()) { const input = document.createElement("input"); input.type = "checkbox"; input.addEventListener("click", (event) => { diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index ec3eaf303..f3754381a 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -634,8 +634,7 @@ window.qBittorrent.DynamicTable ??= (() => { updateHeader(header) { const ths = this.getRowCells(header); - for (let i = 0; i < ths.length; ++i) { - const th = ths[i]; + for (const [i, th] of ths.entries()) { if (th.columnName !== this.columns[i].name) { th.title = this.columns[i].caption; th.textContent = this.columns[i].caption; @@ -865,14 +864,14 @@ window.qBittorrent.DynamicTable ??= (() => { const trs = [...this.getTrs()]; const trMap = new Map(trs.map(tr => [tr.rowId, tr])); - for (let rowPos = 0; rowPos < rows.length; ++rowPos) { - const rowId = rows[rowPos].rowId; + for (const row of rows) { + const rowId = row.rowId; const existingTr = trMap.get(rowId); if (existingTr !== undefined) { this.updateRow(existingTr, fullUpdate); } else { - const tr = this.createRowElement(rows[rowPos]); + const tr = this.createRowElement(row); // TODO look into using DocumentFragment or appending all trs at once for add'l performance gains // add to end of table - we'll move into the proper order later @@ -885,8 +884,7 @@ window.qBittorrent.DynamicTable ??= (() => { // reorder table rows let prevTr = null; - for (let rowPos = 0; rowPos < rows.length; ++rowPos) { - const { rowId } = rows[rowPos]; + for (const [rowPos, { rowId }] of rows.entries()) { const tr = trMap.get(rowId); trMap.delete(rowId); @@ -1061,8 +1059,7 @@ window.qBittorrent.DynamicTable ??= (() => { const selectedRowId = this.getSelectedRowId(); let selectedIndex = -1; - for (let i = 0; i < visibleRows.length; ++i) { - const row = visibleRows[i]; + for (const [i, row] of visibleRows.entries()) { if (row.getAttribute("data-row-id") === selectedRowId) { selectedIndex = i; break; @@ -1083,8 +1080,7 @@ window.qBittorrent.DynamicTable ??= (() => { const selectedRowId = this.getSelectedRowId(); let selectedIndex = -1; - for (let i = 0; i < visibleRows.length; ++i) { - const row = visibleRows[i]; + for (const [i, row] of visibleRows.entries()) { if (row.getAttribute("data-row-id") === selectedRowId) { selectedIndex = i; break; diff --git a/src/webui/www/private/scripts/mocha-init.js b/src/webui/www/private/scripts/mocha-init.js index ada3a87b3..e3d1300c3 100644 --- a/src/webui/www/private/scripts/mocha-init.js +++ b/src/webui/www/private/scripts/mocha-init.js @@ -383,8 +383,7 @@ const initializeWindows = () => { let torrentsHaveSameShareRatio = true; // check if all selected torrents have same share ratio - for (let i = 0; i < hashes.length; ++i) { - const hash = hashes[i]; + for (const hash of hashes) { const row = torrentsTable.getRow(hash).full_data; const origValues = `${row.ratio_limit}|${row.seeding_time_limit}|${row.inactive_seeding_time_limit}|${row.max_ratio}` + `|${row.max_seeding_time}|${row.max_inactive_seeding_time}|${row.share_limit_action}`; @@ -1160,10 +1159,8 @@ const initializeWindows = () => { const names = []; if (selectedRows.length > 0) { const rows = torrentsTable.getFilteredAndSortedRows(); - for (let i = 0; i < selectedRows.length; ++i) { - const hash = selectedRows[i]; + for (const hash of selectedRows) names.push(rows[hash].full_data.name); - } } return names.join("\n"); }; @@ -1198,10 +1195,8 @@ const initializeWindows = () => { const magnets = []; if (selectedRows.length > 0) { const rows = torrentsTable.getFilteredAndSortedRows(); - for (let i = 0; i < selectedRows.length; ++i) { - const hash = selectedRows[i]; + for (const hash of selectedRows) magnets.push(rows[hash].full_data.magnet_uri); - } } return magnets.join("\n"); }; @@ -1215,8 +1210,7 @@ const initializeWindows = () => { const comments = []; if (selectedRows.length > 0) { const rows = torrentsTable.getFilteredAndSortedRows(); - for (let i = 0; i < selectedRows.length; ++i) { - const hash = selectedRows[i]; + for (const hash of selectedRows) { const comment = rows[hash].full_data.comment; if (comment && (comment !== "")) comments.push(comment); diff --git a/src/webui/www/private/scripts/rename-files.js b/src/webui/www/private/scripts/rename-files.js index 2f5402dce..3d29de70d 100644 --- a/src/webui/www/private/scripts/rename-files.js +++ b/src/webui/www/private/scripts/rename-files.js @@ -187,8 +187,7 @@ window.qBittorrent.MultiRename ??= (() => { const match = matches[i]; let replacement = this.#inner_replacement; // Replace numerical groups - for (let g = 0; g < match.length; ++g) { - const group = match[g]; + for (const [g, group] of match.entries()) { if (!group) continue; replacement = replaceGroup(replacement, `$${g}`, group, "\\", false); diff --git a/src/webui/www/private/scripts/search.js b/src/webui/www/private/scripts/search.js index cafc02229..7bfb8cbb3 100644 --- a/src/webui/www/private/scripts/search.js +++ b/src/webui/www/private/scripts/search.js @@ -772,9 +772,9 @@ window.qBittorrent.Search ??= (() => { }; const getPlugin = (name) => { - for (let i = 0; i < searchPlugins.length; ++i) { - if (searchPlugins[i].name === name) - return searchPlugins[i]; + for (const searchPlugin of searchPlugins) { + if (searchPlugin.name === name) + return searchPlugin; } return null; @@ -877,8 +877,7 @@ window.qBittorrent.Search ??= (() => { if (responseJSON.results) { const results = responseJSON.results; - for (let i = 0; i < results.length; ++i) { - const result = results[i]; + for (const result of results) { const row = { rowId: state.rowId, descrLink: result.descrLink, diff --git a/src/webui/www/private/scripts/torrent-content.js b/src/webui/www/private/scripts/torrent-content.js index dd1b61e22..7aa5ea577 100644 --- a/src/webui/www/private/scripts/torrent-content.js +++ b/src/webui/www/private/scripts/torrent-content.js @@ -200,8 +200,7 @@ window.qBittorrent.TorrentContent ??= (() => { const selectComboboxPriority = (combobox, priority) => { const options = combobox.options; - for (let i = 0; i < options.length; ++i) { - const option = options[i]; + for (const option of options) { if (normalizePriority(option.value) === priority) option.selected = true; else @@ -404,8 +403,8 @@ window.qBittorrent.TorrentContent ??= (() => { const uniqueRowIds = new Set(); const uniqueFileIds = new Set(); - for (let i = 0; i < rowIds.length; ++i) { - const rows = getAllChildren(rowIds[i], fileIds[i]); + for (const [i, rowId] of rowIds.entries()) { + const rows = getAllChildren(rowId, fileIds[i]); for (const rowId of rows.rowIds) uniqueRowIds.add(rowId); for (const fileId of rows.fileIds) diff --git a/src/webui/www/private/shareratio.html b/src/webui/www/private/shareratio.html index cd9f529e4..01a724d9e 100644 --- a/src/webui/www/private/shareratio.html +++ b/src/webui/www/private/shareratio.html @@ -127,8 +127,7 @@ const getSelectedRadioValue = (name) => { const radios = document.getElementsByName(name); - for (let i = 0; i < radios.length; ++i) { - const radio = radios[i]; + for (const radio of radios) { if (radio.checked) return radio.value; } @@ -137,8 +136,7 @@ const setSelectedRadioValue = (name, value) => { const radios = document.getElementsByName(name); - for (let i = 0; i < radios.length; ++i) { - const radio = radios[i]; + for (const radio of radios) { if (radio.value === value) radio.checked = true; } diff --git a/src/webui/www/private/views/log.html b/src/webui/www/private/views/log.html index d7d13a0ec..5fde56899 100644 --- a/src/webui/www/private/views/log.html +++ b/src/webui/www/private/views/log.html @@ -387,27 +387,27 @@ clearTimeout(logFilterTimer); logFilterTimer = -1; - for (let i = 0; i < responseJSON.length; ++i) { + for (const logEntry of responseJSON) { let row; if (curTab === "main") { row = { - rowId: responseJSON[i].id, - message: responseJSON[i].message, - timestamp: responseJSON[i].timestamp, - type: responseJSON[i].type, + rowId: logEntry.id, + message: logEntry.message, + timestamp: logEntry.timestamp, + type: logEntry.type, }; } else { row = { - rowId: responseJSON[i].id, - ip: responseJSON[i].ip, - timestamp: responseJSON[i].timestamp, - blocked: responseJSON[i].blocked, - reason: responseJSON[i].reason, + rowId: logEntry.id, + ip: logEntry.ip, + timestamp: logEntry.timestamp, + blocked: logEntry.blocked, + reason: logEntry.reason, }; } tableInfo[curTab].instance.updateRowData(row); - tableInfo[curTab].last_id = Math.max(Number(responseJSON[i].id), tableInfo[curTab].last_id); + tableInfo[curTab].last_id = Math.max(Number(logEntry.id), tableInfo[curTab].last_id); } tableInfo[curTab].instance.updateTable(); diff --git a/src/webui/www/private/views/rss.html b/src/webui/www/private/views/rss.html index 62b73289f..26e27f77d 100644 --- a/src/webui/www/private/views/rss.html +++ b/src/webui/www/private/views/rss.html @@ -558,8 +558,7 @@ // subtract 'unread' row if ((rssFeedRows.length - 1) === flattenedResp.length) { match = true; - for (let i = 0; i < flattenedResp.length; ++i) { - const newData = flattenedResp[i]; + for (const [i, newData] of flattenedResp.entries()) { const existingData = rssFeedRows[i + 1].full_data; if (newData.fullName !== existingData.dataPath) { @@ -578,14 +577,14 @@ // partial refresh // update status let statusDiffers = false; - for (let i = 0; i < flattenedResp.length; ++i) { + for (const [i, item] of flattenedResp.entries()) { const oldStatus = rssFeedRows[i + 1].full_data.status; let status = "default"; - if (flattenedResp[i].hasError) + if (item.hasError) status = "hasError"; - if (flattenedResp[i].isLoading) + if (item.isLoading) status = "isLoading"; - if (flattenedResp[i].isFolder) + if (item.isFolder) status = "isFolder"; if (oldStatus !== status) { diff --git a/src/webui/www/private/views/searchplugins.html b/src/webui/www/private/views/searchplugins.html index 708ee5cf7..41990aac4 100644 --- a/src/webui/www/private/views/searchplugins.html +++ b/src/webui/www/private/views/searchplugins.html @@ -178,16 +178,16 @@ const updateTable = () => { const oldPlugins = [...searchPluginsTable.getRowIds()]; // remove old rows from the table - for (let i = 0; i < oldPlugins.length; ++i) { + for (const oldPlugin of oldPlugins) { let found = false; for (let j = 0; j < window.qBittorrent.Search.searchPlugins.length; ++j) { - if (window.qBittorrent.Search.searchPlugins[j].name === oldPlugins[i]) { + if (window.qBittorrent.Search.searchPlugins[j].name === oldPlugin) { found = true; break; } } if (!found) - searchPluginsTable.removeRow(oldPlugins[i]); + searchPluginsTable.removeRow(oldPlugin); } for (let i = 0; i < window.qBittorrent.Search.searchPlugins.length; ++i) { diff --git a/src/webui/www/private/views/torrentcreator.html b/src/webui/www/private/views/torrentcreator.html index 514c9e020..c9346efab 100644 --- a/src/webui/www/private/views/torrentcreator.html +++ b/src/webui/www/private/views/torrentcreator.html @@ -242,23 +242,23 @@ table.clear(); if (responseJSON.length > 0) { - for (let i = 0; i < responseJSON.length; ++i) { - const status = responseJSON[i].status; + for (const entry of responseJSON) { + const status = entry.status; const row = { - rowId: responseJSON[i].taskID, - source_path: responseJSON[i].sourcePath, - progress: status === "Finished" ? 100 : responseJSON[i].progress, + rowId: entry.taskID, + source_path: entry.sourcePath, + progress: status === "Finished" ? 100 : entry.progress, status: status, - torrent_format: responseJSON[i].format, - piece_size: responseJSON[i].pieceSize, - private: responseJSON[i].private, - added_on: responseJSON[i].timeAdded, - start_on: responseJSON[i].timeStarted, - completion_on: responseJSON[i].timeFinished, - trackers: responseJSON[i].trackers, - comment: responseJSON[i].comment, - source: responseJSON[i].source, - error_message: responseJSON[i].errorMessage, + torrent_format: entry.format, + piece_size: entry.pieceSize, + private: entry.private, + added_on: entry.timeAdded, + start_on: entry.timeStarted, + completion_on: entry.timeFinished, + trackers: entry.trackers, + comment: entry.comment, + source: entry.source, + error_message: entry.errorMessage, }; table.updateRowData(row);