fx115: fix tabs menu

Fixed visuals and working drag-drop again.

Fx115 made previously used toolbarbuttons act very strange wih drag-drop:
instead of dragging the actual button, the #text node would receive
dragstart event and a single letter would end up being dragged.
During troubleshooting, elements created via document.createXULElement
had this issues while being dragged (or acted oddly in other ways, e.g.
refusing to be dragged at all).

This includes a minor rewrite to use div-s instead of XUL components.
This commit is contained in:
Bogdan Abaev 2024-01-25 13:43:10 -05:00 committed by Dan Stillman
parent 87297f8d29
commit 5f37ae4ab1
3 changed files with 46 additions and 21 deletions

View file

@ -790,9 +790,7 @@ var Zotero_Tabs = new function () {
* @returns <description> with bold substrings of title matching this._tabsMenuFilter
*/
let createTabsMenuLabel = (title) => {
let xhtmlNS = "http://www.w3.org/1999/xhtml";
let desc = document.createXULElement('description');
let desc = document.createElement('label');
let regex = new RegExp(`(${Zotero.Utilities.quotemeta(this._tabsMenuFilter)})`, 'gi');
let matches = title.matchAll(regex);
@ -804,9 +802,12 @@ var Zotero_Tabs = new function () {
desc.appendChild(document.createTextNode(title.substring(lastIndex, match.index)));
}
// Add matched text wrapped in <b>
let b = document.createElementNS(xhtmlNS, 'b');
b.textContent = match[0];
desc.appendChild(b);
if (match[0]) {
let b = document.createElement('b');
b.textContent = match[0];
desc.appendChild(b);
}
lastIndex = match.index + match[0].length;
}
@ -839,12 +840,14 @@ var Zotero_Tabs = new function () {
continue;
}
// Top-level entry of the opened tabs array
let row = document.createXULElement('toolbaritem');
let row = document.createElement('div');
let rowIndex = this._tabs.findIndex(x => x.id === tab.id);
row.classList = "row";
row.setAttribute("index", rowIndex);
row.setAttribute("draggable", true);
// Title of the tab
let tabName = document.createXULElement('toolbarbutton');
let tabName = document.createElement('div');
tabName.setAttribute('flex', '1');
tabName.setAttribute('class', 'zotero-tabs-menu-entry title');
tabName.setAttribute('tabindex', `${index++}`);
@ -852,10 +855,13 @@ var Zotero_Tabs = new function () {
tabName.setAttribute('tooltiptext', tab.title);
// Cross button to close a tab
let closeButton = document.createXULElement('toolbarbutton');
closeButton.setAttribute('class', 'zotero-tabs-menu-entry zotero-clicky-cross close');
let closeButton = document.createElement('div');
closeButton.className = "zotero-tabs-menu-entry close";
let closeIcon = document.createElement('span');
closeIcon.setAttribute('class', 'icon icon-css icon-x-8 icon-16');
closeButton.setAttribute('data-l10n-id', 'zotero-tabs-menu-close-button');
closeButton.addEventListener("command", () => {
closeButton.appendChild(closeIcon);
closeButton.addEventListener("click", () => {
// Keep the focus on the cross at the same spot
if (this._tabsMenuFocusedIndex == this.tabsMenuList.childElementCount * 2) {
this._tabsMenuFocusedIndex = Math.max(this._tabsMenuFocusedIndex - 2, 0);
@ -866,7 +872,6 @@ var Zotero_Tabs = new function () {
// Library tab has no close button
if (tab.id == "zotero-pane") {
closeButton.hidden = true;
closeButton.disabled = true;
}
closeButton.setAttribute('tabindex', `${index++}`);
@ -892,7 +897,6 @@ var Zotero_Tabs = new function () {
tabName.appendChild(span);
// Actual label with bolded substrings matching the filter
let tabLabel = createTabsMenuLabel(tab.title, this._tabsMenuFilter);
tabLabel.setAttribute('flex', 1);
tabName.appendChild(tabLabel);
// Selected tab is bold
@ -900,7 +904,7 @@ var Zotero_Tabs = new function () {
tabName.classList.add('selected');
}
// Onclick, go to selected tab + close popup
tabName.addEventListener("command", () => {
tabName.addEventListener("click", () => {
this.tabsMenuPanel.hidePopup();
this.select(tab.id);
});
@ -1068,8 +1072,8 @@ var Zotero_Tabs = new function () {
}
moveTabIndex();
let candidate = this.tabsMenuList.parentElement.querySelector(`[tabindex="${tabindex}"]`);
// If the candidate is disabled (e.g. close button of library tab), skip it
if (candidate && candidate.disabled) {
// If the candidate is hidden (e.g. close button of library tab), skip it
if (candidate && candidate.hidden) {
moveTabIndex();
}
focusTabsMenuEntry(tabindex);
@ -1116,7 +1120,7 @@ var Zotero_Tabs = new function () {
}
focusTabsMenuEntry(tabindex);
}
else if (event.key == "Enter") {
else if (["Enter", " "].includes(event.key)) {
event.preventDefault();
if (event.target.id == "zotero-tabs-menu-filter") {
focusTabsMenuEntry(1);

View file

@ -837,7 +837,7 @@
onkeydown="Zotero_Tabs.handleTabsMenuKeyPress(event)"
tabindex="-1"
>
<vbox width="350" id="zotero-tabs-menu-wrapper">
<vbox id="zotero-tabs-menu-wrapper">
<html:input id="zotero-tabs-menu-filter"
oninput="Zotero_Tabs.handleTabsMenuFilterInput(event, this)"
onfocus="Zotero_Tabs.resetFocusIndex()"

View file

@ -4,10 +4,11 @@
}
#zotero-tabs-menu-wrapper {
width: 350px;
background: var(--material-sidepane);
padding: 7px;
border-radius: 5px;
--width-focus-border: 3px;
--width-focus-border: 2px;
}
#zotero-tabs-menu-filter {
@ -26,6 +27,11 @@
appearance: none;
margin: 0;
.row {
display: flex;
padding-inline-start: 4px;
}
.zotero-tabs-menu-entry {
@include focus-ring;
border-radius: 6px;
@ -33,15 +39,26 @@
margin: 0;
&.close {
width: 22px;
// Center the icon within the larger box
display: flex;
justify-content: center;
align-items: center;
&[hidden] {
visibility: hidden;
}
}
&.title {
padding: 0;
padding-inline-start: 6px;
color: unset;
// Align label with the icon
display: flex;
align-items: center;
width: 100%;
&.selected {
font-weight: 600;
}
description {
label {
overflow: hidden;
// override default description margins
margin-bottom: 0;
@ -50,10 +67,14 @@
white-space: nowrap;
min-width: 280px;
text-overflow: ellipsis;
// Fx115: make label have the right width
max-width: 280px;
display: inline-block;
}
.tab-icon {
width: 16px;
height: 16px;
margin-inline-end: 4px;
}
}