[Editor] Remove a popup from the DOM when it's deleted
This commit is contained in:
parent
2e0f1ec515
commit
b07914843b
@ -2125,6 +2125,8 @@ class PopupElement {
|
|||||||
|
|
||||||
#popup = null;
|
#popup = null;
|
||||||
|
|
||||||
|
#popupAbortController = null;
|
||||||
|
|
||||||
#position = null;
|
#position = null;
|
||||||
|
|
||||||
#rect = null;
|
#rect = null;
|
||||||
@ -2166,18 +2168,7 @@ class PopupElement {
|
|||||||
this.#dateObj = PDFDateString.toDateObject(modificationDate);
|
this.#dateObj = PDFDateString.toDateObject(modificationDate);
|
||||||
|
|
||||||
this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());
|
this.trigger = elements.flatMap(e => e.getElementsToTriggerPopup());
|
||||||
// Attach the event listeners to the trigger element.
|
this.#addEventListeners();
|
||||||
for (const element of this.trigger) {
|
|
||||||
element.addEventListener("click", this.#boundToggle);
|
|
||||||
element.addEventListener("mouseenter", this.#boundShow);
|
|
||||||
element.addEventListener("mouseleave", this.#boundHide);
|
|
||||||
element.classList.add("popupTriggerArea");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach the event listener to toggle the popup with the keyboard.
|
|
||||||
for (const element of elements) {
|
|
||||||
element.container?.addEventListener("keydown", this.#boundKeyDown);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#container.hidden = true;
|
this.#container.hidden = true;
|
||||||
if (open) {
|
if (open) {
|
||||||
@ -2195,6 +2186,29 @@ class PopupElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#addEventListeners() {
|
||||||
|
if (this.#popupAbortController) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#popupAbortController = new AbortController();
|
||||||
|
const { signal } = this.#popupAbortController;
|
||||||
|
|
||||||
|
// Attach the event listeners to the trigger element.
|
||||||
|
for (const element of this.trigger) {
|
||||||
|
element.addEventListener("click", this.#boundToggle, { signal });
|
||||||
|
element.addEventListener("mouseenter", this.#boundShow, { signal });
|
||||||
|
element.addEventListener("mouseleave", this.#boundHide, { signal });
|
||||||
|
element.classList.add("popupTriggerArea");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach the event listener to toggle the popup with the keyboard.
|
||||||
|
for (const element of this.#elements) {
|
||||||
|
element.container?.addEventListener("keydown", this.#boundKeyDown, {
|
||||||
|
signal,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.#popup) {
|
if (this.#popup) {
|
||||||
return;
|
return;
|
||||||
@ -2338,7 +2352,12 @@ class PopupElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateEdited({ rect, popupContent }) {
|
updateEdited({ rect, popupContent, deleted }) {
|
||||||
|
if (deleted) {
|
||||||
|
this.remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.#addEventListeners();
|
||||||
this.#updates ||= {
|
this.#updates ||= {
|
||||||
contentsObj: this.#contentsObj,
|
contentsObj: this.#contentsObj,
|
||||||
richText: this.#richText,
|
richText: this.#richText,
|
||||||
@ -2366,6 +2385,18 @@ class PopupElement {
|
|||||||
this.#position = null;
|
this.#position = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
this.#popupAbortController?.abort();
|
||||||
|
this.#popupAbortController = null;
|
||||||
|
this.#popup?.remove();
|
||||||
|
this.#popup = null;
|
||||||
|
this.#wasVisible = false;
|
||||||
|
this.#pinned = false;
|
||||||
|
for (const element of this.trigger) {
|
||||||
|
element.classList.remove("popupTriggerArea");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#setPosition() {
|
#setPosition() {
|
||||||
if (this.#position !== null) {
|
if (this.#position !== null) {
|
||||||
return;
|
return;
|
||||||
@ -2465,6 +2496,7 @@ class PopupElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maybeShow() {
|
maybeShow() {
|
||||||
|
this.#addEventListeners();
|
||||||
if (!this.#wasVisible) {
|
if (!this.#wasVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -359,6 +359,9 @@ class AnnotationEditorLayer {
|
|||||||
for (const editable of editables) {
|
for (const editable of editables) {
|
||||||
const { id } = editable.data;
|
const { id } = editable.data;
|
||||||
if (this.#uiManager.isDeletedAnnotationElement(id)) {
|
if (this.#uiManager.isDeletedAnnotationElement(id)) {
|
||||||
|
editable.updateEdited({
|
||||||
|
deleted: true,
|
||||||
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let editor = resetAnnotations.get(id);
|
let editor = resetAnnotations.get(id);
|
||||||
|
|||||||
@ -860,9 +860,6 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
renderAnnotationElement(annotation) {
|
renderAnnotationElement(annotation) {
|
||||||
const content = super.renderAnnotationElement(annotation);
|
const content = super.renderAnnotationElement(annotation);
|
||||||
if (this.deleted) {
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
const { style } = content;
|
const { style } = content;
|
||||||
style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`;
|
style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`;
|
||||||
style.color = this.#color;
|
style.color = this.#color;
|
||||||
|
|||||||
@ -1086,6 +1086,61 @@ describe("FreeText Editor", () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("must delete an existing annotation with a popup", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await page.click("[data-annotation-id='26R']");
|
||||||
|
// Wait for the popup to be displayed.
|
||||||
|
const popupSelector = "[data-annotation-id='popup_26R'] .popup";
|
||||||
|
await page.waitForSelector(popupSelector, { visible: true });
|
||||||
|
|
||||||
|
await switchToFreeText(page);
|
||||||
|
|
||||||
|
const editorSelector = getEditorSelector(0);
|
||||||
|
await selectEditor(page, editorSelector);
|
||||||
|
await page.keyboard.press("Backspace");
|
||||||
|
await page.waitForFunction(
|
||||||
|
sel => !document.querySelector(sel),
|
||||||
|
{},
|
||||||
|
editorSelector
|
||||||
|
);
|
||||||
|
|
||||||
|
await waitForSerialized(page, 1);
|
||||||
|
const serialized = await getSerialized(page);
|
||||||
|
expect(serialized).toEqual([
|
||||||
|
{
|
||||||
|
pageIndex: 0,
|
||||||
|
id: "26R",
|
||||||
|
deleted: true,
|
||||||
|
popupRef: "",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Disable editing mode.
|
||||||
|
await switchToFreeText(page, /* disable = */ true);
|
||||||
|
|
||||||
|
await page.waitForSelector(":not([data-annotation-id='26R'] .popup)");
|
||||||
|
|
||||||
|
// Re-enable editing mode.
|
||||||
|
await switchToFreeText(page);
|
||||||
|
await page.focus(".annotationEditorLayer");
|
||||||
|
|
||||||
|
await kbUndo(page);
|
||||||
|
await waitForSerialized(page, 0);
|
||||||
|
|
||||||
|
// Disable editing mode.
|
||||||
|
await switchToFreeText(page, /* disable = */ true);
|
||||||
|
|
||||||
|
const popupAreaSelector =
|
||||||
|
"[data-annotation-id='26R'].popupTriggerArea";
|
||||||
|
await page.waitForSelector(popupAreaSelector, { visible: true });
|
||||||
|
await page.click("[data-annotation-id='26R']");
|
||||||
|
// Wait for the popup to be displayed.
|
||||||
|
await page.waitForSelector(popupSelector, { visible: true });
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("FreeText (copy/paste existing)", () => {
|
describe("FreeText (copy/paste existing)", () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user