viewerjs 1.13.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/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,
@@ -75,13 +76,23 @@ export default {
75
76
  return this;
76
77
  }
77
78
 
79
+ const originalEvent = this.actionEvent
80
+ || this.showOriginalEvent
81
+ || this.viewOriginalEvent
82
+ || null;
83
+
84
+ this.actionEvent = null;
85
+ this.showOriginalEvent = originalEvent;
86
+
78
87
  if (isFunction(options.show)) {
79
88
  addListener(element, EVENT_SHOW, options.show, {
80
89
  once: true,
81
90
  });
82
91
  }
83
92
 
84
- if (dispatchEvent(element, EVENT_SHOW) === false || !this.ready) {
93
+ if (dispatchEvent(element, EVENT_SHOW, {
94
+ originalEvent,
95
+ }) === false || !this.ready) {
85
96
  return this;
86
97
  }
87
98
 
@@ -138,13 +149,20 @@ export default {
138
149
  return this;
139
150
  }
140
151
 
152
+ const originalEvent = this.actionEvent || this.hideOriginalEvent || null;
153
+
154
+ this.actionEvent = null;
155
+ this.hideOriginalEvent = originalEvent;
156
+
141
157
  if (isFunction(options.hide)) {
142
158
  addListener(element, EVENT_HIDE, options.hide, {
143
159
  once: true,
144
160
  });
145
161
  }
146
162
 
147
- if (dispatchEvent(element, EVENT_HIDE) === false || this.destroyed) {
163
+ if (dispatchEvent(element, EVENT_HIDE, {
164
+ originalEvent,
165
+ }) === false || this.destroyed) {
148
166
  return this;
149
167
  }
150
168
 
@@ -200,7 +218,7 @@ export default {
200
218
  addListener(image, EVENT_TRANSITION_END, onImageTransitionEnd, {
201
219
  once: true,
202
220
  });
203
- this.zoomTo(0, false, null, null, true);
221
+ this.zoomTo(0, false, null, true);
204
222
  } else {
205
223
  onImageTransitionEnd();
206
224
  }
@@ -226,6 +244,11 @@ export default {
226
244
  return this;
227
245
  }
228
246
 
247
+ const originalEvent = this.actionEvent || this.viewOriginalEvent || null;
248
+
249
+ this.actionEvent = null;
250
+ this.viewOriginalEvent = originalEvent;
251
+
229
252
  if (!this.isShown) {
230
253
  this.index = index;
231
254
  return this.show();
@@ -267,6 +290,7 @@ export default {
267
290
  originalImage: this.images[index],
268
291
  index,
269
292
  image,
293
+ originalEvent,
270
294
  }) === false || !this.isShown || this.hiding || this.played) {
271
295
  return this;
272
296
  }
@@ -337,71 +361,87 @@ export default {
337
361
  }
338
362
  }
339
363
  };
340
- let onLoad;
341
- let onError;
342
364
 
343
365
  addListener(element, EVENT_VIEWED, onViewed, {
344
366
  once: true,
345
367
  });
346
368
 
