viewerjs 1.12.0 → 1.14.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 +261 -39
- package/dist/viewer.common.js +750 -205
- package/dist/viewer.css +111 -2
- package/dist/viewer.esm.js +750 -205
- package/dist/viewer.js +750 -205
- package/dist/viewer.min.css +3 -3
- package/dist/viewer.min.js +3 -3
- package/package.json +6 -7
- package/src/css/viewer.css +107 -1
- package/src/css/viewer.scss +107 -1
- package/src/js/constants.js +6 -0
- package/src/js/defaults.js +62 -5
- package/src/js/events.js +31 -4
- package/src/js/handlers.js +232 -10
- package/src/js/methods.js +280 -138
- package/src/js/others.js +60 -6
- package/src/js/render.js +87 -15
- package/src/js/template.js +13 -6
- package/src/js/utilities.js +95 -12
- package/src/js/viewer.js +99 -11
- package/types/index.d.ts +116 -16
package/src/js/methods.js
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
EVENT_MOVE,
|
|
18
18
|
EVENT_MOVED,
|
|
19
19
|
EVENT_PLAY,
|
|
20
|
+
EVENT_PLAYING,
|
|
20
21
|
EVENT_ROTATE,
|
|
21
22
|
EVENT_ROTATED,
|
|
22
23
|
EVENT_SCALE,
|
|
@@ -41,9 +42,11 @@ import {
|
|
|
41
42
|
getOffset,
|
|
42
43
|
getPointersCenter,
|
|
43
44
|
hasClass,
|
|
45
|
+
inheritAttributes,
|
|
44
46
|
isFunction,
|
|
45
47
|
isNumber,
|
|
46
48
|
isPlainObject,
|
|
49
|
+
isTransitionEnabled,
|
|
47
50
|
isUndefined,
|
|
48
51
|
removeClass,
|
|
49
52
|
removeListener,
|
|
@@ -73,13 +76,23 @@ export default {
|
|
|
73
76
|
return this;
|
|
74
77
|
}
|
|
75
78
|
|
|
79
|
+
const originalEvent = this.actionEvent
|
|
80
|
+
|| this.showOriginalEvent
|
|
81
|
+
|| this.viewOriginalEvent
|
|
82
|
+
|| null;
|
|
83
|
+
|
|
84
|
+
this.actionEvent = null;
|
|
85
|
+
this.showOriginalEvent = originalEvent;
|
|
86
|
+
|
|
76
87
|
if (isFunction(options.show)) {
|
|
77
88
|
addListener(element, EVENT_SHOW, options.show, {
|
|
78
89
|
once: true,
|
|
79
90
|
});
|
|
80
91
|
}
|
|
81
92
|
|
|
82
|
-
if (dispatchEvent(element, EVENT_SHOW
|
|
93
|
+
if (dispatchEvent(element, EVENT_SHOW, {
|
|
94
|
+
originalEvent,
|
|
95
|
+
}) === false || !this.ready) {
|
|
83
96
|
return this;
|
|
84
97
|
}
|
|
85
98
|
|
|
@@ -98,7 +111,7 @@ export default {
|
|
|
98
111
|
viewer.setAttribute('aria-modal', true);
|
|
99
112
|
viewer.removeAttribute('aria-hidden');
|
|
100
113
|
|
|
101
|
-
if (options
|
|
114
|
+
if (isTransitionEnabled(options, 'show') && !immediate) {
|
|
102
115
|
const shown = this.shown.bind(this);
|
|
103
116
|
|
|
104
117
|
this.transitioning = {
|
|
@@ -136,13 +149,20 @@ export default {
|
|
|
136
149
|
return this;
|
|
137
150
|
}
|
|
138
151
|
|
|
152
|
+
const originalEvent = this.actionEvent || this.hideOriginalEvent || null;
|
|
153
|
+
|
|
154
|
+
this.actionEvent = null;
|
|
155
|
+
this.hideOriginalEvent = originalEvent;
|
|
156
|
+
|
|
139
157
|
if (isFunction(options.hide)) {
|
|
140
158
|
addListener(element, EVENT_HIDE, options.hide, {
|
|
141
159
|
once: true,
|
|
142
160
|
});
|
|
143
161
|
}
|
|
144
162
|
|
|
145
|
-
if (dispatchEvent(element, EVENT_HIDE
|
|
163
|
+
if (dispatchEvent(element, EVENT_HIDE, {
|
|
164
|
+
originalEvent,
|
|
165
|
+
}) === false || this.destroyed) {
|
|
146
166
|
return this;
|
|
147
167
|
}
|
|
148
168
|
|
|
@@ -164,7 +184,7 @@ export default {
|
|
|
164
184
|
this.hidden();
|
|
165
185
|
};
|
|
166
186
|
|
|
167
|
-
if (options
|
|
187
|
+
if (isTransitionEnabled(options, 'hide') && !immediate) {
|
|
168
188
|
const onViewerTransitionEnd = (event) => {
|
|
169
189
|
// Ignore all propagating `transitionend` events (#275).
|
|
170
190
|
if (event && event.target === viewer) {
|
|
@@ -198,7 +218,7 @@ export default {
|
|
|
198
218
|
addListener(image, EVENT_TRANSITION_END, onImageTransitionEnd, {
|
|
199
219
|
once: true,
|
|
200
220
|
});
|
|
201
|
-
this.zoomTo(0, false, null,
|
|
221
|
+
this.zoomTo(0, false, null, true);
|
|
202
222
|
} else {
|
|
203
223
|
onImageTransitionEnd();
|
|
204
224
|
}
|
|
@@ -215,13 +235,20 @@ export default {
|
|
|
215
235
|
* @returns {Viewer} this
|
|
216
236
|
*/
|
|
217
237
|
view(index = this.options.initialViewIndex) {
|
|
238
|
+
const previousIndex = this.index;
|
|
239
|
+
|
|
218
240
|
index = Number(index) || 0;
|
|
219
241
|
|
|
220
242
|
if (this.hiding || this.played || index < 0 || index >= this.length
|
|
221
|
-
|| (this.viewed && index ===
|
|
243
|
+
|| (this.viewed && index === previousIndex)) {
|
|
222
244
|
return this;
|
|
223
245
|
}
|
|
224
246
|
|
|
247
|
+
const originalEvent = this.actionEvent || this.viewOriginalEvent || null;
|
|
248
|
+
|
|
249
|
+
this.actionEvent = null;
|
|
250
|
+
this.viewOriginalEvent = originalEvent;
|
|
251
|
+
|
|
225
252
|
if (!this.isShown) {
|
|
226
253
|
this.index = index;
|
|
227
254
|
return this.show();
|
|
@@ -237,20 +264,19 @@ export default {
|
|
|
237
264
|
title,
|
|
238
265
|
canvas,
|
|
239
266
|
} = this;
|
|
240
|
-
|
|
267
|
+
let item = this.getItem(index);
|
|
268
|
+
|
|
269
|
+
if (!item) {
|
|
270
|
+
this.initList(index);
|
|
271
|
+
item = this.getItem(index);
|
|
272
|
+
}
|
|
273
|
+
|
|
241
274
|
const img = item.querySelector('img');
|
|
242
275
|
const url = getData(img, 'originalUrl');
|
|
243
276
|
const alt = img.getAttribute('alt');
|
|
244
277
|
const image = document.createElement('img');
|
|
245
278
|
|
|
246
|
-
|
|
247
|
-
const value = img.getAttribute(name);
|
|
248
|
-
|
|
249
|
-
if (value !== null) {
|
|
250
|
-
image.setAttribute(name, value);
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
|
|
279
|
+
inheritAttributes(image, img, options.inheritedAttributes);
|
|
254
280
|
image.src = url;
|
|
255
281
|
image.alt = alt;
|
|
256
282
|
|
|
@@ -264,11 +290,14 @@ export default {
|
|
|
264
290
|
originalImage: this.images[index],
|
|
265
291
|
index,
|
|
266
292
|
image,
|
|
293
|
+
originalEvent,
|
|
267
294
|
}) === false || !this.isShown || this.hiding || this.played) {
|
|
268
295
|
return this;
|
|
269
296
|
}
|
|
270
297
|
|
|
271
|
-
|
|
298
|
+
this.hideMagnifier();
|
|
299
|
+
|
|
300
|
+
const activeItem = this.getItem(previousIndex);
|
|
272
301
|
|
|
273
302
|
if (activeItem) {
|
|
274
303
|
removeClass(activeItem, CLASS_ACTIVE);
|
|
@@ -309,72 +338,110 @@ export default {
|
|
|
309
338
|
title.innerHTML = escapeHTMLEntities(isFunction(render)
|
|
310
339
|
? render.call(this, image, imageData)
|
|
311
340
|
: `${alt} (${imageData.naturalWidth} × ${imageData.naturalHeight})`);
|
|
312
|
-
};
|
|
313
|
-
let onLoad;
|
|
314
|
-
let onError;
|
|
315
341
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
this.viewing = {
|
|
321
|
-
abort: () => {
|
|
322
|
-
removeListener(element, EVENT_VIEWED, onViewed);
|
|
342
|
+
// Preload the image in the direction of navigation
|
|
343
|
+
if (options.preload) {
|
|
344
|
+
const direction = index < previousIndex ? -1 : 1;
|
|
345
|
+
let nextIndex = index + direction;
|
|
323
346
|
|
|
324
|
-
if (
|
|
325
|
-
if (
|
|
326
|
-
this.
|
|
327
|
-
} else
|
|
328
|
-
|
|
347
|
+
if (nextIndex < 0 || nextIndex >= this.length) {
|
|
348
|
+
if (options.loop) {
|
|
349
|
+
nextIndex = direction > 0 ? 0 : this.length - 1;
|
|
350
|
+
} else {
|
|
351
|
+
nextIndex = -1;
|
|
329
352
|
}
|
|
330
|
-
}
|
|
331
|
-
// Cancel download to save bandwidth.
|
|
332
|
-
image.src = '';
|
|
333
|
-
removeListener(image, EVENT_LOAD, onLoad);
|
|
353
|
+
}
|
|
334
354
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
355
|
+
if (nextIndex !== index) {
|
|
356
|
+
const nextImage = this.images[nextIndex];
|
|
357
|
+
const preloadedImage = document.createElement('img');
|
|
358
|
+
|
|
359
|
+
inheritAttributes(preloadedImage, nextImage, options.inheritedAttributes);
|
|
360
|
+
preloadedImage.src = this.getImageURL(nextImage) || nextImage.src;
|
|
338
361
|
}
|
|
339
|
-
}
|
|
362
|
+
}
|
|
340
363
|
};
|
|
341
364
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
addListener(image, EVENT_ERROR, onError = () => {
|
|
365
|
+
addListener(element, EVENT_VIEWED, onViewed, {
|
|
366
|
+
once: true,
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
const loadImage = (isFallback = false) => {
|
|
370
|
+
let onLoad;
|
|
371
|
+
let onError;
|
|
372
|
+
|
|
373
|
+
const clean = () => {
|
|
352
374
|
removeListener(image, EVENT_LOAD, onLoad);
|
|
375
|
+
removeListener(image, EVENT_ERROR, onError);
|
|
353
376
|
|
|
354
377
|
if (this.timeout) {
|
|
355
378
|
clearTimeout(this.timeout);
|
|
356
379
|
this.timeout = false;
|
|
357
380
|
}
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
this.viewing = {
|
|
384
|
+
abort: () => {
|
|
385
|
+
removeListener(element, EVENT_VIEWED, onViewed);
|
|
386
|
+
|
|
387
|
+
if (image.complete) {
|
|
388
|
+
if (this.imageRendering) {
|
|
389
|
+
this.imageRendering.abort();
|
|
390
|
+
} else if (this.imageInitializing) {
|
|
391
|
+
this.imageInitializing.abort();
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
// Cancel download to save bandwidth.
|
|
395
|
+
image.src = '';
|
|
396
|
+
clean();
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
if (image.complete) {
|
|
402
|
+
this.load();
|
|
403
|
+
} else {
|
|
404
|
+
addListener(image, EVENT_LOAD, onLoad = () => {
|
|
405
|
+
clean();
|
|
406
|
+
this.load();
|
|
407
|
+
}, {
|
|
408
|
+
once: true,
|
|
409
|
+
});
|
|
410
|
+
addListener(image, EVENT_ERROR, onError = () => {
|
|
411
|
+
clean();
|
|
358
412
|
|
|
359
|
-
|
|
413
|
+
if (!isFallback) {
|
|
414
|
+
const fallbackSrc = img.src;
|
|
360
415
|
|
|
361
|
-
|
|
362
|
-
|
|
416
|
+
if (fallbackSrc && fallbackSrc !== image.src) {
|
|
417
|
+
image.src = fallbackSrc;
|
|
418
|
+
loadImage(true);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
removeClass(image, CLASS_INVISIBLE);
|
|
424
|
+
|
|
425
|
+
if (options.loading) {
|
|
426
|
+
removeClass(this.canvas, CLASS_LOADING);
|
|
427
|
+
}
|
|
428
|
+
}, {
|
|
429
|
+
once: true,
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
if (this.timeout) {
|
|
433
|
+
clearTimeout(this.timeout);
|
|
363
434
|
}
|
|
364
|
-
}, {
|
|
365
|
-
once: true,
|
|
366
|
-
});
|
|
367
435
|
|
|
368
|
-
|
|
369
|
-
|
|
436
|
+
// Make the image visible if it fails to load within 1s
|
|
437
|
+
this.timeout = setTimeout(() => {
|
|
438
|
+
removeClass(image, CLASS_INVISIBLE);
|
|
439
|
+
this.timeout = false;
|
|
440
|
+
}, 1000);
|
|
370
441
|
}
|
|
442
|
+
};
|
|
371
443
|
|
|
372
|
-
|
|
373
|
-
this.timeout = setTimeout(() => {
|
|
374
|
-
removeClass(image, CLASS_INVISIBLE);
|
|
375
|
-
this.timeout = false;
|
|
376
|
-
}, 1000);
|
|
377
|
-
}
|
|
444
|
+
loadImage();
|
|
378
445
|
|
|
379
446
|
return this;
|
|
380
447
|
},
|
|
@@ -435,10 +502,9 @@ export default {
|
|
|
435
502
|
* Move the image to an absolute point.
|
|
436
503
|
* @param {number} x - The new position in the horizontal direction.
|
|
437
504
|
* @param {number} [y=x] - The new position in the vertical direction.
|
|
438
|
-
* @param {Event} [_originalEvent=null] - The original event if any.
|
|
439
505
|
* @returns {Viewer} this
|
|
440
506
|
*/
|
|
441
|
-
moveTo(x, y = x
|
|
507
|
+
moveTo(x, y = x) {
|
|
442
508
|
const { element, options, imageData } = this;
|
|
443
509
|
|
|
444
510
|
x = Number(x);
|
|
@@ -462,6 +528,10 @@ export default {
|
|
|
462
528
|
}
|
|
463
529
|
|
|
464
530
|
if (changed) {
|
|
531
|
+
const originalEvent = this.actionEvent || null;
|
|
532
|
+
|
|
533
|
+
this.actionEvent = null;
|
|
534
|
+
|
|
465
535
|
if (isFunction(options.move)) {
|
|
466
536
|
addListener(element, EVENT_MOVE, options.move, {
|
|
467
537
|
once: true,
|
|
@@ -473,7 +543,7 @@ export default {
|
|
|
473
543
|
y,
|
|
474
544
|
oldX,
|
|
475
545
|
oldY,
|
|
476
|
-
originalEvent
|
|
546
|
+
originalEvent,
|
|
477
547
|
}) === false) {
|
|
478
548
|
return this;
|
|
479
549
|
}
|
|
@@ -482,6 +552,7 @@ export default {
|
|
|
482
552
|
imageData.y = y;
|
|
483
553
|
imageData.left = x;
|
|
484
554
|
imageData.top = y;
|
|
555
|
+
toggleClass(this.image, CLASS_TRANSITION, isTransitionEnabled(options, 'move'));
|
|
485
556
|
this.moving = true;
|
|
486
557
|
this.renderImage(() => {
|
|
487
558
|
this.moving = false;
|
|
@@ -497,7 +568,7 @@ export default {
|
|
|
497
568
|
y,
|
|
498
569
|
oldX,
|
|
499
570
|
oldY,
|
|
500
|
-
originalEvent
|
|
571
|
+
originalEvent,
|
|
501
572
|
}, {
|
|
502
573
|
cancelable: false,
|
|
503
574
|
});
|
|
@@ -531,6 +602,9 @@ export default {
|
|
|
531
602
|
|
|
532
603
|
if (isNumber(degree) && this.viewed && !this.played && options.rotatable) {
|
|
533
604
|
const oldDegree = imageData.rotate;
|
|
605
|
+
const originalEvent = this.actionEvent || null;
|
|
606
|
+
|
|
607
|
+
this.actionEvent = null;
|
|
534
608
|
|
|
535
609
|
if (isFunction(options.rotate)) {
|
|
536
610
|
addListener(element, EVENT_ROTATE, options.rotate, {
|
|
@@ -541,11 +615,13 @@ export default {
|
|
|
541
615
|
if (dispatchEvent(element, EVENT_ROTATE, {
|
|
542
616
|
degree,
|
|
543
617
|
oldDegree,
|
|
618
|
+
originalEvent,
|
|
544
619
|
}) === false) {
|
|
545
620
|
return this;
|
|
546
621
|
}
|
|
547
622
|
|
|
548
623
|
imageData.rotate = degree;
|
|
624
|
+
toggleClass(this.image, CLASS_TRANSITION, isTransitionEnabled(options, 'rotate'));
|
|
549
625
|
this.rotating = true;
|
|
550
626
|
this.renderImage(() => {
|
|
551
627
|
this.rotating = false;
|
|
@@ -559,6 +635,7 @@ export default {
|
|
|
559
635
|
dispatchEvent(element, EVENT_ROTATED, {
|
|
560
636
|
degree,
|
|
561
637
|
oldDegree,
|
|
638
|
+
originalEvent,
|
|
562
639
|
}, {
|
|
563
640
|
cancelable: false,
|
|
564
641
|
});
|
|
@@ -620,6 +697,10 @@ export default {
|
|
|
620
697
|
}
|
|
621
698
|
|
|
622
699
|
if (changed) {
|
|
700
|
+
const originalEvent = this.actionEvent || null;
|
|
701
|
+
|
|
702
|
+
this.actionEvent = null;
|
|
703
|
+
|
|
623
704
|
if (isFunction(options.scale)) {
|
|
624
705
|
addListener(element, EVENT_SCALE, options.scale, {
|
|
625
706
|
once: true,
|
|
@@ -631,12 +712,14 @@ export default {
|
|
|
631
712
|
scaleY,
|
|
632
713
|
oldScaleX,
|
|
633
714
|
oldScaleY,
|
|
715
|
+
originalEvent,
|
|
634
716
|
}) === false) {
|
|
635
717
|
return this;
|
|
636
718
|
}
|
|
637
719
|
|
|
638
720
|
imageData.scaleX = scaleX;
|
|
639
721
|
imageData.scaleY = scaleY;
|
|
722
|
+
toggleClass(this.image, CLASS_TRANSITION, isTransitionEnabled(options, 'scale'));
|
|
640
723
|
this.scaling = true;
|
|
641
724
|
this.renderImage(() => {
|
|
642
725
|
this.scaling = false;
|
|
@@ -652,6 +735,7 @@ export default {
|
|
|
652
735
|
scaleY,
|
|
653
736
|
oldScaleX,
|
|
654
737
|
oldScaleY,
|
|
738
|
+
originalEvent,
|
|
655
739
|
}, {
|
|
656
740
|
cancelable: false,
|
|
657
741
|
});
|
|
@@ -667,10 +751,9 @@ export default {
|
|
|
667
751
|
* @param {number} ratio - The target ratio.
|
|
668
752
|
* @param {boolean} [showTooltip=false] - Indicates whether to show the tooltip.
|
|
669
753
|
* @param {Object} [pivot] - The pivot point coordinate for zooming.
|
|
670
|
-
* @param {Event} [_originalEvent=null] - The original event if any.
|
|
671
754
|
* @returns {Viewer} this
|
|
672
755
|
*/
|
|
673
|
-
zoom(ratio, showTooltip = false, pivot = null
|
|
756
|
+
zoom(ratio, showTooltip = false, pivot = null) {
|
|
674
757
|
const { imageData } = this;
|
|
675
758
|
|
|
676
759
|
ratio = Number(ratio);
|
|
@@ -685,7 +768,6 @@ export default {
|
|
|
685
768
|
(imageData.width * ratio) / imageData.naturalWidth,
|
|
686
769
|
showTooltip,
|
|
687
770
|
pivot,
|
|
688
|
-
_originalEvent,
|
|
689
771
|
);
|
|
690
772
|
|
|
691
773
|
return this;
|
|
@@ -696,11 +778,10 @@ export default {
|
|
|
696
778
|
* @param {number} ratio - The target ratio.
|
|
697
779
|
* @param {boolean} [showTooltip] - Indicates whether to show the tooltip.
|
|
698
780
|
* @param {Object} [pivot] - The pivot point coordinate for zooming.
|
|
699
|
-
* @param {
|
|
700
|
-
* @param {Event} [_zoomable=false] - Indicates if the current zoom is available or not.
|
|
781
|
+
* @param {boolean} [_zoomable=false] - Indicates if the current zoom is available or not.
|
|
701
782
|
* @returns {Viewer} this
|
|
702
783
|
*/
|
|
703
|
-
zoomTo(ratio, showTooltip = false, pivot = null,
|
|
784
|
+
zoomTo(ratio, showTooltip = false, pivot = null, _zoomable = false) {
|
|
704
785
|
const {
|
|
705
786
|
element,
|
|
706
787
|
options,
|
|
@@ -720,14 +801,22 @@ export default {
|
|
|
720
801
|
|
|
721
802
|
if (isNumber(ratio) && this.viewed && !this.played && (_zoomable || options.zoomable)) {
|
|
722
803
|
if (!_zoomable) {
|
|
723
|
-
const minZoomRatio = Math.max(0.01, options.minZoomRatio)
|
|
724
|
-
|
|
804
|
+
const minZoomRatio = Math.max(0.01, isFunction(options.minZoomRatio)
|
|
805
|
+
? options.minZoomRatio.call(this, this.image, imageData)
|
|
806
|
+
: options.minZoomRatio);
|
|
807
|
+
const maxZoomRatio = Math.min(100, isFunction(options.maxZoomRatio)
|
|
808
|
+
? options.maxZoomRatio.call(this, this.image, imageData)
|
|
809
|
+
: options.maxZoomRatio);
|
|
725
810
|
|
|
726
811
|
ratio = Math.min(Math.max(ratio, minZoomRatio), maxZoomRatio);
|
|
727
812
|
}
|
|
728
813
|
|
|
729
|
-
|
|
730
|
-
|
|
814
|
+
const originalEvent = this.actionEvent || null;
|
|
815
|
+
|
|
816
|
+
this.actionEvent = null;
|
|
817
|
+
|
|
818
|
+
if (originalEvent && originalEvent.type !== EVENT_CLICK) {
|
|
819
|
+
switch (originalEvent.type) {
|
|
731
820
|
case 'wheel':
|
|
732
821
|
if (options.zoomRatio >= 0.055 && ratio > 0.95 && ratio < 1.05) {
|
|
733
822
|
ratio = 1;
|
|
@@ -761,20 +850,20 @@ export default {
|
|
|
761
850
|
if (dispatchEvent(element, EVENT_ZOOM, {
|
|
762
851
|
ratio,
|
|
763
852
|
oldRatio,
|
|
764
|
-
originalEvent
|
|
853
|
+
originalEvent,
|
|
765
854
|
}) === false) {
|
|
766
855
|
return this;
|
|
767
856
|
}
|
|
768
857
|
|
|
769
858
|
this.zooming = true;
|
|
770
859
|
|
|
771
|
-
if (
|
|
860
|
+
if (originalEvent && originalEvent.type !== EVENT_CLICK) {
|
|
772
861
|
const offset = getOffset(this.viewer);
|
|
773
862
|
const center = pointers && Object.keys(pointers).length > 0
|
|
774
863
|
? getPointersCenter(pointers)
|
|
775
864
|
: {
|
|
776
|
-
pageX:
|
|
777
|
-
pageY:
|
|
865
|
+
pageX: originalEvent.pageX,
|
|
866
|
+
pageY: originalEvent.pageY,
|
|
778
867
|
};
|
|
779
868
|
|
|
780
869
|
// Zoom from the triggering point of the event
|
|
@@ -795,6 +884,7 @@ export default {
|
|
|
795
884
|
imageData.height = newHeight;
|
|
796
885
|
imageData.oldRatio = oldRatio;
|
|
797
886
|
imageData.ratio = ratio;
|
|
887
|
+
toggleClass(this.image, CLASS_TRANSITION, isTransitionEnabled(options, 'zoom'));
|
|
798
888
|
this.renderImage(() => {
|
|
799
889
|
this.zooming = false;
|
|
800
890
|
|
|
@@ -807,7 +897,7 @@ export default {
|
|
|
807
897
|
dispatchEvent(element, EVENT_ZOOMED, {
|
|
808
898
|
ratio,
|
|
809
899
|
oldRatio,
|
|
810
|
-
originalEvent
|
|
900
|
+
originalEvent,
|
|
811
901
|
}, {
|
|
812
902
|
cancelable: false,
|
|
813
903
|
});
|
|
@@ -832,6 +922,9 @@ export default {
|
|
|
832
922
|
}
|
|
833
923
|
|
|
834
924
|
const { element, options } = this;
|
|
925
|
+
const originalEvent = this.actionEvent || null;
|
|
926
|
+
|
|
927
|
+
this.actionEvent = null;
|
|
835
928
|
|
|
836
929
|
if (isFunction(options.play)) {
|
|
837
930
|
addListener(element, EVENT_PLAY, options.play, {
|
|
@@ -839,7 +932,9 @@ export default {
|
|
|
839
932
|
});
|
|
840
933
|
}
|
|
841
934
|
|
|
842
|
-
if (dispatchEvent(element, EVENT_PLAY
|
|
935
|
+
if (dispatchEvent(element, EVENT_PLAY, {
|
|
936
|
+
originalEvent,
|
|
937
|
+
}) === false) {
|
|
843
938
|
return this;
|
|
844
939
|
}
|
|
845
940
|
|
|
@@ -857,18 +952,18 @@ export default {
|
|
|
857
952
|
}
|
|
858
953
|
|
|
859
954
|
addClass(player, CLASS_SHOW);
|
|
860
|
-
|
|
861
|
-
|
|
955
|
+
player.removeAttribute('aria-hidden');
|
|
956
|
+
forEach(this.images, (originalImage, i) => {
|
|
862
957
|
const image = document.createElement('img');
|
|
863
958
|
|
|
864
|
-
image.src =
|
|
865
|
-
image.alt =
|
|
866
|
-
image.referrerPolicy =
|
|
959
|
+
image.src = this.getImageURL(originalImage) || originalImage.src;
|
|
960
|
+
image.alt = originalImage.alt || '';
|
|
961
|
+
image.referrerPolicy = originalImage.referrerPolicy;
|
|
867
962
|
total += 1;
|
|
868
963
|
addClass(image, CLASS_FADE);
|
|
869
|
-
toggleClass(image, CLASS_TRANSITION, options
|
|
964
|
+
toggleClass(image, CLASS_TRANSITION, isTransitionEnabled(options, 'play'));
|
|
870
965
|
|
|
871
|
-
if (
|
|
966
|
+
if (i === this.index) {
|
|
872
967
|
addClass(image, CLASS_IN);
|
|
873
968
|
index = i;
|
|
874
969
|
}
|
|
@@ -883,26 +978,74 @@ export default {
|
|
|
883
978
|
if (isNumber(options.interval) && options.interval > 0) {
|
|
884
979
|
const prev = () => {
|
|
885
980
|
clearTimeout(this.playing.timeout);
|
|
981
|
+
|
|
982
|
+
const currentOriginalEvent = this.actionEvent || null;
|
|
983
|
+
|
|
984
|
+
this.actionEvent = null;
|
|
985
|
+
|
|
986
|
+
let prevIndex = index - 1;
|
|
987
|
+
|
|
988
|
+
prevIndex = prevIndex >= 0 ? prevIndex : total - 1;
|
|
989
|
+
|
|
990
|
+
if (isFunction(options.playing)) {
|
|
991
|
+
addListener(element, EVENT_PLAYING, options.playing, {
|
|
992
|
+
once: true,
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
if (dispatchEvent(element, EVENT_PLAYING, {
|
|
997
|
+
originalImage: this.images[prevIndex],
|
|
998
|
+
index: prevIndex,
|
|
999
|
+
image: list[prevIndex],
|
|
1000
|
+
originalEvent: currentOriginalEvent,
|
|
1001
|
+
}) === false) {
|
|
1002
|
+
this.playing.timeout = options.autoplay ? setTimeout(prev, options.interval) : null;
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
886
1006
|
removeClass(list[index], CLASS_IN);
|
|
887
|
-
index
|
|
888
|
-
index = index >= 0 ? index : total - 1;
|
|
1007
|
+
index = prevIndex;
|
|
889
1008
|
addClass(list[index], CLASS_IN);
|
|
890
|
-
this.playing.timeout = setTimeout(prev, options.interval);
|
|
1009
|
+
this.playing.timeout = options.autoplay ? setTimeout(prev, options.interval) : null;
|
|
891
1010
|
};
|
|
892
1011
|
const next = () => {
|
|
893
1012
|
clearTimeout(this.playing.timeout);
|
|
1013
|
+
|
|
1014
|
+
const currentOriginalEvent = this.actionEvent || null;
|
|
1015
|
+
|
|
1016
|
+
this.actionEvent = null;
|
|
1017
|
+
|
|
1018
|
+
let nextIndex = index + 1;
|
|
1019
|
+
|
|
1020
|
+
nextIndex = nextIndex < total ? nextIndex : 0;
|
|
1021
|
+
|
|
1022
|
+
if (isFunction(options.playing)) {
|
|
1023
|
+
addListener(element, EVENT_PLAYING, options.playing, {
|
|
1024
|
+
once: true,
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
if (dispatchEvent(element, EVENT_PLAYING, {
|
|
1029
|
+
originalImage: this.images[nextIndex],
|
|
1030
|
+
index: nextIndex,
|
|
1031
|
+
image: list[nextIndex],
|
|
1032
|
+
originalEvent: currentOriginalEvent,
|
|
1033
|
+
}) === false) {
|
|
1034
|
+
this.playing.timeout = options.autoplay ? setTimeout(next, options.interval) : null;
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
894
1038
|
removeClass(list[index], CLASS_IN);
|
|
895
|
-
index
|
|
896
|
-
index = index < total ? index : 0;
|
|
1039
|
+
index = nextIndex;
|
|
897
1040
|
addClass(list[index], CLASS_IN);
|
|
898
|
-
this.playing.timeout = setTimeout(next, options.interval);
|
|
1041
|
+
this.playing.timeout = options.autoplay ? setTimeout(next, options.interval) : null;
|
|
899
1042
|
};
|
|
900
1043
|
|
|
901
1044
|
if (total > 1) {
|
|
902
1045
|
this.playing = {
|
|
903
1046
|
prev,
|
|
904
1047
|
next,
|
|
905
|
-
timeout: setTimeout(next, options.interval),
|
|
1048
|
+
timeout: options.autoplay ? setTimeout(next, options.interval) : null,
|
|
906
1049
|
};
|
|
907
1050
|
}
|
|
908
1051
|
}
|
|
@@ -910,13 +1053,19 @@ export default {
|
|
|
910
1053
|
return this;
|
|
911
1054
|
},
|
|
912
1055
|
|
|
913
|
-
|
|
1056
|
+
/**
|
|
1057
|
+
* Stop play
|
|
1058
|
+
* @returns {Viewer} this
|
|
1059
|
+
*/
|
|
914
1060
|
stop() {
|
|
915
1061
|
if (!this.played) {
|
|
916
1062
|
return this;
|
|
917
1063
|
}
|
|
918
1064
|
|
|
919
1065
|
const { element, options } = this;
|
|
1066
|
+
const originalEvent = this.actionEvent || null;
|
|
1067
|
+
|
|
1068
|
+
this.actionEvent = null;
|
|
920
1069
|
|
|
921
1070
|
if (isFunction(options.stop)) {
|
|
922
1071
|
addListener(element, EVENT_STOP, options.stop, {
|
|
@@ -924,7 +1073,9 @@ export default {
|
|
|
924
1073
|
});
|
|
925
1074
|
}
|
|
926
1075
|
|
|
927
|
-
if (dispatchEvent(element, EVENT_STOP
|
|
1076
|
+
if (dispatchEvent(element, EVENT_STOP, {
|
|
1077
|
+
originalEvent,
|
|
1078
|
+
}) === false) {
|
|
928
1079
|
return this;
|
|
929
1080
|
}
|
|
930
1081
|
|
|
@@ -937,6 +1088,7 @@ export default {
|
|
|
937
1088
|
removeListener(image, EVENT_LOAD, this.onLoadWhenPlay);
|
|
938
1089
|
});
|
|
939
1090
|
removeClass(player, CLASS_SHOW);
|
|
1091
|
+
player.setAttribute('aria-hidden', true);
|
|
940
1092
|
player.innerHTML = '';
|
|
941
1093
|
this.exitFullscreen();
|
|
942
1094
|
|
|
@@ -960,12 +1112,10 @@ export default {
|
|
|
960
1112
|
this.open();
|
|
961
1113
|
addClass(this.button, CLASS_FULLSCREEN_EXIT);
|
|
962
1114
|
|
|
963
|
-
|
|
964
|
-
removeClass(list, CLASS_TRANSITION);
|
|
1115
|
+
removeClass(list, CLASS_TRANSITION);
|
|
965
1116
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
}
|
|
1117
|
+
if (this.viewed) {
|
|
1118
|
+
removeClass(image, CLASS_TRANSITION);
|
|
969
1119
|
}
|
|
970
1120
|
|
|
971
1121
|
addClass(viewer, CLASS_FIXED);
|
|
@@ -987,14 +1137,7 @@ export default {
|
|
|
987
1137
|
|
|
988
1138
|
if (this.viewed) {
|
|
989
1139
|
this.initImage(() => {
|
|
990
|
-
this.renderImage(
|
|
991
|
-
if (options.transition) {
|
|
992
|
-
setTimeout(() => {
|
|
993
|
-
addClass(image, CLASS_TRANSITION);
|
|
994
|
-
addClass(list, CLASS_TRANSITION);
|
|
995
|
-
}, 0);
|
|
996
|
-
}
|
|
997
|
-
});
|
|
1140
|
+
this.renderImage();
|
|
998
1141
|
});
|
|
999
1142
|
}
|
|
1000
1143
|
|
|
@@ -1018,12 +1161,10 @@ export default {
|
|
|
1018
1161
|
this.close();
|
|
1019
1162
|
removeClass(this.button, CLASS_FULLSCREEN_EXIT);
|
|
1020
1163
|
|
|
1021
|
-
|
|
1022
|
-
removeClass(list, CLASS_TRANSITION);
|
|
1164
|
+
removeClass(list, CLASS_TRANSITION);
|
|
1023
1165
|
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
}
|
|
1166
|
+
if (this.viewed) {
|
|
1167
|
+
removeClass(image, CLASS_TRANSITION);
|
|
1027
1168
|
}
|
|
1028
1169
|
|
|
1029
1170
|
if (options.focus) {
|
|
@@ -1044,14 +1185,7 @@ export default {
|
|
|
1044
1185
|
|
|
1045
1186
|
if (this.viewed) {
|
|
1046
1187
|
this.initImage(() => {
|
|
1047
|
-
this.renderImage(
|
|
1048
|
-
if (options.transition) {
|
|
1049
|
-
setTimeout(() => {
|
|
1050
|
-
addClass(image, CLASS_TRANSITION);
|
|
1051
|
-
addClass(list, CLASS_TRANSITION);
|
|
1052
|
-
}, 0);
|
|
1053
|
-
}
|
|
1054
|
-
});
|
|
1188
|
+
this.renderImage();
|
|
1055
1189
|
});
|
|
1056
1190
|
}
|
|
1057
1191
|
|
|
@@ -1069,7 +1203,7 @@ export default {
|
|
|
1069
1203
|
tooltipBox.textContent = `${Math.round(imageData.ratio * 100)}%`;
|
|
1070
1204
|
|
|
1071
1205
|
if (!this.tooltipping) {
|
|
1072
|
-
if (options
|
|
1206
|
+
if (isTransitionEnabled(options, 'tooltip')) {
|
|
1073
1207
|
if (this.fading) {
|
|
1074
1208
|
dispatchEvent(tooltipBox, EVENT_TRANSITION_END);
|
|
1075
1209
|
}
|
|
@@ -1091,7 +1225,7 @@ export default {
|
|
|
1091
1225
|
}
|
|
1092
1226
|
|
|
1093
1227
|
this.tooltipping = setTimeout(() => {
|
|
1094
|
-
if (options
|
|
1228
|
+
if (isTransitionEnabled(options, 'tooltip')) {
|
|
1095
1229
|
addListener(tooltipBox, EVENT_TRANSITION_END, () => {
|
|
1096
1230
|
removeClass(tooltipBox, CLASS_SHOW);
|
|
1097
1231
|
removeClass(tooltipBox, CLASS_FADE);
|
|
@@ -1117,14 +1251,13 @@ export default {
|
|
|
1117
1251
|
|
|
1118
1252
|
/**
|
|
1119
1253
|
* Toggle the image size between its current size and natural size
|
|
1120
|
-
* @param {Event} [_originalEvent=null] - The original event if any.
|
|
1121
1254
|
* @returns {Viewer} this
|
|
1122
1255
|
*/
|
|
1123
|
-
toggle(
|
|
1256
|
+
toggle() {
|
|
1124
1257
|
if (this.imageData.ratio === 1) {
|
|
1125
|
-
this.zoomTo(this.imageData.oldRatio, true
|
|
1258
|
+
this.zoomTo(this.imageData.oldRatio, true);
|
|
1126
1259
|
} else {
|
|
1127
|
-
this.zoomTo(1, true
|
|
1260
|
+
this.zoomTo(1, true);
|
|
1128
1261
|
}
|
|
1129
1262
|
|
|
1130
1263
|
return this;
|
|
@@ -1140,10 +1273,18 @@ export default {
|
|
|
1140
1273
|
return this;
|
|
1141
1274
|
},
|
|
1142
1275
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1276
|
+
/**
|
|
1277
|
+
* Update the viewer when images or options changed.
|
|
1278
|
+
* @param {Object} [updateOptions] - The options to update.
|
|
1279
|
+
* @returns {Viewer} this
|
|
1280
|
+
*/
|
|
1281
|
+
update(updateOptions) {
|
|
1145
1282
|
const { element, options, isImg } = this;
|
|
1146
1283
|
|
|
1284
|
+
if (isPlainObject(updateOptions)) {
|
|
1285
|
+
assign(options, updateOptions);
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1147
1288
|
// Destroy viewer if the target image was deleted
|
|
1148
1289
|
if (isImg && !element.parentNode) {
|
|
1149
1290
|
return this.destroy();
|
|
@@ -1171,9 +1312,10 @@ export default {
|
|
|
1171
1312
|
if (this.ready) {
|
|
1172
1313
|
const changedIndexes = [];
|
|
1173
1314
|
|
|
1174
|
-
forEach(this.items, (item
|
|
1315
|
+
forEach(this.items, (item) => {
|
|
1175
1316
|
const img = item.querySelector('img');
|
|
1176
|
-
const
|
|
1317
|
+
const index = Number(getData(item, 'index'));
|
|
1318
|
+
const image = images[index];
|
|
1177
1319
|
|
|
1178
1320
|
if (image && img) {
|
|
1179
1321
|
if (
|
|
@@ -1182,10 +1324,10 @@ export default {
|
|
|
1182
1324
|
// Title changed (#408)
|
|
1183
1325
|
|| image.alt !== img.alt
|
|
1184
1326
|
) {
|
|
1185
|
-
changedIndexes.push(
|
|
1327
|
+
changedIndexes.push(index);
|
|
1186
1328
|
}
|
|
1187
1329
|
} else {
|
|
1188
|
-
changedIndexes.push(
|
|
1330
|
+
changedIndexes.push(index);
|
|
1189
1331
|
}
|
|
1190
1332
|
});
|
|
1191
1333
|
|
|
@@ -1204,7 +1346,7 @@ export default {
|
|
|
1204
1346
|
this.viewed = false;
|
|
1205
1347
|
this.view(Math.max(Math.min(this.index - changedIndex, this.length - 1), 0));
|
|
1206
1348
|
} else {
|
|
1207
|
-
const activeItem = this.
|
|
1349
|
+
const activeItem = this.getItem(this.index);
|
|
1208
1350
|
|
|
1209
1351
|
// Reactivate the current viewing item after reset the list.
|
|
1210
1352
|
addClass(activeItem, CLASS_ACTIVE);
|