context notes list focus handling followup (#4847)
- remember the last focused note-row in the contextPane and, if possible, refocus it on shift-tab from sidenav, on tab from the reader into notes pane, or on tab into the notes list from the collapsible-section. Otherwise, focus the search input. Per: https://github.com/zotero/zotero/pull/4837#issuecomment-2478108186 - when a note is opened in the context pane, let shift-tab from sidenav place focus on the links-box. That way, it is not skipped during tab navigation. - fix focus not entering note-editor on Tab from the "Go back" button and instead wrapping around to the current tab
This commit is contained in:
parent
8c5a863aaf
commit
a195750f31
5 changed files with 39 additions and 18 deletions
|
@ -51,6 +51,8 @@
|
|||
_numVisible = 0;
|
||||
|
||||
_hasParent = false;
|
||||
|
||||
_lastFocusedNote = null;
|
||||
|
||||
get notes() {
|
||||
return [...this._itemNotes, ...this._allNotes];
|
||||
|
@ -118,6 +120,7 @@
|
|||
this.addEventListener('click', this._handleClick);
|
||||
this.addEventListener('contextmenu', this._handleContextMenu);
|
||||
this.addEventListener('keydown', this._handleKeyDown);
|
||||
this.addEventListener("focusin", this._handleFocusIn);
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
@ -152,6 +155,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
refocusLastFocusedNote() {
|
||||
if (this._lastFocusedNote) {
|
||||
this._lastFocusedNote.focus();
|
||||
return document.activeElement == this._lastFocusedNote;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_makeRow(note) {
|
||||
let row = document.createXULElement('note-row');
|
||||
row.note = note;
|
||||
|
@ -184,9 +195,23 @@
|
|||
}
|
||||
};
|
||||
|
||||
// Remember which note row was last focused to be able to return focus to it
|
||||
_handleFocusIn = (event) => {
|
||||
if (event.target.tagName !== "note-row" && !event.target.classList.contains("more")) return;
|
||||
this._lastFocusedNote = event.target;
|
||||
};
|
||||
|
||||
// ArrowUp/Down navigation between notes
|
||||
// Tab from a note-row focuses sidenav, Shift-Tab from a note focuses the section header
|
||||
// Tab from twisty icon into the notes list will try to refocus the last focused note
|
||||
_handleKeyDown = (event) => {
|
||||
if (event.key == "Tab" && event.target.classList.contains("twisty")) {
|
||||
let section = event.target.closest("collapsible-section");
|
||||
if (this._lastFocusedNote && section.contains(this._lastFocusedNote)) {
|
||||
this.refocusLastFocusedNote();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
if (event.target.tagName !== "note-row" && !event.target.classList.contains("more")) return;
|
||||
if (event.key == "ArrowDown") {
|
||||
event.target.nextElementSibling?.focus();
|
||||
|
|
|
@ -333,9 +333,7 @@
|
|||
return true;
|
||||
}
|
||||
else if (this.mode == "notes") {
|
||||
// Tab into the notes pane
|
||||
Services.focus.moveFocus(window, this._getCurrentNotesContext(), Services.focus.MOVEFOCUS_FORWARD, 0);
|
||||
return true;
|
||||
return this._getCurrentNotesContext().focus();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -386,19 +386,17 @@
|
|||
handleKeyDown = (event) => {
|
||||
if (event.key == "Tab" && !event.shiftKey) {
|
||||
// Wrap focus around to the tab bar
|
||||
Services.focus.moveFocus(window, document.getElementById("zotero-title-bar"), Services.focus.MOVEFOCUS_FORWARD, 0);
|
||||
Zotero_Tabs.moveFocus("current");
|
||||
event.preventDefault();
|
||||
}
|
||||
if (event.key == "Tab" && event.shiftKey) {
|
||||
if (this._contextNotesPaneVisible) {
|
||||
// Tab into notes pane to focus search bar
|
||||
Services.focus.moveFocus(window, this._contextNotesPane, Services.focus.MOVEFOCUS_FORWARD, 0);
|
||||
}
|
||||
else {
|
||||
// Shift-Tab out of sidenav to itemPane
|
||||
Services.focus.moveFocus(window, this, Services.focus.MOVEFOCUS_BACKWARD, 0);
|
||||
}
|
||||
event.preventDefault();
|
||||
if (this._contextNotesPaneVisible && this._contextNotesPane.selectedPanel.mode == "notesList") {
|
||||
let focusHandled = this._contextNotesPane.selectedPanel.focus();
|
||||
if (focusHandled) return;
|
||||
}
|
||||
// Shift-Tab out of sidenav to itemPane
|
||||
Services.focus.moveFocus(window, this, Services.focus.MOVEFOCUS_BACKWARD, 0);
|
||||
}
|
||||
if (["ArrowUp", "ArrowDown"].includes(event.key)) {
|
||||
// Up/Down arrow navigation
|
||||
|
|
|
@ -152,7 +152,10 @@
|
|||
|
||||
focus() {
|
||||
if (this.mode == "notesList") {
|
||||
this.input.focus();
|
||||
let refocused = this.notesList.refocusLastFocusedNote();
|
||||
if (!refocused) {
|
||||
this.input.focus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -1138,14 +1138,11 @@ var ZoteroPane = new function()
|
|||
// Shift-tab from the header into the itemsView.
|
||||
if (Services.focus.activeWindow === window && this.lastKeyPress === "Tab"
|
||||
&& (itemPaneLostFocus || contextPaneLostFocus)) {
|
||||
// event.relatedTarget is null when moving focus in or out of <iframe> or <browser>
|
||||
// so make sure to not refocus tabs when focusing inside of note-editor or reader
|
||||
if (receivingFocus) {
|
||||
Zotero_Tabs.moveFocus("current");
|
||||
}
|
||||
// event.relatedTarget is null when the reader is opened and we need a small
|
||||
// delay otherwise the focus lands within the reader
|
||||
else {
|
||||
setTimeout(() => Zotero_Tabs.moveFocus("current"));
|
||||
}
|
||||
this.lastKeyPress = null;
|
||||
}
|
||||
// When focus shifts, unless we are inside of a panel, save
|
||||
|
|
Loading…
Add table
Reference in a new issue