fx-compat: Fix feed Add To button

And make accessible by keyboard
This commit is contained in:
Abe Jellinek 2022-11-22 20:42:53 -05:00 committed by Dan Stillman
parent 730677a918
commit 53ace4876e
6 changed files with 142 additions and 21 deletions

View file

@ -33,26 +33,9 @@
constructor() {
super();
this.addEventListener('mousedown', (event) => {
let popup = this.querySelector(':scope > menupopup');
if (popup && this.getAttribute('nonnativepopup') != 'true') {
if (this.getAttribute('nonnativepopup') != 'true'
&& Zotero.Utilities.Internal.showNativeElementPopup(this)) {
event.preventDefault();
let rect = this.getBoundingClientRect();
let dir = getComputedStyle(this).direction;
popup.openPopupAtScreen(
window.screenX + (dir == 'rtl' ? rect.right : rect.left),
window.screenY + rect.bottom,
true
);
this.setAttribute('open', true);
let handler = (event) => {
if (event.target == popup) {
this.setAttribute('open', false);
popup.removeEventListener('popuphiding', handler);
}
};
popup.addEventListener('popuphiding', handler);
}
});
}

View file

@ -0,0 +1,95 @@
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2022 Corporation for Digital Scholarship
Vienna, Virginia, USA
https://www.zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
"use strict";
{
/**
* Extends MozButton to provide a split menubutton with a clickable left side and a dropmarker that opens a menu.
*/
class SplitMenuButton extends customElements.get('button') {
constructor() {
super();
// Just in case, make sure this button does NOT appear as a standard <button type="menu">
// We don't want the entire button to open the menu and we don't want the standard dropmarker
this.removeAttribute('type');
// For easier CSS targeting
this.classList.add('split-menu-button');
// Pointer events don't reach the button's children, so check mousedown positions manually and open
// the popup if over the end side of the button
this.addEventListener('mousedown', (event) => {
let rect = this.querySelector('[anonid="dropmarker-box"]').getBoundingClientRect();
if (event.x >= rect.left && event.x <= rect.right
&& Zotero.Utilities.Internal.showNativeElementPopup(this)) {
event.preventDefault();
}
});
this.addEventListener('keydown', (event) => {
if (event.key == 'ArrowDown' && Zotero.Utilities.Internal.showNativeElementPopup(this)) {
event.preventDefault();
}
});
}
connectedCallback() {
if (this.delayConnectedCallback() || this._hasConnected) {
return;
}
super.connectedCallback();
this.querySelector('[anonid="button-box"]').after(this.constructor.dropmarkerFragment);
}
static get dropmarkerFragment() {
// Zotero.hiDPI[Suffix] may not have been initialized yet, so calculate it ourselves
let hiDPISuffix = window.devicePixelRatio > 1 ? '@2x' : '';
let frag = document.importNode(
MozXULElement.parseXULToFragment(`
<hbox align="center" anonid="dropmarker-box">
<image src="chrome://zotero/skin/searchbar-dropmarker${hiDPISuffix}.png" width="7" height="4" class="split-menu-button-dropmarker"/>
</hbox>
`),
true
);
Object.defineProperty(this, "dropmarkerFragment", { value: frag });
return frag;
}
_handleClick() {
super._handleClick();
if (!this.disabled) {
this.doCommand();
}
}
}
customElements.define("split-menu-button", SplitMenuButton, {
extends: "button",
});
}

View file

@ -2339,6 +2339,39 @@ Zotero.Utilities.Internal = {
}
}
return html;
},
/**
* Open an element's <menupopup> child as a native context menu.
*
* @param {XULElement} element
* @return {Boolean} If a <menupopup> child was found and opened
*/
showNativeElementPopup(element) {
let popup = element.querySelector(':scope > menupopup');
if (popup) {
let rect = element.getBoundingClientRect();
let win = element.ownerDocument.defaultView;
let dir = win.getComputedStyle(element).direction;
popup.openPopupAtScreen(
win.screenX + (dir == 'rtl' ? rect.right : rect.left),
win.screenY + rect.bottom,
true
);
element.setAttribute('open', true);
let handler = (event) => {
if (event.target == popup) {
element.setAttribute('open', false);
popup.removeEventListener('popuphiding', handler);
}
};
popup.addEventListener('popuphiding', handler);
return true;
}
return false;
}
}

View file

@ -88,6 +88,7 @@
Services.scriptloader.loadSubScript("chrome://zotero/content/elements/attachmentBox.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/elements/menuToolbarbutton.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/elements/quickSearchTextbox.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/elements/splitMenuButton.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/tabs.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/zoteroPane.js", this);
@ -1054,7 +1055,7 @@
<hbox id="zotero-item-pane-top-buttons-feed" class="zotero-item-pane-top-buttons" hidden="true">
<button id="zotero-feed-item-toggleRead-button"
oncommand="ZoteroPane_Local.toggleSelectedItemsRead();"/>
<button id="zotero-feed-item-addTo-button" type="menu-button"
<button is="split-menu-button" id="zotero-feed-item-addTo-button"
oncommand="ZoteroItemPane.translateSelectedItems()">
<menupopup id="zotero-item-addTo-menu" onpopupshowing="ZoteroItemPane.buildTranslateSelectContextMenu(event);"/>
</button>

View file

@ -100,6 +100,6 @@
}
#zotero-feed-item-addTo-button .button-icon {
margin-right: 5px;
margin-inline-end: 5px;
height: 16px;
}

View file

@ -703,6 +703,15 @@
color: HighlightText;
}
.split-menu-button, .split-menu-button [anonid="dropmarker-box"] {
/* Hide the dropmarker if the button overflows */
overflow: hidden;
}
.split-menu-button .split-menu-button-dropmarker {
margin-inline: 5px;
}
/* BEGIN 2X BLOCK -- DO NOT EDIT MANUALLY -- USE 2XIZE */
@media (min-resolution: 1.25dppx) {