itembox: restore unsaved input value after refresh (#5517)

If itemBox refresh happens when an input is focused and
has some unsaved changes, restore the value of the input
after the refresh.

Potential solution for:
https://forums.zotero.org/discussion/126273/bug-data-that-is-input-is-not-saved-and-needs-to-be-entered-again
This commit is contained in:
abaevbog 2025-08-26 22:43:02 -05:00 • committed by GitHub
parent 23567b0395
commit 31e2e95452
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 1 deletions

View file

@ -60,6 +60,7 @@
this._initialVisibleCreators = 5;
this._draggedCreator = false;
this._selectField = null;
this._selectFieldValue = null;
this._selectFieldSelection = null;
this._addCreatorRow = false;
this._switchedModeOfCreator = null;
@ -2522,7 +2523,7 @@
// Save the field ID
this._selectField = fieldID;
// Save selection inside inputs
// Save selection and value inside inputs
let targetInput = activeElement.closest("input, textarea");
if (targetInput) {
this._selectFieldSelection = [
@ -2530,12 +2531,15 @@
targetInput.selectionEnd,
targetInput.selectionDirection,
];
// Save the value in case it was changed but not saved
this._selectFieldValue = targetInput.value;
}
}
_clearSavedFieldFocus() {
this._selectField = null;
this._selectFieldSelection = null;
this._selectFieldValue = null;
}
_restoreFieldFocus() {
@ -2565,6 +2569,11 @@
if (this._selectFieldSelection) {
let input = refocusField.querySelector("input, textarea");
if (input) {
// Restore the potentially unsaved value
if (this._selectFieldValue) {
refocusField.value = this._selectFieldValue;
}
// Restore the selection
input.setSelectionRange(...this._selectFieldSelection);
}
}

View file

@ -648,6 +648,27 @@ describe("Item pane", function () {
await waitForNotifierEvent('modify', 'item');
assert.equal(itemOne.getDisplayTitle(), "Updated title");
});
it("should retain unsaved value between refreshes", async function () {
let itemOne = new Zotero.Item('book');
await ZoteroPane.selectItem(itemOne.id);
let itemDetails = ZoteroPane.itemPane._itemDetails;
let infoBox = itemDetails.getPane("info");
// Type something into the series field without saving it
let seriesField = infoBox.querySelector("#itembox-field-value-series");
seriesField.focus();
seriesField.value = "Series name";
// Trigger a refresh
infoBox._renderInternal();
await waitForFrame();
// Ensure the field is still focused AND has the yet-unsaved text
assert.equal(doc.activeElement.parentNode.id, "itembox-field-value-series");
assert.equal(doc.activeElement.value, "Series name");
});
});
describe("Libraries and collections pane", function () {