viewerjs 1.12.0 → 1.13.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 +204 -32
- package/dist/viewer.common.js +477 -110
- package/dist/viewer.css +111 -2
- package/dist/viewer.esm.js +477 -110
- package/dist/viewer.js +477 -110
- 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 +5 -0
- package/src/js/defaults.js +46 -4
- package/src/js/events.js +29 -2
- package/src/js/handlers.js +194 -6
- package/src/js/methods.js +86 -61
- package/src/js/others.js +42 -3
- package/src/js/render.js +83 -15
- package/src/js/template.js +7 -0
- package/src/js/utilities.js +68 -12
- package/src/js/viewer.js +69 -10
- package/types/index.d.ts +54 -7
package/src/js/methods.js
CHANGED
|
@@ -41,9 +41,11 @@ import {
|
|
|
41
41
|
getOffset,
|
|
42
42
|
getPointersCenter,
|
|
43
43
|
hasClass,
|
|
44
|
+
inheritAttributes,
|
|
44
45
|
isFunction,
|
|
45
46
|
isNumber,
|
|
46
47
|
isPlainObject,
|
|
48
|
+
isTransitionEnabled,
|
|
47
49
|
isUndefined,
|
|
48
50
|
removeClass,
|
|
49
51
|
removeListener,
|
|
@@ -98,7 +100,7 @@ export default {
|
|
|
98
100
|
viewer.setAttribute('aria-modal', true);
|
|
99
101
|
viewer.removeAttribute('aria-hidden');
|
|
100
102
|
|
|
101
|
-
if (options
|
|
103
|
+
if (isTransitionEnabled(options, 'show') && !immediate) {
|
|
102
104
|
const shown = this.shown.bind(this);
|
|
103
105
|
|
|
104
106
|
this.transitioning = {
|
|
@@ -142,7 +144,7 @@ export default {
|
|
|
142
144
|
});
|
|
143
145
|
}
|
|
144
146
|
|
|
145
|
-
if (dispatchEvent(element, EVENT_HIDE) === false) {
|
|
147
|
+
if (dispatchEvent(element, EVENT_HIDE) === false || this.destroyed) {
|
|
146
148
|
return this;
|
|
147
149
|
}
|
|
148
150
|
|
|
@@ -164,7 +166,7 @@ export default {
|
|
|
164
166
|
this.hidden();
|
|
165
167
|
};
|
|
166
168
|
|
|
167
|
-
if (options
|
|
169
|
+
if (isTransitionEnabled(options, 'hide') && !immediate) {
|
|
168
170
|
const onViewerTransitionEnd = (event) => {
|
|
169
171
|
// Ignore all propagating `transitionend` events (#275).
|
|
170
172
|
if (event && event.target === viewer) {
|
|
@@ -215,10 +217,12 @@ export default {
|
|
|
215
217
|
* @returns {Viewer} this
|
|
216
218
|
*/
|
|
217
219
|
view(index = this.options.initialViewIndex) {
|
|
220
|
+
const previousIndex = this.index;
|
|
221
|
+
|
|
218
222
|
index = Number(index) || 0;
|
|
219
223
|
|
|
220
224
|
if (this.hiding || this.played || index < 0 || index >= this.length
|
|
221
|
-
|| (this.viewed && index ===
|
|
225
|
+
|| (this.viewed && index === previousIndex)) {
|
|
222
226
|
return this;
|
|
223
227
|
}
|
|
224
228
|
|
|
@@ -237,20 +241,19 @@ export default {
|
|
|
237
241
|
title,
|
|
238
242
|
canvas,
|
|
239
243
|
} = this;
|
|
240
|
-
|
|
244
|
+
let item = this.getItem(index);
|
|
245
|
+
|
|
246
|
+
if (!item) {
|
|
247
|
+
this.initList(index);
|
|
248
|
+
item = this.getItem(index);
|
|
249
|
+
}
|
|
250
|
+
|
|
241
251
|
const img = item.querySelector('img');
|
|
242
252
|
const url = getData(img, 'originalUrl');
|
|
243
253
|
const alt = img.getAttribute('alt');
|
|
244
254
|
const image = document.createElement('img');
|
|
245
255
|
|
|
246
|
-
|
|
247
|
-
const value = img.getAttribute(name);
|
|
248
|
-
|
|
249
|
-
if (value !== null) {
|
|
250
|
-
image.setAttribute(name, value);
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
|
|
256
|
+
inheritAttributes(image, img, options.inheritedAttributes);
|
|
254
257
|
image.src = url;
|
|
255
258
|
image.alt = alt;
|
|
256
259
|
|
|
@@ -268,7 +271,9 @@ export default {
|
|
|
268
271
|
return this;
|
|
269
272
|
}
|
|
270
273
|
|
|
271
|
-
|
|
274
|
+
this.hideMagnifier();
|
|
275
|
+
|
|
276
|
+
const activeItem = this.getItem(previousIndex);
|
|
272
277
|
|
|
273
278
|
if (activeItem) {
|
|
274
279
|
removeClass(activeItem, CLASS_ACTIVE);
|
|
@@ -309,6 +314,28 @@ export default {
|
|
|
309
314
|
title.innerHTML = escapeHTMLEntities(isFunction(render)
|
|
310
315
|
? render.call(this, image, imageData)
|
|
311
316
|
: `${alt} (${imageData.naturalWidth} × ${imageData.naturalHeight})`);
|
|
317
|
+
|
|
318
|
+
// Preload the image in the direction of navigation
|
|
319
|
+
if (options.preload) {
|
|
320
|
+
const direction = index < previousIndex ? -1 : 1;
|
|
321
|
+
let nextIndex = index + direction;
|
|
322
|
+
|
|
323
|
+
if (nextIndex < 0 || nextIndex >= this.length) {
|
|
324
|
+
if (options.loop) {
|
|
325
|
+
nextIndex = direction > 0 ? 0 : this.length - 1;
|
|
326
|
+
} else {
|
|
327
|
+
nextIndex = -1;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (nextIndex !== index) {
|
|
332
|
+
const nextImage = this.images[nextIndex];
|
|
333
|
+
const preloadedImage = document.createElement('img');
|
|
334
|
+
|
|
335
|
+
inheritAttributes(preloadedImage, nextImage, options.inheritedAttributes);
|
|
336
|
+
preloadedImage.src = this.getImageURL(nextImage) || nextImage.src;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
312
339
|
};
|
|
313
340
|
let onLoad;
|
|
314
341
|
let onError;
|
|
@@ -482,6 +509,7 @@ export default {
|
|
|
482
509
|
imageData.y = y;
|
|
483
510
|
imageData.left = x;
|
|
484
511
|
imageData.top = y;
|
|
512
|
+
toggleClass(this.image, CLASS_TRANSITION, isTransitionEnabled(options, 'move'));
|
|
485
513
|
this.moving = true;
|
|
486
514
|
this.renderImage(() => {
|
|
487
515
|
this.moving = false;
|
|
@@ -546,6 +574,7 @@ export default {
|
|
|
546
574
|
}
|
|
547
575
|
|
|
548
576
|
imageData.rotate = degree;
|
|
577
|
+
toggleClass(this.image, CLASS_TRANSITION, isTransitionEnabled(options, 'rotate'));
|
|
549
578
|
this.rotating = true;
|
|
550
579
|
this.renderImage(() => {
|
|
551
580
|
this.rotating = false;
|
|
@@ -637,6 +666,7 @@ export default {
|
|
|
637
666
|
|
|
638
667
|
imageData.scaleX = scaleX;
|
|
639
668
|
imageData.scaleY = scaleY;
|
|
669
|
+
toggleClass(this.image, CLASS_TRANSITION, isTransitionEnabled(options, 'scale'));
|
|
640
670
|
this.scaling = true;
|
|
641
671
|
this.renderImage(() => {
|
|
642
672
|
this.scaling = false;
|
|
@@ -720,8 +750,12 @@ export default {
|
|
|
720
750
|
|
|
721
751
|
if (isNumber(ratio) && this.viewed && !this.played && (_zoomable || options.zoomable)) {
|
|
722
752
|
if (!_zoomable) {
|
|
723
|
-
const minZoomRatio = Math.max(0.01, options.minZoomRatio)
|
|
724
|
-
|
|
753
|
+
const minZoomRatio = Math.max(0.01, isFunction(options.minZoomRatio)
|
|
754
|
+
? options.minZoomRatio.call(this, this.image, imageData)
|
|
755
|
+
: options.minZoomRatio);
|
|
756
|
+
const maxZoomRatio = Math.min(100, isFunction(options.maxZoomRatio)
|
|
757
|
+
? options.maxZoomRatio.call(this, this.image, imageData)
|
|
758
|
+
: options.maxZoomRatio);
|
|
725
759
|
|
|
726
760
|
ratio = Math.min(Math.max(ratio, minZoomRatio), maxZoomRatio);
|
|
727
761
|
}
|
|
@@ -795,6 +829,7 @@ export default {
|
|
|
795
829
|
imageData.height = newHeight;
|
|
796
830
|
imageData.oldRatio = oldRatio;
|
|
797
831
|
imageData.ratio = ratio;
|
|
832
|
+
toggleClass(this.image, CLASS_TRANSITION, isTransitionEnabled(options, 'zoom'));
|
|
798
833
|
this.renderImage(() => {
|
|
799
834
|
this.zooming = false;
|
|
800
835
|
|
|
@@ -857,18 +892,17 @@ export default {
|
|
|
857
892
|
}
|
|
858
893
|
|
|
859
894
|
addClass(player, CLASS_SHOW);
|
|
860
|
-
forEach(this.
|
|
861
|
-
const img = item.querySelector('img');
|
|
895
|
+
forEach(this.images, (originalImage, i) => {
|
|
862
896
|
const image = document.createElement('img');
|
|
863
897
|
|
|
864
|
-
image.src =
|
|
865
|
-
image.alt =
|
|
866
|
-
image.referrerPolicy =
|
|
898
|
+
image.src = this.getImageURL(originalImage) || originalImage.src;
|
|
899
|
+
image.alt = originalImage.alt || '';
|
|
900
|
+
image.referrerPolicy = originalImage.referrerPolicy;
|
|
867
901
|
total += 1;
|
|
868
902
|
addClass(image, CLASS_FADE);
|
|
869
|
-
toggleClass(image, CLASS_TRANSITION, options
|
|
903
|
+
toggleClass(image, CLASS_TRANSITION, isTransitionEnabled(options, 'play'));
|
|
870
904
|
|
|
871
|
-
if (
|
|
905
|
+
if (i === this.index) {
|
|
872
906
|
addClass(image, CLASS_IN);
|
|
873
907
|
index = i;
|
|
874
908
|
}
|
|
@@ -887,7 +921,7 @@ export default {
|
|
|
887
921
|
index -= 1;
|
|
888
922
|
index = index >= 0 ? index : total - 1;
|
|
889
923
|
addClass(list[index], CLASS_IN);
|
|
890
|
-
this.playing.timeout = setTimeout(prev, options.interval);
|
|
924
|
+
this.playing.timeout = options.autoplay ? setTimeout(prev, options.interval) : null;
|
|
891
925
|
};
|
|
892
926
|
const next = () => {
|
|
893
927
|
clearTimeout(this.playing.timeout);
|
|
@@ -895,14 +929,14 @@ export default {
|
|
|
895
929
|
index += 1;
|
|
896
930
|
index = index < total ? index : 0;
|
|
897
931
|
addClass(list[index], CLASS_IN);
|
|
898
|
-
this.playing.timeout = setTimeout(next, options.interval);
|
|
932
|
+
this.playing.timeout = options.autoplay ? setTimeout(next, options.interval) : null;
|
|
899
933
|
};
|
|
900
934
|
|
|
901
935
|
if (total > 1) {
|
|
902
936
|
this.playing = {
|
|
903
937
|
prev,
|
|
904
938
|
next,
|
|
905
|
-
timeout: setTimeout(next, options.interval),
|
|
939
|
+
timeout: options.autoplay ? setTimeout(next, options.interval) : null,
|
|
906
940
|
};
|
|
907
941
|
}
|
|
908
942
|
}
|
|
@@ -960,12 +994,10 @@ export default {
|
|
|
960
994
|
this.open();
|
|
961
995
|
addClass(this.button, CLASS_FULLSCREEN_EXIT);
|
|
962
996
|
|
|
963
|
-
|
|
964
|
-
removeClass(list, CLASS_TRANSITION);
|
|
997
|
+
removeClass(list, CLASS_TRANSITION);
|
|
965
998
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
}
|
|
999
|
+
if (this.viewed) {
|
|
1000
|
+
removeClass(image, CLASS_TRANSITION);
|
|
969
1001
|
}
|
|
970
1002
|
|
|
971
1003
|
addClass(viewer, CLASS_FIXED);
|
|
@@ -987,14 +1019,7 @@ export default {
|
|
|
987
1019
|
|
|
988
1020
|
if (this.viewed) {
|
|
989
1021
|
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
|
-
});
|
|
1022
|
+
this.renderImage();
|
|
998
1023
|
});
|
|
999
1024
|
}
|
|
1000
1025
|
|
|
@@ -1018,12 +1043,10 @@ export default {
|
|
|
1018
1043
|
this.close();
|
|
1019
1044
|
removeClass(this.button, CLASS_FULLSCREEN_EXIT);
|
|
1020
1045
|
|
|
1021
|
-
|
|
1022
|
-
removeClass(list, CLASS_TRANSITION);
|
|
1046
|
+
removeClass(list, CLASS_TRANSITION);
|
|
1023
1047
|
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
}
|
|
1048
|
+
if (this.viewed) {
|
|
1049
|
+
removeClass(image, CLASS_TRANSITION);
|
|
1027
1050
|
}
|
|
1028
1051
|
|
|
1029
1052
|
if (options.focus) {
|
|
@@ -1044,14 +1067,7 @@ export default {
|
|
|
1044
1067
|
|
|
1045
1068
|
if (this.viewed) {
|
|
1046
1069
|
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
|
-
});
|
|
1070
|
+
this.renderImage();
|
|
1055
1071
|
});
|
|
1056
1072
|
}
|
|
1057
1073
|
|
|
@@ -1069,7 +1085,7 @@ export default {
|
|
|
1069
1085
|
tooltipBox.textContent = `${Math.round(imageData.ratio * 100)}%`;
|
|
1070
1086
|
|
|
1071
1087
|
if (!this.tooltipping) {
|
|
1072
|
-
if (options
|
|
1088
|
+
if (isTransitionEnabled(options, 'tooltip')) {
|
|
1073
1089
|
if (this.fading) {
|
|
1074
1090
|
dispatchEvent(tooltipBox, EVENT_TRANSITION_END);
|
|
1075
1091
|
}
|
|
@@ -1091,7 +1107,7 @@ export default {
|
|
|
1091
1107
|
}
|
|
1092
1108
|
|
|
1093
1109
|
this.tooltipping = setTimeout(() => {
|
|
1094
|
-
if (options
|
|
1110
|
+
if (isTransitionEnabled(options, 'tooltip')) {
|
|
1095
1111
|
addListener(tooltipBox, EVENT_TRANSITION_END, () => {
|
|
1096
1112
|
removeClass(tooltipBox, CLASS_SHOW);
|
|
1097
1113
|
removeClass(tooltipBox, CLASS_FADE);
|
|
@@ -1140,10 +1156,18 @@ export default {
|
|
|
1140
1156
|
return this;
|
|
1141
1157
|
},
|
|
1142
1158
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1159
|
+
/**
|
|
1160
|
+
* Update the viewer when images or options changed.
|
|
1161
|
+
* @param {Object} [updateOptions] - The options to update.
|
|
1162
|
+
* @returns {Viewer} this
|
|
1163
|
+
*/
|
|
1164
|
+
update(updateOptions) {
|
|
1145
1165
|
const { element, options, isImg } = this;
|
|
1146
1166
|
|
|
1167
|
+
if (isPlainObject(updateOptions)) {
|
|
1168
|
+
assign(options, updateOptions);
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1147
1171
|
// Destroy viewer if the target image was deleted
|
|
1148
1172
|
if (isImg && !element.parentNode) {
|
|
1149
1173
|
return this.destroy();
|
|
@@ -1171,9 +1195,10 @@ export default {
|
|
|
1171
1195
|
if (this.ready) {
|
|
1172
1196
|
const changedIndexes = [];
|
|
1173
1197
|
|
|
1174
|
-
forEach(this.items, (item
|
|
1198
|
+
forEach(this.items, (item) => {
|
|
1175
1199
|
const img = item.querySelector('img');
|
|
1176
|
-
const
|
|
1200
|
+
const index = Number(getData(item, 'index'));
|
|
1201
|
+
const image = images[index];
|
|
1177
1202
|
|
|
1178
1203
|
if (image && img) {
|
|
1179
1204
|
if (
|
|
@@ -1182,10 +1207,10 @@ export default {
|
|
|
1182
1207
|
// Title changed (#408)
|
|
1183
1208
|
|| image.alt !== img.alt
|
|
1184
1209
|
) {
|
|
1185
|
-
changedIndexes.push(
|
|
1210
|
+
changedIndexes.push(index);
|
|
1186
1211
|
}
|
|
1187
1212
|
} else {
|
|
1188
|
-
changedIndexes.push(
|
|
1213
|
+
changedIndexes.push(index);
|
|
1189
1214
|
}
|
|
1190
1215
|
});
|
|
1191
1216
|
|
|
@@ -1204,7 +1229,7 @@ export default {
|
|
|
1204
1229
|
this.viewed = false;
|
|
1205
1230
|
this.view(Math.max(Math.min(this.index - changedIndex, this.length - 1), 0));
|
|
1206
1231
|
} else {
|
|
1207
|
-
const activeItem = this.
|
|
1232
|
+
const activeItem = this.getItem(this.index);
|
|
1208
1233
|
|
|
1209
1234
|
// Reactivate the current viewing item after reset the list.
|
|
1210
1235
|
addClass(activeItem, CLASS_ACTIVE);
|
package/src/js/others.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ACTION_MOVE,
|
|
3
|
+
ACTION_ROTATE,
|
|
3
4
|
ACTION_SWITCH,
|
|
5
|
+
ACTION_TRANSFORM,
|
|
4
6
|
ACTION_ZOOM,
|
|
5
7
|
CLASS_HIDE,
|
|
6
8
|
CLASS_OPEN,
|
|
@@ -13,6 +15,7 @@ import {
|
|
|
13
15
|
addListener,
|
|
14
16
|
dispatchEvent,
|
|
15
17
|
forEach,
|
|
18
|
+
getMaxRotateDegree,
|
|
16
19
|
getMaxZoomRatio,
|
|
17
20
|
isFunction,
|
|
18
21
|
isPlainObject,
|
|
@@ -156,7 +159,7 @@ export default {
|
|
|
156
159
|
},
|
|
157
160
|
|
|
158
161
|
requestFullscreen(options) {
|
|
159
|
-
const document = this
|
|
162
|
+
const { ownerDocument: document } = this;
|
|
160
163
|
|
|
161
164
|
if (this.fulled && !(
|
|
162
165
|
document.fullscreenElement
|
|
@@ -185,7 +188,7 @@ export default {
|
|
|
185
188
|
},
|
|
186
189
|
|
|
187
190
|
exitFullscreen() {
|
|
188
|
-
const document = this
|
|
191
|
+
const { ownerDocument: document } = this;
|
|
189
192
|
|
|
190
193
|
if (this.fulled && (
|
|
191
194
|
document.fullscreenElement
|
|
@@ -229,7 +232,43 @@ export default {
|
|
|
229
232
|
|
|
230
233
|
// Zoom the current image
|
|
231
234
|
case ACTION_ZOOM:
|
|
232
|
-
|
|
235
|
+
if (options.zoomable && options.zoomOnTouch) {
|
|
236
|
+
const zoomRatio = getMaxZoomRatio(pointers);
|
|
237
|
+
|
|
238
|
+
if (zoomRatio !== 0) {
|
|
239
|
+
this.zoom(zoomRatio, false, null, event);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
break;
|
|
243
|
+
|
|
244
|
+
// Rotate the current image
|
|
245
|
+
case ACTION_ROTATE:
|
|
246
|
+
if (options.rotatable && options.rotateOnTouch) {
|
|
247
|
+
const rotateDegree = getMaxRotateDegree(pointers);
|
|
248
|
+
|
|
249
|
+
if (rotateDegree !== 0) {
|
|
250
|
+
this.rotate(rotateDegree, event);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
break;
|
|
254
|
+
|
|
255
|
+
// Transform the current image
|
|
256
|
+
case ACTION_TRANSFORM:
|
|
257
|
+
if (options.zoomable && options.zoomOnTouch) {
|
|
258
|
+
const zoomRatio = getMaxZoomRatio(pointers);
|
|
259
|
+
|
|
260
|
+
if (zoomRatio !== 0) {
|
|
261
|
+
this.zoom(zoomRatio, false, null, event);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (options.rotatable && options.rotateOnTouch) {
|
|
266
|
+
const rotateDegree = getMaxRotateDegree(pointers);
|
|
267
|
+
|
|
268
|
+
if (rotateDegree !== 0) {
|
|
269
|
+
this.rotate(rotateDegree, event);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
233
272
|
break;
|
|
234
273
|
|
|
235
274
|
case ACTION_SWITCH: {
|
package/src/js/render.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CLASS_ACTIVE,
|
|
2
3
|
CLASS_LOADING,
|
|
3
4
|
CLASS_TRANSITION,
|
|
4
5
|
EVENT_ERROR,
|
|
@@ -11,11 +12,15 @@ import {
|
|
|
11
12
|
addListener,
|
|
12
13
|
assign,
|
|
13
14
|
forEach,
|
|
15
|
+
getData,
|
|
14
16
|
getImageNameFromURL,
|
|
15
17
|
getImageNaturalSizes,
|
|
16
18
|
getTransforms,
|
|
17
19
|
hasClass,
|
|
20
|
+
inheritAttributes,
|
|
18
21
|
isNumber,
|
|
22
|
+
isPlainObject,
|
|
23
|
+
isTransitionEnabled,
|
|
19
24
|
removeClass,
|
|
20
25
|
removeListener,
|
|
21
26
|
setData,
|
|
@@ -31,7 +36,7 @@ export default {
|
|
|
31
36
|
},
|
|
32
37
|
|
|
33
38
|
initBody() {
|
|
34
|
-
const { ownerDocument } = this
|
|
39
|
+
const { ownerDocument } = this;
|
|
35
40
|
const body = ownerDocument.body || ownerDocument.documentElement;
|
|
36
41
|
|
|
37
42
|
this.body = body;
|
|
@@ -73,14 +78,41 @@ export default {
|
|
|
73
78
|
}
|
|
74
79
|
},
|
|
75
80
|
|
|
76
|
-
initList() {
|
|
81
|
+
initList(viewIndex = this.index) {
|
|
77
82
|
const { element, options, list } = this;
|
|
78
83
|
const items = [];
|
|
84
|
+
const navbarOptions = isPlainObject(options.navbar) ? options.navbar : {};
|
|
85
|
+
const probe = document.createElement('li');
|
|
86
|
+
|
|
87
|
+
list.appendChild(probe);
|
|
88
|
+
const itemWidth = probe.offsetWidth + parseInt(window.getComputedStyle(probe).marginLeft, 10);
|
|
89
|
+
|
|
90
|
+
list.removeChild(probe);
|
|
91
|
+
|
|
92
|
+
let visibleItemCount = isNumber(navbarOptions.visibleItemCount)
|
|
93
|
+
? Math.floor(navbarOptions.visibleItemCount)
|
|
94
|
+
: Math.floor(this.containerData.width / itemWidth);
|
|
95
|
+
|
|
96
|
+
visibleItemCount = Math.min(visibleItemCount, this.length);
|
|
97
|
+
|
|
98
|
+
const start = visibleItemCount > 0
|
|
99
|
+
? Math.min(
|
|
100
|
+
Math.max(0, viewIndex - Math.floor(visibleItemCount / 2)),
|
|
101
|
+
Math.max(0, this.length - visibleItemCount),
|
|
102
|
+
)
|
|
103
|
+
: 0;
|
|
104
|
+
const end = visibleItemCount > 0
|
|
105
|
+
? Math.min(this.length, start + visibleItemCount)
|
|
106
|
+
: this.length;
|
|
79
107
|
|
|
80
108
|
// initList may be called in this.update, so should keep idempotent
|
|
81
109
|
list.innerHTML = '';
|
|
82
110
|
|
|
83
111
|
forEach(this.images, (image, index) => {
|
|
112
|
+
if (visibleItemCount > 0 && (index < start || index >= end)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
84
116
|
const { src } = image;
|
|
85
117
|
const alt = image.alt || getImageNameFromURL(src);
|
|
86
118
|
const url = this.getImageURL(image);
|
|
@@ -89,13 +121,7 @@ export default {
|
|
|
89
121
|
const item = document.createElement('li');
|
|
90
122
|
const img = document.createElement('img');
|
|
91
123
|
|
|
92
|
-
|
|
93
|
-
const value = image.getAttribute(name);
|
|
94
|
-
|
|
95
|
-
if (value !== null) {
|
|
96
|
-
img.setAttribute(name, value);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
124
|
+
inheritAttributes(img, image, options.inheritedAttributes);
|
|
99
125
|
|
|
100
126
|
if (options.navbar) {
|
|
101
127
|
img.src = src || url;
|
|
@@ -119,6 +145,15 @@ export default {
|
|
|
119
145
|
|
|
120
146
|
this.items = items;
|
|
121
147
|
|
|
148
|
+
if (this.viewed) {
|
|
149
|
+
const activeItem = this.getItem(this.index);
|
|
150
|
+
|
|
151
|
+
if (activeItem) {
|
|
152
|
+
addClass(activeItem, CLASS_ACTIVE);
|
|
153
|
+
activeItem.setAttribute('aria-selected', true);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
122
157
|
forEach(items, (item) => {
|
|
123
158
|
const image = item.firstElementChild;
|
|
124
159
|
let onLoad;
|
|
@@ -152,7 +187,7 @@ export default {
|
|
|
152
187
|
});
|
|
153
188
|
});
|
|
154
189
|
|
|
155
|
-
if (options
|
|
190
|
+
if (isTransitionEnabled(options, 'view')) {
|
|
156
191
|
addListener(element, EVENT_VIEWED, () => {
|
|
157
192
|
addClass(list, CLASS_TRANSITION);
|
|
158
193
|
}, {
|
|
@@ -161,9 +196,24 @@ export default {
|
|
|
161
196
|
}
|
|
162
197
|
},
|
|
163
198
|
|
|
199
|
+
getItem(index) {
|
|
200
|
+
let item;
|
|
201
|
+
|
|
202
|
+
forEach(this.items, (candidate) => {
|
|
203
|
+
if (Number(getData(candidate, 'index')) === index) {
|
|
204
|
+
item = candidate;
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return true;
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
return item;
|
|
212
|
+
},
|
|
213
|
+
|
|
164
214
|
renderList() {
|
|
165
215
|
const { index } = this;
|
|
166
|
-
const item = this.
|
|
216
|
+
const item = this.getItem(index);
|
|
167
217
|
|
|
168
218
|
if (!item) {
|
|
169
219
|
return;
|
|
@@ -176,9 +226,9 @@ export default {
|
|
|
176
226
|
|
|
177
227
|
// Place the active item in the center of the screen
|
|
178
228
|
setStyle(this.list, assign({
|
|
179
|
-
width: outerWidth * this.length - gutter,
|
|
229
|
+
width: outerWidth * this.items.length - gutter,
|
|
180
230
|
}, getTransforms({
|
|
181
|
-
translateX: ((this.viewerData.width - offsetWidth) / 2) -
|
|
231
|
+
translateX: ((this.viewerData.width - offsetWidth) / 2) - item.offsetLeft,
|
|
182
232
|
})));
|
|
183
233
|
},
|
|
184
234
|
|
|
@@ -277,9 +327,27 @@ export default {
|
|
|
277
327
|
marginTop: imageData.y,
|
|
278
328
|
}, getTransforms(imageData)));
|
|
279
329
|
|
|
330
|
+
if (this.magnifierPoint) {
|
|
331
|
+
this.renderMagnifier();
|
|
332
|
+
}
|
|
333
|
+
|
|
280
334
|
if (done) {
|
|
281
|
-
|
|
282
|
-
|
|
335
|
+
let action = false;
|
|
336
|
+
|
|
337
|
+
if (this.viewing) {
|
|
338
|
+
action = 'view';
|
|
339
|
+
} else if (this.moving) {
|
|
340
|
+
action = 'move';
|
|
341
|
+
} else if (this.rotating) {
|
|
342
|
+
action = 'rotate';
|
|
343
|
+
} else if (this.scaling) {
|
|
344
|
+
action = 'scale';
|
|
345
|
+
} else if (this.zooming) {
|
|
346
|
+
action = 'zoom';
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (action
|
|
350
|
+
&& isTransitionEnabled(this.options, action)
|
|
283
351
|
&& hasClass(image, CLASS_TRANSITION)) {
|
|
284
352
|
const onTransitionEnd = () => {
|
|
285
353
|
this.imageRendering = false;
|
package/src/js/template.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
export default (
|
|
2
2
|
'<div class="viewer-container" tabindex="-1" touch-action="none">'
|
|
3
3
|
+ '<div class="viewer-canvas"></div>'
|
|
4
|
+
+ '<div class="viewer-magnifier" aria-hidden="true">'
|
|
5
|
+
+ '<img class="viewer-magnifier-image" alt="">'
|
|
6
|
+
+ '</div>'
|
|
7
|
+
+ '<div class="viewer-navigation">'
|
|
8
|
+
+ '<div class="viewer-prev" data-viewer-action="prev" role="button" aria-label="Previous"></div>'
|
|
9
|
+
+ '<div class="viewer-next" data-viewer-action="next" role="button" aria-label="Next"></div>'
|
|
10
|
+
+ '</div>'
|
|
4
11
|
+ '<div class="viewer-footer">'
|
|
5
12
|
+ '<div class="viewer-title"></div>'
|
|
6
13
|
+ '<div class="viewer-toolbar"></div>'
|