RTL: Use direction-aware arrow key handling
This commit is contained in:
parent
ea2d4417e1
commit
043c6e1795
9 changed files with 55 additions and 49 deletions
|
@ -630,7 +630,7 @@ class VirtualizedTable extends React.Component {
|
|||
if (shiftSelect || moveFocused) return;
|
||||
|
||||
switch (e.key) {
|
||||
case "ArrowLeft":
|
||||
case Zotero.arrowPreviousKey:
|
||||
const parentIndex = this.props.getParentIndex(this.selection.focused);
|
||||
if (this.props.isContainer(this.selection.focused)
|
||||
&& !this.props.isContainerEmpty(this.selection.focused)
|
||||
|
@ -642,7 +642,7 @@ class VirtualizedTable extends React.Component {
|
|||
}
|
||||
break;
|
||||
|
||||
case "ArrowRight":
|
||||
case Zotero.arrowNextKey:
|
||||
if (this.props.isContainer(this.selection.focused)
|
||||
&& !this.props.isContainerEmpty(this.selection.focused)) {
|
||||
if (!this.props.isContainerOpen(this.selection.focused)) {
|
||||
|
|
|
@ -519,8 +519,8 @@
|
|||
}
|
||||
else if (this.isPaginatedType && ["ArrowLeft", "ArrowRight"].includes(e.key)) {
|
||||
let gotoType = {
|
||||
ArrowLeft: "prev",
|
||||
ArrowRight: "next"
|
||||
[Zotero.arrowPreviousKey]: "prev",
|
||||
[Zotero.arrowNextKey]: "next"
|
||||
};
|
||||
this.goto(gotoType[e.key]);
|
||||
stopEvent = true;
|
||||
|
|
|
@ -353,10 +353,10 @@
|
|||
}
|
||||
}
|
||||
// Space/Enter toggle section open/closed.
|
||||
// ArrowLeft/ArrowRight on actual header will close/open
|
||||
// ArrowLeft/ArrowRight on actual header will close/open (depending on locale direction)
|
||||
if (["ArrowLeft", "ArrowRight", " ", "Enter"].includes(event.key)) {
|
||||
stopEvent();
|
||||
this.open = ([" ", "Enter"].includes(event.key)) ? !this.open : (event.key == "ArrowRight");
|
||||
this.open = ([" ", "Enter"].includes(event.key)) ? !this.open : (event.key == Zotero.arrowNextKey);
|
||||
event.target.focus();
|
||||
}
|
||||
if (["ArrowUp", "ArrowDown"].includes(event.key)) {
|
||||
|
|
|
@ -195,10 +195,10 @@
|
|||
});
|
||||
tile.addEventListener('keydown', (event) => {
|
||||
switch (event.key) {
|
||||
case 'ArrowLeft':
|
||||
case Zotero.arrowPreviousKey:
|
||||
(tile.previousElementSibling || tile.parentElement.lastElementChild).focus();
|
||||
break;
|
||||
case 'ArrowRight':
|
||||
case Zotero.arrowNextKey:
|
||||
(tile.nextElementSibling || tile.parentElement.firstElementChild).focus();
|
||||
break;
|
||||
case 'ArrowUp': {
|
||||
|
|
|
@ -54,11 +54,11 @@
|
|||
|
||||
// Select pane with left/right arrow key
|
||||
this.addEventListener('keypress', (event) => {
|
||||
if (event.key == "ArrowRight" && !this._rightPane.hasAttribute("selected")) {
|
||||
if (event.key == Zotero.arrowNextKey && !this._rightPane.hasAttribute("selected")) {
|
||||
this.choosePane(this._rightPane);
|
||||
this.rightPane.groupbox.focus();
|
||||
}
|
||||
else if (event.key == "ArrowLeft" && !this._leftPane.hasAttribute("selected")) {
|
||||
else if (event.key == Zotero.arrowPreviousKey && !this._leftPane.hasAttribute("selected")) {
|
||||
this.choosePane(this._leftPane);
|
||||
this._leftPane.groupbox.focus();
|
||||
}
|
||||
|
|
|
@ -133,11 +133,11 @@ var Zotero_QuickFormat = new function () {
|
|||
}
|
||||
}
|
||||
// Right/Left arrow will hide ref panel and move focus to the previour/next element
|
||||
else if ("ArrowLeft" == event.key) {
|
||||
else if (event.key == Zotero.arrowPreviousKey) {
|
||||
_lastFocusedInput.focus();
|
||||
moveFocusBack(_lastFocusedInput);
|
||||
}
|
||||
else if ("ArrowRight" == event.key) {
|
||||
else if (event.key == Zotero.arrowNextKey) {
|
||||
_lastFocusedInput.focus();
|
||||
moveFocusForward(_lastFocusedInput);
|
||||
}
|
||||
|
@ -1879,13 +1879,13 @@ var Zotero_QuickFormat = new function () {
|
|||
Zotero_QuickFormat._bubbleizeSelected();
|
||||
}
|
||||
else if (["ArrowLeft", "ArrowRight"].includes(event.key) && !event.shiftKey) {
|
||||
// On arrow left from the beginning of the input, move to previous bubble
|
||||
if (event.key === "ArrowLeft" && this.selectionStart === 0) {
|
||||
// On arrow left (right in RTL) from the beginning of the input, move to previous bubble
|
||||
if (event.key === Zotero.arrowPreviousKey && this.selectionStart === 0) {
|
||||
moveFocusBack(this);
|
||||
event.preventDefault();
|
||||
}
|
||||
// On arrow right from the end of the input, move to next bubble
|
||||
else if (event.key === "ArrowRight" && this.selectionStart === this.value.length) {
|
||||
// On arrow right (left in RTL) from the end of the input, move to next bubble
|
||||
else if (event.key === Zotero.arrowNextKey && this.selectionStart === this.value.length) {
|
||||
moveFocusForward(this);
|
||||
event.preventDefault();
|
||||
}
|
||||
|
@ -1940,7 +1940,7 @@ var Zotero_QuickFormat = new function () {
|
|||
event.preventDefault();
|
||||
let newInput = _createInputField();
|
||||
|
||||
if (["ArrowLeft"].includes(event.key)) {
|
||||
if (event.key === Zotero.arrowPreviousKey) {
|
||||
if (isInput(this.previousElementSibling)) {
|
||||
moveFocusBack(this);
|
||||
}
|
||||
|
@ -1949,7 +1949,7 @@ var Zotero_QuickFormat = new function () {
|
|||
newInput.focus();
|
||||
}
|
||||
}
|
||||
else if (["ArrowRight"].includes(event.key)) {
|
||||
else if (event.key === Zotero.arrowNextKey) {
|
||||
if (isInput(this.nextElementSibling)) {
|
||||
moveFocusForward(this);
|
||||
}
|
||||
|
@ -1965,13 +1965,13 @@ var Zotero_QuickFormat = new function () {
|
|||
let findNextBubble = () => {
|
||||
let node = event.target;
|
||||
do {
|
||||
node = event.key == "ArrowLeft" ? node.previousElementSibling : node.nextElementSibling;
|
||||
node = event.key == Zotero.arrowPreviousKey ? node.previousElementSibling : node.nextElementSibling;
|
||||
} while (node && !(node.classList.contains("bubble") || node.classList.contains("zotero-bubble-input")));
|
||||
return node;
|
||||
};
|
||||
let nextBubble = findNextBubble();
|
||||
if (nextBubble) {
|
||||
if (event.key == "ArrowLeft") {
|
||||
if (event.key === Zotero.arrowPreviousKey) {
|
||||
nextBubble.before(this);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -910,7 +910,7 @@ var ItemTree = class ItemTree extends LibraryTree {
|
|||
// Handle arrow keys specially on multiple selection, since
|
||||
// otherwise the tree just applies it to the last-selected row
|
||||
if (this.selection.count > 1 && ["ArrowLeft", "ArrowRight"].includes(event.key)) {
|
||||
if (event.key == "ArrowRight") {
|
||||
if (event.key == Zotero.arrowNextKey) {
|
||||
this.expandSelectedRows();
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -599,8 +599,8 @@ var Zotero_Tabs = new function () {
|
|||
|
||||
/**
|
||||
* Moves focus to a tab in the specified direction.
|
||||
* @param {String} direction. "first", "last", "left", "right", or "current"
|
||||
* If document.activeElement is a tab, "left" or "right" direction moves focus from that tab.
|
||||
* @param {String} direction. "first", "last", "previous", "next", or "current"
|
||||
* If document.activeElement is a tab, "previous" or "next" direction moves focus from that tab.
|
||||
* Otherwise, focus is moved in the given direction from the currently selected tab.
|
||||
*/
|
||||
this.moveFocus = function (direction) {
|
||||
|
@ -627,10 +627,10 @@ var Zotero_Tabs = new function () {
|
|||
}
|
||||
|
||||
switch (direction) {
|
||||
case "left":
|
||||
case "previous":
|
||||
tabIndexToFocus = focusedTabIndex > 0 ? focusedTabIndex - 1 : null;
|
||||
break;
|
||||
case "right":
|
||||
case "next":
|
||||
tabIndexToFocus = focusedTabIndex < this._tabs.length - 1 ? focusedTabIndex + 1 : null;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -195,6 +195,12 @@ var ZoteroPane = new function()
|
|||
else if (verticalArrowIsTab && key == 'ArrowDown' && !onInput) {
|
||||
key = 'Tab';
|
||||
}
|
||||
if (key == Zotero.arrowPreviousKey) {
|
||||
key = 'ArrowPrevious';
|
||||
}
|
||||
else if (key == Zotero.arrowNextKey) {
|
||||
key = 'ArrowNext';
|
||||
}
|
||||
// Fetch the focusFunction by target id
|
||||
let focusFunction = actionsMap[event.target.id]?.[key];
|
||||
// If no function found by target id, try to search by class names
|
||||
|
@ -246,16 +252,16 @@ var ZoteroPane = new function()
|
|||
// Mapping of target ids and possible key presses to desired focus outcomes
|
||||
let actionsMap = {
|
||||
'zotero-tb-tabs-menu': {
|
||||
ArrowRight: () => null,
|
||||
ArrowLeft: () => null,
|
||||
ArrowNext: () => null,
|
||||
ArrowPrevious: () => null,
|
||||
Tab: () => document.getElementById('zotero-tb-sync-error'),
|
||||
ShiftTab: () => {
|
||||
Zotero_Tabs.moveFocus("current");
|
||||
},
|
||||
},
|
||||
'zotero-tb-sync': {
|
||||
ArrowRight: () => null,
|
||||
ArrowLeft: () => null,
|
||||
ArrowNext: () => null,
|
||||
ArrowPrevious: () => null,
|
||||
Tab: () => {
|
||||
if (Zotero_Tabs.selectedIndex > 0) {
|
||||
let reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
|
||||
|
@ -274,8 +280,8 @@ var ZoteroPane = new function()
|
|||
ShiftTab: () => document.getElementById('zotero-tb-sync-error')
|
||||
},
|
||||
'zotero-tb-sync-error': {
|
||||
ArrowRight: () => null,
|
||||
ArrowLeft: () => null,
|
||||
ArrowNext: () => null,
|
||||
ArrowPrevious: () => null,
|
||||
Tab: () => document.getElementById('zotero-tb-sync'),
|
||||
ShiftTab: () => document.getElementById('zotero-tb-tabs-menu'),
|
||||
Enter: () => document.getElementById("zotero-tb-sync-error")
|
||||
|
@ -287,17 +293,17 @@ var ZoteroPane = new function()
|
|||
// keyboard navigation for tabs. 'tab' is the class, not the id
|
||||
Tab: () => document.getElementById('zotero-tb-tabs-menu'),
|
||||
ShiftTab: Zotero_Tabs.focusWrapAround,
|
||||
ArrowRight: (e) => {
|
||||
ArrowNext: (e) => {
|
||||
if (cmdOrCtrlOnly(e)) {
|
||||
Zotero_Tabs.moveFocus("right");
|
||||
Zotero_Tabs.moveFocus("next");
|
||||
}
|
||||
else {
|
||||
Zotero_Tabs.selectNext({ keepTabFocused: true });
|
||||
}
|
||||
},
|
||||
ArrowLeft: (e) => {
|
||||
ArrowPrevious: (e) => {
|
||||
if (cmdOrCtrlOnly(e)) {
|
||||
Zotero_Tabs.moveFocus("left");
|
||||
Zotero_Tabs.moveFocus("previous");
|
||||
}
|
||||
else {
|
||||
Zotero_Tabs.selectPrev({ keepTabFocused: true });
|
||||
|
@ -345,8 +351,8 @@ var ZoteroPane = new function()
|
|||
collectionTreeToolbar.addEventListener("keydown", (event) => {
|
||||
let actionsMap = {
|
||||
'zotero-tb-collection-add': {
|
||||
ArrowRight: () => null,
|
||||
ArrowLeft: () => null,
|
||||
ArrowNext: () => null,
|
||||
ArrowPrevious: () => null,
|
||||
Tab: () => document.getElementById('zotero-tb-collections-search').click(),
|
||||
ShiftTab: () => document.getElementById('zotero-tb-sync')
|
||||
},
|
||||
|
@ -363,8 +369,8 @@ var ZoteroPane = new function()
|
|||
itemTreeToolbar.addEventListener("keydown", (event) => {
|
||||
let actionsMap = {
|
||||
'zotero-tb-add': {
|
||||
ArrowRight: () => document.getElementById("zotero-tb-lookup"),
|
||||
ArrowLeft: () => null,
|
||||
ArrowNext: () => document.getElementById("zotero-tb-lookup"),
|
||||
ArrowPrevious: () => null,
|
||||
Tab: () => document.getElementById("zotero-tb-search")._searchModePopup.flattenedTreeParentNode.focus(),
|
||||
ShiftTab: () => {
|
||||
if (collectionsPane.getAttribute("collapsed")) {
|
||||
|
@ -377,22 +383,22 @@ var ZoteroPane = new function()
|
|||
}
|
||||
},
|
||||
'zotero-tb-lookup': {
|
||||
ArrowRight: () => document.getElementById("zotero-tb-attachment-add"),
|
||||
ArrowLeft: () => document.getElementById("zotero-tb-add"),
|
||||
ArrowNext: () => document.getElementById("zotero-tb-attachment-add"),
|
||||
ArrowPrevious: () => document.getElementById("zotero-tb-add"),
|
||||
Tab: () => document.getElementById("zotero-tb-search")._searchModePopup.flattenedTreeParentNode.focus(),
|
||||
ShiftTab: () => document.getElementById('zotero-tb-collections-search').click(),
|
||||
Enter: () => Zotero_Lookup.showPanel(event.target),
|
||||
' ': () => Zotero_Lookup.showPanel(event.target)
|
||||
},
|
||||
'zotero-tb-attachment-add': {
|
||||
ArrowRight: () => document.getElementById("zotero-tb-note-add"),
|
||||
ArrowLeft: () => document.getElementById("zotero-tb-lookup"),
|
||||
ArrowNext: () => document.getElementById("zotero-tb-note-add"),
|
||||
ArrowPrevious: () => document.getElementById("zotero-tb-lookup"),
|
||||
Tab: () => document.getElementById("zotero-tb-search")._searchModePopup.flattenedTreeParentNode.focus(),
|
||||
ShiftTab: () => document.getElementById('zotero-tb-collections-search').click()
|
||||
},
|
||||
'zotero-tb-note-add': {
|
||||
ArrowRight: () => null,
|
||||
ArrowLeft: () => document.getElementById("zotero-tb-attachment-add"),
|
||||
ArrowNext: () => null,
|
||||
ArrowPrevious: () => document.getElementById("zotero-tb-attachment-add"),
|
||||
Tab: () => document.getElementById("zotero-tb-search")._searchModePopup.flattenedTreeParentNode.focus(),
|
||||
ShiftTab: () => document.getElementById('zotero-tb-collections-search').click()
|
||||
},
|
||||
|
@ -403,8 +409,8 @@ var ZoteroPane = new function()
|
|||
Tab: () => document.getElementById('item-tree-main-default')
|
||||
},
|
||||
'zotero-tb-search-dropmarker': {
|
||||
ArrowRight: () => null,
|
||||
ArrowLeft: () => null,
|
||||
ArrowNext: () => null,
|
||||
ArrowPrevious: () => null,
|
||||
Tab: () => document.getElementById("zotero-tb-search-textbox"),
|
||||
ShiftTab: () => document.getElementById('zotero-tb-add')
|
||||
}
|
||||
|
@ -951,13 +957,13 @@ var ZoteroPane = new function()
|
|||
}
|
||||
}
|
||||
else if (event.metaKey && event.altKey) {
|
||||
if (event.key == 'ArrowLeft') {
|
||||
if (event.key == Zotero.arrowPreviousKey) {
|
||||
Zotero_Tabs.selectPrev();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
else if (event.key == 'ArrowRight') {
|
||||
else if (event.key == Zotero.arrowNextKey) {
|
||||
Zotero_Tabs.selectNext();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
|
Loading…
Reference in a new issue