JS -- Plug PageOpen and PageClose actions
This commit is contained in:
parent
ed3758f84d
commit
6523f8880b
@ -1136,9 +1136,8 @@ class PDFPageProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {GetAnnotationsParameters} params - Annotation parameters.
|
* @returns {Promise<Object>} A promise that is resolved with an
|
||||||
* @returns {Promise<Array<any>>} A promise that is resolved with an
|
* {Object} with JS actions.
|
||||||
* {Array} of the annotation objects.
|
|
||||||
*/
|
*/
|
||||||
getJSActions() {
|
getJSActions() {
|
||||||
if (!this._jsActionsPromise) {
|
if (!this._jsActionsPromise) {
|
||||||
|
@ -91,6 +91,7 @@ class Doc extends PDFObject {
|
|||||||
this._zoom = data.zoom || 100;
|
this._zoom = data.zoom || 100;
|
||||||
this._actions = createActionsMap(data.actions);
|
this._actions = createActionsMap(data.actions);
|
||||||
this._globalEval = data.globalEval;
|
this._globalEval = data.globalEval;
|
||||||
|
this._pageActions = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
_dispatchDocEvent(name) {
|
_dispatchDocEvent(name) {
|
||||||
@ -114,22 +115,28 @@ class Doc extends PDFObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_dispatchPageEvent(name, action, pageNumber) {
|
_dispatchPageEvent(name, actions, pageNumber) {
|
||||||
if (name === "PageOpen") {
|
if (name === "PageOpen") {
|
||||||
|
if (!this._pageActions.has(pageNumber)) {
|
||||||
|
this._pageActions.set(pageNumber, createActionsMap(actions));
|
||||||
|
}
|
||||||
this._pageNum = pageNumber - 1;
|
this._pageNum = pageNumber - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._globalEval(action);
|
actions = this._pageActions.get(pageNumber)?.get(name);
|
||||||
|
if (actions) {
|
||||||
|
for (const action of actions) {
|
||||||
|
this._globalEval(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_runActions(name) {
|
_runActions(name) {
|
||||||
if (!this._actions.has(name)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const actions = this._actions.get(name);
|
const actions = this._actions.get(name);
|
||||||
for (const action of actions) {
|
if (actions) {
|
||||||
this._globalEval(action);
|
for (const action of actions) {
|
||||||
|
this._globalEval(action);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,11 +73,10 @@ class EventDispatcher {
|
|||||||
}
|
}
|
||||||
if (id === "doc") {
|
if (id === "doc") {
|
||||||
this._document.obj._dispatchDocEvent(event.name);
|
this._document.obj._dispatchDocEvent(event.name);
|
||||||
}
|
} else if (id === "page") {
|
||||||
if (id === "page") {
|
|
||||||
this._document.obj._dispatchPageEvent(
|
this._document.obj._dispatchPageEvent(
|
||||||
event.name,
|
event.name,
|
||||||
baseEvent.action,
|
baseEvent.actions,
|
||||||
baseEvent.pageNumber
|
baseEvent.pageNumber
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,10 @@
|
|||||||
const { clearInput, closePages, loadAndWait } = require("./test_utils.js");
|
const { clearInput, closePages, loadAndWait } = require("./test_utils.js");
|
||||||
|
|
||||||
describe("Interaction", () => {
|
describe("Interaction", () => {
|
||||||
async function actAndWaitForInput(page, selector, action) {
|
async function actAndWaitForInput(page, selector, action, clear = true) {
|
||||||
await clearInput(page, selector);
|
if (clear) {
|
||||||
|
await clearInput(page, selector);
|
||||||
|
}
|
||||||
await action();
|
await action();
|
||||||
await page.waitForFunction(
|
await page.waitForFunction(
|
||||||
`document.querySelector("${selector.replace("\\", "\\\\")}").value !== ""`
|
`document.querySelector("${selector.replace("\\", "\\\\")}").value !== ""`
|
||||||
@ -307,6 +309,18 @@ describe("Interaction", () => {
|
|||||||
if (process.platform === "win32" && browserName === "firefox") {
|
if (process.platform === "win32" && browserName === "firefox") {
|
||||||
pending("Disabled in Firefox on Windows, because of bug 1662471.");
|
pending("Disabled in Firefox on Windows, because of bug 1662471.");
|
||||||
}
|
}
|
||||||
|
await page.waitForFunction(
|
||||||
|
"window.PDFViewerApplication.scriptingReady === true"
|
||||||
|
);
|
||||||
|
|
||||||
|
await clearInput(page, "#\\34 7R");
|
||||||
|
await page.evaluate(_ => {
|
||||||
|
window.document.activeElement.blur();
|
||||||
|
});
|
||||||
|
await page.waitForFunction(
|
||||||
|
`document.querySelector("#\\\\34 7R").value === ""`
|
||||||
|
);
|
||||||
|
|
||||||
let text = await actAndWaitForInput(page, "#\\34 7R", async () => {
|
let text = await actAndWaitForInput(page, "#\\34 7R", async () => {
|
||||||
await page.click("#print");
|
await page.click("#print");
|
||||||
});
|
});
|
||||||
@ -337,6 +351,10 @@ describe("Interaction", () => {
|
|||||||
it("must execute WillSave and DidSave actions", async () => {
|
it("must execute WillSave and DidSave actions", async () => {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
pages.map(async ([browserName, page]) => {
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await page.waitForFunction(
|
||||||
|
"window.PDFViewerApplication.scriptingReady === true"
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Disable download in chrome
|
// Disable download in chrome
|
||||||
// (it leads to an error in firefox so the try...)
|
// (it leads to an error in firefox so the try...)
|
||||||
@ -345,6 +363,13 @@ describe("Interaction", () => {
|
|||||||
});
|
});
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
await clearInput(page, "#\\34 7R");
|
await clearInput(page, "#\\34 7R");
|
||||||
|
await page.evaluate(_ => {
|
||||||
|
window.document.activeElement.blur();
|
||||||
|
});
|
||||||
|
await page.waitForFunction(
|
||||||
|
`document.querySelector("#\\\\34 7R").value === ""`
|
||||||
|
);
|
||||||
|
|
||||||
let text = await actAndWaitForInput(page, "#\\34 7R", async () => {
|
let text = await actAndWaitForInput(page, "#\\34 7R", async () => {
|
||||||
await page.click("#download");
|
await page.click("#download");
|
||||||
});
|
});
|
||||||
@ -360,4 +385,70 @@ describe("Interaction", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("in doc_actions.pdf for page actions", () => {
|
||||||
|
let pages;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
pages = await loadAndWait("doc_actions.pdf", "#\\34 7R");
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await closePages(pages);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("must execute PageOpen and PageClose actions", async () => {
|
||||||
|
await Promise.all(
|
||||||
|
pages.map(async ([browserName, page]) => {
|
||||||
|
await page.waitForFunction(
|
||||||
|
"window.PDFViewerApplication.scriptingReady === true"
|
||||||
|
);
|
||||||
|
|
||||||
|
let text = await page.$eval("#\\34 7R", el => el.value);
|
||||||
|
expect(text).withContext(`In ${browserName}`).toEqual("PageOpen 1");
|
||||||
|
|
||||||
|
for (let run = 0; run < 5; run++) {
|
||||||
|
for (const ref of [18, 19, 20, 21, 47, 50]) {
|
||||||
|
await page.evaluate(refElem => {
|
||||||
|
const element = window.document.getElementById(`${refElem}R`);
|
||||||
|
if (element) {
|
||||||
|
element.value = "";
|
||||||
|
}
|
||||||
|
}, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [refOpen, refClose, pageNumOpen, pageNumClose] of [
|
||||||
|
[18, 50, 2, 1],
|
||||||
|
[21, 19, 3, 2],
|
||||||
|
[47, 20, 1, 3],
|
||||||
|
]) {
|
||||||
|
text = await actAndWaitForInput(
|
||||||
|
page,
|
||||||
|
`#\\3${Math.floor(refOpen / 10)} ${refOpen % 10}R`,
|
||||||
|
async () => {
|
||||||
|
await page.evaluate(refElem => {
|
||||||
|
window.document
|
||||||
|
.getElementById(`${refElem}R`)
|
||||||
|
.scrollIntoView();
|
||||||
|
}, refOpen);
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
expect(text)
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toEqual(`PageOpen ${pageNumOpen}`);
|
||||||
|
|
||||||
|
text = await page.$eval(
|
||||||
|
`#\\3${Math.floor(refClose / 10)} ${refClose % 10}R`,
|
||||||
|
el => el.value
|
||||||
|
);
|
||||||
|
expect(text)
|
||||||
|
.withContext(`In ${browserName}`)
|
||||||
|
.toEqual(`PageClose ${pageNumClose}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
60
web/app.js
60
web/app.js
@ -1542,6 +1542,64 @@ const PDFViewerApplication = {
|
|||||||
};
|
};
|
||||||
internalEvents.set("updatefromsandbox", updateFromSandbox);
|
internalEvents.set("updatefromsandbox", updateFromSandbox);
|
||||||
|
|
||||||
|
const visitedPages = new Map();
|
||||||
|
const pageOpen = ({ pageNumber }) => {
|
||||||
|
visitedPages.set(
|
||||||
|
pageNumber,
|
||||||
|
(async () => {
|
||||||
|
// Avoid sending, and thus serializing, the `actions` data
|
||||||
|
// when the same page is open several times.
|
||||||
|
let actions = null;
|
||||||
|
if (!visitedPages.has(pageNumber)) {
|
||||||
|
// visitedPages doesn't contain pageNumber: first visit.
|
||||||
|
|
||||||
|
const pageView = this.pdfViewer.getPageView(
|
||||||
|
/* index = */ pageNumber - 1
|
||||||
|
);
|
||||||
|
if (pageView?.pdfPage) {
|
||||||
|
actions = await pageView.pdfPage.getJSActions();
|
||||||
|
} else {
|
||||||
|
actions = await pdfDocument.getPage(pageNumber).getJSActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdfDocument !== this.pdfDocument) {
|
||||||
|
return; // The document was closed while the actions resolved.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._scriptingInstance?.scripting.dispatchEventInSandbox({
|
||||||
|
id: "page",
|
||||||
|
name: "PageOpen",
|
||||||
|
pageNumber,
|
||||||
|
actions,
|
||||||
|
});
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const pageClose = async ({ pageNumber }) => {
|
||||||
|
const promise = visitedPages.get(pageNumber);
|
||||||
|
if (!promise) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
visitedPages.set(pageNumber, null);
|
||||||
|
|
||||||
|
// Wait for PageOpen has been sent.
|
||||||
|
await promise;
|
||||||
|
|
||||||
|
if (pdfDocument !== this.pdfDocument) {
|
||||||
|
return; // The document was closed while the actions resolved.
|
||||||
|
}
|
||||||
|
|
||||||
|
this._scriptingInstance?.scripting.dispatchEventInSandbox({
|
||||||
|
id: "page",
|
||||||
|
name: "PageClose",
|
||||||
|
pageNumber,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
internalEvents.set("pageopen", pageOpen);
|
||||||
|
internalEvents.set("pageclose", pageClose);
|
||||||
|
|
||||||
const dispatchEventInSandbox = ({ detail }) => {
|
const dispatchEventInSandbox = ({ detail }) => {
|
||||||
scripting.dispatchEventInSandbox(detail);
|
scripting.dispatchEventInSandbox(detail);
|
||||||
};
|
};
|
||||||
@ -1613,6 +1671,8 @@ const PDFViewerApplication = {
|
|||||||
name: "Open",
|
name: "Open",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await pageOpen({ pageNumber: this.pdfViewer.currentPageNumber });
|
||||||
|
|
||||||
// Used together with the integration-tests, see the `scriptingReady`
|
// Used together with the integration-tests, see the `scriptingReady`
|
||||||
// getter, to enable awaiting full initialization of the scripting/sandbox.
|
// getter, to enable awaiting full initialization of the scripting/sandbox.
|
||||||
// (Defer this slightly, to make absolutely sure that everything is done.)
|
// (Defer this slightly, to make absolutely sure that everything is done.)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user