Add generic menu for all unfocused editable-texts

This commit is contained in:
Abe Jellinek 2024-01-29 15:07:14 -05:00 committed by Dan Stillman
parent af79e9c405
commit 6b1940cebb
4 changed files with 96 additions and 54 deletions

View file

@ -101,16 +101,16 @@ function goBuildEditContextMenu() {
MozXULElement.parseXULToFragment(`
<popupset>
<menupopup id="textbox-contextmenu" class="textbox-contextmenu">
<menuitem data-l10n-id="text-action-undo" command="cmd_undo"></menuitem>
<menuitem data-l10n-id="text-action-redo" command="cmd_redo"></menuitem>
<menuitem data-l10n-id="text-action-undo" command="cmd_undo" data-action="undo"></menuitem>
<menuitem data-l10n-id="text-action-redo" command="cmd_redo" data-action="redo"></menuitem>
<menuseparator></menuseparator>
<menuitem data-l10n-id="text-action-cut" command="cmd_cut"></menuitem>
<menuitem data-l10n-id="text-action-copy" command="cmd_copy"></menuitem>
<menuitem data-l10n-id="text-action-paste" command="cmd_paste"></menuitem>
<menuitem data-l10n-id="text-action-delete" command="cmd_delete"></menuitem>
<menuitem data-l10n-id="text-action-select-all" command="cmd_selectAll"></menuitem>
<menuitem data-l10n-id="text-action-cut" command="cmd_cut" data-action="cut"></menuitem>
<menuitem data-l10n-id="text-action-copy" command="cmd_copy" data-action="copy"></menuitem>
<menuitem data-l10n-id="text-action-paste" command="cmd_paste" data-action="paste"></menuitem>
<menuitem data-l10n-id="text-action-delete" command="cmd_delete" data-action="delete"></menuitem>
<menuitem data-l10n-id="text-action-select-all" command="cmd_selectAll" data-action="selectAll"></menuitem>
<menuseparator></menuseparator>
<menuitem data-l10n-id="menu-edit-bidi-switch-text-direction" command="cmd_switchTextDirection"></menuitem>
<menuitem data-l10n-id="menu-edit-bidi-switch-text-direction" command="cmd_switchTextDirection" data-action="switchTextDirection"></menuitem>
</menupopup>
</popupset>
`)

View file

@ -224,12 +224,6 @@
event.preventDefault();
}
});
input.addEventListener('contextmenu', (event) => {
// Prevent the text editing context menu from opening when unfocused
if (document.activeElement !== this._input) {
event.preventDefault();
}
});
let focused = false;
let selectionStart = this._input?.selectionStart;
@ -298,4 +292,33 @@
}
}
customElements.define("editable-text", EditableText);
document.addEventListener('contextmenu', (event) => {
if (event.defaultPrevented
|| !event.target.closest('editable-text')
|| document.activeElement && event.target.contains(document.activeElement)) {
return;
}
event.preventDefault();
let editableText = event.target.closest('editable-text');
let menupopup = document.getElementById('zotero-editable-text-menu');
if (!menupopup) {
menupopup = document.createXULElement('menupopup');
menupopup.id = 'zotero-editable-text-menu';
let popupset = document.querySelector('popupset');
if (!popupset) {
popupset = document.createXULElement('popupset');
document.documentElement.append(popupset);
}
popupset.append(menupopup);
}
menupopup.addEventListener('popupshowing', () => {
Zotero.Utilities.Internal.updateEditContextMenu(menupopup, editableText);
}, { once: true });
menupopup.openPopupAtScreen(event.screenX + 1, event.screenY + 1, true);
});
}

View file

