@progress/kendo-pdfviewer-common 0.2.11 → 0.3.0-dev.202409251459
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/es/annotations.js +68 -0
- package/dist/es/scroller.js +22 -0
- package/dist/es/utils.js +85 -9
- package/dist/es2015/annotations.js +68 -0
- package/dist/es2015/scroller.js +22 -0
- package/dist/es2015/utils.js +85 -9
- package/dist/npm/annotations.d.ts +23 -0
- package/dist/npm/annotations.js +72 -0
- package/dist/npm/scroller.d.ts +1 -0
- package/dist/npm/scroller.js +22 -0
- package/dist/npm/utils.d.ts +11 -0
- package/dist/npm/utils.js +90 -12
- package/package.json +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { createElement, scrollToPage } from './utils';
|
|
2
|
+
class Annotation {
|
|
3
|
+
constructor(container, viewport, annotation, pdfDoc, zoom, rootElement) {
|
|
4
|
+
this.container = container;
|
|
5
|
+
this.viewport = viewport;
|
|
6
|
+
this.zoom = zoom;
|
|
7
|
+
this.annotation = annotation;
|
|
8
|
+
this.pdfDoc = pdfDoc;
|
|
9
|
+
this.rootElement = rootElement;
|
|
10
|
+
}
|
|
11
|
+
destroy() {
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class LinkAnnotation extends Annotation {
|
|
15
|
+
constructor(container, viewport, annotation, pdfDoc, zoom, rootElement) {
|
|
16
|
+
super(container, viewport, annotation, pdfDoc, zoom, rootElement);
|
|
17
|
+
this.onLinkClick = (e) => {
|
|
18
|
+
const destination = e.target.getAttribute('href');
|
|
19
|
+
if (destination && destination.indexOf('#') === 0) {
|
|
20
|
+
this.navigateToDestination(destination);
|
|
21
|
+
e.preventDefault();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
this.linkElement = null;
|
|
25
|
+
this.renderAnnotation();
|
|
26
|
+
this.bindEvents();
|
|
27
|
+
}
|
|
28
|
+
destroy() {
|
|
29
|
+
this.unbindEvents();
|
|
30
|
+
}
|
|
31
|
+
bindEvents() {
|
|
32
|
+
this.linkElement.addEventListener('click', this.onLinkClick);
|
|
33
|
+
}
|
|
34
|
+
unbindEvents() {
|
|
35
|
+
this.linkElement.removeEventListener('click', this.onLinkClick);
|
|
36
|
+
}
|
|
37
|
+
navigateToDestination(destination) {
|
|
38
|
+
const dest = destination.split('#')[1];
|
|
39
|
+
this.pdfDoc.getDestination(dest).then(r => {
|
|
40
|
+
this.pdfDoc.getPageIndex(r[0]).then(i => this.goToPage(i));
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
goToPage(pageNumber) {
|
|
44
|
+
scrollToPage(this.rootElement, pageNumber);
|
|
45
|
+
}
|
|
46
|
+
renderAnnotation() {
|
|
47
|
+
const annotation = this.annotation, viewport = this.viewport, rect = annotation.rect, boundingRect = [
|
|
48
|
+
[rect[0], rect[1]],
|
|
49
|
+
[rect[2], rect[3]]
|
|
50
|
+
], rawHeight = viewport.rawDims.pageHeight;
|
|
51
|
+
const left = Math.min(boundingRect[0][0], boundingRect[1][0]) * this.zoom, top = (rawHeight - Math.max(boundingRect[0][1], boundingRect[1][1])) * this.zoom, width = (boundingRect[1][0] - boundingRect[0][0]) * this.zoom, height = (boundingRect[1][1] - boundingRect[0][1]) * this.zoom;
|
|
52
|
+
const url = annotation.url || (annotation.dest && `#${encodeURI(annotation.dest)}`);
|
|
53
|
+
const annotationElement = createElement('span', '', {
|
|
54
|
+
position: 'absolute',
|
|
55
|
+
left: left + 'pt',
|
|
56
|
+
top: top + 'pt'
|
|
57
|
+
});
|
|
58
|
+
const linkElement = this.linkElement = createElement('a', '', {
|
|
59
|
+
width: width + 'pt',
|
|
60
|
+
height: height + 'pt',
|
|
61
|
+
display: 'inline-block',
|
|
62
|
+
pointerEvents: 'auto'
|
|
63
|
+
});
|
|
64
|
+
linkElement.setAttribute('href', url);
|
|
65
|
+
annotationElement.append(linkElement);
|
|
66
|
+
this.container.append(annotationElement);
|
|
67
|
+
}
|
|
68
|
+
}
|
package/dist/es/scroller.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Draggable from '@progress/kendo-draggable';
|
|
2
|
+
import { renderPage, currentPage } from './utils';
|
|
2
3
|
const throttle = function (func, wait, options = {}) {
|
|
3
4
|
let timeout, context, args, result;
|
|
4
5
|
let previous = 0;
|
|
@@ -81,6 +82,21 @@ export class Scroller {
|
|
|
81
82
|
this.state.trackNextElementScroll = true;
|
|
82
83
|
}
|
|
83
84
|
};
|
|
85
|
+
this.onDemandScroll = () => {
|
|
86
|
+
const pages = this.options.pages, currentPageIndex = currentPage(this.element.parentElement), page = pages[currentPageIndex], nextPage = pages[currentPageIndex + 1], previousPage = pages[currentPageIndex - 1], pageInfo = page === null || page === void 0 ? void 0 : page._pageInfo, nextPageInfo = nextPage === null || nextPage === void 0 ? void 0 : nextPage._pageInfo, previousPageInfo = previousPage === null || previousPage === void 0 ? void 0 : previousPage._pageInfo, error = (e) => {
|
|
87
|
+
throw new Error(e);
|
|
88
|
+
};
|
|
89
|
+
// Render the current and surrounding pages if they have not been rendered already.
|
|
90
|
+
if (page && !pageInfo.rendered && !pageInfo.renderInProgress) {
|
|
91
|
+
renderPage(page, pageInfo.emptyPage, error);
|
|
92
|
+
}
|
|
93
|
+
if (nextPage && !nextPageInfo.rendered && !nextPageInfo.renderInProgress) {
|
|
94
|
+
renderPage(nextPage, nextPageInfo.emptyPage, error);
|
|
95
|
+
}
|
|
96
|
+
if (previousPage && !previousPageInfo.rendered && !previousPageInfo.renderInProgress) {
|
|
97
|
+
renderPage(previousPage, previousPageInfo.emptyPage, error);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
84
100
|
this.onDragStart = (e) => {
|
|
85
101
|
this.state.dragStarted = false;
|
|
86
102
|
if (!this.shouldTrackPanEvents()) {
|
|
@@ -175,6 +191,9 @@ export class Scroller {
|
|
|
175
191
|
this.throttledOnElementScroll = this.onElementScroll;
|
|
176
192
|
}
|
|
177
193
|
this.element.addEventListener(SCROLL, this.throttledOnElementScroll);
|
|
194
|
+
if (this.options.loadOnDemand) {
|
|
195
|
+
this.element.addEventListener(SCROLL, this.onDemandScroll);
|
|
196
|
+
}
|
|
178
197
|
}
|
|
179
198
|
unbindEvents() {
|
|
180
199
|
this.unbindElementScroll();
|
|
@@ -189,6 +208,9 @@ export class Scroller {
|
|
|
189
208
|
this.throttledOnElementScroll.cancel();
|
|
190
209
|
this.throttledOnElementScroll = null;
|
|
191
210
|
}
|
|
211
|
+
if (this.options.loadOnDemand) {
|
|
212
|
+
this.element.removeEventListener(SCROLL, this.onDemandScroll);
|
|
213
|
+
}
|
|
192
214
|
this.element.removeEventListener(SCROLL, this.throttledOnElementScroll);
|
|
193
215
|
}
|
|
194
216
|
setState(newState) {
|
package/dist/es/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { saveAs } from '@progress/kendo-file-saver';
|
|
2
2
|
import { detectDesktopBrowser, detectMobileOS } from '@progress/kendo-common';
|
|
3
3
|
import { getDocument, TextLayer } from 'pdfjs-dist/legacy/build/pdf.mjs';
|
|
4
|
+
import { LinkAnnotation } from './annotations';
|
|
4
5
|
const MAX_CANVAS_WIDTH_HEIGHT_CHROME = 65535;
|
|
5
6
|
const MAX_CANVAS_AREA_CHROME_SAFARI = 268435456;
|
|
6
7
|
const MAX_CANVAS_WIDTH_HEIGHT_FIREFOX = 32767;
|
|
@@ -83,7 +84,8 @@ export const download = (options, fileName = 'Document', saveOptions = {}, onDow
|
|
|
83
84
|
*/
|
|
84
85
|
export const loadPDF = (options) => {
|
|
85
86
|
const params = getDocumentParameters(options);
|
|
86
|
-
const { dom, zoom, done, error } = options;
|
|
87
|
+
const { dom, zoom, done, error, rootElement, enableAnnotations } = options;
|
|
88
|
+
const loadOnDemandPageSize = options.loadOnDemandPageSize || 2;
|
|
87
89
|
getDocument(params)
|
|
88
90
|
.promise.then((pdfDoc) => {
|
|
89
91
|
const pages = [];
|
|
@@ -94,7 +96,18 @@ export const loadPDF = (options) => {
|
|
|
94
96
|
}).then(({ pages, pdfDoc }) => {
|
|
95
97
|
Promise.all(pages)
|
|
96
98
|
.then((all) => all.map((page, i) => {
|
|
97
|
-
|
|
99
|
+
const emptyPage = createEmptyPage(page, zoom, pdfDoc, enableAnnotations, rootElement);
|
|
100
|
+
appendPage(dom, emptyPage.pageElement, i);
|
|
101
|
+
if (options.loadOnDemand) {
|
|
102
|
+
// If LOD is enabled, render the first two(default) or X pages initially.
|
|
103
|
+
if (i < loadOnDemandPageSize) {
|
|
104
|
+
renderPage(page, emptyPage, error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
renderPage(page, emptyPage, error);
|
|
109
|
+
}
|
|
110
|
+
page._pageInfo.emptyPage = emptyPage;
|
|
98
111
|
return page;
|
|
99
112
|
})).then((pdfPages) => {
|
|
100
113
|
// required by new PDFJS version
|
|
@@ -122,17 +135,39 @@ export const loadPDF = (options) => {
|
|
|
122
135
|
* @hidden
|
|
123
136
|
*/
|
|
124
137
|
export const reloadDocument = (params) => {
|
|
125
|
-
const { pdfDoc, zoom, dom, done, error } = params;
|
|
138
|
+
const { pdfDoc, zoom, dom, done, error, loadOnDemand, rootElement, enableAnnotations } = params;
|
|
126
139
|
const pages = [];
|
|
140
|
+
let currentPageIndex = 0;
|
|
141
|
+
// Save the index of the current page in view before we reload the document.
|
|
142
|
+
if (loadOnDemand && rootElement) {
|
|
143
|
+
currentPageIndex = currentPage(rootElement);
|
|
144
|
+
}
|
|
127
145
|
for (let i = 1; i <= pdfDoc.numPages; i++) {
|
|
128
146
|
pages.push(pdfDoc.getPage(i));
|
|
129
147
|
}
|
|
130
148
|
Promise.all(pages)
|
|
131
149
|
.then((all) => all.map((page, i) => {
|
|
132
|
-
|
|
150
|
+
// Set 'rendered' back to false so that the pages can be re-rendered when scrolling.
|
|
151
|
+
page._pageInfo.rendered = false;
|
|
152
|
+
const emptyPage = createEmptyPage(page, zoom, pdfDoc, enableAnnotations, rootElement);
|
|
153
|
+
appendPage(dom, emptyPage.pageElement, i);
|
|
154
|
+
// If on demand is not enabled, proceed as usual.
|
|
155
|
+
if (!loadOnDemand) {
|
|
156
|
+
renderPage(page, emptyPage, error);
|
|
157
|
+
}
|
|
158
|
+
page._pageInfo.emptyPage = emptyPage;
|
|
133
159
|
return page;
|
|
134
160
|
}))
|
|
135
|
-
.then(
|
|
161
|
+
.then((pdfPages) => {
|
|
162
|
+
/* If on demand is enabled, render the page that was previously in view.
|
|
163
|
+
Then scroll to that page. */
|
|
164
|
+
if (loadOnDemand) {
|
|
165
|
+
const page = pdfPages[currentPageIndex];
|
|
166
|
+
renderPage(page, page._pageInfo.emptyPage, error);
|
|
167
|
+
scrollToPage(rootElement, currentPageIndex);
|
|
168
|
+
}
|
|
169
|
+
done(pdfPages);
|
|
170
|
+
})
|
|
136
171
|
.catch(error);
|
|
137
172
|
};
|
|
138
173
|
/**
|
|
@@ -177,6 +212,19 @@ const openPrintDialog = (dom, width, height, done, onError) => {
|
|
|
177
212
|
printDialog.addEventListener('afterprint', onAfterPrint);
|
|
178
213
|
}
|
|
179
214
|
};
|
|
215
|
+
const createEmptyPage = (page, zoom, pdfDoc, enableAnnotations, rootElement) => {
|
|
216
|
+
const { canvasContext, viewport, pageElement, styles } = createCanvas(page, zoom, 'k-page');
|
|
217
|
+
return {
|
|
218
|
+
canvasContext,
|
|
219
|
+
viewport,
|
|
220
|
+
pageElement,
|
|
221
|
+
styles,
|
|
222
|
+
zoom,
|
|
223
|
+
pdfDoc,
|
|
224
|
+
enableAnnotations,
|
|
225
|
+
rootElement
|
|
226
|
+
};
|
|
227
|
+
};
|
|
180
228
|
const renderCanvas = (page, done, error) => {
|
|
181
229
|
const { canvasContext, viewport, scaleNum, canvas, pageElement } = createCanvas(page);
|
|
182
230
|
page.render({ canvasContext, viewport })
|
|
@@ -192,7 +240,7 @@ const renderCanvas = (page, done, error) => {
|
|
|
192
240
|
.catch(error);
|
|
193
241
|
return viewport;
|
|
194
242
|
};
|
|
195
|
-
const createElement = function (name, className, styles) {
|
|
243
|
+
export const createElement = function (name, className, styles) {
|
|
196
244
|
const element = document.createElement(name);
|
|
197
245
|
if (className) {
|
|
198
246
|
element.className = className;
|
|
@@ -206,8 +254,9 @@ const transforms = {
|
|
|
206
254
|
'180': 'rotate(180deg) translate(-100%, -100%)',
|
|
207
255
|
'270': 'rotate(270deg) translateX(-100%)'
|
|
208
256
|
};
|
|
209
|
-
const renderPage = (page,
|
|
210
|
-
const { canvasContext, viewport, pageElement, styles
|
|
257
|
+
export const renderPage = (page, emptyPage, error) => {
|
|
258
|
+
const { canvasContext, viewport, pageElement, styles, zoom, pdfDoc, enableAnnotations, rootElement } = emptyPage;
|
|
259
|
+
page._pageInfo.renderInProgress = true;
|
|
211
260
|
page.render({ canvasContext, viewport })
|
|
212
261
|
.promise.then(() => {
|
|
213
262
|
page.getTextContent().then((textContent) => {
|
|
@@ -229,9 +278,36 @@ const renderPage = (page, zoom, error) => {
|
|
|
229
278
|
el.style.fontSize = el.style.fontSize.replace(/px/g, 'pt');
|
|
230
279
|
}
|
|
231
280
|
});
|
|
232
|
-
pageElement.
|
|
281
|
+
pageElement.prepend(textLayer); // Use prepend to ensure the element is always inserted before the annotation layer.
|
|
233
282
|
}).catch(error);
|
|
234
283
|
});
|
|
284
|
+
if (enableAnnotations) {
|
|
285
|
+
page.getAnnotations({ intent: 'display' }).then((annotations) => {
|
|
286
|
+
const annotationLayer = createElement('div', 'k-annotations-layer', {
|
|
287
|
+
position: 'absolute',
|
|
288
|
+
top: '0',
|
|
289
|
+
left: '0',
|
|
290
|
+
overflow: 'hidden',
|
|
291
|
+
height: styles.height,
|
|
292
|
+
width: styles.width,
|
|
293
|
+
pointerEvents: 'none'
|
|
294
|
+
});
|
|
295
|
+
pageElement.appendChild(annotationLayer);
|
|
296
|
+
for (const annotation of annotations) {
|
|
297
|
+
switch (annotation.subtype) {
|
|
298
|
+
case 'Link':
|
|
299
|
+
new LinkAnnotation(annotationLayer, viewport, annotation, pdfDoc, zoom, rootElement);
|
|
300
|
+
break;
|
|
301
|
+
default:
|
|
302
|
+
null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
.then(() => {
|
|
309
|
+
page._pageInfo.rendered = true;
|
|
310
|
+
page._pageInfo.renderInProgress = false;
|
|
235
311
|
})
|
|
236
312
|
.catch(error);
|
|
237
313
|
return pageElement;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { createElement, scrollToPage } from './utils';
|
|
2
|
+
class Annotation {
|
|
3
|
+
constructor(container, viewport, annotation, pdfDoc, zoom, rootElement) {
|
|
4
|
+
this.container = container;
|
|
5
|
+
this.viewport = viewport;
|
|
6
|
+
this.zoom = zoom;
|
|
7
|
+
this.annotation = annotation;
|
|
8
|
+
this.pdfDoc = pdfDoc;
|
|
9
|
+
this.rootElement = rootElement;
|
|
10
|
+
}
|
|
11
|
+
destroy() {
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class LinkAnnotation extends Annotation {
|
|
15
|
+
constructor(container, viewport, annotation, pdfDoc, zoom, rootElement) {
|
|
16
|
+
super(container, viewport, annotation, pdfDoc, zoom, rootElement);
|
|
17
|
+
this.onLinkClick = (e) => {
|
|
18
|
+
const destination = e.target.getAttribute('href');
|
|
19
|
+
if (destination && destination.indexOf('#') === 0) {
|
|
20
|
+
this.navigateToDestination(destination);
|
|
21
|
+
e.preventDefault();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
this.linkElement = null;
|
|
25
|
+
this.renderAnnotation();
|
|
26
|
+
this.bindEvents();
|
|
27
|
+
}
|
|
28
|
+
destroy() {
|
|
29
|
+
this.unbindEvents();
|
|
30
|
+
}
|
|
31
|
+
bindEvents() {
|
|
32
|
+
this.linkElement.addEventListener('click', this.onLinkClick);
|
|
33
|
+
}
|
|
34
|
+
unbindEvents() {
|
|
35
|
+
this.linkElement.removeEventListener('click', this.onLinkClick);
|
|
36
|
+
}
|
|
37
|
+
navigateToDestination(destination) {
|
|
38
|
+
const dest = destination.split('#')[1];
|
|
39
|
+
this.pdfDoc.getDestination(dest).then(r => {
|
|
40
|
+
this.pdfDoc.getPageIndex(r[0]).then(i => this.goToPage(i));
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
goToPage(pageNumber) {
|
|
44
|
+
scrollToPage(this.rootElement, pageNumber);
|
|
45
|
+
}
|
|
46
|
+
renderAnnotation() {
|
|
47
|
+
const annotation = this.annotation, viewport = this.viewport, rect = annotation.rect, boundingRect = [
|
|
48
|
+
[rect[0], rect[1]],
|
|
49
|
+
[rect[2], rect[3]]
|
|
50
|
+
], rawHeight = viewport.rawDims.pageHeight;
|
|
51
|
+
const left = Math.min(boundingRect[0][0], boundingRect[1][0]) * this.zoom, top = (rawHeight - Math.max(boundingRect[0][1], boundingRect[1][1])) * this.zoom, width = (boundingRect[1][0] - boundingRect[0][0]) * this.zoom, height = (boundingRect[1][1] - boundingRect[0][1]) * this.zoom;
|
|
52
|
+
const url = annotation.url || (annotation.dest && `#${encodeURI(annotation.dest)}`);
|
|
53
|
+
const annotationElement = createElement('span', '', {
|
|
54
|
+
position: 'absolute',
|
|
55
|
+
left: left + 'pt',
|
|
56
|
+
top: top + 'pt'
|
|
57
|
+
});
|
|
58
|
+
const linkElement = this.linkElement = createElement('a', '', {
|
|
59
|
+
width: width + 'pt',
|
|
60
|
+
height: height + 'pt',
|
|
61
|
+
display: 'inline-block',
|
|
62
|
+
pointerEvents: 'auto'
|
|
63
|
+
});
|
|
64
|
+
linkElement.setAttribute('href', url);
|
|
65
|
+
annotationElement.append(linkElement);
|
|
66
|
+
this.container.append(annotationElement);
|
|
67
|
+
}
|
|
68
|
+
}
|
package/dist/es2015/scroller.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Draggable from '@progress/kendo-draggable';
|
|
2
|
+
import { renderPage, currentPage } from './utils';
|
|
2
3
|
const throttle = function (func, wait, options = {}) {
|
|
3
4
|
let timeout, context, args, result;
|
|
4
5
|
let previous = 0;
|
|
@@ -81,6 +82,21 @@ export class Scroller {
|
|
|
81
82
|
this.state.trackNextElementScroll = true;
|
|
82
83
|
}
|
|
83
84
|
};
|
|
85
|
+
this.onDemandScroll = () => {
|
|
86
|
+
const pages = this.options.pages, currentPageIndex = currentPage(this.element.parentElement), page = pages[currentPageIndex], nextPage = pages[currentPageIndex + 1], previousPage = pages[currentPageIndex - 1], pageInfo = page === null || page === void 0 ? void 0 : page._pageInfo, nextPageInfo = nextPage === null || nextPage === void 0 ? void 0 : nextPage._pageInfo, previousPageInfo = previousPage === null || previousPage === void 0 ? void 0 : previousPage._pageInfo, error = (e) => {
|
|
87
|
+
throw new Error(e);
|
|
88
|
+
};
|
|
89
|
+
// Render the current and surrounding pages if they have not been rendered already.
|
|
90
|
+
if (page && !pageInfo.rendered && !pageInfo.renderInProgress) {
|
|
91
|
+
renderPage(page, pageInfo.emptyPage, error);
|
|
92
|
+
}
|
|
93
|
+
if (nextPage && !nextPageInfo.rendered && !nextPageInfo.renderInProgress) {
|
|
94
|
+
renderPage(nextPage, nextPageInfo.emptyPage, error);
|
|
95
|
+
}
|
|
96
|
+
if (previousPage && !previousPageInfo.rendered && !previousPageInfo.renderInProgress) {
|
|
97
|
+
renderPage(previousPage, previousPageInfo.emptyPage, error);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
84
100
|
this.onDragStart = (e) => {
|
|
85
101
|
this.state.dragStarted = false;
|
|
86
102
|
if (!this.shouldTrackPanEvents()) {
|
|
@@ -175,6 +191,9 @@ export class Scroller {
|
|
|
175
191
|
this.throttledOnElementScroll = this.onElementScroll;
|
|
176
192
|
}
|
|
177
193
|
this.element.addEventListener(SCROLL, this.throttledOnElementScroll);
|
|
194
|
+
if (this.options.loadOnDemand) {
|
|
195
|
+
this.element.addEventListener(SCROLL, this.onDemandScroll);
|
|
196
|
+
}
|
|
178
197
|
}
|
|
179
198
|
unbindEvents() {
|
|
180
199
|
this.unbindElementScroll();
|
|
@@ -189,6 +208,9 @@ export class Scroller {
|
|
|
189
208
|
this.throttledOnElementScroll.cancel();
|
|
190
209
|
this.throttledOnElementScroll = null;
|
|
191
210
|
}
|
|
211
|
+
if (this.options.loadOnDemand) {
|
|
212
|
+
this.element.removeEventListener(SCROLL, this.onDemandScroll);
|
|
213
|
+
}
|
|
192
214
|
this.element.removeEventListener(SCROLL, this.throttledOnElementScroll);
|
|
193
215
|
}
|
|
194
216
|
setState(newState) {
|
package/dist/es2015/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { saveAs } from '@progress/kendo-file-saver';
|
|
2
2
|
import { detectDesktopBrowser, detectMobileOS } from '@progress/kendo-common';
|
|
3
3
|
import { getDocument, TextLayer } from 'pdfjs-dist/legacy/build/pdf.mjs';
|
|
4
|
+
import { LinkAnnotation } from './annotations';
|
|
4
5
|
const MAX_CANVAS_WIDTH_HEIGHT_CHROME = 65535;
|
|
5
6
|
const MAX_CANVAS_AREA_CHROME_SAFARI = 268435456;
|
|
6
7
|
const MAX_CANVAS_WIDTH_HEIGHT_FIREFOX = 32767;
|
|
@@ -83,7 +84,8 @@ export const download = (options, fileName = 'Document', saveOptions = {}, onDow
|
|
|
83
84
|
*/
|
|
84
85
|
export const loadPDF = (options) => {
|
|
85
86
|
const params = getDocumentParameters(options);
|
|
86
|
-
const { dom, zoom, done, error } = options;
|
|
87
|
+
const { dom, zoom, done, error, rootElement, enableAnnotations } = options;
|
|
88
|
+
const loadOnDemandPageSize = options.loadOnDemandPageSize || 2;
|
|
87
89
|
getDocument(params)
|
|
88
90
|
.promise.then((pdfDoc) => {
|
|
89
91
|
const pages = [];
|
|
@@ -94,7 +96,18 @@ export const loadPDF = (options) => {
|
|
|
94
96
|
}).then(({ pages, pdfDoc }) => {
|
|
95
97
|
Promise.all(pages)
|
|
96
98
|
.then((all) => all.map((page, i) => {
|
|
97
|
-
|
|
99
|
+
const emptyPage = createEmptyPage(page, zoom, pdfDoc, enableAnnotations, rootElement);
|
|
100
|
+
appendPage(dom, emptyPage.pageElement, i);
|
|
101
|
+
if (options.loadOnDemand) {
|
|
102
|
+
// If LOD is enabled, render the first two(default) or X pages initially.
|
|
103
|
+
if (i < loadOnDemandPageSize) {
|
|
104
|
+
renderPage(page, emptyPage, error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
renderPage(page, emptyPage, error);
|
|
109
|
+
}
|
|
110
|
+
page._pageInfo.emptyPage = emptyPage;
|
|
98
111
|
return page;
|
|
99
112
|
})).then((pdfPages) => {
|
|
100
113
|
// required by new PDFJS version
|
|
@@ -122,17 +135,39 @@ export const loadPDF = (options) => {
|
|
|
122
135
|
* @hidden
|
|
123
136
|
*/
|
|
124
137
|
export const reloadDocument = (params) => {
|
|
125
|
-
const { pdfDoc, zoom, dom, done, error } = params;
|
|
138
|
+
const { pdfDoc, zoom, dom, done, error, loadOnDemand, rootElement, enableAnnotations } = params;
|
|
126
139
|
const pages = [];
|
|
140
|
+
let currentPageIndex = 0;
|
|
141
|
+
// Save the index of the current page in view before we reload the document.
|
|
142
|
+
if (loadOnDemand && rootElement) {
|
|
143
|
+
currentPageIndex = currentPage(rootElement);
|
|
144
|
+
}
|
|
127
145
|
for (let i = 1; i <= pdfDoc.numPages; i++) {
|
|
128
146
|
pages.push(pdfDoc.getPage(i));
|
|
129
147
|
}
|
|
130
148
|
Promise.all(pages)
|
|
131
149
|
.then((all) => all.map((page, i) => {
|
|
132
|
-
|
|
150
|
+
// Set 'rendered' back to false so that the pages can be re-rendered when scrolling.
|
|
151
|
+
page._pageInfo.rendered = false;
|
|
152
|
+
const emptyPage = createEmptyPage(page, zoom, pdfDoc, enableAnnotations, rootElement);
|
|
153
|
+
appendPage(dom, emptyPage.pageElement, i);
|
|
154
|
+
// If on demand is not enabled, proceed as usual.
|
|
155
|
+
if (!loadOnDemand) {
|
|
156
|
+
renderPage(page, emptyPage, error);
|
|
157
|
+
}
|
|
158
|
+
page._pageInfo.emptyPage = emptyPage;
|
|
133
159
|
return page;
|
|
134
160
|
}))
|
|
135
|
-
.then(
|
|
161
|
+
.then((pdfPages) => {
|
|
162
|
+
/* If on demand is enabled, render the page that was previously in view.
|
|
163
|
+
Then scroll to that page. */
|
|
164
|
+
if (loadOnDemand) {
|
|
165
|
+
const page = pdfPages[currentPageIndex];
|
|
166
|
+
renderPage(page, page._pageInfo.emptyPage, error);
|
|
167
|
+
scrollToPage(rootElement, currentPageIndex);
|
|
168
|
+
}
|
|
169
|
+
done(pdfPages);
|
|
170
|
+
})
|
|
136
171
|
.catch(error);
|
|
137
172
|
};
|
|
138
173
|
/**
|
|
@@ -177,6 +212,19 @@ const openPrintDialog = (dom, width, height, done, onError) => {
|
|
|
177
212
|
printDialog.addEventListener('afterprint', onAfterPrint);
|
|
178
213
|
}
|
|
179
214
|
};
|
|
215
|
+
const createEmptyPage = (page, zoom, pdfDoc, enableAnnotations, rootElement) => {
|
|
216
|
+
const { canvasContext, viewport, pageElement, styles } = createCanvas(page, zoom, 'k-page');
|
|
217
|
+
return {
|
|
218
|
+
canvasContext,
|
|
219
|
+
viewport,
|
|
220
|
+
pageElement,
|
|
221
|
+
styles,
|
|
222
|
+
zoom,
|
|
223
|
+
pdfDoc,
|
|
224
|
+
enableAnnotations,
|
|
225
|
+
rootElement
|
|
226
|
+
};
|
|
227
|
+
};
|
|
180
228
|
const renderCanvas = (page, done, error) => {
|
|
181
229
|
const { canvasContext, viewport, scaleNum, canvas, pageElement } = createCanvas(page);
|
|
182
230
|
page.render({ canvasContext, viewport })
|
|
@@ -192,7 +240,7 @@ const renderCanvas = (page, done, error) => {
|
|
|
192
240
|
.catch(error);
|
|
193
241
|
return viewport;
|
|
194
242
|
};
|
|
195
|
-
const createElement = function (name, className, styles) {
|
|
243
|
+
export const createElement = function (name, className, styles) {
|
|
196
244
|
const element = document.createElement(name);
|
|
197
245
|
if (className) {
|
|
198
246
|
element.className = className;
|
|
@@ -206,8 +254,9 @@ const transforms = {
|
|
|
206
254
|
'180': 'rotate(180deg) translate(-100%, -100%)',
|
|
207
255
|
'270': 'rotate(270deg) translateX(-100%)'
|
|
208
256
|
};
|
|
209
|
-
const renderPage = (page,
|
|
210
|
-
const { canvasContext, viewport, pageElement, styles
|
|
257
|
+
export const renderPage = (page, emptyPage, error) => {
|
|
258
|
+
const { canvasContext, viewport, pageElement, styles, zoom, pdfDoc, enableAnnotations, rootElement } = emptyPage;
|
|
259
|
+
page._pageInfo.renderInProgress = true;
|
|
211
260
|
page.render({ canvasContext, viewport })
|
|
212
261
|
.promise.then(() => {
|
|
213
262
|
page.getTextContent().then((textContent) => {
|
|
@@ -229,9 +278,36 @@ const renderPage = (page, zoom, error) => {
|
|
|
229
278
|
el.style.fontSize = el.style.fontSize.replace(/px/g, 'pt');
|
|
230
279
|
}
|
|
231
280
|
});
|
|
232
|
-
pageElement.
|
|
281
|
+
pageElement.prepend(textLayer); // Use prepend to ensure the element is always inserted before the annotation layer.
|
|
233
282
|
}).catch(error);
|
|
234
283
|
});
|
|
284
|
+
if (enableAnnotations) {
|
|
285
|
+
page.getAnnotations({ intent: 'display' }).then((annotations) => {
|
|
286
|
+
const annotationLayer = createElement('div', 'k-annotations-layer', {
|
|
287
|
+
position: 'absolute',
|
|
288
|
+
top: '0',
|
|
289
|
+
left: '0',
|
|
290
|
+
overflow: 'hidden',
|
|
291
|
+
height: styles.height,
|
|
292
|
+
width: styles.width,
|
|
293
|
+
pointerEvents: 'none'
|
|
294
|
+
});
|
|
295
|
+
pageElement.appendChild(annotationLayer);
|
|
296
|
+
for (const annotation of annotations) {
|
|
297
|
+
switch (annotation.subtype) {
|
|
298
|
+
case 'Link':
|
|
299
|
+
new LinkAnnotation(annotationLayer, viewport, annotation, pdfDoc, zoom, rootElement);
|
|
300
|
+
break;
|
|
301
|
+
default:
|
|
302
|
+
null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
.then(() => {
|
|
309
|
+
page._pageInfo.rendered = true;
|
|
310
|
+
page._pageInfo.renderInProgress = false;
|
|
235
311
|
})
|
|
236
312
|
.catch(error);
|
|
237
313
|
return pageElement;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PageViewport, PDFDocumentProxy } from 'pdfjs-dist/legacy/build/pdf.mjs';
|
|
2
|
+
declare class Annotation {
|
|
3
|
+
rootElement: HTMLElement;
|
|
4
|
+
container: HTMLElement;
|
|
5
|
+
viewport: PageViewport;
|
|
6
|
+
zoom: number;
|
|
7
|
+
annotation: any;
|
|
8
|
+
pdfDoc: PDFDocumentProxy;
|
|
9
|
+
constructor(container: any, viewport: any, annotation: any, pdfDoc: any, zoom: any, rootElement: any);
|
|
10
|
+
destroy(): any;
|
|
11
|
+
}
|
|
12
|
+
export declare class LinkAnnotation extends Annotation {
|
|
13
|
+
linkElement: HTMLAnchorElement;
|
|
14
|
+
constructor(container: any, viewport: any, annotation: any, pdfDoc: any, zoom: any, rootElement: any);
|
|
15
|
+
onLinkClick: (e: any) => void;
|
|
16
|
+
destroy(): any;
|
|
17
|
+
bindEvents(): any;
|
|
18
|
+
unbindEvents(): any;
|
|
19
|
+
navigateToDestination(destination: any): void;
|
|
20
|
+
goToPage(pageNumber: any): void;
|
|
21
|
+
renderAnnotation(): void;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LinkAnnotation = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
class Annotation {
|
|
6
|
+
constructor(container, viewport, annotation, pdfDoc, zoom, rootElement) {
|
|
7
|
+
this.container = container;
|
|
8
|
+
this.viewport = viewport;
|
|
9
|
+
this.zoom = zoom;
|
|
10
|
+
this.annotation = annotation;
|
|
11
|
+
this.pdfDoc = pdfDoc;
|
|
12
|
+
this.rootElement = rootElement;
|
|
13
|
+
}
|
|
14
|
+
destroy() {
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
class LinkAnnotation extends Annotation {
|
|
18
|
+
constructor(container, viewport, annotation, pdfDoc, zoom, rootElement) {
|
|
19
|
+
super(container, viewport, annotation, pdfDoc, zoom, rootElement);
|
|
20
|
+
this.onLinkClick = (e) => {
|
|
21
|
+
const destination = e.target.getAttribute('href');
|
|
22
|
+
if (destination && destination.indexOf('#') === 0) {
|
|
23
|
+
this.navigateToDestination(destination);
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
this.linkElement = null;
|
|
28
|
+
this.renderAnnotation();
|
|
29
|
+
this.bindEvents();
|
|
30
|
+
}
|
|
31
|
+
destroy() {
|
|
32
|
+
this.unbindEvents();
|
|
33
|
+
}
|
|
34
|
+
bindEvents() {
|
|
35
|
+
this.linkElement.addEventListener('click', this.onLinkClick);
|
|
36
|
+
}
|
|
37
|
+
unbindEvents() {
|
|
38
|
+
this.linkElement.removeEventListener('click', this.onLinkClick);
|
|
39
|
+
}
|
|
40
|
+
navigateToDestination(destination) {
|
|
41
|
+
const dest = destination.split('#')[1];
|
|
42
|
+
this.pdfDoc.getDestination(dest).then(r => {
|
|
43
|
+
this.pdfDoc.getPageIndex(r[0]).then(i => this.goToPage(i));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
goToPage(pageNumber) {
|
|
47
|
+
(0, utils_1.scrollToPage)(this.rootElement, pageNumber);
|
|
48
|
+
}
|
|
49
|
+
renderAnnotation() {
|
|
50
|
+
const annotation = this.annotation, viewport = this.viewport, rect = annotation.rect, boundingRect = [
|
|
51
|
+
[rect[0], rect[1]],
|
|
52
|
+
[rect[2], rect[3]]
|
|
53
|
+
], rawHeight = viewport.rawDims.pageHeight;
|
|
54
|
+
const left = Math.min(boundingRect[0][0], boundingRect[1][0]) * this.zoom, top = (rawHeight - Math.max(boundingRect[0][1], boundingRect[1][1])) * this.zoom, width = (boundingRect[1][0] - boundingRect[0][0]) * this.zoom, height = (boundingRect[1][1] - boundingRect[0][1]) * this.zoom;
|
|
55
|
+
const url = annotation.url || (annotation.dest && `#${encodeURI(annotation.dest)}`);
|
|
56
|
+
const annotationElement = (0, utils_1.createElement)('span', '', {
|
|
57
|
+
position: 'absolute',
|
|
58
|
+
left: left + 'pt',
|
|
59
|
+
top: top + 'pt'
|
|
60
|
+
});
|
|
61
|
+
const linkElement = this.linkElement = (0, utils_1.createElement)('a', '', {
|
|
62
|
+
width: width + 'pt',
|
|
63
|
+
height: height + 'pt',
|
|
64
|
+
display: 'inline-block',
|
|
65
|
+
pointerEvents: 'auto'
|
|
66
|
+
});
|
|
67
|
+
linkElement.setAttribute('href', url);
|
|
68
|
+
annotationElement.append(linkElement);
|
|
69
|
+
this.container.append(annotationElement);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.LinkAnnotation = LinkAnnotation;
|
package/dist/npm/scroller.d.ts
CHANGED
package/dist/npm/scroller.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Scroller = void 0;
|
|
4
4
|
const kendo_draggable_1 = require("@progress/kendo-draggable");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
5
6
|
const throttle = function (func, wait, options = {}) {
|
|
6
7
|
let timeout, context, args, result;
|
|
7
8
|
let previous = 0;
|
|
@@ -84,6 +85,21 @@ class Scroller {
|
|
|
84
85
|
this.state.trackNextElementScroll = true;
|
|
85
86
|
}
|
|
86
87
|
};
|
|
88
|
+
this.onDemandScroll = () => {
|
|
89
|
+
const pages = this.options.pages, currentPageIndex = (0, utils_1.currentPage)(this.element.parentElement), page = pages[currentPageIndex], nextPage = pages[currentPageIndex + 1], previousPage = pages[currentPageIndex - 1], pageInfo = page === null || page === void 0 ? void 0 : page._pageInfo, nextPageInfo = nextPage === null || nextPage === void 0 ? void 0 : nextPage._pageInfo, previousPageInfo = previousPage === null || previousPage === void 0 ? void 0 : previousPage._pageInfo, error = (e) => {
|
|
90
|
+
throw new Error(e);
|
|
91
|
+
};
|
|
92
|
+
// Render the current and surrounding pages if they have not been rendered already.
|
|
93
|
+
if (page && !pageInfo.rendered && !pageInfo.renderInProgress) {
|
|
94
|
+
(0, utils_1.renderPage)(page, pageInfo.emptyPage, error);
|
|
95
|
+
}
|
|
96
|
+
if (nextPage && !nextPageInfo.rendered && !nextPageInfo.renderInProgress) {
|
|
97
|
+
(0, utils_1.renderPage)(nextPage, nextPageInfo.emptyPage, error);
|
|
98
|
+
}
|
|
99
|
+
if (previousPage && !previousPageInfo.rendered && !previousPageInfo.renderInProgress) {
|
|
100
|
+
(0, utils_1.renderPage)(previousPage, previousPageInfo.emptyPage, error);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
87
103
|
this.onDragStart = (e) => {
|
|
88
104
|
this.state.dragStarted = false;
|
|
89
105
|
if (!this.shouldTrackPanEvents()) {
|
|
@@ -178,6 +194,9 @@ class Scroller {
|
|
|
178
194
|
this.throttledOnElementScroll = this.onElementScroll;
|
|
179
195
|
}
|
|
180
196
|
this.element.addEventListener(SCROLL, this.throttledOnElementScroll);
|
|
197
|
+
if (this.options.loadOnDemand) {
|
|
198
|
+
this.element.addEventListener(SCROLL, this.onDemandScroll);
|
|
199
|
+
}
|
|
181
200
|
}
|
|
182
201
|
unbindEvents() {
|
|
183
202
|
this.unbindElementScroll();
|
|
@@ -192,6 +211,9 @@ class Scroller {
|
|
|
192
211
|
this.throttledOnElementScroll.cancel();
|
|
193
212
|
this.throttledOnElementScroll = null;
|
|
194
213
|
}
|
|
214
|
+
if (this.options.loadOnDemand) {
|
|
215
|
+
this.element.removeEventListener(SCROLL, this.onDemandScroll);
|
|
216
|
+
}
|
|
195
217
|
this.element.removeEventListener(SCROLL, this.throttledOnElementScroll);
|
|
196
218
|
}
|
|
197
219
|
setState(newState) {
|
package/dist/npm/utils.d.ts
CHANGED
|
@@ -21,14 +21,18 @@ export interface PDFReadParameters {
|
|
|
21
21
|
data?: string;
|
|
22
22
|
arrayBuffer?: ArrayBuffer;
|
|
23
23
|
typedArray?: TypedArray;
|
|
24
|
+
loadOnDemand?: boolean;
|
|
25
|
+
loadOnDemandPageSize?: number;
|
|
24
26
|
error: ErrorFn;
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* @hidden
|
|
28
30
|
*/
|
|
29
31
|
export interface PDFReadOptions extends PDFReadParameters {
|
|
32
|
+
rootElement?: HTMLElement | null;
|
|
30
33
|
dom: HTMLDivElement;
|
|
31
34
|
zoom: number;
|
|
35
|
+
enableAnnotations: boolean;
|
|
32
36
|
done: DoneFn;
|
|
33
37
|
}
|
|
34
38
|
/**
|
|
@@ -38,8 +42,11 @@ export interface PDFReloadParameters {
|
|
|
38
42
|
pdfDoc: PDFDocumentProxy;
|
|
39
43
|
zoom: number;
|
|
40
44
|
dom: HTMLElement;
|
|
45
|
+
rootElement?: HTMLElement | null;
|
|
46
|
+
loadOnDemand?: boolean;
|
|
41
47
|
done: (pdfPages: PDFPageProxy[]) => void;
|
|
42
48
|
error: ErrorFn;
|
|
49
|
+
enableAnnotations: boolean;
|
|
43
50
|
}
|
|
44
51
|
/**
|
|
45
52
|
* @hidden
|
|
@@ -68,6 +75,10 @@ export declare const reloadDocument: (params: PDFReloadParameters) => void;
|
|
|
68
75
|
* @hidden
|
|
69
76
|
*/
|
|
70
77
|
export declare const print: (pages: PDFPageProxy[], done: () => void, error: ErrorFn) => void;
|
|
78
|
+
export declare const createElement: <T>(name: string, className: string, styles: {
|
|
79
|
+
[key: string]: string;
|
|
80
|
+
}) => T;
|
|
81
|
+
export declare const renderPage: (page: PDFPageProxy, emptyPage: any, error: ErrorFn) => any;
|
|
71
82
|
/**
|
|
72
83
|
* @hidden
|
|
73
84
|
*/
|
package/dist/npm/utils.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.currentPage = exports.scrollToPage = exports.calculateZoomLevel = exports.goToPreviousSearchMatch = exports.goToNextSearchMatch = exports.print = exports.reloadDocument = exports.loadPDF = exports.download = exports.removeChildren = exports.DEFAULT_ZOOM_LEVEL = void 0;
|
|
3
|
+
exports.currentPage = exports.scrollToPage = exports.calculateZoomLevel = exports.goToPreviousSearchMatch = exports.goToNextSearchMatch = exports.renderPage = exports.createElement = exports.print = exports.reloadDocument = exports.loadPDF = exports.download = exports.removeChildren = exports.DEFAULT_ZOOM_LEVEL = void 0;
|
|
4
4
|
const kendo_file_saver_1 = require("@progress/kendo-file-saver");
|
|
5
5
|
const kendo_common_1 = require("@progress/kendo-common");
|
|
6
6
|
const pdf_mjs_1 = require("pdfjs-dist/legacy/build/pdf.mjs");
|
|
7
|
+
const annotations_1 = require("./annotations");
|
|
7
8
|
const MAX_CANVAS_WIDTH_HEIGHT_CHROME = 65535;
|
|
8
9
|
const MAX_CANVAS_AREA_CHROME_SAFARI = 268435456;
|
|
9
10
|
const MAX_CANVAS_WIDTH_HEIGHT_FIREFOX = 32767;
|
|
@@ -88,7 +89,8 @@ exports.download = download;
|
|
|
88
89
|
*/
|
|
89
90
|
const loadPDF = (options) => {
|
|
90
91
|
const params = getDocumentParameters(options);
|
|
91
|
-
const { dom, zoom, done, error } = options;
|
|
92
|
+
const { dom, zoom, done, error, rootElement, enableAnnotations } = options;
|
|
93
|
+
const loadOnDemandPageSize = options.loadOnDemandPageSize || 2;
|
|
92
94
|
(0, pdf_mjs_1.getDocument)(params)
|
|
93
95
|
.promise.then((pdfDoc) => {
|
|
94
96
|
const pages = [];
|
|
@@ -99,7 +101,18 @@ const loadPDF = (options) => {
|
|
|
99
101
|
}).then(({ pages, pdfDoc }) => {
|
|
100
102
|
Promise.all(pages)
|
|
101
103
|
.then((all) => all.map((page, i) => {
|
|
102
|
-
|
|
104
|
+
const emptyPage = createEmptyPage(page, zoom, pdfDoc, enableAnnotations, rootElement);
|
|
105
|
+
appendPage(dom, emptyPage.pageElement, i);
|
|
106
|
+
if (options.loadOnDemand) {
|
|
107
|
+
// If LOD is enabled, render the first two(default) or X pages initially.
|
|
108
|
+
if (i < loadOnDemandPageSize) {
|
|
109
|
+
(0, exports.renderPage)(page, emptyPage, error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
(0, exports.renderPage)(page, emptyPage, error);
|
|
114
|
+
}
|
|
115
|
+
page._pageInfo.emptyPage = emptyPage;
|
|
103
116
|
return page;
|
|
104
117
|
})).then((pdfPages) => {
|
|
105
118
|
// required by new PDFJS version
|
|
@@ -128,17 +141,39 @@ exports.loadPDF = loadPDF;
|
|
|
128
141
|
* @hidden
|
|
129
142
|
*/
|
|
130
143
|
const reloadDocument = (params) => {
|
|
131
|
-
const { pdfDoc, zoom, dom, done, error } = params;
|
|
144
|
+
const { pdfDoc, zoom, dom, done, error, loadOnDemand, rootElement, enableAnnotations } = params;
|
|
132
145
|
const pages = [];
|
|
146
|
+
let currentPageIndex = 0;
|
|
147
|
+
// Save the index of the current page in view before we reload the document.
|
|
148
|
+
if (loadOnDemand && rootElement) {
|
|
149
|
+
currentPageIndex = (0, exports.currentPage)(rootElement);
|
|
150
|
+
}
|
|
133
151
|
for (let i = 1; i <= pdfDoc.numPages; i++) {
|
|
134
152
|
pages.push(pdfDoc.getPage(i));
|
|
135
153
|
}
|
|
136
154
|
Promise.all(pages)
|
|
137
155
|
.then((all) => all.map((page, i) => {
|
|
138
|
-
|
|
156
|
+
// Set 'rendered' back to false so that the pages can be re-rendered when scrolling.
|
|
157
|
+
page._pageInfo.rendered = false;
|
|
158
|
+
const emptyPage = createEmptyPage(page, zoom, pdfDoc, enableAnnotations, rootElement);
|
|
159
|
+
appendPage(dom, emptyPage.pageElement, i);
|
|
160
|
+
// If on demand is not enabled, proceed as usual.
|
|
161
|
+
if (!loadOnDemand) {
|
|
162
|
+
(0, exports.renderPage)(page, emptyPage, error);
|
|
163
|
+
}
|
|
164
|
+
page._pageInfo.emptyPage = emptyPage;
|
|
139
165
|
return page;
|
|
140
166
|
}))
|
|
141
|
-
.then(
|
|
167
|
+
.then((pdfPages) => {
|
|
168
|
+
/* If on demand is enabled, render the page that was previously in view.
|
|
169
|
+
Then scroll to that page. */
|
|
170
|
+
if (loadOnDemand) {
|
|
171
|
+
const page = pdfPages[currentPageIndex];
|
|
172
|
+
(0, exports.renderPage)(page, page._pageInfo.emptyPage, error);
|
|
173
|
+
(0, exports.scrollToPage)(rootElement, currentPageIndex);
|
|
174
|
+
}
|
|
175
|
+
done(pdfPages);
|
|
176
|
+
})
|
|
142
177
|
.catch(error);
|
|
143
178
|
};
|
|
144
179
|
exports.reloadDocument = reloadDocument;
|
|
@@ -185,6 +220,19 @@ const openPrintDialog = (dom, width, height, done, onError) => {
|
|
|
185
220
|
printDialog.addEventListener('afterprint', onAfterPrint);
|
|
186
221
|
}
|
|
187
222
|
};
|
|
223
|
+
const createEmptyPage = (page, zoom, pdfDoc, enableAnnotations, rootElement) => {
|
|
224
|
+
const { canvasContext, viewport, pageElement, styles } = createCanvas(page, zoom, 'k-page');
|
|
225
|
+
return {
|
|
226
|
+
canvasContext,
|
|
227
|
+
viewport,
|
|
228
|
+
pageElement,
|
|
229
|
+
styles,
|
|
230
|
+
zoom,
|
|
231
|
+
pdfDoc,
|
|
232
|
+
enableAnnotations,
|
|
233
|
+
rootElement
|
|
234
|
+
};
|
|
235
|
+
};
|
|
188
236
|
const renderCanvas = (page, done, error) => {
|
|
189
237
|
const { canvasContext, viewport, scaleNum, canvas, pageElement } = createCanvas(page);
|
|
190
238
|
page.render({ canvasContext, viewport })
|
|
@@ -208,18 +256,20 @@ const createElement = function (name, className, styles) {
|
|
|
208
256
|
Object.keys(styles).forEach((key) => (element.style[key] = styles[key]));
|
|
209
257
|
return element;
|
|
210
258
|
};
|
|
259
|
+
exports.createElement = createElement;
|
|
211
260
|
const transforms = {
|
|
212
261
|
'0': '',
|
|
213
262
|
'90': 'rotate(90deg) translateY(-100%)',
|
|
214
263
|
'180': 'rotate(180deg) translate(-100%, -100%)',
|
|
215
264
|
'270': 'rotate(270deg) translateX(-100%)'
|
|
216
265
|
};
|
|
217
|
-
const renderPage = (page,
|
|
218
|
-
const { canvasContext, viewport, pageElement, styles
|
|
266
|
+
const renderPage = (page, emptyPage, error) => {
|
|
267
|
+
const { canvasContext, viewport, pageElement, styles, zoom, pdfDoc, enableAnnotations, rootElement } = emptyPage;
|
|
268
|
+
page._pageInfo.renderInProgress = true;
|
|
219
269
|
page.render({ canvasContext, viewport })
|
|
220
270
|
.promise.then(() => {
|
|
221
271
|
page.getTextContent().then((textContent) => {
|
|
222
|
-
const textLayer = createElement('div', 'k-text-layer', styles);
|
|
272
|
+
const textLayer = (0, exports.createElement)('div', 'k-text-layer', styles);
|
|
223
273
|
new pdf_mjs_1.TextLayer({
|
|
224
274
|
textContentSource: textContent,
|
|
225
275
|
container: textLayer,
|
|
@@ -237,13 +287,41 @@ const renderPage = (page, zoom, error) => {
|
|
|
237
287
|
el.style.fontSize = el.style.fontSize.replace(/px/g, 'pt');
|
|
238
288
|
}
|
|
239
289
|
});
|
|
240
|
-
pageElement.
|
|
290
|
+
pageElement.prepend(textLayer); // Use prepend to ensure the element is always inserted before the annotation layer.
|
|
241
291
|
}).catch(error);
|
|
242
292
|
});
|
|
293
|
+
if (enableAnnotations) {
|
|
294
|
+
page.getAnnotations({ intent: 'display' }).then((annotations) => {
|
|
295
|
+
const annotationLayer = (0, exports.createElement)('div', 'k-annotations-layer', {
|
|
296
|
+
position: 'absolute',
|
|
297
|
+
top: '0',
|
|
298
|
+
left: '0',
|
|
299
|
+
overflow: 'hidden',
|
|
300
|
+
height: styles.height,
|
|
301
|
+
width: styles.width,
|
|
302
|
+
pointerEvents: 'none'
|
|
303
|
+
});
|
|
304
|
+
pageElement.appendChild(annotationLayer);
|
|
305
|
+
for (const annotation of annotations) {
|
|
306
|
+
switch (annotation.subtype) {
|
|
307
|
+
case 'Link':
|
|
308
|
+
new annotations_1.LinkAnnotation(annotationLayer, viewport, annotation, pdfDoc, zoom, rootElement);
|
|
309
|
+
break;
|
|
310
|
+
default:
|
|
311
|
+
null;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
})
|
|
317
|
+
.then(() => {
|
|
318
|
+
page._pageInfo.rendered = true;
|
|
319
|
+
page._pageInfo.renderInProgress = false;
|
|
243
320
|
})
|
|
244
321
|
.catch(error);
|
|
245
322
|
return pageElement;
|
|
246
323
|
};
|
|
324
|
+
exports.renderPage = renderPage;
|
|
247
325
|
const searchMatchScrollLeftOffset = 0;
|
|
248
326
|
const searchMatchScrollTopOffset = -64;
|
|
249
327
|
const scrollToSearchMatch = (matchElement, ref) => {
|
|
@@ -400,8 +478,8 @@ const createCanvas = (page, zoom = 1, cssClass = '') => {
|
|
|
400
478
|
width: Math.floor(viewport.width / scaleNum) * zoom + 'pt',
|
|
401
479
|
height: Math.floor(viewport.height / scaleNum) * zoom + 'pt'
|
|
402
480
|
};
|
|
403
|
-
const pageElement = createElement('div', cssClass, styles);
|
|
404
|
-
const canvas = createElement('canvas', '', {
|
|
481
|
+
const pageElement = (0, exports.createElement)('div', cssClass, styles);
|
|
482
|
+
const canvas = (0, exports.createElement)('canvas', '', {
|
|
405
483
|
width: '100%',
|
|
406
484
|
height: '100%'
|
|
407
485
|
});
|