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:
parent
9dbe4c246b
commit
390afcb685
10 changed files with 244 additions and 129 deletions
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue