From 938c414e0c7a574b14dfd0579b04ec884fd02eb4 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Tue, 28 Jul 2026 11:35:20 -0400 Subject: [PATCH] Citation dialog: Fix post-add scroll crash that left focus in the items list _scrollItemTreeToRow() parsed the row index from the wrong rowID segment, so it threw on every call, and adding items from the items list never returned focus to the input as intended. --- .../zotero/integration/citationDialog.js | 3 ++- test/tests/citationDialogTest.js | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/chrome/content/zotero/integration/citationDialog.js b/chrome/content/zotero/integration/citationDialog.js index 26abfa1c2a..8faeed38c5 100644 --- a/chrome/content/zotero/integration/citationDialog.js +++ b/chrome/content/zotero/integration/citationDialog.js @@ -1027,10 +1027,11 @@ class LibraryLayout extends Layout { // scroll it back up so that the mouse remains over the same row as before click // do not do it on click of the first row, since then the mouse will be on a header _scrollItemTreeToRow(rowID, rowTopBeforeRefresh) { - let rowIndex = rowID.split("-")[4]; + let rowIndex = parseInt(rowID.split("-").at(-1)); if (rowIndex === 0) return; this.itemsView.ensureRowIsVisible(rowIndex); let rowAfterRefresh = doc.querySelector(`#zotero-items-tree #${rowID}`); + if (!rowAfterRefresh) return; let rowTopAfterRefresh = rowAfterRefresh.getBoundingClientRect().top; let delta = rowTopAfterRefresh - rowTopBeforeRefresh; if (delta > 0.1) { diff --git a/test/tests/citationDialogTest.js b/test/tests/citationDialogTest.js index abaa9b9875..68294253b9 100644 --- a/test/tests/citationDialogTest.js +++ b/test/tests/citationDialogTest.js @@ -485,6 +485,29 @@ describe("Citation Dialog", function () { assert.isTrue(rowNode.classList.contains("highlighted")); }); + it("should focus the input after adding an item with Enter in the items list", async function () { + let collection = await createDataObject('collection'); + let item = await createDataObject('item', { collections: [collection.id] }); + + await IOManager.toggleDialogMode("library"); + let cv = dialog.libraryLayout.collectionsView; + let itemsView = dialog.libraryLayout.itemsView; + await cv.selectByID("C" + collection.id); + await itemsView.waitForLoad(); + + await itemsView.selectItem(item.id); + IOManager.focusItemTree(); + let treeElem = dialog.document.querySelector("#zotero-items-tree [tabindex]"); + treeElem.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter", bubbles: true })); + // the post-add handling returns focus to the input + while (!dialog.document.activeElement.closest("bubble-input")) { + await Zotero.Promise.delay(10); + } + + await cv.selectByID("L" + Zotero.Libraries.userLibraryID); + await itemsView.waitForLoad(); + }); + it("should show the union of items from multiple selected collections", async function () { let collectionOne = await createDataObject('collection'); let collectionTwo = await createDataObject('collection');