1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | "use strict";
|
23 |
|
24 | Object.defineProperty(exports, "__esModule", {
|
25 | value: true
|
26 | });
|
27 | exports.PDFScriptingManager = void 0;
|
28 |
|
29 | var _ui_utils = require("./ui_utils.js");
|
30 |
|
31 | var _pdf = require("../pdf");
|
32 |
|
33 | class PDFScriptingManager {
|
34 | constructor({
|
35 | eventBus,
|
36 | sandboxBundleSrc = null,
|
37 | scriptingFactory = null,
|
38 | docPropertiesLookup = null
|
39 | }) {
|
40 | this._pdfDocument = null;
|
41 | this._pdfViewer = null;
|
42 | this._closeCapability = null;
|
43 | this._destroyCapability = null;
|
44 | this._scripting = null;
|
45 | this._mouseState = Object.create(null);
|
46 | this._ready = false;
|
47 | this._eventBus = eventBus;
|
48 | this._sandboxBundleSrc = sandboxBundleSrc;
|
49 | this._scriptingFactory = scriptingFactory;
|
50 | this._docPropertiesLookup = docPropertiesLookup;
|
51 | }
|
52 |
|
53 | setViewer(pdfViewer) {
|
54 | this._pdfViewer = pdfViewer;
|
55 | }
|
56 |
|
57 | async setDocument(pdfDocument) {
|
58 | if (this._pdfDocument) {
|
59 | await this._destroyScripting();
|
60 | }
|
61 |
|
62 | this._pdfDocument = pdfDocument;
|
63 |
|
64 | if (!pdfDocument) {
|
65 | return;
|
66 | }
|
67 |
|
68 | const [objects, calculationOrder, docActions] = await Promise.all([pdfDocument.getFieldObjects(), pdfDocument.getCalculationOrderIds(), pdfDocument.getJSActions()]);
|
69 |
|
70 | if (!objects && !docActions) {
|
71 | await this._destroyScripting();
|
72 | return;
|
73 | }
|
74 |
|
75 | if (pdfDocument !== this._pdfDocument) {
|
76 | return;
|
77 | }
|
78 |
|
79 | try {
|
80 | this._scripting = this._createScripting();
|
81 | } catch (error) {
|
82 | console.error(`PDFScriptingManager.setDocument: "${error?.message}".`);
|
83 | await this._destroyScripting();
|
84 | return;
|
85 | }
|
86 |
|
87 | this._internalEvents.set("updatefromsandbox", event => {
|
88 | if (event?.source !== window) {
|
89 | return;
|
90 | }
|
91 |
|
92 | this._updateFromSandbox(event.detail);
|
93 | });
|
94 |
|
95 | this._internalEvents.set("dispatcheventinsandbox", event => {
|
96 | this._scripting?.dispatchEventInSandbox(event.detail);
|
97 | });
|
98 |
|
99 | this._internalEvents.set("pagechanging", ({
|
100 | pageNumber,
|
101 | previous
|
102 | }) => {
|
103 | if (pageNumber === previous) {
|
104 | return;
|
105 | }
|
106 |
|
107 | this._dispatchPageClose(previous);
|
108 |
|
109 | this._dispatchPageOpen(pageNumber);
|
110 | });
|
111 |
|
112 | this._internalEvents.set("pagerendered", ({
|
113 | pageNumber
|
114 | }) => {
|
115 | if (!this._pageOpenPending.has(pageNumber)) {
|
116 | return;
|
117 | }
|
118 |
|
119 | if (pageNumber !== this._pdfViewer.currentPageNumber) {
|
120 | return;
|
121 | }
|
122 |
|
123 | this._dispatchPageOpen(pageNumber);
|
124 | });
|
125 |
|
126 | this._internalEvents.set("pagesdestroy", async event => {
|
127 | await this._dispatchPageClose(this._pdfViewer.currentPageNumber);
|
128 | await this._scripting?.dispatchEventInSandbox({
|
129 | id: "doc",
|
130 | name: "WillClose"
|
131 | });
|
132 | this._closeCapability?.resolve();
|
133 | });
|
134 |
|
135 | this._domEvents.set("mousedown", event => {
|
136 | this._mouseState.isDown = true;
|
137 | });
|
138 |
|
139 | this._domEvents.set("mouseup", event => {
|
140 | this._mouseState.isDown = false;
|
141 | });
|
142 |
|
143 | for (const [name, listener] of this._internalEvents) {
|
144 | this._eventBus._on(name, listener);
|
145 | }
|
146 |
|
147 | for (const [name, listener] of this._domEvents) {
|
148 | window.addEventListener(name, listener, true);
|
149 | }
|
150 |
|
151 | try {
|
152 | const docProperties = await this._getDocProperties();
|
153 |
|
154 | if (pdfDocument !== this._pdfDocument) {
|
155 | return;
|
156 | }
|
157 |
|
158 | await this._scripting.createSandbox({
|
159 | objects,
|
160 | calculationOrder,
|
161 | appInfo: {
|
162 | platform: navigator.platform,
|
163 | language: navigator.language
|
164 | },
|
165 | docInfo: { ...docProperties,
|
166 | actions: docActions
|
167 | }
|
168 | });
|
169 |
|
170 | this._eventBus.dispatch("sandboxcreated", {
|
171 | source: this
|
172 | });
|
173 | } catch (error) {
|
174 | console.error(`PDFScriptingManager.setDocument: "${error?.message}".`);
|
175 | await this._destroyScripting();
|
176 | return;
|
177 | }
|
178 |
|
179 | await this._scripting?.dispatchEventInSandbox({
|
180 | id: "doc",
|
181 | name: "Open"
|
182 | });
|
183 | await this._dispatchPageOpen(this._pdfViewer.currentPageNumber, true);
|
184 | Promise.resolve().then(() => {
|
185 | if (pdfDocument === this._pdfDocument) {
|
186 | this._ready = true;
|
187 | }
|
188 | });
|
189 | }
|
190 |
|
191 | async dispatchWillSave(detail) {
|
192 | return this._scripting?.dispatchEventInSandbox({
|
193 | id: "doc",
|
194 | name: "WillSave"
|
195 | });
|
196 | }
|
197 |
|
198 | async dispatchDidSave(detail) {
|
199 | return this._scripting?.dispatchEventInSandbox({
|
200 | id: "doc",
|
201 | name: "DidSave"
|
202 | });
|
203 | }
|
204 |
|
205 | async dispatchWillPrint(detail) {
|
206 | return this._scripting?.dispatchEventInSandbox({
|
207 | id: "doc",
|
208 | name: "WillPrint"
|
209 | });
|
210 | }
|
211 |
|
212 | async dispatchDidPrint(detail) {
|
213 | return this._scripting?.dispatchEventInSandbox({
|
214 | id: "doc",
|
215 | name: "DidPrint"
|
216 | });
|
217 | }
|
218 |
|
219 | get mouseState() {
|
220 | return this._mouseState;
|
221 | }
|
222 |
|
223 | get destroyPromise() {
|
224 | return this._destroyCapability?.promise || null;
|
225 | }
|
226 |
|
227 | get ready() {
|
228 | return this._ready;
|
229 | }
|
230 |
|
231 | get _internalEvents() {
|
232 | return (0, _pdf.shadow)(this, "_internalEvents", new Map());
|
233 | }
|
234 |
|
235 | get _domEvents() {
|
236 | return (0, _pdf.shadow)(this, "_domEvents", new Map());
|
237 | }
|
238 |
|
239 | get _pageOpenPending() {
|
240 | return (0, _pdf.shadow)(this, "_pageOpenPending", new Set());
|
241 | }
|
242 |
|
243 | get _visitedPages() {
|
244 | return (0, _pdf.shadow)(this, "_visitedPages", new Map());
|
245 | }
|
246 |
|
247 | async _updateFromSandbox(detail) {
|
248 | const isInPresentationMode = this._pdfViewer.isInPresentationMode || this._pdfViewer.isChangingPresentationMode;
|
249 | const {
|
250 | id,
|
251 | siblings,
|
252 | command,
|
253 | value
|
254 | } = detail;
|
255 |
|
256 | if (!id) {
|
257 | switch (command) {
|
258 | case "clear":
|
259 | console.clear();
|
260 | break;
|
261 |
|
262 | case "error":
|
263 | console.error(value);
|
264 | break;
|
265 |
|
266 | case "layout":
|
267 | if (isInPresentationMode) {
|
268 | return;
|
269 | }
|
270 |
|
271 | const modes = (0, _ui_utils.apiPageLayoutToViewerModes)(value);
|
272 | this._pdfViewer.spreadMode = modes.spreadMode;
|
273 | break;
|
274 |
|
275 | case "page-num":
|
276 | this._pdfViewer.currentPageNumber = value + 1;
|
277 | break;
|
278 |
|
279 | case "print":
|
280 | await this._pdfViewer.pagesPromise;
|
281 |
|
282 | this._eventBus.dispatch("print", {
|
283 | source: this
|
284 | });
|
285 |
|
286 | break;
|
287 |
|
288 | case "println":
|
289 | console.log(value);
|
290 | break;
|
291 |
|
292 | case "zoom":
|
293 | if (isInPresentationMode) {
|
294 | return;
|
295 | }
|
296 |
|
297 | this._pdfViewer.currentScaleValue = value;
|
298 | break;
|
299 |
|
300 | case "SaveAs":
|
301 | this._eventBus.dispatch("download", {
|
302 | source: this
|
303 | });
|
304 |
|
305 | break;
|
306 |
|
307 | case "FirstPage":
|
308 | this._pdfViewer.currentPageNumber = 1;
|
309 | break;
|
310 |
|
311 | case "LastPage":
|
312 | this._pdfViewer.currentPageNumber = this._pdfViewer.pagesCount;
|
313 | break;
|
314 |
|
315 | case "NextPage":
|
316 | this._pdfViewer.nextPage();
|
317 |
|
318 | break;
|
319 |
|
320 | case "PrevPage":
|
321 | this._pdfViewer.previousPage();
|
322 |
|
323 | break;
|
324 |
|
325 | case "ZoomViewIn":
|
326 | if (isInPresentationMode) {
|
327 | return;
|
328 | }
|
329 |
|
330 | this._pdfViewer.increaseScale();
|
331 |
|
332 | break;
|
333 |
|
334 | case "ZoomViewOut":
|
335 | if (isInPresentationMode) {
|
336 | return;
|
337 | }
|
338 |
|
339 | this._pdfViewer.decreaseScale();
|
340 |
|
341 | break;
|
342 | }
|
343 |
|
344 | return;
|
345 | }
|
346 |
|
347 | if (isInPresentationMode) {
|
348 | if (detail.focus) {
|
349 | return;
|
350 | }
|
351 | }
|
352 |
|
353 | delete detail.id;
|
354 | delete detail.siblings;
|
355 | const ids = siblings ? [id, ...siblings] : [id];
|
356 |
|
357 | for (const elementId of ids) {
|
358 | const element = document.querySelector(`[data-element-id="${elementId}"]`);
|
359 |
|
360 | if (element) {
|
361 | element.dispatchEvent(new CustomEvent("updatefromsandbox", {
|
362 | detail
|
363 | }));
|
364 | } else {
|
365 | this._pdfDocument?.annotationStorage.setValue(elementId, detail);
|
366 | }
|
367 | }
|
368 | }
|
369 |
|
370 | async _dispatchPageOpen(pageNumber, initialize = false) {
|
371 | const pdfDocument = this._pdfDocument,
|
372 | visitedPages = this._visitedPages;
|
373 |
|
374 | if (initialize) {
|
375 | this._closeCapability = (0, _pdf.createPromiseCapability)();
|
376 | }
|
377 |
|
378 | if (!this._closeCapability) {
|
379 | return;
|
380 | }
|
381 |
|
382 | const pageView = this._pdfViewer.getPageView(pageNumber - 1);
|
383 |
|
384 | if (pageView?.renderingState !== _ui_utils.RenderingStates.FINISHED) {
|
385 | this._pageOpenPending.add(pageNumber);
|
386 |
|
387 | return;
|
388 | }
|
389 |
|
390 | this._pageOpenPending.delete(pageNumber);
|
391 |
|
392 | const actionsPromise = (async () => {
|
393 | const actions = await (!visitedPages.has(pageNumber) ? pageView.pdfPage?.getJSActions() : null);
|
394 |
|
395 | if (pdfDocument !== this._pdfDocument) {
|
396 | return;
|
397 | }
|
398 |
|
399 | await this._scripting?.dispatchEventInSandbox({
|
400 | id: "page",
|
401 | name: "PageOpen",
|
402 | pageNumber,
|
403 | actions
|
404 | });
|
405 | })();
|
406 |
|
407 | visitedPages.set(pageNumber, actionsPromise);
|
408 | }
|
409 |
|
410 | async _dispatchPageClose(pageNumber) {
|
411 | const pdfDocument = this._pdfDocument,
|
412 | visitedPages = this._visitedPages;
|
413 |
|
414 | if (!this._closeCapability) {
|
415 | return;
|
416 | }
|
417 |
|
418 | if (this._pageOpenPending.has(pageNumber)) {
|
419 | return;
|
420 | }
|
421 |
|
422 | const actionsPromise = visitedPages.get(pageNumber);
|
423 |
|
424 | if (!actionsPromise) {
|
425 | return;
|
426 | }
|
427 |
|
428 | visitedPages.set(pageNumber, null);
|
429 | await actionsPromise;
|
430 |
|
431 | if (pdfDocument !== this._pdfDocument) {
|
432 | return;
|
433 | }
|
434 |
|
435 | await this._scripting?.dispatchEventInSandbox({
|
436 | id: "page",
|
437 | name: "PageClose",
|
438 | pageNumber
|
439 | });
|
440 | }
|
441 |
|
442 | async _getDocProperties() {
|
443 | if (this._docPropertiesLookup) {
|
444 | return this._docPropertiesLookup(this._pdfDocument);
|
445 | }
|
446 |
|
447 | throw new Error("_getDocProperties: Unable to lookup properties.");
|
448 | }
|
449 |
|
450 | _createScripting() {
|
451 | this._destroyCapability = (0, _pdf.createPromiseCapability)();
|
452 |
|
453 | if (this._scripting) {
|
454 | throw new Error("_createScripting: Scripting already exists.");
|
455 | }
|
456 |
|
457 | if (this._scriptingFactory) {
|
458 | return this._scriptingFactory.createScripting({
|
459 | sandboxBundleSrc: this._sandboxBundleSrc
|
460 | });
|
461 | }
|
462 |
|
463 | throw new Error("_createScripting: Cannot create scripting.");
|
464 | }
|
465 |
|
466 | async _destroyScripting() {
|
467 | if (!this._scripting) {
|
468 | this._pdfDocument = null;
|
469 | this._destroyCapability?.resolve();
|
470 | return;
|
471 | }
|
472 |
|
473 | if (this._closeCapability) {
|
474 | await Promise.race([this._closeCapability.promise, new Promise(resolve => {
|
475 | setTimeout(resolve, 1000);
|
476 | })]).catch(reason => {});
|
477 | this._closeCapability = null;
|
478 | }
|
479 |
|
480 | this._pdfDocument = null;
|
481 |
|
482 | try {
|
483 | await this._scripting.destroySandbox();
|
484 | } catch (ex) {}
|
485 |
|
486 | for (const [name, listener] of this._internalEvents) {
|
487 | this._eventBus._off(name, listener);
|
488 | }
|
489 |
|
490 | this._internalEvents.clear();
|
491 |
|
492 | for (const [name, listener] of this._domEvents) {
|
493 | window.removeEventListener(name, listener, true);
|
494 | }
|
495 |
|
496 | this._domEvents.clear();
|
497 |
|
498 | this._pageOpenPending.clear();
|
499 |
|
500 | this._visitedPages.clear();
|
501 |
|
502 | this._scripting = null;
|
503 | delete this._mouseState.isDown;
|
504 | this._ready = false;
|
505 | this._destroyCapability?.resolve();
|
506 | }
|
507 |
|
508 | }
|
509 |
|
510 | exports.PDFScriptingManager = PDFScriptingManager; |
\ | No newline at end of file |