347
- this.viewing = {
348
- abort: () => {
349
- removeListener(element, EVENT_VIEWED, onViewed);
369
+ const loadImage = (isFallback = false) => {
370
+ let onLoad;
371
+ let onError;
350
372
 
351
- if (image.complete) {
352
- if (this.imageRendering) {
353
- this.imageRendering.abort();
354
- } else if (this.imageInitializing) {
355
- this.imageInitializing.abort();
356
- }
357
- } else {
358
- // Cancel download to save bandwidth.
359
- image.src = '';
360
- removeListener(image, EVENT_LOAD, onLoad);
361
-
362
- if (this.timeout) {
363
- clearTimeout(this.timeout);
364
- }
365
- }
366
- },
367
- };
368
-
369
- if (image.complete) {
370
- this.load();
371
- } else {
372
- addListener(image, EVENT_LOAD, onLoad = () => {
373
- removeListener(image, EVENT_ERROR, onError);
374
- this.load();
375
- }, {
376
- once: true,
377
- });
378
- addListener(image, EVENT_ERROR, onError = () => {
373
+ const clean = () => {
379
374
  removeListener(image, EVENT_LOAD, onLoad);
375
+ removeListener(image, EVENT_ERROR, onError);
380
376
 
381
377
  if (this.timeout) {
382
378
  clearTimeout(this.timeout);
383
379
  this.timeout = false;
384
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();
412
+
413
+ if (!isFallback) {
414
+ const fallbackSrc = img.src;
385
415
 
386
- removeClass(image, CLASS_INVISIBLE);
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
+ });
387
431
 
388
- if (options.loading) {
389
- removeClass(this.canvas, CLASS_LOADING);
432
+ if (this.timeout) {
433
+ clearTimeout(this.timeout);
390
434
  }
391
- }, {
392
- once: true,
393
- });
394
435
 
395
- if (this.timeout) {
396
- clearTimeout(this.timeout);
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);
397
441
  }
442
+ };
398
443
 
399
- // Make the image visible if it fails to load within 1s
400
- this.timeout = setTimeout(() => {
401
- removeClass(image, CLASS_INVISIBLE);
402
- this.timeout = false;
403
- }, 1000);
404
- }
444
+ loadImage();
405
445
 
406
446
  return this;
407
447
  },
