Merge pull request #15786 from calixteman/15780_bis
[Editor] Add a very basic and incomplete workaround for issue #15780
This commit is contained in:
commit
feb6f5951c
@ -246,7 +246,7 @@ class AnnotationEditorLayer {
|
|||||||
this.attach(editor);
|
this.attach(editor);
|
||||||
editor.pageIndex = this.pageIndex;
|
editor.pageIndex = this.pageIndex;
|
||||||
editor.parent?.detach(editor);
|
editor.parent?.detach(editor);
|
||||||
editor.parent = this;
|
editor.setParent(this);
|
||||||
if (editor.div && editor.isAttachedToDOM) {
|
if (editor.div && editor.isAttachedToDOM) {
|
||||||
editor.div.remove();
|
editor.div.remove();
|
||||||
this.div.append(editor.div);
|
this.div.append(editor.div);
|
||||||
@ -521,8 +521,8 @@ class AnnotationEditorLayer {
|
|||||||
for (const editor of this.#editors.values()) {
|
for (const editor of this.#editors.values()) {
|
||||||
this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);
|
this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv);
|
||||||
editor.isAttachedToDOM = false;
|
editor.isAttachedToDOM = false;
|
||||||
|
editor.setParent(null);
|
||||||
editor.div.remove();
|
editor.div.remove();
|
||||||
editor.parent = null;
|
|
||||||
}
|
}
|
||||||
this.div = null;
|
this.div = null;
|
||||||
this.#editors.clear();
|
this.#editors.clear();
|
||||||
|
@ -68,6 +68,8 @@ class AnnotationEditor {
|
|||||||
this.rotation = this.parent.viewport.rotation;
|
this.rotation = this.parent.viewport.rotation;
|
||||||
|
|
||||||
this.isAttachedToDOM = false;
|
this.isAttachedToDOM = false;
|
||||||
|
|
||||||
|
this._serialized = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
static get _defaultLineColor() {
|
static get _defaultLineColor() {
|
||||||
@ -78,6 +80,11 @@ class AnnotationEditor {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setParent(parent) {
|
||||||
|
this._serialized = !parent ? this.serialize() : undefined;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This editor will be behind the others.
|
* This editor will be behind the others.
|
||||||
*/
|
*/
|
||||||
|
@ -478,6 +478,10 @@ class FreeTextEditor extends AnnotationEditor {
|
|||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
serialize() {
|
serialize() {
|
||||||
|
if (this._serialized !== undefined) {
|
||||||
|
return this._serialized;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isEmpty()) {
|
if (this.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1058,6 +1058,10 @@ class InkEditor extends AnnotationEditor {
|
|||||||
|
|
||||||
/** @inheritdoc */
|
/** @inheritdoc */
|
||||||
serialize() {
|
serialize() {
|
||||||
|
if (this._serialized !== undefined) {
|
||||||
|
return this._serialized;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isEmpty()) {
|
if (this.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ const {
|
|||||||
getSelectedEditors,
|
getSelectedEditors,
|
||||||
loadAndWait,
|
loadAndWait,
|
||||||
waitForEvent,
|
waitForEvent,
|
||||||
|
waitForSelectedEditor,
|
||||||
|
waitForStorageEntries,
|
||||||
} = require("./test_utils.js");
|
} = require("./test_utils.js");
|
||||||
|
|
||||||
const copyPaste = async page => {
|
const copyPaste = async page => {
|
||||||
@ -49,23 +51,6 @@ describe("Editor", () => {
|
|||||||
await closePages(pages);
|
await closePages(pages);
|
||||||
});
|
});
|
||||||
|
|
||||||
const waitForStorageEntries = async (page, nEntries) => {
|
|
||||||
await page.waitForFunction(
|
|
||||||
n =>
|
|
||||||
window.PDFViewerApplication.pdfDocument.annotationStorage.size === n,
|
|
||||||
{},
|
|
||||||
nEntries
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const waitForSelected = async (page, selector) => {
|
|
||||||
await page.waitForFunction(
|
|
||||||
sel => document.querySelector(sel).classList.contains("selectedEditor"),
|
|
||||||
{},
|
|
||||||
selector
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
it("must write a string in a FreeText editor", async () => {
|
it("must write a string in a FreeText editor", async () => {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
pages.map(async ([browserName, page]) => {
|
pages.map(async ([browserName, page]) => {
|
||||||
@ -98,7 +83,7 @@ describe("Editor", () => {
|
|||||||
editorRect.y + 2 * editorRect.height
|
editorRect.y + 2 * editorRect.height
|
||||||
);
|
);
|
||||||
|
|
||||||
await waitForSelected(page, getEditorSelector(0));
|
await waitForSelectedEditor(page, getEditorSelector(0));
|
||||||
await waitForStorageEntries(page, 1);
|
await waitForStorageEntries(page, 1);
|
||||||
|
|
||||||
const content = await page.$eval(getEditorSelector(0), el =>
|
const content = await page.$eval(getEditorSelector(0), el =>
|
||||||
@ -123,7 +108,7 @@ describe("Editor", () => {
|
|||||||
editorRect.y + editorRect.height / 2
|
editorRect.y + editorRect.height / 2
|
||||||
);
|
);
|
||||||
|
|
||||||
await waitForSelected(page, getEditorSelector(0));
|
await waitForSelectedEditor(page, getEditorSelector(0));
|
||||||
await copyPaste(page);
|
await copyPaste(page);
|
||||||
await waitForStorageEntries(page, 2);
|
await waitForStorageEntries(page, 2);
|
||||||
|
|
||||||
@ -199,7 +184,7 @@ describe("Editor", () => {
|
|||||||
editorRect.y + editorRect.height / 2
|
editorRect.y + editorRect.height / 2
|
||||||
);
|
);
|
||||||
|
|
||||||
await waitForSelected(page, getEditorSelector(3));
|
await waitForSelectedEditor(page, getEditorSelector(3));
|
||||||
await copyPaste(page);
|
await copyPaste(page);
|
||||||
|
|
||||||
let hasEditor = await page.evaluate(sel => {
|
let hasEditor = await page.evaluate(sel => {
|
||||||
@ -335,7 +320,7 @@ describe("Editor", () => {
|
|||||||
editorRect.y + editorRect.height / 2
|
editorRect.y + editorRect.height / 2
|
||||||
);
|
);
|
||||||
|
|
||||||
await waitForSelected(page, getEditorSelector(8));
|
await waitForSelectedEditor(page, getEditorSelector(8));
|
||||||
|
|
||||||
expect(await getSelectedEditors(page))
|
expect(await getSelectedEditors(page))
|
||||||
.withContext(`In ${browserName}`)
|
.withContext(`In ${browserName}`)
|
||||||
@ -512,4 +497,110 @@ describe("Editor", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("FreeText (bugs)", () => {
|
||||||
|
let pages;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
pages = await loadAndWait("tracemonkey.pdf", ".annotationEditorLayer");
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await closePages(pages);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("must serialize invisible annotations", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await page.click("#editorFreeText");
|
||||||
|
let currentId = 0;
|
||||||
|
const expected = [];
|
||||||
|
const oneToFourteen = [...new Array(14).keys()].map(x => x + 1);
|
||||||
|
|
||||||
|
for (const pageNumber of oneToFourteen) {
|
||||||
|
const pageSelector = `.page[data-page-number = "${pageNumber}"]`;
|
||||||
|
|
||||||
|
await page.evaluate(selector => {
|
||||||
|
const element = window.document.querySelector(selector);
|
||||||
|
element.scrollIntoView();
|
||||||
|
}, pageSelector);
|
||||||
|
|
||||||
|
const annotationLayerSelector = `${pageSelector} > .annotationEditorLayer`;
|
||||||
|
await page.waitForSelector(annotationLayerSelector, {
|
||||||
|
visible: true,
|
||||||
|
timeout: 0,
|
||||||
|
});
|
||||||
|
await page.waitForTimeout(50);
|
||||||
|
if (![1, 14].includes(pageNumber)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rect = await page.$eval(annotationLayerSelector, el => {
|
||||||
|
// With Chrome something is wrong when serializing a DomRect,
|
||||||
|
// hence we extract the values and just return them.
|
||||||
|
const { x, y } = el.getBoundingClientRect();
|
||||||
|
return { x, y };
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = `Hello PDF.js World !! on page ${pageNumber}`;
|
||||||
|
expected.push(data);
|
||||||
|
await page.mouse.click(rect.x + 100, rect.y + 100);
|
||||||
|
await page.type(`${getEditorSelector(currentId)} .internal`, data);
|
||||||
|
|
||||||
|
const editorRect = await page.$eval(
|
||||||
|
getEditorSelector(currentId),
|
||||||
|
el => {
|
||||||
|
const { x, y, width, height } = el.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Commit.
|
||||||
|
await page.mouse.click(
|
||||||
|
editorRect.x,
|
||||||
|
editorRect.y + 2 * editorRect.height
|
||||||
|
);
|
||||||
|
|
||||||
|
await waitForSelectedEditor(page, getEditorSelector(currentId));
|
||||||
|
await waitForStorageEntries(page, currentId + 1);
|
||||||
|
|
||||||
|
const content = await page.$eval(getEditorSelector(currentId), el =>
|
||||||
|
el.innerText.trimEnd()
|
||||||
|
);
|
||||||
|
expect(content).withContext(`In ${browserName}`).toEqual(data);
|
||||||
|
|
||||||
|
currentId += 1;
|
||||||
|
await page.waitForTimeout(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
const serialize = proprName =>
|
||||||
|
page.evaluate(
|
||||||
|
name =>
|
||||||
|
[
|
||||||
|
...window.PDFViewerApplication.pdfDocument.annotationStorage.serializable.values(),
|
||||||
|
].map(x => x[name]),
|
||||||
|
proprName
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(await serialize("value"))
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toEqual(expected);
|
||||||
|
expect(await serialize("fontSize"))
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toEqual([10, 10]);
|
||||||
|
expect(await serialize("color"))
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toEqual([
|
||||||
|
[0, 0, 0],
|
||||||
|
[0, 0, 0],
|
||||||
|
]);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -100,3 +100,21 @@ async function waitForEvent(page, eventName, timeout = 30000) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
exports.waitForEvent = waitForEvent;
|
exports.waitForEvent = waitForEvent;
|
||||||
|
|
||||||
|
const waitForStorageEntries = async (page, nEntries) => {
|
||||||
|
await page.waitForFunction(
|
||||||
|
n => window.PDFViewerApplication.pdfDocument.annotationStorage.size === n,
|
||||||
|
{},
|
||||||
|
nEntries
|
||||||
|
);
|
||||||
|
};
|
||||||
|
exports.waitForStorageEntries = waitForStorageEntries;
|
||||||
|
|
||||||
|
const waitForSelectedEditor = async (page, selector) => {
|
||||||
|
await page.waitForFunction(
|
||||||
|
sel => document.querySelector(sel).classList.contains("selectedEditor"),
|
||||||
|
{},
|
||||||
|
selector
|
||||||
|
);
|
||||||
|
};
|
||||||
|
exports.waitForSelectedEditor = waitForSelectedEditor;
|
||||||
|
Loading…
Reference in New Issue
Block a user