@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
package/dist/es/utils.js
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { saveAs } from '@progress/kendo-file-saver';
|
|
2
|
+
import { getDocument, renderTextLayer } from 'pdfjs-dist';
|
|
3
|
+
/**
|
|
4
|
+
* @hidden
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_ZOOM_LEVEL = 1.25;
|
|
7
|
+
const parsePdfFromBase64String = (base64String) => {
|
|
8
|
+
return atob(base64String.replace(/^(data:application\/pdf;base64,)/gi, ''));
|
|
9
|
+
};
|
|
10
|
+
const getDocumentParameters = (options) => {
|
|
11
|
+
let params = {
|
|
12
|
+
verbosity: 0
|
|
13
|
+
};
|
|
14
|
+
if (typeof options.data === 'string') {
|
|
15
|
+
params.data = parsePdfFromBase64String(options.data);
|
|
16
|
+
}
|
|
17
|
+
else if (typeof options.url === 'string') {
|
|
18
|
+
params.url = options.url;
|
|
19
|
+
}
|
|
20
|
+
else if (options.arrayBuffer instanceof ArrayBuffer) {
|
|
21
|
+
params = options.arrayBuffer;
|
|
22
|
+
}
|
|
23
|
+
else if (options.typedArray) {
|
|
24
|
+
params = options.typedArray;
|
|
25
|
+
}
|
|
26
|
+
return params;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* @hidden
|
|
30
|
+
*/
|
|
31
|
+
export const removeChildren = (dom) => {
|
|
32
|
+
while (dom.firstChild) {
|
|
33
|
+
dom.removeChild(dom.firstChild);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const appendPage = (dom, page, index) => {
|
|
37
|
+
if (index === 0) {
|
|
38
|
+
removeChildren(dom);
|
|
39
|
+
}
|
|
40
|
+
dom.appendChild(page);
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* @hidden
|
|
44
|
+
*/
|
|
45
|
+
export const download = (options, fileName = 'Document', saveOptions = {}, onDownload) => {
|
|
46
|
+
if (options.pdf) {
|
|
47
|
+
options.pdf
|
|
48
|
+
.getData()
|
|
49
|
+
.then((data) => new Blob([data], { type: 'application/pdf' }))
|
|
50
|
+
.then((blob) => {
|
|
51
|
+
if (!onDownload(blob, fileName, saveOptions)) {
|
|
52
|
+
saveAs(blob, fileName, saveOptions);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
.catch((reason) => {
|
|
56
|
+
options.error.call(undefined, reason);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* @hidden
|
|
62
|
+
*/
|
|
63
|
+
export const loadPDF = (options) => {
|
|
64
|
+
const params = getDocumentParameters(options);
|
|
65
|
+
const { dom, zoom, done, error } = options;
|
|
66
|
+
getDocument(params)
|
|
67
|
+
.promise.then((pdfDoc) => {
|
|
68
|
+
const pages = [];
|
|
69
|
+
for (let i = 1; i <= pdfDoc.numPages; i++) {
|
|
70
|
+
pages.push(pdfDoc.getPage(i));
|
|
71
|
+
}
|
|
72
|
+
return { pages, pdfDoc };
|
|
73
|
+
})
|
|
74
|
+
.then(({ pages, pdfDoc }) => {
|
|
75
|
+
Promise.all(pages)
|
|
76
|
+
.then((all) => all.map((page, i) => {
|
|
77
|
+
appendPage(dom, renderPage(page, zoom, error), i);
|
|
78
|
+
return page;
|
|
79
|
+
}))
|
|
80
|
+
.then((pdfPages) => {
|
|
81
|
+
done({ pdfPages, pdfDoc, zoom });
|
|
82
|
+
})
|
|
83
|
+
.catch((reason) => {
|
|
84
|
+
options.error(reason);
|
|
85
|
+
});
|
|
86
|
+
})
|
|
87
|
+
.catch((reason) => {
|
|
88
|
+
options.error(reason);
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* @hidden
|
|
93
|
+
*/
|
|
94
|
+
export const reloadDocument = (params) => {
|
|
95
|
+
const { pdfDoc, zoom, dom, done, error } = params;
|
|
96
|
+
const pages = [];
|
|
97
|
+
for (let i = 1; i <= pdfDoc.numPages; i++) {
|
|
98
|
+
pages.push(pdfDoc.getPage(i));
|
|
99
|
+
}
|
|
100
|
+
Promise.all(pages)
|
|
101
|
+
.then((all) => all.map((page, i) => {
|
|
102
|
+
appendPage(dom, renderPage(page, zoom, error), i);
|
|
103
|
+
return page;
|
|
104
|
+
}))
|
|
105
|
+
.then(done)
|
|
106
|
+
.catch(error);
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* @hidden
|
|
110
|
+
*/
|
|
111
|
+
export const print = (pages, done, error) => {
|
|
112
|
+
const dom = document.createElement('div');
|
|
113
|
+
let dones = pages.map(() => false);
|
|
114
|
+
pages.forEach((page, index) => {
|
|
115
|
+
const viewport = renderCanvas(page, (el) => {
|
|
116
|
+
dom.appendChild(el);
|
|
117
|
+
dones[index] = true;
|
|
118
|
+
if (dones.every(Boolean)) {
|
|
119
|
+
openPrintDialog(dom, viewport.width, viewport.height, done, error);
|
|
120
|
+
}
|
|
121
|
+
}, error);
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
const openPrintDialog = (dom, width, height, done, onError) => {
|
|
125
|
+
const printDialog = window.open('', '', 'innerWidth=' +
|
|
126
|
+
width +
|
|
127
|
+
',innerHeight=' +
|
|
128
|
+
height +
|
|
129
|
+
'location=no,titlebar=no,toolbar=no');
|
|
130
|
+
if (!printDialog || !printDialog.document) {
|
|
131
|
+
onError();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (printDialog) {
|
|
135
|
+
printDialog.document.body.appendChild(dom);
|
|
136
|
+
printDialog.focus();
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
printDialog.print();
|
|
139
|
+
done();
|
|
140
|
+
});
|
|
141
|
+
const onAfterPrint = () => {
|
|
142
|
+
printDialog.removeEventListener('afterprint', onAfterPrint);
|
|
143
|
+
printDialog.close();
|
|
144
|
+
};
|
|
145
|
+
printDialog.addEventListener('afterprint', onAfterPrint);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const renderCanvas = (page, done, error) => {
|
|
149
|
+
const viewport = page.getViewport({ scale: DEFAULT_ZOOM_LEVEL });
|
|
150
|
+
const styles = {};
|
|
151
|
+
const pageElement = createElement('div', '', styles);
|
|
152
|
+
const canvas = createElement('canvas', '', {
|
|
153
|
+
width: '100%',
|
|
154
|
+
height: '100%'
|
|
155
|
+
});
|
|
156
|
+
const canvasContext = canvas.getContext('2d');
|
|
157
|
+
canvas.height = viewport.height;
|
|
158
|
+
canvas.width = viewport.width;
|
|
159
|
+
pageElement.appendChild(canvas);
|
|
160
|
+
page.render({ canvasContext, viewport })
|
|
161
|
+
.promise.then(() => {
|
|
162
|
+
const printContent = new Image();
|
|
163
|
+
printContent.src = canvas.toDataURL();
|
|
164
|
+
pageElement.removeChild(canvas);
|
|
165
|
+
pageElement.appendChild(printContent);
|
|
166
|
+
printContent.width = canvas.width;
|
|
167
|
+
printContent.height = canvas.height;
|
|
168
|
+
const onload = () => {
|
|
169
|
+
printContent.removeEventListener('load', onload);
|
|
170
|
+
done(pageElement);
|
|
171
|
+
};
|
|
172
|
+
printContent.addEventListener('load', onload);
|
|
173
|
+
})
|
|
174
|
+
.catch(error);
|
|
175
|
+
return viewport;
|
|
176
|
+
};
|
|
177
|
+
const createElement = function (name, className, styles) {
|
|
178
|
+
const element = document.createElement(name);
|
|
179
|
+
if (className) {
|
|
180
|
+
element.className = className;
|
|
181
|
+
}
|
|
182
|
+
Object.keys(styles).forEach((key) => (element.style[key] = styles[key]));
|
|
183
|
+
return element;
|
|
184
|
+
};
|
|
185
|
+
const renderPage = (page, zoom, error) => {
|
|
186
|
+
const viewport = page.getViewport({ scale: zoom });
|
|
187
|
+
const styles = {
|
|
188
|
+
width: viewport.width + 'px',
|
|
189
|
+
height: viewport.height + 'px'
|
|
190
|
+
};
|
|
191
|
+
const pageElement = createElement('div', 'k-page', styles);
|
|
192
|
+
const canvas = createElement('canvas', '', {
|
|
193
|
+
width: '100%',
|
|
194
|
+
height: '100%'
|
|
195
|
+
});
|
|
196
|
+
const canvasContext = canvas.getContext('2d');
|
|
197
|
+
canvas.height = viewport.height;
|
|
198
|
+
canvas.width = viewport.width;
|
|
199
|
+
pageElement.appendChild(canvas);
|
|
200
|
+
page.render({ canvasContext, viewport })
|
|
201
|
+
.promise.then(() => {
|
|
202
|
+
page.getTextContent().then((textContent) => {
|
|
203
|
+
const textLayer = createElement('div', 'k-text-layer', styles);
|
|
204
|
+
renderTextLayer({
|
|
205
|
+
textContentSource: textContent,
|
|
206
|
+
container: textLayer,
|
|
207
|
+
viewport: viewport,
|
|
208
|
+
textDivs: []
|
|
209
|
+
})
|
|
210
|
+
.promise.then(() => {
|
|
211
|
+
pageElement.appendChild(textLayer);
|
|
212
|
+
})
|
|
213
|
+
.catch(error);
|
|
214
|
+
});
|
|
215
|
+
})
|
|
216
|
+
.catch(error);
|
|
217
|
+
return pageElement;
|
|
218
|
+
};
|
|
219
|
+
const searchMatchScrollLeftOffset = 0;
|
|
220
|
+
const searchMatchScrollTopOffset = -64;
|
|
221
|
+
const scrollToSearchMatch = (matchElement, ref) => {
|
|
222
|
+
if (!matchElement) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const closestCharElement = matchElement.closest('.k-text-char');
|
|
226
|
+
const closestTextElement = closestCharElement
|
|
227
|
+
? closestCharElement.closest('span[role="presentation"]')
|
|
228
|
+
: null;
|
|
229
|
+
if (!closestTextElement) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const closestPageElement = closestTextElement.closest('.k-page');
|
|
233
|
+
if (!closestPageElement) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const scrollLeft = closestPageElement.offsetLeft +
|
|
237
|
+
-1 * ref.scroller.element.offsetLeft +
|
|
238
|
+
closestTextElement.offsetLeft +
|
|
239
|
+
searchMatchScrollLeftOffset;
|
|
240
|
+
const scrollTop = closestPageElement.offsetTop +
|
|
241
|
+
-1 * ref.scroller.element.offsetTop +
|
|
242
|
+
closestTextElement.offsetTop +
|
|
243
|
+
searchMatchScrollTopOffset;
|
|
244
|
+
ref.scroller.scrollTo(scrollLeft, scrollTop, { trackScrollEvent: false });
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* @hidden
|
|
248
|
+
*/
|
|
249
|
+
export const goToNextSearchMatch = (ref) => {
|
|
250
|
+
ref.search.markNextMatch();
|
|
251
|
+
const matchElement = ref.search.getActiveMatchElement();
|
|
252
|
+
scrollToSearchMatch(matchElement, ref);
|
|
253
|
+
};
|
|
254
|
+
/**
|
|
255
|
+
* @hidden
|
|
256
|
+
*/
|
|
257
|
+
export const goToPreviousSearchMatch = (ref) => {
|
|
258
|
+
ref.search.markPreviousMatch();
|
|
259
|
+
const matchElement = ref.search.getActiveMatchElement();
|
|
260
|
+
scrollToSearchMatch(matchElement, ref);
|
|
261
|
+
};
|
|
262
|
+
/**
|
|
263
|
+
* @hidden
|
|
264
|
+
*/
|
|
265
|
+
export const calculateZoomLevel = (zoomLevel, zoomLevelType, currentZoom, dom) => {
|
|
266
|
+
const documentContainer = dom.closest('.k-pdf-viewer-canvas');
|
|
267
|
+
const page = dom.querySelector('.k-page');
|
|
268
|
+
const pageSize = { width: page.offsetWidth, height: page.offsetHeight };
|
|
269
|
+
let calculatedZoomLevel = zoomLevel;
|
|
270
|
+
if (zoomLevelType === 'ActualWidth') {
|
|
271
|
+
calculatedZoomLevel = 1;
|
|
272
|
+
}
|
|
273
|
+
else if (zoomLevelType === 'FitToWidth') {
|
|
274
|
+
calculatedZoomLevel =
|
|
275
|
+
documentContainer.offsetWidth / (pageSize.width / currentZoom);
|
|
276
|
+
}
|
|
277
|
+
else if (zoomLevelType === 'FitToPage') {
|
|
278
|
+
calculatedZoomLevel =
|
|
279
|
+
documentContainer.offsetHeight / (pageSize.height / currentZoom);
|
|
280
|
+
}
|
|
281
|
+
return calculatedZoomLevel;
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* Scrolls the PDFViewer document to the passed page number.
|
|
285
|
+
*
|
|
286
|
+
* @param rootElement The root HTML element of the PDFViewer component.
|
|
287
|
+
* @param pageNumber The page number.
|
|
288
|
+
*/
|
|
289
|
+
export const scrollToPage = (rootElement, pageNumber) => {
|
|
290
|
+
const pages = rootElement.querySelectorAll('.k-page');
|
|
291
|
+
const page = pages[0];
|
|
292
|
+
if (page instanceof HTMLDivElement) {
|
|
293
|
+
const top = (page.offsetHeight + page.offsetTop) *
|
|
294
|
+
Math.max(0, Math.min(pageNumber, pages.length - 1));
|
|
295
|
+
const scrollElement = page.closest('.k-pdf-viewer-canvas');
|
|
296
|
+
if (scrollElement) {
|
|
297
|
+
scrollElement.scrollTo({ top, behavior: 'auto' });
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
/**
|
|
302
|
+
* A function which gives you the page number of the document according to the scroll position.
|
|
303
|
+
*
|
|
304
|
+
* @param rootElement The root HTML element of the PDFViewer component.
|
|
305
|
+
* @returns The page number.
|
|
306
|
+
*/
|
|
307
|
+
export const currentPage = (rootElement) => {
|
|
308
|
+
const scrollElement = rootElement.querySelector('.k-pdf-viewer-canvas');
|
|
309
|
+
const page = rootElement.querySelector('.k-page');
|
|
310
|
+
return scrollElement && page
|
|
311
|
+
? Math.floor(Math.round(scrollElement.scrollTop) /
|
|
312
|
+
(page.offsetHeight + page.offsetTop) +
|
|
313
|
+
0.01)
|
|
314
|
+
: 0;
|
|
315
|
+
};
|
package/dist/npm/main.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./scroller"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./search"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./utils"), exports);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hidden
|
|
3
|
+
*/
|
|
4
|
+
export declare class Scroller {
|
|
5
|
+
options: any;
|
|
6
|
+
state: any;
|
|
7
|
+
element: any;
|
|
8
|
+
throttledOnDrag: any;
|
|
9
|
+
draggable: any;
|
|
10
|
+
throttledOnElementScroll: any;
|
|
11
|
+
constructor(element: any, options: any);
|
|
12
|
+
destroy(): void;
|
|
13
|
+
initDraggable(): void;
|
|
14
|
+
destroyDraggable(): void;
|
|
15
|
+
bindEvents(): void;
|
|
16
|
+
bindDraggableEvents(): void;
|
|
17
|
+
bindElementScroll(): void;
|
|
18
|
+
unbindEvents(): void;
|
|
19
|
+
unbindDraggableEvents(): void;
|
|
20
|
+
unbindElementScroll(): void;
|
|
21
|
+
setState(newState: any): void;
|
|
22
|
+
resetState(): void;
|
|
23
|
+
enablePanEventsTracking(): void;
|
|
24
|
+
disablePanEventsTracking(): void;
|
|
25
|
+
shouldTrackPanEvents(): boolean;
|
|
26
|
+
onElementScroll: () => void;
|
|
27
|
+
onDragStart: (e: any) => void;
|
|
28
|
+
onDrag: (e: any) => void;
|
|
29
|
+
onDragEnd: () => void;
|
|
30
|
+
calculateEventLocationDelta(e: any): void;
|
|
31
|
+
scrollTo(x: any, y: any, options?: any): void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const kendo_draggable_1 = require("@progress/kendo-draggable");
|
|
4
|
+
const throttle = function (func, wait, options = {}) {
|
|
5
|
+
let timeout, context, args, result;
|
|
6
|
+
let previous = 0;
|
|
7
|
+
const later = function () {
|
|
8
|
+
previous = options.leading === false ? 0 : new Date().getTime();
|
|
9
|
+
timeout = undefined;
|
|
10
|
+
result = func.apply(context, args);
|
|
11
|
+
if (!timeout) {
|
|
12
|
+
context = args = null;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const throttled = function () {
|
|
16
|
+
const now = new Date().getTime();
|
|
17
|
+
if (!previous && options.leading === false) {
|
|
18
|
+
previous = now;
|
|
19
|
+
}
|
|
20
|
+
const remaining = wait - (now - previous);
|
|
21
|
+
context = undefined; // this
|
|
22
|
+
args = arguments;
|
|
23
|
+
if (remaining <= 0 || remaining > wait) {
|
|
24
|
+
if (timeout) {
|
|
25
|
+
clearTimeout(timeout);
|
|
26
|
+
timeout = undefined;
|
|
27
|
+
}
|
|
28
|
+
previous = now;
|
|
29
|
+
result = func.apply(context, args);
|
|
30
|
+
if (!timeout) {
|
|
31
|
+
context = args = null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else if (!timeout && options.trailing !== false) {
|
|
35
|
+
timeout = window.setTimeout(later, remaining);
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
return throttled;
|
|
40
|
+
};
|
|
41
|
+
const preventDefault = (e) => {
|
|
42
|
+
if (e.preventDefault) {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
}
|
|
45
|
+
if (e.originalEvent) {
|
|
46
|
+
e.originalEvent.preventDefault();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const matchesElementSelector = (element, selector) => {
|
|
50
|
+
if (!element || !selector) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
return element.closest(selector);
|
|
54
|
+
};
|
|
55
|
+
const FRAMES_PER_SECOND = 1000 / 60;
|
|
56
|
+
const SCROLL = 'scroll';
|
|
57
|
+
/**
|
|
58
|
+
* @hidden
|
|
59
|
+
*/
|
|
60
|
+
class Scroller {
|
|
61
|
+
constructor(element, options) {
|
|
62
|
+
this.options = {
|
|
63
|
+
events: {
|
|
64
|
+
[SCROLL]: () => undefined
|
|
65
|
+
},
|
|
66
|
+
filter: '',
|
|
67
|
+
// throttle the scroll events to get a more similar experience
|
|
68
|
+
// to the scrolling behavior in Adobe Acrobat Reader
|
|
69
|
+
// as well as allow a way to improve the scrolling performance for large files
|
|
70
|
+
panScrollThrottleDelay: FRAMES_PER_SECOND,
|
|
71
|
+
// the drag directions are actually reversed, e.g.
|
|
72
|
+
// dragging to the right actually moves the document to the left
|
|
73
|
+
scrollDirectionModifier: -1,
|
|
74
|
+
scrollThrottleDelay: FRAMES_PER_SECOND
|
|
75
|
+
};
|
|
76
|
+
this.onElementScroll = () => {
|
|
77
|
+
const element = this.element;
|
|
78
|
+
if (this.state.trackNextElementScroll) {
|
|
79
|
+
this.scrollTo(element.scrollLeft, element.scrollTop);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// reset the state, so that consecutive scroll events can be handled
|
|
83
|
+
this.state.trackNextElementScroll = true;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
this.onDragStart = (e) => {
|
|
87
|
+
this.state.dragStarted = false;
|
|
88
|
+
if (!this.shouldTrackPanEvents()) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const target = e.target || (e.originalEvent || {}).target;
|
|
92
|
+
if (this.options.filter &&
|
|
93
|
+
!matchesElementSelector(target, this.options.filter)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
preventDefault(e);
|
|
97
|
+
this.setState({
|
|
98
|
+
dragStarted: true,
|
|
99
|
+
location: {
|
|
100
|
+
pageX: e.pageX,
|
|
101
|
+
pageY: e.pageY
|
|
102
|
+
},
|
|
103
|
+
locationDelta: {
|
|
104
|
+
x: 0,
|
|
105
|
+
y: 0
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
this.onDrag = (e) => {
|
|
110
|
+
if (!this.shouldTrackPanEvents() || !this.state.dragStarted) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.calculateEventLocationDelta(e);
|
|
114
|
+
this.setState({
|
|
115
|
+
location: {
|
|
116
|
+
pageX: e.pageX,
|
|
117
|
+
pageY: e.pageY
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
const directionModifier = this.options.scrollDirectionModifier;
|
|
121
|
+
const scrollLeft = this.element.scrollLeft +
|
|
122
|
+
directionModifier * this.state.locationDelta.x;
|
|
123
|
+
const scrollTop = this.element.scrollTop +
|
|
124
|
+
directionModifier * this.state.locationDelta.y;
|
|
125
|
+
this.scrollTo(scrollLeft, scrollTop);
|
|
126
|
+
};
|
|
127
|
+
this.onDragEnd = () => {
|
|
128
|
+
if (!this.shouldTrackPanEvents()) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
this.element = element;
|
|
133
|
+
this.options = Object.assign({}, this.options, options);
|
|
134
|
+
this.resetState();
|
|
135
|
+
this.bindEvents();
|
|
136
|
+
}
|
|
137
|
+
destroy() {
|
|
138
|
+
this.unbindEvents();
|
|
139
|
+
}
|
|
140
|
+
initDraggable() {
|
|
141
|
+
this.destroyDraggable();
|
|
142
|
+
if (this.options.panScrollThrottleDelay > 0) {
|
|
143
|
+
this.throttledOnDrag = throttle(this.onDrag, this.options.panScrollThrottleDelay);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
this.throttledOnDrag = this.onDrag;
|
|
147
|
+
}
|
|
148
|
+
this.draggable = new kendo_draggable_1.default({
|
|
149
|
+
mouseOnly: false,
|
|
150
|
+
press: this.onDragStart,
|
|
151
|
+
drag: this.throttledOnDrag,
|
|
152
|
+
release: this.onDragEnd
|
|
153
|
+
});
|
|
154
|
+
this.draggable.bindTo(this.element);
|
|
155
|
+
}
|
|
156
|
+
destroyDraggable() {
|
|
157
|
+
if (this.draggable && this.draggable.destroy) {
|
|
158
|
+
this.draggable.destroy();
|
|
159
|
+
if (this.throttledOnDrag && this.throttledOnDrag.cancel) {
|
|
160
|
+
this.throttledOnDrag.cancel();
|
|
161
|
+
this.throttledOnDrag = null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
bindEvents() {
|
|
166
|
+
this.bindDraggableEvents();
|
|
167
|
+
this.bindElementScroll();
|
|
168
|
+
}
|
|
169
|
+
bindDraggableEvents() {
|
|
170
|
+
this.initDraggable();
|
|
171
|
+
}
|
|
172
|
+
bindElementScroll() {
|
|
173
|
+
if (this.options.scrollThrottleDelay > 0) {
|
|
174
|
+
this.throttledOnElementScroll = throttle(this.onElementScroll, this.options.scrollThrottleDelay);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
this.throttledOnElementScroll = this.onElementScroll;
|
|
178
|
+
}
|
|
179
|
+
this.element.addEventListener(SCROLL, this.throttledOnElementScroll);
|
|
180
|
+
}
|
|
181
|
+
unbindEvents() {
|
|
182
|
+
this.unbindElementScroll();
|
|
183
|
+
this.unbindDraggableEvents();
|
|
184
|
+
}
|
|
185
|
+
unbindDraggableEvents() {
|
|
186
|
+
this.destroyDraggable();
|
|
187
|
+
}
|
|
188
|
+
unbindElementScroll() {
|
|
189
|
+
if (this.throttledOnElementScroll &&
|
|
190
|
+
this.throttledOnElementScroll.cancel) {
|
|
191
|
+
this.throttledOnElementScroll.cancel();
|
|
192
|
+
this.throttledOnElementScroll = null;
|
|
193
|
+
}
|
|
194
|
+
this.element.removeEventListener(SCROLL, this.throttledOnElementScroll);
|
|
195
|
+
}
|
|
196
|
+
setState(newState) {
|
|
197
|
+
this.state = Object.assign({}, this.state || {}, newState);
|
|
198
|
+
}
|
|
199
|
+
resetState() {
|
|
200
|
+
this.setState({
|
|
201
|
+
trackPanEvents: false,
|
|
202
|
+
trackNextElementScroll: false,
|
|
203
|
+
location: { pageX: 0, pageY: 0 },
|
|
204
|
+
locationDelta: { x: 0, y: 0 }
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
enablePanEventsTracking() {
|
|
208
|
+
this.state.trackPanEvents = true;
|
|
209
|
+
this.bindDraggableEvents();
|
|
210
|
+
}
|
|
211
|
+
disablePanEventsTracking() {
|
|
212
|
+
this.unbindDraggableEvents();
|
|
213
|
+
this.state.trackPanEvents = false;
|
|
214
|
+
}
|
|
215
|
+
shouldTrackPanEvents() {
|
|
216
|
+
return this.state.trackPanEvents;
|
|
217
|
+
}
|
|
218
|
+
calculateEventLocationDelta(e) {
|
|
219
|
+
this.state.locationDelta = {
|
|
220
|
+
x: e.pageX - this.state.location.pageX,
|
|
221
|
+
y: e.pageY - this.state.location.pageY
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
scrollTo(x, y, options = { trackScrollEvent: true }) {
|
|
225
|
+
if (!options.trackScrollEvent) {
|
|
226
|
+
this.state.trackNextElementScroll = false;
|
|
227
|
+
}
|
|
228
|
+
this.element.scrollLeft = x;
|
|
229
|
+
this.element.scrollTop = y;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
exports.Scroller = Scroller;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hidden
|
|
3
|
+
*/
|
|
4
|
+
export declare class SearchService {
|
|
5
|
+
options: any;
|
|
6
|
+
state: any;
|
|
7
|
+
constructor(options: any);
|
|
8
|
+
destroy(): void;
|
|
9
|
+
extendOptions(options: any): void;
|
|
10
|
+
setState(newState: any): void;
|
|
11
|
+
resetState(): void;
|
|
12
|
+
search({ text, matchCase }: any): {
|
|
13
|
+
startOffset: number;
|
|
14
|
+
endOffset: number;
|
|
15
|
+
}[];
|
|
16
|
+
clearSearch(): void;
|
|
17
|
+
restoreOriginalText(): void;
|
|
18
|
+
shouldTransformText(): boolean;
|
|
19
|
+
transformTextForSearch(): void;
|
|
20
|
+
extractTextNodes(node: any): void;
|
|
21
|
+
transformTextNodesForSearch(textNodes: any): void;
|
|
22
|
+
transformTextNodeForSearch(node: any): void;
|
|
23
|
+
splitTextByChars(text: any): string;
|
|
24
|
+
forEachTextContainer(callback: any): void;
|
|
25
|
+
highlightAllMatches(): void;
|
|
26
|
+
addMatchHighlight(matchStartOffset: number, matchEndOffset: number, matchIndex: number): void;
|
|
27
|
+
removeMatchHighlights(): void;
|
|
28
|
+
addActiveMatchMark(): void;
|
|
29
|
+
removeActiveMatchMark(): void;
|
|
30
|
+
removeIndicators(): void;
|
|
31
|
+
markNextMatch(): void;
|
|
32
|
+
markPreviousMatch(): void;
|
|
33
|
+
markNextMatchIndex(): void;
|
|
34
|
+
markPreviousMatchIndex(): void;
|
|
35
|
+
moveActiveMatchIndex(delta: any): void;
|
|
36
|
+
getActiveMatchElement(): any;
|
|
37
|
+
}
|