UNPKG

18.9 kBJavaScriptView Raw
1/*
2 * medium-zoom-element v0.0.1
3 * Medium Zoom HTML Element
4 * Copyright 2017 Francois Chalifour
5 * https://github.com/francoischalifour/medium-zoom-element
6 * MIT License
7 */
8(function (global, factory) {
9 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
10 typeof define === 'function' && define.amd ? define(factory) :
11 (global.MediumZoomElement = factory());
12}(this, (function () { 'use strict';
13
14/*
15 * medium-zoom v0.2.0
16 * Medium zoom on your images in vanilla JavaScript
17 * Copyright 2017 Francois Chalifour
18 * https://github.com/francoischalifour/medium-zoom
19 * MIT License
20 */function __$styleInject(a, b) {
21 if ('undefined' == typeof document) return b;a = a || '';var c = document.head || document.getElementsByTagName('head')[0],
22 d = document.createElement('style');return d.type = 'text/css', c.appendChild(d), d.styleSheet ? d.styleSheet.cssText = a : d.appendChild(document.createTextNode(a)), b;
23}function createCommonjsModule(a, b) {
24 return b = { exports: {} }, a(b, b.exports), b.exports;
25}var _extends = Object.assign || function (a) {
26 for (var b, c = 1; c < arguments.length; c++) {
27 for (var d in b = arguments[c], b) {
28 Object.prototype.hasOwnProperty.call(b, d) && (a[d] = b[d]);
29 }
30 }return a;
31};
32var toConsumableArray = function toConsumableArray(a) {
33 if (Array.isArray(a)) {
34 for (var b = 0, c = Array(a.length); b < a.length; b++) {
35 c[b] = a[b];
36 }return c;
37 }return Array.from(a);
38};
39var mediumZoom_1 = createCommonjsModule(function (a) {
40 var b = ['IMG'],
41 c = [27, 81],
42 d = function d(a) {
43 return b.includes(a.tagName);
44 },
45 e = function e(a) {
46 return a.naturalWidth !== a.width;
47 },
48 f = function f(a) {
49 return NodeList.prototype.isPrototypeOf(a) || HTMLCollection.prototype.isPrototypeOf(a);
50 },
51 g = function g(a) {
52 return a && 1 === a.nodeType;
53 };a.exports = function (a) {
54 var h = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {},
55 i = h.margin,
56 j = void 0 === i ? 0 : i,
57 k = h.background,
58 l = void 0 === k ? '#fff' : k,
59 m = h.scrollOffset,
60 n = void 0 === m ? 48 : m,
61 o = h.metaClick,
62 p = function p(a) {
63 var b = a.getBoundingClientRect(),
64 c = b.top,
65 d = b.left,
66 e = b.width,
67 f = b.height,
68 g = a.cloneNode(),
69 h = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
70 i = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;return g.removeAttribute('id'), g.style.position = 'absolute', g.style.top = c + h + 'px', g.style.left = d + i + 'px', g.style.width = e + 'px', g.style.height = f + 'px', g.style.transform = '', g;
71 },
72 q = function q() {
73 if (C.template) if (C.template.dispatchEvent(new Event('show')), D = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0, E = !0, C.zoomed = p(C.template), document.body.appendChild(B), document.body.appendChild(C.zoomed), requestAnimationFrame(function () {
74 document.body.classList.add('medium-zoom--open');
75 }), C.template.style.visibility = 'hidden', C.zoomed.classList.add('medium-zoom-image--open'), C.zoomed.addEventListener('click', r), C.zoomed.addEventListener('transitionend', u), C.template.getAttribute('data-zoom-target')) {
76 C.zoomedHd = C.zoomed.cloneNode(), C.zoomedHd.src = C.zoomed.getAttribute('data-zoom-target'), C.zoomedHd.onerror = function () {
77 clearInterval(a), console.error('Unable to reach the zoom image target ' + C.zoomedHd.src), C.zoomedHd = null, y();
78 };var a = setInterval(function () {
79 C.zoomedHd.naturalWidth && (clearInterval(a), C.zoomedHd.classList.add('medium-zoom-image--open'), C.zoomedHd.addEventListener('click', r), document.body.appendChild(C.zoomedHd), y());
80 }, 10);
81 } else y();
82 },
83 r = function a() {
84 var b = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : 0,
85 c = function c() {
86 E || !C.template || (C.template.dispatchEvent(new Event('hide')), E = !0, document.body.classList.remove('medium-zoom--open'), C.zoomed.style.transform = '', C.zoomedHd && (C.zoomedHd.style.transform = '', C.zoomedHd.removeEventListener('click', a)), C.zoomed.removeEventListener('click', a), C.zoomed.addEventListener('transitionend', v));
87 };0 < b ? setTimeout(c, b) : c();
88 },
89 s = function s(a) {
90 C.template ? r() : (C.template = a ? a.target : A[0], q());
91 },
92 t = function t(a) {
93 return (a.metaKey || a.ctrlKey) && z.metaClick ? window.open(a.target.getAttribute('data-original') || a.target.parentNode.href || a.target.src, '_blank') : void (a.preventDefault(), s(a));
94 },
95 u = function a() {
96 E = !1, C.zoomed.removeEventListener('transitionend', a), C.template.dispatchEvent(new Event('shown'));
97 },
98 v = function a() {
99 C.template && (C.template.style.visibility = '', document.body.removeChild(C.zoomed), C.zoomedHd && document.body.removeChild(C.zoomedHd), document.body.removeChild(B), C.zoomed.classList.remove('medium-zoom-image--open'), E = !1, C.zoomed.removeEventListener('transitionend', a), C.template.dispatchEvent(new Event('hidden')), C.template = null, C.zoomed = null, C.zoomedHd = null);
100 },
101 w = function w() {
102 if (!E && C.template) {
103 var a = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;Math.abs(D - a) > z.scrollOffset && r(150);
104 }
105 },
106 x = function x(a) {
107 c.includes(a.keyCode || a.which) && r();
108 },
109 y = function y() {
110 var a = Math.min;if (C.template) {
111 var b = window.innerWidth,
112 c = window.innerHeight,
113 d = b - 2 * z.margin,
114 e = c - 2 * z.margin,
115 f = C.zoomedHd || C.template,
116 g = f.naturalWidth,
117 h = void 0 === g ? d : g,
118 i = f.naturalHeight,
119 j = void 0 === i ? e : i,
120 k = f.getBoundingClientRect(),
121 l = k.top,
122 m = k.left,
123 n = k.width,
124 o = k.height,
125 p = a(h, d) / n,
126 q = a(j, e) / o,
127 r = a(p, q) || 1,
128 s = (-m + (d - n) / 2 + z.margin) / r,
129 t = (-l + (e - o) / 2 + z.margin) / r,
130 u = 'scale(' + r + ') translate3d(' + s + 'px, ' + t + 'px, 0)';C.zoomed.style.transform = u, C.zoomedHd && (C.zoomedHd.style.transform = u);
131 }
132 },
133 z = { margin: j, background: l, scrollOffset: n, metaClick: void 0 === o || o };a instanceof Object && _extends(z, a);var A = function (a) {
134 try {
135 return Array.isArray(a) ? a.filter(d) : f(a) ? [].concat(toConsumableArray(a)).filter(d) : g(a) ? [a].filter(d) : 'string' == typeof a ? [].concat(toConsumableArray(document.querySelectorAll(a))).filter(d) : [].concat(toConsumableArray(document.querySelectorAll(b.map(function (a) {
136 return a.toLowerCase();
137 }).join(',')))).filter(e);
138 } catch (a) {
139 throw new TypeError('The provided selector is invalid.\nExpects a CSS selector, a Node element, a NodeList, an HTMLCollection or an array.\nSee: https://github.com/francoischalifour/medium-zoom');
140 }
141 }(a),
142 B = function (a) {
143 var b = document.createElement('div');return b.classList.add('medium-zoom-overlay'), b.style.backgroundColor = a, b;
144 }(z.background),
145 C = { template: null, zoomed: null, zoomedHd: null },
146 D = 0,
147 E = !1;return A.forEach(function (a) {
148 a.classList.add('medium-zoom-image'), a.addEventListener('click', t);
149 }), B.addEventListener('click', r), document.addEventListener('scroll', w), document.addEventListener('keyup', x), window.addEventListener('resize', r), { show: s, hide: r, toggle: s, update: function update() {
150 var a = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {};return a.background && (B.style.backgroundColor = a.background), _extends(z, a);
151 }, addEventListeners: function addEventListeners(a, b) {
152 A.forEach(function (c) {
153 c.addEventListener(a, b);
154 });
155 }, detach: function detach() {
156 var a = function a() {
157 var b = new Event('detach');A.forEach(function (a) {
158 a.classList.remove('medium-zoom-image'), a.removeEventListener('click', t), a.dispatchEvent(b);
159 }), A.splice(0, A.length), B.removeEventListener('click', r), document.removeEventListener('scroll', w), document.removeEventListener('keyup', x), window.removeEventListener('resize', r), C.zoomed && C.zoomed.removeEventListener('transitionend', a);
160 };C.zoomed ? (r(), C.zoomed.addEventListener('transitionend', requestAnimationFrame(a))) : a();
161 }, images: A, options: z };
162 };
163});__$styleInject('.medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--open .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s}.medium-zoom-image--open{position:relative;z-index:1;cursor:pointer;cursor:zoom-out;will-change:transform}', void 0);var src = mediumZoom_1;
164
165var asyncGenerator = function () {
166 function AwaitValue(value) {
167 this.value = value;
168 }
169
170 function AsyncGenerator(gen) {
171 var front, back;
172
173 function send(key, arg) {
174 return new Promise(function (resolve, reject) {
175 var request = {
176 key: key,
177 arg: arg,
178 resolve: resolve,
179 reject: reject,
180 next: null
181 };
182
183 if (back) {
184 back = back.next = request;
185 } else {
186 front = back = request;
187 resume(key, arg);
188 }
189 });
190 }
191
192 function resume(key, arg) {
193 try {
194 var result = gen[key](arg);
195 var value = result.value;
196
197 if (value instanceof AwaitValue) {
198 Promise.resolve(value.value).then(function (arg) {
199 resume("next", arg);
200 }, function (arg) {
201 resume("throw", arg);
202 });
203 } else {
204 settle(result.done ? "return" : "normal", result.value);
205 }
206 } catch (err) {
207 settle("throw", err);
208 }
209 }
210
211 function settle(type, value) {
212 switch (type) {
213 case "return":
214 front.resolve({
215 value: value,
216 done: true
217 });
218 break;
219
220 case "throw":
221 front.reject(value);
222 break;
223
224 default:
225 front.resolve({
226 value: value,
227 done: false
228 });
229 break;
230 }
231
232 front = front.next;
233
234 if (front) {
235 resume(front.key, front.arg);
236 } else {
237 back = null;
238 }
239 }
240
241 this._invoke = send;
242
243 if (typeof gen.return !== "function") {
244 this.return = undefined;
245 }
246 }
247
248 if (typeof Symbol === "function" && Symbol.asyncIterator) {
249 AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
250 return this;
251 };
252 }
253
254 AsyncGenerator.prototype.next = function (arg) {
255 return this._invoke("next", arg);
256 };
257
258 AsyncGenerator.prototype.throw = function (arg) {
259 return this._invoke("throw", arg);
260 };
261
262 AsyncGenerator.prototype.return = function (arg) {
263 return this._invoke("return", arg);
264 };
265
266 return {
267 wrap: function (fn) {
268 return function () {
269 return new AsyncGenerator(fn.apply(this, arguments));
270 };
271 },
272 await: function (value) {
273 return new AwaitValue(value);
274 }
275 };
276}();
277
278
279
280
281
282var classCallCheck = function (instance, Constructor) {
283 if (!(instance instanceof Constructor)) {
284 throw new TypeError("Cannot call a class as a function");
285 }
286};
287
288var createClass = function () {
289 function defineProperties(target, props) {
290 for (var i = 0; i < props.length; i++) {
291 var descriptor = props[i];
292 descriptor.enumerable = descriptor.enumerable || false;
293 descriptor.configurable = true;
294 if ("value" in descriptor) descriptor.writable = true;
295 Object.defineProperty(target, descriptor.key, descriptor);
296 }
297 }
298
299 return function (Constructor, protoProps, staticProps) {
300 if (protoProps) defineProperties(Constructor.prototype, protoProps);
301 if (staticProps) defineProperties(Constructor, staticProps);
302 return Constructor;
303 };
304}();
305
306
307
308
309
310var defineProperty = function (obj, key, value) {
311 if (key in obj) {
312 Object.defineProperty(obj, key, {
313 value: value,
314 enumerable: true,
315 configurable: true,
316 writable: true
317 });
318 } else {
319 obj[key] = value;
320 }
321
322 return obj;
323};
324
325
326
327var inherits = function (subClass, superClass) {
328 if (typeof superClass !== "function" && superClass !== null) {
329 throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
330 }
331
332 subClass.prototype = Object.create(superClass && superClass.prototype, {
333 constructor: {
334 value: subClass,
335 enumerable: false,
336 writable: true,
337 configurable: true
338 }
339 });
340 if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
341};
342
343
344
345
346
347
348
349
350
351
352
353var possibleConstructorReturn = function (self, call) {
354 if (!self) {
355 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
356 }
357
358 return call && (typeof call === "object" || typeof call === "function") ? call : self;
359};
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379var toConsumableArray$1 = function (arr) {
380 if (Array.isArray(arr)) {
381 for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
382
383 return arr2;
384 } else {
385 return Array.from(arr);
386 }
387};
388
389function _CustomElement() {
390 return Reflect.construct(HTMLElement, [], this.__proto__.constructor);
391}
392
393
394Object.setPrototypeOf(_CustomElement.prototype, HTMLElement.prototype);
395Object.setPrototypeOf(_CustomElement, HTMLElement);
396var camelCased = function camelCased(string) {
397 return string.replace(/-([a-z])/g, function (g) {
398 return g[1].toUpperCase();
399 });
400};
401
402var template = document.createElement('template');
403template.innerHTML = '\n<style>\n :host {\n display: block;\n }\n img {\n max-width: 100%;\n }\n .medium-zoom-image {\n cursor: zoom-in;\n }\n</style>\n<img />\n';
404
405var MediumZoom = function (_CustomElement2) {
406 inherits(MediumZoom, _CustomElement2);
407 createClass(MediumZoom, null, [{
408 key: 'getOptionName',
409 value: function getOptionName(value) {
410 return value === 'disable-metaclick' ? 'metaClick' : camelCased(value);
411 }
412 }, {
413 key: 'observedOptions',
414 get: function get$$1() {
415 return ['margin', 'background', 'scroll-offset', 'disable-metaclick', 'zoom-target'];
416 }
417 }, {
418 key: 'observedAttributes',
419 get: function get$$1() {
420 return [].concat(toConsumableArray$1(MediumZoom.observedOptions), ['src', 'alt', 'width', 'height', 'style']);
421 }
422 }]);
423
424 function MediumZoom() {
425 classCallCheck(this, MediumZoom);
426
427 var _this = possibleConstructorReturn(this, (MediumZoom.__proto__ || Object.getPrototypeOf(MediumZoom)).call(this));
428
429 _this.attachShadow({ mode: 'open' });
430 _this.shadowRoot.appendChild(template.content.cloneNode(true));
431 _this.image = _this.shadowRoot.querySelector('img');
432 _this.zoom = src(_this.image);
433
434 // Attach all zoom methods to the component
435 Object.keys(_this.zoom).forEach(function (method) {
436 return _this[method] = _this.zoom[method];
437 });
438
439 // Add accessibility attributes to the component
440 _this.setAttribute('role', 'img');
441 _this.setAttribute('aria-label', _this.alt);
442 return _this;
443 }
444
445 createClass(MediumZoom, [{
446 key: 'disconnectedCallback',
447 value: function disconnectedCallback() {
448 this.zoom.detach();
449 }
450 }, {
451 key: 'adoptedCallback',
452 value: function adoptedCallback() {
453 this.zoom.hide();
454 }
455 }, {
456 key: 'attributeChangedCallback',
457 value: function attributeChangedCallback(name, oldValue, newValue) {
458 if (MediumZoom.observedOptions.includes(name)) {
459 if (name === 'zoom-target') {
460 this.image.setAttribute('data-zoom-target', newValue);
461 return;
462 }
463
464 this.zoom.update(defineProperty({}, MediumZoom.getOptionName(name), this[MediumZoom.getOptionName(name)]));
465 } else {
466 // Attach all DOM attributes to the image
467 this.image.setAttribute(name, newValue);
468 }
469 }
470 }, {
471 key: 'src',
472 get: function get$$1() {
473 return this.getAttribute('src') || '';
474 },
475 set: function set$$1(value) {
476 this.setAttribute('src', value);
477 }
478 }, {
479 key: 'alt',
480 get: function get$$1() {
481 return this.getAttribute('alt') || '';
482 },
483 set: function set$$1(value) {
484 this.setAttribute('alt', value);
485 }
486 }, {
487 key: 'zoomTarget',
488 get: function get$$1() {
489 return this.getAttribute('zoom-target') || '';
490 },
491 set: function set$$1(value) {
492 value ? this.setAttribute('zoom-target', value) : this.removeAttribute('zoom-target');
493 }
494 }, {
495 key: 'width',
496 get: function get$$1() {
497 return this.getAttribute('width') || '';
498 },
499 set: function set$$1(value) {
500 value ? this.setAttribute('width', value) : this.removeAttribute('width');
501 }
502 }, {
503 key: 'height',
504 get: function get$$1() {
505 return this.getAttribute('height') || '';
506 },
507 set: function set$$1(value) {
508 value ? this.setAttribute('height', value) : this.removeAttribute('height');
509 }
510 }, {
511 key: 'margin',
512 get: function get$$1() {
513 return Number(this.getAttribute('margin')) || '';
514 },
515 set: function set$$1(value) {
516 value ? this.setAttribute('margin', value) : this.removeAttribute('margin');
517 }
518 }, {
519 key: 'background',
520 get: function get$$1() {
521 return this.getAttribute('background') || '';
522 },
523 set: function set$$1(value) {
524 value ? this.setAttribute('background', value) : this.removeAttribute('background');
525 }
526 }, {
527 key: 'scrollOffset',
528 get: function get$$1() {
529 return this.hasAttribute('scroll-offset') ? Number(this.getAttribute('scroll-offset')) : '';
530 },
531 set: function set$$1(value) {
532 value !== null ? this.setAttribute('scroll-offset', Number(value)) : this.removeAttribute('scroll-offset');
533 }
534 }, {
535 key: 'metaClick',
536 get: function get$$1() {
537 return !this.hasAttribute('disable-metaclick');
538 },
539 set: function set$$1(value) {
540 value ? this.setAttribute('disable-metaclick', value) : this.removeAttribute('disable-metaclick');
541 }
542 }]);
543 return MediumZoom;
544}(_CustomElement);
545
546window.customElements.define('medium-zoom', MediumZoom);
547
548return MediumZoom;
549
550})));