1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-22 16:18:08 +02:00

[Editor] Remove the various listeners when destroying the editor manager

This commit is contained in:
Calixte Denizet 2024-06-18 21:05:26 +02:00
parent 9dbe4c246b
commit 390afcb685
10 changed files with 244 additions and 129 deletions

View file

@ -49,20 +49,27 @@ class AltText {
altText.textContent = msg;
altText.setAttribute("aria-label", msg);
altText.tabIndex = "0";
altText.addEventListener("contextmenu", noContextMenu);
altText.addEventListener("pointerdown", event => event.stopPropagation());
const signal = this.#editor._uiManager._signal;
altText.addEventListener("contextmenu", noContextMenu, { signal });
altText.addEventListener("pointerdown", event => event.stopPropagation(), {
signal,
});
const onClick = event => {
event.preventDefault();
this.#editor._uiManager.editAltText(this.#editor);
};
altText.addEventListener("click", onClick, { capture: true });
altText.addEventListener("keydown", event => {
if (event.target === altText && event.key === "Enter") {
this.#altTextWasFromKeyBoard = true;
onClick(event);
}
});
altText.addEventListener("click", onClick, { capture: true, signal });
altText.addEventListener(
"keydown",
event => {
if (event.target === altText && event.key === "Enter") {
this.#altTextWasFromKeyBoard = true;
onClick(event);
}
},
{ signal }
);
await this.#setState();
return altText;
@ -142,22 +149,39 @@ class AltText {
button.setAttribute("aria-describedby", id);
const DELAY_TO_SHOW_TOOLTIP = 100;
button.addEventListener("mouseenter", () => {
this.#altTextTooltipTimeout = setTimeout(() => {
this.#altTextTooltipTimeout = null;
this.#altTextTooltip.classList.add("show");
this.#editor._reportTelemetry({
action: "alt_text_tooltip",
});
}, DELAY_TO_SHOW_TOOLTIP);
});
button.addEventListener("mouseleave", () => {
if (this.#altTextTooltipTimeout) {
const signal = this.#editor._uiManager._signal;
signal.addEventListener(
"abort",
() => {
clearTimeout(this.#altTextTooltipTimeout);
this.#altTextTooltipTimeout = null;
}
this.#altTextTooltip?.classList.remove("show");
});
},
{ once: true }
);
button.addEventListener(
"mouseenter",
() => {
this.#altTextTooltipTimeout = setTimeout(() => {
this.#altTextTooltipTimeout = null;
this.#altTextTooltip.classList.add("show");
this.#editor._reportTelemetry({
action: "alt_text_tooltip",
});
}, DELAY_TO_SHOW_TOOLTIP);
},
{ signal }
);
button.addEventListener(
"mouseleave",
() => {
if (this.#altTextTooltipTimeout) {
clearTimeout(this.#altTextTooltipTimeout);
this.#altTextTooltipTimeout = null;
}
this.#altTextTooltip?.classList.remove("show");
},
{ signal }
);
}
tooltip.innerText = this.#altTextDecorative
? await AltText._l10nPromise.get(

View file

@ -365,7 +365,8 @@ class AnnotationEditorLayer {
this.#boundTextLayerPointerDown = this.#textLayerPointerDown.bind(this);
this.#textLayer.div.addEventListener(
"pointerdown",
this.#boundTextLayerPointerDown
this.#boundTextLayerPointerDown,
{ signal: this.#uiManager._signal }
);
this.#textLayer.div.classList.add("highlighting");
}
@ -409,7 +410,7 @@ class AnnotationEditorLayer {
() => {
this.#textLayer.div.classList.remove("free");
},
{ once: true }
{ once: true, signal: this.#uiManager._signal }
);
event.preventDefault();
}
@ -419,10 +420,13 @@ class AnnotationEditorLayer {
if (this.#boundPointerdown) {
return;
}
const signal = this.#uiManager._signal;
this.#boundPointerdown = this.pointerdown.bind(this);
this.#boundPointerup = this.pointerup.bind(this);
this.div.addEventListener("pointerdown", this.#boundPointerdown);
this.div.addEventListener("pointerup", this.#boundPointerup);
this.div.addEventListener("pointerdown", this.#boundPointerdown, {
signal,
});
this.div.addEventListener("pointerup", this.#boundPointerup, { signal });
}
disableClick() {
@ -540,7 +544,7 @@ class AnnotationEditorLayer {
() => {
editor._focusEventsAllowed = true;
},
{ once: true }
{ once: true, signal: this.#uiManager._signal }
);
activeElement.focus();
} else {
@ -596,6 +600,10 @@ class AnnotationEditorLayer {
return AnnotationEditorLayer.#editorTypes.get(this.#uiManager.getMode());
}
get _signal() {
return this.#uiManager._signal;
}
/**
* Create a new editor
* @param {Object} params

View file

@ -89,8 +89,9 @@ class ColorPicker {
button.tabIndex = "0";
button.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-button");
button.setAttribute("aria-haspopup", true);
button.addEventListener("click", this.#openDropdown.bind(this));
button.addEventListener("keydown", this.#boundKeyDown);
const signal = this.#uiManager._signal;
button.addEventListener("click", this.#openDropdown.bind(this), { signal });
button.addEventListener("keydown", this.#boundKeyDown, { signal });
const swatch = (this.#buttonSwatch = document.createElement("span"));
swatch.className = "swatch";
swatch.setAttribute("aria-hidden", true);
@ -109,7 +110,8 @@ class ColorPicker {
#getDropdownRoot() {
const div = document.createElement("div");
div.addEventListener("contextmenu", noContextMenu);
const signal = this.#uiManager._signal;
div.addEventListener("contextmenu", noContextMenu, { signal });
div.className = "dropdown";
div.role = "listbox";
div.setAttribute("aria-multiselectable", false);
@ -127,11 +129,13 @@ class ColorPicker {
swatch.className = "swatch";
swatch.style.backgroundColor = color;
button.setAttribute("aria-selected", color === this.#defaultColor);
button.addEventListener("click", this.#colorSelect.bind(this, color));
button.addEventListener("click", this.#colorSelect.bind(this, color), {
signal,
});
div.append(button);
}
div.addEventListener("keydown", this.#boundKeyDown);
div.addEventListener("keydown", this.#boundKeyDown, { signal });
return div;
}
@ -211,7 +215,9 @@ class ColorPicker {
return;
}
this.#dropdownWasFromKeyboard = event.detail === 0;
window.addEventListener("pointerdown", this.#boundPointerDown);
window.addEventListener("pointerdown", this.#boundPointerDown, {
signal: this.#uiManager._signal,
});
if (this.#dropdown) {
this.#dropdown.classList.remove("hidden");
return;

View file

@ -715,6 +715,7 @@ class AnnotationEditor {
"bottomLeft",
"middleLeft",
];
const signal = this._uiManager._signal;
for (const name of classes) {
const div = document.createElement("div");
this.#resizersDiv.append(div);
@ -722,9 +723,10 @@ class AnnotationEditor {
div.setAttribute("data-resizer-name", name);
div.addEventListener(
"pointerdown",
this.#resizerPointerdown.bind(this, name)
this.#resizerPointerdown.bind(this, name),
{ signal }
);
div.addEventListener("contextmenu", noContextMenu);
div.addEventListener("contextmenu", noContextMenu, { signal });
div.tabIndex = -1;
}
this.div.prepend(this.#resizersDiv);
@ -742,14 +744,15 @@ class AnnotationEditor {
const boundResizerPointermove = this.#resizerPointermove.bind(this, name);
const savedDraggable = this._isDraggable;
this._isDraggable = false;
const pointerMoveOptions = { passive: true, capture: true };
const signal = this._uiManager._signal;
const pointerMoveOptions = { passive: true, capture: true, signal };
this.parent.togglePointerEvents(false);
window.addEventListener(
"pointermove",
boundResizerPointermove,
pointerMoveOptions
);
window.addEventListener("contextmenu", noContextMenu);
window.addEventListener("contextmenu", noContextMenu, { signal });
const savedX = this.x;
const savedY = this.y;
const savedWidth = this.width;
@ -776,10 +779,10 @@ class AnnotationEditor {
this.#addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight);
};
window.addEventListener("pointerup", pointerUpCallback);
window.addEventListener("pointerup", pointerUpCallback, { signal });
// If the user switches to another window (with alt+tab), then we end the
// resize session.
window.addEventListener("blur", pointerUpCallback);
window.addEventListener("blur", pointerUpCallback, { signal });
}
#addResizeToUndoStack(savedX, savedY, savedWidth, savedHeight) {
@ -1027,8 +1030,9 @@ class AnnotationEditor {
this.setInForeground();
this.div.addEventListener("focusin", this.#boundFocusin);
this.div.addEventListener("focusout", this.#boundFocusout);
const signal = this._uiManager._signal;
this.div.addEventListener("focusin", this.#boundFocusin, { signal });
this.div.addEventListener("focusout", this.#boundFocusout, { signal });
const [parentWidth, parentHeight] = this.parentDimensions;
if (this.parentRotation % 180 !== 0) {
@ -1089,9 +1093,10 @@ class AnnotationEditor {
this._uiManager.setUpDragSession();
let pointerMoveOptions, pointerMoveCallback;
const signal = this._uiManager._signal;
if (isSelected) {
this.div.classList.add("moving");
pointerMoveOptions = { passive: true, capture: true };
pointerMoveOptions = { passive: true, capture: true, signal };
this.#prevDragX = event.clientX;
this.#prevDragY = event.clientY;
pointerMoveCallback = e => {
@ -1128,11 +1133,11 @@ class AnnotationEditor {
this.#selectOnPointerEvent(event);
}
};
window.addEventListener("pointerup", pointerUpCallback);
window.addEventListener("pointerup", pointerUpCallback, { signal });
// If the user is using alt+tab during the dragging session, the pointerup
// event could be not fired, but a blur event is fired so we can use it in
// order to interrupt the dragging session.
window.addEventListener("blur", pointerUpCallback);
window.addEventListener("blur", pointerUpCallback, { signal });
}
moveInDOM() {
@ -1284,8 +1289,9 @@ class AnnotationEditor {
* To implement in subclasses.
*/
rebuild() {
this.div?.addEventListener("focusin", this.#boundFocusin);
this.div?.addEventListener("focusout", this.#boundFocusout);
const signal = this._uiManager._signal;
this.div?.addEventListener("focusin", this.#boundFocusin, { signal });
this.div?.addEventListener("focusout", this.#boundFocusout, { signal });
}
/**
@ -1429,12 +1435,15 @@ class AnnotationEditor {
this.#allResizerDivs = Array.from(children);
const boundResizerKeydown = this.#resizerKeydown.bind(this);
const boundResizerBlur = this.#resizerBlur.bind(this);
const signal = this._uiManager._signal;
for (const div of this.#allResizerDivs) {
const name = div.getAttribute("data-resizer-name");
div.setAttribute("role", "spinbutton");
div.addEventListener("keydown", boundResizerKeydown);
div.addEventListener("blur", boundResizerBlur);
div.addEventListener("focus", this.#resizerFocus.bind(this, name));
div.addEventListener("keydown", boundResizerKeydown, { signal });
div.addEventListener("blur", boundResizerBlur, { signal });
div.addEventListener("focus", this.#resizerFocus.bind(this, name), {
signal,
});
AnnotationEditor._l10nPromise
.get(`pdfjs-editor-resizer-label-${name}`)
.then(msg => div.setAttribute("aria-label", msg));

View file

@ -307,11 +307,22 @@ class FreeTextEditor extends AnnotationEditor {
this.editorDiv.contentEditable = true;
this._isDraggable = false;
this.div.removeAttribute("aria-activedescendant");
this.editorDiv.addEventListener("keydown", this.#boundEditorDivKeydown);
this.editorDiv.addEventListener("focus", this.#boundEditorDivFocus);
this.editorDiv.addEventListener("blur", this.#boundEditorDivBlur);
this.editorDiv.addEventListener("input", this.#boundEditorDivInput);
this.editorDiv.addEventListener("paste", this.#boundEditorDivPaste);
const signal = this._uiManager._signal;
this.editorDiv.addEventListener("keydown", this.#boundEditorDivKeydown, {
signal,
});
this.editorDiv.addEventListener("focus", this.#boundEditorDivFocus, {
signal,
});
this.editorDiv.addEventListener("blur", this.#boundEditorDivBlur, {
signal,
});
this.editorDiv.addEventListener("input", this.#boundEditorDivInput, {
signal,
});
this.editorDiv.addEventListener("paste", this.#boundEditorDivPaste, {
signal,
});
}
/** @inheritdoc */

View file

@ -568,7 +568,9 @@ class HighlightEditor extends AnnotationEditor {
if (this.#isFreeHighlight) {
div.classList.add("free");
} else {
this.div.addEventListener("keydown", this.#boundKeydown);
this.div.addEventListener("keydown", this.#boundKeydown, {
signal: this._uiManager._signal,
});
}
const highlightDiv = (this.#highlightDiv = document.createElement("div"));
div.append(highlightDiv);
@ -702,7 +704,8 @@ class HighlightEditor extends AnnotationEditor {
const pointerMove = e => {
this.#highlightMove(parent, e);
};
const pointerDownOptions = { capture: true, passive: false };
const signal = parent._signal;
const pointerDownOptions = { capture: true, passive: false, signal };
const pointerDown = e => {
// Avoid to have undesired clicks during the drawing.
e.preventDefault();
@ -720,12 +723,12 @@ class HighlightEditor extends AnnotationEditor {
window.removeEventListener("contextmenu", noContextMenu);
this.#endHighlight(parent, e);
};
window.addEventListener("blur", pointerUpCallback);
window.addEventListener("pointerup", pointerUpCallback);
window.addEventListener("blur", pointerUpCallback, { signal });
window.addEventListener("pointerup", pointerUpCallback, { signal });
window.addEventListener("pointerdown", pointerDown, pointerDownOptions);
window.addEventListener("contextmenu", noContextMenu);
window.addEventListener("contextmenu", noContextMenu, { signal });
textLayer.addEventListener("pointermove", pointerMove);
textLayer.addEventListener("pointermove", pointerMove, { signal });
this._freeHighlight = new FreeOutliner(
{ x, y },
[layerX, layerY, parentWidth, parentHeight],

View file

@ -261,7 +261,7 @@ class InkEditor extends AnnotationEditor {
this.#canvasContextMenuTimeoutId = null;
}
this.#observer.disconnect();
this.#observer?.disconnect();
this.#observer = null;
super.remove();
@ -296,7 +296,9 @@ class InkEditor extends AnnotationEditor {
super.enableEditMode();
this._isDraggable = false;
this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown);
this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown, {
signal: this._uiManager._signal,
});
}
/** @inheritdoc */
@ -363,10 +365,19 @@ class InkEditor extends AnnotationEditor {
* @param {number} y
*/
#startDrawing(x, y) {
this.canvas.addEventListener("contextmenu", noContextMenu);
this.canvas.addEventListener("pointerleave", this.#boundCanvasPointerleave);
this.canvas.addEventListener("pointermove", this.#boundCanvasPointermove);
this.canvas.addEventListener("pointerup", this.#boundCanvasPointerup);
const signal = this._uiManager._signal;
this.canvas.addEventListener("contextmenu", noContextMenu, { signal });
this.canvas.addEventListener(
"pointerleave",
this.#boundCanvasPointerleave,
{ signal }
);
this.canvas.addEventListener("pointermove", this.#boundCanvasPointermove, {
signal,
});
this.canvas.addEventListener("pointerup", this.#boundCanvasPointerup, {
signal,
});
this.canvas.removeEventListener(
"pointerdown",
this.#boundCanvasPointerdown
@ -706,7 +717,9 @@ class InkEditor extends AnnotationEditor {
this.#boundCanvasPointermove
);
this.canvas.removeEventListener("pointerup", this.#boundCanvasPointerup);
this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown);
this.canvas.addEventListener("pointerdown", this.#boundCanvasPointerdown, {
signal: this._uiManager._signal,
});
// Slight delay to avoid the context menu to appear (it can happen on a long
// tap with a pen).
@ -751,6 +764,14 @@ class InkEditor extends AnnotationEditor {
}
});
this.#observer.observe(this.div);
this._uiManager._signal.addEventListener(
"abort",
() => {
this.#observer?.disconnect();
this.#observer = null;
},
{ once: true }
);
}
/** @inheritdoc */

View file

@ -160,26 +160,35 @@ class StampEditor extends AnnotationEditor {
}
input.type = "file";
input.accept = StampEditor.supportedTypesStr;
const signal = this._uiManager._signal;
this.#bitmapPromise = new Promise(resolve => {
input.addEventListener("change", async () => {
if (!input.files || input.files.length === 0) {
input.addEventListener(
"change",
async () => {
if (!input.files || input.files.length === 0) {
this.remove();
} else {
this._uiManager.enableWaiting(true);
const data = await this._uiManager.imageManager.getFromFile(
input.files[0]
);
this.#getBitmapFetched(data);
}
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
input.remove();
}
resolve();
},
{ signal }
);
input.addEventListener(
"cancel",
() => {
this.remove();
} else {
this._uiManager.enableWaiting(true);
const data = await this._uiManager.imageManager.getFromFile(
input.files[0]
);
this.#getBitmapFetched(data);
}
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
input.remove();
}
resolve();
});
input.addEventListener("cancel", () => {
this.remove();
resolve();
});
resolve();
},
{ signal }
);
}).finally(() => this.#getBitmapDone());
if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("TESTING")) {
input.click();
@ -536,6 +545,14 @@ class StampEditor extends AnnotationEditor {
}
});
this.#observer.observe(this.div);
this._uiManager._signal.addEventListener(
"abort",
() => {
this.#observer?.disconnect();
this.#observer = null;
},
{ once: true }
);
}
/** @inheritdoc */

View file

@ -32,8 +32,11 @@ class EditorToolbar {
const editToolbar = (this.#toolbar = document.createElement("div"));
editToolbar.className = "editToolbar";
editToolbar.setAttribute("role", "toolbar");
editToolbar.addEventListener("contextmenu", noContextMenu);
editToolbar.addEventListener("pointerdown", EditorToolbar.#pointerDown);
const signal = this.#editor._uiManager._signal;
editToolbar.addEventListener("contextmenu", noContextMenu, { signal });
editToolbar.addEventListener("pointerdown", EditorToolbar.#pointerDown, {
signal,
});
const buttons = (this.#buttons = document.createElement("div"));
buttons.className = "buttons";
@ -77,13 +80,16 @@ class EditorToolbar {
// If we're clicking on a button with the keyboard or with
// the mouse, we don't want to trigger any focus events on
// the editor.
const signal = this.#editor._uiManager._signal;
element.addEventListener("focusin", this.#focusIn.bind(this), {
capture: true,
signal,
});
element.addEventListener("focusout", this.#focusOut.bind(this), {
capture: true,
signal,
});
element.addEventListener("contextmenu", noContextMenu);
element.addEventListener("contextmenu", noContextMenu, { signal });
}
hide() {
@ -104,9 +110,13 @@ class EditorToolbar {
`pdfjs-editor-remove-${this.#editor.editorType}-button`
);
this.#addListenersToElement(button);
button.addEventListener("click", e => {
this.#editor._uiManager.delete();
});
button.addEventListener(
"click",
e => {
this.#editor._uiManager.delete();
},
{ signal: this.#editor._uiManager._signal }
);
this.#buttons.append(button);
}
@ -150,7 +160,9 @@ class HighlightToolbar {
const editToolbar = (this.#toolbar = document.createElement("div"));
editToolbar.className = "editToolbar";
editToolbar.setAttribute("role", "toolbar");
editToolbar.addEventListener("contextmenu", noContextMenu);
editToolbar.addEventListener("contextmenu", noContextMenu, {
signal: this.#uiManager._signal,
});
const buttons = (this.#buttons = document.createElement("div"));
buttons.className = "buttons";
@ -207,10 +219,15 @@ class HighlightToolbar {
button.append(span);
span.className = "visuallyHidden";
span.setAttribute("data-l10n-id", "pdfjs-highlight-floating-button-label");
button.addEventListener("contextmenu", noContextMenu);
button.addEventListener("click", () => {
this.#uiManager.highlightSelection("floating_button");
});
const signal = this.#uiManager._signal;
button.addEventListener("contextmenu", noContextMenu, { signal });
button.addEventListener(
"click",
() => {
this.#uiManager.highlightSelection("floating_button");
},
{ signal }
);
this.#buttons.append(button);
}
}

View file

@ -534,6 +534,8 @@ class ColorManager {
* some action like copy/paste, undo/redo, ...
*/
class AnnotationEditorUIManager {
#abortController = new AbortController();
#activeEditor = null;
#allEditors = new Map();
@ -600,10 +602,6 @@ class AnnotationEditorUIManager {
#boundCut = this.cut.bind(this);
#boundDragOver = this.dragOver.bind(this);
#boundDrop = this.drop.bind(this);
#boundPaste = this.paste.bind(this);
#boundKeydown = this.keydown.bind(this);
@ -616,8 +614,6 @@ class AnnotationEditorUIManager {
#boundOnScaleChanging = this.onScaleChanging.bind(this);
#boundSelectionChange = this.#selectionChange.bind(this);
#boundOnRotationChanging = this.onRotationChanging.bind(this);
#previousStates = {
@ -785,6 +781,7 @@ class AnnotationEditorUIManager {
enableHighlightFloatingButton,
mlManager
) {
this._signal = this.#abortController.signal;
this.#container = container;
this.#viewer = viewer;
this.#altTextManager = altTextManager;
@ -820,9 +817,10 @@ class AnnotationEditorUIManager {
}
destroy() {
this.#removeDragAndDropListeners();
this.#removeKeyboardManager();
this.#removeFocusManager();
this.#abortController?.abort();
this.#abortController = null;
this._signal = null;
this._eventBus._off("editingaction", this.#boundOnEditingAction);
this._eventBus._off("pagechanging", this.#boundOnPageChanging);
this._eventBus._off("scalechanging", this.#boundOnScaleChanging);
@ -847,7 +845,6 @@ class AnnotationEditorUIManager {
clearTimeout(this.#translationTimeoutId);
this.#translationTimeoutId = null;
}
this.#removeSelectionListener();
}
async mlGuess(data) {
@ -1084,6 +1081,7 @@ class AnnotationEditorUIManager {
this.#highlightWhenShiftUp = this.isShiftKeyDown;
if (!this.isShiftKeyDown) {
const signal = this._signal;
const pointerup = e => {
if (e.type === "pointerup" && e.button !== 0) {
// Do nothing on right click.
@ -1095,8 +1093,8 @@ class AnnotationEditorUIManager {
this.#onSelectEnd("main_toolbar");
}
};
window.addEventListener("pointerup", pointerup);
window.addEventListener("blur", pointerup);
window.addEventListener("pointerup", pointerup, { signal });
window.addEventListener("blur", pointerup, { signal });
}
}
@ -1109,16 +1107,19 @@ class AnnotationEditorUIManager {
}
#addSelectionListener() {
document.addEventListener("selectionchange", this.#boundSelectionChange);
}
#removeSelectionListener() {
document.removeEventListener("selectionchange", this.#boundSelectionChange);
document.addEventListener(
"selectionchange",
this.#selectionChange.bind(this),
{
signal: this._signal,
}
);
}
#addFocusManager() {
window.addEventListener("focus", this.#boundFocus);
window.addEventListener("blur", this.#boundBlur);
const signal = this._signal;
window.addEventListener("focus", this.#boundFocus, { signal });
window.addEventListener("blur", this.#boundBlur, { signal });
}
#removeFocusManager() {
@ -1160,16 +1161,17 @@ class AnnotationEditorUIManager {
() => {
lastEditor._focusEventsAllowed = true;
},
{ once: true }
{ once: true, signal: this._signal }
);
lastActiveElement.focus();
}
#addKeyboardManager() {
const signal = this._signal;
// The keyboard events are caught at the container level in order to be able
// to execute some callbacks even if the current page doesn't have focus.
window.addEventListener("keydown", this.#boundKeydown);
window.addEventListener("keyup", this.#boundKeyup);
window.addEventListener("keydown", this.#boundKeydown, { signal });
window.addEventListener("keyup", this.#boundKeyup, { signal });
}
#removeKeyboardManager() {
@ -1178,9 +1180,10 @@ class AnnotationEditorUIManager {
}
#addCopyPasteListeners() {
document.addEventListener("copy", this.#boundCopy);
document.addEventListener("cut", this.#boundCut);
document.addEventListener("paste", this.#boundPaste);
const signal = this._signal;
document.addEventListener("copy", this.#boundCopy, { signal });
document.addEventListener("cut", this.#boundCut, { signal });
document.addEventListener("paste", this.#boundPaste, { signal });
}
#removeCopyPasteListeners() {
@ -1190,13 +1193,9 @@ class AnnotationEditorUIManager {
}
#addDragAndDropListeners() {
document.addEventListener("dragover", this.#boundDragOver);
document.addEventListener("drop", this.#boundDrop);
}
#removeDragAndDropListeners() {
document.removeEventListener("dragover", this.#boundDragOver);
document.removeEventListener("drop", this.#boundDrop);
const signal = this._signal;
document.addEventListener("dragover", this.dragOver.bind(this), { signal });
document.addEventListener("drop", this.drop.bind(this), { signal });
}
addEditListeners() {