: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
editorType.initialize(l10n, uiManager);
uiManager.registerEditorTypes(editorTypes);
this.#uiManager = uiManager;
this.pageIndex = pageIndex;
this.#accessibilityManager = accessibilityManager;
this.#annotationLayer = annotationLayer;
this.viewport = viewport;
this.#textLayer = textLayer;
this.drawLayer = drawLayer;
this.#uiManager.addLayer(this);
return this.#editors.size === 0;
return this.isEmpty && this.#uiManager.getMode() === AnnotationEditorType.NONE;
this.#uiManager.updateToolbar(mode);
updateMode(mode = this.#uiManager.getMode()) {
case AnnotationEditorType.NONE:
this.disableTextSelection();
this.togglePointerEvents(false);
this.toggleAnnotationLayerPointerEvents(true);
case AnnotationEditorType.INK:
this.addInkEditorIfNeeded(false);
this.disableTextSelection();
this.togglePointerEvents(true);
case AnnotationEditorType.HIGHLIGHT:
this.enableTextSelection();
this.togglePointerEvents(false);
this.disableTextSelection();
this.togglePointerEvents(true);
this.toggleAnnotationLayerPointerEvents(false);
for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {
classList.toggle(`${editorType._type}Editing`, mode === editorType._editorType);
hasTextLayer(textLayer) {
return textLayer === this.#textLayer?.div;
addInkEditorIfNeeded(isCommitting) {
if (this.#uiManager.getMode() !== AnnotationEditorType.INK) {
for (const editor of this.#editors.values()) {
editor.setInBackground();
const editor = this.createAndAddNewEditor({
editor.setInBackground();
setEditingState(isEditing) {
this.#uiManager.setEditingState(isEditing);
this.#uiManager.addCommands(params);
togglePointerEvents(enabled = false) {
this.div.classList.toggle("disabled", !enabled);
toggleAnnotationLayerPointerEvents(enabled = false) {
this.#annotationLayer?.div.classList.toggle("disabled", !enabled);
this.togglePointerEvents(true);
const annotationElementIds = new Set();
for (const editor of this.#editors.values()) {
if (editor.annotationElementId) {
this.#uiManager.removeChangedExistingAnnotation(editor);
annotationElementIds.add(editor.annotationElementId);
if (!this.#annotationLayer) {
const editables = this.#annotationLayer.getEditableAnnotations();
for (const editable of editables) {
if (this.#uiManager.isDeletedAnnotationElement(editable.data.id)) {
if (annotationElementIds.has(editable.data.id)) {
const editor = this.deserialize(editable);
this.addOrRebuild(editor);
this.#isDisabling = true;
this.togglePointerEvents(false);
const changedAnnotations = new Map();
const resetAnnotations = new Map();
for (const editor of this.#editors.values()) {
if (!editor.annotationElementId) {
if (editor.serialize() !== null) {
changedAnnotations.set(editor.annotationElementId, editor);
resetAnnotations.set(editor.annotationElementId, editor);
this.getEditableAnnotation(editor.annotationElementId)?.show();
if (this.#annotationLayer) {
const editables = this.#annotationLayer.getEditableAnnotations();
for (const editable of editables) {
if (this.#uiManager.isDeletedAnnotationElement(id)) {
let editor = resetAnnotations.get(id);
editor.resetAnnotationElement(editable);
editor = changedAnnotations.get(id);
this.#uiManager.addChangedExistingAnnotation(editor);
editor.renderAnnotationElement(editable);
for (const editorType of AnnotationEditorLayer.#editorTypes.values()) {
classList.remove(`${editorType._type}Editing`);
this.disableTextSelection();
this.toggleAnnotationLayerPointerEvents(true);
this.#isDisabling = false;
getEditableAnnotation(id) {
return this.#annotationLayer?.getEditableAnnotation(id) || null;
setActiveEditor(editor) {
const currentActive = this.#uiManager.getActive();
if (currentActive === editor) {
this.#uiManager.setActiveEditor(editor);
if (this.#textLayer?.div && !this.#boundTextLayerPointerDown) {
this.#boundTextLayerPointerDown = this.#textLayerPointerDown.bind(this);
this.#textLayer.div.addEventListener("pointerdown", this.#boundTextLayerPointerDown);
this.#textLayer.div.classList.add("highlighting");
if (this.#textLayer?.div && this.#boundTextLayerPointerDown) {
this.#textLayer.div.removeEventListener("pointerdown", this.#boundTextLayerPointerDown);
this.#boundTextLayerPointerDown = null;
this.#textLayer.div.classList.remove("highlighting");
#textLayerPointerDown(event) {
this.#uiManager.unselectAll();
if (event.target === this.#textLayer.div) {
} = util_FeatureTest.platform;
if (event.button !== 0 || event.ctrlKey && isMac) {
this.#uiManager.showAllEditors("highlight", true, true);
this.#textLayer.div.classList.add("free");
HighlightEditor.startHighlighting(this, this.#uiManager.direction === "ltr", event);
this.#textLayer.div.addEventListener("pointerup", () => {
this.#textLayer.div.classList.remove("free");
if (this.#boundPointerdown) {
this.#boundPointerdown = this.pointerdown.bind(this);
this.#boundPointerup = this.pointerup.bind(this);
this.div.addEventListener("pointerdown", this.#boundPointerdown);
this.div.addEventListener("pointerup", this.#boundPointerup);
if (!this.#boundPointerdown) {
this.div.removeEventListener("pointerdown", this.#boundPointerdown);
this.div.removeEventListener("pointerup", this.#boundPointerup);
this.#boundPointerdown = null;
this.#boundPointerup = null;
this.#editors.set(editor.id, editor);
if (annotationElementId && this.#uiManager.isDeletedAnnotationElement(annotationElementId)) {
this.#uiManager.removeDeletedAnnotationElement(editor);
this.#editors.delete(editor.id);
this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);
if (!this.#isDisabling && editor.annotationElementId) {
this.#uiManager.addDeletedAnnotationElement(editor);
this.#uiManager.removeEditor(editor);
editor.isAttachedToDOM = false;
if (!this.#isCleaningUp) {
this.addInkEditorIfNeeded(false);
if (editor.parent === this) {
if (editor.parent && editor.annotationElementId) {
this.#uiManager.addDeletedAnnotationElement(editor.annotationElementId);
AnnotationEditor.deleteAnnotationElement(editor);
editor.annotationElementId = null;
editor.parent?.detach(editor);
if (editor.div && editor.isAttachedToDOM) {
this.div.append(editor.div);
if (editor.parent === this && editor.isAttachedToDOM) {
this.changeParent(editor);
this.#uiManager.addEditor(editor);
if (!editor.isAttachedToDOM) {
const div = editor.render();
editor.isAttachedToDOM = true;
editor.fixAndSetPosition();
this.#uiManager.addToAnnotationStorage(editor);
editor._reportTelemetry(editor.telemetryInitialData);
moveEditorInDOM(editor) {
if (!editor.isAttachedToDOM) {
if (editor.div.contains(activeElement) && !this.#editorFocusTimeoutId) {
editor._focusEventsAllowed = false;
this.#editorFocusTimeoutId = setTimeout(() => {
this.#editorFocusTimeoutId = null;
if (!editor.div.contains(document.activeElement)) {
editor.div.addEventListener("focusin", () => {
editor._focusEventsAllowed = true;
editor._focusEventsAllowed = true;
editor._structTreeParentId = this.#accessibilityManager?.moveElementInDOM(this.div, editor.div, editor.contentDiv, true);
if (editor.needsToBeRebuilt()) {
addUndoableEditor(editor) {
const cmd = () => editor._uiManager.rebuild(editor);
return this.#uiManager.getId();
get #currentEditorType() {
return AnnotationEditorLayer.#editorTypes.get(this.#uiManager.getMode());
#createNewEditor(params) {
const editorType = this.#currentEditorType;
return editorType ? new editorType.prototype.constructor(params) : null;
canCreateNewEmptyEditor() {
return this.#currentEditorType?.canCreateNewEmptyEditor();
pasteEditor(mode, params) {
this.#uiManager.updateToolbar(mode);
this.#uiManager.updateMode(mode);
} = this.#getCenterPoint();
const id = this.getNextId();
const editor = this.#createNewEditor({
uiManager: this.#uiManager,
return AnnotationEditorLayer.#editorTypes.get(data.annotationType ?? data.annotationEditorType)?.deserialize(data, this, this.#uiManager) || null;
createAndAddNewEditor(event, isCentered, data = {}) {
const id = this.getNextId();
const editor = this.#createNewEditor({
uiManager: this.#uiManager,
} = this.div.getBoundingClientRect();
const tlX = Math.max(0, x);
const tlY = Math.max(0, y);
const brX = Math.min(window.innerWidth, x + width);
const brY = Math.min(window.innerHeight, y + height);
const centerX = (tlX + brX) / 2 - x;
const centerY = (tlY + brY) / 2 - y;
const [offsetX, offsetY] = this.viewport.rotation % 180 === 0 ? [centerX, centerY] : [centerY, centerX];
this.createAndAddNewEditor(this.#getCenterPoint(), true);
this.#uiManager.setSelected(editor);
this.#uiManager.toggleSelected(editor);
return this.#uiManager.isSelected(editor);
this.#uiManager.unselect(editor);
} = util_FeatureTest.platform;
if (event.button !== 0 || event.ctrlKey && isMac) {
if (event.target !== this.div) {
if (!this.#hadPointerDown) {
this.#hadPointerDown = false;
if (this.#uiManager.getMode() === AnnotationEditorType.STAMP) {
this.#uiManager.unselectAll();
this.createAndAddNewEditor(event, false);
if (this.#uiManager.getMode() === AnnotationEditorType.HIGHLIGHT) {
this.enableTextSelection();
if (this.#hadPointerDown) {
this.#hadPointerDown = false;
} = util_FeatureTest.platform;
if (event.button !== 0 || event.ctrlKey && isMac) {
if (event.target !== this.div) {
this.#hadPointerDown = true;
const editor = this.#uiManager.getActive();
this.#allowClick = !editor || editor.isEmpty();
findNewParent(editor, x, y) {
const layer = this.#uiManager.findParent(x, y);
if (layer === null || layer === this) {
layer.changeParent(editor);
if (this.#uiManager.getActive()?.parent === this) {
this.#uiManager.commitOrRemove();
this.#uiManager.setActiveEditor(null);
if (this.#editorFocusTimeoutId) {
clearTimeout(this.#editorFocusTimeoutId);
this.#editorFocusTimeoutId = null;
for (const editor of this.#editors.values()) {
this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);