@teipublisher/pb-components 2.25.5 → 2.25.6

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.
Files changed (128) hide show
  1. package/.github/workflows/main.yml +3 -3
  2. package/.github/workflows/node.js.yml +3 -3
  3. package/.github/workflows/release.js.yml +3 -3
  4. package/CHANGELOG.md +8 -0
  5. package/Dockerfile +78 -70
  6. package/css/components.css +5 -5
  7. package/dist/demo/pb-drawer2.html +1 -1
  8. package/dist/demo/pb-leaflet-map.html +1 -1
  9. package/dist/demo/pb-repeat.html +1 -3
  10. package/dist/demo/pb-view3.html +1 -1
  11. package/dist/{paper-icon-button-0fb125c4.js → paper-icon-button-72125e67.js} +1 -1
  12. package/dist/pb-code-editor.js +25 -20
  13. package/dist/pb-component-docs.js +58 -54
  14. package/dist/pb-components-bundle.js +1827 -1520
  15. package/dist/pb-edit-app.js +167 -107
  16. package/dist/pb-elements.json +54 -54
  17. package/dist/{pb-i18n-0611135a.js → pb-i18n-4cc00bfe.js} +1 -1
  18. package/dist/pb-leaflet-map.js +23 -23
  19. package/dist/pb-mei.js +56 -41
  20. package/dist/{pb-mixin-b1caa22e.js → pb-mixin-886ece32.js} +1 -1
  21. package/dist/pb-odd-editor.js +925 -758
  22. package/dist/pb-tify.js +2 -2
  23. package/dist/{vaadin-element-mixin-859a0132.js → vaadin-element-mixin-ad07ba25.js} +88 -61
  24. package/gh-pages.js +5 -3
  25. package/package.json +2 -2
  26. package/pb-elements.json +54 -54
  27. package/src/assets/components.css +5 -5
  28. package/src/authority/airtable.js +20 -21
  29. package/src/authority/anton.js +129 -129
  30. package/src/authority/custom.js +23 -21
  31. package/src/authority/geonames.js +38 -32
  32. package/src/authority/gnd.js +47 -42
  33. package/src/authority/kbga.js +137 -134
  34. package/src/authority/metagrid.js +44 -46
  35. package/src/authority/reconciliation.js +66 -67
  36. package/src/authority/registry.js +4 -4
  37. package/src/docs/pb-component-docs.js +2 -2
  38. package/src/docs/pb-component-view.js +5 -5
  39. package/src/docs/pb-components-list.js +2 -2
  40. package/src/docs/pb-demo-snippet.js +2 -2
  41. package/src/dts-client.js +299 -297
  42. package/src/dts-select-endpoint.js +90 -82
  43. package/src/parse-date-service.js +184 -135
  44. package/src/pb-ajax.js +171 -167
  45. package/src/pb-authority-lookup.js +96 -81
  46. package/src/pb-autocomplete.js +292 -280
  47. package/src/pb-blacklab-highlight.js +264 -259
  48. package/src/pb-blacklab-results.js +236 -221
  49. package/src/pb-browse-docs.js +540 -475
  50. package/src/pb-browse.js +68 -65
  51. package/src/pb-clipboard.js +79 -76
  52. package/src/pb-code-editor.js +110 -102
  53. package/src/pb-code-highlight.js +209 -204
  54. package/src/pb-codepen.js +79 -72
  55. package/src/pb-collapse.js +149 -146
  56. package/src/pb-combo-box.js +190 -190
  57. package/src/pb-components-bundle.js +1 -1
  58. package/src/pb-custom-form.js +150 -149
  59. package/src/pb-document.js +89 -90
  60. package/src/pb-download.js +208 -195
  61. package/src/pb-drawer.js +145 -148
  62. package/src/pb-edit-app.js +301 -229
  63. package/src/pb-edit-xml.js +99 -96
  64. package/src/pb-events.js +114 -107
  65. package/src/pb-facs-link.js +104 -102
  66. package/src/pb-facsimile.js +411 -413
  67. package/src/pb-formula.js +151 -153
  68. package/src/pb-geolocation.js +129 -131
  69. package/src/pb-grid-action.js +53 -56
  70. package/src/pb-grid.js +231 -228
  71. package/src/pb-highlight.js +140 -140
  72. package/src/pb-hotkeys.js +40 -42
  73. package/src/pb-i18n.js +101 -104
  74. package/src/pb-image-strip.js +84 -78
  75. package/src/pb-lang.js +83 -70
  76. package/src/pb-leaflet-map.js +488 -485
  77. package/src/pb-link.js +126 -124
  78. package/src/pb-load.js +431 -426
  79. package/src/pb-login.js +275 -254
  80. package/src/pb-manage-odds.js +364 -318
  81. package/src/pb-map-icon.js +89 -89
  82. package/src/pb-map-layer.js +85 -85
  83. package/src/pb-markdown.js +90 -99
  84. package/src/pb-media-query.js +74 -72
  85. package/src/pb-mei.js +306 -295
  86. package/src/pb-message.js +143 -130
  87. package/src/pb-mixin.js +269 -264
  88. package/src/pb-navigation.js +80 -82
  89. package/src/pb-observable.js +38 -38
  90. package/src/pb-odd-editor.js +1056 -958
  91. package/src/pb-odd-elementspec-editor.js +348 -297
  92. package/src/pb-odd-model-editor.js +1058 -898
  93. package/src/pb-odd-parameter-editor.js +200 -178
  94. package/src/pb-odd-rendition-editor.js +136 -124
  95. package/src/pb-page.js +432 -422
  96. package/src/pb-paginate.js +202 -190
  97. package/src/pb-panel.js +191 -179
  98. package/src/pb-popover-themes.js +7 -5
  99. package/src/pb-popover.js +296 -287
  100. package/src/pb-print-preview.js +127 -127
  101. package/src/pb-progress.js +49 -49
  102. package/src/pb-repeat.js +105 -104
  103. package/src/pb-restricted.js +84 -77
  104. package/src/pb-search.js +238 -221
  105. package/src/pb-select-feature.js +127 -120
  106. package/src/pb-select-odd.js +132 -124
  107. package/src/pb-select-template.js +89 -78
  108. package/src/pb-select.js +251 -227
  109. package/src/pb-split-list.js +179 -174
  110. package/src/pb-svg.js +80 -79
  111. package/src/pb-table-column.js +54 -54
  112. package/src/pb-table-grid.js +221 -203
  113. package/src/pb-tabs.js +61 -63
  114. package/src/pb-tify.js +154 -154
  115. package/src/pb-timeline.js +271 -229
  116. package/src/pb-toggle-feature.js +198 -185
  117. package/src/pb-upload.js +184 -174
  118. package/src/pb-version.js +30 -30
  119. package/src/pb-view-annotate.js +132 -98
  120. package/src/pb-view.js +1282 -1263
  121. package/src/pb-zoom.js +40 -40
  122. package/src/polymer-hack.js +1 -1
  123. package/src/search-result-service.js +256 -223
  124. package/src/seed-element.js +13 -20
  125. package/src/settings.js +4 -4
  126. package/src/theming.js +91 -91
  127. package/src/urls.js +289 -289
  128. package/src/utils.js +53 -51
