making toolbar accessible to the keyboard - initial conversion (#3188)
Port of d866a10a2b
Fixes #3001
This commit is contained in:
parent
aca86967bf
commit
13571f9fd2
9 changed files with 364 additions and 26 deletions
|
@ -53,3 +53,6 @@ tab {
|
|||
background-color: #ececec;
|
||||
border-top: 1px solid hsla(0, 0%, 0%, 0.2);
|
||||
}
|
||||
.zotero-tb-button:focus {
|
||||
border: 1px dotted #999;
|
||||
}
|
||||
|
|
|
@ -2313,6 +2313,19 @@
|
|||
focusFirstField() {
|
||||
this._focusNextField(1);
|
||||
}
|
||||
|
||||
focusLastField() {
|
||||
const tabbableFields = this.querySelectorAll('*[ztabindex]:not([disabled=true])');
|
||||
const last = tabbableFields[tabbableFields.length - 1];
|
||||
|
||||
if (last.classList.contains('zotero-focusable')) {
|
||||
last.focus();
|
||||
}
|
||||
// Fields need to be clicked
|
||||
else {
|
||||
last.click();
|
||||
}
|
||||
}
|
||||
|
||||
focusField(fieldName) {
|
||||
let field = this.querySelector(`[fieldname="${fieldName}"][ztabindex]`);
|
||||
|
|
|
@ -253,6 +253,12 @@
|
|||
_id(id) {
|
||||
return this.querySelector(`[id=${id}]`);
|
||||
}
|
||||
|
||||
receiveKeyboardFocus(direction) {
|
||||
this._id("addButton").focus();
|
||||
// TODO: the relatedbox is not currently keyboard accessible
|
||||
// so we are ignoring the direction
|
||||
}
|
||||
}
|
||||
customElements.define("related-box", RelatedBox);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<div id="tags-box" style="flex-grow: 1" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<div class="tags-box-header">
|
||||
<label id="count"/>
|
||||
<button id="add">&zotero.item.add;</button>
|
||||
<button id="tags-box-add-button">&zotero.item.add;</button>
|
||||
</div>
|
||||
<ul id="rows" class="tags-box-list"/>
|
||||
</div>
|
||||
|
@ -79,8 +79,8 @@
|
|||
let content = document.importNode(this.content, true);
|
||||
this.append(content);
|
||||
|
||||
this._id('add').addEventListener('click', this._handleAddButtonClick);
|
||||
this._id('add').addEventListener('keydown', this._handleAddButtonKeyDown);
|
||||
this._id("tags-box-add-button").addEventListener('click', this._handleAddButtonClick);
|
||||
this._id("tags-box-add-button").addEventListener('keydown', this._handleAddButtonKeyDown);
|
||||
this._id('tags-box').addEventListener('click', (event) => {
|
||||
if (event.target.id == 'tags-box') {
|
||||
this.blurOpenField();
|
||||
|
@ -228,7 +228,7 @@
|
|||
// Cancel field focusing while we're updating
|
||||
this._reloading = true;
|
||||
|
||||
this._id('add').hidden = !this.editable;
|
||||
this._id("tags-box-add-button").hidden = !this.editable;
|
||||
|
||||
this._tagColors = Zotero.Tags.getColors(this.item.libraryID);
|
||||
|
||||
|
@ -889,7 +889,7 @@
|
|||
else if (dir == -1) {
|
||||
if (tabindex == 1) {
|
||||
// Focus Add button
|
||||
this._id('add').focus();
|
||||
this._id("tags-box-add-button").focus();
|
||||
return false;
|
||||
}
|
||||
var nextIndex = tabindex - 1;
|
||||
|
|
|
@ -41,6 +41,7 @@ var Zotero_Lookup = new function () {
|
|||
* @param toggleProgress {function} - Callback to toggle progress on/off
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
this._button = null;
|
||||
this.addItemsFromIdentifier = async function (textBox, childItem, toggleProgress) {
|
||||
var identifiers = Zotero.Utilities.extractIdentifiers(textBox.value);
|
||||
if (!identifiers.length) {
|
||||
|
@ -134,9 +135,34 @@ var Zotero_Lookup = new function () {
|
|||
|
||||
this.showPanel = function (button) {
|
||||
var panel = document.getElementById('zotero-lookup-panel');
|
||||
this._button = button;
|
||||
if (!button) {
|
||||
button = document.getElementById("zotero-tb-lookup");
|
||||
}
|
||||
panel.openPopup(button, "after_start", 16, -2, false, false);
|
||||
}
|
||||
|
||||
this.onFocusOut = function(event) {
|
||||
|
||||
/*
|
||||
if the lookup popup was triggered by the lookup button,
|
||||
we want to return there on focus out. So we check
|
||||
(1) that we came from a button and (2) that
|
||||
event.relatedTarget === null, i.e. that the user hasn't used
|
||||
the mouse or keyboard to select something, and focus is leaving
|
||||
the popup because the popup was hidden/dismissed.
|
||||
*/
|
||||
if (this._button && event.relatedTarget === null) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this._button.focus();
|
||||
this._button = null;
|
||||
}
|
||||
else {
|
||||
this._button = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Focuses the field
|
||||
|
|
|
@ -1492,7 +1492,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
|||
panel.removeChild(panel.firstChild);
|
||||
}
|
||||
|
||||
for (let e of errors) {
|
||||
for (let [index, e] of errors.entries()) {
|
||||
var box = doc.createXULElement('vbox');
|
||||
var label = doc.createXULElement('label');
|
||||
if (e.libraryID !== undefined) {
|
||||
|
@ -1516,6 +1516,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
|||
if (e.dialogHeader) {
|
||||
let header = doc.createXULElement('description');
|
||||
header.className = 'error-header';
|
||||
header.setAttribute("control", `zotero-sync-error-panel-button-${index}`);
|
||||
header.textContent = e.dialogHeader;
|
||||
content.appendChild(header);
|
||||
}
|
||||
|
@ -1538,7 +1539,8 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
|||
// Make the text selectable
|
||||
desc.setAttribute('style', '-moz-user-select: text; cursor: text');
|
||||
content.appendChild(desc);
|
||||
|
||||
desc.setAttribute("control", `zotero-sync-error-panel-button-${index}`);
|
||||
|
||||
/*// If not an error and there's no explicit button text, don't show
|
||||
// button to report errors
|
||||
if (e.errorType != 'error' && e.dialogButtonText === undefined) {
|
||||
|
@ -1557,12 +1559,24 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
|||
var buttonCallback = e.dialogButtonCallback;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-inner-declarations
|
||||
function addEventHandlers(button, cb) {
|
||||
button.addEventListener("click", () => {
|
||||
cb();
|
||||
panel.hidePopup();
|
||||
});
|
||||
|
||||
button.addEventListener("keydown", (event) => {
|
||||
if (event.key !== ' ' && event.key !== 'Enter') return;
|
||||
cb();
|
||||
panel.hidePopup();
|
||||
});
|
||||
}
|
||||
|
||||
let button = doc.createXULElement('button');
|
||||
button.setAttribute('label', buttonText);
|
||||
button.onclick = function () {
|
||||
buttonCallback();
|
||||
panel.hidePopup();
|
||||
};
|
||||
button.setAttribute("id", `zotero-sync-error-panel-button-${index}`);
|
||||
addEventHandlers(button, buttonCallback);
|
||||
buttons.appendChild(button);
|
||||
|
||||
// Second button
|
||||
|
@ -1571,11 +1585,10 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
|||
buttonCallback = e.dialogButton2Callback;
|
||||
|
||||
let button2 = doc.createXULElement('button');
|
||||
button2.setAttribute("id", `zotero-sync-error-panel-button-${index}`);
|
||||
button.removeAttribute("id");
|
||||
button2.setAttribute('label', buttonText);
|
||||
button2.onclick = () => {
|
||||
buttonCallback();
|
||||
panel.hidePopup();
|
||||
};
|
||||
addEventHandlers(button2, buttonCallback);
|
||||
buttons.insertBefore(button2, button);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,10 @@ var ZoteroPane = new function()
|
|||
this.reportErrors = reportErrors;
|
||||
|
||||
this.document = document;
|
||||
|
||||
|
||||
const modifierIsNotShift = ev => ev.getModifierState("Meta") || ev.getModifierState("Alt")
|
||||
|| ev.getModifierState("Control") || ev.getModifierState("OS");
|
||||
|
||||
var self = this,
|
||||
_loaded = false, _madeVisible = false,
|
||||
titlebarcolorState, titleState, observerService,
|
||||
|
@ -129,14 +132,276 @@ var ZoteroPane = new function()
|
|||
|
||||
// register an observer for Zotero reload
|
||||
observerService = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
observerService.addObserver(_reloadObserver, "zotero-reloaded", false);
|
||||
observerService.addObserver(_reloadObserver, "zotero-before-reload", false);
|
||||
this.addReloadListener(_loadPane);
|
||||
|
||||
// continue loading pane
|
||||
_loadPane();
|
||||
setUpToolbar();
|
||||
};
|
||||
|
||||
function setUpToolbar() {
|
||||
// if the hidden property is ever set on a grandparent or more distant
|
||||
// ancestor this will need to be updated
|
||||
const isVisible = b => !b.hidden && !b.parentElement.hidden;
|
||||
const isTbButton = node => node && node.tagName === "toolbarbutton";
|
||||
|
||||
function nextVisible(id, field = "after") {
|
||||
let b = document.getElementById(id);
|
||||
while (!isVisible(b)) {
|
||||
const mapData = focusMap.get(b.id);
|
||||
b = document.getElementById(mapData[field]);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/* constants */
|
||||
const toolbar = this.document.getElementById("zotero-toolbar");
|
||||
|
||||
// assumes no toolbarbuttons are dynamically added, just hidden
|
||||
// or revealed. If this changes, the observer will have to monitor
|
||||
// changes to the childList for each hbox in the toolbar which might
|
||||
// have dynamic children
|
||||
const buttons = toolbar.getElementsByTagName("toolbarbutton");
|
||||
const focusMap = new Map();
|
||||
const zones = [
|
||||
{
|
||||
get start() {
|
||||
return document.getElementById("zotero-tb-collection-add");
|
||||
},
|
||||
focusBefore() {
|
||||
// If no item is selected, focus items list.
|
||||
const pane = document.getElementById("zotero-item-pane-content");
|
||||
if (pane.selectedIndex === "0") {
|
||||
document.getElementById("item-tree-main-default").focus();
|
||||
}
|
||||
else {
|
||||
const tabBox = document.getElementById("zotero-view-tabbox");
|
||||
if (tabBox.selectedIndex === 0) {
|
||||
const itembox = document.getElementById("zotero-editpane-item-box");
|
||||
itembox.focusLastField();
|
||||
}
|
||||
else if (tabBox.selectedIndex === 1) {
|
||||
const notes = document.getElementById("zotero-editpane-notes");
|
||||
const nodes = notes.querySelectorAll("button");
|
||||
const node = nodes[nodes.length - 1];
|
||||
node.focus();
|
||||
// TODO: the notes are currently inaccessible to the keyboard
|
||||
}
|
||||
else if (tabBox.selectedIndex === 2) {
|
||||
const tagContainer = document.getElementById("tags-box-container");
|
||||
const tags = tagContainer.querySelectorAll("#tags-box-add-button,.zotero-clicky");
|
||||
const last = tags[tags.length - 1];
|
||||
if (last.id === "tags-box-add-button") {
|
||||
last.focus();
|
||||
}
|
||||
else {
|
||||
last.click();
|
||||
}
|
||||
}
|
||||
else if (tabBox.selectedIndex === 3) {
|
||||
const related = tabBox.querySelector("relatedbox");
|
||||
related.receiveKeyboardFocus("end");
|
||||
}
|
||||
else {
|
||||
throw new Error("The selectedIndex should always be between 1 and 4");
|
||||
}
|
||||
}
|
||||
},
|
||||
focusAfter() {
|
||||
document.getElementById("zotero-tb-search")._searchModePopup.flattenedTreeParentNode.focus();
|
||||
}
|
||||
},
|
||||
{
|
||||
get start() {
|
||||
return document.getElementById("zotero-tb-locate");
|
||||
},
|
||||
focusBefore() {
|
||||
document.getElementById("zotero-tb-search").focus();
|
||||
},
|
||||
focusAfter() {
|
||||
document.getElementById("collection-tree").focus();
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
/*
|
||||
observe buttons and containers for changes in the "hidden"
|
||||
attribute
|
||||
*/
|
||||
const observer = new MutationObserver((mutations, _) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.target.hidden
|
||||
&& (document.activeElement === mutation.target
|
||||
|| mutation.target.contains(document.activeElement))
|
||||
) {
|
||||
const next = nextVisible(document.activeElement.id, "before");
|
||||
next.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
build a chain which connects all the <toolbarbutton>s,
|
||||
except for zotero-tb-locate and zotero-tb-advanced-search
|
||||
which is where the chain breaks
|
||||
*/
|
||||
let prev = null;
|
||||
let _zone = zones[0];
|
||||
for (const button of buttons) {
|
||||
focusMap.set(button.id, {
|
||||
before: prev,
|
||||
after: null,
|
||||
zone: _zone
|
||||
});
|
||||
|
||||
/* observe each button for changes to "hidden" */
|
||||
observer.observe(button, {
|
||||
attributes: true,
|
||||
attributeFilter: ["hidden"]
|
||||
});
|
||||
|
||||
if (focusMap.has(prev)) {
|
||||
focusMap.get(prev).after = button.id;
|
||||
}
|
||||
|
||||
prev = button.id;
|
||||
|
||||
// break the chain at zotero-tb-advanced-search
|
||||
if (button.id === "zotero-tb-advanced-search") {
|
||||
_zone = zones[1];
|
||||
prev = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
observer.observe(document.getElementById("zotero-tb-sync-stop"), {
|
||||
attributes: true,
|
||||
attributeFilter: ["hidden"]
|
||||
});
|
||||
|
||||
// lookupButton and syncErrorButton show popup panels, and so need special treatment
|
||||
const lookupButton = document.getElementById("zotero-tb-lookup");
|
||||
const syncErrorButton = document.getElementById("zotero-tb-sync-error");
|
||||
|
||||
/* buttons at the start of zones need tabindex=0 */
|
||||
for (const zone of zones) {
|
||||
zone.start.setAttribute("tabindex", "0");
|
||||
}
|
||||
|
||||
toolbar.addEventListener("keydown", (event) => {
|
||||
// manually move focus when Shift+Tabbing from the search-menu-button
|
||||
if (event.key === 'Tab' && event.shiftKey
|
||||
&& !modifierIsNotShift(event)
|
||||
&& event.originalTarget
|
||||
&& event.originalTarget.id == "zotero-tb-search-menu-button") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
zones[0].start.focus();
|
||||
return;
|
||||
}
|
||||
// manually move focus to search menu when Shift+Tabbing from the search-menu
|
||||
if (event.key === 'Tab' && event.shiftKey
|
||||
&& !modifierIsNotShift(event)
|
||||
&& event.originalTarget?.tagName == "input") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
document.getElementById("zotero-tb-search")._searchModePopup.flattenedTreeParentNode.focus();
|
||||
return;
|
||||
}
|
||||
// only handle events on a <toolbarbutton>
|
||||
if (!isTbButton(event.target)) return;
|
||||
|
||||
const mapData = focusMap.get(event.target.id);
|
||||
|
||||
if (!Zotero.rtl && event.key === 'ArrowRight'
|
||||
|| Zotero.rtl && event.key === 'ArrowLeft') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (mapData.after) {
|
||||
nextVisible(mapData.after, "after").focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!Zotero.rtl && event.key === 'ArrowLeft'
|
||||
|| Zotero.rtl && event.key === 'ArrowRight') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (mapData.before) {
|
||||
nextVisible(mapData.before, "before").focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* manually trigger on space and enter */
|
||||
if (event.key === ' ' || event.key === 'Enter') {
|
||||
if (event.target.disabled) return;
|
||||
|
||||
if (event.target === lookupButton) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
Zotero_Lookup.showPanel(event.target);
|
||||
}
|
||||
else if (event.target === syncErrorButton) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
syncErrorButton.dispatchEvent(new MouseEvent("click", {
|
||||
target: event.target
|
||||
}));
|
||||
}
|
||||
else if (event.target.getAttribute('type') === 'menu') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const popup = event.target.querySelector("menupopup");
|
||||
if (popup !== null && !event.target.disabled) {
|
||||
popup.openPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* activate menus and popups on ArrowDown and ArrowUp, otherwise prepare for a focus change */
|
||||
else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
||||
if (event.target === lookupButton && !event.target.disabled) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
Zotero_Lookup.showPanel(event.target);
|
||||
}
|
||||
else if (event.target.getAttribute('type') === 'menu' && !event.target.disabled) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const popup = event.target.querySelector("menupopup");
|
||||
if (popup !== null && !event.target.disabled) {
|
||||
popup.openPopup();
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare for a focus change */
|
||||
else if (event.key === 'ArrowDown') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
mapData.zone.focusBefore();
|
||||
}
|
||||
else if (event.key === 'ArrowUp') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
mapData.zone.focusAfter();
|
||||
}
|
||||
}
|
||||
else if (event.key === 'Tab' && !modifierIsNotShift(event)) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (event.shiftKey) {
|
||||
mapData.zone.focusBefore();
|
||||
}
|
||||
else {
|
||||
mapData.zone.focusAfter();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called on window load or when pane has been reloaded after switching into or out of connector
|
||||
|
|
|
@ -720,12 +720,13 @@
|
|||
onkeypress="ZoteroPane_Local.handleKeyPress(event)"
|
||||
chromedir="&locale.dir;">
|
||||
|
||||
<toolbar id="zotero-toolbar" class="toolbar toolbar-primary">
|
||||
<toolbar id="zotero-toolbar" tabindex="-1" class="toolbar toolbar-primary">
|
||||
<hbox id="zotero-collections-toolbar" align="center">
|
||||
<toolbarbutton id="zotero-tb-collection-add" class="zotero-tb-button" tooltiptext="&zotero.toolbar.newCollection.label;" command="cmd_zotero_newCollection"/>
|
||||
<toolbarbutton id="zotero-tb-collection-add" tabindex="-1" class="zotero-tb-button" tooltiptext="&zotero.toolbar.newCollection.label;" command="cmd_zotero_newCollection"/>
|
||||
<toolbarbutton
|
||||
id="zotero-tb-library-add-menu"
|
||||
class="zotero-tb-button"
|
||||
tabindex="-1"
|
||||
tooltiptext="&zotero.toolbar.newLibrary.label;"
|
||||
type="menu"
|
||||
wantdropmarker="true">
|
||||
|
@ -747,6 +748,7 @@
|
|||
<toolbarbutton
|
||||
id="zotero-tb-add"
|
||||
class="zotero-tb-button"
|
||||
tabindex="-1"
|
||||
tooltiptext="&zotero.toolbar.newItem.label;"
|
||||
type="menu"
|
||||
wantdropmarker="true"
|
||||
|
@ -762,16 +764,17 @@
|
|||
</menupopup>
|
||||
</toolbarbutton>
|
||||
|
||||
<toolbarbutton id="zotero-tb-lookup" class="zotero-tb-button" tooltiptext="&zotero.toolbar.lookup.label;" type="panel"
|
||||
<toolbarbutton id="zotero-tb-lookup" tabindex="-1" class="zotero-tb-button" tooltiptext="&zotero.toolbar.lookup.label;" type="panel"
|
||||
onmousedown="if (this.disabled) { event.preventDefault(); return; } Zotero_Lookup.showPanel(this)"/>
|
||||
|
||||
<panel id="zotero-lookup-panel" type="arrow"
|
||||
onpopupshowing="Zotero_Lookup.onShowing(event)"
|
||||
onpopupshown="Zotero_Lookup.onShown(event)"
|
||||
onpopuphidden="Zotero_Lookup.onHidden(event)"
|
||||
onfocusout="Zotero_Lookup.onFocusOut(event)"
|
||||
>
|
||||
<vbox>
|
||||
<label>&zotero.lookup.description;</label>
|
||||
<label control="zotero-lookup-textbox">&zotero.lookup.description;</label>
|
||||
<vbox id="zotero-lookup-multiline">
|
||||
<html:textarea
|
||||
id="zotero-lookup-textbox"
|
||||
|
@ -794,6 +797,7 @@
|
|||
<toolbarbutton
|
||||
id="zotero-tb-note-add" class="zotero-tb-button" tooltiptext="&zotero.toolbar.newNote;"
|
||||
type="menu"
|
||||
tabindex="-1"
|
||||
wantdropmarker="true"
|
||||
onmousedown="if (this.disabled) { event.preventDefault(); return; }">
|
||||
<menupopup onpopupshowing="ZoteroPane_Local.updateNoteButtonMenu()">
|
||||
|
@ -804,6 +808,7 @@
|
|||
<toolbarbutton
|
||||
id="zotero-tb-attachment-add"
|
||||
class="zotero-tb-button"
|
||||
tabindex="-1"
|
||||
tooltiptext="&zotero.items.menu.attach;"
|
||||
type="menu"
|
||||
wantdropmarker="true"
|
||||
|
@ -815,7 +820,7 @@
|
|||
</menupopup>
|
||||
</toolbarbutton>
|
||||
<toolbarseparator/>
|
||||
<toolbarbutton id="zotero-tb-advanced-search" class="zotero-tb-button" tooltiptext="&zotero.toolbar.advancedSearch;" command="cmd_zotero_advancedSearch"/>
|
||||
<toolbarbutton id="zotero-tb-advanced-search" tabindex="-1" class="zotero-tb-button" tooltiptext="&zotero.toolbar.advancedSearch;" command="cmd_zotero_advancedSearch"/>
|
||||
<spacer flex="1"/>
|
||||
<image id="zotero-tb-search-spinner" class="zotero-spinner-14" style="display: none"/>
|
||||
<quick-search-textbox id="zotero-tb-search" timeout="250"
|
||||
|
@ -835,9 +840,11 @@
|
|||
<menupopup id="zotero-tb-locate-menu" onpopupshowing="Zotero_LocateMenu.buildLocateMenu()"/>
|
||||
</toolbarbutton>
|
||||
</hbox>
|
||||
<hbox align="center" pack="end">
|
||||
<hbox id="zotero-tb-sync-progress-box" align="center" pack="end">
|
||||
<toolbarbutton id="zotero-tb-sync-stop"
|
||||
tooltiptext="&zotero.sync.stop;"
|
||||
tabindex="-1"
|
||||
style="-moz-user-focus: normal;"
|
||||
oncommand="this.hidden = true; Zotero.Sync.Runner.stop()"
|
||||
hidden="true"/>
|
||||
</hbox>
|
||||
|
@ -845,15 +852,19 @@
|
|||
<hbox id="zotero-pq-buttons">
|
||||
</hbox>
|
||||
|
||||
<toolbarbutton id="zotero-tb-sync-error" hidden="true"/>
|
||||
<toolbarbutton tabindex="-1" id="zotero-tb-sync-error" hidden="true" style="-moz-user-focus: normal;" />
|
||||
|
||||
<!--
|
||||
We put this here, but it can be used wherever
|
||||
Zotero.Sync.Runner.updateErrorPanel() puts it
|
||||
-->
|
||||
<panel id="zotero-sync-error-panel" type="arrow"/>
|
||||
<panel id="zotero-sync-error-panel" type="arrow" onpopupshown="
|
||||
const buttons = this.getElementsByTagName('button');
|
||||
if (buttons[0]) {
|
||||
buttons[0].focus();
|
||||
}" />
|
||||
|
||||
<toolbarbutton id="zotero-tb-sync" class="zotero-tb-button" tooltip="_child"
|
||||
<toolbarbutton id="zotero-tb-sync" tabindex="-1" class="zotero-tb-button" tooltip="_child"
|
||||
oncommand="ZoteroPane.sync()">
|
||||
<tooltip
|
||||
id="zotero-tb-sync-tooltip"
|
||||
|
|
|
@ -216,6 +216,7 @@
|
|||
}
|
||||
|
||||
.zotero-tb-button {
|
||||
-moz-user-focus: normal;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
margin-right: 2px;
|
||||
|
|
Loading…
Reference in a new issue