@progress/kendo-pdfviewer-common 0.1.0
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/LICENSE.md +7 -0
- package/NOTICE.txt +614 -0
- package/README.md +9 -0
- package/dist/es/main.js +3 -0
- package/dist/es/scroller.js +229 -0
- package/dist/es/search.js +256 -0
- package/dist/es/utils.js +315 -0
- package/dist/npm/main.d.ts +5 -0
- package/dist/npm/main.js +6 -0
- package/dist/npm/scroller.d.ts +32 -0
- package/dist/npm/scroller.js +232 -0
- package/dist/npm/search.d.ts +37 -0
- package/dist/npm/search.js +259 -0
- package/dist/npm/utils.d.ts +96 -0
- package/dist/npm/utils.js +317 -0
- package/package.json +98 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const unwrapElement = (element) => {
|
|
4
|
+
const parentElement = element.parentElement;
|
|
5
|
+
if (!element || !parentElement) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
parentElement.replaceWith(...Array.from(parentElement.childNodes));
|
|
9
|
+
};
|
|
10
|
+
const unwrapElements = (elements) => {
|
|
11
|
+
if (!elements || !elements.length || elements.length <= 0) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
for (let i = 0; i < elements.length; i++) {
|
|
15
|
+
unwrapElement(elements[i]);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const wrapElement = (element, wrapper) => {
|
|
19
|
+
if (element.parentNode) {
|
|
20
|
+
element.parentNode.insertBefore(wrapper, element);
|
|
21
|
+
wrapper.appendChild(element);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const wrapInnerElement = (element, wrapper) => {
|
|
25
|
+
if (!element || !element.parentNode || !wrapper) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
element.appendChild(wrapper);
|
|
29
|
+
while (element.firstChild && element.firstChild !== wrapper) {
|
|
30
|
+
wrapper.appendChild(element.firstChild);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const addClass = (className, element) => {
|
|
34
|
+
element.classList.add(className);
|
|
35
|
+
};
|
|
36
|
+
const removeClass = (className, element) => {
|
|
37
|
+
element.classList.remove(className);
|
|
38
|
+
};
|
|
39
|
+
const toClassSelector = (className) => `.${className}`;
|
|
40
|
+
const CHAR_INDEX_DATA_ATTR = 'data-char-index';
|
|
41
|
+
const MATCH_INDEX_DATA_ATTR = 'data-match-index';
|
|
42
|
+
/**
|
|
43
|
+
* @hidden
|
|
44
|
+
*/
|
|
45
|
+
class SearchService {
|
|
46
|
+
constructor(options) {
|
|
47
|
+
this.options = {
|
|
48
|
+
highlightClass: 'k-search-highlight',
|
|
49
|
+
highlightMarkClass: 'k-search-highlight-mark',
|
|
50
|
+
charClass: 'k-text-char',
|
|
51
|
+
textContainers: []
|
|
52
|
+
};
|
|
53
|
+
this.extendOptions(options);
|
|
54
|
+
this.resetState();
|
|
55
|
+
}
|
|
56
|
+
destroy() {
|
|
57
|
+
this.clearSearch();
|
|
58
|
+
}
|
|
59
|
+
extendOptions(options) {
|
|
60
|
+
this.options = Object.assign({}, this.options, options);
|
|
61
|
+
}
|
|
62
|
+
setState(newState) {
|
|
63
|
+
this.state = Object.assign({}, this.state || {}, newState);
|
|
64
|
+
}
|
|
65
|
+
resetState() {
|
|
66
|
+
this.setState({
|
|
67
|
+
text: '',
|
|
68
|
+
textNodes: [],
|
|
69
|
+
charIndex: 0,
|
|
70
|
+
activeMatchIndex: 0,
|
|
71
|
+
matches: []
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
search({ text, matchCase }) {
|
|
75
|
+
let searchRegex = new RegExp(text, matchCase ? 'g' : 'ig');
|
|
76
|
+
let match;
|
|
77
|
+
if (this.shouldTransformText()) {
|
|
78
|
+
this.transformTextForSearch();
|
|
79
|
+
}
|
|
80
|
+
this.state.matches = [];
|
|
81
|
+
this.state.activeMatchIndex = 0;
|
|
82
|
+
this.removeIndicators();
|
|
83
|
+
if (text === '') {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
match = searchRegex.exec(this.state.text);
|
|
87
|
+
while (match) {
|
|
88
|
+
this.state.matches.push({
|
|
89
|
+
startOffset: match.index,
|
|
90
|
+
endOffset: match.index + match[0].length
|
|
91
|
+
});
|
|
92
|
+
match = searchRegex.exec(this.state.text);
|
|
93
|
+
}
|
|
94
|
+
this.highlightAllMatches();
|
|
95
|
+
this.addActiveMatchMark();
|
|
96
|
+
return this.state.matches;
|
|
97
|
+
}
|
|
98
|
+
clearSearch() {
|
|
99
|
+
this.removeIndicators();
|
|
100
|
+
this.restoreOriginalText();
|
|
101
|
+
}
|
|
102
|
+
restoreOriginalText() {
|
|
103
|
+
this.forEachTextContainer((textContainer) => {
|
|
104
|
+
const nodes = Array.from(textContainer.querySelectorAll('span:not(.' + this.options.charClass + ')'));
|
|
105
|
+
nodes.forEach((node) => {
|
|
106
|
+
node.innerHTML = node.textContent;
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
shouldTransformText() {
|
|
111
|
+
return !this.state.text;
|
|
112
|
+
}
|
|
113
|
+
transformTextForSearch() {
|
|
114
|
+
this.state.textNodes = [];
|
|
115
|
+
this.state.charIndex = 0;
|
|
116
|
+
this.state.text = '';
|
|
117
|
+
this.forEachTextContainer((textContainer) => {
|
|
118
|
+
this.extractTextNodes(textContainer);
|
|
119
|
+
});
|
|
120
|
+
this.transformTextNodesForSearch(this.state.textNodes);
|
|
121
|
+
}
|
|
122
|
+
extractTextNodes(node) {
|
|
123
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
124
|
+
this.state.textNodes.push(node);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
for (let i = 0; i < node.childNodes.length; i++) {
|
|
128
|
+
this.extractTextNodes(node.childNodes[i]);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
transformTextNodesForSearch(textNodes) {
|
|
133
|
+
for (let i = 0; i < textNodes.length; i++) {
|
|
134
|
+
this.transformTextNodeForSearch(textNodes[i]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
transformTextNodeForSearch(node) {
|
|
138
|
+
const text = node.textContent;
|
|
139
|
+
if (text.length <= 0) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
this.state.text = this.state.text + text;
|
|
143
|
+
const span = document.createElement('span');
|
|
144
|
+
wrapElement(node, span);
|
|
145
|
+
const splittedHtml = this.splitTextByChars(text);
|
|
146
|
+
span.innerHTML = splittedHtml;
|
|
147
|
+
unwrapElement(span.childNodes[0]);
|
|
148
|
+
}
|
|
149
|
+
splitTextByChars(text) {
|
|
150
|
+
let splittedTextHtml = '';
|
|
151
|
+
for (let i = 0; i < text.length; i++) {
|
|
152
|
+
splittedTextHtml += `<span class='${this.options.charClass}' ${CHAR_INDEX_DATA_ATTR}=${this.state.charIndex}>${text[i]}</span>`;
|
|
153
|
+
this.state.charIndex++;
|
|
154
|
+
}
|
|
155
|
+
return splittedTextHtml;
|
|
156
|
+
}
|
|
157
|
+
forEachTextContainer(callback) {
|
|
158
|
+
for (let i = 0; i < this.options.textContainers.length; i++) {
|
|
159
|
+
const textContainer = this.options.textContainers[i];
|
|
160
|
+
callback(textContainer, i);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
highlightAllMatches() {
|
|
164
|
+
this.state.matches.forEach((match, matchIndex) => {
|
|
165
|
+
this.addMatchHighlight(match.startOffset, match.endOffset, matchIndex);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
addMatchHighlight(matchStartOffset, matchEndOffset, matchIndex) {
|
|
169
|
+
for (let i = matchStartOffset; i < matchEndOffset; i++) {
|
|
170
|
+
this.forEachTextContainer((textContainer) => {
|
|
171
|
+
const highlights = Array.from(textContainer.querySelectorAll(toClassSelector(`${this.options.charClass}[${CHAR_INDEX_DATA_ATTR}='${i}']`)));
|
|
172
|
+
highlights.forEach((highlight) => {
|
|
173
|
+
addClass(this.options.highlightClass, highlight);
|
|
174
|
+
highlight.setAttribute(MATCH_INDEX_DATA_ATTR, matchIndex);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
removeMatchHighlights() {
|
|
180
|
+
this.forEachTextContainer((textContainer) => {
|
|
181
|
+
const highlights = Array.from(textContainer.querySelectorAll(toClassSelector(this.options.highlightClass)));
|
|
182
|
+
highlights.forEach((highlight) => {
|
|
183
|
+
removeClass(this.options.highlightClass, highlight);
|
|
184
|
+
highlight.removeAttribute(MATCH_INDEX_DATA_ATTR);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
addActiveMatchMark() {
|
|
189
|
+
if (!this.state.activeMatchIndex && this.state.activeMatchIndex !== 0) {
|
|
190
|
+
this.state.activeMatchIndex = 0;
|
|
191
|
+
}
|
|
192
|
+
else if (this.state.activeMatchIndex > this.state.matches.length) {
|
|
193
|
+
this.state.activeMatchIndex = this.state.matches.length;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
this.removeActiveMatchMark();
|
|
197
|
+
}
|
|
198
|
+
const mark = document.createElement('span');
|
|
199
|
+
mark.classList.add(this.options.highlightMarkClass);
|
|
200
|
+
this.forEachTextContainer((textContainer) => {
|
|
201
|
+
const matches = Array.from(textContainer.querySelectorAll(toClassSelector(this.options.charClass +
|
|
202
|
+
'[' +
|
|
203
|
+
MATCH_INDEX_DATA_ATTR +
|
|
204
|
+
"='" +
|
|
205
|
+
this.state.activeMatchIndex +
|
|
206
|
+
"']")));
|
|
207
|
+
matches.forEach((match) => {
|
|
208
|
+
wrapInnerElement(match, mark.cloneNode(true));
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
removeActiveMatchMark() {
|
|
213
|
+
this.forEachTextContainer((textContainer) => {
|
|
214
|
+
const marks = Array.from(textContainer.querySelectorAll(toClassSelector(this.options.highlightMarkClass)));
|
|
215
|
+
const childNodes = marks.flatMap((x) => Array.from(x.childNodes));
|
|
216
|
+
unwrapElements(childNodes);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
removeIndicators() {
|
|
220
|
+
this.removeActiveMatchMark();
|
|
221
|
+
this.removeMatchHighlights();
|
|
222
|
+
}
|
|
223
|
+
markNextMatch() {
|
|
224
|
+
this.markNextMatchIndex();
|
|
225
|
+
this.addActiveMatchMark();
|
|
226
|
+
}
|
|
227
|
+
markPreviousMatch() {
|
|
228
|
+
this.markPreviousMatchIndex();
|
|
229
|
+
this.addActiveMatchMark();
|
|
230
|
+
}
|
|
231
|
+
markNextMatchIndex() {
|
|
232
|
+
this.moveActiveMatchIndex(1);
|
|
233
|
+
}
|
|
234
|
+
markPreviousMatchIndex() {
|
|
235
|
+
this.moveActiveMatchIndex(-1);
|
|
236
|
+
}
|
|
237
|
+
moveActiveMatchIndex(delta) {
|
|
238
|
+
this.state.activeMatchIndex += delta;
|
|
239
|
+
if (this.state.activeMatchIndex < 0) {
|
|
240
|
+
this.state.activeMatchIndex = Math.max(this.state.matches.length - 1, 0);
|
|
241
|
+
}
|
|
242
|
+
else if (this.state.activeMatchIndex >
|
|
243
|
+
this.state.matches.length - 1) {
|
|
244
|
+
this.state.activeMatchIndex = 0;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
getActiveMatchElement() {
|
|
248
|
+
let markedMatch;
|
|
249
|
+
this.forEachTextContainer((textContainer) => {
|
|
250
|
+
const mark = textContainer.querySelector(toClassSelector(this.options.highlightMarkClass));
|
|
251
|
+
if (mark) {
|
|
252
|
+
markedMatch = mark;
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
return markedMatch;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
exports.SearchService = SearchService;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { SaveOptions } from '@progress/kendo-file-saver';
|
|
2
|
+
import { PDFPageProxy, PDFDocumentProxy } from 'pdfjs-dist';
|
|
3
|
+
import { TypedArray } from 'pdfjs-dist/types/src/display/api';
|
|
4
|
+
/**
|
|
5
|
+
* @hidden
|
|
6
|
+
*/
|
|
7
|
+
export declare type DoneFn = (result: {
|
|
8
|
+
pdfPages: PDFPageProxy[];
|
|
9
|
+
pdfDoc: PDFDocumentProxy;
|
|
10
|
+
zoom: number;
|
|
11
|
+
}) => void;
|
|
12
|
+
/**
|
|
13
|
+
* @hidden
|
|
14
|
+
*/
|
|
15
|
+
export declare type ErrorFn = (e?: any) => void;
|
|
16
|
+
/**
|
|
17
|
+
* @hidden
|
|
18
|
+
*/
|
|
19
|
+
export interface PDFReadParameters {
|
|
20
|
+
url?: string;
|
|
21
|
+
data?: string;
|
|
22
|
+
arrayBuffer?: ArrayBuffer;
|
|
23
|
+
typedArray?: TypedArray;
|
|
24
|
+
error: ErrorFn;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @hidden
|
|
28
|
+
*/
|
|
29
|
+
export interface PDFReadOptions extends PDFReadParameters {
|
|
30
|
+
dom: HTMLDivElement;
|
|
31
|
+
zoom: number;
|
|
32
|
+
done: DoneFn;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @hidden
|
|
36
|
+
*/
|
|
37
|
+
export interface PDFReloadParameters {
|
|
38
|
+
pdfDoc: PDFDocumentProxy;
|
|
39
|
+
zoom: number;
|
|
40
|
+
dom: HTMLElement;
|
|
41
|
+
done: (pdfPages: PDFPageProxy[]) => void;
|
|
42
|
+
error: ErrorFn;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @hidden
|
|
46
|
+
*/
|
|
47
|
+
export declare const DEFAULT_ZOOM_LEVEL = 1.25;
|
|
48
|
+
/**
|
|
49
|
+
* @hidden
|
|
50
|
+
*/
|
|
51
|
+
export declare const removeChildren: (dom: HTMLElement) => void;
|
|
52
|
+
/**
|
|
53
|
+
* @hidden
|
|
54
|
+
*/
|
|
55
|
+
export declare const download: (options: {
|
|
56
|
+
pdf: import("pdfjs-dist/types/src/display/api").PDFDocumentProxy;
|
|
57
|
+
error: ErrorFn;
|
|
58
|
+
}, fileName: string, saveOptions: SaveOptions, onDownload: (blob: Blob, fileName: string, saveOptions: SaveOptions) => boolean) => void;
|
|
59
|
+
/**
|
|
60
|
+
* @hidden
|
|
61
|
+
*/
|
|
62
|
+
export declare const loadPDF: (options: PDFReadOptions) => void;
|
|
63
|
+
/**
|
|
64
|
+
* @hidden
|
|
65
|
+
*/
|
|
66
|
+
export declare const reloadDocument: (params: PDFReloadParameters) => void;
|
|
67
|
+
/**
|
|
68
|
+
* @hidden
|
|
69
|
+
*/
|
|
70
|
+
export declare const print: (pages: import("pdfjs-dist/types/src/display/api").PDFPageProxy[], done: () => void, error: ErrorFn) => void;
|
|
71
|
+
/**
|
|
72
|
+
* @hidden
|
|
73
|
+
*/
|
|
74
|
+
export declare const goToNextSearchMatch: (ref: any) => void;
|
|
75
|
+
/**
|
|
76
|
+
* @hidden
|
|
77
|
+
*/
|
|
78
|
+
export declare const goToPreviousSearchMatch: (ref: any) => void;
|
|
79
|
+
/**
|
|
80
|
+
* @hidden
|
|
81
|
+
*/
|
|
82
|
+
export declare const calculateZoomLevel: (zoomLevel: number, zoomLevelType: string, currentZoom: number, dom: HTMLDivElement) => number;
|
|
83
|
+
/**
|
|
84
|
+
* Scrolls the PDFViewer document to the passed page number.
|
|
85
|
+
*
|
|
86
|
+
* @param rootElement The root HTML element of the PDFViewer component.
|
|
87
|
+
* @param pageNumber The page number.
|
|
88
|
+
*/
|
|
89
|
+
export declare const scrollToPage: (rootElement: HTMLElement, pageNumber: number) => void;
|
|
90
|
+
/**
|
|
91
|
+
* A function which gives you the page number of the document according to the scroll position.
|
|
92
|
+
*
|
|
93
|
+
* @param rootElement The root HTML element of the PDFViewer component.
|
|
94
|
+
* @returns The page number.
|
|
95
|
+
*/
|
|
96
|
+
export declare const currentPage: (rootElement: HTMLElement) => number;
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const kendo_file_saver_1 = require("@progress/kendo-file-saver");
|
|
4
|
+
const pdfjs_dist_1 = require("pdfjs-dist");
|
|
5
|
+
/**
|
|
6
|
+
* @hidden
|
|
7
|
+
*/
|
|
8
|
+
exports.DEFAULT_ZOOM_LEVEL = 1.25;
|
|
9
|
+
const parsePdfFromBase64String = (base64String) => {
|
|
10
|
+
return atob(base64String.replace(/^(data:application\/pdf;base64,)/gi, ''));
|
|
11
|
+
};
|
|
12
|
+
const getDocumentParameters = (options) => {
|
|
13
|
+
let params = {
|
|
14
|
+
verbosity: 0
|
|
15
|
+
};
|
|
16
|
+
if (typeof options.data === 'string') {
|
|
17
|
+
params.data = parsePdfFromBase64String(options.data);
|
|
18
|
+
}
|
|
19
|
+
else if (typeof options.url === 'string') {
|
|
20
|
+
params.url = options.url;
|
|
21
|
+
}
|
|
22
|
+
else if (options.arrayBuffer instanceof ArrayBuffer) {
|
|
23
|
+
params = options.arrayBuffer;
|
|
24
|
+
}
|
|
25
|
+
else if (options.typedArray) {
|
|
26
|
+
params = options.typedArray;
|
|
27
|
+
}
|
|
28
|
+
return params;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* @hidden
|
|
32
|
+
*/
|
|
33
|
+
exports.removeChildren = (dom) => {
|
|
34
|
+
while (dom.firstChild) {
|
|
35
|
+
dom.removeChild(dom.firstChild);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const appendPage = (dom, page, index) => {
|
|
39
|
+
if (index === 0) {
|
|
40
|
+
exports.removeChildren(dom);
|
|
41
|
+
}
|
|
42
|
+
dom.appendChild(page);
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* @hidden
|
|
46
|
+
*/
|
|
47
|
+
exports.download = (options, fileName = 'Document', saveOptions = {}, onDownload) => {
|
|
48
|
+
if (options.pdf) {
|
|
49
|
+
options.pdf
|
|
50
|
+
.getData()
|
|
51
|
+
.then((data) => new Blob([data], { type: 'application/pdf' }))
|
|
52
|
+
.then((blob) => {
|
|
53
|
+
if (!onDownload(blob, fileName, saveOptions)) {
|
|
54
|
+
kendo_file_saver_1.saveAs(blob, fileName, saveOptions);
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
.catch((reason) => {
|
|
58
|
+
options.error.call(undefined, reason);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* @hidden
|
|
64
|
+
*/
|
|
65
|
+
exports.loadPDF = (options) => {
|
|
66
|
+
const params = getDocumentParameters(options);
|
|
67
|
+
const { dom, zoom, done, error } = options;
|
|
68
|
+
pdfjs_dist_1.getDocument(params)
|
|
69
|
+
.promise.then((pdfDoc) => {
|
|
70
|
+
const pages = [];
|
|
71
|
+
for (let i = 1; i <= pdfDoc.numPages; i++) {
|
|
72
|
+
pages.push(pdfDoc.getPage(i));
|
|
73
|
+
}
|
|
74
|
+
return { pages, pdfDoc };
|
|
75
|
+
})
|
|
76
|
+
.then(({ pages, pdfDoc }) => {
|
|
77
|
+
Promise.all(pages)
|
|
78
|
+
.then((all) => all.map((page, i) => {
|
|
79
|
+
appendPage(dom, renderPage(page, zoom, error), i);
|
|
80
|
+
return page;
|
|
81
|
+
}))
|
|
82
|
+
.then((pdfPages) => {
|
|
83
|
+
done({ pdfPages, pdfDoc, zoom });
|
|
84
|
+
})
|
|
85
|
+
.catch((reason) => {
|
|
86
|
+
options.error(reason);
|
|
87
|
+
});
|
|
88
|
+
})
|
|
89
|
+
.catch((reason) => {
|
|
90
|
+
options.error(reason);
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* @hidden
|
|
95
|
+
*/
|
|
96
|
+
exports.reloadDocument = (params) => {
|
|
97
|
+
const { pdfDoc, zoom, dom, done, error } = params;
|
|
98
|
+
const pages = [];
|
|
99
|
+
for (let i = 1; i <= pdfDoc.numPages; i++) {
|
|
100
|
+
pages.push(pdfDoc.getPage(i));
|
|
101
|
+
}
|
|
102
|
+
Promise.all(pages)
|
|
103
|
+
.then((all) => all.map((page, i) => {
|
|
104
|
+
appendPage(dom, renderPage(page, zoom, error), i);
|
|
105
|
+
return page;
|
|
106
|
+
}))
|
|
107
|
+
.then(done)
|
|
108
|
+
.catch(error);
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* @hidden
|
|
112
|
+
*/
|
|
113
|
+
exports.print = (pages, done, error) => {
|
|
114
|
+
const dom = document.createElement('div');
|
|
115
|
+
let dones = pages.map(() => false);
|
|
116
|
+
pages.forEach((page, index) => {
|
|
117
|
+
const viewport = renderCanvas(page, (el) => {
|
|
118
|
+
dom.appendChild(el);
|
|
119
|
+
dones[index] = true;
|
|
120
|
+
if (dones.every(Boolean)) {
|
|
121
|
+
openPrintDialog(dom, viewport.width, viewport.height, done, error);
|
|
122
|
+
}
|
|
123
|
+
}, error);
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
const openPrintDialog = (dom, width, height, done, onError) => {
|
|
127
|
+
const printDialog = window.open('', '', 'innerWidth=' +
|
|
128
|
+
width +
|
|
129
|
+
',innerHeight=' +
|
|
130
|
+
height +
|
|
131
|
+
'location=no,titlebar=no,toolbar=no');
|
|
132
|
+
if (!printDialog || !printDialog.document) {
|
|
133
|
+
onError();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (printDialog) {
|
|
137
|
+
printDialog.document.body.appendChild(dom);
|
|
138
|
+
printDialog.focus();
|
|
139
|
+
setTimeout(() => {
|
|
140
|
+
printDialog.print();
|
|
141
|
+
done();
|
|
142
|
+
});
|
|
143
|
+
const onAfterPrint = () => {
|
|
144
|
+
printDialog.removeEventListener('afterprint', onAfterPrint);
|
|
145
|
+
printDialog.close();
|
|
146
|
+
};
|
|
147
|
+
printDialog.addEventListener('afterprint', onAfterPrint);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const renderCanvas = (page, done, error) => {
|
|
151
|
+
const viewport = page.getViewport({ scale: exports.DEFAULT_ZOOM_LEVEL });
|
|
152
|
+
const styles = {};
|
|
153
|
+
const pageElement = createElement('div', '', styles);
|
|
154
|
+
const canvas = createElement('canvas', '', {
|
|
155
|
+
width: '100%',
|
|
156
|
+
height: '100%'
|
|
157
|
+
});
|
|
158
|
+
const canvasContext = canvas.getContext('2d');
|
|
159
|
+
canvas.height = viewport.height;
|
|
160
|
+
canvas.width = viewport.width;
|
|
161
|
+
pageElement.appendChild(canvas);
|
|
162
|
+
page.render({ canvasContext, viewport })
|
|
163
|
+
.promise.then(() => {
|
|
164
|
+
const printContent = new Image();
|
|
165
|
+
printContent.src = canvas.toDataURL();
|
|
166
|
+
pageElement.removeChild(canvas);
|
|
167
|
+
pageElement.appendChild(printContent);
|
|
168
|
+
printContent.width = canvas.width;
|
|
169
|
+
printContent.height = canvas.height;
|
|
170
|
+
const onload = () => {
|
|
171
|
+
printContent.removeEventListener('load', onload);
|
|
172
|
+
done(pageElement);
|
|
173
|
+
};
|
|
174
|
+
printContent.addEventListener('load', onload);
|
|
175
|
+
})
|
|
176
|
+
.catch(error);
|
|
177
|
+
return viewport;
|
|
178
|
+
};
|
|
179
|
+
const createElement = function (name, className, styles) {
|
|
180
|
+
const element = document.createElement(name);
|
|
181
|
+
if (className) {
|
|
182
|
+
element.className = className;
|
|
183
|
+
}
|
|
184
|
+
Object.keys(styles).forEach((key) => (element.style[key] = styles[key]));
|
|
185
|
+
return element;
|
|
186
|
+
};
|
|
187
|
+
const renderPage = (page, zoom, error) => {
|
|
188
|
+
const viewport = page.getViewport({ scale: zoom });
|
|
189
|
+
const styles = {
|
|
190
|
+
width: viewport.width + 'px',
|
|
191
|
+
height: viewport.height + 'px'
|
|
192
|
+
};
|
|
193
|
+
const pageElement = createElement('div', 'k-page', styles);
|
|
194
|
+
const canvas = createElement('canvas', '', {
|
|
195
|
+
width: '100%',
|
|
196
|
+
height: '100%'
|
|
197
|
+
});
|
|
198
|
+
const canvasContext = canvas.getContext('2d');
|
|
199
|
+
canvas.height = viewport.height;
|
|
200
|
+
canvas.width = viewport.width;
|
|
201
|
+
pageElement.appendChild(canvas);
|
|
202
|
+
page.render({ canvasContext, viewport })
|
|
203
|
+
.promise.then(() => {
|
|
204
|
+
page.getTextContent().then((textContent) => {
|
|
205
|
+
const textLayer = createElement('div', 'k-text-layer', styles);
|
|
206
|
+
pdfjs_dist_1.renderTextLayer({
|
|
207
|
+
textContentSource: textContent,
|
|
208
|
+
container: textLayer,
|
|
209
|
+
viewport: viewport,
|
|
210
|
+
textDivs: []
|
|
211
|
+
})
|
|
212
|
+
.promise.then(() => {
|
|
213
|
+
pageElement.appendChild(textLayer);
|
|
214
|
+
})
|
|
215
|
+
.catch(error);
|
|
216
|
+
});
|
|
217
|
+
})
|
|
218
|
+
.catch(error);
|
|
219
|
+
return pageElement;
|
|
220
|
+
};
|
|
221
|
+
const searchMatchScrollLeftOffset = 0;
|
|
222
|
+
const searchMatchScrollTopOffset = -64;
|
|
223
|
+
const scrollToSearchMatch = (matchElement, ref) => {
|
|
224
|
+
if (!matchElement) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const closestCharElement = matchElement.closest('.k-text-char');
|
|
228
|
+
const closestTextElement = closestCharElement
|
|
229
|
+
? closestCharElement.closest('span[role="presentation"]')
|
|
230
|
+
: null;
|
|
231
|
+
if (!closestTextElement) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const closestPageElement = closestTextElement.closest('.k-page');
|
|
235
|
+
if (!closestPageElement) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const scrollLeft = closestPageElement.offsetLeft +
|
|
239
|
+
-1 * ref.scroller.element.offsetLeft +
|
|
240
|
+
closestTextElement.offsetLeft +
|
|
241
|
+
searchMatchScrollLeftOffset;
|
|
242
|
+
const scrollTop = closestPageElement.offsetTop +
|
|
243
|
+
-1 * ref.scroller.element.offsetTop +
|
|
244
|
+
closestTextElement.offsetTop +
|
|
245
|
+
searchMatchScrollTopOffset;
|
|
246
|
+
ref.scroller.scrollTo(scrollLeft, scrollTop, { trackScrollEvent: false });
|
|
247
|
+
};
|
|
248
|
+
/**
|
|
249
|
+
* @hidden
|
|
250
|
+
*/
|
|
251
|
+
exports.goToNextSearchMatch = (ref) => {
|
|
252
|
+
ref.search.markNextMatch();
|
|
253
|
+
const matchElement = ref.search.getActiveMatchElement();
|
|
254
|
+
scrollToSearchMatch(matchElement, ref);
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* @hidden
|
|
258
|
+
*/
|
|
259
|
+
exports.goToPreviousSearchMatch = (ref) => {
|
|
260
|
+
ref.search.markPreviousMatch();
|
|
261
|
+
const matchElement = ref.search.getActiveMatchElement();
|
|
262
|
+
scrollToSearchMatch(matchElement, ref);
|
|
263
|
+
};
|
|
264
|
+
/**
|
|
265
|
+
* @hidden
|
|
266
|
+
*/
|
|
267
|
+
exports.calculateZoomLevel = (zoomLevel, zoomLevelType, currentZoom, dom) => {
|
|
268
|
+
const documentContainer = dom.closest('.k-pdf-viewer-canvas');
|
|
269
|
+
const page = dom.querySelector('.k-page');
|
|
270
|
+
const pageSize = { width: page.offsetWidth, height: page.offsetHeight };
|
|
271
|
+
let calculatedZoomLevel = zoomLevel;
|
|
272
|
+
if (zoomLevelType === 'ActualWidth') {
|
|
273
|
+
calculatedZoomLevel = 1;
|
|
274
|
+
}
|
|
275
|
+
else if (zoomLevelType === 'FitToWidth') {
|
|
276
|
+
calculatedZoomLevel =
|
|
277
|
+
documentContainer.offsetWidth / (pageSize.width / currentZoom);
|
|
278
|
+
}
|
|
279
|
+
else if (zoomLevelType === 'FitToPage') {
|
|
280
|
+
calculatedZoomLevel =
|
|
281
|
+
documentContainer.offsetHeight / (pageSize.height / currentZoom);
|
|
282
|
+
}
|
|
283
|
+
return calculatedZoomLevel;
|
|
284
|
+
};
|
|
285
|
+
/**
|
|
286
|
+
* Scrolls the PDFViewer document to the passed page number.
|
|
287
|
+
*
|
|
288
|
+
* @param rootElement The root HTML element of the PDFViewer component.
|
|
289
|
+
* @param pageNumber The page number.
|
|
290
|
+
*/
|
|
291
|
+
exports.scrollToPage = (rootElement, pageNumber) => {
|
|
292
|
+
const pages = rootElement.querySelectorAll('.k-page');
|
|
293
|
+
const page = pages[0];
|
|
294
|
+
if (page instanceof HTMLDivElement) {
|
|
295
|
+
const top = (page.offsetHeight + page.offsetTop) *
|
|
296
|
+
Math.max(0, Math.min(pageNumber, pages.length - 1));
|
|
297
|
+
const scrollElement = page.closest('.k-pdf-viewer-canvas');
|
|
298
|
+
if (scrollElement) {
|
|
299
|
+
scrollElement.scrollTo({ top, behavior: 'auto' });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
/**
|
|
304
|
+
* A function which gives you the page number of the document according to the scroll position.
|
|
305
|
+
*
|
|
306
|
+
* @param rootElement The root HTML element of the PDFViewer component.
|
|
307
|
+
* @returns The page number.
|
|
308
|
+
*/
|
|
309
|
+
exports.currentPage = (rootElement) => {
|
|
310
|
+
const scrollElement = rootElement.querySelector('.k-pdf-viewer-canvas');
|
|
311
|
+
const page = rootElement.querySelector('.k-page');
|
|
312
|
+
return scrollElement && page
|
|
313
|
+
? Math.floor(Math.round(scrollElement.scrollTop) /
|
|
314
|
+
(page.offsetHeight + page.offsetTop) +
|
|
315
|
+
0.01)
|
|
316
|
+
: 0;
|
|
317
|
+
};
|