handleTabClose(event, id)}
@@ -310,7 +297,6 @@ const TabBar = forwardRef(function (props, ref) {
{tabs.length ? renderTab(tabs[0], 0) : null}
@@ -332,7 +318,6 @@ const TabBar = forwardRef(function (props, ref) {
ref={tabsRef}
className="tabs"
onDragOver={handleTabBarDragOver}
- onMouseOut={handleTabBarMouseOut}
onScroll={updateScrollArrows}
dir={Zotero.dir}
>
diff --git a/chrome/content/zotero/components/tagSelector/tagSelectorList.jsx b/chrome/content/zotero/components/tagSelector/tagSelectorList.jsx
index 92767475a8..f02af93b6e 100644
--- a/chrome/content/zotero/components/tagSelector/tagSelectorList.jsx
+++ b/chrome/content/zotero/components/tagSelector/tagSelectorList.jsx
@@ -196,10 +196,8 @@ class TagList extends React.PureComponent {
delete props.style.width;
}
else {
- // Setting this via props doesn't seem to work in XUL, but setting it on hover does.
- // Hopefully in an HTML window we'll be able to just set 'title'.
props.onMouseOver = function (event) {
- event.target.setAttribute('tooltiptext', tag.name);
+ event.target.setAttribute('title', tag.name);
};
}
diff --git a/chrome/content/zotero/tooltip.js b/chrome/content/zotero/components/tooltip.js
similarity index 84%
rename from chrome/content/zotero/tooltip.js
rename to chrome/content/zotero/components/tooltip.js
index 9ad98c94ba..b58131fd40 100644
--- a/chrome/content/zotero/tooltip.js
+++ b/chrome/content/zotero/components/tooltip.js
@@ -67,12 +67,24 @@ var Zotero_Tooltip = new function () {
function handleMouseStop() {
var tooltipElem = document.getElementById('fake-tooltip');
+ // Create the fake tooltip if it does not exist
+ if (!tooltipElem) {
+ tooltipElem = document.createXULElement("tooltip");
+ tooltipElem.id = "fake-tooltip";
+ // The tooltip location is important. If the tooltip is placed
+ // within a lower level component, it may be not visible
+ document.documentElement.appendChild(tooltipElem);
+ }
tooltipElem.setAttribute('label', text);
tooltipElem.openPopupAtScreen(x, y, false, null);
}
function hidePopup() {
var tooltipElem = document.getElementById('fake-tooltip');
- tooltipElem.hidePopup();
+ if (tooltipElem) {
+ tooltipElem.hidePopup();
+ }
}
};
+
+export { Zotero_Tooltip };
diff --git a/chrome/content/zotero/components/virtualized-table.jsx b/chrome/content/zotero/components/virtualized-table.jsx
index f7b7dac7d0..22c26d4e45 100644
--- a/chrome/content/zotero/components/virtualized-table.jsx
+++ b/chrome/content/zotero/components/virtualized-table.jsx
@@ -31,6 +31,7 @@ const cx = require('classnames');
const WindowedList = require('./windowed-list');
const Draggable = require('./draggable');
const { CSSIcon, getDOMElement } = require('components/icons');
+const { Zotero_Tooltip } = require('./tooltip');
const TYPING_TIMEOUT = 1000;
const MINIMUM_ROW_HEIGHT = 20; // px
@@ -909,6 +910,9 @@ class VirtualizedTable extends React.Component {
* @param event
*/
_handleMouseOver = (event) => {
+ // On scroll, mouse position does not change, so _handleMouseMove does not fire
+ // to close the fake tooltip. Make sure it is closed here.
+ Zotero_Tooltip.stop();
let elem = event.target;
if (!elem.classList.contains('cell') || elem.classList.contains('cell-icon')) return;
let textElem = elem.querySelector('.label, .cell-text');
@@ -929,6 +933,59 @@ class VirtualizedTable extends React.Component {
}
}
+ /**
+ * Manually handle tooltip setting for table cells with overflowing values.
+ * Temporary, after
+ * https://github.com/zotero/zotero/commit/8e2790e2d2a1d8b15efbf84935f0a80d58db4e44.
+ * @param event
+ */
+ _handleMouseMove = (event) => {
+ let tgt = event.target;
+ // Mouse left the previous cell - close the tooltip
+ if (!tgt.classList.contains("row")
+ || event.clientX < parseInt(tgt.dataset.mouseLeft)
+ || event.clientX > parseInt(tgt.dataset.mouseRight)) {
+ delete tgt.dataset.mouseLeft;
+ delete tgt.dataset.mouseRight;
+ Zotero_Tooltip.stop();
+ }
+
+ if (!tgt.classList.contains("row")) return;
+ let cells = tgt.querySelectorAll(".cell");
+ let targetCell;
+ // Find the cell the mouse is over
+ for (let cell of cells) {
+ let rect = cell.getBoundingClientRect();
+ if (event.clientX >= rect.left && event.clientX <= rect.right) {
+ targetCell = cell;
+ tgt.dataset.mouseLeft = rect.left;
+ tgt.dataset.mouseRight = rect.right;
+ break;
+ }
+ }
+ if (!targetCell) return;
+ // Primary cell will .cell-text child node
+ let textCell = targetCell.querySelector(".cell-text") || targetCell;
+ // If the cell has overflowing content, display the fake tooltip
+ if (textCell.offsetWidth < textCell.scrollWidth) {
+ Zotero_Tooltip.stop();
+ Zotero_Tooltip.start(textCell.textContent);
+ }
+ };
+
+ /**
+ * Remove manually added fake tooltip from _handleMouseMove when the
+ * mouse leaves the row completely.
+ */
+ _handleMouseLeave = (_) => {
+ Zotero_Tooltip.stop();
+ let lastRow = document.querySelector("[mouseLeft][mouseRight]");
+ if (lastRow) {
+ delete lastRow.dataset.mouseLeft;
+ delete lastRow.dataset.mouseRight;
+ }
+ };
+
_handleResizerDragStop = (event) => {
event.stopPropagation();
const result = this._getResizeColumns();
@@ -1193,6 +1250,8 @@ class VirtualizedTable extends React.Component {
onDrop: e => this.props.onDrop && this.props.onDrop(e),
onFocus: e => this.props.onFocus && this.props.onFocus(e),
onMouseOver: e => this._handleMouseOver(e),
+ onMouseMove: e => this._handleMouseMove(e),
+ onMouseLeave: e => this._handleMouseLeave(e),
className: cx(["virtualized-table", {
resizing: this.state.resizing,
'multi-select': this.props.multiSelect
diff --git a/chrome/content/zotero/tabs.js b/chrome/content/zotero/tabs.js
index 7ff330550b..2868aff7fd 100644
--- a/chrome/content/zotero/tabs.js
+++ b/chrome/content/zotero/tabs.js
@@ -128,8 +128,6 @@ var Zotero_Tabs = new function () {
return;
}
document.title = (tab.title.length ? tab.title + ' - ' : '') + Zotero.appName;
- // Hide any tab `title` tooltips that might be open
- window.Zotero_Tooltip.stop();
if (this.isTabsMenuVisible()) {
this.refreshTabsMenuList();
if (document.activeElement.id !== "zotero-tabs-menu-filter") {
@@ -639,7 +637,6 @@ var Zotero_Tabs = new function () {
this._openMenu = function (x, y, id) {
var { tab, tabIndex } = this._getTab(id);
- window.Zotero_Tooltip.stop();
let menuitem;
let popup = document.createXULElement('menupopup');
document.querySelector('popupset').appendChild(popup);
@@ -851,7 +848,7 @@ var Zotero_Tabs = new function () {
tabName.setAttribute('class', 'zotero-tabs-menu-entry title');
tabName.setAttribute('tabindex', `${index++}`);
tabName.setAttribute('aria-label', tab.title);
- tabName.setAttribute('tooltiptext', tab.title);
+ tabName.setAttribute('title', tab.title);
// Cross button to close a tab
let closeButton = document.createElement('div');
@@ -907,25 +904,6 @@ var Zotero_Tabs = new function () {
this.tabsMenuPanel.hidePopup();
this.select(tab.id);
});
- // Manually handle hover effects as a workaround for a likely mozilla bug that
- // keeps :hover at the location of dragstart after drop.
- for (let node of [tabName, closeButton]) {
- node.addEventListener('mouseenter', (_) => {
- if (this._tabsMenuIgnoreMouseover) {
- return;
- }
- node.classList.add('hover');
- // If the mouse moves over a tab, send focus back to the panel
- // to avoid having two fields that appear greyed out.
- if (document.activeElement.id !== "zotero-tabs-menu-filter") {
- this._tabsMenuFocusedIndex = -1;
- this.tabsMenuPanel.focus();
- }
- });
- node.addEventListener('mouseleave', (_) => {
- node.classList.remove('hover');
- });
- }
row.appendChild(tabName);
row.appendChild(closeButton);
diff --git a/chrome/content/zotero/zoteroPane.xhtml b/chrome/content/zotero/zoteroPane.xhtml
index 93c6a1d316..5720f8ff89 100644
--- a/chrome/content/zotero/zoteroPane.xhtml
+++ b/chrome/content/zotero/zoteroPane.xhtml
@@ -85,7 +85,6 @@
Services.scriptloader.loadSubScript("chrome://zotero/content/lookup.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/locateMenu.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/menuAccessKey.js", this);
- Services.scriptloader.loadSubScript("chrome://zotero/content/tooltip.js", this);
Services.scriptloader.loadSubScript("chrome://zotero/content/containers/tagSelectorContainer.js", this);
@@ -837,7 +836,7 @@
tabindex="0"
data-l10n-id="zotero-tabs-menu-filter"
/>
-
+
@@ -876,6 +875,7 @@
+
&zotero.general.loading;
@@ -907,7 +907,6 @@
-
-
diff --git a/chrome/locale/en-US/zotero/zotero.ftl b/chrome/locale/en-US/zotero/zotero.ftl
index f033b24e11..0104afd6b2 100644
--- a/chrome/locale/en-US/zotero/zotero.ftl
+++ b/chrome/locale/en-US/zotero/zotero.ftl
@@ -52,7 +52,7 @@ zotero-collections-search-btn =
zotero-tabs-menu-filter =
.placeholder = Search Tabs
zotero-tabs-menu-close-button =
- .tooltiptext = Close Tab
+ .title = Close Tab
toolbar-add-attachment =
.tooltiptext = { add-attachment }
diff --git a/scss/components/_tabsMenu.scss b/scss/components/_tabsMenu.scss
index 43966c088c..dd2f653b32 100644
--- a/scss/components/_tabsMenu.scss
+++ b/scss/components/_tabsMenu.scss
@@ -78,10 +78,7 @@
}
}
- // Using .hover class instead of pseudo element to avoid the
- // hover effect from sticking around after drag-and-drop
- // https://bugs.webkit.org/show_bug.cgi?id=134555
- &.hover {
+ &:hover {
background-color: var(--fill-quinary) !important;
}
&:active {