@ -95,7 +95,7 @@
<div id="retraction-hide"><button/></div>
</div>
</div>
<div id="info-table"> </div>
<div id="info-table"></div>
</div>
</html:div>
</collapsible-section>
@ -207,9 +207,24 @@
event => this.capitalizeCreatorName(event));
this._linkMenu.addEventListener('popupshowing', () => {
let disabled = !this._linkMenu.dataset.link;
this._id('zotero-link-menu-view-online').disabled = disabled;
this._id('zotero-link-menu-copy').disabled = disabled;
let menu = this._linkMenu;
let link = menu.dataset.link;
let val = menu.dataset.val;
let viewOnline = this._id('zotero-link-menu-view-online');
let copy = this._id('zotero-link-menu-copy');
viewOnline.disabled = !link;
copy.disabled = !link;
copy.hidden = link === val;
let existingCopyMenuitem = menu.querySelector('menuitem[data-action="copy"]');
if (existingCopyMenuitem) {
existingCopyMenuitem.after(copy);
}
else {
menu.append(copy);
}
});
this._id('zotero-link-menu-view-online').addEventListener(
@ -535,12 +550,11 @@
}
}
for (let i = 0; i < fieldNames.length; i++) {
var fieldName = fieldNames[i];
for (let fieldName of fieldNames) {
if (this._ignoreFields.includes(fieldName)) {
continue;
}
var val = '';
let val = '';
if (fieldName) {
var fieldID = Zotero.ItemFields.getID(fieldName);
@ -604,13 +618,13 @@
}
let openLinkButton;
let link = val;
let addContextMenu = false;
let addLinkContextMenu = false;
// TEMP - NSF (homepage)
if ((fieldName == 'url' || fieldName == 'homepage')
// Only make plausible HTTP URLs clickable
&& Zotero.Utilities.isHTTPURL(val, true)) {
openLinkButton = this.createOpenLinkIcon(val);
addContextMenu = true;
addLinkContextMenu = true;
}
else if (fieldName == 'DOI' && val && typeof val == 'string') {
// Pull out DOI, in case there's a prefix
@ -625,7 +639,7 @@
.replace(/"/g, '%22');
openLinkButton = this.createOpenLinkIcon(doi);
link = doi;
addContextMenu = true;
addLinkContextMenu = true;
}
}
let rowData = document.createElement('div');
@ -634,9 +648,10 @@
if (openLinkButton) {
rowData.appendChild(openLinkButton);
}
if (addContextMenu) {
if (addLinkContextMenu) {
rowData.oncontextmenu = (event) => {
this._linkMenu.dataset.link = link;
this._linkMenu.dataset.val = val;
document.popupNode = rowLabel.parentElement;
let menupopup = this._id('zotero-link-menu');
@ -2405,7 +2420,9 @@
}
handlePopupOpening(event, popup) {
event.preventDefault();
event.stopPropagation();
let isRightClick = event.type == 'contextmenu';
if (!isRightClick) {
event.target.style.visibility = "visible";

View file

@ -2334,10 +2334,9 @@ Zotero.Utilities.Internal = {
win.goUpdateGlobalEditMenuItems(true);
for (let menuitem of Array.from(menupopup.children)) {
if (!menuitem.hasAttribute('data-edit-menu-item')) {
break;
if (menuitem.hasAttribute('data-edit-menu-item')) {
menuitem.remove();
}
menuitem.remove();
}
if (target && target.tagName === 'editable-text') {
@ -2345,11 +2344,9 @@ Zotero.Utilities.Internal = {
}
let targetInput = target?.closest('input, textarea');
let showEdit = targetInput
&& !targetInput.readOnly
&& targetInput.ownerDocument.activeElement
&& targetInput.ownerDocument.activeElement === targetInput;
let showCopyField = targetInput && !showEdit;
let showPasteField = showCopyField && !targetInput.readOnly;
let disablePasteField = targetInput && targetInput.readOnly;
let editMenuItems = [];
if (showEdit) {
@ -2360,29 +2357,34 @@ Zotero.Utilities.Internal = {
editMenuItems.push(menuitem);
}
}
else {
if (showCopyField) {
let copyMenuitem = win.document.createXULElement('menuitem');
copyMenuitem.setAttribute('data-l10n-id', 'text-action-copy');
copyMenuitem.setAttribute('data-edit-menu-item', 'true');
copyMenuitem.disabled = !targetInput.value;
copyMenuitem.addEventListener('command', () => {
Zotero.Utilities.Internal.copyTextToClipboard(targetInput.value);
});
editMenuItems.push(copyMenuitem);
}
if (showPasteField) {
let pasteMenuitem = win.document.createXULElement('menuitem');
pasteMenuitem.setAttribute('data-l10n-id', 'text-action-paste');
pasteMenuitem.setAttribute('data-edit-menu-item', 'true');
pasteMenuitem.disabled = win.document.getElementById('cmd_paste')?.disabled;
pasteMenuitem.addEventListener('command', () => {
targetInput.focus();
targetInput.value = Zotero.Utilities.Internal.getClipboard('text/unicode') || '';
targetInput.dispatchEvent(new Event('input'));
});
editMenuItems.push(pasteMenuitem);
}
else if (targetInput) {
let targetInputWeak = new WeakRef(targetInput);
let copyMenuitem = win.document.createXULElement('menuitem');
copyMenuitem.setAttribute('data-l10n-id', 'text-action-copy');
copyMenuitem.setAttribute('data-edit-menu-item', 'true');
copyMenuitem.setAttribute('data-action', 'copy');
copyMenuitem.disabled = !targetInput.value;
copyMenuitem.addEventListener('command', () => {
let targetInput = targetInputWeak.deref();
if (!targetInput) return;
Zotero.Utilities.Internal.copyTextToClipboard(targetInput.value);
});
editMenuItems.push(copyMenuitem);
let pasteMenuitem = win.document.createXULElement('menuitem');
pasteMenuitem.setAttribute('data-l10n-id', 'text-action-paste');
pasteMenuitem.setAttribute('data-edit-menu-item', 'true');
pasteMenuitem.setAttribute('data-action', 'paste');
pasteMenuitem.disabled = disablePasteField || win.document.getElementById('cmd_paste')?.disabled;
pasteMenuitem.addEventListener('command', () => {
let targetInput = targetInputWeak.deref();
if (!targetInput) return;
targetInput.focus();
targetInput.value = Zotero.Utilities.Internal.getClipboard('text/unicode') || '';
targetInput.dispatchEvent(new Event('input'));
});
editMenuItems.push(pasteMenuitem);
}
if (editMenuItems.length) {
if (menupopup.childElementCount) {