@vaadin-component-factory/vcf-pdf-viewer 3.0.2 → 4.0.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/README.md +2 -1
- package/package.json +56 -52
- package/pdfjs/dist/display_utils.js +609 -714
- package/pdfjs/dist/fetch_stream.js +239 -293
- package/pdfjs/dist/l10n_utils.js +113 -122
- package/pdfjs/dist/message_handler.js +451 -524
- package/pdfjs/dist/network.js +441 -552
- package/pdfjs/dist/network_utils.js +262 -309
- package/pdfjs/dist/node_stream.js +383 -481
- package/pdfjs/dist/pdf.js +9883 -11687
- package/pdfjs/dist/pdf_link_service.js +440 -534
- package/pdfjs/dist/pdf_rendering_queue.js +134 -154
- package/pdfjs/dist/pdf_thumbnail_viewer.js +620 -738
- package/pdfjs/dist/pdf_viewer.js +2667 -3207
- package/pdfjs/dist/ui_utils.js +762 -881
- package/pdfjs/dist/util.js +867 -991
- package/pdfjs/dist/worker.js +51434 -60846
- package/src/vcf-pdf-viewer.js +999 -868
- package/theme/base/vcf-pdf-viewer-styles.js +144 -0
- package/theme/base/vcf-pdf-viewer-toolbar-icons-styles.js +39 -0
- package/theme/base/vcf-pdf-viewer.js +3 -0
- package/vcf-pdf-viewer.js +1 -1
- package/theme/lumo/vcf-pdf-viewer-styles.js +0 -153
- package/theme/lumo/vcf-pdf-viewer-toolbar-icons-styles.js +0 -35
- package/theme/lumo/vcf-pdf-viewer.js +0 -3
- package/theme/material/baseline-keyboard_arrow_down-24px.svg +0 -1
- package/theme/material/baseline-keyboard_arrow_up-24px.svg +0 -1
- package/theme/material/vcf-pdf-viewer-styles.js +0 -123
- package/theme/material/vcf-pdf-viewer.js +0 -2
package/src/vcf-pdf-viewer.js
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
import * as
|
|
16
|
-
import * as
|
|
17
|
-
import * as
|
|
18
|
-
import * as
|
|
19
|
-
import
|
|
20
|
-
import * as
|
|
1
|
+
import { LitElement, html, css } from "lit";
|
|
2
|
+
import { ElementMixin } from "@vaadin/component-base/src/element-mixin";
|
|
3
|
+
import { ThemeDetectionMixin } from "@vaadin/vaadin-themable-mixin/vaadin-theme-detection-mixin";
|
|
4
|
+
import { ResizeMixin, SlotStylesMixin } from "@vaadin/component-base/";
|
|
5
|
+
import { ThemableMixin } from "@vaadin/vaadin-themable-mixin";
|
|
6
|
+
|
|
7
|
+
import "@vaadin/text-field";
|
|
8
|
+
import "@vaadin/select";
|
|
9
|
+
import "@vaadin/item";
|
|
10
|
+
import "@vaadin/button";
|
|
11
|
+
import "@vaadin/icon";
|
|
12
|
+
import "@vaadin/icons";
|
|
13
|
+
import "@vaadin/tooltip";
|
|
14
|
+
|
|
15
|
+
import * as pdfjsLib from "../pdfjs/dist/pdf";
|
|
16
|
+
import * as pdfjsViewer from "../pdfjs/dist/pdf_viewer";
|
|
17
|
+
import * as pdfUtils from "../pdfjs/dist/ui_utils";
|
|
18
|
+
import * as pdfjsLinkService from "../pdfjs/dist/pdf_link_service";
|
|
19
|
+
import * as pdfjsThumbnailViewer from "../pdfjs/dist/pdf_thumbnail_viewer";
|
|
20
|
+
import * as pdfjsRenderingQueue from "../pdfjs/dist/pdf_rendering_queue";
|
|
21
|
+
import { NullL10n } from "../pdfjs/dist/l10n_utils";
|
|
22
|
+
import * as pdfjsWorker from "../pdfjs/dist/worker";
|
|
23
|
+
|
|
21
24
|
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
|
|
22
25
|
|
|
23
26
|
/**
|
|
@@ -34,886 +37,1017 @@ pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
|
|
|
34
37
|
* @mixes Vaadin.ThemableMixin
|
|
35
38
|
* @demo demo/index.html
|
|
36
39
|
*/
|
|
37
|
-
class PdfViewerElement extends
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
border: 2px solid;
|
|
241
|
-
border-color: rgba(0, 0, 0, 0.5);
|
|
242
|
-
width: 40px;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
::slotted(#nextPage), ::slotted(#previousPage) {
|
|
246
|
-
width: 30px;
|
|
247
|
-
margin: 0;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
[part~="toolbar"].ready ::slotted(.toolbar-zoom.hide-zoom) {
|
|
251
|
-
display: none;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
</style>
|
|
255
|
-
|
|
256
|
-
<div id="outerContainer" part="outer-container" >
|
|
257
|
-
<div id="sidebarContainer" part="sidebar-container">
|
|
258
|
-
<div id="sidebarContent" part="sidebar-content">
|
|
259
|
-
<div id="thumbnailView" part="thumbnail-view"></div>
|
|
260
|
-
</div>
|
|
261
|
-
</div>
|
|
262
|
-
<div id="mainContainer" part="main-container">
|
|
263
|
-
<div id="toolbar" part="toolbar">
|
|
264
|
-
<slot name="sidebar-toggle-button-slot"></slot>
|
|
265
|
-
<span id="title" part="toolbar-text toolbar-title">{{__title}}</span>
|
|
266
|
-
<slot name="toolbar-zoom-slot"></slot>
|
|
267
|
-
<div part="toolbar-pages">
|
|
268
|
-
<slot name="toolbar-current-page-slot"></slot>
|
|
269
|
-
<span id="pageSeparator" part="toolbar-text toolbar-page-separator">/</span>
|
|
270
|
-
<span id="totalPages" part="toolbar-text toolbar-total-pages">{{__totalPages}}</span>
|
|
271
|
-
<slot name="previous-page-button-slot"></slot>
|
|
272
|
-
<slot name="next-page-button-slot"></slot>
|
|
273
|
-
</div>
|
|
274
|
-
<slot></slot>
|
|
275
|
-
</div>
|
|
276
|
-
|
|
277
|
-
<div id="viewerContainer" part="viewer-container" tabindex="0">
|
|
278
|
-
<div id="viewer" part="viewer"></div>
|
|
279
|
-
</div>
|
|
280
|
-
</div>
|
|
281
|
-
</div>
|
|
40
|
+
export class PdfViewerElement extends ResizeMixin(
|
|
41
|
+
SlotStylesMixin(ThemeDetectionMixin(ThemableMixin(ElementMixin(LitElement)))),
|
|
42
|
+
) {
|
|
43
|
+
static get styles() {
|
|
44
|
+
return css`
|
|
45
|
+
:host {
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
width: 100%;
|
|
49
|
+
height: 500px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:host([hidden]) {
|
|
53
|
+
display: none !important;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
[part~="toolbar"] #currentPage,
|
|
57
|
+
[part~="toolbar"] #pageSeparator,
|
|
58
|
+
[part~="toolbar"] #totalPages,
|
|
59
|
+
[part~="toolbar"] #previousPage,
|
|
60
|
+
[part~="toolbar"] #nextPage,
|
|
61
|
+
[part~="toolbar"] #zoom,
|
|
62
|
+
[part~="toolbar"] #sidebarToggle {
|
|
63
|
+
display: none;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
[part~="toolbar"].ready #currentPage,
|
|
67
|
+
[part~="toolbar"].ready #pageSeparator,
|
|
68
|
+
[part~="toolbar"].ready #totalPages,
|
|
69
|
+
[part~="toolbar"].ready #previousPage,
|
|
70
|
+
[part~="toolbar"].ready #nextPage,
|
|
71
|
+
[part~="toolbar"].ready #zoom,
|
|
72
|
+
[part~="toolbar"].ready #sidebarToggle {
|
|
73
|
+
display: inherit;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
[part~="outer-container"] {
|
|
77
|
+
width: 100%;
|
|
78
|
+
height: 100%;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
[part~="main-container"] {
|
|
82
|
+
position: absolute;
|
|
83
|
+
top: 0;
|
|
84
|
+
right: 0;
|
|
85
|
+
bottom: 0;
|
|
86
|
+
left: 0;
|
|
87
|
+
min-width: 320px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
[part~="viewer-container"] {
|
|
91
|
+
position: absolute;
|
|
92
|
+
flex: 1;
|
|
93
|
+
overflow: auto;
|
|
94
|
+
width: 100%;
|
|
95
|
+
height: -moz-calc(100% - 45px); /* Firefox */
|
|
96
|
+
height: -webkit-calc(100% - 45px); /* Chrome, Safari */
|
|
97
|
+
height: calc(100% - 45px); /*all other browsers */
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
[part~="sidebar-container"] {
|
|
101
|
+
position: absolute;
|
|
102
|
+
width: 200px;
|
|
103
|
+
top: 45px;
|
|
104
|
+
bottom: 0;
|
|
105
|
+
visibility: hidden;
|
|
106
|
+
height: -moz-calc(100% - 45px); /* Firefox */
|
|
107
|
+
height: -webkit-calc(100% - 45px); /* Chrome, Safari */
|
|
108
|
+
height: calc(100% - 45px); /*all other browsers */
|
|
109
|
+
z-index: 100;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
[part~="sidebar-content"] {
|
|
113
|
+
position: absolute;
|
|
114
|
+
top: 0;
|
|
115
|
+
bottom: 0;
|
|
116
|
+
overflow: auto;
|
|
117
|
+
width: 100%;
|
|
118
|
+
background-color: rgba(0, 0, 0, 0.1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
[part~="thumbnail-view"] {
|
|
122
|
+
position: absolute;
|
|
123
|
+
width: calc(100% - 60px);
|
|
124
|
+
top: 0;
|
|
125
|
+
bottom: 0;
|
|
126
|
+
padding: 10px 30px 0;
|
|
127
|
+
overflow: auto;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
[part~="toolbar"] {
|
|
131
|
+
height: 44px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.page {
|
|
135
|
+
position: relative;
|
|
136
|
+
margin: 0 auto;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.textLayer {
|
|
140
|
+
position: absolute;
|
|
141
|
+
left: 0;
|
|
142
|
+
top: 0;
|
|
143
|
+
right: 0;
|
|
144
|
+
bottom: 0;
|
|
145
|
+
overflow: hidden;
|
|
146
|
+
line-height: 1;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.textLayer > span {
|
|
150
|
+
color: transparent;
|
|
151
|
+
position: absolute;
|
|
152
|
+
white-space: pre;
|
|
153
|
+
cursor: text;
|
|
154
|
+
-webkit-transform-origin: 0% 0%;
|
|
155
|
+
transform-origin: 0% 0%;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.textLayer .highlight {
|
|
159
|
+
margin: -1px;
|
|
160
|
+
padding: 1px;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.textLayer .highlight.begin {
|
|
164
|
+
border-radius: 4px 0 0 4px;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.textLayer .highlight.end {
|
|
168
|
+
border-radius: 0 4px 4px 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.textLayer .highlight.middle {
|
|
172
|
+
border-radius: 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.textLayer .endOfContent {
|
|
176
|
+
display: block;
|
|
177
|
+
position: absolute;
|
|
178
|
+
left: 0;
|
|
179
|
+
top: 100%;
|
|
180
|
+
right: 0;
|
|
181
|
+
bottom: 0;
|
|
182
|
+
z-index: -1;
|
|
183
|
+
cursor: default;
|
|
184
|
+
-webkit-user-select: none;
|
|
185
|
+
-moz-user-select: none;
|
|
186
|
+
-ms-user-select: none;
|
|
187
|
+
user-select: none;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.textLayer .endOfContent.active {
|
|
191
|
+
top: 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
#header {
|
|
195
|
+
display: flex;
|
|
196
|
+
flex-direction: row;
|
|
197
|
+
align-items: baseline;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
::slotted(#currentPage) {
|
|
201
|
+
align-self: baseline;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
#outerContainer.sidebarOpen #viewerContainer {
|
|
205
|
+
transition-property: left;
|
|
206
|
+
left: 200px;
|
|
207
|
+
width: -moz-calc(100% - 200px); /* Firefox */
|
|
208
|
+
width: -webkit-calc(100% - 200px); /* Chrome, Safari */
|
|
209
|
+
width: calc(100% - 200px); /*all other browsers */
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
#outerContainer.sidebarOpen #sidebarContainer {
|
|
213
|
+
visibility: visible;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.thumbnail {
|
|
217
|
+
margin: 0 10px 5px;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.thumbnailImage {
|
|
221
|
+
border: 1px solid rgba(0, 0, 0, 0);
|
|
222
|
+
box-shadow:
|
|
223
|
+
0 0 0 1px rgba(0, 0, 0, 0.5),
|
|
224
|
+
0 2px 8px rgba(0, 0, 0, 0.3);
|
|
225
|
+
opacity: 1;
|
|
226
|
+
z-index: 99;
|
|
227
|
+
background-color: rgba(255, 255, 255, 1);
|
|
228
|
+
background-clip: content-box;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.thumbnailSelectionRing {
|
|
232
|
+
border-radius: 2px;
|
|
233
|
+
padding: 7px;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.thumbnail.selected > .thumbnailSelectionRing {
|
|
237
|
+
background-color: rgba(0, 0, 0, 0.15);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
[part~="toolbar"].ready ::slotted(.toolbar-zoom.hide-zoom) {
|
|
241
|
+
display: none;
|
|
242
|
+
}
|
|
282
243
|
`;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
static get is() {
|
|
286
|
-
return 'vcf-pdf-viewer';
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
static get version() {
|
|
290
|
-
return '3.0.2';
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
static get properties() {
|
|
294
|
-
return {
|
|
295
|
-
/**
|
|
296
|
-
* You can set a pdf file that you want to render with src. Note that regular cross
|
|
297
|
-
* site scripting (XSS) rules apply. This means that the file should be on the same
|
|
298
|
-
* server as where the component is run, or that the server where the file is on should
|
|
299
|
-
* be configured to allow loading files from other sites.
|
|
300
|
-
*/
|
|
301
|
-
src: {
|
|
302
|
-
type: String,
|
|
303
|
-
observer: '__srcChanged'
|
|
304
|
-
},
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* The viewer, which takes care of rendering content into a DOM element.
|
|
308
|
-
*/
|
|
309
|
-
__viewer: Object,
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* The viewer for thumbnails.
|
|
313
|
-
*/
|
|
314
|
-
__thumbnailViewer: Object,
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* The link service.
|
|
318
|
-
*/
|
|
319
|
-
__linkService: Object,
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* A represenentation of a document that has been read in.
|
|
323
|
-
*/
|
|
324
|
-
__document: Object,
|
|
325
|
-
/**
|
|
326
|
-
* The title for the PDF shown in the toolbar of component. It uses both the file name and
|
|
327
|
-
* the title in the PDF metadata if available.
|
|
328
|
-
*/
|
|
329
|
-
__title: {
|
|
330
|
-
type: String,
|
|
331
|
-
value: 'PDF'
|
|
332
|
-
},
|
|
333
|
-
/**
|
|
334
|
-
* Relative filename
|
|
335
|
-
*/
|
|
336
|
-
__filename: String,
|
|
337
|
-
/**
|
|
338
|
-
* The pdf metadata title
|
|
339
|
-
*/
|
|
340
|
-
__pdfTitle: String,
|
|
341
|
-
/**
|
|
342
|
-
* The level of zoom on the document.
|
|
343
|
-
* Allowed values are
|
|
344
|
-
* - Number, for zoom percentage. Eg. 1.5 means 150% zoom
|
|
345
|
-
* - 'auto', default value
|
|
346
|
-
* - 'page-fit', fit a full page into component
|
|
347
|
-
*/
|
|
348
|
-
zoom: {
|
|
349
|
-
type: String,
|
|
350
|
-
value: 'auto'
|
|
351
|
-
},
|
|
352
|
-
/**
|
|
353
|
-
* The current page visible viewed right now
|
|
354
|
-
*/
|
|
355
|
-
currentPage: {
|
|
356
|
-
type: String,
|
|
357
|
-
value: "1"
|
|
358
|
-
},
|
|
359
|
-
/**
|
|
360
|
-
* Total amount of pages in an opened document
|
|
361
|
-
*/
|
|
362
|
-
__totalPages: Number,
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Loading state
|
|
366
|
-
*/
|
|
367
|
-
__loading: {
|
|
368
|
-
type: Boolean,
|
|
369
|
-
value: true
|
|
370
|
-
},
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Whether sidebar is open after loading or not
|
|
374
|
-
*/
|
|
375
|
-
__sidebarOpen: {
|
|
376
|
-
type: Boolean,
|
|
377
|
-
value: false
|
|
378
|
-
},
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Flag to indicate if toolbar should only show filename as title
|
|
382
|
-
*/
|
|
383
|
-
toolbarOnlyFilename: {
|
|
384
|
-
type: Boolean,
|
|
385
|
-
value: false
|
|
386
|
-
},
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Property to define auto zoom label
|
|
390
|
-
*/
|
|
391
|
-
autoZoomOptionLabel: {
|
|
392
|
-
type: String,
|
|
393
|
-
value: "Automatic zoom"
|
|
394
|
-
},
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Property to define page fit zoom label
|
|
398
|
-
*/
|
|
399
|
-
fitZoomOptionLabel: {
|
|
400
|
-
type: String,
|
|
401
|
-
value: "Page fit"
|
|
402
|
-
},
|
|
244
|
+
}
|
|
403
245
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
customTitle: {
|
|
408
|
-
type: String,
|
|
409
|
-
value: ""
|
|
410
|
-
},
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Renders interactive form elements in the annotation layer (html) if true,
|
|
414
|
-
* renders values of form elements directly onto the canvas if false
|
|
415
|
-
*/
|
|
416
|
-
renderInteractiveForms: {
|
|
417
|
-
type: Boolean,
|
|
418
|
-
value: true
|
|
419
|
-
},
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* Allows to hide the zoom dropdown. By default it's always shown.
|
|
423
|
-
*/
|
|
424
|
-
hideZoom: {
|
|
425
|
-
type: Boolean,
|
|
426
|
-
value: false
|
|
427
|
-
},
|
|
428
|
-
|
|
429
|
-
__zoomItems: {
|
|
430
|
-
computed: '__computeZoomItems(autoZoomOptionLabel, fitZoomOptionLabel)'
|
|
431
|
-
},
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Property to define a custom tooltip for the sidebar toggle button
|
|
435
|
-
*/
|
|
436
|
-
sidebarToggleTooltip: {
|
|
437
|
-
type: String,
|
|
438
|
-
value: ""
|
|
439
|
-
},
|
|
440
|
-
|
|
441
|
-
/**
|
|
442
|
-
* Property to define a custom tooltip for the previous page button
|
|
443
|
-
*/
|
|
444
|
-
previousPageTooltip: {
|
|
445
|
-
type: String,
|
|
446
|
-
value: ""
|
|
447
|
-
},
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Property to define a custom tooltip for the next page button
|
|
451
|
-
*/
|
|
452
|
-
nextPageTooltip: {
|
|
453
|
-
type: String,
|
|
454
|
-
value: ""
|
|
455
|
-
},
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
__createToolbarButton() {
|
|
460
|
-
const icon = document.createElement('vaadin-icon');
|
|
461
|
-
icon.setAttribute('slot', 'prefix');
|
|
462
|
-
|
|
463
|
-
const tooltip = document.createElement('vaadin-tooltip');
|
|
464
|
-
tooltip.setAttribute('slot', 'tooltip');
|
|
465
|
-
|
|
466
|
-
const button = document.createElement('vaadin-button');
|
|
467
|
-
button.classList.add('toolbar-button');
|
|
468
|
-
button.setAttribute('theme', 'icon');
|
|
469
|
-
|
|
470
|
-
button.appendChild(icon);
|
|
471
|
-
button.appendChild(tooltip);
|
|
472
|
-
return button;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Adds toggle button to the toolbar slot named "sidebar-toggle-button-slot".
|
|
477
|
-
*/
|
|
478
|
-
_createSideBarToggleButton() {
|
|
479
|
-
const button = this.__createToolbarButton();
|
|
480
|
-
const icon = button.querySelector('vaadin-icon');
|
|
481
|
-
icon.classList.add('toggle-button-icon')
|
|
482
|
-
button.querySelector('vaadin-tooltip').setAttribute('text', this.sidebarToggleTooltip);
|
|
483
|
-
button.setAttribute('slot', 'sidebar-toggle-button-slot');
|
|
484
|
-
button.setAttribute('id','sidebarToggle');
|
|
485
|
-
button.setAttribute('aria-label', 'Sidebar toggle');
|
|
486
|
-
button.addEventListener('click', () => {
|
|
487
|
-
this.__toogleSidebar();
|
|
488
|
-
if(this.$.outerContainer.classList.contains('sidebarOpen')) {
|
|
489
|
-
icon.classList.add('sidebarOpen');
|
|
490
|
-
} else {
|
|
491
|
-
icon.classList.remove('sidebarOpen');
|
|
492
|
-
}
|
|
493
|
-
});
|
|
494
|
-
this.appendChild(button);
|
|
495
|
-
}
|
|
246
|
+
get slotStyles() {
|
|
247
|
+
const tag = "vcf-pdf-viewer";
|
|
248
|
+
const lumo = '[data-application-theme="lumo"]';
|
|
496
249
|
|
|
497
250
|
/**
|
|
498
|
-
*
|
|
251
|
+
* These rules target a <vaadin-text-field> element with a child element
|
|
252
|
+
* having the 'toggle-button' class name. We can't use `::slotted()` as
|
|
253
|
+
* the toggle button is not a direct child of the month picker element.
|
|
254
|
+
* Also for `vaadin-popover` we can't use `::part()` after `::slotted()`.
|
|
499
255
|
*/
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
button.setAttribute('slot', 'previous-page-button-slot');
|
|
505
|
-
button.setAttribute('id', 'previousPage');
|
|
506
|
-
button.setAttribute('aria-label', 'Previous page');
|
|
507
|
-
button.addEventListener('click', () => this.__previousPage());
|
|
508
|
-
this.appendChild(button);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
/**
|
|
512
|
-
* Adds next page button to the toolbar slot named "next-page-button-slot".
|
|
513
|
-
*/
|
|
514
|
-
_createNextPageButton() {
|
|
515
|
-
const button = this.__createToolbarButton();
|
|
516
|
-
button.querySelector('vaadin-icon').classList.add('next-page-button-icon')
|
|
517
|
-
button.querySelector('vaadin-tooltip').setAttribute('text', this.nextPageTooltip);
|
|
518
|
-
button.setAttribute('slot', 'next-page-button-slot');
|
|
519
|
-
button.setAttribute('id', 'nextPage');
|
|
520
|
-
button.setAttribute('aria-label', 'Next page');
|
|
521
|
-
button.addEventListener('click', () => this.__nextPage());
|
|
522
|
-
this.appendChild(button);
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
/**
|
|
526
|
-
* Adds current page text field to the toolbar slot named "toolbar-current-page-slot".
|
|
527
|
-
*/
|
|
528
|
-
_createCurrentPageTextField() {
|
|
529
|
-
const textField = document.createElement('vaadin-text-field');
|
|
530
|
-
textField.setAttribute('slot', 'toolbar-current-page-slot');
|
|
531
|
-
textField.setAttribute('id', 'currentPage');
|
|
532
|
-
textField.classList.add('toolbar-current-page');
|
|
533
|
-
textField.setAttribute('value', this.currentPage);
|
|
534
|
-
textField.addEventListener('change', () => this.__pageChange());
|
|
535
|
-
this.appendChild(textField);
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* Adds zoom select to the toolbar slot named "toolbar-zoom-slot".
|
|
540
|
-
*/
|
|
541
|
-
_createZoomSelect() {
|
|
542
|
-
const select = document.createElement('vaadin-select');
|
|
543
|
-
select.setAttribute('slot', 'toolbar-zoom-slot');
|
|
544
|
-
select.setAttribute('id', 'zoom');
|
|
545
|
-
select.classList.add('toolbar-zoom');
|
|
546
|
-
select.setAttribute('value', this.zoom);
|
|
547
|
-
select.items = this.__zoomItems;
|
|
548
|
-
select.addEventListener('value-changed', (e) => this.__zoomChanged(e.detail.value));
|
|
549
|
-
if(this.hideZoom) {
|
|
550
|
-
select.classList.add('hide-zoom');
|
|
551
|
-
} else {
|
|
552
|
-
select.classList.remove('hide-zoom');
|
|
256
|
+
return [
|
|
257
|
+
`
|
|
258
|
+
${tag}:not(${lumo}) vaadin-button.toolbar-button vaadin-icon {
|
|
259
|
+
display: none;
|
|
553
260
|
}
|
|
554
|
-
|
|
555
|
-
|
|
261
|
+
|
|
262
|
+
${tag}:not(${lumo}) vaadin-button.toolbar-button {
|
|
263
|
+
height: var(--vaadin-icon-size, 1.5lh);
|
|
264
|
+
width: var(--vaadin-icon-size, 1.5lh);
|
|
265
|
+
padding: 0;
|
|
266
|
+
justify-content: flex-start;
|
|
267
|
+
box-sizing: content-box;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
${tag}:not(${lumo}) vaadin-button.toolbar-button::before {
|
|
271
|
+
content: '';
|
|
272
|
+
flex: none;
|
|
273
|
+
background: var(--vaadin-input-field-button-text-color, var(--vaadin-text-color-secondary));
|
|
274
|
+
cursor: var(--vaadin-clickable-cursor);
|
|
275
|
+
touch-action: manipulation;
|
|
276
|
+
-webkit-tap-highlight-color: transparent;
|
|
277
|
+
-webkit-user-select: none;
|
|
278
|
+
user-select: none;
|
|
279
|
+
height: var(--vaadin-icon-size, 1.5lh);
|
|
280
|
+
width: var(--vaadin-icon-size, 1.5lh);
|
|
281
|
+
mask-size: var(--vaadin-icon-visual-size, 100%);
|
|
282
|
+
mask-position: 50%;
|
|
283
|
+
mask-repeat: no-repeat;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
${tag}:not(${lumo}) vaadin-button.toolbar-button#sidebarToggle::before {
|
|
287
|
+
mask-image: var(--pdf-viewer-toggle-button-icon-closed);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
${tag}:not(${lumo}) vaadin-button.toolbar-button#sidebarToggle:has(vaadin-icon.sidebarOpen)::before {
|
|
291
|
+
mask-image: var(--pdf-viewer-toggle-button-icon-open);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
${tag}:not(${lumo}) vaadin-button.toolbar-button#previousPage::before {
|
|
295
|
+
mask-image: var(--pdf-viewer-previous-page-button-icon);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
${tag}:not(${lumo}) vaadin-button.toolbar-button#nextPage::before {
|
|
299
|
+
mask-image: var(--pdf-viewer-next-page-button-icon);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
${tag}${lumo} vaadin-button[theme~="icon"] {
|
|
303
|
+
padding-left: 6px;
|
|
304
|
+
padding-right: 6px;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
${tag}${lumo} vaadin-button.toolbar-button#sidebarToggle {
|
|
308
|
+
border: 2px solid;
|
|
309
|
+
border-color: rgba(0, 0, 0, 0.5);
|
|
310
|
+
}
|
|
311
|
+
`,
|
|
312
|
+
];
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
render() {
|
|
316
|
+
return html`
|
|
317
|
+
<div id="outerContainer" part="outer-container">
|
|
318
|
+
<div id="sidebarContainer" part="sidebar-container">
|
|
319
|
+
<div id="sidebarContent" part="sidebar-content">
|
|
320
|
+
<div id="thumbnailView" part="thumbnail-view"></div>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
<div id="mainContainer" part="main-container">
|
|
324
|
+
<div id="toolbar" part="toolbar">
|
|
325
|
+
<slot name="sidebar-toggle-button-slot"></slot>
|
|
326
|
+
<span id="title" part="toolbar-text toolbar-title"
|
|
327
|
+
>${this.__title}</span
|
|
328
|
+
>
|
|
329
|
+
<slot name="toolbar-zoom-slot"></slot>
|
|
330
|
+
<div part="toolbar-pages">
|
|
331
|
+
<slot name="toolbar-current-page-slot"></slot>
|
|
332
|
+
<span
|
|
333
|
+
id="pageSeparator"
|
|
334
|
+
part="toolbar-text toolbar-page-separator"
|
|
335
|
+
>/</span
|
|
336
|
+
>
|
|
337
|
+
<span id="totalPages" part="toolbar-text toolbar-total-pages"
|
|
338
|
+
>${this.__totalPages}</span
|
|
339
|
+
>
|
|
340
|
+
<slot name="previous-page-button-slot"></slot>
|
|
341
|
+
<slot name="next-page-button-slot"></slot>
|
|
342
|
+
</div>
|
|
343
|
+
<slot></slot>
|
|
344
|
+
</div>
|
|
556
345
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
346
|
+
<div id="viewerContainer" part="viewer-container">
|
|
347
|
+
<div id="viewer" part="viewer"></div>
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
</div>
|
|
351
|
+
`;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
static get is() {
|
|
355
|
+
return "vcf-pdf-viewer";
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
static get version() {
|
|
359
|
+
return "4.0.0";
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
static get properties() {
|
|
363
|
+
return {
|
|
364
|
+
/**
|
|
365
|
+
* You can set a pdf file that you want to render with src. Note that regular cross
|
|
366
|
+
* site scripting (XSS) rules apply. This means that the file should be on the same
|
|
367
|
+
* server as where the component is run, or that the server where the file is on should
|
|
368
|
+
* be configured to allow loading files from other sites.
|
|
369
|
+
*/
|
|
370
|
+
src: { type: String },
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* The viewer, which takes care of rendering content into a DOM element.
|
|
374
|
+
*/
|
|
375
|
+
__viewer: Object,
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* The viewer for thumbnails.
|
|
379
|
+
*/
|
|
380
|
+
__thumbnailViewer: Object,
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* The link service.
|
|
384
|
+
*/
|
|
385
|
+
__linkService: Object,
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* A represenentation of a document that has been read in.
|
|
389
|
+
*/
|
|
390
|
+
__document: Object,
|
|
391
|
+
/**
|
|
392
|
+
* The title for the PDF shown in the toolbar of component. It uses both the file name and
|
|
393
|
+
* the title in the PDF metadata if available.
|
|
394
|
+
*/
|
|
395
|
+
__title: { type: String },
|
|
396
|
+
/**
|
|
397
|
+
* Relative filename
|
|
398
|
+
*/
|
|
399
|
+
__filename: String,
|
|
400
|
+
/**
|
|
401
|
+
* The pdf metadata title
|
|
402
|
+
*/
|
|
403
|
+
__pdfTitle: String,
|
|
404
|
+
/**
|
|
405
|
+
* The level of zoom on the document.
|
|
406
|
+
* Allowed values are
|
|
407
|
+
* - Number, for zoom percentage. Eg. 1.5 means 150% zoom
|
|
408
|
+
* - 'auto', default value
|
|
409
|
+
* - 'page-fit', fit a full page into component
|
|
410
|
+
*/
|
|
411
|
+
zoom: { type: String },
|
|
412
|
+
/**
|
|
413
|
+
* The current page visible viewed right now
|
|
414
|
+
*/
|
|
415
|
+
currentPage: { type: String },
|
|
416
|
+
/**
|
|
417
|
+
* Total amount of pages in an opened document
|
|
418
|
+
*/
|
|
419
|
+
__totalPages: Number,
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Loading state
|
|
423
|
+
*/
|
|
424
|
+
__loading: { type: Boolean },
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Whether sidebar is open after loading or not
|
|
428
|
+
*/
|
|
429
|
+
__sidebarOpen: { type: Boolean },
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Flag to indicate if toolbar should only show filename as title
|
|
433
|
+
*/
|
|
434
|
+
toolbarOnlyFilename: { type: Boolean },
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Property to define auto zoom label
|
|
438
|
+
*/
|
|
439
|
+
autoZoomOptionLabel: { type: String },
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Property to define page fit zoom label
|
|
443
|
+
*/
|
|
444
|
+
fitZoomOptionLabel: { type: String },
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Property to define a custom title for the viewer
|
|
448
|
+
*/
|
|
449
|
+
customTitle: { type: String },
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Renders interactive form elements in the annotation layer (html) if true,
|
|
453
|
+
* renders values of form elements directly onto the canvas if false
|
|
454
|
+
*/
|
|
455
|
+
renderInteractiveForms: { type: Boolean },
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Allows to hide the zoom dropdown. By default it's always shown.
|
|
459
|
+
*/
|
|
460
|
+
hideZoom: { type: Boolean },
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Property to define a custom tooltip for the sidebar toggle button
|
|
464
|
+
*/
|
|
465
|
+
sidebarToggleTooltip: { type: String },
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Property to define a custom tooltip for the previous page button
|
|
469
|
+
*/
|
|
470
|
+
previousPageTooltip: { type: String },
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Property to define a custom tooltip for the next page button
|
|
474
|
+
*/
|
|
475
|
+
nextPageTooltip: { type: String },
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
get __zoomItems() {
|
|
480
|
+
return this.__computeZoomItems(
|
|
481
|
+
this.autoZoomOptionLabel,
|
|
482
|
+
this.fitZoomOptionLabel,
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
constructor() {
|
|
487
|
+
super();
|
|
488
|
+
this.__title = "PDF";
|
|
489
|
+
this.zoom = "auto";
|
|
490
|
+
this.currentPage = "1";
|
|
491
|
+
this.__loading = true;
|
|
492
|
+
this.__sidebarOpen = false;
|
|
493
|
+
this.toolbarOnlyFilename = false;
|
|
494
|
+
this.autoZoomOptionLabel = "Automatic zoom";
|
|
495
|
+
this.fitZoomOptionLabel = "Page fit";
|
|
496
|
+
this.customTitle = "";
|
|
497
|
+
this.renderInteractiveForms = true;
|
|
498
|
+
this.hideZoom = false;
|
|
499
|
+
this.sidebarToggleTooltip = "";
|
|
500
|
+
this.previousPageTooltip = "";
|
|
501
|
+
this.nextPageTooltip = "";
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
willUpdate(changedProperties) {
|
|
505
|
+
super.willUpdate(changedProperties);
|
|
506
|
+
|
|
507
|
+
// Compute filename if src changes
|
|
508
|
+
if (changedProperties.has("src")) {
|
|
509
|
+
this.__setFilename(this.src);
|
|
570
510
|
}
|
|
571
511
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
512
|
+
// Compute title before rendering to avoid setting reactive properties during update
|
|
513
|
+
if (
|
|
514
|
+
changedProperties.has("src") ||
|
|
515
|
+
changedProperties.has("customTitle") ||
|
|
516
|
+
changedProperties.has("toolbarOnlyFilename")
|
|
517
|
+
) {
|
|
518
|
+
this.__setTitle(this.__pdfTitle, this.__filename);
|
|
576
519
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
updated(changedProperties) {
|
|
523
|
+
super.updated(changedProperties);
|
|
524
|
+
|
|
525
|
+
// Defer property synchronization to avoid "update during update" warning
|
|
526
|
+
// This ensures these calls happen after the current update cycle completes
|
|
527
|
+
Promise.resolve().then(() => {
|
|
528
|
+
if (changedProperties.has("src")) {
|
|
529
|
+
this.__srcChanged(this.src);
|
|
530
|
+
}
|
|
531
|
+
if (changedProperties.has("zoom")) {
|
|
532
|
+
const zoomSelect = this.querySelector("#zoom");
|
|
533
|
+
if (zoomSelect && zoomSelect.value !== this.zoom) {
|
|
534
|
+
zoomSelect.value = this.zoom;
|
|
591
535
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
536
|
+
this.__zoomChanged(this.zoom);
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
__createToolbarButton() {
|
|
542
|
+
const icon = document.createElement("vaadin-icon");
|
|
543
|
+
icon.setAttribute("slot", "prefix");
|
|
544
|
+
|
|
545
|
+
const tooltip = document.createElement("vaadin-tooltip");
|
|
546
|
+
tooltip.setAttribute("slot", "tooltip");
|
|
547
|
+
|
|
548
|
+
const button = document.createElement("vaadin-button");
|
|
549
|
+
button.classList.add("toolbar-button");
|
|
550
|
+
button.setAttribute("theme", "icon tertiary contrast");
|
|
551
|
+
|
|
552
|
+
button.appendChild(icon);
|
|
553
|
+
button.appendChild(tooltip);
|
|
554
|
+
return button;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Adds toggle button to the toolbar slot named "sidebar-toggle-button-slot".
|
|
559
|
+
*/
|
|
560
|
+
_createSideBarToggleButton() {
|
|
561
|
+
const button = this.__createToolbarButton();
|
|
562
|
+
const icon = button.querySelector("vaadin-icon");
|
|
563
|
+
icon.classList.add("toggle-button-icon");
|
|
564
|
+
button
|
|
565
|
+
.querySelector("vaadin-tooltip")
|
|
566
|
+
.setAttribute("text", this.sidebarToggleTooltip);
|
|
567
|
+
button.setAttribute("slot", "sidebar-toggle-button-slot");
|
|
568
|
+
button.setAttribute("id", "sidebarToggle");
|
|
569
|
+
button.setAttribute("aria-label", "Sidebar toggle");
|
|
570
|
+
button.addEventListener("click", () => {
|
|
571
|
+
this.__toogleSidebar();
|
|
572
|
+
if (this._outerContainer.classList.contains("sidebarOpen")) {
|
|
573
|
+
icon.classList.add("sidebarOpen");
|
|
574
|
+
} else {
|
|
575
|
+
icon.classList.remove("sidebarOpen");
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
this.appendChild(button);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Adds previous page button to the toolbar slot named "previous-page-button-slot".
|
|
583
|
+
*/
|
|
584
|
+
_createPreviousPageButton() {
|
|
585
|
+
const button = this.__createToolbarButton();
|
|
586
|
+
button
|
|
587
|
+
.querySelector("vaadin-icon")
|
|
588
|
+
.classList.add("previous-page-button-icon");
|
|
589
|
+
button
|
|
590
|
+
.querySelector("vaadin-tooltip")
|
|
591
|
+
.setAttribute("text", this.previousPageTooltip);
|
|
592
|
+
button.setAttribute("slot", "previous-page-button-slot");
|
|
593
|
+
button.setAttribute("id", "previousPage");
|
|
594
|
+
button.setAttribute("aria-label", "Previous page");
|
|
595
|
+
button.addEventListener("click", () => this.__previousPage());
|
|
596
|
+
this.appendChild(button);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Adds next page button to the toolbar slot named "next-page-button-slot".
|
|
601
|
+
*/
|
|
602
|
+
_createNextPageButton() {
|
|
603
|
+
const button = this.__createToolbarButton();
|
|
604
|
+
button.querySelector("vaadin-icon").classList.add("next-page-button-icon");
|
|
605
|
+
button
|
|
606
|
+
.querySelector("vaadin-tooltip")
|
|
607
|
+
.setAttribute("text", this.nextPageTooltip);
|
|
608
|
+
button.setAttribute("slot", "next-page-button-slot");
|
|
609
|
+
button.setAttribute("id", "nextPage");
|
|
610
|
+
button.setAttribute("aria-label", "Next page");
|
|
611
|
+
button.addEventListener("click", () => this.__nextPage());
|
|
612
|
+
this.appendChild(button);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Adds current page text field to the toolbar slot named "toolbar-current-page-slot".
|
|
617
|
+
*/
|
|
618
|
+
_createCurrentPageTextField() {
|
|
619
|
+
const textField = document.createElement("vaadin-text-field");
|
|
620
|
+
textField.setAttribute("slot", "toolbar-current-page-slot");
|
|
621
|
+
textField.setAttribute("id", "currentPage");
|
|
622
|
+
textField.classList.add("toolbar-current-page");
|
|
623
|
+
textField.setAttribute("value", this.currentPage);
|
|
624
|
+
textField.addEventListener("change", () => this.__pageChange());
|
|
625
|
+
this.appendChild(textField);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Adds zoom select to the toolbar slot named "toolbar-zoom-slot".
|
|
630
|
+
*/
|
|
631
|
+
_createZoomSelect() {
|
|
632
|
+
const select = document.createElement("vaadin-select");
|
|
633
|
+
select.setAttribute("slot", "toolbar-zoom-slot");
|
|
634
|
+
select.setAttribute("id", "zoom");
|
|
635
|
+
select.classList.add("toolbar-zoom");
|
|
636
|
+
select.setAttribute("value", this.zoom);
|
|
637
|
+
select.items = this.__zoomItems;
|
|
638
|
+
select.addEventListener("value-changed", (e) => {
|
|
639
|
+
if (e.detail.value !== this.zoom) {
|
|
640
|
+
this.__zoomChanged(e.detail.value);
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
if (this.hideZoom) {
|
|
644
|
+
select.classList.add("hide-zoom");
|
|
645
|
+
} else {
|
|
646
|
+
select.classList.remove("hide-zoom");
|
|
600
647
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
linkService: this.__linkService,
|
|
633
|
-
renderingQueue: pdfRenderingQueue,
|
|
634
|
-
l10n: l10n,
|
|
635
|
-
renderInteractiveForms: this.renderInteractiveForms
|
|
636
|
-
});
|
|
637
|
-
|
|
638
|
-
this.__linkService.setViewer(this.__viewer);
|
|
639
|
-
pdfRenderingQueue.setViewer(this.__viewer);
|
|
640
|
-
|
|
641
|
-
// thumbnailViewer
|
|
642
|
-
this.__thumbnailViewer = new pdfjsThumbnailViewer.PDFThumbnailViewer({
|
|
643
|
-
container: this.$.thumbnailView,
|
|
644
|
-
eventBus: eventBus,
|
|
645
|
-
linkService: this.__linkService,
|
|
646
|
-
renderingQueue: pdfRenderingQueue,
|
|
647
|
-
l10n: l10n
|
|
648
|
-
})
|
|
649
|
-
|
|
650
|
-
pdfRenderingQueue.setThumbnailViewer(this.__thumbnailViewer);
|
|
651
|
-
|
|
652
|
-
// listeners
|
|
653
|
-
eventBus.on('pagesinit', () => {
|
|
654
|
-
this.__viewer.currentScaleValue = this.zoom;
|
|
655
|
-
this.__loading = false;
|
|
656
|
-
this.__updateThumbnailViewer();
|
|
657
|
-
if(this.__sidebarOpen){
|
|
658
|
-
this.__openSidebar();
|
|
659
|
-
} else {
|
|
660
|
-
this.__closeSidebar();
|
|
661
|
-
}
|
|
662
|
-
this.__viewer.currentPage = this.setCurrentPage();
|
|
663
|
-
});
|
|
664
|
-
eventBus.on('pagechanging', (event) => {
|
|
665
|
-
this.__updateCurrentPageValue(event.pageNumber);
|
|
666
|
-
this.__updatePageNumberStates();
|
|
667
|
-
if(this.__thumbnailViewer && this.__thumbnailViewer.renderingQueue.isThumbnailViewEnabled){
|
|
668
|
-
this.__thumbnailViewer.scrollThumbnailIntoView(this.currentPage);
|
|
669
|
-
}
|
|
670
|
-
this.querySelector('#currentPage').value = this.currentPage;
|
|
671
|
-
});
|
|
672
|
-
|
|
673
|
-
this.__resizeObserver = new ResizeObserver(() => {
|
|
674
|
-
requestAnimationFrame(() => this.__recalculateSizes());
|
|
675
|
-
});
|
|
676
|
-
|
|
677
|
-
this.__resizeObserver.observe(this);
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
connectedCallback() {
|
|
681
|
-
super.connectedCallback();
|
|
682
|
-
this.__recalculateSizes();
|
|
648
|
+
this.appendChild(select);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
__computeZoomItems(autoZoomOptionLabel, fitZoomOptionLabel) {
|
|
652
|
+
return [
|
|
653
|
+
{ label: autoZoomOptionLabel, value: "auto" },
|
|
654
|
+
{ label: fitZoomOptionLabel, value: "page-fit" },
|
|
655
|
+
{ label: "50%", value: "0.5" },
|
|
656
|
+
{ label: "75%", value: "0.75" },
|
|
657
|
+
{ label: "100%", value: "1.0" },
|
|
658
|
+
{ label: "125%", value: "1.25" },
|
|
659
|
+
{ label: "150%", value: "1.5" },
|
|
660
|
+
{ label: "200%", value: "2.0" },
|
|
661
|
+
{ label: "300%", value: "3.0" },
|
|
662
|
+
{ label: "400%", value: "4.0" },
|
|
663
|
+
];
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
__setTitle(pdfTitle, filename) {
|
|
667
|
+
if (this.customTitle) {
|
|
668
|
+
this.__title = this.customTitle;
|
|
669
|
+
} else if (this.__viewer && this.toolbarOnlyFilename && filename) {
|
|
670
|
+
this.__title = filename;
|
|
671
|
+
} else if (pdfTitle && filename) {
|
|
672
|
+
this.__title = pdfTitle + " - " + filename;
|
|
673
|
+
} else if (pdfTitle) {
|
|
674
|
+
this.__title = pdfTitle;
|
|
675
|
+
} else if (filename) {
|
|
676
|
+
this.__title = filename;
|
|
677
|
+
} else {
|
|
678
|
+
this.__title = "PDF";
|
|
683
679
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
_addToolbarButtons() {
|
|
683
|
+
this._createSideBarToggleButton();
|
|
684
|
+
this._createZoomSelect();
|
|
685
|
+
this._createCurrentPageTextField();
|
|
686
|
+
this._createPreviousPageButton();
|
|
687
|
+
this._createNextPageButton();
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
firstUpdated() {
|
|
691
|
+
this._toolbar = this.shadowRoot.querySelector("#toolbar");
|
|
692
|
+
this._viewerContainer = this.shadowRoot.querySelector("#viewerContainer");
|
|
693
|
+
this._outerContainer = this.shadowRoot.querySelector("#outerContainer");
|
|
694
|
+
this._viewer = this.shadowRoot.querySelector("#viewer");
|
|
695
|
+
this._thumbnailView = this.shadowRoot.querySelector("#thumbnailView");
|
|
696
|
+
|
|
697
|
+
this._addToolbarButtons();
|
|
698
|
+
|
|
699
|
+
this._viewerContainer.addEventListener(
|
|
700
|
+
"focus",
|
|
701
|
+
(e) => this.__setFocused(true),
|
|
702
|
+
true,
|
|
703
|
+
);
|
|
704
|
+
this._viewerContainer.addEventListener(
|
|
705
|
+
"blur",
|
|
706
|
+
(e) => this.__setFocused(false),
|
|
707
|
+
true,
|
|
708
|
+
);
|
|
709
|
+
this._viewerContainer.addEventListener("mousedown", (e) => {
|
|
710
|
+
this._mousedown = true;
|
|
711
|
+
const mouseUpListener = () => {
|
|
712
|
+
this._mousedown = false;
|
|
713
|
+
document.removeEventListener("mouseup", mouseUpListener);
|
|
714
|
+
};
|
|
715
|
+
document.addEventListener("mouseup", mouseUpListener);
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
// options
|
|
719
|
+
const eventBus = new pdfUtils.EventBus();
|
|
720
|
+
|
|
721
|
+
// Defer initialization of reactive controller properties to avoid immediate update request
|
|
722
|
+
// that triggers "update scheduled after update" warning.
|
|
723
|
+
Promise.resolve().then(() => {
|
|
724
|
+
this.__linkService = new pdfjsLinkService.PDFLinkService({
|
|
725
|
+
eventBus,
|
|
726
|
+
});
|
|
727
|
+
var pdfRenderingQueue = new pdfjsRenderingQueue.PDFRenderingQueue();
|
|
728
|
+
var l10n = NullL10n;
|
|
729
|
+
|
|
730
|
+
// pdfViewer
|
|
731
|
+
this.__viewer = new pdfjsViewer.PDFViewer({
|
|
732
|
+
container: this._viewerContainer,
|
|
733
|
+
textLayerMode: 2,
|
|
734
|
+
viewer: this._viewer,
|
|
735
|
+
eventBus: eventBus,
|
|
736
|
+
linkService: this.__linkService,
|
|
737
|
+
renderingQueue: pdfRenderingQueue,
|
|
738
|
+
l10n: l10n,
|
|
739
|
+
renderInteractiveForms: this.renderInteractiveForms,
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
this.__linkService.setViewer(this.__viewer);
|
|
743
|
+
pdfRenderingQueue.setViewer(this.__viewer);
|
|
744
|
+
|
|
745
|
+
// thumbnailViewer
|
|
746
|
+
this.__thumbnailViewer = new pdfjsThumbnailViewer.PDFThumbnailViewer({
|
|
747
|
+
container: this._thumbnailView,
|
|
748
|
+
eventBus: eventBus,
|
|
749
|
+
linkService: this.__linkService,
|
|
750
|
+
renderingQueue: pdfRenderingQueue,
|
|
751
|
+
l10n: l10n,
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
pdfRenderingQueue.setThumbnailViewer(this.__thumbnailViewer);
|
|
755
|
+
|
|
756
|
+
// Initialize listeners after viewer creation
|
|
757
|
+
this.__initListeners(eventBus);
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
__initListeners(eventBus) {
|
|
762
|
+
// listeners
|
|
763
|
+
eventBus.on("pagesinit", () => {
|
|
764
|
+
this.__viewer.currentScaleValue = this.zoom;
|
|
765
|
+
this.__loading = false;
|
|
766
|
+
this.__updateThumbnailViewer();
|
|
767
|
+
if (this.__sidebarOpen) {
|
|
768
|
+
this.__openSidebar();
|
|
769
|
+
} else {
|
|
770
|
+
this.__closeSidebar();
|
|
771
|
+
}
|
|
772
|
+
this.__viewer.currentPage = this.setCurrentPage();
|
|
773
|
+
});
|
|
774
|
+
eventBus.on("pagechanging", (event) => {
|
|
775
|
+
this.__updateCurrentPageValue(event.pageNumber);
|
|
776
|
+
this.__updatePageNumberStates();
|
|
777
|
+
if (
|
|
778
|
+
this.__thumbnailViewer &&
|
|
779
|
+
this.__thumbnailViewer.renderingQueue.isThumbnailViewEnabled
|
|
780
|
+
) {
|
|
781
|
+
this.__thumbnailViewer.scrollThumbnailIntoView(this.currentPage);
|
|
782
|
+
}
|
|
783
|
+
this.querySelector("#currentPage").value = this.currentPage;
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
__updateCurrentPageValue(pageNumber) {
|
|
788
|
+
this.currentPage = "" + pageNumber;
|
|
789
|
+
this.dispatchEvent(new CustomEvent("currentPage-changed"));
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
__setFocused(focused) {
|
|
793
|
+
if (focused) {
|
|
794
|
+
this._viewerContainer.setAttribute("focused", "");
|
|
795
|
+
if (!this._mousedown) {
|
|
796
|
+
this._viewerContainer.setAttribute("focus-ring", "");
|
|
797
|
+
}
|
|
798
|
+
} else {
|
|
799
|
+
this._viewerContainer.removeAttribute("focused");
|
|
800
|
+
this._viewerContainer.removeAttribute("focus-ring");
|
|
688
801
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
__open(src) {
|
|
805
|
+
// Is there already a document loaded?
|
|
806
|
+
if (this.__document) {
|
|
807
|
+
// We need to close the current document
|
|
808
|
+
return this.__close().then(() => {
|
|
809
|
+
// and start over with opening the new one
|
|
810
|
+
return this.__open(src);
|
|
811
|
+
});
|
|
698
812
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
if (!this._mousedown) {
|
|
703
|
-
this.$.viewerContainer.setAttribute('focus-ring', '');
|
|
704
|
-
}
|
|
705
|
-
} else {
|
|
706
|
-
this.$.viewerContainer.removeAttribute('focused');
|
|
707
|
-
this.$.viewerContainer.removeAttribute('focus-ring');
|
|
708
|
-
}
|
|
813
|
+
if (!src) {
|
|
814
|
+
// No file given, show nothing.
|
|
815
|
+
return;
|
|
709
816
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
this.__linkService.setDocument(pdfDocument);
|
|
731
|
-
|
|
732
|
-
this.$.toolbar.classList.add('ready');
|
|
733
|
-
this.__totalPages = pdfDocument.numPages;
|
|
734
|
-
this.__updatePageNumberStates();
|
|
735
|
-
this.__setPdfTitleFromMetadata(pdfDocument).then(() => {
|
|
736
|
-
this.dispatchEvent(new CustomEvent('document-loaded', {
|
|
737
|
-
detail: {
|
|
738
|
-
document: pdfDocument
|
|
739
|
-
}
|
|
740
|
-
}));
|
|
741
|
-
});
|
|
742
|
-
}, function (exception) {
|
|
743
|
-
console.error(exception && exception.message);
|
|
817
|
+
this.__setFilename(src);
|
|
818
|
+
this.__document = pdfjsLib.getDocument(new URL(src, document.baseURI).href);
|
|
819
|
+
return this.__document.promise.then(
|
|
820
|
+
(pdfDocument) => {
|
|
821
|
+
// Document loaded, specifying document for the viewer.
|
|
822
|
+
this.__thumbnailViewer.setDocument(pdfDocument);
|
|
823
|
+
this.__viewer.setDocument(pdfDocument);
|
|
824
|
+
this.__linkService.setDocument(pdfDocument);
|
|
825
|
+
|
|
826
|
+
this._toolbar.classList.add("ready");
|
|
827
|
+
this.__totalPages = pdfDocument.numPages;
|
|
828
|
+
this.__updatePageNumberStates();
|
|
829
|
+
this.__setPdfTitleFromMetadata(pdfDocument).then(() => {
|
|
830
|
+
this.dispatchEvent(
|
|
831
|
+
new CustomEvent("document-loaded", {
|
|
832
|
+
detail: {
|
|
833
|
+
document: pdfDocument,
|
|
834
|
+
},
|
|
835
|
+
}),
|
|
836
|
+
);
|
|
744
837
|
});
|
|
838
|
+
},
|
|
839
|
+
function (exception) {
|
|
840
|
+
console.error(exception && exception.message);
|
|
841
|
+
},
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
__srcChanged(newSrc) {
|
|
846
|
+
this.__open(newSrc);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* Closes opened PDF document.
|
|
851
|
+
* @returns {Promise} - Returns the promise, which is resolved when all
|
|
852
|
+
* destruction is completed.
|
|
853
|
+
*/
|
|
854
|
+
__close() {
|
|
855
|
+
this._toolbar.classList.remove("ready");
|
|
856
|
+
this.__filename = "PDF";
|
|
857
|
+
if (!this.__document) {
|
|
858
|
+
return Promise.resolve();
|
|
745
859
|
}
|
|
746
860
|
|
|
747
|
-
|
|
748
|
-
|
|
861
|
+
var promise = this.__document.destroy();
|
|
862
|
+
if (this.__document) {
|
|
863
|
+
this.__document = null;
|
|
864
|
+
this.__viewer.setDocument(null);
|
|
865
|
+
this.__thumbnailViewer.setDocument(null);
|
|
866
|
+
this.__linkService.setDocument(null);
|
|
749
867
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
return Promise.resolve();
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
var promise = this.__document.destroy();
|
|
764
|
-
if (this.__document) {
|
|
765
|
-
this.__document = null;
|
|
766
|
-
this.__viewer.setDocument(null);
|
|
767
|
-
this.__thumbnailViewer.setDocument(null);
|
|
768
|
-
this.__linkService.setDocument(null);
|
|
769
|
-
}
|
|
770
|
-
return promise;
|
|
868
|
+
return promise;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
__setFilename(src) {
|
|
872
|
+
let filename = pdfjsLib.getFilenameFromUrl(src) || src;
|
|
873
|
+
try {
|
|
874
|
+
filename = decodeURIComponent(filename);
|
|
875
|
+
} catch (e) {
|
|
876
|
+
// decodeURIComponent may throw URIError,
|
|
877
|
+
// fall back to using the unprocessed url in that case
|
|
771
878
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
879
|
+
this.__filename = filename;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
__setPdfTitleFromMetadata(pdfDocument) {
|
|
883
|
+
return pdfDocument.getMetadata().then((data) => {
|
|
884
|
+
let pdfTitle;
|
|
885
|
+
const metadata = data.metadata;
|
|
886
|
+
if (metadata && metadata.has("dc:title")) {
|
|
887
|
+
const title = metadata.get("dc:title");
|
|
888
|
+
// Ghostscript sometimes returns 'Untitled', so prevent setting the
|
|
889
|
+
// title to 'Untitled'.
|
|
890
|
+
if (title !== "Untitled") {
|
|
891
|
+
pdfTitle = title;
|
|
780
892
|
}
|
|
781
|
-
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
const info = data.info;
|
|
896
|
+
if (!pdfTitle && info && info["Title"]) {
|
|
897
|
+
pdfTitle = info["Title"];
|
|
898
|
+
}
|
|
899
|
+
this.__pdfTitle = pdfTitle;
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
__updatePageNumberStates() {
|
|
904
|
+
this.querySelector("#previousPage").disabled = this.currentPage === "1";
|
|
905
|
+
this.querySelector("#nextPage").disabled =
|
|
906
|
+
this.currentPage === "" + this.__totalPages;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
__zoomChanged(value) {
|
|
910
|
+
if (!this.__viewer || this.__loading) {
|
|
911
|
+
return;
|
|
782
912
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
}
|
|
801
|
-
this.__pdfTitle = pdfTitle;
|
|
802
|
-
});
|
|
913
|
+
// This logs error 'TextLayerBuilder._bindEvents: `this.cancel()` should have
|
|
914
|
+
// been called when the page was reset, or rendering cancelled.'
|
|
915
|
+
//
|
|
916
|
+
// There is a problem deep inside pdfjs viewer that causes an console.error()
|
|
917
|
+
// to be logged, but the component still works. It seems to be due to
|
|
918
|
+
// webcomponents/shadow dom messing with
|
|
919
|
+
// TODO: Fix the issue so that we get rid of the error in log
|
|
920
|
+
this.__viewer.currentScaleValue = value;
|
|
921
|
+
this.__viewer.forceRendering();
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
__pageChange(event) {
|
|
925
|
+
const currentPageValue = this.querySelector("#currentPage").value;
|
|
926
|
+
let pageNumber = parseInt(currentPageValue, 10);
|
|
927
|
+
if (isNaN(pageNumber)) {
|
|
928
|
+
pageNumber = this.__viewer.currentPageNumber;
|
|
929
|
+
this.querySelector("#currentPage").value = "" + pageNumber;
|
|
803
930
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
this.querySelector('#previousPage').disabled = (this.currentPage === "1");
|
|
807
|
-
this.querySelector('#nextPage').disabled = (this.currentPage === "" + this.__totalPages);
|
|
931
|
+
if (pageNumber < 1) {
|
|
932
|
+
pageNumber = 1;
|
|
808
933
|
}
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
if (!this.__viewer || this.__loading) {
|
|
812
|
-
return;
|
|
813
|
-
}
|
|
814
|
-
// This logs error 'TextLayerBuilder._bindEvents: `this.cancel()` should have
|
|
815
|
-
// been called when the page was reset, or rendering cancelled.'
|
|
816
|
-
//
|
|
817
|
-
// There is a problem deep inside pdfjs viewer that causes an console.error()
|
|
818
|
-
// to be logged, but the component still works. It seems to be due to
|
|
819
|
-
// webcomponents/shadow dom messing with
|
|
820
|
-
// TODO: Fix the issue so that we get rid of the error in log
|
|
821
|
-
this.__viewer.currentScaleValue = value;
|
|
822
|
-
this.__viewer.forceRendering();
|
|
934
|
+
if (pageNumber > this.__totalPages) {
|
|
935
|
+
pageNumber = this.__totalPages;
|
|
823
936
|
}
|
|
937
|
+
this.__viewer.currentPageNumber = pageNumber;
|
|
938
|
+
}
|
|
824
939
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
if (isNaN(pageNumber)) {
|
|
829
|
-
pageNumber = this.__viewer.currentPageNumber;
|
|
830
|
-
this.querySelector('#currentPage').value = "" + pageNumber;
|
|
831
|
-
}
|
|
832
|
-
if (pageNumber < 1) {
|
|
833
|
-
pageNumber = 1;
|
|
834
|
-
}
|
|
835
|
-
if (pageNumber > this.__totalPages) {
|
|
836
|
-
pageNumber = this.__totalPages;
|
|
837
|
-
}
|
|
838
|
-
this.__viewer.currentPageNumber = pageNumber;
|
|
940
|
+
setCurrentPage(value) {
|
|
941
|
+
if (value != undefined) {
|
|
942
|
+
this.querySelector("#currentPage").value = "" + value;
|
|
839
943
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
944
|
+
this.__pageChange();
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
_getPage() {
|
|
948
|
+
return this.__viewer.currentPageNumber;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
__previousPage() {
|
|
952
|
+
this.__viewer.currentPageNumber--;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
__nextPage() {
|
|
956
|
+
this.__viewer.currentPageNumber++;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
__toogleSidebar() {
|
|
960
|
+
if (this._outerContainer.classList.length == 0) {
|
|
961
|
+
this.__openSidebar();
|
|
962
|
+
} else {
|
|
963
|
+
this.__closeSidebar();
|
|
846
964
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
__openSidebar() {
|
|
968
|
+
if (!this.__thumbnailViewer || this.__loading) {
|
|
969
|
+
this.__sidebarOpen = true;
|
|
970
|
+
} else {
|
|
971
|
+
this.__thumbnailViewer.renderingQueue.isThumbnailViewEnabled = true;
|
|
972
|
+
this.__updateThumbnailViewer();
|
|
973
|
+
this._outerContainer.classList.add("sidebarOpen");
|
|
850
974
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
__closeSidebar() {
|
|
978
|
+
if (!this.__thumbnailViewer || this.__loading) {
|
|
979
|
+
this.__sidebarOpen = false;
|
|
980
|
+
} else {
|
|
981
|
+
this.__thumbnailViewer.renderingQueue.isThumbnailViewEnabled = false;
|
|
982
|
+
this._outerContainer.classList.remove("sidebarOpen");
|
|
854
983
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
__updateThumbnailViewer() {
|
|
987
|
+
const pagesCount = this.__totalPages;
|
|
988
|
+
for (let i = 0; i < pagesCount; i++) {
|
|
989
|
+
const pageView = this.__viewer.getPageView(i);
|
|
990
|
+
if (
|
|
991
|
+
pageView.renderingState === pdfjsRenderingQueue.RenderingStates.FINISHED
|
|
992
|
+
) {
|
|
993
|
+
const thumbnailView = this.__thumbnailViewer.getThumbnail(i);
|
|
994
|
+
thumbnailView.setImage(pageView);
|
|
995
|
+
} else {
|
|
996
|
+
this.__thumbnailViewer.renderingQueue.renderHighestPriority();
|
|
997
|
+
}
|
|
866
998
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
999
|
+
var component = this;
|
|
1000
|
+
for (let i = 0; i < this.__thumbnailViewer._thumbnails.length; i++) {
|
|
1001
|
+
const thumbnailView = this.__thumbnailViewer.getThumbnail(i);
|
|
1002
|
+
thumbnailView.anchor.onclick = function () {
|
|
1003
|
+
const id = thumbnailView.id;
|
|
1004
|
+
thumbnailView.linkService.goToPage(id);
|
|
1005
|
+
component.dispatchEvent(
|
|
1006
|
+
new CustomEvent("thumbnail-clicked", {
|
|
1007
|
+
detail: {
|
|
1008
|
+
source: component,
|
|
1009
|
+
pageNumber: id,
|
|
1010
|
+
},
|
|
1011
|
+
}),
|
|
1012
|
+
);
|
|
1013
|
+
return false;
|
|
1014
|
+
};
|
|
876
1015
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
this.__thumbnailViewer.renderingQueue.isThumbnailViewEnabled = false;
|
|
883
|
-
this.$.outerContainer.classList.remove('sidebarOpen');
|
|
884
|
-
}
|
|
1016
|
+
if (
|
|
1017
|
+
this.__thumbnailViewer &&
|
|
1018
|
+
this.__thumbnailViewer.renderingQueue.isThumbnailViewEnabled
|
|
1019
|
+
) {
|
|
1020
|
+
this.__thumbnailViewer.scrollThumbnailIntoView(this.currentPage);
|
|
885
1021
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
this.__thumbnailViewer.renderingQueue.renderHighestPriority();
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
var component = this;
|
|
899
|
-
for (let i = 0; i < this.__thumbnailViewer._thumbnails.length; i++) {
|
|
900
|
-
const thumbnailView = this.__thumbnailViewer.getThumbnail(i);
|
|
901
|
-
thumbnailView.anchor.onclick = function () {
|
|
902
|
-
const id = thumbnailView.id;
|
|
903
|
-
thumbnailView.linkService.goToPage(id);
|
|
904
|
-
component.dispatchEvent(new CustomEvent('thumbnail-clicked', {
|
|
905
|
-
detail: {
|
|
906
|
-
source: component,
|
|
907
|
-
pageNumber: id
|
|
908
|
-
}
|
|
909
|
-
}));
|
|
910
|
-
return false;
|
|
911
|
-
};
|
|
912
|
-
}
|
|
913
|
-
if(this.__thumbnailViewer && this.__thumbnailViewer.renderingQueue.isThumbnailViewEnabled){
|
|
914
|
-
this.__thumbnailViewer.scrollThumbnailIntoView(this.currentPage);
|
|
915
|
-
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
_onResize() {
|
|
1025
|
+
if (this.offsetWidth < 600) {
|
|
1026
|
+
this.classList.add("small-size");
|
|
1027
|
+
this._toolbar.classList.add("small-size");
|
|
1028
|
+
} else {
|
|
1029
|
+
this.classList.remove("small-size");
|
|
1030
|
+
this._toolbar.classList.remove("small-size");
|
|
916
1031
|
}
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* Rotates document clockwise.
|
|
1036
|
+
*/
|
|
1037
|
+
rotateCw() {
|
|
1038
|
+
let delta = 90;
|
|
1039
|
+
this.__viewer.pagesRotation += delta;
|
|
1040
|
+
this.__viewer.forceRendering();
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* Rotates document counterclockwise.
|
|
1045
|
+
*/
|
|
1046
|
+
rotateCcw() {
|
|
1047
|
+
let delta = -90;
|
|
1048
|
+
this.__viewer.pagesRotation += delta;
|
|
1049
|
+
this.__viewer.forceRendering();
|
|
1050
|
+
}
|
|
917
1051
|
}
|
|
918
1052
|
|
|
919
1053
|
customElements.define(PdfViewerElement.is, PdfViewerElement);
|
|
@@ -922,6 +1056,3 @@ customElements.define(PdfViewerElement.is, PdfViewerElement);
|
|
|
922
1056
|
* @namespace Vaadin
|
|
923
1057
|
*/
|
|
924
1058
|
window.Vaadin.PdfViewerElement = PdfViewerElement;
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|