@pdfslick/core 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/README.md +119 -0
- package/dist/esm/PDFSlick.d.ts +103 -0
- package/dist/esm/PDFSlick.d.ts.map +1 -0
- package/dist/esm/index.css +0 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +2912 -0
- package/dist/esm/lib/index.d.ts +7 -0
- package/dist/esm/lib/index.d.ts.map +1 -0
- package/dist/esm/lib/overlay_manager.d.ts +32 -0
- package/dist/esm/lib/overlay_manager.d.ts.map +1 -0
- package/dist/esm/lib/pdf_presentation_mode.d.ts +46 -0
- package/dist/esm/lib/pdf_presentation_mode.d.ts.map +1 -0
- package/dist/esm/lib/pdf_print_service.d.ts +30 -0
- package/dist/esm/lib/pdf_print_service.d.ts.map +1 -0
- package/dist/esm/lib/pdf_rendering_queue.d.ts +65 -0
- package/dist/esm/lib/pdf_rendering_queue.d.ts.map +1 -0
- package/dist/esm/lib/pdf_thumbnail_view.d.ts +101 -0
- package/dist/esm/lib/pdf_thumbnail_view.d.ts.map +1 -0
- package/dist/esm/lib/pdf_thumbnail_viewer.d.ts +119 -0
- package/dist/esm/lib/pdf_thumbnail_viewer.d.ts.map +1 -0
- package/dist/esm/lib/ui_utils.d.ts +292 -0
- package/dist/esm/lib/ui_utils.d.ts.map +1 -0
- package/dist/esm/store.d.ts +4 -0
- package/dist/esm/store.d.ts.map +1 -0
- package/dist/esm/types.d.ts +111 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/pdf_viewer.css +2762 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/umd/PDFSlick.d.ts +103 -0
- package/dist/umd/PDFSlick.d.ts.map +1 -0
- package/dist/umd/index.d.ts +5 -0
- package/dist/umd/index.d.ts.map +1 -0
- package/dist/umd/index.js +45 -0
- package/dist/umd/lib/index.d.ts +7 -0
- package/dist/umd/lib/index.d.ts.map +1 -0
- package/dist/umd/lib/overlay_manager.d.ts +32 -0
- package/dist/umd/lib/overlay_manager.d.ts.map +1 -0
- package/dist/umd/lib/pdf_presentation_mode.d.ts +46 -0
- package/dist/umd/lib/pdf_presentation_mode.d.ts.map +1 -0
- package/dist/umd/lib/pdf_print_service.d.ts +30 -0
- package/dist/umd/lib/pdf_print_service.d.ts.map +1 -0
- package/dist/umd/lib/pdf_rendering_queue.d.ts +65 -0
- package/dist/umd/lib/pdf_rendering_queue.d.ts.map +1 -0
- package/dist/umd/lib/pdf_thumbnail_view.d.ts +101 -0
- package/dist/umd/lib/pdf_thumbnail_view.d.ts.map +1 -0
- package/dist/umd/lib/pdf_thumbnail_viewer.d.ts +119 -0
- package/dist/umd/lib/pdf_thumbnail_viewer.d.ts.map +1 -0
- package/dist/umd/lib/ui_utils.d.ts +292 -0
- package/dist/umd/lib/ui_utils.d.ts.map +1 -0
- package/dist/umd/store.d.ts +4 -0
- package/dist/umd/store.d.ts.map +1 -0
- package/dist/umd/types.d.ts +111 -0
- package/dist/umd/types.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,2912 @@
|
|
|
1
|
+
import { RenderingCancelledException, PixelsPerInch, getXfaPageViewport, AnnotationMode, AnnotationEditorType, GlobalWorkerOptions, version, getPdfFilenameFromUrl, getDocument, PDFDateString } from 'pdfjs-dist';
|
|
2
|
+
import { SimpleLinkService, XfaLayerBuilder, NullL10n, DownloadManager, EventBus, PDFLinkService, PDFSinglePageViewer, PDFViewer } from 'pdfjs-dist/web/pdf_viewer';
|
|
3
|
+
import { createStore } from 'zustand/vanilla';
|
|
4
|
+
|
|
5
|
+
/******************************************************************************
|
|
6
|
+
Copyright (c) Microsoft Corporation.
|
|
7
|
+
|
|
8
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
9
|
+
purpose with or without fee is hereby granted.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
12
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
13
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
14
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
15
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
17
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
18
|
+
***************************************************************************** */
|
|
19
|
+
|
|
20
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
21
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
22
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
23
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
24
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
25
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
26
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function __classPrivateFieldGet(receiver, state, kind, f) {
|
|
31
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
32
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
33
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
|
37
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
38
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
39
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
40
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Copyright 2012 Mozilla Foundation
|
|
44
|
+
*
|
|
45
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
46
|
+
* you may not use this file except in compliance with the License.
|
|
47
|
+
* You may obtain a copy of the License at
|
|
48
|
+
*
|
|
49
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
50
|
+
*
|
|
51
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
52
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
53
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
54
|
+
* See the License for the specific language governing permissions and
|
|
55
|
+
* limitations under the License.
|
|
56
|
+
*/
|
|
57
|
+
var _ProgressBar_classList, _ProgressBar_disableAutoFetchTimeout, _ProgressBar_percent, _ProgressBar_style, _ProgressBar_visible;
|
|
58
|
+
const DEFAULT_SCALE_VALUE = "auto";
|
|
59
|
+
const DEFAULT_SCALE = 1.0;
|
|
60
|
+
const DEFAULT_SCALE_DELTA = 1.1;
|
|
61
|
+
const MIN_SCALE = 0.1;
|
|
62
|
+
const MAX_SCALE = 10.0;
|
|
63
|
+
const UNKNOWN_SCALE = 0;
|
|
64
|
+
const MAX_AUTO_SCALE = 1.25;
|
|
65
|
+
const SCROLLBAR_PADDING = 40;
|
|
66
|
+
const VERTICAL_PADDING = 5;
|
|
67
|
+
const RenderingStates = {
|
|
68
|
+
INITIAL: 0,
|
|
69
|
+
RUNNING: 1,
|
|
70
|
+
PAUSED: 2,
|
|
71
|
+
FINISHED: 3,
|
|
72
|
+
};
|
|
73
|
+
const PresentationModeState = {
|
|
74
|
+
UNKNOWN: 0,
|
|
75
|
+
NORMAL: 1,
|
|
76
|
+
CHANGING: 2,
|
|
77
|
+
FULLSCREEN: 3,
|
|
78
|
+
};
|
|
79
|
+
const SidebarView = {
|
|
80
|
+
UNKNOWN: -1,
|
|
81
|
+
NONE: 0,
|
|
82
|
+
THUMBS: 1,
|
|
83
|
+
OUTLINE: 2,
|
|
84
|
+
ATTACHMENTS: 3,
|
|
85
|
+
LAYERS: 4,
|
|
86
|
+
};
|
|
87
|
+
const RendererType = {
|
|
88
|
+
CANVAS: "canvas",
|
|
89
|
+
SVG: "svg",
|
|
90
|
+
};
|
|
91
|
+
const TextLayerMode = {
|
|
92
|
+
DISABLE: 0,
|
|
93
|
+
ENABLE: 1,
|
|
94
|
+
};
|
|
95
|
+
const ScrollMode = {
|
|
96
|
+
UNKNOWN: -1,
|
|
97
|
+
VERTICAL: 0,
|
|
98
|
+
HORIZONTAL: 1,
|
|
99
|
+
WRAPPED: 2,
|
|
100
|
+
PAGE: 3,
|
|
101
|
+
};
|
|
102
|
+
const SpreadMode = {
|
|
103
|
+
UNKNOWN: -1,
|
|
104
|
+
NONE: 0,
|
|
105
|
+
ODD: 1,
|
|
106
|
+
EVEN: 2,
|
|
107
|
+
};
|
|
108
|
+
const CursorTool = {
|
|
109
|
+
SELECT: 0,
|
|
110
|
+
HAND: 1,
|
|
111
|
+
ZOOM: 2,
|
|
112
|
+
};
|
|
113
|
+
// Used by `PDFViewerApplication`, and by the API unit-tests.
|
|
114
|
+
const AutoPrintRegExp = /\bprint\s*\(/;
|
|
115
|
+
/**
|
|
116
|
+
* Scale factors for the canvas, necessary with HiDPI displays.
|
|
117
|
+
*/
|
|
118
|
+
class OutputScale {
|
|
119
|
+
constructor() {
|
|
120
|
+
const pixelRatio = window.devicePixelRatio || 1;
|
|
121
|
+
/**
|
|
122
|
+
* @type {number} Horizontal scale.
|
|
123
|
+
*/
|
|
124
|
+
this.sx = pixelRatio;
|
|
125
|
+
/**
|
|
126
|
+
* @type {number} Vertical scale.
|
|
127
|
+
*/
|
|
128
|
+
this.sy = pixelRatio;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* @type {boolean} Returns `true` when scaling is required, `false` otherwise.
|
|
132
|
+
*/
|
|
133
|
+
get scaled() {
|
|
134
|
+
return this.sx !== 1 || this.sy !== 1;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Scrolls specified element into view of its parent.
|
|
139
|
+
* @param {Object} element - The element to be visible.
|
|
140
|
+
* @param {Object} spot - An object with optional top and left properties,
|
|
141
|
+
* specifying the offset from the top left edge.
|
|
142
|
+
* @param {boolean} [scrollMatches] - When scrolling search results into view,
|
|
143
|
+
* ignore elements that either: Contains marked content identifiers,
|
|
144
|
+
* or have the CSS-rule `overflow: hidden;` set. The default value is `false`.
|
|
145
|
+
*/
|
|
146
|
+
function scrollIntoView(element, spot, scrollMatches = false) {
|
|
147
|
+
// Assuming offsetParent is available (it's not available when viewer is in
|
|
148
|
+
// hidden iframe or object). We have to scroll: if the offsetParent is not set
|
|
149
|
+
// producing the error. See also animationStarted.
|
|
150
|
+
let parent = element.offsetParent;
|
|
151
|
+
if (!parent) {
|
|
152
|
+
console.error("offsetParent is not set -- cannot scroll");
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
let offsetY = element.offsetTop + element.clientTop;
|
|
156
|
+
let offsetX = element.offsetLeft + element.clientLeft;
|
|
157
|
+
while ((parent.clientHeight === parent.scrollHeight &&
|
|
158
|
+
parent.clientWidth === parent.scrollWidth) ||
|
|
159
|
+
(scrollMatches &&
|
|
160
|
+
(parent.classList.contains("markedContent") ||
|
|
161
|
+
getComputedStyle(parent).overflow === "hidden"))) {
|
|
162
|
+
offsetY += parent.offsetTop;
|
|
163
|
+
offsetX += parent.offsetLeft;
|
|
164
|
+
parent = parent.offsetParent;
|
|
165
|
+
if (!parent) {
|
|
166
|
+
return; // no need to scroll
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (spot) {
|
|
170
|
+
if (spot.top !== undefined) {
|
|
171
|
+
offsetY += spot.top;
|
|
172
|
+
}
|
|
173
|
+
if (spot.left !== undefined) {
|
|
174
|
+
offsetX += spot.left;
|
|
175
|
+
parent.scrollLeft = offsetX;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
parent.scrollTop = offsetY;
|
|
179
|
+
parent.scrollLeft = offsetX;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Helper function to start monitoring the scroll event and converting them into
|
|
183
|
+
* PDF.js friendly one: with scroll debounce and scroll direction.
|
|
184
|
+
*/
|
|
185
|
+
function watchScroll(viewAreaElement, callback) {
|
|
186
|
+
const debounceScroll = function (evt) {
|
|
187
|
+
if (rAF) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// schedule an invocation of scroll for next animation frame.
|
|
191
|
+
rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {
|
|
192
|
+
rAF = null;
|
|
193
|
+
const currentX = viewAreaElement.scrollLeft;
|
|
194
|
+
const lastX = state.lastX;
|
|
195
|
+
if (currentX !== lastX) {
|
|
196
|
+
state.right = currentX > lastX;
|
|
197
|
+
}
|
|
198
|
+
state.lastX = currentX;
|
|
199
|
+
const currentY = viewAreaElement.scrollTop;
|
|
200
|
+
const lastY = state.lastY;
|
|
201
|
+
if (currentY !== lastY) {
|
|
202
|
+
state.down = currentY > lastY;
|
|
203
|
+
}
|
|
204
|
+
state.lastY = currentY;
|
|
205
|
+
callback(state);
|
|
206
|
+
});
|
|
207
|
+
};
|
|
208
|
+
const state = {
|
|
209
|
+
right: true,
|
|
210
|
+
down: true,
|
|
211
|
+
lastX: viewAreaElement.scrollLeft,
|
|
212
|
+
lastY: viewAreaElement.scrollTop,
|
|
213
|
+
_eventHandler: debounceScroll,
|
|
214
|
+
};
|
|
215
|
+
let rAF = null;
|
|
216
|
+
viewAreaElement.addEventListener("scroll", debounceScroll, true);
|
|
217
|
+
return state;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Helper function to parse query string (e.g. ?param1=value¶m2=...).
|
|
221
|
+
* @param {string}
|
|
222
|
+
* @returns {Map}
|
|
223
|
+
*/
|
|
224
|
+
function parseQueryString(query) {
|
|
225
|
+
const params = new Map();
|
|
226
|
+
for (const [key, value] of new URLSearchParams(query)) {
|
|
227
|
+
params.set(key.toLowerCase(), value);
|
|
228
|
+
}
|
|
229
|
+
return params;
|
|
230
|
+
}
|
|
231
|
+
const NullCharactersRegExp = /\x00/g;
|
|
232
|
+
const InvisibleCharactersRegExp = /[\x01-\x1F]/g;
|
|
233
|
+
/**
|
|
234
|
+
* @param {string} str
|
|
235
|
+
* @param {boolean} [replaceInvisible]
|
|
236
|
+
*/
|
|
237
|
+
function removeNullCharacters(str, replaceInvisible = false) {
|
|
238
|
+
if (typeof str !== "string") {
|
|
239
|
+
console.error(`The argument must be a string.`);
|
|
240
|
+
return str;
|
|
241
|
+
}
|
|
242
|
+
if (replaceInvisible) {
|
|
243
|
+
str = str.replace(InvisibleCharactersRegExp, " ");
|
|
244
|
+
}
|
|
245
|
+
return str.replace(NullCharactersRegExp, "");
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Use binary search to find the index of the first item in a given array which
|
|
249
|
+
* passes a given condition. The items are expected to be sorted in the sense
|
|
250
|
+
* that if the condition is true for one item in the array, then it is also true
|
|
251
|
+
* for all following items.
|
|
252
|
+
*
|
|
253
|
+
* @returns {number} Index of the first array element to pass the test,
|
|
254
|
+
* or |items.length| if no such element exists.
|
|
255
|
+
*/
|
|
256
|
+
function binarySearchFirstItem(items, condition, start = 0) {
|
|
257
|
+
let minIndex = start;
|
|
258
|
+
let maxIndex = items.length - 1;
|
|
259
|
+
if (maxIndex < 0 || !condition(items[maxIndex])) {
|
|
260
|
+
return items.length;
|
|
261
|
+
}
|
|
262
|
+
if (condition(items[minIndex])) {
|
|
263
|
+
return minIndex;
|
|
264
|
+
}
|
|
265
|
+
while (minIndex < maxIndex) {
|
|
266
|
+
const currentIndex = (minIndex + maxIndex) >> 1;
|
|
267
|
+
const currentItem = items[currentIndex];
|
|
268
|
+
if (condition(currentItem)) {
|
|
269
|
+
maxIndex = currentIndex;
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
minIndex = currentIndex + 1;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return minIndex; /* === maxIndex */
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Approximates float number as a fraction using Farey sequence (max order
|
|
279
|
+
* of 8).
|
|
280
|
+
* @param {number} x - Positive float number.
|
|
281
|
+
* @returns {Array} Estimated fraction: the first array item is a numerator,
|
|
282
|
+
* the second one is a denominator.
|
|
283
|
+
*/
|
|
284
|
+
function approximateFraction(x) {
|
|
285
|
+
// Fast paths for int numbers or their inversions.
|
|
286
|
+
if (Math.floor(x) === x) {
|
|
287
|
+
return [x, 1];
|
|
288
|
+
}
|
|
289
|
+
const xinv = 1 / x;
|
|
290
|
+
const limit = 8;
|
|
291
|
+
if (xinv > limit) {
|
|
292
|
+
return [1, limit];
|
|
293
|
+
}
|
|
294
|
+
else if (Math.floor(xinv) === xinv) {
|
|
295
|
+
return [1, xinv];
|
|
296
|
+
}
|
|
297
|
+
const x_ = x > 1 ? xinv : x;
|
|
298
|
+
// a/b and c/d are neighbours in Farey sequence.
|
|
299
|
+
let a = 0, b = 1, c = 1, d = 1;
|
|
300
|
+
// Limiting search to order 8.
|
|
301
|
+
while (true) {
|
|
302
|
+
// Generating next term in sequence (order of q).
|
|
303
|
+
const p = a + c, q = b + d;
|
|
304
|
+
if (q > limit) {
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
if (x_ <= p / q) {
|
|
308
|
+
c = p;
|
|
309
|
+
d = q;
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
a = p;
|
|
313
|
+
b = q;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
let result;
|
|
317
|
+
// Select closest of the neighbours to x.
|
|
318
|
+
if (x_ - a / b < c / d - x_) {
|
|
319
|
+
result = x_ === x ? [a, b] : [b, a];
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
result = x_ === x ? [c, d] : [d, c];
|
|
323
|
+
}
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
function roundToDivide(x, div) {
|
|
327
|
+
const r = x % div;
|
|
328
|
+
return r === 0 ? x : Math.round(x - r + div);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* @typedef {Object} GetPageSizeInchesParameters
|
|
332
|
+
* @property {number[]} view
|
|
333
|
+
* @property {number} userUnit
|
|
334
|
+
* @property {number} rotate
|
|
335
|
+
*/
|
|
336
|
+
/**
|
|
337
|
+
* @typedef {Object} PageSize
|
|
338
|
+
* @property {number} width - In inches.
|
|
339
|
+
* @property {number} height - In inches.
|
|
340
|
+
*/
|
|
341
|
+
/**
|
|
342
|
+
* Gets the size of the specified page, converted from PDF units to inches.
|
|
343
|
+
* @param {GetPageSizeInchesParameters} params
|
|
344
|
+
* @returns {PageSize}
|
|
345
|
+
*/
|
|
346
|
+
function getPageSizeInches({ view, userUnit, rotate }) {
|
|
347
|
+
const [x1, y1, x2, y2] = view;
|
|
348
|
+
// We need to take the page rotation into account as well.
|
|
349
|
+
const changeOrientation = rotate % 180 !== 0;
|
|
350
|
+
const width = ((x2 - x1) / 72) * userUnit;
|
|
351
|
+
const height = ((y2 - y1) / 72) * userUnit;
|
|
352
|
+
return {
|
|
353
|
+
width: changeOrientation ? height : width,
|
|
354
|
+
height: changeOrientation ? width : height,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Helper function for getVisibleElements.
|
|
359
|
+
*
|
|
360
|
+
* @param {number} index - initial guess at the first visible element
|
|
361
|
+
* @param {Array} views - array of pages, into which `index` is an index
|
|
362
|
+
* @param {number} top - the top of the scroll pane
|
|
363
|
+
* @returns {number} less than or equal to `index` that is definitely at or
|
|
364
|
+
* before the first visible element in `views`, but not by too much. (Usually,
|
|
365
|
+
* this will be the first element in the first partially visible row in
|
|
366
|
+
* `views`, although sometimes it goes back one row further.)
|
|
367
|
+
*/
|
|
368
|
+
function backtrackBeforeAllVisibleElements(index, views, top) {
|
|
369
|
+
// binarySearchFirstItem's assumption is that the input is ordered, with only
|
|
370
|
+
// one index where the conditions flips from false to true: [false ...,
|
|
371
|
+
// true...]. With vertical scrolling and spreads, it is possible to have
|
|
372
|
+
// [false ..., true, false, true ...]. With wrapped scrolling we can have a
|
|
373
|
+
// similar sequence, with many more mixed true and false in the middle.
|
|
374
|
+
//
|
|
375
|
+
// So there is no guarantee that the binary search yields the index of the
|
|
376
|
+
// first visible element. It could have been any of the other visible elements
|
|
377
|
+
// that were preceded by a hidden element.
|
|
378
|
+
// Of course, if either this element or the previous (hidden) element is also
|
|
379
|
+
// the first element, there's nothing to worry about.
|
|
380
|
+
if (index < 2) {
|
|
381
|
+
return index;
|
|
382
|
+
}
|
|
383
|
+
// That aside, the possible cases are represented below.
|
|
384
|
+
//
|
|
385
|
+
// **** = fully hidden
|
|
386
|
+
// A*B* = mix of partially visible and/or hidden pages
|
|
387
|
+
// CDEF = fully visible
|
|
388
|
+
//
|
|
389
|
+
// (1) Binary search could have returned A, in which case we can stop.
|
|
390
|
+
// (2) Binary search could also have returned B, in which case we need to
|
|
391
|
+
// check the whole row.
|
|
392
|
+
// (3) Binary search could also have returned C, in which case we need to
|
|
393
|
+
// check the whole previous row.
|
|
394
|
+
//
|
|
395
|
+
// There's one other possibility:
|
|
396
|
+
//
|
|
397
|
+
// **** = fully hidden
|
|
398
|
+
// ABCD = mix of fully and/or partially visible pages
|
|
399
|
+
//
|
|
400
|
+
// (4) Binary search could only have returned A.
|
|
401
|
+
// Initially assume that we need to find the beginning of the current row
|
|
402
|
+
// (case 1, 2, or 4), which means finding a page that is above the current
|
|
403
|
+
// page's top. If the found page is partially visible, we're definitely not in
|
|
404
|
+
// case 3, and this assumption is correct.
|
|
405
|
+
let elt = views[index].div;
|
|
406
|
+
let pageTop = elt.offsetTop + elt.clientTop;
|
|
407
|
+
if (pageTop >= top) {
|
|
408
|
+
// The found page is fully visible, so we're actually either in case 3 or 4,
|
|
409
|
+
// and unfortunately we can't tell the difference between them without
|
|
410
|
+
// scanning the entire previous row, so we just conservatively assume that
|
|
411
|
+
// we do need to backtrack to that row. In both cases, the previous page is
|
|
412
|
+
// in the previous row, so use its top instead.
|
|
413
|
+
elt = views[index - 1].div;
|
|
414
|
+
pageTop = elt.offsetTop + elt.clientTop;
|
|
415
|
+
}
|
|
416
|
+
// Now we backtrack to the first page that still has its bottom below
|
|
417
|
+
// `pageTop`, which is the top of a page in the first visible row (unless
|
|
418
|
+
// we're in case 4, in which case it's the row before that).
|
|
419
|
+
// `index` is found by binary search, so the page at `index - 1` is
|
|
420
|
+
// invisible and we can start looking for potentially visible pages from
|
|
421
|
+
// `index - 2`. (However, if this loop terminates on its first iteration,
|
|
422
|
+
// which is the case when pages are stacked vertically, `index` should remain
|
|
423
|
+
// unchanged, so we use a distinct loop variable.)
|
|
424
|
+
for (let i = index - 2; i >= 0; --i) {
|
|
425
|
+
elt = views[i].div;
|
|
426
|
+
if (elt.offsetTop + elt.clientTop + elt.clientHeight <= pageTop) {
|
|
427
|
+
// We have reached the previous row, so stop now.
|
|
428
|
+
// This loop is expected to terminate relatively quickly because the
|
|
429
|
+
// number of pages per row is expected to be small.
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
index = i;
|
|
433
|
+
}
|
|
434
|
+
return index;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* @typedef {Object} GetVisibleElementsParameters
|
|
438
|
+
* @property {HTMLElement} scrollEl - A container that can possibly scroll.
|
|
439
|
+
* @property {Array} views - Objects with a `div` property that contains an
|
|
440
|
+
* HTMLElement, which should all be descendants of `scrollEl` satisfying the
|
|
441
|
+
* relevant layout assumptions.
|
|
442
|
+
* @property {boolean} sortByVisibility - If `true`, the returned elements are
|
|
443
|
+
* sorted in descending order of the percent of their padding box that is
|
|
444
|
+
* visible. The default value is `false`.
|
|
445
|
+
* @property {boolean} horizontal - If `true`, the elements are assumed to be
|
|
446
|
+
* laid out horizontally instead of vertically. The default value is `false`.
|
|
447
|
+
* @property {boolean} rtl - If `true`, the `scrollEl` container is assumed to
|
|
448
|
+
* be in right-to-left mode. The default value is `false`.
|
|
449
|
+
*/
|
|
450
|
+
/**
|
|
451
|
+
* Generic helper to find out what elements are visible within a scroll pane.
|
|
452
|
+
*
|
|
453
|
+
* Well, pretty generic. There are some assumptions placed on the elements
|
|
454
|
+
* referenced by `views`:
|
|
455
|
+
* - If `horizontal`, no left of any earlier element is to the right of the
|
|
456
|
+
* left of any later element.
|
|
457
|
+
* - Otherwise, `views` can be split into contiguous rows where, within a row,
|
|
458
|
+
* no top of any element is below the bottom of any other element, and
|
|
459
|
+
* between rows, no bottom of any element in an earlier row is below the
|
|
460
|
+
* top of any element in a later row.
|
|
461
|
+
*
|
|
462
|
+
* (Here, top, left, etc. all refer to the padding edge of the element in
|
|
463
|
+
* question. For pages, that ends up being equivalent to the bounding box of the
|
|
464
|
+
* rendering canvas. Earlier and later refer to index in `views`, not page
|
|
465
|
+
* layout.)
|
|
466
|
+
*
|
|
467
|
+
* @param {GetVisibleElementsParameters}
|
|
468
|
+
* @returns {Object} `{ first, last, views: [{ id, x, y, view, percent }] }`
|
|
469
|
+
*/
|
|
470
|
+
function getVisibleElements({ scrollEl, views, sortByVisibility = false, horizontal = false, rtl = false, }) {
|
|
471
|
+
const top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight;
|
|
472
|
+
const left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;
|
|
473
|
+
// Throughout this "generic" function, comments will assume we're working with
|
|
474
|
+
// PDF document pages, which is the most important and complex case. In this
|
|
475
|
+
// case, the visible elements we're actually interested is the page canvas,
|
|
476
|
+
// which is contained in a wrapper which adds no padding/border/margin, which
|
|
477
|
+
// is itself contained in `view.div` which adds no padding (but does add a
|
|
478
|
+
// border). So, as specified in this function's doc comment, this function
|
|
479
|
+
// does all of its work on the padding edge of the provided views, starting at
|
|
480
|
+
// offsetLeft/Top (which includes margin) and adding clientLeft/Top (which is
|
|
481
|
+
// the border). Adding clientWidth/Height gets us the bottom-right corner of
|
|
482
|
+
// the padding edge.
|
|
483
|
+
function isElementBottomAfterViewTop(view) {
|
|
484
|
+
const element = view.div;
|
|
485
|
+
const elementBottom = element.offsetTop + element.clientTop + element.clientHeight;
|
|
486
|
+
return elementBottom > top;
|
|
487
|
+
}
|
|
488
|
+
function isElementNextAfterViewHorizontally(view) {
|
|
489
|
+
const element = view.div;
|
|
490
|
+
const elementLeft = element.offsetLeft + element.clientLeft;
|
|
491
|
+
const elementRight = elementLeft + element.clientWidth;
|
|
492
|
+
return rtl ? elementLeft < right : elementRight > left;
|
|
493
|
+
}
|
|
494
|
+
const visible = [], ids = new Set(), numViews = views.length;
|
|
495
|
+
let firstVisibleElementInd = binarySearchFirstItem(views, horizontal
|
|
496
|
+
? isElementNextAfterViewHorizontally
|
|
497
|
+
: isElementBottomAfterViewTop);
|
|
498
|
+
// Please note the return value of the `binarySearchFirstItem` function when
|
|
499
|
+
// no valid element is found (hence the `firstVisibleElementInd` check below).
|
|
500
|
+
if (firstVisibleElementInd > 0 &&
|
|
501
|
+
firstVisibleElementInd < numViews &&
|
|
502
|
+
!horizontal) {
|
|
503
|
+
// In wrapped scrolling (or vertical scrolling with spreads), with some page
|
|
504
|
+
// sizes, isElementBottomAfterViewTop doesn't satisfy the binary search
|
|
505
|
+
// condition: there can be pages with bottoms above the view top between
|
|
506
|
+
// pages with bottoms below. This function detects and corrects that error;
|
|
507
|
+
// see it for more comments.
|
|
508
|
+
firstVisibleElementInd = backtrackBeforeAllVisibleElements(firstVisibleElementInd, views, top);
|
|
509
|
+
}
|
|
510
|
+
// lastEdge acts as a cutoff for us to stop looping, because we know all
|
|
511
|
+
// subsequent pages will be hidden.
|
|
512
|
+
//
|
|
513
|
+
// When using wrapped scrolling or vertical scrolling with spreads, we can't
|
|
514
|
+
// simply stop the first time we reach a page below the bottom of the view;
|
|
515
|
+
// the tops of subsequent pages on the same row could still be visible. In
|
|
516
|
+
// horizontal scrolling, we don't have that issue, so we can stop as soon as
|
|
517
|
+
// we pass `right`, without needing the code below that handles the -1 case.
|
|
518
|
+
let lastEdge = horizontal ? right : -1;
|
|
519
|
+
for (let i = firstVisibleElementInd; i < numViews; i++) {
|
|
520
|
+
const view = views[i], element = view.div;
|
|
521
|
+
const currentWidth = element.offsetLeft + element.clientLeft;
|
|
522
|
+
const currentHeight = element.offsetTop + element.clientTop;
|
|
523
|
+
const viewWidth = element.clientWidth, viewHeight = element.clientHeight;
|
|
524
|
+
const viewRight = currentWidth + viewWidth;
|
|
525
|
+
const viewBottom = currentHeight + viewHeight;
|
|
526
|
+
if (lastEdge === -1) {
|
|
527
|
+
// As commented above, this is only needed in non-horizontal cases.
|
|
528
|
+
// Setting lastEdge to the bottom of the first page that is partially
|
|
529
|
+
// visible ensures that the next page fully below lastEdge is on the
|
|
530
|
+
// next row, which has to be fully hidden along with all subsequent rows.
|
|
531
|
+
if (viewBottom >= bottom) {
|
|
532
|
+
lastEdge = viewBottom;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
else if ((horizontal ? currentWidth : currentHeight) > lastEdge) {
|
|
536
|
+
break;
|
|
537
|
+
}
|
|
538
|
+
if (viewBottom <= top ||
|
|
539
|
+
currentHeight >= bottom ||
|
|
540
|
+
viewRight <= left ||
|
|
541
|
+
currentWidth >= right) {
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
const hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, viewBottom - bottom);
|
|
545
|
+
const hiddenWidth = Math.max(0, left - currentWidth) + Math.max(0, viewRight - right);
|
|
546
|
+
const fractionHeight = (viewHeight - hiddenHeight) / viewHeight, fractionWidth = (viewWidth - hiddenWidth) / viewWidth;
|
|
547
|
+
const percent = (fractionHeight * fractionWidth * 100) | 0;
|
|
548
|
+
visible.push({
|
|
549
|
+
id: view.id,
|
|
550
|
+
x: currentWidth,
|
|
551
|
+
y: currentHeight,
|
|
552
|
+
view,
|
|
553
|
+
percent,
|
|
554
|
+
widthPercent: (fractionWidth * 100) | 0,
|
|
555
|
+
});
|
|
556
|
+
ids.add(view.id);
|
|
557
|
+
}
|
|
558
|
+
const first = visible[0], last = visible.at(-1);
|
|
559
|
+
if (sortByVisibility) {
|
|
560
|
+
visible.sort(function (a, b) {
|
|
561
|
+
const pc = a.percent - b.percent;
|
|
562
|
+
if (Math.abs(pc) > 0.001) {
|
|
563
|
+
return -pc;
|
|
564
|
+
}
|
|
565
|
+
return a.id - b.id; // ensure stability
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
return { first, last, views: visible, ids };
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Event handler to suppress context menu.
|
|
572
|
+
*/
|
|
573
|
+
function noContextMenuHandler(evt) {
|
|
574
|
+
evt.preventDefault();
|
|
575
|
+
}
|
|
576
|
+
function normalizeWheelEventDirection(evt) {
|
|
577
|
+
let delta = Math.hypot(evt.deltaX, evt.deltaY);
|
|
578
|
+
const angle = Math.atan2(evt.deltaY, evt.deltaX);
|
|
579
|
+
if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) {
|
|
580
|
+
// All that is left-up oriented has to change the sign.
|
|
581
|
+
delta = -delta;
|
|
582
|
+
}
|
|
583
|
+
return delta;
|
|
584
|
+
}
|
|
585
|
+
function normalizeWheelEventDelta(evt) {
|
|
586
|
+
const deltaMode = evt.deltaMode; // Avoid being affected by bug 1392460.
|
|
587
|
+
let delta = normalizeWheelEventDirection(evt);
|
|
588
|
+
const MOUSE_PIXELS_PER_LINE = 30;
|
|
589
|
+
const MOUSE_LINES_PER_PAGE = 30;
|
|
590
|
+
// Converts delta to per-page units
|
|
591
|
+
if (deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
|
|
592
|
+
delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE;
|
|
593
|
+
}
|
|
594
|
+
else if (deltaMode === WheelEvent.DOM_DELTA_LINE) {
|
|
595
|
+
delta /= MOUSE_LINES_PER_PAGE;
|
|
596
|
+
}
|
|
597
|
+
return delta;
|
|
598
|
+
}
|
|
599
|
+
function isValidRotation(angle) {
|
|
600
|
+
return Number.isInteger(angle) && angle % 90 === 0;
|
|
601
|
+
}
|
|
602
|
+
function isValidScrollMode(mode) {
|
|
603
|
+
return (Number.isInteger(mode) &&
|
|
604
|
+
Object.values(ScrollMode).includes(mode) &&
|
|
605
|
+
mode !== ScrollMode.UNKNOWN);
|
|
606
|
+
}
|
|
607
|
+
function isValidSpreadMode(mode) {
|
|
608
|
+
return (Number.isInteger(mode) &&
|
|
609
|
+
Object.values(SpreadMode).includes(mode) &&
|
|
610
|
+
mode !== SpreadMode.UNKNOWN);
|
|
611
|
+
}
|
|
612
|
+
function isPortraitOrientation(size) {
|
|
613
|
+
return size.width <= size.height;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Promise that is resolved when DOM window becomes visible.
|
|
617
|
+
*/
|
|
618
|
+
const animationStarted = new Promise(function (resolve) {
|
|
619
|
+
window.requestAnimationFrame(resolve);
|
|
620
|
+
});
|
|
621
|
+
const docStyle = document.documentElement.style;
|
|
622
|
+
function clamp(v, min, max) {
|
|
623
|
+
return Math.min(Math.max(v, min), max);
|
|
624
|
+
}
|
|
625
|
+
class ProgressBar {
|
|
626
|
+
constructor(bar) {
|
|
627
|
+
_ProgressBar_classList.set(this, null);
|
|
628
|
+
_ProgressBar_disableAutoFetchTimeout.set(this, null);
|
|
629
|
+
_ProgressBar_percent.set(this, 0);
|
|
630
|
+
_ProgressBar_style.set(this, null);
|
|
631
|
+
_ProgressBar_visible.set(this, true);
|
|
632
|
+
__classPrivateFieldSet(this, _ProgressBar_classList, bar.classList, "f");
|
|
633
|
+
__classPrivateFieldSet(this, _ProgressBar_style, bar.style, "f");
|
|
634
|
+
}
|
|
635
|
+
get percent() {
|
|
636
|
+
return __classPrivateFieldGet(this, _ProgressBar_percent, "f");
|
|
637
|
+
}
|
|
638
|
+
set percent(val) {
|
|
639
|
+
var _a, _b, _c;
|
|
640
|
+
__classPrivateFieldSet(this, _ProgressBar_percent, clamp(val, 0, 100), "f");
|
|
641
|
+
if (isNaN(val)) {
|
|
642
|
+
(_a = __classPrivateFieldGet(this, _ProgressBar_classList, "f")) === null || _a === void 0 ? void 0 : _a.add("indeterminate");
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
(_b = __classPrivateFieldGet(this, _ProgressBar_classList, "f")) === null || _b === void 0 ? void 0 : _b.remove("indeterminate");
|
|
646
|
+
(_c = __classPrivateFieldGet(this, _ProgressBar_style, "f")) === null || _c === void 0 ? void 0 : _c.setProperty("--progressBar-percent", `${__classPrivateFieldGet(this, _ProgressBar_percent, "f")}%`);
|
|
647
|
+
}
|
|
648
|
+
setWidth(viewer) {
|
|
649
|
+
var _a;
|
|
650
|
+
if (!viewer) {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
const container = viewer.parentNode;
|
|
654
|
+
const scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
|
|
655
|
+
if (scrollbarWidth > 0) {
|
|
656
|
+
(_a = __classPrivateFieldGet(this, _ProgressBar_style, "f")) === null || _a === void 0 ? void 0 : _a.setProperty("--progressBar-end-offset", `${scrollbarWidth}px`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
setDisableAutoFetch(delay = /* ms = */ 5000) {
|
|
660
|
+
if (isNaN(__classPrivateFieldGet(this, _ProgressBar_percent, "f"))) {
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (__classPrivateFieldGet(this, _ProgressBar_disableAutoFetchTimeout, "f")) {
|
|
664
|
+
clearTimeout(__classPrivateFieldGet(this, _ProgressBar_disableAutoFetchTimeout, "f"));
|
|
665
|
+
}
|
|
666
|
+
this.show();
|
|
667
|
+
__classPrivateFieldSet(this, _ProgressBar_disableAutoFetchTimeout, setTimeout(() => {
|
|
668
|
+
__classPrivateFieldSet(this, _ProgressBar_disableAutoFetchTimeout, null, "f");
|
|
669
|
+
this.hide();
|
|
670
|
+
}, delay), "f");
|
|
671
|
+
}
|
|
672
|
+
hide() {
|
|
673
|
+
var _a;
|
|
674
|
+
if (!__classPrivateFieldGet(this, _ProgressBar_visible, "f")) {
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
__classPrivateFieldSet(this, _ProgressBar_visible, false, "f");
|
|
678
|
+
(_a = __classPrivateFieldGet(this, _ProgressBar_classList, "f")) === null || _a === void 0 ? void 0 : _a.add("hidden");
|
|
679
|
+
}
|
|
680
|
+
show() {
|
|
681
|
+
var _a;
|
|
682
|
+
if (__classPrivateFieldGet(this, _ProgressBar_visible, "f")) {
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
__classPrivateFieldSet(this, _ProgressBar_visible, true, "f");
|
|
686
|
+
(_a = __classPrivateFieldGet(this, _ProgressBar_classList, "f")) === null || _a === void 0 ? void 0 : _a.remove("hidden");
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
_ProgressBar_classList = new WeakMap(), _ProgressBar_disableAutoFetchTimeout = new WeakMap(), _ProgressBar_percent = new WeakMap(), _ProgressBar_style = new WeakMap(), _ProgressBar_visible = new WeakMap();
|
|
690
|
+
/**
|
|
691
|
+
* Get the active or focused element in current DOM.
|
|
692
|
+
*
|
|
693
|
+
* Recursively search for the truly active or focused element in case there are
|
|
694
|
+
* shadow DOMs.
|
|
695
|
+
*
|
|
696
|
+
* @returns {Element} the truly active or focused element.
|
|
697
|
+
*/
|
|
698
|
+
function getActiveOrFocusedElement() {
|
|
699
|
+
let curRoot = document;
|
|
700
|
+
let curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus");
|
|
701
|
+
while (curActiveOrFocused === null || curActiveOrFocused === void 0 ? void 0 : curActiveOrFocused.shadowRoot) {
|
|
702
|
+
curRoot = curActiveOrFocused.shadowRoot;
|
|
703
|
+
curActiveOrFocused =
|
|
704
|
+
curRoot.activeElement || curRoot.querySelector(":focus");
|
|
705
|
+
}
|
|
706
|
+
return curActiveOrFocused;
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Converts API PageLayout values to the format used by `BaseViewer`.
|
|
710
|
+
* @param {string} mode - The API PageLayout value.
|
|
711
|
+
* @returns {Object}
|
|
712
|
+
*/
|
|
713
|
+
function apiPageLayoutToViewerModes(layout) {
|
|
714
|
+
let scrollMode = ScrollMode.VERTICAL, spreadMode = SpreadMode.NONE;
|
|
715
|
+
switch (layout) {
|
|
716
|
+
case "SinglePage":
|
|
717
|
+
scrollMode = ScrollMode.PAGE;
|
|
718
|
+
break;
|
|
719
|
+
case "OneColumn":
|
|
720
|
+
break;
|
|
721
|
+
case "TwoPageLeft":
|
|
722
|
+
scrollMode = ScrollMode.PAGE;
|
|
723
|
+
/* falls through */
|
|
724
|
+
case "TwoColumnLeft":
|
|
725
|
+
spreadMode = SpreadMode.ODD;
|
|
726
|
+
break;
|
|
727
|
+
case "TwoPageRight":
|
|
728
|
+
scrollMode = ScrollMode.PAGE;
|
|
729
|
+
/* falls through */
|
|
730
|
+
case "TwoColumnRight":
|
|
731
|
+
spreadMode = SpreadMode.EVEN;
|
|
732
|
+
break;
|
|
733
|
+
}
|
|
734
|
+
return { scrollMode, spreadMode };
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Converts API PageMode values to the format used by `PDFSidebar`.
|
|
738
|
+
* NOTE: There's also a "FullScreen" parameter which is not possible to support,
|
|
739
|
+
* since the Fullscreen API used in browsers requires that entering
|
|
740
|
+
* fullscreen mode only occurs as a result of a user-initiated event.
|
|
741
|
+
* @param {string} mode - The API PageMode value.
|
|
742
|
+
* @returns {number} A value from {SidebarView}.
|
|
743
|
+
*/
|
|
744
|
+
function apiPageModeToSidebarView(mode) {
|
|
745
|
+
switch (mode) {
|
|
746
|
+
case "UseNone":
|
|
747
|
+
return SidebarView.NONE;
|
|
748
|
+
case "UseThumbs":
|
|
749
|
+
return SidebarView.THUMBS;
|
|
750
|
+
case "UseOutlines":
|
|
751
|
+
return SidebarView.OUTLINE;
|
|
752
|
+
case "UseAttachments":
|
|
753
|
+
return SidebarView.ATTACHMENTS;
|
|
754
|
+
case "UseOC":
|
|
755
|
+
return SidebarView.LAYERS;
|
|
756
|
+
}
|
|
757
|
+
return SidebarView.NONE; // Default value.
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/* Copyright 2012 Mozilla Foundation
|
|
761
|
+
*
|
|
762
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
763
|
+
* you may not use this file except in compliance with the License.
|
|
764
|
+
* You may obtain a copy of the License at
|
|
765
|
+
*
|
|
766
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
767
|
+
*
|
|
768
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
769
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
770
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
771
|
+
* See the License for the specific language governing permissions and
|
|
772
|
+
* limitations under the License.
|
|
773
|
+
*/
|
|
774
|
+
const CLEANUP_TIMEOUT = 30000;
|
|
775
|
+
/**
|
|
776
|
+
* Controls rendering of the views for pages and thumbnails.
|
|
777
|
+
*/
|
|
778
|
+
class PDFRenderingQueue {
|
|
779
|
+
constructor() {
|
|
780
|
+
this.pdfViewer = null;
|
|
781
|
+
this.pdfThumbnailViewer = null;
|
|
782
|
+
this.onIdle = null;
|
|
783
|
+
this.highestPriorityPage = null;
|
|
784
|
+
/** @type {number} */
|
|
785
|
+
this.idleTimeout = null;
|
|
786
|
+
this.printing = false;
|
|
787
|
+
this.isThumbnailViewEnabled = false;
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* @param {PDFViewer} pdfViewer
|
|
791
|
+
*/
|
|
792
|
+
setViewer(pdfViewer) {
|
|
793
|
+
this.pdfViewer = pdfViewer;
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* @param {PDFThumbnailViewer} pdfThumbnailViewer
|
|
797
|
+
*/
|
|
798
|
+
setThumbnailViewer(pdfThumbnailViewer) {
|
|
799
|
+
this.pdfThumbnailViewer = pdfThumbnailViewer;
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* @param {IRenderableView} view
|
|
803
|
+
* @returns {boolean}
|
|
804
|
+
*/
|
|
805
|
+
isHighestPriority(view) {
|
|
806
|
+
return this.highestPriorityPage === view.renderingId;
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* @returns {boolean}
|
|
810
|
+
*/
|
|
811
|
+
hasViewer() {
|
|
812
|
+
return !!this.pdfViewer;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* @param {Object} currentlyVisiblePages
|
|
816
|
+
*/
|
|
817
|
+
renderHighestPriority(currentlyVisiblePages) {
|
|
818
|
+
var _a, _b;
|
|
819
|
+
if (this.idleTimeout) {
|
|
820
|
+
clearTimeout(this.idleTimeout);
|
|
821
|
+
this.idleTimeout = null;
|
|
822
|
+
}
|
|
823
|
+
// Pages have a higher priority than thumbnails, so check them first.
|
|
824
|
+
if ((_a = this.pdfViewer) === null || _a === void 0 ? void 0 : _a.forceRendering(currentlyVisiblePages)) {
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
// No pages needed rendering, so check thumbnails.
|
|
828
|
+
if (this.isThumbnailViewEnabled &&
|
|
829
|
+
((_b = this.pdfThumbnailViewer) === null || _b === void 0 ? void 0 : _b.forceRendering())) {
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
if (this.printing) {
|
|
833
|
+
// If printing is currently ongoing do not reschedule cleanup.
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
if (this.onIdle) {
|
|
837
|
+
this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* @param {Object} visible
|
|
842
|
+
* @param {Array} views
|
|
843
|
+
* @param {boolean} scrolledDown
|
|
844
|
+
* @param {boolean} [preRenderExtra]
|
|
845
|
+
*/
|
|
846
|
+
getHighestPriority(visible, views, scrolledDown, preRenderExtra = false) {
|
|
847
|
+
/**
|
|
848
|
+
* The state has changed. Figure out which page has the highest priority to
|
|
849
|
+
* render next (if any).
|
|
850
|
+
*
|
|
851
|
+
* Priority:
|
|
852
|
+
* 1. visible pages
|
|
853
|
+
* 2. if last scrolled down, the page after the visible pages, or
|
|
854
|
+
* if last scrolled up, the page before the visible pages
|
|
855
|
+
*/
|
|
856
|
+
const visibleViews = visible.views, numVisible = visibleViews.length;
|
|
857
|
+
if (numVisible === 0) {
|
|
858
|
+
return null;
|
|
859
|
+
}
|
|
860
|
+
for (let i = 0; i < numVisible; i++) {
|
|
861
|
+
const view = visibleViews[i].view;
|
|
862
|
+
if (!this.isViewFinished(view)) {
|
|
863
|
+
return view;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
const firstId = visible.first.id, lastId = visible.last.id;
|
|
867
|
+
// All the visible views have rendered; try to handle any "holes" in the
|
|
868
|
+
// page layout (can happen e.g. with spreadModes at higher zoom levels).
|
|
869
|
+
if (lastId - firstId + 1 > numVisible) {
|
|
870
|
+
const visibleIds = visible.ids;
|
|
871
|
+
for (let i = 1, ii = lastId - firstId; i < ii; i++) {
|
|
872
|
+
const holeId = scrolledDown ? firstId + i : lastId - i;
|
|
873
|
+
if (visibleIds.has(holeId)) {
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
const holeView = views[holeId - 1];
|
|
877
|
+
if (!this.isViewFinished(holeView)) {
|
|
878
|
+
return holeView;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
// All the visible views have rendered; try to render next/previous page.
|
|
883
|
+
// (IDs start at 1, so no need to add 1 when `scrolledDown === true`.)
|
|
884
|
+
let preRenderIndex = scrolledDown ? lastId : firstId - 2;
|
|
885
|
+
let preRenderView = views[preRenderIndex];
|
|
886
|
+
if (preRenderView && !this.isViewFinished(preRenderView)) {
|
|
887
|
+
return preRenderView;
|
|
888
|
+
}
|
|
889
|
+
if (preRenderExtra) {
|
|
890
|
+
preRenderIndex += scrolledDown ? 1 : -1;
|
|
891
|
+
preRenderView = views[preRenderIndex];
|
|
892
|
+
if (preRenderView && !this.isViewFinished(preRenderView)) {
|
|
893
|
+
return preRenderView;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
// Everything that needs to be rendered has been.
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* @param {IRenderableView} view
|
|
901
|
+
* @returns {boolean}
|
|
902
|
+
*/
|
|
903
|
+
isViewFinished(view) {
|
|
904
|
+
return view.renderingState === RenderingStates.FINISHED;
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Render a page or thumbnail view. This calls the appropriate function
|
|
908
|
+
* based on the views state. If the view is already rendered it will return
|
|
909
|
+
* `false`.
|
|
910
|
+
*
|
|
911
|
+
* @param {IRenderableView} view
|
|
912
|
+
*/
|
|
913
|
+
renderView(view) {
|
|
914
|
+
switch (view.renderingState) {
|
|
915
|
+
case RenderingStates.FINISHED:
|
|
916
|
+
return false;
|
|
917
|
+
case RenderingStates.PAUSED:
|
|
918
|
+
this.highestPriorityPage = view.renderingId;
|
|
919
|
+
view.resume();
|
|
920
|
+
break;
|
|
921
|
+
case RenderingStates.RUNNING:
|
|
922
|
+
this.highestPriorityPage = view.renderingId;
|
|
923
|
+
break;
|
|
924
|
+
case RenderingStates.INITIAL:
|
|
925
|
+
this.highestPriorityPage = view.renderingId;
|
|
926
|
+
view
|
|
927
|
+
.draw()
|
|
928
|
+
.finally(() => {
|
|
929
|
+
this.renderHighestPriority();
|
|
930
|
+
})
|
|
931
|
+
.catch(reason => {
|
|
932
|
+
if (reason instanceof RenderingCancelledException) {
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
935
|
+
console.error(`renderView: "${reason}"`);
|
|
936
|
+
});
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
return true;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
/* Copyright 2012 Mozilla Foundation
|
|
944
|
+
*
|
|
945
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
946
|
+
* you may not use this file except in compliance with the License.
|
|
947
|
+
* You may obtain a copy of the License at
|
|
948
|
+
*
|
|
949
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
950
|
+
*
|
|
951
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
952
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
953
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
954
|
+
* See the License for the specific language governing permissions and
|
|
955
|
+
* limitations under the License.
|
|
956
|
+
*/
|
|
957
|
+
var _a, _TempImageFactory_tempCanvas;
|
|
958
|
+
const DRAW_UPSCALE_FACTOR = 2; // See comment in `PDFThumbnailView.draw` below.
|
|
959
|
+
const MAX_NUM_SCALING_STEPS = 3;
|
|
960
|
+
/**
|
|
961
|
+
* @typedef {Object} PDFThumbnailViewOptions
|
|
962
|
+
* @property {HTMLDivElement} container - The viewer element.
|
|
963
|
+
* @property {number} id - The thumbnail's unique ID (normally its number).
|
|
964
|
+
* @property {PageViewport} defaultViewport - The page viewport.
|
|
965
|
+
* @property {Promise<OptionalContentConfig>} [optionalContentConfigPromise] -
|
|
966
|
+
* A promise that is resolved with an {@link OptionalContentConfig} instance.
|
|
967
|
+
* The default value is `null`.
|
|
968
|
+
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
|
969
|
+
* @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
|
|
970
|
+
* @property {IL10n} l10n - Localization service.
|
|
971
|
+
* @property {Object} [pageColors] - Overwrites background and foreground colors
|
|
972
|
+
* with user defined ones in order to improve readability in high contrast
|
|
973
|
+
* mode.
|
|
974
|
+
*/
|
|
975
|
+
class TempImageFactory {
|
|
976
|
+
static getCanvas(width, height) {
|
|
977
|
+
const tempCanvas = (__classPrivateFieldSet(this, _a, __classPrivateFieldGet(this, _a, "f", _TempImageFactory_tempCanvas) || document.createElement("canvas"), "f", _TempImageFactory_tempCanvas));
|
|
978
|
+
tempCanvas.width = width;
|
|
979
|
+
tempCanvas.height = height;
|
|
980
|
+
// Since this is a temporary canvas, we need to fill it with a white
|
|
981
|
+
// background ourselves. `_getPageDrawContext` uses CSS rules for this.
|
|
982
|
+
const ctx = tempCanvas.getContext("2d", { alpha: false });
|
|
983
|
+
ctx.save();
|
|
984
|
+
ctx.fillStyle = "rgb(255, 255, 255)";
|
|
985
|
+
ctx.fillRect(0, 0, width, height);
|
|
986
|
+
ctx.restore();
|
|
987
|
+
const c = tempCanvas.getContext("2d");
|
|
988
|
+
return [tempCanvas, c];
|
|
989
|
+
}
|
|
990
|
+
static destroyCanvas() {
|
|
991
|
+
const tempCanvas = __classPrivateFieldGet(this, _a, "f", _TempImageFactory_tempCanvas);
|
|
992
|
+
if (tempCanvas) {
|
|
993
|
+
// Zeroing the width and height causes Firefox to release graphics
|
|
994
|
+
// resources immediately, which can greatly reduce memory consumption.
|
|
995
|
+
tempCanvas.width = 0;
|
|
996
|
+
tempCanvas.height = 0;
|
|
997
|
+
}
|
|
998
|
+
__classPrivateFieldSet(this, _a, null, "f", _TempImageFactory_tempCanvas);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
_a = TempImageFactory;
|
|
1002
|
+
_TempImageFactory_tempCanvas = { value: null };
|
|
1003
|
+
/**
|
|
1004
|
+
* @implements {IRenderableView}
|
|
1005
|
+
*/
|
|
1006
|
+
class PDFThumbnailView {
|
|
1007
|
+
/**
|
|
1008
|
+
* @param {PDFThumbnailViewOptions} options
|
|
1009
|
+
*/
|
|
1010
|
+
constructor({ container, id, defaultViewport, optionalContentConfigPromise, linkService, renderingQueue, l10n, pageColors, store, thumbnailWidth }) {
|
|
1011
|
+
this.container = container;
|
|
1012
|
+
this.id = id;
|
|
1013
|
+
this.renderingId = "thumbnail" + id;
|
|
1014
|
+
this.pageLabel = null;
|
|
1015
|
+
this.store = store;
|
|
1016
|
+
this.loaded = false;
|
|
1017
|
+
this.pdfPage = null;
|
|
1018
|
+
this.rotation = 0;
|
|
1019
|
+
this.viewport = defaultViewport;
|
|
1020
|
+
this.pdfPageRotate = defaultViewport.rotation;
|
|
1021
|
+
this._optionalContentConfigPromise = optionalContentConfigPromise || null;
|
|
1022
|
+
this.pageColors = pageColors || null;
|
|
1023
|
+
this.linkService = linkService;
|
|
1024
|
+
this.renderingQueue = renderingQueue;
|
|
1025
|
+
this.renderTask = null;
|
|
1026
|
+
this.renderingState = RenderingStates.INITIAL;
|
|
1027
|
+
this.resume = null;
|
|
1028
|
+
const pageWidth = this.viewport.width, pageHeight = this.viewport.height, pageRatio = pageWidth / pageHeight;
|
|
1029
|
+
this.canvasWidth = thumbnailWidth; // THUMBNAIL_WIDTH;
|
|
1030
|
+
this.canvasHeight = (this.canvasWidth / pageRatio) | 0;
|
|
1031
|
+
this.scale = this.canvasWidth / pageWidth;
|
|
1032
|
+
this.l10n = l10n;
|
|
1033
|
+
this.canvas = null;
|
|
1034
|
+
this.src = null;
|
|
1035
|
+
const div = document.createElement("div");
|
|
1036
|
+
div.className = "thumbnail pdfSlickThumbHolder";
|
|
1037
|
+
div.setAttribute("data-page-number", this.id.toString());
|
|
1038
|
+
this.div = div;
|
|
1039
|
+
container.append(div);
|
|
1040
|
+
}
|
|
1041
|
+
setPdfPage(pdfPage) {
|
|
1042
|
+
this.pdfPage = pdfPage;
|
|
1043
|
+
this.pdfPageRotate = pdfPage.rotate;
|
|
1044
|
+
const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
|
|
1045
|
+
this.viewport = pdfPage.getViewport({ scale: 1, rotation: totalRotation });
|
|
1046
|
+
this.reset();
|
|
1047
|
+
}
|
|
1048
|
+
reset() {
|
|
1049
|
+
this.cancelRendering();
|
|
1050
|
+
this.renderingState = RenderingStates.INITIAL;
|
|
1051
|
+
const pageWidth = this.viewport.width, pageHeight = this.viewport.height, pageRatio = pageWidth / pageHeight;
|
|
1052
|
+
this.canvasHeight = (this.canvasWidth / pageRatio) | 0;
|
|
1053
|
+
this.scale = this.canvasWidth / pageWidth;
|
|
1054
|
+
this.div.removeAttribute("data-loaded");
|
|
1055
|
+
this.loaded = false;
|
|
1056
|
+
if (this.canvas) {
|
|
1057
|
+
// Zeroing the width and height causes Firefox to release graphics
|
|
1058
|
+
// resources immediately, which can greatly reduce memory consumption.
|
|
1059
|
+
this.canvas.width = 0;
|
|
1060
|
+
this.canvas.height = 0;
|
|
1061
|
+
delete this.canvas;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
update({ rotation = null }) {
|
|
1065
|
+
if (typeof rotation === "number") {
|
|
1066
|
+
this.rotation = rotation; // The rotation may be zero.
|
|
1067
|
+
}
|
|
1068
|
+
const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
|
|
1069
|
+
this.viewport = this.viewport.clone({
|
|
1070
|
+
scale: 1,
|
|
1071
|
+
rotation: totalRotation,
|
|
1072
|
+
});
|
|
1073
|
+
this.reset();
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* PLEASE NOTE: Most likely you want to use the `this.reset()` method,
|
|
1077
|
+
* rather than calling this one directly.
|
|
1078
|
+
*/
|
|
1079
|
+
cancelRendering() {
|
|
1080
|
+
if (this.renderTask) {
|
|
1081
|
+
this.renderTask.cancel();
|
|
1082
|
+
this.renderTask = null;
|
|
1083
|
+
}
|
|
1084
|
+
this.resume = null;
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* @private
|
|
1088
|
+
*/
|
|
1089
|
+
_getPageDrawContext(upscaleFactor = 1) {
|
|
1090
|
+
// Keep the no-thumbnail outline visible, i.e. `data-loaded === false`,
|
|
1091
|
+
// until rendering/image conversion is complete, to avoid display issues.
|
|
1092
|
+
const canvas = document.createElement("canvas");
|
|
1093
|
+
const ctx = canvas.getContext("2d", { alpha: false });
|
|
1094
|
+
const outputScale = new OutputScale();
|
|
1095
|
+
canvas.width = (upscaleFactor * this.canvasWidth * outputScale.sx) | 0;
|
|
1096
|
+
canvas.height = (upscaleFactor * this.canvasHeight * outputScale.sy) | 0;
|
|
1097
|
+
const transform = outputScale.scaled
|
|
1098
|
+
? [outputScale.sx, 0, 0, outputScale.sy, 0, 0]
|
|
1099
|
+
: null;
|
|
1100
|
+
return { ctx, canvas, transform };
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* @private
|
|
1104
|
+
*/
|
|
1105
|
+
_convertCanvasToImage(canvas) {
|
|
1106
|
+
if (this.renderingState !== RenderingStates.FINISHED) {
|
|
1107
|
+
throw new Error("_convertCanvasToImage: Rendering has not finished.");
|
|
1108
|
+
}
|
|
1109
|
+
const reducedCanvas = this._reduceImage(canvas);
|
|
1110
|
+
this.src = reducedCanvas.toDataURL();
|
|
1111
|
+
this.div.setAttribute("data-loaded", "true");
|
|
1112
|
+
this.loaded = true;
|
|
1113
|
+
// this.store.getState()._setThumbnail(this.id, this.src)
|
|
1114
|
+
this.store.getState()._setThumbnailView(this.id, this);
|
|
1115
|
+
// Zeroing the width and height causes Firefox to release graphics
|
|
1116
|
+
// resources immediately, which can greatly reduce memory consumption.
|
|
1117
|
+
reducedCanvas.width = 0;
|
|
1118
|
+
reducedCanvas.height = 0;
|
|
1119
|
+
}
|
|
1120
|
+
draw() {
|
|
1121
|
+
if (this.renderingState !== RenderingStates.INITIAL) {
|
|
1122
|
+
console.error("Must be in new state before drawing");
|
|
1123
|
+
return Promise.resolve();
|
|
1124
|
+
}
|
|
1125
|
+
const { pdfPage } = this;
|
|
1126
|
+
if (!pdfPage) {
|
|
1127
|
+
this.renderingState = RenderingStates.FINISHED;
|
|
1128
|
+
return Promise.reject(new Error("pdfPage is not loaded"));
|
|
1129
|
+
}
|
|
1130
|
+
this.renderingState = RenderingStates.RUNNING;
|
|
1131
|
+
const finishRenderTask = (error = null) => __awaiter(this, void 0, void 0, function* () {
|
|
1132
|
+
// The renderTask may have been replaced by a new one, so only remove
|
|
1133
|
+
// the reference to the renderTask if it matches the one that is
|
|
1134
|
+
// triggering this callback.
|
|
1135
|
+
if (renderTask === this.renderTask) {
|
|
1136
|
+
this.renderTask = null;
|
|
1137
|
+
}
|
|
1138
|
+
if (error instanceof RenderingCancelledException) {
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
this.renderingState = RenderingStates.FINISHED;
|
|
1142
|
+
this._convertCanvasToImage(canvas);
|
|
1143
|
+
if (error) {
|
|
1144
|
+
throw error;
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
// Render the thumbnail at a larger size and downsize the canvas (similar
|
|
1148
|
+
// to `setImage`), to improve consistency between thumbnails created by
|
|
1149
|
+
// the `draw` and `setImage` methods (fixes issue 8233).
|
|
1150
|
+
// NOTE: To primarily avoid increasing memory usage too much, but also to
|
|
1151
|
+
// reduce downsizing overhead, we purposely limit the up-scaling factor.
|
|
1152
|
+
const { ctx, canvas, transform } = this._getPageDrawContext(DRAW_UPSCALE_FACTOR);
|
|
1153
|
+
const drawViewport = this.viewport.clone({
|
|
1154
|
+
scale: DRAW_UPSCALE_FACTOR * this.scale,
|
|
1155
|
+
});
|
|
1156
|
+
const renderContinueCallback = (cont) => {
|
|
1157
|
+
if (!this.renderingQueue.isHighestPriority(this)) {
|
|
1158
|
+
this.renderingState = RenderingStates.PAUSED;
|
|
1159
|
+
this.resume = () => {
|
|
1160
|
+
this.renderingState = RenderingStates.RUNNING;
|
|
1161
|
+
cont();
|
|
1162
|
+
};
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
cont();
|
|
1166
|
+
};
|
|
1167
|
+
const renderContext = {
|
|
1168
|
+
canvasContext: ctx,
|
|
1169
|
+
transform,
|
|
1170
|
+
viewport: drawViewport,
|
|
1171
|
+
optionalContentConfigPromise: this._optionalContentConfigPromise,
|
|
1172
|
+
pageColors: this.pageColors,
|
|
1173
|
+
};
|
|
1174
|
+
const renderTask = (this.renderTask = pdfPage.render(renderContext));
|
|
1175
|
+
renderTask.onContinue = renderContinueCallback;
|
|
1176
|
+
const resultPromise = renderTask.promise.then(function () {
|
|
1177
|
+
return finishRenderTask(null);
|
|
1178
|
+
}, function (error) {
|
|
1179
|
+
return finishRenderTask(error);
|
|
1180
|
+
});
|
|
1181
|
+
resultPromise.finally(() => {
|
|
1182
|
+
var _b;
|
|
1183
|
+
// Zeroing the width and height causes Firefox to release graphics
|
|
1184
|
+
// resources immediately, which can greatly reduce memory consumption.
|
|
1185
|
+
canvas.width = 0;
|
|
1186
|
+
canvas.height = 0;
|
|
1187
|
+
// Only trigger cleanup, once rendering has finished, when the current
|
|
1188
|
+
// pageView is *not* cached on the `BaseViewer`-instance.
|
|
1189
|
+
const pageCached = this.linkService.isPageCached(this.id);
|
|
1190
|
+
if (!pageCached) {
|
|
1191
|
+
(_b = this.pdfPage) === null || _b === void 0 ? void 0 : _b.cleanup();
|
|
1192
|
+
}
|
|
1193
|
+
});
|
|
1194
|
+
return resultPromise;
|
|
1195
|
+
}
|
|
1196
|
+
setImage(pageView) {
|
|
1197
|
+
if (this.renderingState !== RenderingStates.INITIAL) {
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
const { thumbnailCanvas: canvas, pdfPage, scale } = pageView;
|
|
1201
|
+
if (!canvas) {
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1204
|
+
if (!this.pdfPage) {
|
|
1205
|
+
this.setPdfPage(pdfPage);
|
|
1206
|
+
}
|
|
1207
|
+
if (scale < this.scale) {
|
|
1208
|
+
// Avoid upscaling the image, since that makes the thumbnail look blurry.
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
this.renderingState = RenderingStates.FINISHED;
|
|
1212
|
+
this._convertCanvasToImage(canvas);
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* @private
|
|
1216
|
+
*/
|
|
1217
|
+
_reduceImage(img) {
|
|
1218
|
+
const { ctx, canvas } = this._getPageDrawContext();
|
|
1219
|
+
if (img.width <= 2 * canvas.width) {
|
|
1220
|
+
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
|
|
1221
|
+
return canvas;
|
|
1222
|
+
}
|
|
1223
|
+
// drawImage does an awful job of rescaling the image, doing it gradually.
|
|
1224
|
+
let reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS;
|
|
1225
|
+
let reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS;
|
|
1226
|
+
const [reducedImage, reducedImageCtx] = TempImageFactory.getCanvas(reducedWidth, reducedHeight);
|
|
1227
|
+
while (reducedWidth > img.width || reducedHeight > img.height) {
|
|
1228
|
+
reducedWidth >>= 1;
|
|
1229
|
+
reducedHeight >>= 1;
|
|
1230
|
+
}
|
|
1231
|
+
reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight);
|
|
1232
|
+
while (reducedWidth > 2 * canvas.width) {
|
|
1233
|
+
reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1);
|
|
1234
|
+
reducedWidth >>= 1;
|
|
1235
|
+
reducedHeight >>= 1;
|
|
1236
|
+
}
|
|
1237
|
+
ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height);
|
|
1238
|
+
return canvas;
|
|
1239
|
+
}
|
|
1240
|
+
get _thumbPageTitle() {
|
|
1241
|
+
var _b;
|
|
1242
|
+
return this.l10n.get("thumb_page_title", {
|
|
1243
|
+
page: (_b = this.pageLabel) !== null && _b !== void 0 ? _b : this.id,
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
get _thumbPageCanvas() {
|
|
1247
|
+
var _b;
|
|
1248
|
+
return this.l10n.get("thumb_page_canvas", {
|
|
1249
|
+
page: ((_b = this.pageLabel) !== null && _b !== void 0 ? _b : this.id),
|
|
1250
|
+
});
|
|
1251
|
+
}
|
|
1252
|
+
/**
|
|
1253
|
+
* @param {string|null} label
|
|
1254
|
+
*/
|
|
1255
|
+
setPageLabel(label) {
|
|
1256
|
+
this.pageLabel = typeof label === "string" ? label : null;
|
|
1257
|
+
// this._thumbPageTitle.then((msg: string) => {
|
|
1258
|
+
// this.anchor.title = msg;
|
|
1259
|
+
// });
|
|
1260
|
+
// if (this.renderingState !== RenderingStates.FINISHED) {
|
|
1261
|
+
// return;
|
|
1262
|
+
// }
|
|
1263
|
+
// this._thumbPageCanvas.then((msg: string) => {
|
|
1264
|
+
// this.image?.setAttribute("aria-label", msg);
|
|
1265
|
+
// });
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/* Copyright 2012 Mozilla Foundation
|
|
1270
|
+
*
|
|
1271
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1272
|
+
* you may not use this file except in compliance with the License.
|
|
1273
|
+
* You may obtain a copy of the License at
|
|
1274
|
+
*
|
|
1275
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1276
|
+
*
|
|
1277
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1278
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1279
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1280
|
+
* See the License for the specific language governing permissions and
|
|
1281
|
+
* limitations under the License.
|
|
1282
|
+
*/
|
|
1283
|
+
var _PDFThumbnailViewer_instances, _PDFThumbnailViewer_ensurePdfPageLoaded, _PDFThumbnailViewer_getScrollAhead;
|
|
1284
|
+
const THUMBNAIL_SCROLL_MARGIN = -19;
|
|
1285
|
+
const THUMBNAIL_SELECTED_CLASS = "selected";
|
|
1286
|
+
/**
|
|
1287
|
+
* @typedef {Object} PDFThumbnailViewerOptions
|
|
1288
|
+
* @property {HTMLDivElement} container - The container for the thumbnail
|
|
1289
|
+
* elements.
|
|
1290
|
+
* @property {IPDFLinkService} linkService - The navigation/linking service.
|
|
1291
|
+
* @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
|
|
1292
|
+
* @property {IL10n} l10n - Localization service.
|
|
1293
|
+
* @property {Object} [pageColors] - Overwrites background and foreground colors
|
|
1294
|
+
* with user defined ones in order to improve readability in high contrast
|
|
1295
|
+
* mode.
|
|
1296
|
+
*/
|
|
1297
|
+
/**
|
|
1298
|
+
* Viewer control to display thumbnails for pages in a PDF document.
|
|
1299
|
+
*/
|
|
1300
|
+
class PDFThumbnailViewer {
|
|
1301
|
+
/**
|
|
1302
|
+
* @param {PDFThumbnailViewerOptions} options
|
|
1303
|
+
*/
|
|
1304
|
+
constructor({ container, linkService, renderingQueue, l10n, pageColors, store, thumbnailWidth }) {
|
|
1305
|
+
_PDFThumbnailViewer_instances.add(this);
|
|
1306
|
+
this.container = container;
|
|
1307
|
+
this.linkService = linkService;
|
|
1308
|
+
this.renderingQueue = renderingQueue;
|
|
1309
|
+
this.l10n = l10n;
|
|
1310
|
+
this.pageColors = pageColors || null;
|
|
1311
|
+
this._thumbnails = [];
|
|
1312
|
+
this._currentPageNumber = 0;
|
|
1313
|
+
this._pagesRotation = 0;
|
|
1314
|
+
this._pageLabels = [];
|
|
1315
|
+
this.pdfDocument = null;
|
|
1316
|
+
this.store = store;
|
|
1317
|
+
this.thumbnailWidth = thumbnailWidth;
|
|
1318
|
+
if (this.pageColors &&
|
|
1319
|
+
!(CSS.supports("color", this.pageColors.background) &&
|
|
1320
|
+
CSS.supports("color", this.pageColors.foreground))) {
|
|
1321
|
+
if (this.pageColors.background || this.pageColors.foreground) {
|
|
1322
|
+
console.warn("PDFThumbnailViewer: Ignoring `pageColors`-option, since the browser doesn't support the values used.");
|
|
1323
|
+
}
|
|
1324
|
+
this.pageColors = null;
|
|
1325
|
+
}
|
|
1326
|
+
this.scroll = watchScroll(this.container, this._scrollUpdated.bind(this));
|
|
1327
|
+
this._resetView();
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* @private
|
|
1331
|
+
*/
|
|
1332
|
+
_scrollUpdated() {
|
|
1333
|
+
this.renderingQueue.renderHighestPriority();
|
|
1334
|
+
}
|
|
1335
|
+
getThumbnail(index) {
|
|
1336
|
+
return this._thumbnails[index];
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* @private
|
|
1340
|
+
*/
|
|
1341
|
+
_getVisibleThumbs() {
|
|
1342
|
+
return getVisibleElements({
|
|
1343
|
+
scrollEl: this.container,
|
|
1344
|
+
views: this._thumbnails
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
scrollThumbnailIntoView(pageNumber) {
|
|
1348
|
+
if (!this.pdfDocument) {
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
const thumbnailView = this._thumbnails[pageNumber - 1];
|
|
1352
|
+
if (!thumbnailView) {
|
|
1353
|
+
console.error('scrollThumbnailIntoView: Invalid "pageNumber" parameter.');
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
if (pageNumber !== this._currentPageNumber) {
|
|
1357
|
+
const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1];
|
|
1358
|
+
// Remove the highlight from the previous thumbnail...
|
|
1359
|
+
prevThumbnailView.div.classList.remove(THUMBNAIL_SELECTED_CLASS);
|
|
1360
|
+
// ... and add the highlight to the new thumbnail.
|
|
1361
|
+
thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS);
|
|
1362
|
+
}
|
|
1363
|
+
const visibleThumbs = this._getVisibleThumbs();
|
|
1364
|
+
const { first, last, views } = visibleThumbs;
|
|
1365
|
+
// If the thumbnail isn't currently visible, scroll it into view.
|
|
1366
|
+
if (views.length > 0) {
|
|
1367
|
+
let shouldScroll = false;
|
|
1368
|
+
if (pageNumber <= first.id || pageNumber >= (last === null || last === void 0 ? void 0 : last.id)) {
|
|
1369
|
+
shouldScroll = true;
|
|
1370
|
+
}
|
|
1371
|
+
else {
|
|
1372
|
+
for (const { id, percent } of views) {
|
|
1373
|
+
if (id !== pageNumber) {
|
|
1374
|
+
continue;
|
|
1375
|
+
}
|
|
1376
|
+
shouldScroll = percent < 100;
|
|
1377
|
+
break;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
if (shouldScroll) {
|
|
1381
|
+
scrollIntoView(thumbnailView.div, { top: THUMBNAIL_SCROLL_MARGIN });
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
this._currentPageNumber = pageNumber;
|
|
1385
|
+
this.forceRendering();
|
|
1386
|
+
}
|
|
1387
|
+
get pagesRotation() {
|
|
1388
|
+
return this._pagesRotation;
|
|
1389
|
+
}
|
|
1390
|
+
set pagesRotation(rotation) {
|
|
1391
|
+
if (!isValidRotation(rotation)) {
|
|
1392
|
+
throw new Error("Invalid thumbnails rotation angle.");
|
|
1393
|
+
}
|
|
1394
|
+
if (!this.pdfDocument) {
|
|
1395
|
+
return;
|
|
1396
|
+
}
|
|
1397
|
+
if (this._pagesRotation === rotation) {
|
|
1398
|
+
return; // The rotation didn't change.
|
|
1399
|
+
}
|
|
1400
|
+
this._pagesRotation = rotation;
|
|
1401
|
+
const updateArgs = { rotation: rotation };
|
|
1402
|
+
for (const thumbnail of this._thumbnails) {
|
|
1403
|
+
thumbnail.update(updateArgs);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
cleanup() {
|
|
1407
|
+
for (const thumbnail of this._thumbnails) {
|
|
1408
|
+
if (thumbnail.renderingState !== RenderingStates.FINISHED) {
|
|
1409
|
+
thumbnail.reset();
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
TempImageFactory.destroyCanvas();
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* @private
|
|
1416
|
+
*/
|
|
1417
|
+
_resetView() {
|
|
1418
|
+
this._thumbnails = [];
|
|
1419
|
+
this._currentPageNumber = 1;
|
|
1420
|
+
this._pageLabels = [];
|
|
1421
|
+
this._pagesRotation = 0;
|
|
1422
|
+
// Remove the thumbnails from the DOM.
|
|
1423
|
+
this.container.textContent = "";
|
|
1424
|
+
}
|
|
1425
|
+
/**
|
|
1426
|
+
* @param {PDFDocumentProxy} pdfDocument
|
|
1427
|
+
*/
|
|
1428
|
+
setDocument(pdfDocument) {
|
|
1429
|
+
if (this.pdfDocument) {
|
|
1430
|
+
this._cancelRendering();
|
|
1431
|
+
this._resetView();
|
|
1432
|
+
}
|
|
1433
|
+
this.pdfDocument = pdfDocument;
|
|
1434
|
+
if (!pdfDocument) {
|
|
1435
|
+
return;
|
|
1436
|
+
}
|
|
1437
|
+
const firstPagePromise = pdfDocument.getPage(1);
|
|
1438
|
+
const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
|
|
1439
|
+
firstPagePromise
|
|
1440
|
+
.then(firstPdfPage => {
|
|
1441
|
+
var _a;
|
|
1442
|
+
const pagesCount = pdfDocument.numPages;
|
|
1443
|
+
const viewport = firstPdfPage.getViewport({ scale: 1 });
|
|
1444
|
+
for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
|
1445
|
+
const thumbnail = new PDFThumbnailView({
|
|
1446
|
+
container: this.container,
|
|
1447
|
+
id: pageNum,
|
|
1448
|
+
defaultViewport: viewport.clone(),
|
|
1449
|
+
optionalContentConfigPromise,
|
|
1450
|
+
linkService: this.linkService,
|
|
1451
|
+
renderingQueue: this.renderingQueue,
|
|
1452
|
+
l10n: this.l10n,
|
|
1453
|
+
pageColors: this.pageColors,
|
|
1454
|
+
store: this.store,
|
|
1455
|
+
thumbnailWidth: this.thumbnailWidth
|
|
1456
|
+
});
|
|
1457
|
+
this._thumbnails.push(thumbnail);
|
|
1458
|
+
}
|
|
1459
|
+
// Set the first `pdfPage` immediately, since it's already loaded,
|
|
1460
|
+
// rather than having to repeat the `PDFDocumentProxy.getPage` call in
|
|
1461
|
+
// the `this.#ensurePdfPageLoaded` method before rendering can start.
|
|
1462
|
+
(_a = this._thumbnails[0]) === null || _a === void 0 ? void 0 : _a.setPdfPage(firstPdfPage);
|
|
1463
|
+
// Ensure that the current thumbnail is always highlighted on load.
|
|
1464
|
+
const thumbnailView = this._thumbnails[this._currentPageNumber - 1];
|
|
1465
|
+
thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS);
|
|
1466
|
+
this.store.getState()._setThumbnailsViews(this._thumbnails);
|
|
1467
|
+
})
|
|
1468
|
+
.catch(reason => {
|
|
1469
|
+
console.error("Unable to initialize thumbnail viewer", reason);
|
|
1470
|
+
});
|
|
1471
|
+
}
|
|
1472
|
+
/**
|
|
1473
|
+
* @private
|
|
1474
|
+
*/
|
|
1475
|
+
_cancelRendering() {
|
|
1476
|
+
for (const thumbnail of this._thumbnails) {
|
|
1477
|
+
thumbnail.cancelRendering();
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
/**
|
|
1481
|
+
* @param {Array|null} labels
|
|
1482
|
+
*/
|
|
1483
|
+
setPageLabels(labels) {
|
|
1484
|
+
var _a, _b;
|
|
1485
|
+
if (!this.pdfDocument) {
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
if (!labels) {
|
|
1489
|
+
this._pageLabels = [];
|
|
1490
|
+
}
|
|
1491
|
+
else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {
|
|
1492
|
+
this._pageLabels = [];
|
|
1493
|
+
console.error("PDFThumbnailViewer_setPageLabels: Invalid page labels.");
|
|
1494
|
+
}
|
|
1495
|
+
else {
|
|
1496
|
+
this._pageLabels = labels;
|
|
1497
|
+
}
|
|
1498
|
+
// Update all the `PDFThumbnailView` instances.
|
|
1499
|
+
for (let i = 0, ii = this._thumbnails.length; i < ii; i++) {
|
|
1500
|
+
this._thumbnails[i].setPageLabel((_b = (_a = this._pageLabels) === null || _a === void 0 ? void 0 : _a[i]) !== null && _b !== void 0 ? _b : null);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
forceRendering() {
|
|
1504
|
+
const visibleThumbs = this._getVisibleThumbs();
|
|
1505
|
+
// console.log(`forceRendering, visibleThumbs: `, visibleThumbs)
|
|
1506
|
+
const scrollAhead = __classPrivateFieldGet(this, _PDFThumbnailViewer_instances, "m", _PDFThumbnailViewer_getScrollAhead).call(this, visibleThumbs);
|
|
1507
|
+
const thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, this._thumbnails, scrollAhead);
|
|
1508
|
+
// console.log(`forceRendering, thumbView: `, thumbView)
|
|
1509
|
+
if (thumbView) {
|
|
1510
|
+
__classPrivateFieldGet(this, _PDFThumbnailViewer_instances, "m", _PDFThumbnailViewer_ensurePdfPageLoaded).call(this, thumbView).then(() => {
|
|
1511
|
+
this.renderingQueue.renderView(thumbView);
|
|
1512
|
+
});
|
|
1513
|
+
return true;
|
|
1514
|
+
}
|
|
1515
|
+
return false;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
_PDFThumbnailViewer_instances = new WeakSet(), _PDFThumbnailViewer_ensurePdfPageLoaded = function _PDFThumbnailViewer_ensurePdfPageLoaded(thumbView) {
|
|
1519
|
+
var _a;
|
|
1520
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1521
|
+
if (thumbView === null || thumbView === void 0 ? void 0 : thumbView.pdfPage) {
|
|
1522
|
+
return thumbView.pdfPage;
|
|
1523
|
+
}
|
|
1524
|
+
try {
|
|
1525
|
+
const pdfPage = yield ((_a = this.pdfDocument) === null || _a === void 0 ? void 0 : _a.getPage(thumbView.id));
|
|
1526
|
+
if (!(thumbView === null || thumbView === void 0 ? void 0 : thumbView.pdfPage)) {
|
|
1527
|
+
thumbView.setPdfPage(pdfPage);
|
|
1528
|
+
}
|
|
1529
|
+
return pdfPage;
|
|
1530
|
+
}
|
|
1531
|
+
catch (reason) {
|
|
1532
|
+
console.error("Unable to get page for thumb view", reason);
|
|
1533
|
+
return null; // Page error -- there is nothing that can be done.
|
|
1534
|
+
}
|
|
1535
|
+
});
|
|
1536
|
+
}, _PDFThumbnailViewer_getScrollAhead = function _PDFThumbnailViewer_getScrollAhead(visible) {
|
|
1537
|
+
var _a, _b;
|
|
1538
|
+
// console.log(`visible: `, visible)
|
|
1539
|
+
if (((_a = visible.first) === null || _a === void 0 ? void 0 : _a.id) === 1) {
|
|
1540
|
+
return true;
|
|
1541
|
+
}
|
|
1542
|
+
else if (((_b = visible.last) === null || _b === void 0 ? void 0 : _b.id) === this._thumbnails.length) {
|
|
1543
|
+
return false;
|
|
1544
|
+
}
|
|
1545
|
+
return this.scroll.down;
|
|
1546
|
+
};
|
|
1547
|
+
|
|
1548
|
+
/* Copyright 2014 Mozilla Foundation
|
|
1549
|
+
*
|
|
1550
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1551
|
+
* you may not use this file except in compliance with the License.
|
|
1552
|
+
* You may obtain a copy of the License at
|
|
1553
|
+
*
|
|
1554
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1555
|
+
*
|
|
1556
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1557
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1558
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1559
|
+
* See the License for the specific language governing permissions and
|
|
1560
|
+
* limitations under the License.
|
|
1561
|
+
*/
|
|
1562
|
+
var _OverlayManager_overlays, _OverlayManager_active;
|
|
1563
|
+
class OverlayManager {
|
|
1564
|
+
constructor() {
|
|
1565
|
+
_OverlayManager_overlays.set(this, new WeakMap());
|
|
1566
|
+
_OverlayManager_active.set(this, null);
|
|
1567
|
+
}
|
|
1568
|
+
get active() {
|
|
1569
|
+
return __classPrivateFieldGet(this, _OverlayManager_active, "f");
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
|
|
1573
|
+
* @param {boolean} [canForceClose] - Indicates if opening the overlay closes
|
|
1574
|
+
* an active overlay. The default is `false`.
|
|
1575
|
+
* @returns {Promise} A promise that is resolved when the overlay has been
|
|
1576
|
+
* registered.
|
|
1577
|
+
*/
|
|
1578
|
+
register(dialog, canForceClose = false) {
|
|
1579
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1580
|
+
if (typeof dialog !== "object") {
|
|
1581
|
+
throw new Error("Not enough parameters.");
|
|
1582
|
+
}
|
|
1583
|
+
else if (__classPrivateFieldGet(this, _OverlayManager_overlays, "f").has(dialog)) {
|
|
1584
|
+
throw new Error("The overlay is already registered.");
|
|
1585
|
+
}
|
|
1586
|
+
__classPrivateFieldGet(this, _OverlayManager_overlays, "f").set(dialog, { canForceClose });
|
|
1587
|
+
dialog.addEventListener("cancel", () => {
|
|
1588
|
+
__classPrivateFieldSet(this, _OverlayManager_active, null, "f");
|
|
1589
|
+
});
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
/**
|
|
1593
|
+
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
|
|
1594
|
+
* @returns {Promise} A promise that is resolved when the overlay has been
|
|
1595
|
+
* unregistered.
|
|
1596
|
+
*/
|
|
1597
|
+
unregister(dialog) {
|
|
1598
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1599
|
+
if (!__classPrivateFieldGet(this, _OverlayManager_overlays, "f").has(dialog)) {
|
|
1600
|
+
throw new Error("The overlay does not exist.");
|
|
1601
|
+
}
|
|
1602
|
+
else if (__classPrivateFieldGet(this, _OverlayManager_active, "f") === dialog) {
|
|
1603
|
+
throw new Error("The overlay cannot be removed while it is active.");
|
|
1604
|
+
}
|
|
1605
|
+
__classPrivateFieldGet(this, _OverlayManager_overlays, "f").delete(dialog);
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
/**
|
|
1609
|
+
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
|
|
1610
|
+
* @returns {Promise} A promise that is resolved when the overlay has been
|
|
1611
|
+
* opened.
|
|
1612
|
+
*/
|
|
1613
|
+
open(dialog) {
|
|
1614
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1615
|
+
if (!__classPrivateFieldGet(this, _OverlayManager_overlays, "f").has(dialog)) {
|
|
1616
|
+
throw new Error("The overlay does not exist.");
|
|
1617
|
+
}
|
|
1618
|
+
else if (__classPrivateFieldGet(this, _OverlayManager_active, "f")) {
|
|
1619
|
+
if (__classPrivateFieldGet(this, _OverlayManager_active, "f") === dialog) {
|
|
1620
|
+
throw new Error("The overlay is already active.");
|
|
1621
|
+
}
|
|
1622
|
+
else if (__classPrivateFieldGet(this, _OverlayManager_overlays, "f").get(dialog).canForceClose) {
|
|
1623
|
+
yield this.close();
|
|
1624
|
+
}
|
|
1625
|
+
else {
|
|
1626
|
+
throw new Error("Another overlay is currently active.");
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
__classPrivateFieldSet(this, _OverlayManager_active, dialog, "f");
|
|
1630
|
+
dialog.showModal();
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
/**
|
|
1634
|
+
* @param {HTMLDialogElement} dialog - The overlay's DOM element.
|
|
1635
|
+
* @returns {Promise} A promise that is resolved when the overlay has been
|
|
1636
|
+
* closed.
|
|
1637
|
+
*/
|
|
1638
|
+
close(dialog = __classPrivateFieldGet(this, _OverlayManager_active, "f")) {
|
|
1639
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1640
|
+
if (!dialog || !__classPrivateFieldGet(this, _OverlayManager_overlays, "f").has(dialog)) {
|
|
1641
|
+
throw new Error("The overlay does not exist.");
|
|
1642
|
+
}
|
|
1643
|
+
else if (!__classPrivateFieldGet(this, _OverlayManager_active, "f")) {
|
|
1644
|
+
throw new Error("The overlay is currently not active.");
|
|
1645
|
+
}
|
|
1646
|
+
else if (__classPrivateFieldGet(this, _OverlayManager_active, "f") !== dialog) {
|
|
1647
|
+
throw new Error("Another overlay is currently active.");
|
|
1648
|
+
}
|
|
1649
|
+
dialog.close();
|
|
1650
|
+
__classPrivateFieldSet(this, _OverlayManager_active, null, "f");
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
_OverlayManager_overlays = new WeakMap(), _OverlayManager_active = new WeakMap();
|
|
1655
|
+
|
|
1656
|
+
/* Copyright 2016 Mozilla Foundation
|
|
1657
|
+
*
|
|
1658
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1659
|
+
* you may not use this file except in compliance with the License.
|
|
1660
|
+
* You may obtain a copy of the License at
|
|
1661
|
+
*
|
|
1662
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1663
|
+
*
|
|
1664
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1665
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1666
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1667
|
+
* See the License for the specific language governing permissions and
|
|
1668
|
+
* limitations under the License.
|
|
1669
|
+
*/
|
|
1670
|
+
//
|
|
1671
|
+
// https://github.com/mozilla/pdf.js/blob/master/web/print_utils.js
|
|
1672
|
+
//
|
|
1673
|
+
function getXfaHtmlForPrinting(printContainer, pdfDocument) {
|
|
1674
|
+
const xfaHtml = pdfDocument.allXfaHtml;
|
|
1675
|
+
const linkService = new SimpleLinkService();
|
|
1676
|
+
const scale = Math.round(PixelsPerInch.PDF_TO_CSS_UNITS * 100) / 100;
|
|
1677
|
+
for (const xfaPage of xfaHtml === null || xfaHtml === void 0 ? void 0 : xfaHtml.children) {
|
|
1678
|
+
const page = document.createElement("div");
|
|
1679
|
+
page.className = "xfaPrintedPage";
|
|
1680
|
+
printContainer.append(page);
|
|
1681
|
+
const builder = new XfaLayerBuilder({
|
|
1682
|
+
pageDiv: page,
|
|
1683
|
+
pdfPage: null,
|
|
1684
|
+
annotationStorage: pdfDocument.annotationStorage,
|
|
1685
|
+
linkService,
|
|
1686
|
+
xfaHtml: xfaPage,
|
|
1687
|
+
});
|
|
1688
|
+
const viewport = getXfaPageViewport(xfaPage, { scale });
|
|
1689
|
+
builder.render(viewport, "print");
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
let activeService = null;
|
|
1693
|
+
let dialog = null;
|
|
1694
|
+
let overlayManager = new OverlayManager;
|
|
1695
|
+
// Renders the page to the canvas of the given print service, and returns
|
|
1696
|
+
// the suggested dimensions of the output page.
|
|
1697
|
+
function renderPage(activeServiceOnEntry, pdfDocument, pageNumber, size, printResolution, optionalContentConfigPromise, printAnnotationStoragePromise) {
|
|
1698
|
+
const scratchCanvas = activeService.scratchCanvas;
|
|
1699
|
+
// The size of the canvas in pixels for printing.
|
|
1700
|
+
const PRINT_UNITS = printResolution / PixelsPerInch.PDF;
|
|
1701
|
+
scratchCanvas.width = Math.floor(size.width * PRINT_UNITS);
|
|
1702
|
+
scratchCanvas.height = Math.floor(size.height * PRINT_UNITS);
|
|
1703
|
+
const ctx = scratchCanvas.getContext("2d");
|
|
1704
|
+
ctx.save();
|
|
1705
|
+
ctx.fillStyle = "rgb(255, 255, 255)";
|
|
1706
|
+
ctx.fillRect(0, 0, scratchCanvas.width, scratchCanvas.height);
|
|
1707
|
+
ctx.restore();
|
|
1708
|
+
return Promise.all([
|
|
1709
|
+
pdfDocument.getPage(pageNumber),
|
|
1710
|
+
printAnnotationStoragePromise,
|
|
1711
|
+
]).then(function ([pdfPage, printAnnotationStorage]) {
|
|
1712
|
+
const renderContext = {
|
|
1713
|
+
canvasContext: ctx,
|
|
1714
|
+
transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
|
|
1715
|
+
viewport: pdfPage.getViewport({ scale: 1, rotation: size.rotation }),
|
|
1716
|
+
intent: "print",
|
|
1717
|
+
annotationMode: AnnotationMode.ENABLE_STORAGE,
|
|
1718
|
+
optionalContentConfigPromise,
|
|
1719
|
+
printAnnotationStorage,
|
|
1720
|
+
};
|
|
1721
|
+
return pdfPage.render(renderContext).promise;
|
|
1722
|
+
});
|
|
1723
|
+
}
|
|
1724
|
+
class PDFPrintService {
|
|
1725
|
+
constructor(pdfDocument, pagesOverview, printContainer, printResolution, optionalContentConfigPromise = null, printAnnotationStoragePromise = null, l10n) {
|
|
1726
|
+
this.pdfDocument = pdfDocument;
|
|
1727
|
+
this.pagesOverview = pagesOverview;
|
|
1728
|
+
this.printContainer = printContainer;
|
|
1729
|
+
this._printResolution = printResolution || 150;
|
|
1730
|
+
this._optionalContentConfigPromise =
|
|
1731
|
+
optionalContentConfigPromise || pdfDocument.getOptionalContentConfig();
|
|
1732
|
+
this._printAnnotationStoragePromise =
|
|
1733
|
+
printAnnotationStoragePromise || Promise.resolve();
|
|
1734
|
+
this.l10n = l10n;
|
|
1735
|
+
this.currentPage = -1;
|
|
1736
|
+
// The temporary canvas where renderPage paints one page at a time.
|
|
1737
|
+
this.scratchCanvas = document.createElement("canvas");
|
|
1738
|
+
}
|
|
1739
|
+
layout() {
|
|
1740
|
+
this.throwIfInactive();
|
|
1741
|
+
const body = document.querySelector("body");
|
|
1742
|
+
body === null || body === void 0 ? void 0 : body.setAttribute("data-pdfjsprinting", "true");
|
|
1743
|
+
const hasEqualPageSizes = this.pagesOverview.every((size) => {
|
|
1744
|
+
return (size.width === this.pagesOverview[0].width &&
|
|
1745
|
+
size.height === this.pagesOverview[0].height);
|
|
1746
|
+
}, this);
|
|
1747
|
+
if (!hasEqualPageSizes) {
|
|
1748
|
+
console.warn("Not all pages have the same size. The printed " +
|
|
1749
|
+
"result may be incorrect!");
|
|
1750
|
+
}
|
|
1751
|
+
// Insert a @page + size rule to make sure that the page size is correctly
|
|
1752
|
+
// set. Note that we assume that all pages have the same size, because
|
|
1753
|
+
// variable-size pages are not supported yet (e.g. in Chrome & Firefox).
|
|
1754
|
+
// TODO(robwu): Use named pages when size calculation bugs get resolved
|
|
1755
|
+
// (e.g. https://crbug.com/355116) AND when support for named pages is
|
|
1756
|
+
// added (http://www.w3.org/TR/css3-page/#using-named-pages).
|
|
1757
|
+
// In browsers where @page + size is not supported (such as Firefox,
|
|
1758
|
+
// https://bugzil.la/851441), the next stylesheet will be ignored and the
|
|
1759
|
+
// user has to select the correct paper size in the UI if wanted.
|
|
1760
|
+
this.pageStyleSheet = document.createElement("style");
|
|
1761
|
+
const pageSize = this.pagesOverview[0];
|
|
1762
|
+
this.pageStyleSheet.textContent =
|
|
1763
|
+
"@page { size: " + pageSize.width + "pt " + pageSize.height + "pt;}";
|
|
1764
|
+
body === null || body === void 0 ? void 0 : body.append(this.pageStyleSheet);
|
|
1765
|
+
}
|
|
1766
|
+
destroy() {
|
|
1767
|
+
if (activeService !== this) {
|
|
1768
|
+
// |activeService| cannot be replaced without calling destroy() first,
|
|
1769
|
+
// so if it differs then an external consumer has a stale reference to us.
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
this.printContainer.textContent = "";
|
|
1773
|
+
const body = document.querySelector("body");
|
|
1774
|
+
body === null || body === void 0 ? void 0 : body.removeAttribute("data-pdfjsprinting");
|
|
1775
|
+
if (this.pageStyleSheet) {
|
|
1776
|
+
this.pageStyleSheet.remove();
|
|
1777
|
+
this.pageStyleSheet = null;
|
|
1778
|
+
}
|
|
1779
|
+
this.scratchCanvas.width = this.scratchCanvas.height = 0;
|
|
1780
|
+
this.scratchCanvas = null;
|
|
1781
|
+
activeService = null;
|
|
1782
|
+
ensureOverlay().then(function () {
|
|
1783
|
+
if (overlayManager.active === dialog) {
|
|
1784
|
+
overlayManager.close(dialog);
|
|
1785
|
+
}
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1788
|
+
renderPages() {
|
|
1789
|
+
if (this.pdfDocument.isPureXfa) {
|
|
1790
|
+
getXfaHtmlForPrinting(this.printContainer, this.pdfDocument);
|
|
1791
|
+
return Promise.resolve();
|
|
1792
|
+
}
|
|
1793
|
+
const pageCount = this.pagesOverview.length;
|
|
1794
|
+
const renderNextPage = (resolve, reject) => {
|
|
1795
|
+
this.throwIfInactive();
|
|
1796
|
+
if (++this.currentPage >= pageCount) {
|
|
1797
|
+
renderProgress(pageCount, pageCount, this.l10n);
|
|
1798
|
+
resolve();
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
const index = this.currentPage;
|
|
1802
|
+
renderProgress(index, pageCount, this.l10n);
|
|
1803
|
+
renderPage(this, this.pdfDocument,
|
|
1804
|
+
/* pageNumber = */ index + 1, this.pagesOverview[index], this._printResolution, this._optionalContentConfigPromise, this._printAnnotationStoragePromise)
|
|
1805
|
+
.then(this.useRenderedPage.bind(this))
|
|
1806
|
+
.then(function () {
|
|
1807
|
+
renderNextPage(resolve, reject);
|
|
1808
|
+
}, reject);
|
|
1809
|
+
};
|
|
1810
|
+
return new Promise(renderNextPage);
|
|
1811
|
+
}
|
|
1812
|
+
useRenderedPage() {
|
|
1813
|
+
this.throwIfInactive();
|
|
1814
|
+
const img = document.createElement("img");
|
|
1815
|
+
const scratchCanvas = this.scratchCanvas;
|
|
1816
|
+
if ("toBlob" in scratchCanvas) {
|
|
1817
|
+
scratchCanvas.toBlob(function (blob) {
|
|
1818
|
+
img.src = URL.createObjectURL(blob);
|
|
1819
|
+
});
|
|
1820
|
+
}
|
|
1821
|
+
else {
|
|
1822
|
+
img.src = scratchCanvas.toDataURL();
|
|
1823
|
+
}
|
|
1824
|
+
const wrapper = document.createElement("div");
|
|
1825
|
+
wrapper.className = "printedPage";
|
|
1826
|
+
wrapper.append(img);
|
|
1827
|
+
this.printContainer.append(wrapper);
|
|
1828
|
+
return new Promise(function (resolve, reject) {
|
|
1829
|
+
img.onload = resolve;
|
|
1830
|
+
img.onerror = reject;
|
|
1831
|
+
});
|
|
1832
|
+
}
|
|
1833
|
+
performPrint() {
|
|
1834
|
+
this.throwIfInactive();
|
|
1835
|
+
return new Promise(resolve => {
|
|
1836
|
+
// Push window.print in the macrotask queue to avoid being affected by
|
|
1837
|
+
// the deprecation of running print() code in a microtask, see
|
|
1838
|
+
// https://github.com/mozilla/pdf.js/issues/7547.
|
|
1839
|
+
setTimeout(() => {
|
|
1840
|
+
if (!this.active) {
|
|
1841
|
+
resolve();
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
print.call(window);
|
|
1845
|
+
// Delay promise resolution in case print() was not synchronous.
|
|
1846
|
+
setTimeout(resolve, 20); // Tidy-up.
|
|
1847
|
+
}, 0);
|
|
1848
|
+
});
|
|
1849
|
+
}
|
|
1850
|
+
get active() {
|
|
1851
|
+
return this === activeService;
|
|
1852
|
+
}
|
|
1853
|
+
throwIfInactive() {
|
|
1854
|
+
if (!this.active) {
|
|
1855
|
+
throw new Error("This print request was cancelled or completed.");
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
const print = window.print;
|
|
1860
|
+
window.print = function () {
|
|
1861
|
+
if (activeService) {
|
|
1862
|
+
console.warn("Ignored window.print() because of a pending print job.");
|
|
1863
|
+
return;
|
|
1864
|
+
}
|
|
1865
|
+
ensureOverlay().then(function () {
|
|
1866
|
+
if (activeService) {
|
|
1867
|
+
overlayManager.open(dialog);
|
|
1868
|
+
}
|
|
1869
|
+
});
|
|
1870
|
+
try {
|
|
1871
|
+
dispatchEvent("beforeprint");
|
|
1872
|
+
}
|
|
1873
|
+
finally {
|
|
1874
|
+
if (!activeService) {
|
|
1875
|
+
console.error("Expected print service to be initialized.");
|
|
1876
|
+
ensureOverlay().then(function () {
|
|
1877
|
+
if (overlayManager.active === dialog) {
|
|
1878
|
+
overlayManager.close(dialog);
|
|
1879
|
+
}
|
|
1880
|
+
});
|
|
1881
|
+
return; // eslint-disable-line no-unsafe-finally
|
|
1882
|
+
}
|
|
1883
|
+
const activeServiceOnEntry = activeService;
|
|
1884
|
+
activeService
|
|
1885
|
+
.renderPages()
|
|
1886
|
+
.then(function () {
|
|
1887
|
+
return activeServiceOnEntry.performPrint();
|
|
1888
|
+
})
|
|
1889
|
+
.catch(function () {
|
|
1890
|
+
// Ignore any error messages.
|
|
1891
|
+
})
|
|
1892
|
+
.then(function () {
|
|
1893
|
+
// aborts acts on the "active" print request, so we need to check
|
|
1894
|
+
// whether the print request (activeServiceOnEntry) is still active.
|
|
1895
|
+
// Without the check, an unrelated print request (created after aborting
|
|
1896
|
+
// this print request while the pages were being generated) would be
|
|
1897
|
+
// aborted.
|
|
1898
|
+
if (activeServiceOnEntry.active) {
|
|
1899
|
+
abort();
|
|
1900
|
+
}
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
function dispatchEvent(eventType) {
|
|
1905
|
+
const event = document.createEvent("CustomEvent");
|
|
1906
|
+
event.initCustomEvent(eventType, false, false, "custom");
|
|
1907
|
+
window.dispatchEvent(event);
|
|
1908
|
+
}
|
|
1909
|
+
function abort() {
|
|
1910
|
+
if (activeService) {
|
|
1911
|
+
activeService.destroy();
|
|
1912
|
+
dispatchEvent("afterprint");
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
function renderProgress(index, total, l10n) {
|
|
1916
|
+
dialog || (dialog = document.getElementById("printServiceDialog"));
|
|
1917
|
+
const progress = Math.round((100 * index) / total);
|
|
1918
|
+
const progressBar = dialog.querySelector("progress");
|
|
1919
|
+
const progressPerc = dialog.querySelector(".relative-progress");
|
|
1920
|
+
progressBar.value = progress;
|
|
1921
|
+
l10n.get("print_progress_percent", { progress }).then((msg) => {
|
|
1922
|
+
progressPerc.textContent = msg;
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
window.addEventListener("keydown", function (event) {
|
|
1926
|
+
// Intercept Cmd/Ctrl + P in all browsers.
|
|
1927
|
+
// Also intercept Cmd/Ctrl + Shift + P in Chrome and Opera
|
|
1928
|
+
if (event.keyCode === /* P= */ 80 &&
|
|
1929
|
+
(event.ctrlKey || event.metaKey) &&
|
|
1930
|
+
!event.altKey &&
|
|
1931
|
+
!event.shiftKey // (!event.shiftKey || window.chrome || window.opera)
|
|
1932
|
+
) {
|
|
1933
|
+
window.print();
|
|
1934
|
+
event.preventDefault();
|
|
1935
|
+
event.stopImmediatePropagation();
|
|
1936
|
+
}
|
|
1937
|
+
}, true);
|
|
1938
|
+
if ("onbeforeprint" in window) {
|
|
1939
|
+
// Do not propagate before/afterprint events when they are not triggered
|
|
1940
|
+
// from within this polyfill. (FF / Chrome 63+).
|
|
1941
|
+
const stopPropagationIfNeeded = function (event) {
|
|
1942
|
+
if (event.detail !== "custom") {
|
|
1943
|
+
event.stopImmediatePropagation();
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1946
|
+
window.addEventListener("beforeprint", stopPropagationIfNeeded);
|
|
1947
|
+
window.addEventListener("afterprint", stopPropagationIfNeeded);
|
|
1948
|
+
}
|
|
1949
|
+
let overlayPromise;
|
|
1950
|
+
function ensureOverlay() {
|
|
1951
|
+
if (!overlayPromise) {
|
|
1952
|
+
if (!overlayManager) {
|
|
1953
|
+
throw new Error("The overlay manager has not yet been initialized.");
|
|
1954
|
+
}
|
|
1955
|
+
dialog || (dialog = document.getElementById("printServiceDialog"));
|
|
1956
|
+
overlayPromise = overlayManager.register(dialog,
|
|
1957
|
+
/* canForceClose = */ true);
|
|
1958
|
+
document.getElementById("printCancel").onclick = abort;
|
|
1959
|
+
dialog.addEventListener("close", abort);
|
|
1960
|
+
}
|
|
1961
|
+
return overlayPromise;
|
|
1962
|
+
}
|
|
1963
|
+
const PDFPrintServiceFactory = {
|
|
1964
|
+
instance: {
|
|
1965
|
+
supportsPrinting: true,
|
|
1966
|
+
createPrintService(pdfDocument, pagesOverview, printContainer, printResolution, optionalContentConfigPromise, printAnnotationStoragePromise, l10n) {
|
|
1967
|
+
if (activeService) {
|
|
1968
|
+
throw new Error("The print service is created and active.");
|
|
1969
|
+
}
|
|
1970
|
+
activeService = new PDFPrintService(pdfDocument, pagesOverview, printContainer, printResolution, optionalContentConfigPromise, printAnnotationStoragePromise, l10n);
|
|
1971
|
+
return activeService;
|
|
1972
|
+
},
|
|
1973
|
+
},
|
|
1974
|
+
};
|
|
1975
|
+
|
|
1976
|
+
/* Copyright 2012 Mozilla Foundation
|
|
1977
|
+
*
|
|
1978
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
1979
|
+
* you may not use this file except in compliance with the License.
|
|
1980
|
+
* You may obtain a copy of the License at
|
|
1981
|
+
*
|
|
1982
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
1983
|
+
*
|
|
1984
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
1985
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
1986
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
1987
|
+
* See the License for the specific language governing permissions and
|
|
1988
|
+
* limitations under the License.
|
|
1989
|
+
*/
|
|
1990
|
+
var _PDFPresentationMode_instances, _PDFPresentationMode_state, _PDFPresentationMode_args, _PDFPresentationMode_mouseWheel, _PDFPresentationMode_notifyStateChange, _PDFPresentationMode_enter, _PDFPresentationMode_exit, _PDFPresentationMode_mouseDown, _PDFPresentationMode_contextMenu, _PDFPresentationMode_showControls, _PDFPresentationMode_hideControls, _PDFPresentationMode_resetMouseScrollState, _PDFPresentationMode_touchSwipe, _PDFPresentationMode_addWindowListeners, _PDFPresentationMode_removeWindowListeners, _PDFPresentationMode_fullscreenChange, _PDFPresentationMode_addFullscreenChangeListeners, _PDFPresentationMode_removeFullscreenChangeListeners;
|
|
1991
|
+
const DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms
|
|
1992
|
+
const ACTIVE_SELECTOR = "pdfPresentationMode";
|
|
1993
|
+
const CONTROLS_SELECTOR = "pdfPresentationModeControls";
|
|
1994
|
+
const MOUSE_SCROLL_COOLDOWN_TIME = 50; // in ms
|
|
1995
|
+
const PAGE_SWITCH_THRESHOLD = 0.1;
|
|
1996
|
+
// Number of CSS pixels for a movement to count as a swipe.
|
|
1997
|
+
const SWIPE_MIN_DISTANCE_THRESHOLD = 50;
|
|
1998
|
+
// Swipe angle deviation from the x or y axis before it is not
|
|
1999
|
+
// considered a swipe in that direction any more.
|
|
2000
|
+
const SWIPE_ANGLE_THRESHOLD = Math.PI / 6;
|
|
2001
|
+
/**
|
|
2002
|
+
* @typedef {Object} PDFPresentationModeOptions
|
|
2003
|
+
* @property {HTMLDivElement} container - The container for the viewer element.
|
|
2004
|
+
* @property {PDFViewer} pdfViewer - The document viewer.
|
|
2005
|
+
* @property {EventBus} eventBus - The application event bus.
|
|
2006
|
+
*/
|
|
2007
|
+
class PDFPresentationMode {
|
|
2008
|
+
/**
|
|
2009
|
+
* @param {PDFPresentationModeOptions} options
|
|
2010
|
+
*/
|
|
2011
|
+
constructor({ container, pdfViewer, eventBus }) {
|
|
2012
|
+
_PDFPresentationMode_instances.add(this);
|
|
2013
|
+
_PDFPresentationMode_state.set(this, PresentationModeState.UNKNOWN);
|
|
2014
|
+
_PDFPresentationMode_args.set(this, null);
|
|
2015
|
+
this.container = container;
|
|
2016
|
+
this.pdfViewer = pdfViewer;
|
|
2017
|
+
this.eventBus = eventBus;
|
|
2018
|
+
this.contextMenuOpen = false;
|
|
2019
|
+
this.mouseScrollTimeStamp = 0;
|
|
2020
|
+
this.mouseScrollDelta = 0;
|
|
2021
|
+
this.touchSwipeState = null;
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Request the browser to enter fullscreen mode.
|
|
2025
|
+
* @returns {Promise<boolean>} Indicating if the request was successful.
|
|
2026
|
+
*/
|
|
2027
|
+
request() {
|
|
2028
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2029
|
+
const { container, pdfViewer } = this;
|
|
2030
|
+
if (this.active || !pdfViewer.pagesCount || !container.requestFullscreen) {
|
|
2031
|
+
return false;
|
|
2032
|
+
}
|
|
2033
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_addFullscreenChangeListeners).call(this);
|
|
2034
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_notifyStateChange).call(this, PresentationModeState.CHANGING);
|
|
2035
|
+
const promise = container.requestFullscreen();
|
|
2036
|
+
__classPrivateFieldSet(this, _PDFPresentationMode_args, {
|
|
2037
|
+
pageNumber: pdfViewer.currentPageNumber,
|
|
2038
|
+
scaleValue: pdfViewer.currentScaleValue,
|
|
2039
|
+
scrollMode: pdfViewer.scrollMode,
|
|
2040
|
+
spreadMode: null,
|
|
2041
|
+
annotationEditorMode: null,
|
|
2042
|
+
}, "f");
|
|
2043
|
+
if (pdfViewer.spreadMode !== SpreadMode.NONE &&
|
|
2044
|
+
!(pdfViewer.pageViewsReady && pdfViewer.hasEqualPageSizes)) {
|
|
2045
|
+
console.warn("Ignoring Spread modes when entering PresentationMode, " +
|
|
2046
|
+
"since the document may contain varying page sizes.");
|
|
2047
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_args, "f").spreadMode = pdfViewer.spreadMode;
|
|
2048
|
+
}
|
|
2049
|
+
if (pdfViewer.annotationEditorMode !== AnnotationEditorType.DISABLE) {
|
|
2050
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_args, "f").annotationEditorMode = pdfViewer.annotationEditorMode;
|
|
2051
|
+
}
|
|
2052
|
+
try {
|
|
2053
|
+
yield promise;
|
|
2054
|
+
pdfViewer.focus(); // Fixes bug 1787456.
|
|
2055
|
+
return true;
|
|
2056
|
+
}
|
|
2057
|
+
catch (reason) {
|
|
2058
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_removeFullscreenChangeListeners).call(this);
|
|
2059
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_notifyStateChange).call(this, PresentationModeState.NORMAL);
|
|
2060
|
+
}
|
|
2061
|
+
return false;
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
2064
|
+
get active() {
|
|
2065
|
+
return (__classPrivateFieldGet(this, _PDFPresentationMode_state, "f") === PresentationModeState.CHANGING ||
|
|
2066
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_state, "f") === PresentationModeState.FULLSCREEN);
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
_PDFPresentationMode_state = new WeakMap(), _PDFPresentationMode_args = new WeakMap(), _PDFPresentationMode_instances = new WeakSet(), _PDFPresentationMode_mouseWheel = function _PDFPresentationMode_mouseWheel(evt) {
|
|
2070
|
+
if (!this.active) {
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
evt.preventDefault();
|
|
2074
|
+
const delta = normalizeWheelEventDelta(evt);
|
|
2075
|
+
const currentTime = Date.now();
|
|
2076
|
+
const storedTime = this.mouseScrollTimeStamp;
|
|
2077
|
+
// If we've already switched page, avoid accidentally switching again.
|
|
2078
|
+
if (currentTime > storedTime &&
|
|
2079
|
+
currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) {
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2082
|
+
// If the scroll direction changed, reset the accumulated scroll delta.
|
|
2083
|
+
if ((this.mouseScrollDelta > 0 && delta < 0) ||
|
|
2084
|
+
(this.mouseScrollDelta < 0 && delta > 0)) {
|
|
2085
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_resetMouseScrollState).call(this);
|
|
2086
|
+
}
|
|
2087
|
+
this.mouseScrollDelta += delta;
|
|
2088
|
+
if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) {
|
|
2089
|
+
const totalDelta = this.mouseScrollDelta;
|
|
2090
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_resetMouseScrollState).call(this);
|
|
2091
|
+
const success = totalDelta > 0
|
|
2092
|
+
? this.pdfViewer.previousPage()
|
|
2093
|
+
: this.pdfViewer.nextPage();
|
|
2094
|
+
if (success) {
|
|
2095
|
+
this.mouseScrollTimeStamp = currentTime;
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
}, _PDFPresentationMode_notifyStateChange = function _PDFPresentationMode_notifyStateChange(state) {
|
|
2099
|
+
__classPrivateFieldSet(this, _PDFPresentationMode_state, state, "f");
|
|
2100
|
+
this.eventBus.dispatch("presentationmodechanged", { source: this, state });
|
|
2101
|
+
}, _PDFPresentationMode_enter = function _PDFPresentationMode_enter() {
|
|
2102
|
+
var _a;
|
|
2103
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_notifyStateChange).call(this, PresentationModeState.FULLSCREEN);
|
|
2104
|
+
this.container.classList.add(ACTIVE_SELECTOR);
|
|
2105
|
+
// Ensure that the correct page is scrolled into view when entering
|
|
2106
|
+
// Presentation Mode, by waiting until fullscreen mode in enabled.
|
|
2107
|
+
setTimeout(() => {
|
|
2108
|
+
this.pdfViewer.scrollMode = ScrollMode.PAGE;
|
|
2109
|
+
if (__classPrivateFieldGet(this, _PDFPresentationMode_args, "f").spreadMode !== null) {
|
|
2110
|
+
this.pdfViewer.spreadMode = SpreadMode.NONE;
|
|
2111
|
+
}
|
|
2112
|
+
this.pdfViewer.currentPageNumber = __classPrivateFieldGet(this, _PDFPresentationMode_args, "f").pageNumber;
|
|
2113
|
+
this.pdfViewer.currentScaleValue = "page-fit";
|
|
2114
|
+
if (__classPrivateFieldGet(this, _PDFPresentationMode_args, "f").annotationEditorMode !== null) {
|
|
2115
|
+
this.pdfViewer.annotationEditorMode = AnnotationEditorType.NONE;
|
|
2116
|
+
}
|
|
2117
|
+
}, 0);
|
|
2118
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_addWindowListeners).call(this);
|
|
2119
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_showControls).call(this);
|
|
2120
|
+
this.contextMenuOpen = false;
|
|
2121
|
+
// Text selection is disabled in Presentation Mode, thus it's not possible
|
|
2122
|
+
// for the user to deselect text that is selected (e.g. with "Select all")
|
|
2123
|
+
// when entering Presentation Mode, hence we remove any active selection.
|
|
2124
|
+
(_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.removeAllRanges();
|
|
2125
|
+
}, _PDFPresentationMode_exit = function _PDFPresentationMode_exit() {
|
|
2126
|
+
const pageNumber = this.pdfViewer.currentPageNumber;
|
|
2127
|
+
this.container.classList.remove(ACTIVE_SELECTOR);
|
|
2128
|
+
// Ensure that the correct page is scrolled into view when exiting
|
|
2129
|
+
// Presentation Mode, by waiting until fullscreen mode is disabled.
|
|
2130
|
+
setTimeout(() => {
|
|
2131
|
+
var _a;
|
|
2132
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_removeFullscreenChangeListeners).call(this);
|
|
2133
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_notifyStateChange).call(this, PresentationModeState.NORMAL);
|
|
2134
|
+
this.pdfViewer.scrollMode = __classPrivateFieldGet(this, _PDFPresentationMode_args, "f").scrollMode;
|
|
2135
|
+
if (((_a = __classPrivateFieldGet(this, _PDFPresentationMode_args, "f")) === null || _a === void 0 ? void 0 : _a.spreadMode) !== null) {
|
|
2136
|
+
this.pdfViewer.spreadMode = __classPrivateFieldGet(this, _PDFPresentationMode_args, "f").spreadMode;
|
|
2137
|
+
}
|
|
2138
|
+
this.pdfViewer.currentScaleValue = __classPrivateFieldGet(this, _PDFPresentationMode_args, "f").scaleValue;
|
|
2139
|
+
this.pdfViewer.currentPageNumber = pageNumber;
|
|
2140
|
+
if (__classPrivateFieldGet(this, _PDFPresentationMode_args, "f").annotationEditorMode !== null) {
|
|
2141
|
+
this.pdfViewer.annotationEditorMode = __classPrivateFieldGet(this, _PDFPresentationMode_args, "f").annotationEditorMode;
|
|
2142
|
+
}
|
|
2143
|
+
__classPrivateFieldSet(this, _PDFPresentationMode_args, null, "f");
|
|
2144
|
+
}, 0);
|
|
2145
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_removeWindowListeners).call(this);
|
|
2146
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_hideControls).call(this);
|
|
2147
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_resetMouseScrollState).call(this);
|
|
2148
|
+
this.contextMenuOpen = false;
|
|
2149
|
+
}, _PDFPresentationMode_mouseDown = function _PDFPresentationMode_mouseDown(evt) {
|
|
2150
|
+
var _a;
|
|
2151
|
+
if (this.contextMenuOpen) {
|
|
2152
|
+
this.contextMenuOpen = false;
|
|
2153
|
+
evt.preventDefault();
|
|
2154
|
+
return;
|
|
2155
|
+
}
|
|
2156
|
+
if (evt.button !== 0) {
|
|
2157
|
+
return;
|
|
2158
|
+
}
|
|
2159
|
+
// Enable clicking of links in presentation mode. Note: only links
|
|
2160
|
+
// pointing to destinations in the current PDF document work.
|
|
2161
|
+
if (evt.target.href &&
|
|
2162
|
+
((_a = evt.target.parentNode) === null || _a === void 0 ? void 0 : _a.hasAttribute("data-internal-link"))) {
|
|
2163
|
+
return;
|
|
2164
|
+
}
|
|
2165
|
+
// Unless an internal link was clicked, advance one page.
|
|
2166
|
+
evt.preventDefault();
|
|
2167
|
+
if (evt.shiftKey) {
|
|
2168
|
+
this.pdfViewer.previousPage();
|
|
2169
|
+
}
|
|
2170
|
+
else {
|
|
2171
|
+
this.pdfViewer.nextPage();
|
|
2172
|
+
}
|
|
2173
|
+
}, _PDFPresentationMode_contextMenu = function _PDFPresentationMode_contextMenu() {
|
|
2174
|
+
this.contextMenuOpen = true;
|
|
2175
|
+
}, _PDFPresentationMode_showControls = function _PDFPresentationMode_showControls() {
|
|
2176
|
+
if (this.controlsTimeout) {
|
|
2177
|
+
clearTimeout(this.controlsTimeout);
|
|
2178
|
+
}
|
|
2179
|
+
else {
|
|
2180
|
+
this.container.classList.add(CONTROLS_SELECTOR);
|
|
2181
|
+
}
|
|
2182
|
+
this.controlsTimeout = setTimeout(() => {
|
|
2183
|
+
this.container.classList.remove(CONTROLS_SELECTOR);
|
|
2184
|
+
delete this.controlsTimeout;
|
|
2185
|
+
}, DELAY_BEFORE_HIDING_CONTROLS);
|
|
2186
|
+
}, _PDFPresentationMode_hideControls = function _PDFPresentationMode_hideControls() {
|
|
2187
|
+
if (!this.controlsTimeout) {
|
|
2188
|
+
return;
|
|
2189
|
+
}
|
|
2190
|
+
clearTimeout(this.controlsTimeout);
|
|
2191
|
+
this.container.classList.remove(CONTROLS_SELECTOR);
|
|
2192
|
+
delete this.controlsTimeout;
|
|
2193
|
+
}, _PDFPresentationMode_resetMouseScrollState = function _PDFPresentationMode_resetMouseScrollState() {
|
|
2194
|
+
this.mouseScrollTimeStamp = 0;
|
|
2195
|
+
this.mouseScrollDelta = 0;
|
|
2196
|
+
}, _PDFPresentationMode_touchSwipe = function _PDFPresentationMode_touchSwipe(evt) {
|
|
2197
|
+
if (!this.active) {
|
|
2198
|
+
return;
|
|
2199
|
+
}
|
|
2200
|
+
if (evt.touches.length > 1) {
|
|
2201
|
+
// Multiple touch points detected; cancel the swipe.
|
|
2202
|
+
this.touchSwipeState = null;
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2205
|
+
switch (evt.type) {
|
|
2206
|
+
case "touchstart":
|
|
2207
|
+
this.touchSwipeState = {
|
|
2208
|
+
startX: evt.touches[0].pageX,
|
|
2209
|
+
startY: evt.touches[0].pageY,
|
|
2210
|
+
endX: evt.touches[0].pageX,
|
|
2211
|
+
endY: evt.touches[0].pageY,
|
|
2212
|
+
};
|
|
2213
|
+
break;
|
|
2214
|
+
case "touchmove":
|
|
2215
|
+
if (this.touchSwipeState === null) {
|
|
2216
|
+
return;
|
|
2217
|
+
}
|
|
2218
|
+
this.touchSwipeState.endX = evt.touches[0].pageX;
|
|
2219
|
+
this.touchSwipeState.endY = evt.touches[0].pageY;
|
|
2220
|
+
// Avoid the swipe from triggering browser gestures (Chrome in
|
|
2221
|
+
// particular has some sort of swipe gesture in fullscreen mode).
|
|
2222
|
+
evt.preventDefault();
|
|
2223
|
+
break;
|
|
2224
|
+
case "touchend":
|
|
2225
|
+
if (this.touchSwipeState === null) {
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2228
|
+
let delta = 0;
|
|
2229
|
+
const dx = this.touchSwipeState.endX - this.touchSwipeState.startX;
|
|
2230
|
+
const dy = this.touchSwipeState.endY - this.touchSwipeState.startY;
|
|
2231
|
+
const absAngle = Math.abs(Math.atan2(dy, dx));
|
|
2232
|
+
if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD &&
|
|
2233
|
+
(absAngle <= SWIPE_ANGLE_THRESHOLD ||
|
|
2234
|
+
absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) {
|
|
2235
|
+
// Horizontal swipe.
|
|
2236
|
+
delta = dx;
|
|
2237
|
+
}
|
|
2238
|
+
else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD &&
|
|
2239
|
+
Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) {
|
|
2240
|
+
// Vertical swipe.
|
|
2241
|
+
delta = dy;
|
|
2242
|
+
}
|
|
2243
|
+
if (delta > 0) {
|
|
2244
|
+
this.pdfViewer.previousPage();
|
|
2245
|
+
}
|
|
2246
|
+
else if (delta < 0) {
|
|
2247
|
+
this.pdfViewer.nextPage();
|
|
2248
|
+
}
|
|
2249
|
+
break;
|
|
2250
|
+
}
|
|
2251
|
+
}, _PDFPresentationMode_addWindowListeners = function _PDFPresentationMode_addWindowListeners() {
|
|
2252
|
+
this.showControlsBind = __classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_showControls).bind(this);
|
|
2253
|
+
this.mouseDownBind = __classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_mouseDown).bind(this);
|
|
2254
|
+
this.mouseWheelBind = __classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_mouseWheel).bind(this);
|
|
2255
|
+
this.resetMouseScrollStateBind = __classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_resetMouseScrollState).bind(this);
|
|
2256
|
+
this.contextMenuBind = __classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_contextMenu).bind(this);
|
|
2257
|
+
this.touchSwipeBind = __classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_touchSwipe).bind(this);
|
|
2258
|
+
window.addEventListener("mousemove", this.showControlsBind);
|
|
2259
|
+
window.addEventListener("mousedown", this.mouseDownBind);
|
|
2260
|
+
window.addEventListener("wheel", this.mouseWheelBind, { passive: false });
|
|
2261
|
+
window.addEventListener("keydown", this.resetMouseScrollStateBind);
|
|
2262
|
+
window.addEventListener("contextmenu", this.contextMenuBind);
|
|
2263
|
+
window.addEventListener("touchstart", this.touchSwipeBind);
|
|
2264
|
+
window.addEventListener("touchmove", this.touchSwipeBind);
|
|
2265
|
+
window.addEventListener("touchend", this.touchSwipeBind);
|
|
2266
|
+
}, _PDFPresentationMode_removeWindowListeners = function _PDFPresentationMode_removeWindowListeners() {
|
|
2267
|
+
window.removeEventListener("mousemove", this.showControlsBind);
|
|
2268
|
+
window.removeEventListener("mousedown", this.mouseDownBind);
|
|
2269
|
+
window.removeEventListener("wheel", this.mouseWheelBind, {
|
|
2270
|
+
// @ts-ignore
|
|
2271
|
+
passive: false,
|
|
2272
|
+
});
|
|
2273
|
+
window.removeEventListener("keydown", this.resetMouseScrollStateBind);
|
|
2274
|
+
window.removeEventListener("contextmenu", this.contextMenuBind);
|
|
2275
|
+
window.removeEventListener("touchstart", this.touchSwipeBind);
|
|
2276
|
+
window.removeEventListener("touchmove", this.touchSwipeBind);
|
|
2277
|
+
window.removeEventListener("touchend", this.touchSwipeBind);
|
|
2278
|
+
delete this.showControlsBind;
|
|
2279
|
+
delete this.mouseDownBind;
|
|
2280
|
+
delete this.mouseWheelBind;
|
|
2281
|
+
delete this.resetMouseScrollStateBind;
|
|
2282
|
+
delete this.contextMenuBind;
|
|
2283
|
+
delete this.touchSwipeBind;
|
|
2284
|
+
}, _PDFPresentationMode_fullscreenChange = function _PDFPresentationMode_fullscreenChange() {
|
|
2285
|
+
if ( /* isFullscreen = */document.fullscreenElement) {
|
|
2286
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_enter).call(this);
|
|
2287
|
+
}
|
|
2288
|
+
else {
|
|
2289
|
+
__classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_exit).call(this);
|
|
2290
|
+
}
|
|
2291
|
+
}, _PDFPresentationMode_addFullscreenChangeListeners = function _PDFPresentationMode_addFullscreenChangeListeners() {
|
|
2292
|
+
this.fullscreenChangeBind = __classPrivateFieldGet(this, _PDFPresentationMode_instances, "m", _PDFPresentationMode_fullscreenChange).bind(this);
|
|
2293
|
+
window.addEventListener("fullscreenchange", this.fullscreenChangeBind);
|
|
2294
|
+
}, _PDFPresentationMode_removeFullscreenChangeListeners = function _PDFPresentationMode_removeFullscreenChangeListeners() {
|
|
2295
|
+
window.removeEventListener("fullscreenchange", this.fullscreenChangeBind);
|
|
2296
|
+
delete this.fullscreenChangeBind;
|
|
2297
|
+
};
|
|
2298
|
+
|
|
2299
|
+
const initialState = {
|
|
2300
|
+
isDocumentLoaded: false,
|
|
2301
|
+
pagesReady: false,
|
|
2302
|
+
url: null,
|
|
2303
|
+
numPages: 0,
|
|
2304
|
+
pageNumber: 0,
|
|
2305
|
+
scale: 0,
|
|
2306
|
+
scaleValue: "auto",
|
|
2307
|
+
pagesRotation: 0,
|
|
2308
|
+
spreadMode: SpreadMode.UNKNOWN,
|
|
2309
|
+
scrollMode: ScrollMode.UNKNOWN,
|
|
2310
|
+
documentOutline: null,
|
|
2311
|
+
attachments: new Map(),
|
|
2312
|
+
thumbnails: new Map(),
|
|
2313
|
+
thumbnailViews: new Map(),
|
|
2314
|
+
annotationEditorMode: AnnotationEditorType.NONE,
|
|
2315
|
+
pdfSlick: null
|
|
2316
|
+
};
|
|
2317
|
+
const create = () => createStore((set, get) => (Object.assign(Object.assign({}, initialState), { _setThumbnailView: (pageNumber, view) => {
|
|
2318
|
+
const thumbnails = new Map(get().thumbnails);
|
|
2319
|
+
const thumbnailViews = new Map(get().thumbnailViews);
|
|
2320
|
+
const { canvasWidth: width, canvasHeight: height, scale, rotation, loaded, pageLabel, src = null, } = view;
|
|
2321
|
+
thumbnailViews.set(pageNumber, view);
|
|
2322
|
+
thumbnails.set(pageNumber, {
|
|
2323
|
+
pageNumber,
|
|
2324
|
+
width,
|
|
2325
|
+
height,
|
|
2326
|
+
scale,
|
|
2327
|
+
rotation,
|
|
2328
|
+
loaded,
|
|
2329
|
+
pageLabel,
|
|
2330
|
+
src,
|
|
2331
|
+
});
|
|
2332
|
+
set({ thumbnailViews, thumbnails });
|
|
2333
|
+
}, _setThumbnailsViews: (views) => {
|
|
2334
|
+
const thumbnailViews = new Map(views.map(view => [view.id, view]));
|
|
2335
|
+
const thumbnails = new Map(views.map(view => {
|
|
2336
|
+
const { canvasWidth: width, canvasHeight: height, scale, rotation, loaded, pageLabel, src = null, } = view;
|
|
2337
|
+
return [view.id, {
|
|
2338
|
+
pageNumber: view.id,
|
|
2339
|
+
width,
|
|
2340
|
+
height,
|
|
2341
|
+
scale,
|
|
2342
|
+
rotation,
|
|
2343
|
+
loaded,
|
|
2344
|
+
pageLabel,
|
|
2345
|
+
src,
|
|
2346
|
+
}];
|
|
2347
|
+
}));
|
|
2348
|
+
set({ thumbnailViews, thumbnails });
|
|
2349
|
+
} })));
|
|
2350
|
+
|
|
2351
|
+
var _PDFSlick_instances, _PDFSlick_renderingQueue, _PDFSlick_container, _PDFSlick_viewerContainer, _PDFSlick_thumbsContainer, _PDFSlick_annotationMode, _PDFSlick_annotationEditorMode, _PDFSlick_initializePageLabels, _PDFSlick_parseDocumentInfo, _PDFSlick_parsePageSize, _PDFSlick_initInternalEventListeners, _PDFSlick_onDocumentReady, _PDFSlick_onRotationChanging, _PDFSlick_onSwitchSpreadMode, _PDFSlick_onSwitchScrollMode, _PDFSlick_onScaleChanging, _PDFSlick_onPageChanging, _PDFSlick_onPageRendered;
|
|
2352
|
+
GlobalWorkerOptions.workerSrc = `//cdn.jsdelivr.net/npm/pdfjs-dist@${version}/build/pdf.worker.min.js`;
|
|
2353
|
+
const US_PAGE_NAMES = {
|
|
2354
|
+
"8.5x11": "Letter",
|
|
2355
|
+
"8.5x14": "Legal",
|
|
2356
|
+
};
|
|
2357
|
+
const METRIC_PAGE_NAMES = {
|
|
2358
|
+
"297x420": "A3",
|
|
2359
|
+
"210x297": "A4",
|
|
2360
|
+
};
|
|
2361
|
+
function getPageName(size, isPortrait, pageNames) {
|
|
2362
|
+
const width = isPortrait ? size.width : size.height;
|
|
2363
|
+
const height = isPortrait ? size.height : size.width;
|
|
2364
|
+
return pageNames[`${width}x${height}`];
|
|
2365
|
+
}
|
|
2366
|
+
class PDFSlick {
|
|
2367
|
+
constructor({ container, viewer, thumbs, store = create(), options }) {
|
|
2368
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
2369
|
+
_PDFSlick_instances.add(this);
|
|
2370
|
+
_PDFSlick_renderingQueue.set(this, void 0);
|
|
2371
|
+
_PDFSlick_container.set(this, void 0);
|
|
2372
|
+
_PDFSlick_viewerContainer.set(this, void 0);
|
|
2373
|
+
_PDFSlick_thumbsContainer.set(this, void 0);
|
|
2374
|
+
this.downloadManager = null;
|
|
2375
|
+
this.findController = null;
|
|
2376
|
+
this.pdfPresentationMode = null;
|
|
2377
|
+
this.document = null;
|
|
2378
|
+
// options
|
|
2379
|
+
_PDFSlick_annotationMode.set(this, void 0);
|
|
2380
|
+
_PDFSlick_annotationEditorMode.set(this, void 0);
|
|
2381
|
+
__classPrivateFieldSet(this, _PDFSlick_container, container, "f");
|
|
2382
|
+
__classPrivateFieldSet(this, _PDFSlick_viewerContainer, viewer, "f");
|
|
2383
|
+
__classPrivateFieldSet(this, _PDFSlick_thumbsContainer, thumbs, "f");
|
|
2384
|
+
this.l10n = (_a = options === null || options === void 0 ? void 0 : options.l10n) !== null && _a !== void 0 ? _a : NullL10n;
|
|
2385
|
+
this.downloadManager = new DownloadManager();
|
|
2386
|
+
this.textLayerMode = (_b = options === null || options === void 0 ? void 0 : options.textLayerMode) !== null && _b !== void 0 ? _b : TextLayerMode.ENABLE;
|
|
2387
|
+
__classPrivateFieldSet(this, _PDFSlick_annotationMode, (_c = options === null || options === void 0 ? void 0 : options.annotationMode) !== null && _c !== void 0 ? _c : AnnotationMode.ENABLE_FORMS, "f");
|
|
2388
|
+
__classPrivateFieldSet(this, _PDFSlick_annotationEditorMode, (_d = options === null || options === void 0 ? void 0 : options.annotationEditorMode) !== null && _d !== void 0 ? _d : AnnotationEditorType.NONE, "f");
|
|
2389
|
+
this.removePageBorders = (_e = options === null || options === void 0 ? void 0 : options.removePageBorders) !== null && _e !== void 0 ? _e : false;
|
|
2390
|
+
this.singlePageViewer = (_f = options === null || options === void 0 ? void 0 : options.singlePageViewer) !== null && _f !== void 0 ? _f : false;
|
|
2391
|
+
this.enablePrintAutoRotate = (_g = options === null || options === void 0 ? void 0 : options.enablePrintAutoRotate) !== null && _g !== void 0 ? _g : false;
|
|
2392
|
+
this.useOnlyCssZoom = (_h = options === null || options === void 0 ? void 0 : options.useOnlyCssZoom) !== null && _h !== void 0 ? _h : false;
|
|
2393
|
+
this.pageColors = (_j = options === null || options === void 0 ? void 0 : options.pageColors) !== null && _j !== void 0 ? _j : null;
|
|
2394
|
+
this.maxCanvasPixels = (_k = options === null || options === void 0 ? void 0 : options.maxCanvasPixels) !== null && _k !== void 0 ? _k : 16777216;
|
|
2395
|
+
this.printResolution = (_l = options === null || options === void 0 ? void 0 : options.printResolution) !== null && _l !== void 0 ? _l : 72;
|
|
2396
|
+
this.thumbnailWidth = (_m = options === null || options === void 0 ? void 0 : options.thumbnailWidth) !== null && _m !== void 0 ? _m : 125;
|
|
2397
|
+
if (this.pageColors &&
|
|
2398
|
+
!(CSS.supports("color", this.pageColors.background) &&
|
|
2399
|
+
CSS.supports("color", this.pageColors.foreground))) {
|
|
2400
|
+
if (this.pageColors.background || this.pageColors.foreground) {
|
|
2401
|
+
console.warn("PDFViewer: Ignoring `pageColors`-option, since the browser doesn't support the values used.");
|
|
2402
|
+
}
|
|
2403
|
+
this.pageColors = null;
|
|
2404
|
+
}
|
|
2405
|
+
this.l10n = NullL10n;
|
|
2406
|
+
this.store = store;
|
|
2407
|
+
const renderingQueue = new PDFRenderingQueue();
|
|
2408
|
+
renderingQueue.onIdle = this._cleanup.bind(this);
|
|
2409
|
+
renderingQueue.isThumbnailViewEnabled = true;
|
|
2410
|
+
__classPrivateFieldSet(this, _PDFSlick_renderingQueue, renderingQueue, "f");
|
|
2411
|
+
const eventBus = new EventBus();
|
|
2412
|
+
const linkService = new PDFLinkService({
|
|
2413
|
+
eventBus,
|
|
2414
|
+
externalLinkTarget: 2,
|
|
2415
|
+
externalLinkRel: "noopener noreferrer nofollow",
|
|
2416
|
+
ignoreDestinationZoom: false
|
|
2417
|
+
});
|
|
2418
|
+
const viewerOptions = Object.assign(Object.assign({ container }, viewer && { viewer }), { eventBus,
|
|
2419
|
+
linkService,
|
|
2420
|
+
renderingQueue, defaultRenderingQueue: true, textLayerMode: this.textLayerMode, l10n: this.l10n, annotationMode: __classPrivateFieldGet(this, _PDFSlick_annotationMode, "f"), annotationEditorMode: __classPrivateFieldGet(this, _PDFSlick_annotationEditorMode, "f"), removePageBorders: this.removePageBorders, imageResourcesPath: "/images/", useOnlyCssZoom: this.useOnlyCssZoom });
|
|
2421
|
+
const pdfViewer = this.singlePageViewer ? new PDFSinglePageViewer(viewerOptions) : new PDFViewer(viewerOptions);
|
|
2422
|
+
renderingQueue.setViewer(pdfViewer);
|
|
2423
|
+
if (thumbs) {
|
|
2424
|
+
this.thumbnailViewer = new PDFThumbnailViewer({
|
|
2425
|
+
container: thumbs,
|
|
2426
|
+
linkService,
|
|
2427
|
+
renderingQueue,
|
|
2428
|
+
l10n: this.l10n,
|
|
2429
|
+
pageColors: this.pageColors,
|
|
2430
|
+
store: store,
|
|
2431
|
+
thumbnailWidth: this.thumbnailWidth
|
|
2432
|
+
});
|
|
2433
|
+
renderingQueue.setThumbnailViewer(this.thumbnailViewer);
|
|
2434
|
+
}
|
|
2435
|
+
if (document.fullscreenEnabled) {
|
|
2436
|
+
this.pdfPresentationMode = new PDFPresentationMode({
|
|
2437
|
+
container,
|
|
2438
|
+
pdfViewer: pdfViewer,
|
|
2439
|
+
eventBus,
|
|
2440
|
+
});
|
|
2441
|
+
}
|
|
2442
|
+
this.eventBus = eventBus;
|
|
2443
|
+
this.linkService = linkService;
|
|
2444
|
+
this.viewer = pdfViewer;
|
|
2445
|
+
this.linkService.setViewer(pdfViewer);
|
|
2446
|
+
const scaleValue = (_o = options === null || options === void 0 ? void 0 : options.scaleValue) !== null && _o !== void 0 ? _o : "auto";
|
|
2447
|
+
this.store.setState({ scaleValue });
|
|
2448
|
+
}
|
|
2449
|
+
loadDocument(url, options) {
|
|
2450
|
+
var _a, _b, _c, _d, _e;
|
|
2451
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2452
|
+
if (this.url) {
|
|
2453
|
+
try {
|
|
2454
|
+
URL.revokeObjectURL(this.url.toString());
|
|
2455
|
+
}
|
|
2456
|
+
catch (err) { }
|
|
2457
|
+
}
|
|
2458
|
+
(_a = this.document) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
2459
|
+
(_b = this.viewer) === null || _b === void 0 ? void 0 : _b.cleanup();
|
|
2460
|
+
this.url = url.toString();
|
|
2461
|
+
const filename = (_c = options === null || options === void 0 ? void 0 : options.filename) !== null && _c !== void 0 ? _c : getPdfFilenameFromUrl((_d = this.url) === null || _d === void 0 ? void 0 : _d.toString());
|
|
2462
|
+
this.filename = filename;
|
|
2463
|
+
const pdfDocument = yield getDocument({ url }).promise;
|
|
2464
|
+
this.document = pdfDocument;
|
|
2465
|
+
this.viewer.setDocument(this.document);
|
|
2466
|
+
this.linkService.setDocument(this.document);
|
|
2467
|
+
if (this.thumbnailViewer) {
|
|
2468
|
+
(_e = this.thumbnailViewer) === null || _e === void 0 ? void 0 : _e.setDocument(pdfDocument);
|
|
2469
|
+
}
|
|
2470
|
+
__classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_initInternalEventListeners).call(this);
|
|
2471
|
+
yield __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_initializePageLabels).call(this);
|
|
2472
|
+
this.store.setState({
|
|
2473
|
+
filename,
|
|
2474
|
+
numPages: pdfDocument.numPages,
|
|
2475
|
+
pageNumber: 1,
|
|
2476
|
+
isDocumentLoaded: true,
|
|
2477
|
+
url: url.toString()
|
|
2478
|
+
});
|
|
2479
|
+
const rawAttachments = yield pdfDocument.getAttachments();
|
|
2480
|
+
const attachments = new Map(Object.keys(rawAttachments !== null && rawAttachments !== void 0 ? rawAttachments : {})
|
|
2481
|
+
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
|
|
2482
|
+
.map((key) => ([key, rawAttachments[key]])));
|
|
2483
|
+
this.store.setState({ attachments });
|
|
2484
|
+
yield __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_parseDocumentInfo).call(this);
|
|
2485
|
+
this.forceRendering();
|
|
2486
|
+
});
|
|
2487
|
+
}
|
|
2488
|
+
forceRendering(isThumbnailViewEnabled = true) {
|
|
2489
|
+
__classPrivateFieldGet(this, _PDFSlick_renderingQueue, "f").printing = !!this.printService;
|
|
2490
|
+
__classPrivateFieldGet(this, _PDFSlick_renderingQueue, "f").isThumbnailViewEnabled = isThumbnailViewEnabled;
|
|
2491
|
+
// @ts-ignore
|
|
2492
|
+
__classPrivateFieldGet(this, _PDFSlick_renderingQueue, "f").renderHighestPriority();
|
|
2493
|
+
}
|
|
2494
|
+
gotoPage(pageNumber) {
|
|
2495
|
+
this.linkService.goToPage(pageNumber);
|
|
2496
|
+
}
|
|
2497
|
+
openOrDownloadData(element, content, filename) {
|
|
2498
|
+
var _a;
|
|
2499
|
+
(_a = this.downloadManager) === null || _a === void 0 ? void 0 : _a.openOrDownloadData(element, content, filename);
|
|
2500
|
+
}
|
|
2501
|
+
download() {
|
|
2502
|
+
var _a, _b;
|
|
2503
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2504
|
+
const url = this.url;
|
|
2505
|
+
const { filename } = this;
|
|
2506
|
+
try {
|
|
2507
|
+
// this._ensureDownloadComplete();
|
|
2508
|
+
const data = yield this.document.getData();
|
|
2509
|
+
const blob = new Blob([data], { type: "application/pdf" });
|
|
2510
|
+
yield ((_a = this.downloadManager) === null || _a === void 0 ? void 0 : _a.download(blob, url, filename));
|
|
2511
|
+
}
|
|
2512
|
+
catch (reason) {
|
|
2513
|
+
// When the PDF document isn't ready, or the PDF file is still
|
|
2514
|
+
// downloading, simply download using the URL.
|
|
2515
|
+
yield ((_b = this.downloadManager) === null || _b === void 0 ? void 0 : _b.downloadUrl(url, filename));
|
|
2516
|
+
}
|
|
2517
|
+
});
|
|
2518
|
+
}
|
|
2519
|
+
save() {
|
|
2520
|
+
var _a;
|
|
2521
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2522
|
+
// if (this._saveInProgress) return;
|
|
2523
|
+
// this._saveInProgress = true;
|
|
2524
|
+
// await this.pdfScriptingManager.dispatchWillSave();
|
|
2525
|
+
const url = this.url;
|
|
2526
|
+
const { filename } = this;
|
|
2527
|
+
try {
|
|
2528
|
+
// this._ensureDownloadComplete();
|
|
2529
|
+
const data = yield this.document.saveDocument();
|
|
2530
|
+
const blob = new Blob([data], { type: "application/pdf" });
|
|
2531
|
+
yield ((_a = this.downloadManager) === null || _a === void 0 ? void 0 : _a.download(blob, url, filename));
|
|
2532
|
+
}
|
|
2533
|
+
catch (reason) {
|
|
2534
|
+
// When the PDF document isn't ready, or the PDF file is still
|
|
2535
|
+
// downloading, simply fallback to a "regular" download.
|
|
2536
|
+
console.error(`Error when saving the document: ${reason.message}`);
|
|
2537
|
+
yield this.download();
|
|
2538
|
+
}
|
|
2539
|
+
finally {
|
|
2540
|
+
// await this.pdfScriptingManager.dispatchDidSave();
|
|
2541
|
+
// this._saveInProgress = false;
|
|
2542
|
+
}
|
|
2543
|
+
});
|
|
2544
|
+
}
|
|
2545
|
+
downloadOrSave() {
|
|
2546
|
+
var _a;
|
|
2547
|
+
const { annotationStorage } = (_a = this.document) !== null && _a !== void 0 ? _a : {};
|
|
2548
|
+
if (annotationStorage && annotationStorage.size > 0) {
|
|
2549
|
+
this.save();
|
|
2550
|
+
}
|
|
2551
|
+
else {
|
|
2552
|
+
this.download();
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
get supportsPrinting() {
|
|
2556
|
+
return PDFPrintServiceFactory.instance.supportsPrinting;
|
|
2557
|
+
}
|
|
2558
|
+
beforePrint() {
|
|
2559
|
+
// this._printAnnotationStoragePromise = this.pdfScriptingManager
|
|
2560
|
+
// .dispatchWillPrint()
|
|
2561
|
+
// .catch(() => {
|
|
2562
|
+
// /* Avoid breaking printing; ignoring errors. */
|
|
2563
|
+
// })
|
|
2564
|
+
// .then(() => {
|
|
2565
|
+
// return this.document?.annotationStorage.print;
|
|
2566
|
+
// });
|
|
2567
|
+
if (this.printService) {
|
|
2568
|
+
// There is no way to suppress beforePrint/afterPrint events,
|
|
2569
|
+
// but PDFPrintService may generate double events -- this will ignore
|
|
2570
|
+
// the second event that will be coming from native window.print().
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2573
|
+
if (!this.supportsPrinting) {
|
|
2574
|
+
// this.l10n.get("printing_not_supported").then(msg => {
|
|
2575
|
+
// this._otherError(msg);
|
|
2576
|
+
// });
|
|
2577
|
+
return;
|
|
2578
|
+
}
|
|
2579
|
+
// The beforePrint is a sync method and we need to know layout before
|
|
2580
|
+
// returning from this method. Ensure that we can get sizes of the pages.
|
|
2581
|
+
if (!this.viewer.pageViewsReady) {
|
|
2582
|
+
this.l10n.get("printing_not_ready").then(msg => {
|
|
2583
|
+
// eslint-disable-next-line no-alert
|
|
2584
|
+
window.alert(msg);
|
|
2585
|
+
});
|
|
2586
|
+
return;
|
|
2587
|
+
}
|
|
2588
|
+
const pagesOverview = this.viewer.getPagesOverview();
|
|
2589
|
+
const printContainer = document.getElementById("printContainer");
|
|
2590
|
+
const printResolution = this.printResolution;
|
|
2591
|
+
const optionalContentConfigPromise = this.viewer.optionalContentConfigPromise;
|
|
2592
|
+
const printService = PDFPrintServiceFactory.instance.createPrintService(this.document, pagesOverview, printContainer, printResolution, optionalContentConfigPromise, null, // this._printAnnotationStoragePromise,
|
|
2593
|
+
this.l10n);
|
|
2594
|
+
this.printService = printService;
|
|
2595
|
+
this.forceRendering();
|
|
2596
|
+
// Disable the editor-indicator during printing (fixes bug 1790552).
|
|
2597
|
+
// this.setTitle();
|
|
2598
|
+
printService.layout();
|
|
2599
|
+
// if (this._hasAnnotationEditors) {
|
|
2600
|
+
// this.externalServices.reportTelemetry({
|
|
2601
|
+
// type: "editing",
|
|
2602
|
+
// data: { type: "print" },
|
|
2603
|
+
// });
|
|
2604
|
+
// }
|
|
2605
|
+
}
|
|
2606
|
+
afterPrint() {
|
|
2607
|
+
// if (this._printAnnotationStoragePromise) {
|
|
2608
|
+
// this._printAnnotationStoragePromise.then(() => {
|
|
2609
|
+
// this.pdfScriptingManager.dispatchDidPrint();
|
|
2610
|
+
// });
|
|
2611
|
+
// this._printAnnotationStoragePromise = null;
|
|
2612
|
+
// }
|
|
2613
|
+
var _a;
|
|
2614
|
+
if (this.printService) {
|
|
2615
|
+
this.printService.destroy();
|
|
2616
|
+
this.printService = null;
|
|
2617
|
+
(_a = this.document) === null || _a === void 0 ? void 0 : _a.annotationStorage.resetModified();
|
|
2618
|
+
}
|
|
2619
|
+
this.forceRendering();
|
|
2620
|
+
// Re-enable the editor-indicator after printing (fixes bug 1790552).
|
|
2621
|
+
// this.setTitle();
|
|
2622
|
+
}
|
|
2623
|
+
requestPresentationMode() {
|
|
2624
|
+
var _a;
|
|
2625
|
+
(_a = this.pdfPresentationMode) === null || _a === void 0 ? void 0 : _a.request();
|
|
2626
|
+
}
|
|
2627
|
+
triggerPrinting() {
|
|
2628
|
+
if (!this.supportsPrinting) {
|
|
2629
|
+
return;
|
|
2630
|
+
}
|
|
2631
|
+
window.print();
|
|
2632
|
+
}
|
|
2633
|
+
_cleanup() {
|
|
2634
|
+
var _a;
|
|
2635
|
+
if (!this.document) {
|
|
2636
|
+
return; // run cleanup when document is loaded
|
|
2637
|
+
}
|
|
2638
|
+
try {
|
|
2639
|
+
this.viewer.cleanup();
|
|
2640
|
+
(_a = this.thumbnailViewer) === null || _a === void 0 ? void 0 : _a.cleanup();
|
|
2641
|
+
this.document.cleanup();
|
|
2642
|
+
}
|
|
2643
|
+
catch (reason) {
|
|
2644
|
+
console.error("Unable to perform cleanup", reason);
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
setAnnotationEditorMode(annotationEditorMode) {
|
|
2648
|
+
this.viewer.annotationEditorMode = annotationEditorMode;
|
|
2649
|
+
this.store.setState({ annotationEditorMode });
|
|
2650
|
+
}
|
|
2651
|
+
setAnnotationEditorParams(annotationEditorParams) {
|
|
2652
|
+
const pairs = Array.isArray(annotationEditorParams) ? annotationEditorParams : [annotationEditorParams];
|
|
2653
|
+
for (const params of pairs) {
|
|
2654
|
+
this.viewer.annotationEditorParams = params;
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
setSpreadMode(spread) {
|
|
2658
|
+
if (isValidSpreadMode(spread)) {
|
|
2659
|
+
this.viewer.spreadMode = spread;
|
|
2660
|
+
this.dispatch("switchspreadmode", { mode: spread });
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
setScrollMode(scroll) {
|
|
2664
|
+
if (isValidScrollMode(scroll)) {
|
|
2665
|
+
this.viewer.scrollMode = scroll;
|
|
2666
|
+
this.dispatch("switchscrollmode", { mode: scroll });
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
setRotation(rotation) {
|
|
2670
|
+
if (isValidRotation(rotation)) {
|
|
2671
|
+
this.viewer.pagesRotation = rotation;
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
getPagesOverview() {
|
|
2675
|
+
var _a, _b;
|
|
2676
|
+
try {
|
|
2677
|
+
const pagesOverview = (_b = (_a = this.viewer) === null || _a === void 0 ? void 0 : _a.getPagesOverview()) !== null && _b !== void 0 ? _b : [];
|
|
2678
|
+
return pagesOverview;
|
|
2679
|
+
}
|
|
2680
|
+
catch (reason) {
|
|
2681
|
+
return [];
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
/**
|
|
2685
|
+
* Zoom In
|
|
2686
|
+
*/
|
|
2687
|
+
increaseScale() {
|
|
2688
|
+
this.viewer.increaseScale();
|
|
2689
|
+
}
|
|
2690
|
+
/**
|
|
2691
|
+
* Zoom out
|
|
2692
|
+
*/
|
|
2693
|
+
decreaseScale() {
|
|
2694
|
+
this.viewer.decreaseScale();
|
|
2695
|
+
}
|
|
2696
|
+
/**
|
|
2697
|
+
* Set preset value ("auto", "page-width" wtc)
|
|
2698
|
+
*/
|
|
2699
|
+
set currentScaleValue(val) {
|
|
2700
|
+
this.viewer.currentScaleValue = val;
|
|
2701
|
+
}
|
|
2702
|
+
/**
|
|
2703
|
+
* Set viewer's scale to a number value
|
|
2704
|
+
*/
|
|
2705
|
+
set currentScale(val) {
|
|
2706
|
+
this.viewer.currentScale = val;
|
|
2707
|
+
}
|
|
2708
|
+
getPageView(ix) {
|
|
2709
|
+
return this.viewer.getPageView(ix);
|
|
2710
|
+
}
|
|
2711
|
+
/**
|
|
2712
|
+
* Add event listener on the pdfViewer eventBus
|
|
2713
|
+
* @param eventName TEventBusName
|
|
2714
|
+
* @param listener TEventBusListener
|
|
2715
|
+
* @param options TEventBusOptions
|
|
2716
|
+
*/
|
|
2717
|
+
on(eventName, listener, options) {
|
|
2718
|
+
this.eventBus.on(eventName, listener, options);
|
|
2719
|
+
}
|
|
2720
|
+
/**
|
|
2721
|
+
* Remove event listener from the pdfViewer eventBus
|
|
2722
|
+
* @param eventName TEventBusName
|
|
2723
|
+
* @param listener TEventBusListener
|
|
2724
|
+
* @param options TEventBusOptions
|
|
2725
|
+
*/
|
|
2726
|
+
off(eventName, listener, options) {
|
|
2727
|
+
this.eventBus.off(eventName, listener, options);
|
|
2728
|
+
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Dispatch event on teh eventBus
|
|
2731
|
+
* @param eventName TEventBusName
|
|
2732
|
+
* @param data Object
|
|
2733
|
+
*/
|
|
2734
|
+
dispatch(eventName, data) {
|
|
2735
|
+
this.eventBus.dispatch(eventName, data);
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
_PDFSlick_renderingQueue = new WeakMap(), _PDFSlick_container = new WeakMap(), _PDFSlick_viewerContainer = new WeakMap(), _PDFSlick_thumbsContainer = new WeakMap(), _PDFSlick_annotationMode = new WeakMap(), _PDFSlick_annotationEditorMode = new WeakMap(), _PDFSlick_instances = new WeakSet(), _PDFSlick_initializePageLabels = function _PDFSlick_initializePageLabels() {
|
|
2739
|
+
var _a;
|
|
2740
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2741
|
+
const pdfDocument = this.document;
|
|
2742
|
+
const labels = (_a = yield pdfDocument.getPageLabels()) !== null && _a !== void 0 ? _a : [];
|
|
2743
|
+
const numLabels = labels.length;
|
|
2744
|
+
// Ignore page labels that correspond to standard page numbering,
|
|
2745
|
+
// or page labels that are all empty.
|
|
2746
|
+
let standardLabels = 0, emptyLabels = 0;
|
|
2747
|
+
for (let i = 0; i < numLabels; i++) {
|
|
2748
|
+
const label = labels[i];
|
|
2749
|
+
if (label === (i + 1).toString()) {
|
|
2750
|
+
standardLabels++;
|
|
2751
|
+
}
|
|
2752
|
+
else if (label === "") {
|
|
2753
|
+
emptyLabels++;
|
|
2754
|
+
}
|
|
2755
|
+
else {
|
|
2756
|
+
break;
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
if (standardLabels >= numLabels || emptyLabels >= numLabels) {
|
|
2760
|
+
return;
|
|
2761
|
+
}
|
|
2762
|
+
const { viewer: pdfViewer, thumbnailViewer: pdfThumbnailViewer } = this;
|
|
2763
|
+
pdfViewer.setPageLabels(labels);
|
|
2764
|
+
pdfThumbnailViewer === null || pdfThumbnailViewer === void 0 ? void 0 : pdfThumbnailViewer.setPageLabels(labels);
|
|
2765
|
+
});
|
|
2766
|
+
}, _PDFSlick_parseDocumentInfo = function _PDFSlick_parseDocumentInfo() {
|
|
2767
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2768
|
+
const { info, contentLength } = yield this.document.getMetadata();
|
|
2769
|
+
const pageSize = yield this.document.getPage(this.store.getState().pageNumber).then(pdfPage => {
|
|
2770
|
+
return __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_parsePageSize).call(this, getPageSizeInches(pdfPage), 0);
|
|
2771
|
+
});
|
|
2772
|
+
this.store.setState({
|
|
2773
|
+
filesize: contentLength,
|
|
2774
|
+
title: info.Title,
|
|
2775
|
+
author: info.Author,
|
|
2776
|
+
subject: info.Subject,
|
|
2777
|
+
keywords: info.Keywords,
|
|
2778
|
+
creator: info.Creator,
|
|
2779
|
+
producer: info.Producer,
|
|
2780
|
+
version: info.PDFFormatVersion,
|
|
2781
|
+
creationDate: PDFDateString.toDateObject(info.CreationDate),
|
|
2782
|
+
modificationDate: PDFDateString.toDateObject(info.ModDate),
|
|
2783
|
+
isLinearized: info.IsLinearized,
|
|
2784
|
+
pageSize,
|
|
2785
|
+
});
|
|
2786
|
+
});
|
|
2787
|
+
}, _PDFSlick_parsePageSize = function _PDFSlick_parsePageSize(pageSizeInches, pagesRotation) {
|
|
2788
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2789
|
+
if (!pageSizeInches) {
|
|
2790
|
+
return undefined;
|
|
2791
|
+
}
|
|
2792
|
+
// Take the viewer rotation into account as well; compare with Adobe Reader.
|
|
2793
|
+
if (pagesRotation % 180 !== 0) {
|
|
2794
|
+
pageSizeInches = {
|
|
2795
|
+
width: pageSizeInches.height,
|
|
2796
|
+
height: pageSizeInches.width,
|
|
2797
|
+
};
|
|
2798
|
+
}
|
|
2799
|
+
const isPortrait = isPortraitOrientation(pageSizeInches);
|
|
2800
|
+
let sizeInches = {
|
|
2801
|
+
width: Math.round(pageSizeInches.width * 100) / 100,
|
|
2802
|
+
height: Math.round(pageSizeInches.height * 100) / 100,
|
|
2803
|
+
};
|
|
2804
|
+
// 1in == 25.4mm; no need to round to 2 decimals for millimeters.
|
|
2805
|
+
let sizeMillimeters = {
|
|
2806
|
+
width: Math.round(pageSizeInches.width * 25.4 * 10) / 10,
|
|
2807
|
+
height: Math.round(pageSizeInches.height * 25.4 * 10) / 10,
|
|
2808
|
+
};
|
|
2809
|
+
let rawName = getPageName(sizeInches, isPortrait, US_PAGE_NAMES) ||
|
|
2810
|
+
getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES);
|
|
2811
|
+
if (!rawName &&
|
|
2812
|
+
!(Number.isInteger(sizeMillimeters.width) &&
|
|
2813
|
+
Number.isInteger(sizeMillimeters.height))) {
|
|
2814
|
+
// Attempt to improve the page name detection by falling back to fuzzy
|
|
2815
|
+
// matching of the metric dimensions, to account for e.g. rounding errors
|
|
2816
|
+
// and/or PDF files that define the page sizes in an imprecise manner.
|
|
2817
|
+
const exactMillimeters = {
|
|
2818
|
+
width: pageSizeInches.width * 25.4,
|
|
2819
|
+
height: pageSizeInches.height * 25.4,
|
|
2820
|
+
};
|
|
2821
|
+
const intMillimeters = {
|
|
2822
|
+
width: Math.round(sizeMillimeters.width),
|
|
2823
|
+
height: Math.round(sizeMillimeters.height),
|
|
2824
|
+
};
|
|
2825
|
+
// Try to avoid false positives, by only considering "small" differences.
|
|
2826
|
+
if (Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 &&
|
|
2827
|
+
Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1) {
|
|
2828
|
+
rawName = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES);
|
|
2829
|
+
if (rawName) {
|
|
2830
|
+
// Update *both* sizes, computed above, to ensure that the displayed
|
|
2831
|
+
// dimensions always correspond to the detected page name.
|
|
2832
|
+
sizeInches = {
|
|
2833
|
+
width: Math.round((intMillimeters.width / 25.4) * 100) / 100,
|
|
2834
|
+
height: Math.round((intMillimeters.height / 25.4) * 100) / 100,
|
|
2835
|
+
};
|
|
2836
|
+
sizeMillimeters = intMillimeters;
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
const [{ width, height }, unit, name, orientation] = yield Promise.all([
|
|
2841
|
+
sizeInches ,
|
|
2842
|
+
this.l10n.get(`document_properties_page_size_unit_${"inches" }`),
|
|
2843
|
+
rawName &&
|
|
2844
|
+
this.l10n.get(`document_properties_page_size_name_${rawName.toLowerCase()}`),
|
|
2845
|
+
this.l10n.get(`document_properties_page_size_orientation_${isPortrait ? "portrait" : "landscape"}`),
|
|
2846
|
+
]);
|
|
2847
|
+
return {
|
|
2848
|
+
width: width.toLocaleString(),
|
|
2849
|
+
height: height.toLocaleString(),
|
|
2850
|
+
unit,
|
|
2851
|
+
name,
|
|
2852
|
+
orientation,
|
|
2853
|
+
};
|
|
2854
|
+
});
|
|
2855
|
+
}, _PDFSlick_initInternalEventListeners = function _PDFSlick_initInternalEventListeners() {
|
|
2856
|
+
this.eventBus._on("pagesinit", __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_onDocumentReady).bind(this));
|
|
2857
|
+
this.eventBus._on("scalechanging", __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_onScaleChanging).bind(this));
|
|
2858
|
+
this.eventBus._on("pagechanging", __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_onPageChanging).bind(this));
|
|
2859
|
+
this.eventBus._on("pagerendered", __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_onPageRendered).bind(this));
|
|
2860
|
+
this.eventBus._on("rotationchanging", __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_onRotationChanging).bind(this));
|
|
2861
|
+
this.eventBus._on("switchspreadmode", __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_onSwitchSpreadMode).bind(this));
|
|
2862
|
+
this.eventBus._on("switchscrollmode", __classPrivateFieldGet(this, _PDFSlick_instances, "m", _PDFSlick_onSwitchScrollMode).bind(this));
|
|
2863
|
+
this.eventBus._on("beforeprint", this.beforePrint.bind(this));
|
|
2864
|
+
this.eventBus._on("afterprint", this.afterPrint.bind(this));
|
|
2865
|
+
window.onbeforeprint = (e) => {
|
|
2866
|
+
this.eventBus.dispatch("beforeprint", { source: window });
|
|
2867
|
+
};
|
|
2868
|
+
window.onafterprint = (e) => {
|
|
2869
|
+
this.eventBus.dispatch("afterprint", { source: window });
|
|
2870
|
+
};
|
|
2871
|
+
}, _PDFSlick_onDocumentReady = function _PDFSlick_onDocumentReady({ source }) {
|
|
2872
|
+
var _a;
|
|
2873
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2874
|
+
const documentOutline = yield ((_a = this.document) === null || _a === void 0 ? void 0 : _a.getOutline());
|
|
2875
|
+
const scaleValue = this.store.getState().scaleValue;
|
|
2876
|
+
// source._setScale(scaleValue, {}); // page-fit, page-actual, auto, page-width
|
|
2877
|
+
source.currentScale = 1;
|
|
2878
|
+
source.currentScaleValue = "auto";
|
|
2879
|
+
this.store.setState({ documentOutline, pageNumber: 1, scaleValue, pagesReady: true });
|
|
2880
|
+
});
|
|
2881
|
+
}, _PDFSlick_onRotationChanging = function _PDFSlick_onRotationChanging({ pagesRotation, pageNumber }) {
|
|
2882
|
+
this.store.setState({ pagesRotation });
|
|
2883
|
+
if (this.thumbnailViewer) {
|
|
2884
|
+
this.thumbnailViewer.pagesRotation = pagesRotation;
|
|
2885
|
+
}
|
|
2886
|
+
this.forceRendering();
|
|
2887
|
+
// Ensure that the active page doesn't change during rotation.
|
|
2888
|
+
this.viewer.currentPageNumber = pageNumber;
|
|
2889
|
+
}, _PDFSlick_onSwitchSpreadMode = function _PDFSlick_onSwitchSpreadMode({ mode: spreadMode }) {
|
|
2890
|
+
this.store.setState({ spreadMode });
|
|
2891
|
+
}, _PDFSlick_onSwitchScrollMode = function _PDFSlick_onSwitchScrollMode({ mode: scrollMode }) {
|
|
2892
|
+
this.store.setState({ scrollMode });
|
|
2893
|
+
}, _PDFSlick_onScaleChanging = function _PDFSlick_onScaleChanging({ scale, presetValue: scaleValue }) {
|
|
2894
|
+
this.store.setState({ scale, scaleValue });
|
|
2895
|
+
this.viewer.update();
|
|
2896
|
+
}, _PDFSlick_onPageChanging = function _PDFSlick_onPageChanging({ pageNumber }) {
|
|
2897
|
+
var _a;
|
|
2898
|
+
(_a = this.thumbnailViewer) === null || _a === void 0 ? void 0 : _a.scrollThumbnailIntoView(pageNumber);
|
|
2899
|
+
this.store.setState({ pageNumber });
|
|
2900
|
+
}, _PDFSlick_onPageRendered = function _PDFSlick_onPageRendered({ pageNumber, error }) {
|
|
2901
|
+
var _a;
|
|
2902
|
+
// Use the rendered page to set the corresponding thumbnail image.
|
|
2903
|
+
if (__classPrivateFieldGet(this, _PDFSlick_thumbsContainer, "f")) {
|
|
2904
|
+
const pageView = this.viewer.getPageView(pageNumber - 1);
|
|
2905
|
+
const thumbnailView = (_a = this.thumbnailViewer) === null || _a === void 0 ? void 0 : _a.getThumbnail(pageNumber - 1);
|
|
2906
|
+
if (pageView && thumbnailView) {
|
|
2907
|
+
thumbnailView.setImage(pageView);
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
};
|
|
2911
|
+
|
|
2912
|
+
export { AutoPrintRegExp, CursorTool, DEFAULT_SCALE, DEFAULT_SCALE_DELTA, DEFAULT_SCALE_VALUE, MAX_AUTO_SCALE, MAX_SCALE, MIN_SCALE, OutputScale, PDFSlick, PresentationModeState, ProgressBar, RendererType, RenderingStates, SCROLLBAR_PADDING, ScrollMode, SidebarView, SpreadMode, TextLayerMode, UNKNOWN_SCALE, VERTICAL_PADDING, animationStarted, apiPageLayoutToViewerModes, apiPageModeToSidebarView, approximateFraction, backtrackBeforeAllVisibleElements, binarySearchFirstItem, create, docStyle, getActiveOrFocusedElement, getPageSizeInches, getVisibleElements, initialState, isPortraitOrientation, isValidRotation, isValidScrollMode, isValidSpreadMode, noContextMenuHandler, normalizeWheelEventDelta, normalizeWheelEventDirection, parseQueryString, removeNullCharacters, roundToDivide, scrollIntoView, watchScroll };
|