From 72e033db797f7881a55097655b2260052ef2c32f Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 20 Nov 2024 22:33:41 +0800 Subject: [PATCH 1/9] WebUI: remove child elements directly --- src/webui/www/private/scripts/contextmenu.js | 3 +-- src/webui/www/private/scripts/dynamicTable.js | 10 +++------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/webui/www/private/scripts/contextmenu.js b/src/webui/www/private/scripts/contextmenu.js index 876a3792a..6408e8486 100644 --- a/src/webui/www/private/scripts/contextmenu.js +++ b/src/webui/www/private/scripts/contextmenu.js @@ -535,8 +535,7 @@ window.qBittorrent.ContextMenu ??= (() => { updateTagsSubMenu(tagList) { const contextTagList = $("contextTagList"); - while (contextTagList.firstChild !== null) - contextTagList.removeChild(contextTagList.firstChild); + contextTagList.replaceChildren(); 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 47f4899c1..7447137fb 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -288,8 +288,7 @@ window.qBittorrent.DynamicTable ??= (() => { LocalPreferences.set("columns_order_" + this.dynamicTableDivId, val.join(",")); this.loadColumnsOrder(); this.updateTableHeaders(); - while (this.tableBody.firstChild) - this.tableBody.removeChild(this.tableBody.firstChild); + this.tableBody.replaceChildren(); this.updateTable(true); } if (this.currentHeaderAction === "drag") { @@ -465,11 +464,8 @@ window.qBittorrent.DynamicTable ??= (() => { this.showColumn(action, this.columns[action].visible === "0"); }.bind(this); - // recreate child nodes when reusing (enables the context menu to work correctly) - if (ul.hasChildNodes()) { - while (ul.firstChild) - ul.removeChild(ul.lastChild); - } + // recreate child elements when reusing (enables the context menu to work correctly) + ul.replaceChildren(); for (let i = 0; i < this.columns.length; ++i) { const text = this.columns[i].caption; From f34787e6ba8cc7e44f53a4754050d15fa895c895 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 20 Nov 2024 22:38:32 +0800 Subject: [PATCH 2/9] WebUI: use correct property for selecting child elements `firstChild` will select the first `Node` which is often not intended (it should be `Element` instead). --- src/webui/www/private/scripts/client.js | 38 +++++++++---------- src/webui/www/private/scripts/contextmenu.js | 4 +- src/webui/www/private/scripts/dynamicTable.js | 6 +-- .../www/private/scripts/prop-trackers.js | 2 +- .../www/private/scripts/prop-webseeds.js | 2 +- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index 6f0f973fc..bf6a9cea7 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -339,28 +339,28 @@ window.addEventListener("DOMContentLoaded", () => { // Show Top Toolbar is enabled by default let showTopToolbar = LocalPreferences.get("show_top_toolbar", "true") === "true"; if (!showTopToolbar) { - $("showTopToolbarLink").firstChild.style.opacity = "0"; + $("showTopToolbarLink").firstElementChild.style.opacity = "0"; $("mochaToolbar").addClass("invisible"); } // Show Status Bar is enabled by default let showStatusBar = LocalPreferences.get("show_status_bar", "true") === "true"; if (!showStatusBar) { - $("showStatusBarLink").firstChild.style.opacity = "0"; + $("showStatusBarLink").firstElementChild.style.opacity = "0"; $("desktopFooterWrapper").addClass("invisible"); } // Show Filters Sidebar is enabled by default let showFiltersSidebar = LocalPreferences.get("show_filters_sidebar", "true") === "true"; if (!showFiltersSidebar) { - $("showFiltersSidebarLink").firstChild.style.opacity = "0"; + $("showFiltersSidebarLink").firstElementChild.style.opacity = "0"; $("filtersColumn").addClass("invisible"); $("filtersColumn_handle").addClass("invisible"); } let speedInTitle = LocalPreferences.get("speed_in_browser_title_bar") === "true"; if (!speedInTitle) - $("speedInBrowserTitleBarLink").firstChild.style.opacity = "0"; + $("speedInBrowserTitleBarLink").firstElementChild.style.opacity = "0"; // After showing/hiding the toolbar + status bar window.qBittorrent.Client.showSearchEngine(LocalPreferences.get("show_search_engine") !== "false"); @@ -465,7 +465,7 @@ window.addEventListener("DOMContentLoaded", () => { if (filterEl.classList.toggle("invisible", hideFilter)) return; } - filterEl.firstElementChild.lastChild.nodeValue = filterTitle.replace("%1", filterTorrentCount); + filterEl.firstElementChild.lastChild.textContent = filterTitle.replace("%1", filterTorrentCount); }; const updateFiltersList = () => { @@ -1122,11 +1122,11 @@ window.addEventListener("DOMContentLoaded", () => { showTopToolbar = !showTopToolbar; LocalPreferences.set("show_top_toolbar", showTopToolbar.toString()); if (showTopToolbar) { - $("showTopToolbarLink").firstChild.style.opacity = "1"; + $("showTopToolbarLink").firstElementChild.style.opacity = "1"; $("mochaToolbar").removeClass("invisible"); } else { - $("showTopToolbarLink").firstChild.style.opacity = "0"; + $("showTopToolbarLink").firstElementChild.style.opacity = "0"; $("mochaToolbar").addClass("invisible"); } MochaUI.Desktop.setDesktopSize(); @@ -1136,11 +1136,11 @@ window.addEventListener("DOMContentLoaded", () => { showStatusBar = !showStatusBar; LocalPreferences.set("show_status_bar", showStatusBar.toString()); if (showStatusBar) { - $("showStatusBarLink").firstChild.style.opacity = "1"; + $("showStatusBarLink").firstElementChild.style.opacity = "1"; $("desktopFooterWrapper").removeClass("invisible"); } else { - $("showStatusBarLink").firstChild.style.opacity = "0"; + $("showStatusBarLink").firstElementChild.style.opacity = "0"; $("desktopFooterWrapper").addClass("invisible"); } MochaUI.Desktop.setDesktopSize(); @@ -1174,12 +1174,12 @@ window.addEventListener("DOMContentLoaded", () => { showFiltersSidebar = !showFiltersSidebar; LocalPreferences.set("show_filters_sidebar", showFiltersSidebar.toString()); if (showFiltersSidebar) { - $("showFiltersSidebarLink").firstChild.style.opacity = "1"; + $("showFiltersSidebarLink").firstElementChild.style.opacity = "1"; $("filtersColumn").removeClass("invisible"); $("filtersColumn_handle").removeClass("invisible"); } else { - $("showFiltersSidebarLink").firstChild.style.opacity = "0"; + $("showFiltersSidebarLink").firstElementChild.style.opacity = "0"; $("filtersColumn").addClass("invisible"); $("filtersColumn_handle").addClass("invisible"); } @@ -1190,9 +1190,9 @@ window.addEventListener("DOMContentLoaded", () => { speedInTitle = !speedInTitle; LocalPreferences.set("speed_in_browser_title_bar", speedInTitle.toString()); if (speedInTitle) - $("speedInBrowserTitleBarLink").firstChild.style.opacity = "1"; + $("speedInBrowserTitleBarLink").firstElementChild.style.opacity = "1"; else - $("speedInBrowserTitleBarLink").firstChild.style.opacity = "0"; + $("speedInBrowserTitleBarLink").firstElementChild.style.opacity = "0"; processServerState(); }); @@ -1216,42 +1216,42 @@ window.addEventListener("DOMContentLoaded", () => { const updateTabDisplay = () => { if (window.qBittorrent.Client.isShowRssReader()) { - $("showRssReaderLink").firstChild.style.opacity = "1"; + $("showRssReaderLink").firstElementChild.style.opacity = "1"; $("mainWindowTabs").removeClass("invisible"); $("rssTabLink").removeClass("invisible"); if (!MochaUI.Panels.instances.RssPanel) addRssPanel(); } else { - $("showRssReaderLink").firstChild.style.opacity = "0"; + $("showRssReaderLink").firstElementChild.style.opacity = "0"; $("rssTabLink").addClass("invisible"); if ($("rssTabLink").hasClass("selected")) $("transfersTabLink").click(); } if (window.qBittorrent.Client.isShowSearchEngine()) { - $("showSearchEngineLink").firstChild.style.opacity = "1"; + $("showSearchEngineLink").firstElementChild.style.opacity = "1"; $("mainWindowTabs").removeClass("invisible"); $("searchTabLink").removeClass("invisible"); if (!MochaUI.Panels.instances.SearchPanel) addSearchPanel(); } else { - $("showSearchEngineLink").firstChild.style.opacity = "0"; + $("showSearchEngineLink").firstElementChild.style.opacity = "0"; $("searchTabLink").addClass("invisible"); if ($("searchTabLink").hasClass("selected")) $("transfersTabLink").click(); } if (window.qBittorrent.Client.isShowLogViewer()) { - $("showLogViewerLink").firstChild.style.opacity = "1"; + $("showLogViewerLink").firstElementChild.style.opacity = "1"; $("mainWindowTabs").removeClass("invisible"); $("logTabLink").removeClass("invisible"); if (!MochaUI.Panels.instances.LogPanel) addLogPanel(); } else { - $("showLogViewerLink").firstChild.style.opacity = "0"; + $("showLogViewerLink").firstElementChild.style.opacity = "0"; $("logTabLink").addClass("invisible"); if ($("logTabLink").hasClass("selected")) $("transfersTabLink").click(); diff --git a/src/webui/www/private/scripts/contextmenu.js b/src/webui/www/private/scripts/contextmenu.js index 6408e8486..38dd70696 100644 --- a/src/webui/www/private/scripts/contextmenu.js +++ b/src/webui/www/private/scripts/contextmenu.js @@ -246,13 +246,13 @@ window.qBittorrent.ContextMenu ??= (() => { } setItemChecked(item, checked) { - this.menu.getElement("a[href$=" + item + "]").firstChild.style.opacity = + this.menu.getElement("a[href$=" + item + "]").firstElementChild.style.opacity = checked ? "1" : "0"; return this; } getItemChecked(item) { - return this.menu.getElement("a[href$=" + item + "]").firstChild.style.opacity !== "0"; + return this.menu.getElement("a[href$=" + item + "]").firstElementChild.style.opacity !== "0"; } // hide an item diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index 7447137fb..849dd2ef2 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -492,9 +492,9 @@ window.qBittorrent.DynamicTable ??= (() => { const autoResizeAllElement = createResizeElement("Resize All", "#autoResizeAllAction"); const autoResizeElement = createResizeElement("Resize", "#autoResizeAction"); - ul.firstChild.classList.add("separator"); - ul.insertBefore(autoResizeAllElement, ul.firstChild); - ul.insertBefore(autoResizeElement, ul.firstChild); + ul.firstElementChild.classList.add("separator"); + ul.insertBefore(autoResizeAllElement, ul.firstElementChild); + ul.insertBefore(autoResizeElement, ul.firstElementChild); ul.inject(document.body); this.headerContextMenu = new DynamicTableHeaderContextMenuClass({ diff --git a/src/webui/www/private/scripts/prop-trackers.js b/src/webui/www/private/scripts/prop-trackers.js index 06449dcef..44bba126c 100644 --- a/src/webui/www/private/scripts/prop-trackers.js +++ b/src/webui/www/private/scripts/prop-trackers.js @@ -132,7 +132,7 @@ window.qBittorrent.PropTrackers ??= (() => { }, EditTracker: (element, ref) => { // only allow editing of one row - element.firstChild.click(); + element.firstElementChild.click(); editTrackerFN(element); }, RemoveTracker: (element, ref) => { diff --git a/src/webui/www/private/scripts/prop-webseeds.js b/src/webui/www/private/scripts/prop-webseeds.js index 7cebc49c8..8f80e4f88 100644 --- a/src/webui/www/private/scripts/prop-webseeds.js +++ b/src/webui/www/private/scripts/prop-webseeds.js @@ -103,7 +103,7 @@ window.qBittorrent.PropWebseeds ??= (() => { }, EditWebSeed: (element, ref) => { // only allow editing of one row - element.firstChild.click(); + element.firstElementChild.click(); editWebSeedFN(element); }, RemoveWebSeed: (element, ref) => { From 5eec0c02136f27447d2cbe7a94b08d7b14d43a0a Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sat, 23 Nov 2024 03:40:12 +0800 Subject: [PATCH 3/9] WebUI: use idiomatic string methods --- src/webui/www/private/scripts/client.js | 2 +- src/webui/www/private/scripts/misc.js | 6 +++--- src/webui/www/private/scripts/prop-trackers.js | 2 +- src/webui/www/private/views/log.html | 8 ++++---- src/webui/www/private/views/preferences.html | 2 +- src/webui/www/private/views/rssDownloader.html | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index bf6a9cea7..70381f547 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -1492,7 +1492,7 @@ window.addEventListener("DOMContentLoaded", () => { const handleDownloadParam = () => { // Extract torrent URL from download param in WebUI URL hash const downloadHash = "#download="; - if (location.hash.indexOf(downloadHash) !== 0) + if (!location.hash.startsWith(downloadHash)) return; const url = decodeURIComponent(location.hash.substring(downloadHash.length)); diff --git a/src/webui/www/private/scripts/misc.js b/src/webui/www/private/scripts/misc.js index 94f0eebcf..6313adfe2 100644 --- a/src/webui/www/private/scripts/misc.js +++ b/src/webui/www/private/scripts/misc.js @@ -255,8 +255,8 @@ window.qBittorrent.Misc ??= (() => { const containsAllTerms = (text, terms) => { const textToSearch = text.toLowerCase(); return terms.every((term) => { - const isTermRequired = (term[0] === "+"); - const isTermExcluded = (term[0] === "-"); + const isTermRequired = term.startsWith("+"); + const isTermExcluded = term.startsWith("-"); if (isTermRequired || isTermExcluded) { // ignore lonely +/- if (term.length === 1) @@ -265,7 +265,7 @@ window.qBittorrent.Misc ??= (() => { term = term.substring(1); } - const textContainsTerm = (textToSearch.indexOf(term) !== -1); + const textContainsTerm = textToSearch.includes(term); return isTermExcluded ? !textContainsTerm : textContainsTerm; }); }; diff --git a/src/webui/www/private/scripts/prop-trackers.js b/src/webui/www/private/scripts/prop-trackers.js index 44bba126c..ab9cec75b 100644 --- a/src/webui/www/private/scripts/prop-trackers.js +++ b/src/webui/www/private/scripts/prop-trackers.js @@ -146,7 +146,7 @@ window.qBittorrent.PropTrackers ??= (() => { onShow: function() { const selectedTrackers = torrentTrackersTable.selectedRowsIds(); const containsStaticTracker = selectedTrackers.some((tracker) => { - return (tracker.indexOf("** [") === 0); + return tracker.startsWith("** ["); }); if (containsStaticTracker || (selectedTrackers.length === 0)) { diff --git a/src/webui/www/private/views/log.html b/src/webui/www/private/views/log.html index c88da6ac8..dc757dbe8 100644 --- a/src/webui/www/private/views/log.html +++ b/src/webui/www/private/views/log.html @@ -343,10 +343,10 @@ if (curTab === "main") { url = new URI("api/v2/log/main"); url.setData({ - normal: selectedLogLevels.indexOf("1") !== -1, - info: selectedLogLevels.indexOf("2") !== -1, - warning: selectedLogLevels.indexOf("4") !== -1, - critical: selectedLogLevels.indexOf("8") !== -1 + normal: selectedLogLevels.includes("1"), + info: selectedLogLevels.includes("2"), + warning: selectedLogLevels.includes("4"), + critical: selectedLogLevels.includes("8") }); } else { diff --git a/src/webui/www/private/views/preferences.html b/src/webui/www/private/views/preferences.html index b1fee4bf7..7c21a7675 100644 --- a/src/webui/www/private/views/preferences.html +++ b/src/webui/www/private/views/preferences.html @@ -2138,7 +2138,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD languages.push($("locale_select").options[i].value); if (!languages.includes(selected)) { - const lang = selected.slice(0, selected.indexOf("_")); + const lang = selected.split("_", 1)[0]; selected = languages.includes(lang) ? lang : "en"; } $("locale_select").value = selected; diff --git a/src/webui/www/private/views/rssDownloader.html b/src/webui/www/private/views/rssDownloader.html index 243915902..d644fe0dc 100644 --- a/src/webui/www/private/views/rssDownloader.html +++ b/src/webui/www/private/views/rssDownloader.html @@ -388,7 +388,7 @@ Supports the formats: S01E01, 1x1, 2017.12.31 and 31.12.2017 (Date formats also $("rssDownloaderFeeds").style.height = "calc(100% - " + centerRowNotTableHeight + "px)"; // firefox calculates the height of the table inside fieldset differently and thus doesn't need the offset - if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) { + if (navigator.userAgent.toLowerCase().includes("firefox")) { $("rssDownloaderFeedsTable").style.height = "100%"; } else { From 2109e13746f943f28e9d2d968972c63b7baa8318 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 25 Nov 2024 22:32:20 +0800 Subject: [PATCH 4/9] WebUI: use proper event for handling text changes --- src/webui/www/private/views/log.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webui/www/private/views/log.html b/src/webui/www/private/views/log.html index dc757dbe8..6590f0ef5 100644 --- a/src/webui/www/private/views/log.html +++ b/src/webui/www/private/views/log.html @@ -96,7 +96,7 @@ - + From 24d349ffbaceb55ef1b5873d7ae9e95633fd8b70 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 25 Nov 2024 23:12:34 +0800 Subject: [PATCH 5/9] WebUI: fix wrong event property --- src/webui/www/private/scripts/contextmenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webui/www/private/scripts/contextmenu.js b/src/webui/www/private/scripts/contextmenu.js index 38dd70696..00ea280a4 100644 --- a/src/webui/www/private/scripts/contextmenu.js +++ b/src/webui/www/private/scripts/contextmenu.js @@ -160,7 +160,7 @@ window.qBittorrent.ContextMenu ??= (() => { this.touchStartAt = null; this.touchStartEvent = null; - const isTargetUnchanged = (Math.abs(e.event.pageX - touchStartEvent.event.pageX) <= 10) && (Math.abs(e.event.pageY - touchStartEvent.event.pageY) <= 10); + const isTargetUnchanged = (Math.abs(e.changedTouches[0].pageX - touchStartEvent.changedTouches[0].pageX) <= 10) && (Math.abs(e.changedTouches[0].pageY - touchStartEvent.changedTouches[0].pageY) <= 10); if (((now - touchStartAt) >= this.options.touchTimer) && isTargetUnchanged) this.triggerMenu(touchStartEvent, elem); }, { passive: true }); From ef5506321a1f6c4b1eddf65d152ea4d5e7061b7a Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Tue, 26 Nov 2024 00:17:39 +0800 Subject: [PATCH 6/9] WebUI: fix invalid style `initial` isn't applicable to `borderLeft`/`borderRight`. --- src/webui/www/private/scripts/dynamicTable.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index 849dd2ef2..a1442407d 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -224,11 +224,15 @@ window.qBittorrent.DynamicTable ??= (() => { changeBorderSide = "left"; } - const borderStyle = "initial solid #e60"; - if (changeBorderSide === "left") + const borderStyle = "solid #e60"; + if (changeBorderSide === "left") { borderChangeElement.style.borderLeft = borderStyle; - else + borderChangeElement.style.borderLeftWidth = "initial"; + } + else { borderChangeElement.style.borderRight = borderStyle; + borderChangeElement.style.borderRightWidth = "initial"; + } resetElementBorderStyle(borderChangeElement, ((changeBorderSide === "right") ? "left" : "right")); From 83b0dd3026bf5b645ebc242dd505594b55d0cdc1 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Tue, 26 Nov 2024 02:14:07 +0800 Subject: [PATCH 7/9] WebUI: fix checkbox initialization Previously the checkbox had all options checked regardless of the stored setting. --- src/webui/www/private/views/log.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webui/www/private/views/log.html b/src/webui/www/private/views/log.html index 6590f0ef5..3fa373fd0 100644 --- a/src/webui/www/private/views/log.html +++ b/src/webui/www/private/views/log.html @@ -189,7 +189,7 @@ const init = () => { for (const option of $("logLevelSelect").options) - option.setAttribute("selected", selectedLogLevels.includes(option.value)); + option.toggleAttribute("selected", selectedLogLevels.includes(option.value)); selectBox = new vanillaSelectBox("#logLevelSelect", { maxHeight: 200, From b84a51c76de52bdd950a4f315d724d2ee144fc3a Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 27 Nov 2024 01:01:11 +0800 Subject: [PATCH 8/9] WebUI: revise Edit Category dialog button text The generic "OK" is suitable for more scenarios. --- src/webui/www/private/newcategory.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webui/www/private/newcategory.html b/src/webui/www/private/newcategory.html index 7d9cfd27d..aad167a22 100644 --- a/src/webui/www/private/newcategory.html +++ b/src/webui/www/private/newcategory.html @@ -159,7 +159,7 @@
- +
From f8aaea34768d4bfd34b2796df6db8d07edb70ece Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 27 Nov 2024 16:16:27 +0800 Subject: [PATCH 9/9] WebUI: locate element faster --- src/webui/www/private/views/cookies.html | 2 +- src/webui/www/private/views/log.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webui/www/private/views/cookies.html b/src/webui/www/private/views/cookies.html index 677e4534b..5767b39d1 100644 --- a/src/webui/www/private/views/cookies.html +++ b/src/webui/www/private/views/cookies.html @@ -178,7 +178,7 @@ addCookie(); }); - document.querySelector("#saveButton").addEventListener("click", (event) => { + document.getElementById("saveButton").addEventListener("click", (event) => { save(); }); }; diff --git a/src/webui/www/private/views/log.html b/src/webui/www/private/views/log.html index 3fa373fd0..eab8c2134 100644 --- a/src/webui/www/private/views/log.html +++ b/src/webui/www/private/views/log.html @@ -97,7 +97,7 @@ - +