@@ -462,10 +502,9 @@ export default {
462
502
  * Move the image to an absolute point.
463
503
  * @param {number} x - The new position in the horizontal direction.
464
504
  * @param {number} [y=x] - The new position in the vertical direction.
465
- * @param {Event} [_originalEvent=null] - The original event if any.
466
505
  * @returns {Viewer} this
467
506
  */
468
- moveTo(x, y = x, _originalEvent = null) {
507
+ moveTo(x, y = x) {
469
508
  const { element, options, imageData } = this;
470
509
 
471
510
  x = Number(x);
@@ -489,6 +528,10 @@ export default {
489
528
  }
490
529
 
491
530
  if (changed) {
531
+ const originalEvent = this.actionEvent || null;
532
+
533
+ this.actionEvent = null;
534
+
492
535
  if (isFunction(options.move)) {
493
536
  addListener(element, EVENT_MOVE, options.move, {
494
537
  once: true,
@@ -500,7 +543,7 @@ export default {
500
543
  y,
501
544
  oldX,
502
545
  oldY,
503
- originalEvent: _originalEvent,
546
+ originalEvent,
504
547
  }) === false) {
505
548
  return this;
506
549
  }
@@ -525,7 +568,7 @@ export default {
525
568
  y,
526
569
  oldX,
527
570
  oldY,
528
- originalEvent: _originalEvent,
571
+ originalEvent,
529
572
  }, {
530
573
  cancelable: false,
531
574
  });
@@ -559,6 +602,9 @@ export default {
559
602
 
560
603
  if (isNumber(degree) && this.viewed && !this.played && options.rotatable) {
561
604
  const oldDegree = imageData.rotate;
605
+ const originalEvent = this.actionEvent || null;
606
+
607
+ this.actionEvent = null;
562
608
 
563
609
  if (isFunction(options.rotate)) {
564
610
  addListener(element, EVENT_ROTATE, options.rotate, {
@@ -569,6 +615,7 @@ export default {
569
615
  if (dispatchEvent(element, EVENT_ROTATE, {
570
616
  degree,
571
617
  oldDegree,
618
+ originalEvent,
572
619
  }) === false) {
573
620
  return this;
574
621
  }
@@ -588,6 +635,7 @@ export default {
588
635
  dispatchEvent(element, EVENT_ROTATED, {
589
636
  degree,
590
637
  oldDegree,
638
+ originalEvent,
591
639
  }, {
592
640
  cancelable: false,
593
641
  });
@@ -649,6 +697,10 @@ export default {
649
697
  }
650
698
 
651
699
  if (changed) {
700
+ const originalEvent = this.actionEvent || null;
701
+
702
+ this.actionEvent = null;
703
+
652
704
  if (isFunction(options.scale)) {
653
705
  addListener(element, EVENT_SCALE, options.scale, {
654
706
  once: true,
@@ -660,6 +712,7 @@ export default {
660
712
  scaleY,
661
713
  oldScaleX,
662
714
  oldScaleY,
715
+ originalEvent,
663
716
  }) === false) {
664
717
  return this;
665
718
  }
@@ -682,6 +735,7 @@ export default {
682
735
  scaleY,
683
736
  oldScaleX,
684
737
  oldScaleY,
738
+ originalEvent,
685
739
  }, {
686
740
  cancelable: false,
687
741
  });
@@ -697,10 +751,9 @@ export default {
697
751
  * @param {number} ratio - The target ratio.
698
752
  * @param {boolean} [showTooltip=false] - Indicates whether to show the tooltip.
699
753
  * @param {Object} [pivot] - The pivot point coordinate for zooming.
700
- * @param {Event} [_originalEvent=null] - The original event if any.
701
754
  * @returns {Viewer} this
702
755
  */
703
- zoom(ratio, showTooltip = false, pivot = null, _originalEvent = null) {
756
+ zoom(ratio, showTooltip = false, pivot = null) {
704
757
  const { imageData } = this;
705
758
 
706
759
  ratio = Number(ratio);
@@ -715,7 +768,6 @@ export default {
715
768
  (imageData.width * ratio) / imageData.naturalWidth,
716
769
  showTooltip,
717
770
  pivot,
718
- _originalEvent,
719
771
  );
720
772
 
721
773
  return this;
@@ -726,11 +778,10 @@ export default {
726
778
  * @param {number} ratio - The target ratio.
727
779
  * @param {boolean} [showTooltip] - Indicates whether to show the tooltip.
728
780
  * @param {Object} [pivot] - The pivot point coordinate for zooming.
729
- * @param {Event} [_originalEvent=null] - The original event if any.
730
- * @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.
731
782
  * @returns {Viewer} this
732
783
  */
733
- zoomTo(ratio, showTooltip = false, pivot = null, _originalEvent = null, _zoomable = false) {
784
+ zoomTo(ratio, showTooltip = false, pivot = null, _zoomable = false) {
734
785
  const {
735
786
  element,
736
787
  options,
@@ -760,8 +811,12 @@ export default {
760
811
  ratio = Math.min(Math.max(ratio, minZoomRatio), maxZoomRatio);
761
812
  }
762
813
 
763
- if (_originalEvent) {
764
- switch (_originalEvent.type) {
814
+ const originalEvent = this.actionEvent || null;
815
+
816
+ this.actionEvent = null;
817
+
818
+ if (originalEvent && originalEvent.type !== EVENT_CLICK) {
819
+ switch (originalEvent.type) {
765
820
  case 'wheel':
766
821
  if (options.zoomRatio >= 0.055 && ratio > 0.95 && ratio < 1.05) {
767
822
  ratio = 1;
@@ -795,20 +850,20 @@ export default {
795
850
  if (dispatchEvent(element, EVENT_ZOOM, {
796
851
  ratio,
797
852
  oldRatio,
798
- originalEvent: _originalEvent,
853
+ originalEvent,
799
854
  }) === false) {
800
855
  return this;
801
856
  }
802
857
 
803
858
  this.zooming = true;
804
859
 
805
- if (_originalEvent) {
860
+ if (originalEvent && originalEvent.type !== EVENT_CLICK) {
806
861
  const offset = getOffset(this.viewer);
807
862
  const center = pointers && Object.keys(pointers).length > 0
808
863
  ? getPointersCenter(pointers)
809
864
  : {
810
- pageX: _originalEvent.pageX,
811
- pageY: _originalEvent.pageY,
865
+ pageX: originalEvent.pageX,
866
+ pageY: originalEvent.pageY,
812
867
  };
813
868
 
814
869
  // Zoom from the triggering point of the event
@@ -842,7 +897,7 @@ export default {
842
897
  dispatchEvent(element, EVENT_ZOOMED, {
843
898
  ratio,
844
899
  oldRatio,
845
- originalEvent: _originalEvent,
900
+ originalEvent,
846
901
  }, {
847
902
  cancelable: false,
848
903
  });
@@ -867,6 +922,9 @@ export default {
867
922
  }
868
923
 
869
924
  const { element, options } = this;
925
+ const originalEvent = this.actionEvent || null;
926
+
927
+ this.actionEvent = null;
870
928
 
871
929
  if (isFunction(options.play)) {
872
930
  addListener(element, EVENT_PLAY, options.play, {
@@ -874,7 +932,9 @@ export default {
874
932
  });
875
933
  }
876
934
 
877
- if (dispatchEvent(element, EVENT_PLAY) === false) {
935
+ if (dispatchEvent(element, EVENT_PLAY, {
936
+ originalEvent,
937
+ }) === false) {
878
938
  return this;
879
939
  }
880
940
 
@@ -892,6 +952,7 @@ export default {
892
952
  }
893
953
 
894
954
  addClass(player, CLASS_SHOW);
955
+ player.removeAttribute('aria-hidden');
895
956
  forEach(this.images, (originalImage, i) => {
896
957
  const image = document.createElement('img');
897
958
 
@@ -917,17 +978,65 @@ export default {
917
978
  if (isNumber(options.interval) && options.interval > 0) {
918
979
  const prev = () => {
919
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
+
920
1006
  removeClass(list[index], CLASS_IN);
921
- index -= 1;
922
- index = index >= 0 ? index : total - 1;
1007
+ index = prevIndex;
923
1008
  addClass(list[index], CLASS_IN);
924
1009
  this.playing.timeout = options.autoplay ? setTimeout(prev, options.interval) : null;
925
1010
  };
926
1011
  const next = () => {
927
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
+
928
1038
  removeClass(list[index], CLASS_IN);
929
- index += 1;
930
- index = index < total ? index : 0;
1039
+ index = nextIndex;
931
1040
  addClass(list[index], CLASS_IN);
932
1041
  this.playing.timeout = options.autoplay ? setTimeout(next, options.interval) : null;
933
1042
  };
@@ -944,13 +1053,19 @@ export default {
944
1053
  return this;
945
1054
  },
946
1055
 
947
- // Stop play
1056
+ /**
1057
+ * Stop play
1058
+ * @returns {Viewer} this
1059
+ */
948
1060
  stop() {
949
1061
  if (!this.played) {
950
1062
  return this;
951
1063
  }
952
1064
 
953
1065
  const { element, options } = this;
1066
+ const originalEvent = this.actionEvent || null;
1067
+
1068
+ this.actionEvent = null;
954
1069
 
955
1070
  if (isFunction(options.stop)) {
956
1071
  addListener(element, EVENT_STOP, options.stop, {
@@ -958,7 +1073,9 @@ export default {
958
1073
  });
959
1074
  }
960
1075
 
961
- if (dispatchEvent(element, EVENT_STOP) === false) {
1076
+ if (dispatchEvent(element, EVENT_STOP, {
1077
+ originalEvent,
1078
+ }) === false) {
962
1079
  return this;
963
1080
  }
964
1081
 
@@ -971,6 +1088,7 @@ export default {
971
1088
  removeListener(image, EVENT_LOAD, this.onLoadWhenPlay);
972
1089
  });
973
1090
  removeClass(player, CLASS_SHOW);
1091
+ player.setAttribute('aria-hidden', true);
974
1092
  player.innerHTML = '';
975
1093
  this.exitFullscreen();
976
1094
 
@@ -1133,14 +1251,13 @@ export default {
1133
1251
 
1134
1252
  /**
1135
1253
  * Toggle the image size between its current size and natural size
1136
- * @param {Event} [_originalEvent=null] - The original event if any.
1137
1254
  * @returns {Viewer} this
1138
1255
  */
1139
- toggle(_originalEvent = null) {
1256
+ toggle() {
1140
1257
  if (this.imageData.ratio === 1) {
1141
- this.zoomTo(this.imageData.oldRatio, true, null, _originalEvent);
1258
+ this.zoomTo(this.imageData.oldRatio, true);
1142
1259
  } else {
1143
- this.zoomTo(1, true, null, _originalEvent);
1260
+ this.zoomTo(1, true);
1144
1261
  }
1145
1262
 
1146
1263
  return this;
package/src/js/others.js CHANGED
@@ -109,10 +109,14 @@ export default {
109
109
  });
110
110
  }
111
111
 
112
- if (dispatchEvent(element, EVENT_SHOWN) === false) {
112
+ if (dispatchEvent(element, EVENT_SHOWN, {
113
+ originalEvent: this.showOriginalEvent || null,
114
+ }) === false) {
113
115
  return;
114
116
  }
115
117
 
118
+ this.showOriginalEvent = null;
119
+
116
120
  if (this.ready && this.isShown && !this.hiding) {
117
121
  this.view(this.index);
118
122
  }
@@ -152,9 +156,13 @@ export default {
152
156
  });
153
157
  }
154
158
 
155
- dispatchEvent(element, EVENT_HIDDEN, null, {
159
+ dispatchEvent(element, EVENT_HIDDEN, {
160
+ originalEvent: this.hideOriginalEvent || null,
161
+ }, {
156
162
  cancelable: false,
157
163
  });
164
+
165
+ this.hideOriginalEvent = null;
158
166
  }
159
167
  },
160
168
 
@@ -226,7 +234,8 @@ export default {
226
234
  case ACTION_MOVE:
227
235
  if (offsetX !== 0 || offsetY !== 0) {
228
236
  this.pointerMoved = true;
229
- this.move(offsetX, offsetY, event);
237
+ this.actionEvent = event;
238
+ this.move(offsetX, offsetY);
230
239
  }
231
240
  break;
232
241
 
@@ -236,7 +245,8 @@ export default {
236
245
  const zoomRatio = getMaxZoomRatio(pointers);
237
246
 
238
247
  if (zoomRatio !== 0) {
239
- this.zoom(zoomRatio, false, null, event);
248
+ this.actionEvent = event;
249
+ this.zoom(zoomRatio);
240
250
  }
241
251
  }
242
252
  break;
@@ -247,7 +257,8 @@ export default {
247
257
  const rotateDegree = getMaxRotateDegree(pointers);
248
258
 
249
259
  if (rotateDegree !== 0) {
250
- this.rotate(rotateDegree, event);
260
+ this.actionEvent = event;
261
+ this.rotate(rotateDegree);
251
262
  }
252
263
  }
253
264
  break;
@@ -258,7 +269,8 @@ export default {
258
269
  const zoomRatio = getMaxZoomRatio(pointers);
259
270
 
260
271
  if (zoomRatio !== 0) {
261
- this.zoom(zoomRatio, false, null, event);
272
+ this.actionEvent = event;
273
+ this.zoom(zoomRatio);
262
274
  }
263
275
  }
264
276
 
@@ -266,7 +278,8 @@ export default {
266
278
  const rotateDegree = getMaxRotateDegree(pointers);
267
279
 
268
280
  if (rotateDegree !== 0) {
269
- this.rotate(rotateDegree, event);
281
+ this.actionEvent = event;
282
+ this.rotate(rotateDegree);
270
283
  }
271
284
  }
272
285
  break;
@@ -280,6 +293,8 @@ export default {
280
293
  // Empty `pointers` as `touchend` event will not be fired after swiped in iOS browsers.
281
294
  this.pointers = {};
282
295
 
296
+ this.actionEvent = event;
297
+
283
298
  if (offsetX > 1) {
284
299
  this.prev(options.loop);
285
300
  } else if (offsetX < -1) {
package/src/js/render.js CHANGED
@@ -84,6 +84,10 @@ export default {
84
84
  const navbarOptions = isPlainObject(options.navbar) ? options.navbar : {};
85
85
  const probe = document.createElement('li');
86
86
 
87
+ if (!this.containerData) {
88
+ this.initContainer();
89
+ }
90
+
87
91
  list.appendChild(probe);
88
92
  const itemWidth = probe.offsetWidth + parseInt(window.getComputedStyle(probe).marginLeft, 10);
89
93
 
@@ -4,19 +4,19 @@ export default (
4
4
  + '<div class="viewer-magnifier" aria-hidden="true">'
5
5
  + '<img class="viewer-magnifier-image" alt="">'
6
6
  + '</div>'
7
- + '<div class="viewer-navigation">'
7
+ + '<div class="viewer-navigation" aria-hidden="true">'
8
8
  + '<div class="viewer-prev" data-viewer-action="prev" role="button" aria-label="Previous"></div>'
9
9
  + '<div class="viewer-next" data-viewer-action="next" role="button" aria-label="Next"></div>'
10
10
  + '</div>'
11
- + '<div class="viewer-footer">'
12
- + '<div class="viewer-title"></div>'
13
- + '<div class="viewer-toolbar"></div>'
14
- + '<div class="viewer-navbar">'
11
+ + '<div class="viewer-footer" aria-hidden="true">'
12
+ + '<div class="viewer-title" aria-hidden="true"></div>'
13
+ + '<div class="viewer-toolbar" aria-hidden="true"></div>'
14
+ + '<div class="viewer-navbar" aria-hidden="true">'
15
15
  + '<ul class="viewer-list" role="navigation"></ul>'
16
16
  + '</div>'
17
17
  + '</div>'
18
18
  + '<div class="viewer-tooltip" role="alert" aria-hidden="true"></div>'
19
- + '<div class="viewer-button" data-viewer-action="mix" role="button"></div>'
20
- + '<div class="viewer-player"></div>'
19
+ + '<div class="viewer-button" data-viewer-action="mix" role="button" aria-hidden="true"></div>'
20
+ + '<div class="viewer-player" aria-hidden="true"></div>'
21
21
  + '</div>'
22
22
  );
@@ -16,6 +16,33 @@ export function isString(value) {
16
16
  return typeof value === 'string';
17
17
  }
18
18
 
19
+ const MODIFIER_KEY_PROPERTIES = {
20
+ ctrl: 'ctrlKey',
21
+ shift: 'shiftKey',
22
+ alt: 'altKey',
23
+ meta: 'metaKey',
24
+ };
25
+
26
+ /**
27
+ * Check if a wheel option (`zoomOnWheel` or `slideOnWheel`) takes effect for the given wheel event.
28
+ * @param {boolean | string} option - The option value.
29
+ * @param {WheelEvent} event - The wheel event.
30
+ * @returns {boolean} Returns `true` if the option takes effect for the event, else `false`.
31
+ */
32
+ export function isWheelActionEnabled(option, event) {
33
+ if (!option) {
34
+ return false;
35
+ }
36
+
37
+ if (option === true) {
38
+ return true;
39
+ }
40
+
41
+ return isString(option) && option
42
+ .split('+')
43
+ .every((key) => event[MODIFIER_KEY_PROPERTIES[key.trim().toLowerCase()]]);
44
+ }
45
+
19
46
  /**
20
47
  * Check if the given value is not a number.
21
48
  */