diff --git a/chrome/content/zotero/components/button.jsx b/chrome/content/zotero/components/button.jsx
index e9f4485c5e..41ea8a65b3 100644
--- a/chrome/content/zotero/components/button.jsx
+++ b/chrome/content/zotero/components/button.jsx
@@ -99,8 +99,23 @@ class Button extends PureComponent {
}
if (!this.props.isDisabled) {
- attr.onMouseDown = this.handleMouseDown
+ attr.onMouseDown = (event) => {
+ // Hide tooltip on mousedown
+ if (this.title) {
+ window.Zotero_Tooltip.stop();
+ }
+ return this.handleMouseDown(event);
+ };
attr.onClick = this.handleClick
+ // Fake tooltip behavior as long as 'title' doesn't work for HTML-in-XUL elements
+ if (this.title) {
+ attr.onMouseOver = () => {
+ window.Zotero_Tooltip.start(this.title);
+ };
+ attr.onMouseOut = () => {
+ window.Zotero_Tooltip.stop();
+ };
+ }
}
return attr
diff --git a/chrome/content/zotero/tooltip.js b/chrome/content/zotero/tooltip.js
new file mode 100644
index 0000000000..9ad98c94ba
--- /dev/null
+++ b/chrome/content/zotero/tooltip.js
@@ -0,0 +1,78 @@
+/*
+ ***** BEGIN LICENSE BLOCK *****
+
+ Copyright © 2020 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 .
+
+ ***** END LICENSE BLOCK *****
+*/
+
+/**
+ * Fake tooltip implementation for HTML-in-XUL elements where neither 'title' nor 'tooltiptext' works
+ */
+// eslint-disable-next-line camelcase,no-unused-vars
+var Zotero_Tooltip = new function () {
+ // On macOS, the tooltip appears even if the mouse keeps moving over the element, but Mozilla
+ // shows it only once the mouse stops, so follow that as long as there are XUL elements.
+ const MOUSE_STOP_DELAY = 500;
+
+ var text;
+ var timeoutID;
+ var x;
+ var y;
+
+ /**
+ * Start tracking the mouse and show a tooltip after it stops
+ */
+ this.start = function (tooltipText) {
+ window.addEventListener('mousemove', handleMouseMove);
+ text = tooltipText;
+ };
+
+ /**
+ * Stop tracking the mouse and hide the tooltip if it's showing
+ */
+ this.stop = function () {
+ window.removeEventListener('mousemove', handleMouseMove);
+ clearTimeout(timeoutID);
+ // Mozilla hides the tooltip as soon as the mouse leaves the element, which is also different
+ // from macOS behavior
+ hidePopup();
+ };
+
+ function handleMouseMove(event) {
+ if (timeoutID) {
+ clearTimeout(timeoutID);
+ }
+ x = event.screenX;
+ y = event.screenY;
+ timeoutID = setTimeout(handleMouseStop, MOUSE_STOP_DELAY);
+ }
+
+ function handleMouseStop() {
+ var tooltipElem = document.getElementById('fake-tooltip');
+ tooltipElem.setAttribute('label', text);
+ tooltipElem.openPopupAtScreen(x, y, false, null);
+ }
+
+ function hidePopup() {
+ var tooltipElem = document.getElementById('fake-tooltip');
+ tooltipElem.hidePopup();
+ }
+};
diff --git a/chrome/content/zotero/zoteroPane.xul b/chrome/content/zotero/zoteroPane.xul
index 661dc59396..4d20c0ad9a 100644
--- a/chrome/content/zotero/zoteroPane.xul
+++ b/chrome/content/zotero/zoteroPane.xul
@@ -49,6 +49,7 @@
+
@@ -289,6 +290,8 @@
+
+