@@ -1,5 +1,5 @@
1
1
  import { LitElement, html, css } from 'lit-element';
2
- import "@lrnwebcomponents/es-global-bridge";
2
+ import '@lrnwebcomponents/es-global-bridge';
3
3
  import { pbMixin } from './pb-mixin.js';
4
4
  import { resolveURL } from './utils.js';
5
5
 
@@ -24,445 +24,443 @@ import { resolveURL } from './utils.js';
24
24
  * @slot after - use for content which should be shown below the facsimile viewer
25
25
  */
26
26
  export class PbFacsimile extends pbMixin(LitElement) {
27
- static get properties() {
28
- return {
29
- ...super.properties,
30
- /**
31
- * Set to false to prevent the appearance of the default navigation controls.
32
- * Note that if set to false, the customs buttons set by the options
33
- * zoomInButton, zoomOutButton etc, are rendered inactive.
34
- */
35
- showNavigationControl: {
36
- type: Boolean,
37
- attribute: 'show-navigation-control'
38
- },
39
- // Set to true to make the navigator minimap appear.
40
- showNavigator: {
41
- type: Boolean,
42
- attribute: 'show-navigator'
43
- },
44
-
45
- /** If true then the 'previous" and 'next' button is displayed switch between images. */
46
- showSequenceMode: {
47
- type: Boolean,
48
- attribute: 'show-sequence-control'
49
- },
50
-
51
- /** If true then the 'Go home' button is displayed to go back to the original zoom and pan. */
52
- showHomeControl: {
53
- type: Boolean,
54
- attribute: 'show-home-control'
55
- },
56
- /** If true then the 'Toggle full page' button is displayed to switch between full page and normal mode. */
57
- showFullPageControl: {
58
- type: Boolean,
59
- attribute: 'show-full-page-control'
60
- },
61
- /**
62
- * if true shows a 'download' button
63
- */
64
- showDownloadButton:{
65
- type: Boolean,
66
- attribute: 'show-download-control'
67
- },
68
- /**
69
- * Default zoom between: set to 0 to adjust to viewer size.
70
- */
71
- defaultZoomLevel: {
72
- type: Number,
73
- attribute: 'default-zoom-level'
74
- },
75
- /**
76
- * If true then the rotate left/right controls will be displayed
77
- * as part of the standard controls. This is also subject to the
78
- * browser support for rotate (e.g. viewer.drawer.canRotate()).
79
- */
80
- showRotationControl: {
81
- type: Boolean,
82
- attribute: 'show-rotation-control'
83
- },
84
- // Constrain during pan
85
- constrainDuringPan: {
86
- type: Boolean,
87
- attribute: 'contrain-during-pan'
88
- },
89
- /**
90
- * The percentage ( as a number from 0 to 1 ) of the source image
91
- * which must be kept within the viewport.
92
- * If the image is dragged beyond that limit, it will 'bounce'
93
- * back until the minimum visibility ratio is achieved.
94
- * Setting this to 0 and wrapHorizontal ( or wrapVertical )
95
- * to true will provide the effect of an infinitely scrolling viewport.
96
- */
97
- visibilityRatio: {
98
- type: Number,
99
- attribute: 'visibility-ratio'
100
- },
101
- /**
102
- * If set, thumbnails of all images are shown in a reference strip at the
103
- * bottom of the viewer.
104
- */
105
- referenceStrip: {
106
- type: Boolean,
107
- attribute: 'reference-strip'
108
- },
109
- /**
110
- * Size ratio for the reference strip thumbnails. 0.2 by default.
111
- */
112
- referenceStripSizeRatio: {
113
- type: Number,
114
- attribute: 'reference-strip-size-ratio'
115
- },
116
- /**
117
- * Type of the source of the image to display: either 'iiif' or 'image'
118
- * (for simple image links not served via IIIF).
119
- */
120
- type: {
121
- type: String
122
- },
123
- baseUri: {
124
- type: String,
125
- attribute: 'base-uri'
126
- },
127
- /**
128
- * Path pointing to the location of openseadragon user interface images.
129
- */
130
- prefixUrl: {
131
- type: String,
132
- attribute: 'prefix-url'
133
- },
134
- /**
135
- * Array of facsimiles
136
- *
137
- */
138
- facsimiles: {
139
- type: Array
140
- },
141
- /**
142
- * Will be true if images were loaded for display, false if there are no images
143
- * to show.
144
- */
145
- loaded: {
146
- type: Boolean,
147
- reflect: true
148
- },
149
- /**
150
- * CORS (Cross-Origin Resource Sharing) policy - wraps the OSD Viewer option -
151
- * only sensible values are 'anonymous' (default) or 'use-credentials'.
152
- */
153
- crossOriginPolicy:{
154
- type: String,
155
- attribute: 'cors'
156
- }
157
- };
27
+ static get properties() {
28
+ return {
29
+ ...super.properties,
30
+ /**
31
+ * Set to false to prevent the appearance of the default navigation controls.
32
+ * Note that if set to false, the customs buttons set by the options
33
+ * zoomInButton, zoomOutButton etc, are rendered inactive.
34
+ */
35
+ showNavigationControl: {
36
+ type: Boolean,
37
+ attribute: 'show-navigation-control',
38
+ },
39
+ // Set to true to make the navigator minimap appear.
40
+ showNavigator: {
41
+ type: Boolean,
42
+ attribute: 'show-navigator',
43
+ },
44
+
45
+ /** If true then the 'previous" and 'next' button is displayed switch between images. */
46
+ showSequenceMode: {
47
+ type: Boolean,
48
+ attribute: 'show-sequence-control',
49
+ },
50
+
51
+ /** If true then the 'Go home' button is displayed to go back to the original zoom and pan. */
52
+ showHomeControl: {
53
+ type: Boolean,
54
+ attribute: 'show-home-control',
55
+ },
56
+ /** If true then the 'Toggle full page' button is displayed to switch between full page and normal mode. */
57
+ showFullPageControl: {
58
+ type: Boolean,
59
+ attribute: 'show-full-page-control',
60
+ },
61
+ /**
62
+ * if true shows a 'download' button
63
+ */
64
+ showDownloadButton: {
65
+ type: Boolean,
66
+ attribute: 'show-download-control',
67
+ },
68
+ /**
69
+ * Default zoom between: set to 0 to adjust to viewer size.
70
+ */
71
+ defaultZoomLevel: {
72
+ type: Number,
73
+ attribute: 'default-zoom-level',
74
+ },
75
+ /**
76
+ * If true then the rotate left/right controls will be displayed
77
+ * as part of the standard controls. This is also subject to the
78
+ * browser support for rotate (e.g. viewer.drawer.canRotate()).
79
+ */
80
+ showRotationControl: {
81
+ type: Boolean,
82
+ attribute: 'show-rotation-control',
83
+ },
84
+ // Constrain during pan
85
+ constrainDuringPan: {
86
+ type: Boolean,
87
+ attribute: 'contrain-during-pan',
88
+ },
89
+ /**
90
+ * The percentage ( as a number from 0 to 1 ) of the source image
91
+ * which must be kept within the viewport.
92
+ * If the image is dragged beyond that limit, it will 'bounce'
93
+ * back until the minimum visibility ratio is achieved.
94
+ * Setting this to 0 and wrapHorizontal ( or wrapVertical )
95
+ * to true will provide the effect of an infinitely scrolling viewport.
96
+ */
97
+ visibilityRatio: {
98
+ type: Number,
99
+ attribute: 'visibility-ratio',
100
+ },
101
+ /**
102
+ * If set, thumbnails of all images are shown in a reference strip at the
103
+ * bottom of the viewer.
104
+ */
105
+ referenceStrip: {
106
+ type: Boolean,
107
+ attribute: 'reference-strip',
108
+ },
109
+ /**
110
+ * Size ratio for the reference strip thumbnails. 0.2 by default.
111
+ */
112
+ referenceStripSizeRatio: {
113
+ type: Number,
114
+ attribute: 'reference-strip-size-ratio',
115
+ },
116
+ /**
117
+ * Type of the source of the image to display: either 'iiif' or 'image'
118
+ * (for simple image links not served via IIIF).
119
+ */
120
+ type: {
121
+ type: String,
122
+ },
123
+ baseUri: {
124
+ type: String,
125
+ attribute: 'base-uri',
126
+ },
127
+ /**
128
+ * Path pointing to the location of openseadragon user interface images.
129
+ */
130
+ prefixUrl: {
131
+ type: String,
132
+ attribute: 'prefix-url',
133
+ },
134
+ /**
135
+ * Array of facsimiles
136
+ *
137
+ */
138
+ facsimiles: {
139
+ type: Array,
140
+ },
141
+ /**
142
+ * Will be true if images were loaded for display, false if there are no images
143
+ * to show.
144
+ */
145
+ loaded: {
146
+ type: Boolean,
147
+ reflect: true,
148
+ },
149
+ /**
150
+ * CORS (Cross-Origin Resource Sharing) policy - wraps the OSD Viewer option -
151
+ * only sensible values are 'anonymous' (default) or 'use-credentials'.
152
+ */
153
+ crossOriginPolicy: {
154
+ type: String,
155
+ attribute: 'cors',
156
+ },
157
+ };
158
+ }
159
+
160
+ constructor() {
161
+ super();
162
+ this._facsimiles = [];
163
+ this.baseUri = '';
164
+ this.crossOriginPolicy = 'anonymous';
165
+ this.type = 'iiif';
166
+ this.visibilityRatio = 1;
167
+ this.defaultZoomLevel = 0;
168
+ this.sequenceMode = false;
169
+ this.showHomeControl = false;
170
+ this.showNavigator = false;
171
+ this.showNavigationControl = false;
172
+ this.showFullPageControl = false;
173
+ this.showRotationControl = false;
174
+ this.showDownloadButton = false;
175
+ this.constrainDuringPan = false;
176
+ this.referenceStrip = false;
177
+ this.referenceStripSizeRatio = 0.2;
178
+ this.prefixUrl = '../images/openseadragon/';
179
+ this.loaded = false;
180
+ }
181
+
182
+ set facsimiles(facs) {
183
+ this._facsimiles = facs || [];
184
+ this.loaded = this._facsimiles.length > 0;
185
+ this.emitTo('pb-facsimile-status', { status: 'loading' });
186
+ }
187
+
188
+ connectedCallback() {
189
+ super.connectedCallback();
190
+ this.subscribeTo('pb-start-update', this._clearAll.bind(this));
191
+ this.subscribeTo('pb-load-facsimile', e => {
192
+ const { element, order } = e.detail;
193
+ const itemOrder = this._facsimiles.map(item =>
194
+ item.getOrder ? item.getOrder() : Number.POSITIVE_INFINITY,
195
+ );
196
+ const insertAt = itemOrder.reduce((result, next, index) => {
197
+ if (order < next) return result;
198
+ if (order === next) return index;
199
+ return index + 1;
200
+ }, 0);
201
+
202
+ this._facsimiles.splice(insertAt, 0, element);
203
+ this.loaded = this._facsimiles.length > 0;
204
+
205
+ this._facsimileObserver();
206
+ });
207
+ this.subscribeTo('pb-show-annotation', this._showAnnotationListener.bind(this));
208
+ }
209
+
210
+ firstUpdated() {
211
+ try {
212
+ window.ESGlobalBridge.requestAvailability();
213
+ const path = resolveURL('../lib/openseadragon.min.js');
214
+ window.ESGlobalBridge.instance.load('openseadragon', path);
215
+ window.addEventListener(
216
+ 'es-bridge-openseadragon-loaded',
217
+ this._initOpenSeadragon.bind(this),
218
+ { once: true },
219
+ );
220
+ } catch (error) {
221
+ console.error(error.message);
158
222
  }
159
-
160
- constructor() {
161
- super();
162
- this._facsimiles = [];
163
- this.baseUri = '';
164
- this.crossOriginPolicy = 'anonymous';
165
- this.type = 'iiif';
166
- this.visibilityRatio = 1;
167
- this.defaultZoomLevel = 0;
168
- this.sequenceMode = false;
169
- this.showHomeControl = false;
170
- this.showNavigator = false;
171
- this.showNavigationControl = false;
172
- this.showFullPageControl = false;
173
- this.showRotationControl = false;
174
- this.showDownloadButton = false;
175
- this.constrainDuringPan = false;
176
- this.referenceStrip = false;
177
- this.referenceStripSizeRatio = 0.2;
178
- this.prefixUrl = '../images/openseadragon/';
179
- this.loaded = false;
180
- }
181
-
182
- set facsimiles(facs) {
183
- this._facsimiles = facs || [];
184
- this.loaded = this._facsimiles.length > 0;
185
- this.emitTo('pb-facsimile-status', { status: 'loading' });
186
- }
187
-
188
- connectedCallback() {
189
- super.connectedCallback();
190
- this.subscribeTo('pb-start-update', this._clearAll.bind(this));
191
- this.subscribeTo('pb-load-facsimile', (e) => {
192
- const { element, order } = e.detail
193
- const itemOrder = this._facsimiles.map(item => item.getOrder ? item.getOrder() : Number.POSITIVE_INFINITY )
194
- const insertAt = itemOrder.reduce((result, next, index) => {
195
- if (order < next) return result;
196
- if (order === next) return index;
197
- return index + 1;
198
- }, 0)
199
-
200
- this._facsimiles.splice(insertAt, 0, element)
201
- this.loaded = this._facsimiles.length > 0;
202
-
203
- this._facsimileObserver()
204
- });
205
- this.subscribeTo('pb-show-annotation', this._showAnnotationListener.bind(this));
223
+ }
224
+
225
+ render() {
226
+ return html`
227
+ <slot name="before"></slot>
228
+ <!-- Openseadragon -->
229
+
230
+ <div id="viewer" part="image"></div>
231
+ <slot name="after"></slot>
232
+ ${this.showDownloadButton ? html`<a id="downloadBtn" title="Download">&#8676;</a>` : ''}
233
+ `;
234
+ }
235
+
236
+ static get styles() {
237
+ return css`
238
+ :host {
239
+ display: flex;
240
+ flex-direction: column;
241
+ position: relative;
242
+ background: transparent;
243
+ }
244
+
245
+ #runtime-overlay {
246
+ border: var(--pb-facsimile-border, 4px solid rgba(0, 0, 128, 0.5));
247
+ }
248
+
249
+ #viewer {
250
+ flex: 1;
251
+ position: relative;
252
+ max-height: var(--pb-facsimile-height, auto);
253
+ width: 100%;
254
+ }
255
+ #downloadBtn {
256
+ position: absolute;
257
+ z-index: 100;
258
+ bottom: 0.25rem;
259
+ width: 1.35rem;
260
+ height: 1.35rem;
261
+ transform: rotate(-90deg);
262
+ cursor: pointer;
263
+ border: thin solid #d7dde8;
264
+ display: flex;
265
+ align-items: center;
266
+ justify-content: center;
267
+ border-radius: 0.75rem;
268
+ background-image: linear-gradient(to left, #fafafa 0%, #d7dde8 51%, #bbbbbb 100%);
269
+ font-size: 1.2rem;
270
+ box-shadow: -2px 1px 5px 0px rgba(0, 0, 0, 0.75);
271
+ }
272
+ #downloadBtn:hover {
273
+ background-image: radial-gradient(white, #efefef);
274
+ }
275
+ `;
276
+ }
277
+
278
+ // Init openseadragon
279
+ _initOpenSeadragon() {
280
+ const prefixUrl = resolveURL(this.prefixUrl + (this.prefixUrl.endsWith('/') ? '' : '/'));
281
+ const options = {
282
+ element: this.shadowRoot.getElementById('viewer'),
283
+ prefixUrl,
284
+ preserveViewport: true,
285
+ showZoomControl: true,
286
+ sequenceMode: this.showSequenceMode,
287
+ showHomeControl: this.showHomeControl,
288
+ showFullPageControl: this.showFullPageControl,
289
+ showNavigator: this.showNavigator,
290
+ showNavigationControl: this.showNavigationControl,
291
+ showRotationControl: this.showRotationControl,
292
+ autoHideControls: false,
293
+ visibilityRatio: 1,
294
+ minZoomLevel: 1,
295
+ defaultZoomLevel: this.defaultZoomLevel,
296
+ constrainDuringPan: true,
297
+ crossOriginPolicy: this.crossOriginPolicy,
298
+ };
299
+
300
+ if (this.referenceStrip) {
301
+ options.showReferenceStrip = true;
302
+ options.referenceStripSizeRatio = this.referenceStripSizeRatio;
206
303
  }
207
-
208
- firstUpdated() {
209
- try{
210
- window.ESGlobalBridge.requestAvailability();
211
- const path = resolveURL('../lib/openseadragon.min.js');
212
- window.ESGlobalBridge.instance.load("openseadragon", path);
213
- window.addEventListener(
214
- "es-bridge-openseadragon-loaded",
215
- this._initOpenSeadragon.bind(this),
216
- { once: true }
217
- );
218
- } catch (error){
219
- console.error(error.message);
220
- }
304
+ this.viewer = OpenSeadragon(options);
305
+
306
+ this.viewer.addHandler('open', () => {
307
+ this.resetZoom();
308
+ this.emitTo('pb-facsimile-status', { status: 'loaded', facsimiles: this._facsimiles });
309
+ });
310
+ this.viewer.addHandler('open-failed', ev => {
311
+ console.error('<pb-facsimile> open failed: %s', ev.message);
312
+ this.loaded = false;
313
+ this.emitTo('pb-facsimile-status', { status: 'fail' });
314
+ });
315
+
316
+ const download = this.shadowRoot.querySelector('#downloadBtn');
317
+ if (this.showDownloadButton) {
318
+ download.addEventListener('click', ev => {
319
+ ev.preventDefault();
320
+ const currentImage = this.viewer.drawer.canvas.toDataURL('image/png');
321
+ const downloadLink = document.createElement('a');
322
+ downloadLink.href = currentImage;
323
+ downloadLink.download = 'download';
324
+ downloadLink.click();
325
+ });
221
326
  }
222
327
 
223
- render() {
224
- return html`
225
- <slot name="before"></slot>
226
- <!-- Openseadragon -->
227
-
228
- <div id="viewer" part="image"></div>
229
- <slot name="after"></slot>
230
- ${this.showDownloadButton ?
231
- html`<a id="downloadBtn" title="Download">&#8676;</a>`:''
232
- }
233
-
234
- `;
235
- }
236
-
237
- static get styles() {
238
- return css`
239
- :host {
240
- display: flex;
241
- flex-direction: column;
242
- position: relative;
243
- background: transparent;
244
- }
245
-
246
- #runtime-overlay {
247
- border: var(--pb-facsimile-border, 4px solid rgba(0, 0, 128, 0.5));
248
- }
249
-
250
- #viewer {
251
- flex: 1;
252
- position: relative;
253
- max-height: var(--pb-facsimile-height, auto);
254
- width: 100%;
255
- }
256
- #downloadBtn{
257
- position: absolute;
258
- z-index: 100;
259
- bottom:0.25rem;
260
- width:1.35rem;
261
- height:1.35rem;
262
- transform:rotate(-90deg);
263
- cursor: pointer;
264
- border: thin solid #D7DDE8;
265
- display: flex;
266
- align-items: center;
267
- justify-content: center;
268
- border-radius:0.75rem;
269
- background-image:linear-gradient(to left, #fafafa 0%, #D7DDE8 51%, #bbbbbb 100%);
270
- font-size:1.2rem;
271
- box-shadow: -2px 1px 5px 0px rgba(0,0,0,0.75);
272
- }
273
- #downloadBtn:hover{
274
- background-image:radial-gradient( white, #efefef);
275
- }
276
- `;
277
- }
278
-
279
- // Init openseadragon
280
- _initOpenSeadragon() {
281
- const prefixUrl = resolveURL(this.prefixUrl + (this.prefixUrl.endsWith("/") ? "" : "/"));
282
- const options = {
283
- element: this.shadowRoot.getElementById('viewer'),
284
- prefixUrl,
285
- preserveViewport: true,
286
- showZoomControl: true,
287
- sequenceMode: this.showSequenceMode,
288
- showHomeControl: this.showHomeControl,
289
- showFullPageControl: this.showFullPageControl,
290
- showNavigator: this.showNavigator,
291
- showNavigationControl: this.showNavigationControl,
292
- showRotationControl: this.showRotationControl,
293
- autoHideControls: false,
294
- visibilityRatio: 1,
295
- minZoomLevel: 1,
296
- defaultZoomLevel: this.defaultZoomLevel,
297
- constrainDuringPan: true,
298
- crossOriginPolicy: this.crossOriginPolicy
299
- };
300
-
301
- if (this.referenceStrip) {
302
- options.showReferenceStrip = true;
303
- options.referenceStripSizeRatio = this.referenceStripSizeRatio;
304
- }
305
- this.viewer = OpenSeadragon(options);
306
-
307
- this.viewer.addHandler('open', () => {
308
- this.resetZoom();
309
- this.emitTo('pb-facsimile-status', { status: 'loaded', facsimiles: this._facsimiles });
310
- });
311
- this.viewer.addHandler('open-failed', (ev) => {
312
- console.error('<pb-facsimile> open failed: %s', ev.message);
313
- this.loaded = false;
314
- this.emitTo('pb-facsimile-status', { status: 'fail' });
315
- });
316
-
317
- const download = this.shadowRoot.querySelector('#downloadBtn');
318
- if(this.showDownloadButton){
319
- download.addEventListener('click', (ev) => {
320
- ev.preventDefault();
321
- const currentImage = this.viewer.drawer.canvas.toDataURL("image/png");
322
- const downloadLink = document.createElement('a');
323
- downloadLink.href = currentImage;
324
- downloadLink.download = 'download';
325
- downloadLink.click();
326
- });
327
- }
328
-
329
- /*
328
+ /*
330
329
  handling of full-screen view requires to hide/unhide the content of body to allow full screen viewer
331
330
  to full-page functionality. Standard OSD completely deletes all body children disconnecting all event-handlers
332
331
  that have been there. This solution just uses style.display to hide/show. Former display value of pb-page
333
332
  will be preserved.
334
333
  */
335
- this.ownerPage = document.querySelector('pb-page');
336
- if(this.ownerPage){
337
- this.pbPageDisplay = window.getComputedStyle(this.ownerPage).getPropertyValue('display');
338
- this.viewer.addHandler('full-screen', (ev) => {
339
- if(ev.fullScreen){
340
- this.ownerPage.style.display = 'none';
341
- }else{
342
- this.viewer.clearOverlays();
343
- this.emitTo('pb-refresh');
344
- this.ownerPage.style.display = this.pbPageDisplay;
345
- }
346
- });
334
+ this.ownerPage = document.querySelector('pb-page');
335
+ if (this.ownerPage) {
336
+ this.pbPageDisplay = window.getComputedStyle(this.ownerPage).getPropertyValue('display');
337
+ this.viewer.addHandler('full-screen', ev => {
338
+ if (ev.fullScreen) {
339
+ this.ownerPage.style.display = 'none';
340
+ } else {
341
+ this.viewer.clearOverlays();
342
+ this.emitTo('pb-refresh');
343
+ this.ownerPage.style.display = this.pbPageDisplay;
347
344
  }
348
- this._facsimileObserver();
349
-
350
- this.signalReady();
345
+ });
351
346
  }
347
+ this._facsimileObserver();
352
348
 
353
- _facsimileObserver() {
354
- if (!this.viewer) {
355
- return;
356
- }
357
- if (this._facsimiles.length === 0) {
358
- return this.viewer.close()
359
- }
360
- const uris = this._facsimiles.map(facsLink => {
361
- const url = this.baseUri + (facsLink.getImage ? facsLink.getImage() : facsLink)
362
- if (this.type === 'iiif') {
363
- return `${url}/info.json`;
364
- }
365
- return {
366
- tileSource: {
367
- type: 'image',
368
- url,
369
- buildPyramid: false
370
- }
371
- }
372
- });
373
-
374
- this.viewer.open(uris)
375
- this.viewer.goToPage(0)
376
- }
349
+ this.signalReady();
350
+ }
377
351
 
378
- _clearAll() {
379
- if (!this.viewer) {
380
- return;
381
- }
382
- this.resetZoom();
383
- this.viewer.clearOverlays();
384
- this.facsimiles = [];
352
+ _facsimileObserver() {
353
+ if (!this.viewer) {
354
+ return;
385
355
  }
356
+ if (this._facsimiles.length === 0) {
357
+ return this.viewer.close();
358
+ }
359
+ const uris = this._facsimiles.map(facsLink => {
360
+ const url = this.baseUri + (facsLink.getImage ? facsLink.getImage() : facsLink);
361
+ if (this.type === 'iiif') {
362
+ return `${url}/info.json`;
363
+ }
364
+ return {
365
+ tileSource: {
366
+ type: 'image',
367
+ url,
368
+ buildPyramid: false,
369
+ },
370
+ };
371
+ });
372
+
373
+ this.viewer.open(uris);
374
+ this.viewer.goToPage(0);
375
+ }
376
+
377
+ _clearAll() {
378
+ if (!this.viewer) {
379
+ return;
380
+ }
381
+ this.resetZoom();
382
+ this.viewer.clearOverlays();
383
+ this.facsimiles = [];
384
+ }
385
+
386
+ _showAnnotationListener(event) {
387
+ if (!this.viewer) {
388
+ return;
389
+ }
390
+ const overlayId = 'runtime-overlay';
386
391
 
387
- _showAnnotationListener(event) {
388
- if (!this.viewer) {
389
- return;
390
- }
391
- const overlayId = 'runtime-overlay'
392
-
393
- // remove old overlay
394
- this.viewer.removeOverlay(this.overlay);
395
-
396
- // check event data for completeness
397
- if (!event.detail.file || event.detail.file === 0) {
398
- return console.error('file missing', event.detail)
399
- }
392
+ // remove old overlay
393
+ this.viewer.removeOverlay(this.overlay);
400
394
 
401
- if (
402
- event.detail.coordinates &&
403
- (!event.detail.coordinates[0] ||
404
- event.detail.coordinates.length !== 4)
405
- ) {
406
- return console.error('coords incomplete or missing', event.detail)
407
- }
408
-
409
- // find page to show
410
- const page = event.detail.element ? this._pageByElement(event.detail.element) : this._pageIndexByUrl(event.detail.file);
395
+ // check event data for completeness
396
+ if (!event.detail.file || event.detail.file === 0) {
397
+ return console.error('file missing', event.detail);
398
+ }
411
399
 
412
- if (page < 0) {
413
- return console.error('page not found', event.detail)
414
- }
400
+ if (
401
+ event.detail.coordinates &&
402
+ (!event.detail.coordinates[0] || event.detail.coordinates.length !== 4)
403
+ ) {
404
+ return console.error('coords incomplete or missing', event.detail);
405
+ }
415
406
 
416
- if (this.viewer.currentPage() !== page) {
417
- this.viewer.goToPage(page);
418
- }
407
+ // find page to show
408
+ const page = event.detail.element
409
+ ? this._pageByElement(event.detail.element)
410
+ : this._pageIndexByUrl(event.detail.file);
419
411
 
420
- if (event.detail.coordinates) {
421
- // deconstruct given coordinates into variables
422
- const [x1, y1, w, h] = event.detail.coordinates;
423
- const tiledImage = this.viewer.world.getItemAt(0);
424
- const currentRect = tiledImage.viewportToImageRectangle(
425
- tiledImage.getBounds(true));
426
-
427
- // scroll into view?
428
- if (!currentRect.containsPoint(new OpenSeadragon.Point(x1, y1))) {
429
- this.viewer.viewport.fitBoundsWithConstraints(
430
- tiledImage.imageToViewportRectangle(x1, y1, currentRect.width, currentRect.height));
431
- }
432
-
433
- // create new overlay
434
- const overlay = document.createElement('div');
435
- this.overlay = overlay
436
- overlay.id = overlayId;
437
-
438
- // place marker
439
- const marker = tiledImage.imageToViewportRectangle(x1, y1, w, h);
440
-
441
- this.viewer.addOverlay({
442
- element: overlay,
443
- location: marker
444
- });
445
- }
412
+ if (page < 0) {
413
+ return console.error('page not found', event.detail);
446
414
  }
447
415
 
448
- _pageByElement(element) {
449
- return this._facsimiles.indexOf(element);
416
+ if (this.viewer.currentPage() !== page) {
417
+ this.viewer.goToPage(page);
450
418
  }
451
419
 
452
- _pageIndexByUrl(file) {
453
- return this._facsimiles.findIndex(element => element.getImage() === file);
420
+ if (event.detail.coordinates) {
421
+ // deconstruct given coordinates into variables
422
+ const [x1, y1, w, h] = event.detail.coordinates;
423
+ const tiledImage = this.viewer.world.getItemAt(0);
424
+ const currentRect = tiledImage.viewportToImageRectangle(tiledImage.getBounds(true));
425
+
426
+ // scroll into view?
427
+ if (!currentRect.containsPoint(new OpenSeadragon.Point(x1, y1))) {
428
+ this.viewer.viewport.fitBoundsWithConstraints(
429
+ tiledImage.imageToViewportRectangle(x1, y1, currentRect.width, currentRect.height),
430
+ );
431
+ }
432
+
433
+ // create new overlay
434
+ const overlay = document.createElement('div');
435
+ this.overlay = overlay;
436
+ overlay.id = overlayId;
437
+
438
+ // place marker
439
+ const marker = tiledImage.imageToViewportRectangle(x1, y1, w, h);
440
+
441
+ this.viewer.addOverlay({
442
+ element: overlay,
443
+ location: marker,
444
+ });
454
445
  }
446
+ }
455
447
 
456
- // reset zoom
457
- resetZoom() {
458
- if (!this.viewer) {
459
- return;
460
- }
461
- this.viewer.viewport.goHome();
462
- }
448
+ _pageByElement(element) {
449
+ return this._facsimiles.indexOf(element);
450
+ }
463
451
 
452
+ _pageIndexByUrl(file) {
453
+ return this._facsimiles.findIndex(element => element.getImage() === file);
454
+ }
464
455
 
456
+ // reset zoom
457
+ resetZoom() {
458
+ if (!this.viewer) {
459
+ return;
460
+ }
461
+ this.viewer.viewport.goHome();
462
+ }
465
463
  }
466
464
  if (!customElements.get('pb-facsimile')) {
467
- customElements.define('pb-facsimile', PbFacsimile);
465
+ customElements.define('pb-facsimile', PbFacsimile);
468
466
  }