1 |
|
2 | var _extends = Object.assign || function (target) {
|
3 | for (var i = 1; i < arguments.length; i++) {
|
4 | var source = arguments[i];
|
5 |
|
6 | for (var key in source) {
|
7 | if (Object.prototype.hasOwnProperty.call(source, key)) {
|
8 | target[key] = source[key];
|
9 | }
|
10 | }
|
11 | }
|
12 |
|
13 | return target;
|
14 | };
|
15 |
|
16 | var isSupported = function isSupported(node) {
|
17 | return node.tagName === 'IMG';
|
18 | };
|
19 |
|
20 |
|
21 | var isNodeList = function isNodeList(selector) {
|
22 | return NodeList.prototype.isPrototypeOf(selector);
|
23 | };
|
24 |
|
25 | var isNode = function isNode(selector) {
|
26 | return selector && selector.nodeType === 1;
|
27 | };
|
28 |
|
29 | var isSvg = function isSvg(image) {
|
30 | var source = image.currentSrc || image.src;
|
31 | return source.substr(-4).toLowerCase() === '.svg';
|
32 | };
|
33 |
|
34 | var getImagesFromSelector = function getImagesFromSelector(selector) {
|
35 | try {
|
36 | if (Array.isArray(selector)) {
|
37 | return selector.filter(isSupported);
|
38 | }
|
39 |
|
40 | if (isNodeList(selector)) {
|
41 |
|
42 | return [].slice.call(selector).filter(isSupported);
|
43 | }
|
44 |
|
45 | if (isNode(selector)) {
|
46 | return [selector].filter(isSupported);
|
47 | }
|
48 |
|
49 | if (typeof selector === 'string') {
|
50 |
|
51 | return [].slice.call(document.querySelectorAll(selector)).filter(isSupported);
|
52 | }
|
53 |
|
54 | return [];
|
55 | } catch (err) {
|
56 | throw new TypeError('The provided selector is invalid.\n' + 'Expects a CSS selector, a Node element, a NodeList or an array.\n' + 'See: https://github.com/francoischalifour/medium-zoom');
|
57 | }
|
58 | };
|
59 |
|
60 | var createOverlay = function createOverlay(background) {
|
61 | var overlay = document.createElement('div');
|
62 | overlay.classList.add('medium-zoom-overlay');
|
63 | overlay.style.background = background;
|
64 |
|
65 | return overlay;
|
66 | };
|
67 |
|
68 | var cloneTarget = function cloneTarget(template) {
|
69 | var _template$getBounding = template.getBoundingClientRect(),
|
70 | top = _template$getBounding.top,
|
71 | left = _template$getBounding.left,
|
72 | width = _template$getBounding.width,
|
73 | height = _template$getBounding.height;
|
74 |
|
75 | var clone = template.cloneNode();
|
76 | var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
77 | var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
|
78 |
|
79 | clone.removeAttribute('id');
|
80 | clone.style.position = 'absolute';
|
81 | clone.style.top = top + scrollTop + 'px';
|
82 | clone.style.left = left + scrollLeft + 'px';
|
83 | clone.style.width = width + 'px';
|
84 | clone.style.height = height + 'px';
|
85 | clone.style.transform = '';
|
86 |
|
87 | return clone;
|
88 | };
|
89 |
|
90 | var createCustomEvent = function createCustomEvent(type, params) {
|
91 | var eventParams = _extends({
|
92 | bubbles: false,
|
93 | cancelable: false,
|
94 | detail: undefined
|
95 | }, params);
|
96 |
|
97 | if (typeof window.CustomEvent === 'function') {
|
98 | return new CustomEvent(type, eventParams);
|
99 | }
|
100 |
|
101 | var customEvent = document.createEvent('CustomEvent');
|
102 | customEvent.initCustomEvent(type, eventParams.bubbles, eventParams.cancelable, eventParams.detail);
|
103 |
|
104 | return customEvent;
|
105 | };
|
106 |
|
107 | var mediumZoom = function mediumZoom(selector) {
|
108 | var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
109 |
|
110 | |
111 |
|
112 |
|
113 | var Promise = window.Promise || function Promise(fn) {
|
114 | function noop() {}
|
115 | fn(noop, noop);
|
116 | };
|
117 |
|
118 | var _handleClick = function _handleClick(event) {
|
119 | var target = event.target;
|
120 |
|
121 |
|
122 | if (target === overlay) {
|
123 | close();
|
124 | return;
|
125 | }
|
126 |
|
127 | if (images.indexOf(target) === -1) {
|
128 | return;
|
129 | }
|
130 |
|
131 | toggle({ target: target });
|
132 | };
|
133 |
|
134 | var _handleScroll = function _handleScroll() {
|
135 | if (isAnimating || !active.original) {
|
136 | return;
|
137 | }
|
138 |
|
139 | var currentScroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
140 |
|
141 | if (Math.abs(scrollTop - currentScroll) > zoomOptions.scrollOffset) {
|
142 | setTimeout(close, 150);
|
143 | }
|
144 | };
|
145 |
|
146 | var _handleKeyUp = function _handleKeyUp(event) {
|
147 | var key = event.key || event.keyCode;
|
148 |
|
149 |
|
150 | if (key === 'Escape' || key === 'Esc' || key === 27) {
|
151 | close();
|
152 | }
|
153 | };
|
154 |
|
155 | var update = function update() {
|
156 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
157 |
|
158 | var newOptions = options;
|
159 |
|
160 | if (options.background) {
|
161 | overlay.style.background = options.background;
|
162 | }
|
163 |
|
164 | if (options.container && options.container instanceof Object) {
|
165 | newOptions.container = _extends({}, zoomOptions.container, options.container);
|
166 | }
|
167 |
|
168 | if (options.template) {
|
169 | var template = isNode(options.template) ? options.template : document.querySelector(options.template);
|
170 |
|
171 | newOptions.template = template;
|
172 | }
|
173 |
|
174 | zoomOptions = _extends({}, zoomOptions, newOptions);
|
175 |
|
176 | images.forEach(function (image) {
|
177 | image.dispatchEvent(createCustomEvent('medium-zoom:update', {
|
178 | detail: { zoom: zoom }
|
179 | }));
|
180 | });
|
181 |
|
182 | return zoom;
|
183 | };
|
184 |
|
185 | var clone = function clone() {
|
186 | var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
187 | return mediumZoom(_extends({}, zoomOptions, options));
|
188 | };
|
189 |
|
190 | var attach = function attach() {
|
191 | for (var _len = arguments.length, selectors = Array(_len), _key = 0; _key < _len; _key++) {
|
192 | selectors[_key] = arguments[_key];
|
193 | }
|
194 |
|
195 | var newImages = selectors.reduce(function (imagesAccumulator, currentSelector) {
|
196 | return [].concat(imagesAccumulator, getImagesFromSelector(currentSelector));
|
197 | }, []);
|
198 |
|
199 | newImages.filter(function (newImage) {
|
200 | return images.indexOf(newImage) === -1;
|
201 | }).forEach(function (newImage) {
|
202 | images.push(newImage);
|
203 | newImage.classList.add('medium-zoom-image');
|
204 | });
|
205 |
|
206 | eventListeners.forEach(function (_ref) {
|
207 | var type = _ref.type,
|
208 | listener = _ref.listener,
|
209 | options = _ref.options;
|
210 |
|
211 | newImages.forEach(function (image) {
|
212 | image.addEventListener(type, listener, options);
|
213 | });
|
214 | });
|
215 |
|
216 | return zoom;
|
217 | };
|
218 |
|
219 | var detach = function detach() {
|
220 | for (var _len2 = arguments.length, selectors = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
221 | selectors[_key2] = arguments[_key2];
|
222 | }
|
223 |
|
224 | if (active.zoomed) {
|
225 | close();
|
226 | }
|
227 |
|
228 | var imagesToDetach = selectors.length > 0 ? selectors.reduce(function (imagesAccumulator, currentSelector) {
|
229 | return [].concat(imagesAccumulator, getImagesFromSelector(currentSelector));
|
230 | }, []) : images;
|
231 |
|
232 | imagesToDetach.forEach(function (image) {
|
233 | image.classList.remove('medium-zoom-image');
|
234 | image.dispatchEvent(createCustomEvent('medium-zoom:detach', {
|
235 | detail: { zoom: zoom }
|
236 | }));
|
237 | });
|
238 |
|
239 | images = images.filter(function (image) {
|
240 | return imagesToDetach.indexOf(image) === -1;
|
241 | });
|
242 |
|
243 | return zoom;
|
244 | };
|
245 |
|
246 | var on = function on(type, listener) {
|
247 | var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
248 |
|
249 | images.forEach(function (image) {
|
250 | image.addEventListener('medium-zoom:' + type, listener, options);
|
251 | });
|
252 |
|
253 | eventListeners.push({ type: 'medium-zoom:' + type, listener: listener, options: options });
|
254 |
|
255 | return zoom;
|
256 | };
|
257 |
|
258 | var off = function off(type, listener) {
|
259 | var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
260 |
|
261 | images.forEach(function (image) {
|
262 | image.removeEventListener('medium-zoom:' + type, listener, options);
|
263 | });
|
264 |
|
265 | eventListeners = eventListeners.filter(function (eventListener) {
|
266 | return !(eventListener.type === 'medium-zoom:' + type && eventListener.listener.toString() === listener.toString());
|
267 | });
|
268 |
|
269 | return zoom;
|
270 | };
|
271 |
|
272 | var open = function open() {
|
273 | var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
274 | target = _ref2.target;
|
275 |
|
276 | var _animate = function _animate() {
|
277 | var container = {
|
278 | width: document.documentElement.clientWidth,
|
279 | height: document.documentElement.clientHeight,
|
280 | left: 0,
|
281 | top: 0,
|
282 | right: 0,
|
283 | bottom: 0
|
284 | };
|
285 | var viewportWidth = void 0;
|
286 | var viewportHeight = void 0;
|
287 |
|
288 | if (zoomOptions.container) {
|
289 | if (zoomOptions.container instanceof Object) {
|
290 |
|
291 | container = _extends({}, container, zoomOptions.container);
|
292 |
|
293 |
|
294 | viewportWidth = container.width - container.left - container.right - zoomOptions.margin * 2;
|
295 | viewportHeight = container.height - container.top - container.bottom - zoomOptions.margin * 2;
|
296 | } else {
|
297 |
|
298 | var zoomContainer = isNode(zoomOptions.container) ? zoomOptions.container : document.querySelector(zoomOptions.container);
|
299 |
|
300 | var _zoomContainer$getBou = zoomContainer.getBoundingClientRect(),
|
301 | _width = _zoomContainer$getBou.width,
|
302 | _height = _zoomContainer$getBou.height,
|
303 | _left = _zoomContainer$getBou.left,
|
304 | _top = _zoomContainer$getBou.top;
|
305 |
|
306 | container = _extends({}, container, {
|
307 | width: _width,
|
308 | height: _height,
|
309 | left: _left,
|
310 | top: _top
|
311 | });
|
312 | }
|
313 | }
|
314 |
|
315 | viewportWidth = viewportWidth || container.width - zoomOptions.margin * 2;
|
316 | viewportHeight = viewportHeight || container.height - zoomOptions.margin * 2;
|
317 |
|
318 | var zoomTarget = active.zoomedHd || active.original;
|
319 | var naturalWidth = isSvg(zoomTarget) ? viewportWidth : zoomTarget.naturalWidth || viewportWidth;
|
320 | var naturalHeight = isSvg(zoomTarget) ? viewportHeight : zoomTarget.naturalHeight || viewportHeight;
|
321 |
|
322 | var _zoomTarget$getBoundi = zoomTarget.getBoundingClientRect(),
|
323 | top = _zoomTarget$getBoundi.top,
|
324 | left = _zoomTarget$getBoundi.left,
|
325 | width = _zoomTarget$getBoundi.width,
|
326 | height = _zoomTarget$getBoundi.height;
|
327 |
|
328 | var scaleX = Math.min(naturalWidth, viewportWidth) / width;
|
329 | var scaleY = Math.min(naturalHeight, viewportHeight) / height;
|
330 | var scale = Math.min(scaleX, scaleY);
|
331 | var translateX = (-left + (viewportWidth - width) / 2 + zoomOptions.margin + container.left) / scale;
|
332 | var translateY = (-top + (viewportHeight - height) / 2 + zoomOptions.margin + container.top) / scale;
|
333 | var transform = 'scale(' + scale + ') translate3d(' + translateX + 'px, ' + translateY + 'px, 0)';
|
334 |
|
335 | active.zoomed.style.transform = transform;
|
336 |
|
337 | if (active.zoomedHd) {
|
338 | active.zoomedHd.style.transform = transform;
|
339 | }
|
340 | };
|
341 |
|
342 | return new Promise(function (resolve) {
|
343 | if (target && images.indexOf(target) === -1) {
|
344 | resolve(zoom);
|
345 | return;
|
346 | }
|
347 |
|
348 | var _handleOpenEnd = function _handleOpenEnd() {
|
349 | isAnimating = false;
|
350 | active.zoomed.removeEventListener('transitionend', _handleOpenEnd);
|
351 | active.original.dispatchEvent(createCustomEvent('medium-zoom:opened', {
|
352 | detail: { zoom: zoom }
|
353 | }));
|
354 |
|
355 | resolve(zoom);
|
356 | };
|
357 |
|
358 | if (active.zoomed) {
|
359 | resolve(zoom);
|
360 | return;
|
361 | }
|
362 |
|
363 | if (target) {
|
364 |
|
365 | active.original = target;
|
366 | } else if (images.length > 0) {
|
367 | var _images = images;
|
368 | active.original = _images[0];
|
369 | } else {
|
370 | resolve(zoom);
|
371 | return;
|
372 | }
|
373 |
|
374 | active.original.dispatchEvent(createCustomEvent('medium-zoom:open', {
|
375 | detail: { zoom: zoom }
|
376 | }));
|
377 |
|
378 | scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
379 | isAnimating = true;
|
380 | active.zoomed = cloneTarget(active.original);
|
381 |
|
382 | document.body.appendChild(overlay);
|
383 |
|
384 | if (zoomOptions.template) {
|
385 | var template = isNode(zoomOptions.template) ? zoomOptions.template : document.querySelector(zoomOptions.template);
|
386 | active.template = document.createElement('div');
|
387 | active.template.appendChild(template.content.cloneNode(true));
|
388 |
|
389 | document.body.appendChild(active.template);
|
390 | }
|
391 |
|
392 | document.body.appendChild(active.zoomed);
|
393 |
|
394 | window.requestAnimationFrame(function () {
|
395 | document.body.classList.add('medium-zoom--opened');
|
396 | });
|
397 |
|
398 | active.original.classList.add('medium-zoom-image--hidden');
|
399 | active.zoomed.classList.add('medium-zoom-image--opened');
|
400 |
|
401 | active.zoomed.addEventListener('click', close);
|
402 | active.zoomed.addEventListener('transitionend', _handleOpenEnd);
|
403 |
|
404 | if (active.original.getAttribute('data-zoom-src')) {
|
405 | active.zoomedHd = active.zoomed.cloneNode();
|
406 |
|
407 |
|
408 | active.zoomedHd.removeAttribute('srcset');
|
409 | active.zoomedHd.removeAttribute('sizes');
|
410 |
|
411 | active.zoomedHd.src = active.zoomed.getAttribute('data-zoom-src');
|
412 |
|
413 | active.zoomedHd.onerror = function () {
|
414 | clearInterval(getZoomTargetSize);
|
415 | console.warn('Unable to reach the zoom image target ' + active.zoomedHd.src);
|
416 | active.zoomedHd = null;
|
417 | _animate();
|
418 | };
|
419 |
|
420 |
|
421 |
|
422 | var getZoomTargetSize = setInterval(function () {
|
423 | if ( active.zoomedHd.complete) {
|
424 | clearInterval(getZoomTargetSize);
|
425 | active.zoomedHd.classList.add('medium-zoom-image--opened');
|
426 | active.zoomedHd.addEventListener('click', close);
|
427 | document.body.appendChild(active.zoomedHd);
|
428 | _animate();
|
429 | }
|
430 | }, 10);
|
431 | } else if (active.original.hasAttribute('srcset')) {
|
432 |
|
433 |
|
434 |
|
435 | active.zoomedHd = active.zoomed.cloneNode();
|
436 |
|
437 |
|
438 |
|
439 | active.zoomedHd.removeAttribute('sizes');
|
440 |
|
441 |
|
442 |
|
443 | active.zoomedHd.removeAttribute('loading');
|
444 |
|
445 |
|
446 |
|
447 | var loadEventListener = active.zoomedHd.addEventListener('load', function () {
|
448 | active.zoomedHd.removeEventListener('load', loadEventListener);
|
449 | active.zoomedHd.classList.add('medium-zoom-image--opened');
|
450 | active.zoomedHd.addEventListener('click', close);
|
451 | document.body.appendChild(active.zoomedHd);
|
452 | _animate();
|
453 | });
|
454 | } else {
|
455 | _animate();
|
456 | }
|
457 | });
|
458 | };
|
459 |
|
460 | var close = function close() {
|
461 | return new Promise(function (resolve) {
|
462 | if (isAnimating || !active.original) {
|
463 | resolve(zoom);
|
464 | return;
|
465 | }
|
466 |
|
467 | var _handleCloseEnd = function _handleCloseEnd() {
|
468 | active.original.classList.remove('medium-zoom-image--hidden');
|
469 | document.body.removeChild(active.zoomed);
|
470 | if (active.zoomedHd) {
|
471 | document.body.removeChild(active.zoomedHd);
|
472 | }
|
473 | document.body.removeChild(overlay);
|
474 | active.zoomed.classList.remove('medium-zoom-image--opened');
|
475 | if (active.template) {
|
476 | document.body.removeChild(active.template);
|
477 | }
|
478 |
|
479 | isAnimating = false;
|
480 | active.zoomed.removeEventListener('transitionend', _handleCloseEnd);
|
481 |
|
482 | active.original.dispatchEvent(createCustomEvent('medium-zoom:closed', {
|
483 | detail: { zoom: zoom }
|
484 | }));
|
485 |
|
486 | active.original = null;
|
487 | active.zoomed = null;
|
488 | active.zoomedHd = null;
|
489 | active.template = null;
|
490 |
|
491 | resolve(zoom);
|
492 | };
|
493 |
|
494 | isAnimating = true;
|
495 | document.body.classList.remove('medium-zoom--opened');
|
496 | active.zoomed.style.transform = '';
|
497 |
|
498 | if (active.zoomedHd) {
|
499 | active.zoomedHd.style.transform = '';
|
500 | }
|
501 |
|
502 |
|
503 | if (active.template) {
|
504 | active.template.style.transition = 'opacity 150ms';
|
505 | active.template.style.opacity = 0;
|
506 | }
|
507 |
|
508 | active.original.dispatchEvent(createCustomEvent('medium-zoom:close', {
|
509 | detail: { zoom: zoom }
|
510 | }));
|
511 |
|
512 | active.zoomed.addEventListener('transitionend', _handleCloseEnd);
|
513 | });
|
514 | };
|
515 |
|
516 | var toggle = function toggle() {
|
517 | var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
518 | target = _ref3.target;
|
519 |
|
520 | if (active.original) {
|
521 | return close();
|
522 | }
|
523 |
|
524 | return open({ target: target });
|
525 | };
|
526 |
|
527 | var getOptions = function getOptions() {
|
528 | return zoomOptions;
|
529 | };
|
530 |
|
531 | var getImages = function getImages() {
|
532 | return images;
|
533 | };
|
534 |
|
535 | var getZoomedImage = function getZoomedImage() {
|
536 | return active.original;
|
537 | };
|
538 |
|
539 | var images = [];
|
540 | var eventListeners = [];
|
541 | var isAnimating = false;
|
542 | var scrollTop = 0;
|
543 | var zoomOptions = options;
|
544 | var active = {
|
545 | original: null,
|
546 | zoomed: null,
|
547 | zoomedHd: null,
|
548 | template: null
|
549 |
|
550 |
|
551 | };if (Object.prototype.toString.call(selector) === '[object Object]') {
|
552 | zoomOptions = selector;
|
553 | } else if (selector || typeof selector === 'string'
|
554 | ) {
|
555 | attach(selector);
|
556 | }
|
557 |
|
558 |
|
559 | zoomOptions = _extends({
|
560 | margin: 0,
|
561 | background: '#fff',
|
562 | scrollOffset: 40,
|
563 | container: null,
|
564 | template: null
|
565 | }, zoomOptions);
|
566 |
|
567 | var overlay = createOverlay(zoomOptions.background);
|
568 |
|
569 | document.addEventListener('click', _handleClick);
|
570 | document.addEventListener('keyup', _handleKeyUp);
|
571 | document.addEventListener('scroll', _handleScroll);
|
572 | window.addEventListener('resize', close);
|
573 |
|
574 | var zoom = {
|
575 | open: open,
|
576 | close: close,
|
577 | toggle: toggle,
|
578 | update: update,
|
579 | clone: clone,
|
580 | attach: attach,
|
581 | detach: detach,
|
582 | on: on,
|
583 | off: off,
|
584 | getOptions: getOptions,
|
585 | getImages: getImages,
|
586 | getZoomedImage: getZoomedImage
|
587 | };
|
588 |
|
589 | return zoom;
|
590 | };
|
591 |
|
592 | function styleInject(css, ref) {
|
593 | if ( ref === void 0 ) ref = {};
|
594 | var insertAt = ref.insertAt;
|
595 |
|
596 | if (!css || typeof document === 'undefined') { return; }
|
597 |
|
598 | var head = document.head || document.getElementsByTagName('head')[0];
|
599 | var style = document.createElement('style');
|
600 | style.type = 'text/css';
|
601 |
|
602 | if (insertAt === 'top') {
|
603 | if (head.firstChild) {
|
604 | head.insertBefore(style, head.firstChild);
|
605 | } else {
|
606 | head.appendChild(style);
|
607 | }
|
608 | } else {
|
609 | head.appendChild(style);
|
610 | }
|
611 |
|
612 | if (style.styleSheet) {
|
613 | style.styleSheet.cssText = css;
|
614 | } else {
|
615 | style.appendChild(document.createTextNode(css));
|
616 | }
|
617 | }
|
618 |
|
619 | var css = ".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}";
|
620 | styleInject(css);
|
621 |
|
622 | export default mediumZoom;
|