diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 54cd3ac811..e76f6b82a1 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -174,8 +174,8 @@ var ZoteroPane = new function () { function setUpKeyboardNavigation() { let collectionTreeToolbar = document.getElementById("zotero-toolbar-collection-tree"); let itemTreeToolbar = document.getElementById("zotero-toolbar-item-tree"); - // Plugins append their toolbar buttons after Zotero's built-in controls. - // Read the current buttons for each key event so installation needs no registration. + // Plugins can opt into keyboard focus with tabindex=0 on an appended + // toolbarbutton. Read the current buttons for each key event. let pluginButtons = () => [...document.querySelectorAll( '#zotero-items-toolbar > toolbarbutton[tabindex="0"]' )].filter(button => !button.disabled && !button.hidden @@ -408,7 +408,7 @@ var ZoteroPane = new function () { ShiftTab: () => document.getElementById('zotero-tb-collections-search').click() }, 'zotero-tb-note-add': { - ArrowNext: () => pluginButtons()[0] || null, + ArrowNext: () => null, ArrowPrevious: () => document.getElementById("zotero-tb-attachment-add"), Tab: () => document.getElementById("zotero-tb-search").focus(), ShiftTab: () => document.getElementById('zotero-tb-collections-search').click() @@ -438,8 +438,7 @@ var ZoteroPane = new function () { if (pluginButtons().includes(event.target)) { actionsMap[event.target.id] = { ArrowNext: () => adjacentPluginButton(event.target, 1) || null, - ArrowPrevious: () => adjacentPluginButton(event.target, -1) - || document.getElementById('zotero-tb-note-add'), + ArrowPrevious: () => adjacentPluginButton(event.target, -1) || null, Tab: () => adjacentPluginButton(event.target, 1) || itemTree.querySelector(".virtualized-table"), ShiftTab: () => adjacentPluginButton(event.target, -1) diff --git a/test/tests/zoteroPaneTest.js b/test/tests/zoteroPaneTest.js index 413d310ff6..87e63e8574 100644 --- a/test/tests/zoteroPaneTest.js +++ b/test/tests/zoteroPaneTest.js @@ -1930,10 +1930,11 @@ describe("ZoteroPane", function () { doc.activeElement.dispatchEvent(shiftTab); assert.equal(doc.activeElement, buttons[0]); doc.activeElement.dispatchEvent(shiftTab); - assert.include( - ['zotero-tb-toggle-item-pane-stacked', 'zotero-tb-search-advanced-button'], - doc.activeElement.id - ); + let toggleHidden = paneToggle.disabled || paneToggle.hidden + || paneToggle.parentNode.hidden + || win.getComputedStyle(paneToggle).display === 'none'; + assert.equal(doc.activeElement.id, toggleHidden + ? 'zotero-tb-search-advanced-button' : paneToggle.id); doc.getElementById('zotero-tb-lookup').focus(); doc.activeElement.dispatchEvent(tab); assert.equal(doc.activeElement.id, 'zotero-tb-search-textbox'); @@ -1943,6 +1944,9 @@ describe("ZoteroPane", function () { doc.getElementById('zotero-tb-note-add').focus(); doc.activeElement.dispatchEvent(rightArrow); + assert.equal(doc.activeElement.id, 'zotero-tb-note-add'); + buttons[0].focus(); + doc.activeElement.dispatchEvent(leftArrow); assert.equal(doc.activeElement, buttons[0]); doc.activeElement.dispatchEvent(rightArrow); assert.equal(doc.activeElement, buttons[1]); @@ -1952,6 +1956,14 @@ describe("ZoteroPane", function () { buttons[0].hidden = true; paneToggle.dispatchEvent(tab); assert.equal(doc.activeElement, buttons[1]); + buttons[0].hidden = false; + buttons[0].disabled = true; + paneToggle.dispatchEvent(tab); + assert.equal(doc.activeElement, buttons[1]); + buttons[0].disabled = false; + buttons[0].style.display = 'none'; + paneToggle.dispatchEvent(tab); + assert.equal(doc.activeElement, buttons[1]); } finally { buttons.forEach(button => button.remove());