From 8b94642ab17a195a684b035bdc4b140d951c91a7 Mon Sep 17 00:00:00 2001 From: Thomas Piccirello Date: Fri, 9 Jul 2021 21:44:02 -0700 Subject: [PATCH 1/3] Always set Web UI row id as a string This helps ensure consistent behavior when performing rowId comparisons against strings. --- src/webui/www/private/scripts/dynamicTable.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index 37519058e..12be836b4 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -617,7 +617,8 @@ window.qBittorrent.DynamicTable = (function() { onSelectedRowChanged: function() {}, updateRowData: function(data) { - const rowId = data['rowId']; + // ensure rowId is a string + const rowId = `${data['rowId']}`; let row; if (!this.rows.has(rowId)) { From e76bac41314b0f5fe90693f8b6067ac2563307ff Mon Sep 17 00:00:00 2001 From: Thomas Piccirello Date: Fri, 9 Jul 2021 22:36:51 -0700 Subject: [PATCH 2/3] Support navigating Web UI tables with arrow keys This allows navigating rows via up/down arrow keys. --- src/webui/www/private/scripts/dynamicTable.js | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index 12be836b4..46d8a7b1f 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -697,8 +697,13 @@ window.qBittorrent.DynamicTable = (function() { this.updateRow(trs[rowPos], fullUpdate); else { // else create a new row in the table const tr = new Element('tr'); + // set tabindex so element receives keydown events + // more info: https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event + tr.setProperty("tabindex", "-1"); - tr['rowId'] = rows[rowPos]['rowId']; + const rowId = rows[rowPos]['rowId']; + tr.setProperty("data-row-id", rowId); + tr['rowId'] = rowId; tr._this = this; tr.addEvent('contextmenu', function(e) { @@ -735,6 +740,16 @@ window.qBittorrent.DynamicTable = (function() { } return false; }); + tr.addEvent('keydown', function(event) { + switch (event.key) { + case "up": + this._this.selectPreviousRow(); + return false; + case "down": + this._this.selectNextRow(); + return false; + } + }); this.setupTr(tr); @@ -813,6 +828,50 @@ window.qBittorrent.DynamicTable = (function() { getRowIds: function() { return this.rows.getKeys(); }, + + selectNextRow: function() { + const visibleRows = $(this.dynamicTableDivId).getElements("tbody tr").filter(e => e.getStyle("display") !== "none"); + const selectedRowId = this.getSelectedRowId(); + + let selectedIndex = -1; + for (let i = 0; i < visibleRows.length; ++i) { + const row = visibleRows[i]; + if (row.getProperty("data-row-id") === selectedRowId) { + selectedIndex = i; + break; + } + } + + const isLastRowSelected = (selectedIndex >= (visibleRows.length - 1)); + if (!isLastRowSelected) { + this.deselectAll(); + + const newRow = visibleRows[selectedIndex + 1]; + this.selectRow(newRow.getProperty("data-row-id")); + } + }, + + selectPreviousRow: function() { + const visibleRows = $(this.dynamicTableDivId).getElements("tbody tr").filter(e => e.getStyle("display") !== "none"); + const selectedRowId = this.getSelectedRowId(); + + let selectedIndex = -1; + for (let i = 0; i < visibleRows.length; ++i) { + const row = visibleRows[i]; + if (row.getProperty("data-row-id") === selectedRowId) { + selectedIndex = i; + break; + } + } + + const isFirstRowSelected = selectedIndex <= 0; + if (!isFirstRowSelected) { + this.deselectAll(); + + const newRow = visibleRows[selectedIndex - 1]; + this.selectRow(newRow.getProperty("data-row-id")); + } + }, }); const TorrentsTable = new Class({ From 32f29e72c6d9de55948b4d6db04442e24ca035bc Mon Sep 17 00:00:00 2001 From: Thomas Piccirello Date: Fri, 9 Jul 2021 22:38:56 -0700 Subject: [PATCH 3/3] Support expanding/collapsing Web UI folders with arrow keys --- src/webui/www/private/scripts/dynamicTable.js | 13 +++++++++++++ src/webui/www/private/scripts/prop-files.js | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index 46d8a7b1f..742bdaa1e 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -2066,6 +2066,19 @@ window.qBittorrent.DynamicTable = (function() { row.full_data.remaining = 0; else row.full_data.remaining = (row.full_data.size * (1.0 - (row.full_data.progress / 100))); + }, + + setupTr: function(tr) { + tr.addEvent('keydown', function(event) { + switch (event.key) { + case "left": + qBittorrent.PropFiles.collapseFolder(this._this.getSelectedRowId()); + return false; + case "right": + qBittorrent.PropFiles.expandFolder(this._this.getSelectedRowId()); + return false; + } + }); } }); diff --git a/src/webui/www/private/scripts/prop-files.js b/src/webui/www/private/scripts/prop-files.js index 9b8d67ec9..d66092ad2 100644 --- a/src/webui/www/private/scripts/prop-files.js +++ b/src/webui/www/private/scripts/prop-files.js @@ -43,7 +43,9 @@ window.qBittorrent.PropFiles = (function() { createPriorityCombo: createPriorityCombo, updatePriorityCombo: updatePriorityCombo, updateData: updateData, - collapseIconClicked: collapseIconClicked + collapseIconClicked: collapseIconClicked, + expandFolder: expandFolder, + collapseFolder: collapseFolder }; }; @@ -495,6 +497,20 @@ window.qBittorrent.PropFiles = (function() { collapseNode(node); }; + const expandFolder = function(id) { + const node = torrentFilesTable.getNode(id); + if (node.isFolder) { + expandNode(node); + } + }; + + const collapseFolder = function(id) { + const node = torrentFilesTable.getNode(id); + if (node.isFolder) { + collapseNode(node); + } + }; + const filesPriorityMenuClicked = function(priority) { const selectedRows = torrentFilesTable.selectedRowsIds(); if (selectedRows.length === 0) return;