UNPKG

127 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) :
3 typeof define === 'function' && define.amd ? define(['react'], factory) :
4 (global = global || self, global.Lightgallery = factory(global.React));
5}(this, (function (React) { 'use strict';
6
7 /*! *****************************************************************************
8 Copyright (c) Microsoft Corporation.
9
10 Permission to use, copy, modify, and/or distribute this software for any
11 purpose with or without fee is hereby granted.
12
13 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
18 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 PERFORMANCE OF THIS SOFTWARE.
20 ***************************************************************************** */
21
22 function __rest(s, e) {
23 var t = {};
24 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
25 t[p] = s[p];
26 if (s != null && typeof Object.getOwnPropertySymbols === "function")
27 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
28 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
29 t[p[i]] = s[p[i]];
30 }
31 return t;
32 }
33
34 /*!
35 * lightgallery | 2.2.1 | September 4th 2021
36 * http://www.lightgalleryjs.com/
37 * Copyright (c) 2020 Sachin Neravath;
38 * @license GPLv3
39 */
40
41 /*! *****************************************************************************
42 Copyright (c) Microsoft Corporation.
43
44 Permission to use, copy, modify, and/or distribute this software for any
45 purpose with or without fee is hereby granted.
46
47 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
48 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
49 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
50 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
51 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
52 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
53 PERFORMANCE OF THIS SOFTWARE.
54 ***************************************************************************** */
55
56 var __assign = function() {
57 __assign = Object.assign || function __assign(t) {
58 for (var s, i = 1, n = arguments.length; i < n; i++) {
59 s = arguments[i];
60 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
61 }
62 return t;
63 };
64 return __assign.apply(this, arguments);
65 };
66
67 function __spreadArrays() {
68 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
69 for (var r = Array(s), k = 0, i = 0; i < il; i++)
70 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
71 r[k] = a[j];
72 return r;
73 }
74
75 (function () {
76 if (typeof window.CustomEvent === 'function')
77 return false;
78 function CustomEvent(event, params) {
79 params = params || { bubbles: false, cancelable: false, detail: null };
80 var evt = document.createEvent('CustomEvent');
81 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
82 return evt;
83 }
84 window.CustomEvent = CustomEvent;
85 })();
86 (function () {
87 if (!Element.prototype.matches) {
88 Element.prototype.matches =
89 Element.prototype.msMatchesSelector ||
90 Element.prototype.webkitMatchesSelector;
91 }
92 })();
93 var lgQuery = /** @class */ (function () {
94 function lgQuery(selector) {
95 this.cssVenderPrefixes = [
96 'TransitionDuration',
97 'TransitionTimingFunction',
98 'Transform',
99 'Transition',
100 ];
101 this.selector = this._getSelector(selector);
102 this.firstElement = this._getFirstEl();
103 return this;
104 }
105 lgQuery.generateUUID = function () {
106 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
107 var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
108 return v.toString(16);
109 });
110 };
111 lgQuery.prototype._getSelector = function (selector, context) {
112 if (context === void 0) { context = document; }
113 if (typeof selector !== 'string') {
114 return selector;
115 }
116 context = context || document;
117 var fl = selector.substring(0, 1);
118 if (fl === '#') {
119 return context.querySelector(selector);
120 }
121 else {
122 return context.querySelectorAll(selector);
123 }
124 };
125 lgQuery.prototype._each = function (func) {
126 if (!this.selector) {
127 return this;
128 }
129 if (this.selector.length !== undefined) {
130 [].forEach.call(this.selector, func);
131 }
132 else {
133 func(this.selector, 0);
134 }
135 return this;
136 };
137 lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
138 // prettier-ignore
139 var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
140 return group1.toUpperCase();
141 });
142 if (this.cssVenderPrefixes.indexOf(property) !== -1) {
143 el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
144 el.style['webkit' + property] = value;
145 el.style['moz' + property] = value;
146 el.style['ms' + property] = value;
147 el.style['o' + property] = value;
148 }
149 else {
150 el.style[property] = value;
151 }
152 };
153 lgQuery.prototype._getFirstEl = function () {
154 if (this.selector && this.selector.length !== undefined) {
155 return this.selector[0];
156 }
157 else {
158 return this.selector;
159 }
160 };
161 lgQuery.prototype.isEventMatched = function (event, eventName) {
162 var eventNamespace = eventName.split('.');
163 return event
164 .split('.')
165 .filter(function (e) { return e; })
166 .every(function (e) {
167 return eventNamespace.indexOf(e) !== -1;
168 });
169 };
170 lgQuery.prototype.attr = function (attr, value) {
171 if (value === undefined) {
172 if (!this.firstElement) {
173 return '';
174 }
175 return this.firstElement.getAttribute(attr);
176 }
177 this._each(function (el) {
178 el.setAttribute(attr, value);
179 });
180 return this;
181 };
182 lgQuery.prototype.find = function (selector) {
183 return $LG(this._getSelector(selector, this.selector));
184 };
185 lgQuery.prototype.first = function () {
186 if (this.selector && this.selector.length !== undefined) {
187 return $LG(this.selector[0]);
188 }
189 else {
190 return $LG(this.selector);
191 }
192 };
193 lgQuery.prototype.eq = function (index) {
194 return $LG(this.selector[index]);
195 };
196 lgQuery.prototype.parent = function () {
197 return $LG(this.selector.parentElement);
198 };
199 lgQuery.prototype.get = function () {
200 return this._getFirstEl();
201 };
202 lgQuery.prototype.removeAttr = function (attributes) {
203 var attrs = attributes.split(' ');
204 this._each(function (el) {
205 attrs.forEach(function (attr) { return el.removeAttribute(attr); });
206 });
207 return this;
208 };
209 lgQuery.prototype.wrap = function (className) {
210 if (!this.firstElement) {
211 return this;
212 }
213 var wrapper = document.createElement('div');
214 wrapper.className = className;
215 this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
216 this.firstElement.parentNode.removeChild(this.firstElement);
217 wrapper.appendChild(this.firstElement);
218 return this;
219 };
220 lgQuery.prototype.addClass = function (classNames) {
221 if (classNames === void 0) { classNames = ''; }
222 this._each(function (el) {
223 // IE doesn't support multiple arguments
224 classNames.split(' ').forEach(function (className) {
225 el.classList.add(className);
226 });
227 });
228 return this;
229 };
230 lgQuery.prototype.removeClass = function (classNames) {
231 this._each(function (el) {
232 // IE doesn't support multiple arguments
233 classNames.split(' ').forEach(function (className) {
234 el.classList.remove(className);
235 });
236 });
237 return this;
238 };
239 lgQuery.prototype.hasClass = function (className) {
240 if (!this.firstElement) {
241 return false;
242 }
243 return this.firstElement.classList.contains(className);
244 };
245 lgQuery.prototype.hasAttribute = function (attribute) {
246 if (!this.firstElement) {
247 return false;
248 }
249 return this.firstElement.hasAttribute(attribute);
250 };
251 lgQuery.prototype.toggleClass = function (className) {
252 if (!this.firstElement) {
253 return this;
254 }
255 if (this.hasClass(className)) {
256 this.removeClass(className);
257 }
258 else {
259 this.addClass(className);
260 }
261 return this;
262 };
263 lgQuery.prototype.css = function (property, value) {
264 var _this = this;
265 this._each(function (el) {
266 _this._setCssVendorPrefix(el, property, value);
267 });
268 return this;
269 };
270 // Need to pass separate namespaces for separate elements
271 lgQuery.prototype.on = function (events, listener) {
272 var _this = this;
273 if (!this.selector) {
274 return this;
275 }
276 events.split(' ').forEach(function (event) {
277 if (!Array.isArray(lgQuery.eventListeners[event])) {
278 lgQuery.eventListeners[event] = [];
279 }
280 lgQuery.eventListeners[event].push(listener);
281 _this.selector.addEventListener(event.split('.')[0], listener);
282 });
283 return this;
284 };
285 // @todo - test this
286 lgQuery.prototype.once = function (event, listener) {
287 var _this = this;
288 this.on(event, function () {
289 _this.off(event);
290 listener(event);
291 });
292 return this;
293 };
294 lgQuery.prototype.off = function (event) {
295 var _this = this;
296 if (!this.selector) {
297 return this;
298 }
299 Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
300 if (_this.isEventMatched(event, eventName)) {
301 lgQuery.eventListeners[eventName].forEach(function (listener) {
302 _this.selector.removeEventListener(eventName.split('.')[0], listener);
303 });
304 lgQuery.eventListeners[eventName] = [];
305 }
306 });
307 return this;
308 };
309 lgQuery.prototype.trigger = function (event, detail) {
310 if (!this.firstElement) {
311 return this;
312 }
313 var customEvent = new CustomEvent(event.split('.')[0], {
314 detail: detail || null,
315 });
316 this.firstElement.dispatchEvent(customEvent);
317 return this;
318 };
319 // Does not support IE
320 lgQuery.prototype.load = function (url) {
321 var _this = this;
322 fetch(url).then(function (res) {
323 _this.selector.innerHTML = res;
324 });
325 return this;
326 };
327 lgQuery.prototype.html = function (html) {
328 if (html === undefined) {
329 if (!this.firstElement) {
330 return '';
331 }
332 return this.firstElement.innerHTML;
333 }
334 this._each(function (el) {
335 el.innerHTML = html;
336 });
337 return this;
338 };
339 lgQuery.prototype.append = function (html) {
340 this._each(function (el) {
341 if (typeof html === 'string') {
342 el.insertAdjacentHTML('beforeend', html);
343 }
344 else {
345 el.appendChild(html);
346 }
347 });
348 return this;
349 };
350 lgQuery.prototype.prepend = function (html) {
351 this._each(function (el) {
352 el.insertAdjacentHTML('afterbegin', html);
353 });
354 return this;
355 };
356 lgQuery.prototype.remove = function () {
357 this._each(function (el) {
358 el.parentNode.removeChild(el);
359 });
360 return this;
361 };
362 lgQuery.prototype.empty = function () {
363 this._each(function (el) {
364 el.innerHTML = '';
365 });
366 return this;
367 };
368 lgQuery.prototype.scrollTop = function (scrollTop) {
369 if (scrollTop !== undefined) {
370 document.body.scrollTop = scrollTop;
371 document.documentElement.scrollTop = scrollTop;
372 return this;
373 }
374 else {
375 return (window.pageYOffset ||
376 document.documentElement.scrollTop ||
377 document.body.scrollTop ||
378 0);
379 }
380 };
381 lgQuery.prototype.scrollLeft = function (scrollLeft) {
382 if (scrollLeft !== undefined) {
383 document.body.scrollLeft = scrollLeft;
384 document.documentElement.scrollLeft = scrollLeft;
385 return this;
386 }
387 else {
388 return (window.pageXOffset ||
389 document.documentElement.scrollLeft ||
390 document.body.scrollLeft ||
391 0);
392 }
393 };
394 lgQuery.prototype.offset = function () {
395 if (!this.firstElement) {
396 return {
397 left: 0,
398 top: 0,
399 };
400 }
401 var rect = this.firstElement.getBoundingClientRect();
402 var bodyMarginLeft = $LG('body').style().marginLeft;
403 // Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
404 return {
405 left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
406 top: rect.top + this.scrollTop(),
407 };
408 };
409 lgQuery.prototype.style = function () {
410 if (!this.firstElement) {
411 return {};
412 }
413 return (this.firstElement.currentStyle ||
414 window.getComputedStyle(this.firstElement));
415 };
416 // Width without padding and border even if box-sizing is used.
417 lgQuery.prototype.width = function () {
418 var style = this.style();
419 return (this.firstElement.clientWidth -
420 parseFloat(style.paddingLeft) -
421 parseFloat(style.paddingRight));
422 };
423 // Height without padding and border even if box-sizing is used.
424 lgQuery.prototype.height = function () {
425 var style = this.style();
426 return (this.firstElement.clientHeight -
427 parseFloat(style.paddingTop) -
428 parseFloat(style.paddingBottom));
429 };
430 lgQuery.eventListeners = {};
431 return lgQuery;
432 }());
433 function $LG(selector) {
434 return new lgQuery(selector);
435 }
436
437 var defaultDynamicOptions = [
438 'src',
439 'sources',
440 'subHtml',
441 'subHtmlUrl',
442 'html',
443 'video',
444 'poster',
445 'slideName',
446 'responsive',
447 'srcset',
448 'sizes',
449 'iframe',
450 'downloadUrl',
451 'download',
452 'width',
453 'facebookShareUrl',
454 'tweetText',
455 'iframeTitle',
456 'twitterShareUrl',
457 'pinterestShareUrl',
458 'pinterestText',
459 'fbHtml',
460 'disqusIdentifier',
461 'disqusUrl',
462 ];
463 // Convert html data-attribute to camalcase
464 function convertToData(attr) {
465 // FInd a way for lgsize
466 if (attr === 'href') {
467 return 'src';
468 }
469 attr = attr.replace('data-', '');
470 attr = attr.charAt(0).toLowerCase() + attr.slice(1);
471 attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
472 return attr;
473 }
474 var utils = {
475 /**
476 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
477 */
478 getSize: function (el, container, spacing, defaultLgSize) {
479 if (spacing === void 0) { spacing = 0; }
480 var LGel = $LG(el);
481 var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
482 if (!lgSize) {
483 return;
484 }
485 var isResponsiveSizes = lgSize.split(',');
486 // if at-least two viewport sizes are available
487 if (isResponsiveSizes[1]) {
488 var wWidth = window.innerWidth;
489 for (var i = 0; i < isResponsiveSizes.length; i++) {
490 var size_1 = isResponsiveSizes[i];
491 var responsiveWidth = parseInt(size_1.split('-')[2], 10);
492 if (responsiveWidth > wWidth) {
493 lgSize = size_1;
494 break;
495 }
496 // take last item as last option
497 if (i === isResponsiveSizes.length - 1) {
498 lgSize = size_1;
499 }
500 }
501 }
502 var size = lgSize.split('-');
503 var width = parseInt(size[0], 10);
504 var height = parseInt(size[1], 10);
505 var cWidth = container.width();
506 var cHeight = container.height() - spacing;
507 var maxWidth = Math.min(cWidth, width);
508 var maxHeight = Math.min(cHeight, height);
509 var ratio = Math.min(maxWidth / width, maxHeight / height);
510 return { width: width * ratio, height: height * ratio };
511 },
512 /**
513 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
514 * @param {jQuery Element}
515 * @returns {String} Transform CSS string
516 */
517 getTransform: function (el, container, top, bottom, imageSize) {
518 if (!imageSize) {
519 return;
520 }
521 var LGel = $LG(el).find('img').first();
522 if (!LGel.get()) {
523 return;
524 }
525 var containerRect = container.get().getBoundingClientRect();
526 var wWidth = containerRect.width;
527 // using innerWidth to include mobile safari bottom bar
528 var wHeight = container.height() - (top + bottom);
529 var elWidth = LGel.width();
530 var elHeight = LGel.height();
531 var elStyle = LGel.style();
532 var x = (wWidth - elWidth) / 2 -
533 LGel.offset().left +
534 (parseFloat(elStyle.paddingLeft) || 0) +
535 (parseFloat(elStyle.borderLeft) || 0) +
536 $LG(window).scrollLeft() +
537 containerRect.left;
538 var y = (wHeight - elHeight) / 2 -
539 LGel.offset().top +
540 (parseFloat(elStyle.paddingTop) || 0) +
541 (parseFloat(elStyle.borderTop) || 0) +
542 $LG(window).scrollTop() +
543 top;
544 var scX = elWidth / imageSize.width;
545 var scY = elHeight / imageSize.height;
546 var transform = 'translate3d(' +
547 (x *= -1) +
548 'px, ' +
549 (y *= -1) +
550 'px, 0) scale3d(' +
551 scX +
552 ', ' +
553 scY +
554 ', 1)';
555 return transform;
556 },
557 getIframeMarkup: function (iframeWidth, iframeHeight, src, iframeTitle) {
558 var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
559 return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" + iframeWidth + "; height: " + iframeHeight + "\">\n <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\" allowfullscreen=\"true\"></iframe>\n </div>";
560 },
561 getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
562 var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
563 var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
564 var imgMarkup = "<img " + altAttr + " " + srcsetAttr + " " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
565 var sourceTag = '';
566 if (sources) {
567 var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
568 sourceTag = sourceObj.map(function (source) {
569 var attrs = '';
570 Object.keys(source).forEach(function (key) {
571 // Do not remove the first space as it is required to separate the attributes
572 attrs += " " + key + "=\"" + source[key] + "\"";
573 });
574 return "<source " + attrs + "></source>";
575 });
576 }
577 return "" + sourceTag + imgMarkup;
578 },
579 // Get src from responsive src
580 getResponsiveSrc: function (srcItms) {
581 var rsWidth = [];
582 var rsSrc = [];
583 var src = '';
584 for (var i = 0; i < srcItms.length; i++) {
585 var _src = srcItms[i].split(' ');
586 // Manage empty space
587 if (_src[0] === '') {
588 _src.splice(0, 1);
589 }
590 rsSrc.push(_src[0]);
591 rsWidth.push(_src[1]);
592 }
593 var wWidth = window.innerWidth;
594 for (var j = 0; j < rsWidth.length; j++) {
595 if (parseInt(rsWidth[j], 10) > wWidth) {
596 src = rsSrc[j];
597 break;
598 }
599 }
600 return src;
601 },
602 isImageLoaded: function (img) {
603 if (!img)
604 return false;
605 // During the onload event, IE correctly identifies any images that
606 // weren’t downloaded as not complete. Others should too. Gecko-based
607 // browsers act like NS4 in that they report this incorrectly.
608 if (!img.complete) {
609 return false;
610 }
611 // However, they do have two very useful properties: naturalWidth and
612 // naturalHeight. These give the true size of the image. If it failed
613 // to load, either of these should be zero.
614 if (img.naturalWidth === 0) {
615 return false;
616 }
617 // No other way of checking: assume it’s ok.
618 return true;
619 },
620 getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, _isVideo) {
621 var videoClass = '';
622 if (_isVideo && _isVideo.youtube) {
623 videoClass = 'lg-has-youtube';
624 }
625 else if (_isVideo && _isVideo.vimeo) {
626 videoClass = 'lg-has-vimeo';
627 }
628 else {
629 videoClass = 'lg-has-html5';
630 }
631 return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n <div class=\"lg-video-play-button\">\n <svg\n viewBox=\"0 0 20 20\"\n preserveAspectRatio=\"xMidYMid\"\n focusable=\"false\"\n aria-labelledby=\"Play video\"\n role=\"img\"\n class=\"lg-video-play-icon\"\n >\n <title>Play video</title>\n <polygon class=\"lg-video-play-icon-inner\" points=\"1,0 20,10 1,20\"></polygon>\n </svg>\n <svg class=\"lg-video-play-icon-bg\" viewBox=\"0 0 50 50\" focusable=\"false\">\n <circle cx=\"50%\" cy=\"50%\" r=\"20\"></circle></svg>\n <svg class=\"lg-video-play-icon-circle\" viewBox=\"0 0 50 50\" focusable=\"false\">\n <circle cx=\"50%\" cy=\"50%\" r=\"20\"></circle>\n </svg>\n </div>\n " + (dummyImg || '') + "\n <img class=\"lg-object lg-video-poster\" src=\"" + _poster + "\" />\n </div>";
632 },
633 /**
634 * @desc Create dynamic elements array from gallery items when dynamic option is false
635 * It helps to avoid frequent DOM interaction
636 * and avoid multiple checks for dynamic elments
637 *
638 * @returns {Array} dynamicEl
639 */
640 getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
641 var dynamicElements = [];
642 var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
643 [].forEach.call(items, function (item) {
644 var dynamicEl = {};
645 for (var i = 0; i < item.attributes.length; i++) {
646 var attr = item.attributes[i];
647 if (attr.specified) {
648 var dynamicAttr = convertToData(attr.name);
649 var label = '';
650 if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
651 label = dynamicAttr;
652 }
653 if (label) {
654 dynamicEl[label] = attr.value;
655 }
656 }
657 }
658 var currentItem = $LG(item);
659 var alt = currentItem.find('img').first().attr('alt');
660 var title = currentItem.attr('title');
661 var thumb = exThumbImage
662 ? currentItem.attr(exThumbImage)
663 : currentItem.find('img').first().attr('src');
664 dynamicEl.thumb = thumb;
665 if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
666 dynamicEl.subHtml = title || alt || '';
667 }
668 dynamicEl.alt = alt || title || '';
669 dynamicElements.push(dynamicEl);
670 });
671 return dynamicElements;
672 },
673 isMobile: function () {
674 return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
675 },
676 };
677
678 var lightGalleryCoreSettings = {
679 mode: 'lg-slide',
680 easing: 'ease',
681 speed: 400,
682 licenseKey: '0000-0000-000-0000',
683 height: '100%',
684 width: '100%',
685 addClass: '',
686 startClass: 'lg-start-zoom',
687 backdropDuration: 300,
688 container: document.body,
689 startAnimationDuration: 400,
690 zoomFromOrigin: true,
691 hideBarsDelay: 0,
692 showBarsAfter: 10000,
693 slideDelay: 0,
694 supportLegacyBrowser: true,
695 allowMediaOverlap: false,
696 videoMaxSize: '1280-720',
697 defaultCaptionHeight: 0,
698 ariaLabelledby: '',
699 ariaDescribedby: '',
700 closable: true,
701 swipeToClose: true,
702 closeOnTap: true,
703 showCloseIcon: true,
704 showMaximizeIcon: false,
705 loop: true,
706 escKey: true,
707 keyPress: true,
708 controls: true,
709 slideEndAnimation: true,
710 hideControlOnEnd: false,
711 mousewheel: false,
712 getCaptionFromTitleOrAlt: true,
713 appendSubHtmlTo: '.lg-sub-html',
714 subHtmlSelectorRelative: false,
715 preload: 2,
716 numberOfSlideItemsInDom: 10,
717 showAfterLoad: true,
718 selector: '',
719 selectWithin: '',
720 nextHtml: '',
721 prevHtml: '',
722 index: 0,
723 iframeWidth: '100%',
724 iframeHeight: '100%',
725 download: true,
726 counter: true,
727 appendCounterTo: '.lg-toolbar',
728 swipeThreshold: 50,
729 enableSwipe: true,
730 enableDrag: true,
731 dynamic: false,
732 dynamicEl: [],
733 extraProps: [],
734 exThumbImage: '',
735 isMobile: undefined,
736 mobileSettings: {
737 controls: false,
738 showCloseIcon: false,
739 download: false,
740 },
741 plugins: [],
742 };
743
744 /**
745 * List of lightGallery events
746 * All events should be documented here
747 * Below interfaces are used to build the website documentations
748 * */
749 var lGEvents = {
750 afterAppendSlide: 'lgAfterAppendSlide',
751 init: 'lgInit',
752 hasVideo: 'lgHasVideo',
753 containerResize: 'lgContainerResize',
754 updateSlides: 'lgUpdateSlides',
755 afterAppendSubHtml: 'lgAfterAppendSubHtml',
756 beforeOpen: 'lgBeforeOpen',
757 afterOpen: 'lgAfterOpen',
758 slideItemLoad: 'lgSlideItemLoad',
759 beforeSlide: 'lgBeforeSlide',
760 afterSlide: 'lgAfterSlide',
761 posterClick: 'lgPosterClick',
762 dragStart: 'lgDragStart',
763 dragMove: 'lgDragMove',
764 dragEnd: 'lgDragEnd',
765 beforeNextSlide: 'lgBeforeNextSlide',
766 beforePrevSlide: 'lgBeforePrevSlide',
767 beforeClose: 'lgBeforeClose',
768 afterClose: 'lgAfterClose',
769 rotateLeft: 'lgRotateLeft',
770 rotateRight: 'lgRotateRight',
771 flipHorizontal: 'lgFlipHorizontal',
772 flipVertical: 'lgFlipVertical',
773 };
774
775 // @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
776 // @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
777 // Unique id for each gallery
778 var lgId = 0;
779 var LightGallery = /** @class */ (function () {
780 function LightGallery(element, options) {
781 this.lgOpened = false;
782 this.index = 0;
783 // lightGallery modules
784 this.plugins = [];
785 // false when lightGallery load first slide content;
786 this.lGalleryOn = false;
787 // True when a slide animation is in progress
788 this.lgBusy = false;
789 this.currentItemsInDom = [];
790 // Scroll top value before lightGallery is opened
791 this.prevScrollTop = 0;
792 this.isDummyImageRemoved = false;
793 this.dragOrSwipeEnabled = false;
794 this.mediaContainerPosition = {
795 top: 0,
796 bottom: 0,
797 };
798 if (!element) {
799 return this;
800 }
801 lgId++;
802 this.lgId = lgId;
803 this.el = element;
804 this.LGel = $LG(element);
805 this.generateSettings(options);
806 this.buildModules();
807 // When using dynamic mode, ensure dynamicEl is an array
808 if (this.settings.dynamic &&
809 this.settings.dynamicEl !== undefined &&
810 !Array.isArray(this.settings.dynamicEl)) {
811 throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
812 }
813 this.galleryItems = this.getItems();
814 this.normalizeSettings();
815 // Gallery items
816 this.init();
817 this.validateLicense();
818 return this;
819 }
820 LightGallery.prototype.generateSettings = function (options) {
821 // lightGallery settings
822 this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
823 if (this.settings.isMobile &&
824 typeof this.settings.isMobile === 'function'
825 ? this.settings.isMobile()
826 : utils.isMobile()) {
827 var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
828 this.settings = __assign(__assign({}, this.settings), mobileSettings);
829 }
830 };
831 LightGallery.prototype.normalizeSettings = function () {
832 if (this.settings.slideEndAnimation) {
833 this.settings.hideControlOnEnd = false;
834 }
835 if (!this.settings.closable) {
836 this.settings.swipeToClose = false;
837 }
838 // And reset it on close to get the correct value next time
839 this.zoomFromOrigin = this.settings.zoomFromOrigin;
840 // At the moment, Zoom from image doesn't support dynamic options
841 // @todo add zoomFromOrigin support for dynamic images
842 if (this.settings.dynamic) {
843 this.zoomFromOrigin = false;
844 }
845 if (!this.settings.container) {
846 this.settings.container = document.body;
847 }
848 // settings.preload should not be grater than $item.length
849 this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
850 };
851 LightGallery.prototype.init = function () {
852 var _this = this;
853 this.addSlideVideoInfo(this.galleryItems);
854 this.buildStructure();
855 this.LGel.trigger(lGEvents.init, {
856 instance: this,
857 });
858 if (this.settings.keyPress) {
859 this.keyPress();
860 }
861 setTimeout(function () {
862 _this.enableDrag();
863 _this.enableSwipe();
864 _this.triggerPosterClick();
865 }, 50);
866 this.arrow();
867 if (this.settings.mousewheel) {
868 this.mousewheel();
869 }
870 if (!this.settings.dynamic) {
871 this.openGalleryOnItemClick();
872 }
873 };
874 LightGallery.prototype.openGalleryOnItemClick = function () {
875 var _this = this;
876 var _loop_1 = function (index) {
877 var element = this_1.items[index];
878 var $element = $LG(element);
879 // Using different namespace for click because click event should not unbind if selector is same object('this')
880 // @todo manage all event listners - should have namespace that represent element
881 var uuid = lgQuery.generateUUID();
882 $element
883 .attr('data-lg-id', uuid)
884 .on("click.lgcustom-item-" + uuid, function (e) {
885 e.preventDefault();
886 var currentItemIndex = _this.settings.index || index;
887 _this.openGallery(currentItemIndex, element);
888 });
889 };
890 var this_1 = this;
891 // Using for loop instead of using bubbling as the items can be any html element.
892 for (var index = 0; index < this.items.length; index++) {
893 _loop_1(index);
894 }
895 };
896 /**
897 * Module constructor
898 * Modules are build incrementally.
899 * Gallery should be opened only once all the modules are initialized.
900 * use moduleBuildTimeout to make sure this
901 */
902 LightGallery.prototype.buildModules = function () {
903 var _this = this;
904 this.settings.plugins.forEach(function (plugin) {
905 _this.plugins.push(new plugin(_this, $LG));
906 });
907 };
908 LightGallery.prototype.validateLicense = function () {
909 if (!this.settings.licenseKey) {
910 console.error('Please provide a valid license key');
911 }
912 else if (this.settings.licenseKey === '0000-0000-000-0000') {
913 console.warn("lightGallery: " + this.settings.licenseKey + " license key is not valid for production use");
914 }
915 };
916 LightGallery.prototype.getSlideItem = function (index) {
917 return $LG(this.getSlideItemId(index));
918 };
919 LightGallery.prototype.getSlideItemId = function (index) {
920 return "#lg-item-" + this.lgId + "-" + index;
921 };
922 LightGallery.prototype.getIdName = function (id) {
923 return id + "-" + this.lgId;
924 };
925 LightGallery.prototype.getElementById = function (id) {
926 return $LG("#" + this.getIdName(id));
927 };
928 LightGallery.prototype.manageSingleSlideClassName = function () {
929 if (this.galleryItems.length < 2) {
930 this.outer.addClass('lg-single-item');
931 }
932 else {
933 this.outer.removeClass('lg-single-item');
934 }
935 };
936 LightGallery.prototype.buildStructure = function () {
937 var _this = this;
938 var container = this.$container && this.$container.get();
939 if (container) {
940 return;
941 }
942 var controls = '';
943 var subHtmlCont = '';
944 // Create controls
945 if (this.settings.controls) {
946 controls = "<button type=\"button\" id=\"" + this.getIdName('lg-prev') + "\" aria-label=\"Previous slide\" class=\"lg-prev lg-icon\"> " + this.settings.prevHtml + " </button>\n <button type=\"button\" id=\"" + this.getIdName('lg-next') + "\" aria-label=\"Next slide\" class=\"lg-next lg-icon\"> " + this.settings.nextHtml + " </button>";
947 }
948 if (this.settings.appendSubHtmlTo !== '.lg-item') {
949 subHtmlCont =
950 '<div class="lg-sub-html" role="status" aria-live="polite"></div>';
951 }
952 var addClasses = '';
953 if (this.settings.allowMediaOverlap) {
954 // Do not remove space before last single quote
955 addClasses += 'lg-media-overlap ';
956 }
957 var ariaLabelledby = this.settings.ariaLabelledby
958 ? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
959 : '';
960 var ariaDescribedby = this.settings.ariaDescribedby
961 ? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
962 : '';
963 var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
964 var closeIcon = this.settings.closable && this.settings.showCloseIcon
965 ? "<button type=\"button\" aria-label=\"Close gallery\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
966 : '';
967 var maximizeIcon = this.settings.showMaximizeIcon
968 ? "<button type=\"button\" aria-label=\"Toggle maximize\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
969 : '';
970 var template = "\n <div class=\"" + containerClassName + "\" id=\"" + this.getIdName('lg-container') + "\" tabindex=\"-1\" aria-modal=\"true\" " + ariaLabelledby + " " + ariaDescribedby + " role=\"dialog\"\n >\n <div id=\"" + this.getIdName('lg-backdrop') + "\" class=\"lg-backdrop\"></div>\n\n <div id=\"" + this.getIdName('lg-outer') + "\" class=\"lg-outer lg-use-css3 lg-css3 lg-hide-items " + addClasses + " \">\n\n <div id=\"" + this.getIdName('lg-content') + "\" class=\"lg-content\">\n <div id=\"" + this.getIdName('lg-inner') + "\" class=\"lg-inner\">\n </div>\n " + controls + "\n </div>\n <div id=\"" + this.getIdName('lg-toolbar') + "\" class=\"lg-toolbar lg-group\">\n " + maximizeIcon + "\n " + closeIcon + "\n </div>\n " + (this.settings.appendSubHtmlTo === '.lg-outer'
971 ? subHtmlCont
972 : '') + "\n <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
973 ? subHtmlCont
974 : '') + "\n </div>\n </div>\n </div>\n ";
975 $LG(this.settings.container)
976 .css('position', 'relative')
977 .append(template);
978 this.outer = this.getElementById('lg-outer');
979 this.$lgComponents = this.getElementById('lg-components');
980 this.$backdrop = this.getElementById('lg-backdrop');
981 this.$container = this.getElementById('lg-container');
982 this.$inner = this.getElementById('lg-inner');
983 this.$content = this.getElementById('lg-content');
984 this.$toolbar = this.getElementById('lg-toolbar');
985 this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
986 var outerClassNames = this.settings.mode + " ";
987 this.manageSingleSlideClassName();
988 if (this.settings.enableDrag) {
989 outerClassNames += 'lg-grab ';
990 }
991 if (this.settings.showAfterLoad) {
992 outerClassNames += 'lg-show-after-load';
993 }
994 this.outer.addClass(outerClassNames);
995 this.$inner.css('transition-timing-function', this.settings.easing);
996 this.$inner.css('transition-duration', this.settings.speed + 'ms');
997 if (this.settings.download) {
998 this.$toolbar.append("<a id=\"" + this.getIdName('lg-download') + "\" target=\"_blank\" rel=\"noopener\" aria-label=\"Download\" download class=\"lg-download lg-icon\"></a>");
999 }
1000 this.counter();
1001 $LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
1002 _this.refreshOnResize();
1003 });
1004 this.hideBars();
1005 this.manageCloseGallery();
1006 this.toggleMaximize();
1007 this.initModules();
1008 };
1009 LightGallery.prototype.refreshOnResize = function () {
1010 if (this.lgOpened) {
1011 var currentGalleryItem = this.galleryItems[this.index];
1012 var videoInfo = currentGalleryItem.__slideVideoInfo;
1013 this.mediaContainerPosition = this.getMediaContainerPosition();
1014 var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
1015 this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, videoInfo && this.settings.videoMaxSize);
1016 if (videoInfo) {
1017 this.resizeVideoSlide(this.index, this.currentImageSize);
1018 }
1019 if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
1020 var imgStyle = this.getDummyImgStyles(this.currentImageSize);
1021 this.outer
1022 .find('.lg-current .lg-dummy-img')
1023 .first()
1024 .attr('style', imgStyle);
1025 }
1026 this.LGel.trigger(lGEvents.containerResize);
1027 }
1028 };
1029 LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
1030 var lgVideoStyle = this.getVideoContStyle(imageSize);
1031 var currentSlide = this.getSlideItem(index);
1032 currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
1033 };
1034 /**
1035 * Update slides dynamically.
1036 * Add, edit or delete slides dynamically when lightGallery is opened.
1037 * Modify the current gallery items and pass it via updateSlides method
1038 * @note
1039 * - Do not mutate existing lightGallery items directly.
1040 * - Always pass new list of gallery items
1041 * - You need to take care of thumbnails outside the gallery if any
1042 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
1043 * @param items Gallery items
1044 * @param index After the update operation, which slide gallery should navigate to
1045 * @category lGPublicMethods
1046 * @example
1047 * const plugin = lightGallery();
1048 *
1049 * // Adding slides dynamically
1050 * let galleryItems = [
1051 * // Access existing lightGallery items
1052 * // galleryItems are automatically generated internally from the gallery HTML markup
1053 * // or directly from galleryItems when dynamic gallery is used
1054 * ...plugin.galleryItems,
1055 * ...[
1056 * {
1057 * src: 'img/img-1.png',
1058 * thumb: 'img/thumb1.png',
1059 * },
1060 * ],
1061 * ];
1062 * plugin.updateSlides(
1063 * galleryItems,
1064 * plugin.index,
1065 * );
1066 *
1067 *
1068 * // Remove slides dynamically
1069 * galleryItems = JSON.parse(
1070 * JSON.stringify(updateSlideInstance.galleryItems),
1071 * );
1072 * galleryItems.shift();
1073 * updateSlideInstance.updateSlides(galleryItems, 1);
1074 * @see <a href="/demos/update-slides/">Demo</a>
1075 */
1076 LightGallery.prototype.updateSlides = function (items, index) {
1077 if (this.index > items.length - 1) {
1078 this.index = items.length - 1;
1079 }
1080 if (items.length === 1) {
1081 this.index = 0;
1082 }
1083 if (!items.length) {
1084 this.closeGallery();
1085 return;
1086 }
1087 var currentSrc = this.galleryItems[index].src;
1088 this.galleryItems = items;
1089 this.updateControls();
1090 this.$inner.empty();
1091 this.currentItemsInDom = [];
1092 var _index = 0;
1093 // Find the current index based on source value of the slide
1094 this.galleryItems.some(function (galleryItem, itemIndex) {
1095 if (galleryItem.src === currentSrc) {
1096 _index = itemIndex;
1097 return true;
1098 }
1099 return false;
1100 });
1101 this.currentItemsInDom = this.organizeSlideItems(_index, -1);
1102 this.loadContent(_index, true);
1103 this.getSlideItem(_index).addClass('lg-current');
1104 this.index = _index;
1105 this.updateCurrentCounter(_index);
1106 this.LGel.trigger(lGEvents.updateSlides);
1107 };
1108 // Get gallery items based on multiple conditions
1109 LightGallery.prototype.getItems = function () {
1110 // Gallery items
1111 this.items = [];
1112 if (!this.settings.dynamic) {
1113 if (this.settings.selector === 'this') {
1114 this.items.push(this.el);
1115 }
1116 else if (this.settings.selector) {
1117 if (typeof this.settings.selector === 'string') {
1118 if (this.settings.selectWithin) {
1119 var selectWithin = $LG(this.settings.selectWithin);
1120 this.items = selectWithin
1121 .find(this.settings.selector)
1122 .get();
1123 }
1124 else {
1125 this.items = this.el.querySelectorAll(this.settings.selector);
1126 }
1127 }
1128 else {
1129 this.items = this.settings.selector;
1130 }
1131 }
1132 else {
1133 this.items = this.el.children;
1134 }
1135 return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
1136 }
1137 else {
1138 return this.settings.dynamicEl || [];
1139 }
1140 };
1141 /**
1142 * Open lightGallery.
1143 * Open gallery with specific slide by passing index of the slide as parameter.
1144 * @category lGPublicMethods
1145 * @param {Number} index - index of the slide
1146 * @param {HTMLElement} element - Which image lightGallery should zoom from
1147 *
1148 * @example
1149 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
1150 * const dynamicGallery = lightGallery($dynamicGallery, {
1151 * dynamic: true,
1152 * dynamicEl: [
1153 * {
1154 * src: 'img/1.jpg',
1155 * thumb: 'img/thumb-1.jpg',
1156 * subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
1157 * },
1158 * ...
1159 * ],
1160 * });
1161 * $dynamicGallery.addEventListener('click', function () {
1162 * // Starts with third item.(Optional).
1163 * // This is useful if you want use dynamic mode with
1164 * // custom thumbnails (thumbnails outside gallery),
1165 * dynamicGallery.openGallery(2);
1166 * });
1167 *
1168 */
1169 LightGallery.prototype.openGallery = function (index, element) {
1170 var _this = this;
1171 if (index === void 0) { index = this.settings.index; }
1172 // prevent accidental double execution
1173 if (this.lgOpened)
1174 return;
1175 this.lgOpened = true;
1176 this.outer.get().focus();
1177 this.outer.removeClass('lg-hide-items');
1178 // Add display block, but still has opacity 0
1179 this.$container.addClass('lg-show');
1180 var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
1181 this.currentItemsInDom = itemsToBeInsertedToDom;
1182 var items = '';
1183 itemsToBeInsertedToDom.forEach(function (item) {
1184 items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
1185 });
1186 this.$inner.append(items);
1187 this.addHtml(index);
1188 var transform = '';
1189 this.mediaContainerPosition = this.getMediaContainerPosition();
1190 var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
1191 if (!this.settings.allowMediaOverlap) {
1192 this.setMediaContainerPosition(top, bottom);
1193 }
1194 if (this.zoomFromOrigin && element) {
1195 this.currentImageSize = utils.getSize(element, this.outer, top + bottom, this.galleryItems[index].__slideVideoInfo &&
1196 this.settings.videoMaxSize);
1197 transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
1198 }
1199 if (!this.zoomFromOrigin || !transform) {
1200 this.outer.addClass(this.settings.startClass);
1201 this.getSlideItem(index).removeClass('lg-complete');
1202 }
1203 var timeout = this.settings.zoomFromOrigin
1204 ? 100
1205 : this.settings.backdropDuration;
1206 setTimeout(function () {
1207 _this.outer.addClass('lg-components-open');
1208 }, timeout);
1209 this.index = index;
1210 this.LGel.trigger(lGEvents.beforeOpen);
1211 // add class lg-current to remove initial transition
1212 this.getSlideItem(index).addClass('lg-current');
1213 this.lGalleryOn = false;
1214 // Store the current scroll top value to scroll back after closing the gallery..
1215 this.prevScrollTop = $LG(window).scrollTop();
1216 setTimeout(function () {
1217 // Need to check both zoomFromOrigin and transform values as we need to set set the
1218 // default opening animation if user missed to add the lg-size attribute
1219 if (_this.zoomFromOrigin && transform) {
1220 var currentSlide_1 = _this.getSlideItem(index);
1221 currentSlide_1.css('transform', transform);
1222 setTimeout(function () {
1223 currentSlide_1
1224 .addClass('lg-start-progress lg-start-end-progress')
1225 .css('transition-duration', _this.settings.startAnimationDuration + 'ms');
1226 _this.outer.addClass('lg-zoom-from-image');
1227 });
1228 setTimeout(function () {
1229 currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
1230 }, 100);
1231 }
1232 setTimeout(function () {
1233 _this.$backdrop.addClass('in');
1234 _this.$container.addClass('lg-show-in');
1235 }, 10);
1236 // lg-visible class resets gallery opacity to 1
1237 if (!_this.zoomFromOrigin || !transform) {
1238 setTimeout(function () {
1239 _this.outer.addClass('lg-visible');
1240 }, _this.settings.backdropDuration);
1241 }
1242 // initiate slide function
1243 _this.slide(index, false, false, false);
1244 _this.LGel.trigger(lGEvents.afterOpen);
1245 });
1246 if (document.body === this.settings.container) {
1247 $LG('html').addClass('lg-on');
1248 }
1249 };
1250 /**
1251 * Note - Changing the position of the media on every slide transition creates a flickering effect.
1252 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
1253 * if you have dynamic captions for each media,
1254 * you can provide an appropriate height for the captions via allowMediaOverlap option
1255 */
1256 LightGallery.prototype.getMediaContainerPosition = function () {
1257 if (this.settings.allowMediaOverlap) {
1258 return {
1259 top: 0,
1260 bottom: 0,
1261 };
1262 }
1263 var top = this.$toolbar.get().clientHeight || 0;
1264 var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
1265 var captionHeight = this.settings.defaultCaptionHeight ||
1266 (subHtml && subHtml.clientHeight) ||
1267 0;
1268 var thumbContainer = this.outer.find('.lg-thumb-outer').get();
1269 var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
1270 var bottom = thumbHeight + captionHeight;
1271 return {
1272 top: top,
1273 bottom: bottom,
1274 };
1275 };
1276 LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
1277 if (top === void 0) { top = 0; }
1278 if (bottom === void 0) { bottom = 0; }
1279 this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
1280 };
1281 LightGallery.prototype.hideBars = function () {
1282 var _this = this;
1283 // Hide controllers if mouse doesn't move for some period
1284 setTimeout(function () {
1285 _this.outer.removeClass('lg-hide-items');
1286 if (_this.settings.hideBarsDelay > 0) {
1287 _this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
1288 _this.outer.removeClass('lg-hide-items');
1289 clearTimeout(_this.hideBarTimeout);
1290 // Timeout will be cleared on each slide movement also
1291 _this.hideBarTimeout = setTimeout(function () {
1292 _this.outer.addClass('lg-hide-items');
1293 }, _this.settings.hideBarsDelay);
1294 });
1295 _this.outer.trigger('mousemove.lg');
1296 }
1297 }, this.settings.showBarsAfter);
1298 };
1299 LightGallery.prototype.initPictureFill = function ($img) {
1300 if (this.settings.supportLegacyBrowser) {
1301 try {
1302 picturefill({
1303 elements: [$img.get()],
1304 });
1305 }
1306 catch (e) {
1307 console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
1308 }
1309 }
1310 };
1311 /**
1312 * @desc Create image counter
1313 * Ex: 1/10
1314 */
1315 LightGallery.prototype.counter = function () {
1316 if (this.settings.counter) {
1317 var counterHtml = "<div class=\"lg-counter\" role=\"status\" aria-live=\"polite\">\n <span id=\"" + this.getIdName('lg-counter-current') + "\" class=\"lg-counter-current\">" + (this.index + 1) + " </span> /\n <span id=\"" + this.getIdName('lg-counter-all') + "\" class=\"lg-counter-all\">" + this.galleryItems.length + " </span></div>";
1318 this.outer.find(this.settings.appendCounterTo).append(counterHtml);
1319 }
1320 };
1321 /**
1322 * @desc add sub-html into the slide
1323 * @param {Number} index - index of the slide
1324 */
1325 LightGallery.prototype.addHtml = function (index) {
1326 var subHtml;
1327 var subHtmlUrl;
1328 if (this.galleryItems[index].subHtmlUrl) {
1329 subHtmlUrl = this.galleryItems[index].subHtmlUrl;
1330 }
1331 else {
1332 subHtml = this.galleryItems[index].subHtml;
1333 }
1334 if (!subHtmlUrl) {
1335 if (subHtml) {
1336 // get first letter of sub-html
1337 // if first letter starts with . or # get the html form the jQuery object
1338 var fL = subHtml.substring(0, 1);
1339 if (fL === '.' || fL === '#') {
1340 if (this.settings.subHtmlSelectorRelative &&
1341 !this.settings.dynamic) {
1342 subHtml = $LG(this.items)
1343 .eq(index)
1344 .find(subHtml)
1345 .first()
1346 .html();
1347 }
1348 else {
1349 subHtml = $LG(subHtml).first().html();
1350 }
1351 }
1352 }
1353 else {
1354 subHtml = '';
1355 }
1356 }
1357 if (this.settings.appendSubHtmlTo !== '.lg-item') {
1358 if (subHtmlUrl) {
1359 this.outer.find('.lg-sub-html').load(subHtmlUrl);
1360 }
1361 else {
1362 this.outer.find('.lg-sub-html').html(subHtml);
1363 }
1364 }
1365 else {
1366 var currentSlide = $LG(this.getSlideItemId(index));
1367 if (subHtmlUrl) {
1368 currentSlide.load(subHtmlUrl);
1369 }
1370 else {
1371 currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
1372 }
1373 }
1374 // Add lg-empty-html class if title doesn't exist
1375 if (typeof subHtml !== 'undefined' && subHtml !== null) {
1376 if (subHtml === '') {
1377 this.outer
1378 .find(this.settings.appendSubHtmlTo)
1379 .addClass('lg-empty-html');
1380 }
1381 else {
1382 this.outer
1383 .find(this.settings.appendSubHtmlTo)
1384 .removeClass('lg-empty-html');
1385 }
1386 }
1387 this.LGel.trigger(lGEvents.afterAppendSubHtml, {
1388 index: index,
1389 });
1390 };
1391 /**
1392 * @desc Preload slides
1393 * @param {Number} index - index of the slide
1394 * @todo preload not working for the first slide, Also, should work for the first and last slide as well
1395 */
1396 LightGallery.prototype.preload = function (index) {
1397 for (var i = 1; i <= this.settings.preload; i++) {
1398 if (i >= this.galleryItems.length - index) {
1399 break;
1400 }
1401 this.loadContent(index + i, false);
1402 }
1403 for (var j = 1; j <= this.settings.preload; j++) {
1404 if (index - j < 0) {
1405 break;
1406 }
1407 this.loadContent(index - j, false);
1408 }
1409 };
1410 LightGallery.prototype.getDummyImgStyles = function (imageSize) {
1411 if (!imageSize)
1412 return '';
1413 return "width:" + imageSize.width + "px;\n margin-left: -" + imageSize.width / 2 + "px;\n margin-top: -" + imageSize.height / 2 + "px;\n height:" + imageSize.height + "px";
1414 };
1415 LightGallery.prototype.getVideoContStyle = function (imageSize) {
1416 if (!imageSize)
1417 return '';
1418 return "width:" + imageSize.width + "px;\n height:" + imageSize.height + "px";
1419 };
1420 LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
1421 var $currentItem;
1422 if (!this.settings.dynamic) {
1423 $currentItem = $LG(this.items).eq(index);
1424 }
1425 if ($currentItem) {
1426 var _dummyImgSrc = void 0;
1427 if (!this.settings.exThumbImage) {
1428 _dummyImgSrc = $currentItem.find('img').first().attr('src');
1429 }
1430 else {
1431 _dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
1432 }
1433 if (!_dummyImgSrc)
1434 return '';
1435 var imgStyle = this.getDummyImgStyles(this.currentImageSize);
1436 var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
1437 $currentSlide.addClass('lg-first-slide');
1438 this.outer.addClass('lg-first-slide-loading');
1439 return dummyImgContent;
1440 }
1441 return '';
1442 };
1443 LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
1444 var currentGalleryItem = this.galleryItems[index];
1445 var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
1446 // Use the thumbnail as dummy image which will be resized to actual image size and
1447 // displayed on top of actual image
1448 var imgContent = '';
1449 var altAttr = alt ? 'alt="' + alt + '"' : '';
1450 if (!this.lGalleryOn && this.zoomFromOrigin && this.currentImageSize) {
1451 imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
1452 }
1453 else {
1454 imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
1455 }
1456 var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
1457 $currentSlide.prepend(imgMarkup);
1458 };
1459 LightGallery.prototype.onLgObjectLoad = function ($el, index, delay, speed, dummyImageLoaded) {
1460 var _this = this;
1461 if (dummyImageLoaded) {
1462 this.LGel.trigger(lGEvents.slideItemLoad, {
1463 index: index,
1464 delay: delay || 0,
1465 });
1466 }
1467 $el.find('.lg-object')
1468 .first()
1469 .on('load.lg', function () {
1470 _this.handleLgObjectLoad($el, index, delay, speed, dummyImageLoaded);
1471 });
1472 setTimeout(function () {
1473 $el.find('.lg-object')
1474 .first()
1475 .on('error.lg', function () {
1476 $el.addClass('lg-complete lg-complete_');
1477 $el.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
1478 });
1479 }, speed);
1480 };
1481 LightGallery.prototype.handleLgObjectLoad = function ($el, index, delay, speed, dummyImageLoaded) {
1482 var _this = this;
1483 setTimeout(function () {
1484 $el.addClass('lg-complete lg-complete_');
1485 if (!dummyImageLoaded) {
1486 _this.LGel.trigger(lGEvents.slideItemLoad, {
1487 index: index,
1488 delay: delay || 0,
1489 });
1490 }
1491 }, speed);
1492 };
1493 /**
1494 * @desc Check the given src is video
1495 * @param {String} src
1496 * @return {Object} video type
1497 * Ex:{ youtube : ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
1498 *
1499 * @todo - this information can be moved to dynamicEl to avoid frequent calls
1500 */
1501 LightGallery.prototype.isVideo = function (src, index) {
1502 if (!src) {
1503 if (this.galleryItems[index].video) {
1504 return {
1505 html5: true,
1506 };
1507 }
1508 else {
1509 console.error('lightGallery :- data-src is not provided on slide item ' +
1510 (index + 1) +
1511 '. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
1512 return;
1513 }
1514 }
1515 var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)/i);
1516 var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)/i);
1517 var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
1518 if (youtube) {
1519 return {
1520 youtube: youtube,
1521 };
1522 }
1523 else if (vimeo) {
1524 return {
1525 vimeo: vimeo,
1526 };
1527 }
1528 else if (wistia) {
1529 return {
1530 wistia: wistia,
1531 };
1532 }
1533 };
1534 // Add video slideInfo
1535 LightGallery.prototype.addSlideVideoInfo = function (items) {
1536 var _this = this;
1537 items.forEach(function (element, index) {
1538 element.__slideVideoInfo = _this.isVideo(element.src, index);
1539 });
1540 };
1541 /**
1542 * Load slide content into slide.
1543 * This is used to load content into slides that is not visible too
1544 * @param {Number} index - index of the slide.
1545 * @param {Boolean} rec - if true call loadcontent() function again.
1546 */
1547 LightGallery.prototype.loadContent = function (index, rec) {
1548 var _this = this;
1549 var currentGalleryItem = this.galleryItems[index];
1550 var $currentSlide = $LG(this.getSlideItemId(index));
1551 var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
1552 var src = currentGalleryItem.src;
1553 var video = currentGalleryItem.video;
1554 var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
1555 if (currentGalleryItem.responsive) {
1556 var srcDyItms = currentGalleryItem.responsive.split(',');
1557 src = utils.getResponsiveSrc(srcDyItms) || src;
1558 }
1559 var videoInfo = currentGalleryItem.__slideVideoInfo;
1560 var lgVideoStyle = '';
1561 var iframe = !!currentGalleryItem.iframe;
1562 if (!$currentSlide.hasClass('lg-loaded')) {
1563 if (videoInfo) {
1564 var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
1565 var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
1566 lgVideoStyle = this.getVideoContStyle(videoSize);
1567 }
1568 if (iframe) {
1569 var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, src, currentGalleryItem.iframeTitle);
1570 $currentSlide.prepend(markup);
1571 }
1572 else if (poster) {
1573 var dummyImg = '';
1574 var isFirstSlide_1 = !this.lGalleryOn;
1575 var hasStartAnimation = !this.lGalleryOn &&
1576 this.zoomFromOrigin &&
1577 this.currentImageSize;
1578 if (hasStartAnimation) {
1579 dummyImg = this.getDummyImageContent($currentSlide, index, '');
1580 }
1581 var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, videoInfo);
1582 $currentSlide.prepend(markup);
1583 var delay_1 = (hasStartAnimation
1584 ? this.settings.startAnimationDuration
1585 : this.settings.backdropDuration) + 100;
1586 setTimeout(function () {
1587 _this.LGel.trigger(lGEvents.hasVideo, {
1588 index: index,
1589 src: src,
1590 html5Video: _html5Video,
1591 hasPoster: true,
1592 isFirstSlide: isFirstSlide_1,
1593 });
1594 }, delay_1);
1595 }
1596 else if (videoInfo) {
1597 var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
1598 $currentSlide.prepend(markup);
1599 this.LGel.trigger(lGEvents.hasVideo, {
1600 index: index,
1601 src: src,
1602 html5Video: _html5Video,
1603 hasPoster: false,
1604 });
1605 }
1606 else {
1607 this.setImgMarkup(src, $currentSlide, index);
1608 if (srcset || sources) {
1609 var $img = $currentSlide.find('.lg-object');
1610 this.initPictureFill($img);
1611 }
1612 }
1613 this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
1614 if (this.lGalleryOn &&
1615 this.settings.appendSubHtmlTo === '.lg-item') {
1616 this.addHtml(index);
1617 }
1618 }
1619 // For first time add some delay for displaying the start animation.
1620 var _speed = 0;
1621 // delay for adding complete class. it is 0 except first time.
1622 var delay = 0;
1623 if (!this.lGalleryOn) {
1624 if (this.zoomFromOrigin && this.currentImageSize) {
1625 delay = this.settings.startAnimationDuration + 10;
1626 }
1627 else {
1628 delay = this.settings.backdropDuration + 10;
1629 }
1630 }
1631 // Do not change the delay value because it is required for zoom plugin.
1632 // If gallery opened from direct url (hash) speed value should be 0
1633 if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
1634 _speed = delay;
1635 }
1636 // Only for first slide
1637 if (!this.lGalleryOn && this.zoomFromOrigin && this.currentImageSize) {
1638 setTimeout(function () {
1639 $currentSlide
1640 .removeClass('lg-start-end-progress lg-start-progress')
1641 .removeAttr('style');
1642 }, this.settings.startAnimationDuration + 100);
1643 if (!$currentSlide.hasClass('lg-loaded')) {
1644 setTimeout(function () {
1645 $currentSlide
1646 .find('.lg-img-wrap')
1647 .append(utils.getImgMarkup(index, src, '', srcset, sizes, currentGalleryItem.sources));
1648 if (srcset || sources) {
1649 var $img = $currentSlide.find('.lg-object');
1650 _this.initPictureFill($img);
1651 }
1652 _this.onLgObjectLoad($currentSlide, index, delay, _speed, true);
1653 var mediaObject = $currentSlide
1654 .find('.lg-object')
1655 .first();
1656 if (utils.isImageLoaded(mediaObject.get())) {
1657 _this.loadContentOnLoad(index, $currentSlide, _speed);
1658 }
1659 else {
1660 mediaObject.on('load.lg error.lg', function () {
1661 _this.loadContentOnLoad(index, $currentSlide, _speed);
1662 });
1663 }
1664 }, this.settings.startAnimationDuration + 100);
1665 }
1666 }
1667 // SLide content has been added to dom
1668 $currentSlide.addClass('lg-loaded');
1669 this.onLgObjectLoad($currentSlide, index, delay, _speed, false);
1670 // @todo check load state for html5 videos
1671 if (videoInfo && videoInfo.html5 && !poster) {
1672 $currentSlide.addClass('lg-complete lg-complete_');
1673 }
1674 // When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
1675 if ((!this.zoomFromOrigin || !this.currentImageSize) &&
1676 $currentSlide.hasClass('lg-complete_') &&
1677 !this.lGalleryOn) {
1678 setTimeout(function () {
1679 $currentSlide.addClass('lg-complete');
1680 }, this.settings.backdropDuration);
1681 }
1682 // Content loaded
1683 // Need to set lGalleryOn before calling preload function
1684 this.lGalleryOn = true;
1685 if (rec === true) {
1686 if (!$currentSlide.hasClass('lg-complete_')) {
1687 $currentSlide
1688 .find('.lg-object')
1689 .first()
1690 .on('load.lg error.lg', function () {
1691 _this.preload(index);
1692 });
1693 }
1694 else {
1695 this.preload(index);
1696 }
1697 }
1698 };
1699 LightGallery.prototype.loadContentOnLoad = function (index, $currentSlide, speed) {
1700 var _this = this;
1701 setTimeout(function () {
1702 $currentSlide.find('.lg-dummy-img').remove();
1703 $currentSlide.removeClass('lg-first-slide');
1704 _this.outer.removeClass('lg-first-slide-loading');
1705 _this.isDummyImageRemoved = true;
1706 _this.preload(index);
1707 }, speed + 300);
1708 };
1709 LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
1710 var _this = this;
1711 if (numberOfItems === void 0) { numberOfItems = 0; }
1712 var itemsToBeInsertedToDom = [];
1713 // Minimum 2 items should be there
1714 var possibleNumberOfItems = Math.max(numberOfItems, 3);
1715 possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
1716 var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
1717 if (this.galleryItems.length <= 3) {
1718 this.galleryItems.forEach(function (_element, index) {
1719 itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
1720 });
1721 return itemsToBeInsertedToDom;
1722 }
1723 if (index < (this.galleryItems.length - 1) / 2) {
1724 for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
1725 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
1726 }
1727 var numberOfExistingItems = itemsToBeInsertedToDom.length;
1728 for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
1729 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
1730 }
1731 }
1732 else {
1733 for (var idx = index; idx <= this.galleryItems.length - 1 &&
1734 idx < index + possibleNumberOfItems / 2; idx++) {
1735 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
1736 }
1737 var numberOfExistingItems = itemsToBeInsertedToDom.length;
1738 for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
1739 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
1740 }
1741 }
1742 if (this.settings.loop) {
1743 if (index === this.galleryItems.length - 1) {
1744 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
1745 }
1746 else if (index === 0) {
1747 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
1748 }
1749 }
1750 if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
1751 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
1752 }
1753 return itemsToBeInsertedToDom;
1754 };
1755 LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
1756 var _this = this;
1757 var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
1758 itemsToBeInsertedToDom.forEach(function (item) {
1759 if (_this.currentItemsInDom.indexOf(item) === -1) {
1760 _this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
1761 }
1762 });
1763 this.currentItemsInDom.forEach(function (item) {
1764 if (itemsToBeInsertedToDom.indexOf(item) === -1) {
1765 $LG("#" + item).remove();
1766 }
1767 });
1768 return itemsToBeInsertedToDom;
1769 };
1770 /**
1771 * Get previous index of the slide
1772 */
1773 LightGallery.prototype.getPreviousSlideIndex = function () {
1774 var prevIndex = 0;
1775 try {
1776 var currentItemId = this.outer
1777 .find('.lg-current')
1778 .first()
1779 .attr('id');
1780 prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
1781 }
1782 catch (error) {
1783 prevIndex = 0;
1784 }
1785 return prevIndex;
1786 };
1787 LightGallery.prototype.setDownloadValue = function (index) {
1788 if (this.settings.download) {
1789 var currentGalleryItem = this.galleryItems[index];
1790 var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
1791 currentGalleryItem.downloadUrl === 'false';
1792 if (hideDownloadBtn) {
1793 this.outer.addClass('lg-hide-download');
1794 }
1795 else {
1796 var $download = this.getElementById('lg-download');
1797 this.outer.removeClass('lg-hide-download');
1798 $download.attr('href', currentGalleryItem.downloadUrl ||
1799 currentGalleryItem.src);
1800 if (currentGalleryItem.download) {
1801 $download.attr('download', currentGalleryItem.download);
1802 }
1803 }
1804 }
1805 };
1806 LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
1807 var _this = this;
1808 if (this.lGalleryOn) {
1809 previousSlideItem.addClass('lg-slide-progress');
1810 }
1811 setTimeout(function () {
1812 // remove all transitions
1813 _this.outer.addClass('lg-no-trans');
1814 _this.outer
1815 .find('.lg-item')
1816 .removeClass('lg-prev-slide lg-next-slide');
1817 if (direction === 'prev') {
1818 //prevslide
1819 currentSlideItem.addClass('lg-prev-slide');
1820 previousSlideItem.addClass('lg-next-slide');
1821 }
1822 else {
1823 // next slide
1824 currentSlideItem.addClass('lg-next-slide');
1825 previousSlideItem.addClass('lg-prev-slide');
1826 }
1827 // give 50 ms for browser to add/remove class
1828 setTimeout(function () {
1829 _this.outer.find('.lg-item').removeClass('lg-current');
1830 currentSlideItem.addClass('lg-current');
1831 // reset all transitions
1832 _this.outer.removeClass('lg-no-trans');
1833 }, 50);
1834 }, this.lGalleryOn ? this.settings.slideDelay : 0);
1835 };
1836 /**
1837 * Goto a specific slide.
1838 * @param {Number} index - index of the slide
1839 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
1840 * @param {Boolean} fromThumb - true if slide function called via thumbnail click
1841 * @param {String} direction - Direction of the slide(next/prev)
1842 * @category lGPublicMethods
1843 * @example
1844 * const plugin = lightGallery();
1845 * // to go to 3rd slide
1846 * plugin.slide(2);
1847 *
1848 */
1849 LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
1850 var _this = this;
1851 var prevIndex = this.getPreviousSlideIndex();
1852 this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
1853 // Prevent multiple call, Required for hsh plugin
1854 if (this.lGalleryOn && prevIndex === index) {
1855 return;
1856 }
1857 var numberOfGalleryItems = this.galleryItems.length;
1858 if (!this.lgBusy) {
1859 if (this.settings.counter) {
1860 this.updateCurrentCounter(index);
1861 }
1862 var currentSlideItem = this.getSlideItem(index);
1863 var previousSlideItem_1 = this.getSlideItem(prevIndex);
1864 var currentGalleryItem = this.galleryItems[index];
1865 var videoInfo = currentGalleryItem.__slideVideoInfo;
1866 this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
1867 this.setDownloadValue(index);
1868 if (videoInfo) {
1869 var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
1870 var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
1871 this.resizeVideoSlide(index, videoSize);
1872 }
1873 this.LGel.trigger(lGEvents.beforeSlide, {
1874 prevIndex: prevIndex,
1875 index: index,
1876 fromTouch: !!fromTouch,
1877 fromThumb: !!fromThumb,
1878 });
1879 this.lgBusy = true;
1880 clearTimeout(this.hideBarTimeout);
1881 this.arrowDisable(index);
1882 if (!direction) {
1883 if (index < prevIndex) {
1884 direction = 'prev';
1885 }
1886 else if (index > prevIndex) {
1887 direction = 'next';
1888 }
1889 }
1890 if (!fromTouch) {
1891 this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
1892 }
1893 else {
1894 this.outer
1895 .find('.lg-item')
1896 .removeClass('lg-prev-slide lg-current lg-next-slide');
1897 var touchPrev = void 0;
1898 var touchNext = void 0;
1899 if (numberOfGalleryItems > 2) {
1900 touchPrev = index - 1;
1901 touchNext = index + 1;
1902 if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
1903 // next slide
1904 touchNext = 0;
1905 touchPrev = numberOfGalleryItems - 1;
1906 }
1907 else if (index === numberOfGalleryItems - 1 &&
1908 prevIndex === 0) {
1909 // prev slide
1910 touchNext = 0;
1911 touchPrev = numberOfGalleryItems - 1;
1912 }
1913 }
1914 else {
1915 touchPrev = 0;
1916 touchNext = 1;
1917 }
1918 if (direction === 'prev') {
1919 this.getSlideItem(touchNext).addClass('lg-next-slide');
1920 }
1921 else {
1922 this.getSlideItem(touchPrev).addClass('lg-prev-slide');
1923 }
1924 currentSlideItem.addClass('lg-current');
1925 }
1926 // Do not put load content in set timeout as it needs to load immediately when the gallery is opened
1927 if (!this.lGalleryOn) {
1928 this.loadContent(index, true);
1929 }
1930 setTimeout(function () {
1931 if (_this.lGalleryOn) {
1932 _this.loadContent(index, true);
1933 }
1934 // Add title if this.settings.appendSubHtmlTo === lg-sub-html
1935 if (_this.settings.appendSubHtmlTo !== '.lg-item') {
1936 _this.addHtml(index);
1937 }
1938 }, (this.lGalleryOn ? this.settings.speed + 50 : 50) + (fromTouch ? 0 : this.settings.slideDelay));
1939 setTimeout(function () {
1940 _this.lgBusy = false;
1941 previousSlideItem_1.removeClass('lg-slide-progress');
1942 _this.LGel.trigger(lGEvents.afterSlide, {
1943 prevIndex: prevIndex,
1944 index: index,
1945 fromTouch: fromTouch,
1946 fromThumb: fromThumb,
1947 });
1948 }, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
1949 }
1950 this.index = index;
1951 };
1952 LightGallery.prototype.updateCurrentCounter = function (index) {
1953 this.getElementById('lg-counter-current').html(index + 1 + '');
1954 };
1955 LightGallery.prototype.updateCounterTotal = function () {
1956 this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
1957 };
1958 LightGallery.prototype.getSlideType = function (item) {
1959 if (item.__slideVideoInfo) {
1960 return 'video';
1961 }
1962 else if (item.iframe) {
1963 return 'iframe';
1964 }
1965 else {
1966 return 'image';
1967 }
1968 };
1969 LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
1970 var distanceX = endCoords.pageX - startCoords.pageX;
1971 var distanceY = endCoords.pageY - startCoords.pageY;
1972 var allowSwipe = false;
1973 if (this.swipeDirection) {
1974 allowSwipe = true;
1975 }
1976 else {
1977 if (Math.abs(distanceX) > 15) {
1978 this.swipeDirection = 'horizontal';
1979 allowSwipe = true;
1980 }
1981 else if (Math.abs(distanceY) > 15) {
1982 this.swipeDirection = 'vertical';
1983 allowSwipe = true;
1984 }
1985 }
1986 if (!allowSwipe) {
1987 return;
1988 }
1989 var $currentSlide = this.getSlideItem(this.index);
1990 if (this.swipeDirection === 'horizontal') {
1991 e === null || e === void 0 ? void 0 : e.preventDefault();
1992 // reset opacity and transition duration
1993 this.outer.addClass('lg-dragging');
1994 // move current slide
1995 this.setTranslate($currentSlide, distanceX, 0);
1996 // move next and prev slide with current slide
1997 var width = $currentSlide.get().offsetWidth;
1998 var slideWidthAmount = (width * 15) / 100;
1999 var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
2000 this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
2001 this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
2002 }
2003 else if (this.swipeDirection === 'vertical') {
2004 if (this.settings.swipeToClose) {
2005 e === null || e === void 0 ? void 0 : e.preventDefault();
2006 this.$container.addClass('lg-dragging-vertical');
2007 var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
2008 this.$backdrop.css('opacity', opacity);
2009 var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
2010 this.setTranslate($currentSlide, 0, distanceY, scale, scale);
2011 if (Math.abs(distanceY) > 100) {
2012 this.outer
2013 .addClass('lg-hide-items')
2014 .removeClass('lg-components-open');
2015 }
2016 }
2017 }
2018 };
2019 LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
2020 var _this = this;
2021 var distance;
2022 // keep slide animation for any mode while dragg/swipe
2023 if (this.settings.mode !== 'lg-slide') {
2024 this.outer.addClass('lg-slide');
2025 }
2026 // set transition duration
2027 setTimeout(function () {
2028 _this.$container.removeClass('lg-dragging-vertical');
2029 _this.outer
2030 .removeClass('lg-dragging lg-hide-items')
2031 .addClass('lg-components-open');
2032 var triggerClick = true;
2033 if (_this.swipeDirection === 'horizontal') {
2034 distance = endCoords.pageX - startCoords.pageX;
2035 var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
2036 if (distance < 0 &&
2037 distanceAbs > _this.settings.swipeThreshold) {
2038 _this.goToNextSlide(true);
2039 triggerClick = false;
2040 }
2041 else if (distance > 0 &&
2042 distanceAbs > _this.settings.swipeThreshold) {
2043 _this.goToPrevSlide(true);
2044 triggerClick = false;
2045 }
2046 }
2047 else if (_this.swipeDirection === 'vertical') {
2048 distance = Math.abs(endCoords.pageY - startCoords.pageY);
2049 if (_this.settings.closable &&
2050 _this.settings.swipeToClose &&
2051 distance > 100) {
2052 _this.closeGallery();
2053 return;
2054 }
2055 else {
2056 _this.$backdrop.css('opacity', 1);
2057 }
2058 }
2059 _this.outer.find('.lg-item').removeAttr('style');
2060 if (triggerClick &&
2061 Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
2062 // Trigger click if distance is less than 5 pix
2063 var target = $LG(event.target);
2064 if (_this.isPosterElement(target)) {
2065 _this.LGel.trigger(lGEvents.posterClick);
2066 }
2067 }
2068 _this.swipeDirection = undefined;
2069 });
2070 // remove slide class once drag/swipe is completed if mode is not slide
2071 setTimeout(function () {
2072 if (!_this.outer.hasClass('lg-dragging') &&
2073 _this.settings.mode !== 'lg-slide') {
2074 _this.outer.removeClass('lg-slide');
2075 }
2076 }, this.settings.speed + 100);
2077 };
2078 LightGallery.prototype.enableSwipe = function () {
2079 var _this = this;
2080 var startCoords = {};
2081 var endCoords = {};
2082 var isMoved = false;
2083 var isSwiping = false;
2084 if (this.settings.enableSwipe) {
2085 this.$inner.on('touchstart.lg', function (e) {
2086 _this.dragOrSwipeEnabled = true;
2087 var $item = _this.getSlideItem(_this.index);
2088 if (($LG(e.target).hasClass('lg-item') ||
2089 $item.get().contains(e.target)) &&
2090 !_this.outer.hasClass('lg-zoomed') &&
2091 !_this.lgBusy &&
2092 e.targetTouches.length === 1) {
2093 isSwiping = true;
2094 _this.touchAction = 'swipe';
2095 _this.manageSwipeClass();
2096 startCoords = {
2097 pageX: e.targetTouches[0].pageX,
2098 pageY: e.targetTouches[0].pageY,
2099 };
2100 }
2101 });
2102 this.$inner.on('touchmove.lg', function (e) {
2103 if (isSwiping &&
2104 _this.touchAction === 'swipe' &&
2105 e.targetTouches.length === 1) {
2106 endCoords = {
2107 pageX: e.targetTouches[0].pageX,
2108 pageY: e.targetTouches[0].pageY,
2109 };
2110 _this.touchMove(startCoords, endCoords, e);
2111 isMoved = true;
2112 }
2113 });
2114 this.$inner.on('touchend.lg', function (event) {
2115 if (_this.touchAction === 'swipe') {
2116 if (isMoved) {
2117 isMoved = false;
2118 _this.touchEnd(endCoords, startCoords, event);
2119 }
2120 else if (isSwiping) {
2121 var target = $LG(event.target);
2122 if (_this.isPosterElement(target)) {
2123 _this.LGel.trigger(lGEvents.posterClick);
2124 }
2125 }
2126 _this.touchAction = undefined;
2127 isSwiping = false;
2128 }
2129 });
2130 }
2131 };
2132 LightGallery.prototype.enableDrag = function () {
2133 var _this = this;
2134 var startCoords = {};
2135 var endCoords = {};
2136 var isDraging = false;
2137 var isMoved = false;
2138 if (this.settings.enableDrag) {
2139 this.outer.on('mousedown.lg', function (e) {
2140 _this.dragOrSwipeEnabled = true;
2141 var $item = _this.getSlideItem(_this.index);
2142 if ($LG(e.target).hasClass('lg-item') ||
2143 $item.get().contains(e.target)) {
2144 if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
2145 e.preventDefault();
2146 if (!_this.lgBusy) {
2147 _this.manageSwipeClass();
2148 startCoords = {
2149 pageX: e.pageX,
2150 pageY: e.pageY,
2151 };
2152 isDraging = true;
2153 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
2154 _this.outer.get().scrollLeft += 1;
2155 _this.outer.get().scrollLeft -= 1;
2156 // *
2157 _this.outer
2158 .removeClass('lg-grab')
2159 .addClass('lg-grabbing');
2160 _this.LGel.trigger(lGEvents.dragStart);
2161 }
2162 }
2163 }
2164 });
2165 $LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
2166 if (isDraging && _this.lgOpened) {
2167 isMoved = true;
2168 endCoords = {
2169 pageX: e.pageX,
2170 pageY: e.pageY,
2171 };
2172 _this.touchMove(startCoords, endCoords);
2173 _this.LGel.trigger(lGEvents.dragMove);
2174 }
2175 });
2176 $LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
2177 if (!_this.lgOpened) {
2178 return;
2179 }
2180 var target = $LG(event.target);
2181 if (isMoved) {
2182 isMoved = false;
2183 _this.touchEnd(endCoords, startCoords, event);
2184 _this.LGel.trigger(lGEvents.dragEnd);
2185 }
2186 else if (_this.isPosterElement(target)) {
2187 _this.LGel.trigger(lGEvents.posterClick);
2188 }
2189 // Prevent execution on click
2190 if (isDraging) {
2191 isDraging = false;
2192 _this.outer.removeClass('lg-grabbing').addClass('lg-grab');
2193 }
2194 });
2195 }
2196 };
2197 LightGallery.prototype.triggerPosterClick = function () {
2198 var _this = this;
2199 this.$inner.on('click.lg', function (event) {
2200 if (!_this.dragOrSwipeEnabled &&
2201 _this.isPosterElement($LG(event.target))) {
2202 _this.LGel.trigger(lGEvents.posterClick);
2203 }
2204 });
2205 };
2206 LightGallery.prototype.manageSwipeClass = function () {
2207 var _touchNext = this.index + 1;
2208 var _touchPrev = this.index - 1;
2209 if (this.settings.loop && this.galleryItems.length > 2) {
2210 if (this.index === 0) {
2211 _touchPrev = this.galleryItems.length - 1;
2212 }
2213 else if (this.index === this.galleryItems.length - 1) {
2214 _touchNext = 0;
2215 }
2216 }
2217 this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
2218 if (_touchPrev > -1) {
2219 this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
2220 }
2221 this.getSlideItem(_touchNext).addClass('lg-next-slide');
2222 };
2223 /**
2224 * Go to next slide
2225 * @param {Boolean} fromTouch - true if slide function called via touch event
2226 * @category lGPublicMethods
2227 * @example
2228 * const plugin = lightGallery();
2229 * plugin.goToNextSlide();
2230 * @see <a href="/demos/methods/">Demo</a>
2231 */
2232 LightGallery.prototype.goToNextSlide = function (fromTouch) {
2233 var _this = this;
2234 var _loop = this.settings.loop;
2235 if (fromTouch && this.galleryItems.length < 3) {
2236 _loop = false;
2237 }
2238 if (!this.lgBusy) {
2239 if (this.index + 1 < this.galleryItems.length) {
2240 this.index++;
2241 this.LGel.trigger(lGEvents.beforeNextSlide, {
2242 index: this.index,
2243 });
2244 this.slide(this.index, !!fromTouch, false, 'next');
2245 }
2246 else {
2247 if (_loop) {
2248 this.index = 0;
2249 this.LGel.trigger(lGEvents.beforeNextSlide, {
2250 index: this.index,
2251 });
2252 this.slide(this.index, !!fromTouch, false, 'next');
2253 }
2254 else if (this.settings.slideEndAnimation && !fromTouch) {
2255 this.outer.addClass('lg-right-end');
2256 setTimeout(function () {
2257 _this.outer.removeClass('lg-right-end');
2258 }, 400);
2259 }
2260 }
2261 }
2262 };
2263 /**
2264 * Go to previous slides
2265 * @param {Boolean} fromTouch - true if slide function called via touch event
2266 * @category lGPublicMethods
2267 * @example
2268 * const plugin = lightGallery({});
2269 * plugin.goToPrevSlide();
2270 * @see <a href="/demos/methods/">Demo</a>
2271 *
2272 */
2273 LightGallery.prototype.goToPrevSlide = function (fromTouch) {
2274 var _this = this;
2275 var _loop = this.settings.loop;
2276 if (fromTouch && this.galleryItems.length < 3) {
2277 _loop = false;
2278 }
2279 if (!this.lgBusy) {
2280 if (this.index > 0) {
2281 this.index--;
2282 this.LGel.trigger(lGEvents.beforePrevSlide, {
2283 index: this.index,
2284 fromTouch: fromTouch,
2285 });
2286 this.slide(this.index, !!fromTouch, false, 'prev');
2287 }
2288 else {
2289 if (_loop) {
2290 this.index = this.galleryItems.length - 1;
2291 this.LGel.trigger(lGEvents.beforePrevSlide, {
2292 index: this.index,
2293 fromTouch: fromTouch,
2294 });
2295 this.slide(this.index, !!fromTouch, false, 'prev');
2296 }
2297 else if (this.settings.slideEndAnimation && !fromTouch) {
2298 this.outer.addClass('lg-left-end');
2299 setTimeout(function () {
2300 _this.outer.removeClass('lg-left-end');
2301 }, 400);
2302 }
2303 }
2304 }
2305 };
2306 LightGallery.prototype.keyPress = function () {
2307 var _this = this;
2308 $LG(window).on("keydown.lg.global" + this.lgId, function (e) {
2309 if (_this.lgOpened &&
2310 _this.settings.escKey === true &&
2311 e.keyCode === 27) {
2312 e.preventDefault();
2313 if (_this.settings.allowMediaOverlap &&
2314 _this.outer.hasClass('lg-can-toggle') &&
2315 _this.outer.hasClass('lg-components-open')) {
2316 _this.outer.removeClass('lg-components-open');
2317 }
2318 else {
2319 _this.closeGallery();
2320 }
2321 }
2322 if (_this.lgOpened && _this.galleryItems.length > 1) {
2323 if (e.keyCode === 37) {
2324 e.preventDefault();
2325 _this.goToPrevSlide();
2326 }
2327 if (e.keyCode === 39) {
2328 e.preventDefault();
2329 _this.goToNextSlide();
2330 }
2331 }
2332 });
2333 };
2334 LightGallery.prototype.arrow = function () {
2335 var _this = this;
2336 this.getElementById('lg-prev').on('click.lg', function () {
2337 _this.goToPrevSlide();
2338 });
2339 this.getElementById('lg-next').on('click.lg', function () {
2340 _this.goToNextSlide();
2341 });
2342 };
2343 LightGallery.prototype.arrowDisable = function (index) {
2344 // Disable arrows if settings.hideControlOnEnd is true
2345 if (!this.settings.loop && this.settings.hideControlOnEnd) {
2346 var $prev = this.getElementById('lg-prev');
2347 var $next = this.getElementById('lg-next');
2348 if (index + 1 === this.galleryItems.length) {
2349 $next.attr('disabled', 'disabled').addClass('disabled');
2350 }
2351 else {
2352 $next.removeAttr('disabled').removeClass('disabled');
2353 }
2354 if (index === 0) {
2355 $prev.attr('disabled', 'disabled').addClass('disabled');
2356 }
2357 else {
2358 $prev.removeAttr('disabled').removeClass('disabled');
2359 }
2360 }
2361 };
2362 LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
2363 if (scaleX === void 0) { scaleX = 1; }
2364 if (scaleY === void 0) { scaleY = 1; }
2365 $el.css('transform', 'translate3d(' +
2366 xValue +
2367 'px, ' +
2368 yValue +
2369 'px, 0px) scale3d(' +
2370 scaleX +
2371 ', ' +
2372 scaleY +
2373 ', 1)');
2374 };
2375 LightGallery.prototype.mousewheel = function () {
2376 var _this = this;
2377 this.outer.on('mousewheel.lg', function (e) {
2378 if (!e.deltaY || _this.galleryItems.length < 2) {
2379 return;
2380 }
2381 if (e.deltaY > 0) {
2382 _this.goToPrevSlide();
2383 }
2384 else {
2385 _this.goToNextSlide();
2386 }
2387 e.preventDefault();
2388 });
2389 };
2390 LightGallery.prototype.isSlideElement = function (target) {
2391 return (target.hasClass('lg-outer') ||
2392 target.hasClass('lg-item') ||
2393 target.hasClass('lg-img-wrap'));
2394 };
2395 LightGallery.prototype.isPosterElement = function (target) {
2396 var playButton = this.getSlideItem(this.index)
2397 .find('.lg-video-play-button')
2398 .get();
2399 return (target.hasClass('lg-video-poster') ||
2400 target.hasClass('lg-video-play-button') ||
2401 (playButton && playButton.contains(target.get())));
2402 };
2403 /**
2404 * Maximize minimize inline gallery.
2405 * @category lGPublicMethods
2406 */
2407 LightGallery.prototype.toggleMaximize = function () {
2408 var _this = this;
2409 this.getElementById('lg-maximize').on('click.lg', function () {
2410 _this.$container.toggleClass('lg-inline');
2411 _this.refreshOnResize();
2412 });
2413 };
2414 LightGallery.prototype.invalidateItems = function () {
2415 for (var index = 0; index < this.items.length; index++) {
2416 var element = this.items[index];
2417 var $element = $LG(element);
2418 $element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
2419 }
2420 };
2421 LightGallery.prototype.manageCloseGallery = function () {
2422 var _this = this;
2423 if (!this.settings.closable)
2424 return;
2425 var mousedown = false;
2426 this.getElementById('lg-close').on('click.lg', function () {
2427 _this.closeGallery();
2428 });
2429 if (this.settings.closeOnTap) {
2430 // If you drag the slide and release outside gallery gets close on chrome
2431 // for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
2432 this.outer.on('mousedown.lg', function (e) {
2433 var target = $LG(e.target);
2434 if (_this.isSlideElement(target)) {
2435 mousedown = true;
2436 }
2437 else {
2438 mousedown = false;
2439 }
2440 });
2441 this.outer.on('mousemove.lg', function () {
2442 mousedown = false;
2443 });
2444 this.outer.on('mouseup.lg', function (e) {
2445 var target = $LG(e.target);
2446 if (_this.isSlideElement(target) && mousedown) {
2447 if (!_this.outer.hasClass('lg-dragging')) {
2448 _this.closeGallery();
2449 }
2450 }
2451 });
2452 }
2453 };
2454 /**
2455 * Close lightGallery if it is opened.
2456 *
2457 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
2458 * @return returns the estimated time to close gallery completely including the close animation duration
2459 * @category lGPublicMethods
2460 * @example
2461 * const plugin = lightGallery();
2462 * plugin.closeGallery();
2463 *
2464 */
2465 LightGallery.prototype.closeGallery = function (force) {
2466 var _this = this;
2467 if (!this.lgOpened || (!this.settings.closable && !force)) {
2468 return 0;
2469 }
2470 this.LGel.trigger(lGEvents.beforeClose);
2471 $LG(window).scrollTop(this.prevScrollTop);
2472 var currentItem = this.items[this.index];
2473 var transform;
2474 if (this.zoomFromOrigin && currentItem) {
2475 var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
2476 var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, this.galleryItems[this.index].__slideVideoInfo &&
2477 this.settings.videoMaxSize);
2478 transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
2479 }
2480 if (this.zoomFromOrigin && transform) {
2481 this.outer.addClass('lg-closing lg-zoom-from-image');
2482 this.getSlideItem(this.index)
2483 .addClass('lg-start-end-progress')
2484 .css('transition-duration', this.settings.startAnimationDuration + 'ms')
2485 .css('transform', transform);
2486 }
2487 else {
2488 this.outer.addClass('lg-hide-items');
2489 // lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
2490 // If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
2491 this.outer.removeClass('lg-zoom-from-image');
2492 }
2493 // Unbind all events added by lightGallery
2494 // @todo
2495 //this.$el.off('.lg.tm');
2496 this.destroyModules();
2497 this.lGalleryOn = false;
2498 this.isDummyImageRemoved = false;
2499 this.zoomFromOrigin = this.settings.zoomFromOrigin;
2500 clearTimeout(this.hideBarTimeout);
2501 this.hideBarTimeout = false;
2502 $LG('html').removeClass('lg-on');
2503 this.outer.removeClass('lg-visible lg-components-open');
2504 // Resetting opacity to 0 isd required as vertical swipe to close function adds inline opacity.
2505 this.$backdrop.removeClass('in').css('opacity', 0);
2506 var removeTimeout = this.zoomFromOrigin && transform
2507 ? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
2508 : this.settings.backdropDuration;
2509 this.$container.removeClass('lg-show-in');
2510 // Once the closign animation is completed and gallery is invisible
2511 setTimeout(function () {
2512 if (_this.zoomFromOrigin && transform) {
2513 _this.outer.removeClass('lg-zoom-from-image');
2514 }
2515 _this.$container.removeClass('lg-show');
2516 // Need to remove inline opacity as it is used in the stylesheet as well
2517 _this.$backdrop
2518 .removeAttr('style')
2519 .css('transition-duration', _this.settings.backdropDuration + 'ms');
2520 _this.outer.removeClass("lg-closing " + _this.settings.startClass);
2521 _this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
2522 _this.$inner.empty();
2523 if (_this.lgOpened) {
2524 _this.LGel.trigger(lGEvents.afterClose, {
2525 instance: _this,
2526 });
2527 }
2528 if (_this.outer.get()) {
2529 _this.outer.get().blur();
2530 }
2531 _this.lgOpened = false;
2532 }, removeTimeout + 100);
2533 return removeTimeout + 100;
2534 };
2535 LightGallery.prototype.initModules = function () {
2536 this.plugins.forEach(function (module) {
2537 try {
2538 module.init();
2539 }
2540 catch (err) {
2541 console.warn("lightGallery:- make sure lightGallery module is properly initiated");
2542 }
2543 });
2544 };
2545 LightGallery.prototype.destroyModules = function (destroy) {
2546 this.plugins.forEach(function (module) {
2547 try {
2548 if (destroy) {
2549 module.destroy();
2550 }
2551 else {
2552 module.closeGallery && module.closeGallery();
2553 }
2554 }
2555 catch (err) {
2556 console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
2557 }
2558 });
2559 };
2560 /**
2561 * Refresh lightGallery with new set of children.
2562 *
2563 * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
2564 *
2565 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
2566 * @see <a href="/demos/dynamic-mode/">Demo</a>
2567 * @category lGPublicMethods
2568 * @example
2569 * const plugin = lightGallery();
2570 * // Delete or add children, then call
2571 * plugin.refresh();
2572 *
2573 */
2574 LightGallery.prototype.refresh = function (galleryItems) {
2575 if (!this.settings.dynamic) {
2576 this.invalidateItems();
2577 }
2578 if (galleryItems) {
2579 this.galleryItems = galleryItems;
2580 }
2581 else {
2582 this.galleryItems = this.getItems();
2583 }
2584 this.updateControls();
2585 this.openGalleryOnItemClick();
2586 this.LGel.trigger(lGEvents.updateSlides);
2587 };
2588 LightGallery.prototype.updateControls = function () {
2589 this.addSlideVideoInfo(this.galleryItems);
2590 this.updateCounterTotal();
2591 this.manageSingleSlideClassName();
2592 };
2593 /**
2594 * Destroy lightGallery.
2595 * Destroy lightGallery and its plugin instances completely
2596 *
2597 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
2598 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
2599 * You can use refresh method most of the times.
2600 * @category lGPublicMethods
2601 * @example
2602 * const plugin = lightGallery();
2603 * plugin.destroy();
2604 *
2605 */
2606 LightGallery.prototype.destroy = function () {
2607 var _this = this;
2608 var closeTimeout = this.closeGallery(true);
2609 setTimeout(function () {
2610 _this.destroyModules(true);
2611 if (!_this.settings.dynamic) {
2612 _this.invalidateItems();
2613 }
2614 $LG(window).off(".lg.global" + _this.lgId);
2615 _this.LGel.off('.lg');
2616 _this.$container.remove();
2617 }, closeTimeout);
2618 return closeTimeout;
2619 };
2620 return LightGallery;
2621 }());
2622
2623 function lightGallery(el, options) {
2624 return new LightGallery(el, options);
2625 }
2626
2627 var LgMethods = {
2628 onAfterAppendSlide: 'lgAfterAppendSlide',
2629 onInit: 'lgInit',
2630 onHasVideo: 'lgHasVideo',
2631 onContainerResize: 'lgContainerResize',
2632 onUpdateSlides: 'lgUpdateSlides',
2633 onAfterAppendSubHtml: 'lgAfterAppendSubHtml',
2634 onBeforeOpen: 'lgBeforeOpen',
2635 onAfterOpen: 'lgAfterOpen',
2636 onSlideItemLoad: 'lgSlideItemLoad',
2637 onBeforeSlide: 'lgBeforeSlide',
2638 onAfterSlide: 'lgAfterSlide',
2639 onPosterClick: 'lgPosterClick',
2640 onDragStart: 'lgDragStart',
2641 onDragMove: 'lgDragMove',
2642 onDragEnd: 'lgDragEnd',
2643 onBeforeNextSlide: 'lgBeforeNextSlide',
2644 onBeforePrevSlide: 'lgBeforePrevSlide',
2645 onBeforeClose: 'lgBeforeClose',
2646 onAfterClose: 'lgAfterClose',
2647 };
2648 var LG = function (_a) {
2649 var children = _a.children, elementClassNames = _a.elementClassNames, onAfterAppendSlide = _a.onAfterAppendSlide, onInit = _a.onInit, onHasVideo = _a.onHasVideo, onContainerResize = _a.onContainerResize, onAfterAppendSubHtml = _a.onAfterAppendSubHtml, onBeforeOpen = _a.onBeforeOpen, onAfterOpen = _a.onAfterOpen, onSlideItemLoad = _a.onSlideItemLoad, onBeforeSlide = _a.onBeforeSlide, onAfterSlide = _a.onAfterSlide, onPosterClick = _a.onPosterClick, onDragStart = _a.onDragStart, onDragMove = _a.onDragMove, onDragEnd = _a.onDragEnd, onBeforeNextSlide = _a.onBeforeNextSlide, onBeforePrevSlide = _a.onBeforePrevSlide, onBeforeClose = _a.onBeforeClose, onAfterClose = _a.onAfterClose, restProps = __rest(_a, ["children", "elementClassNames", "onAfterAppendSlide", "onInit", "onHasVideo", "onContainerResize", "onAfterAppendSubHtml", "onBeforeOpen", "onAfterOpen", "onSlideItemLoad", "onBeforeSlide", "onAfterSlide", "onPosterClick", "onDragStart", "onDragMove", "onDragEnd", "onBeforeNextSlide", "onBeforePrevSlide", "onBeforeClose", "onAfterClose"]);
2650 var $lg = React.useRef(null);
2651 var registerEvents = React.useCallback(function () {
2652 if (onAfterAppendSlide && $lg && $lg.current) {
2653 $lg.current.addEventListener(LgMethods.onAfterAppendSlide, (function (event) {
2654 onAfterAppendSlide(event.detail);
2655 }));
2656 }
2657 if (onInit && $lg && $lg.current) {
2658 $lg.current.addEventListener(LgMethods.onInit, (function (event) {
2659 onInit(event.detail);
2660 }));
2661 }
2662 if (onHasVideo && $lg && $lg.current) {
2663 $lg.current.addEventListener(LgMethods.onHasVideo, (function (event) {
2664 onHasVideo(event.detail);
2665 }));
2666 }
2667 if (onContainerResize && $lg && $lg.current) {
2668 $lg.current.addEventListener(LgMethods.onContainerResize, (function (event) {
2669 onContainerResize(event.detail);
2670 }));
2671 }
2672 if (onAfterAppendSubHtml && $lg && $lg.current) {
2673 $lg.current.addEventListener(LgMethods.onAfterAppendSubHtml, (function (event) {
2674 onAfterAppendSubHtml(event.detail);
2675 }));
2676 }
2677 if (onBeforeOpen && $lg && $lg.current) {
2678 $lg.current.addEventListener(LgMethods.onBeforeOpen, (function (event) {
2679 onBeforeOpen(event.detail);
2680 }));
2681 }
2682 if (onAfterOpen && $lg && $lg.current) {
2683 $lg.current.addEventListener(LgMethods.onAfterOpen, (function (event) {
2684 onAfterOpen(event.detail);
2685 }));
2686 }
2687 if (onSlideItemLoad && $lg && $lg.current) {
2688 $lg.current.addEventListener(LgMethods.onSlideItemLoad, (function (event) {
2689 onSlideItemLoad(event.detail);
2690 }));
2691 }
2692 if (onBeforeSlide && $lg && $lg.current) {
2693 $lg.current.addEventListener(LgMethods.onBeforeSlide, (function (event) {
2694 onBeforeSlide(event.detail);
2695 }));
2696 }
2697 if (onAfterSlide && $lg && $lg.current) {
2698 $lg.current.addEventListener(LgMethods.onAfterSlide, (function (event) {
2699 onAfterSlide(event.detail);
2700 }));
2701 }
2702 if (onPosterClick && $lg && $lg.current) {
2703 $lg.current.addEventListener(LgMethods.onPosterClick, (function (event) {
2704 onPosterClick(event.detail);
2705 }));
2706 }
2707 if (onDragStart && $lg && $lg.current) {
2708 $lg.current.addEventListener(LgMethods.onDragStart, (function (event) {
2709 onDragStart(event.detail);
2710 }));
2711 }
2712 if (onDragMove && $lg && $lg.current) {
2713 $lg.current.addEventListener(LgMethods.onDragMove, (function (event) {
2714 onDragMove(event.detail);
2715 }));
2716 }
2717 if (onDragEnd && $lg && $lg.current) {
2718 $lg.current.addEventListener(LgMethods.onDragEnd, (function (event) {
2719 onDragEnd(event.detail);
2720 }));
2721 }
2722 if (onBeforeNextSlide && $lg && $lg.current) {
2723 $lg.current.addEventListener(LgMethods.onBeforeNextSlide, (function (event) {
2724 onBeforeNextSlide(event.detail);
2725 }));
2726 }
2727 if (onBeforePrevSlide && $lg && $lg.current) {
2728 $lg.current.addEventListener(LgMethods.onBeforePrevSlide, (function (event) {
2729 onBeforePrevSlide(event.detail);
2730 }));
2731 }
2732 if (onBeforeClose && $lg && $lg.current) {
2733 $lg.current.addEventListener(LgMethods.onBeforeClose, (function (event) {
2734 onBeforeClose(event.detail);
2735 }));
2736 }
2737 if (onAfterClose && $lg && $lg.current) {
2738 $lg.current.addEventListener(LgMethods.onAfterClose, (function (event) {
2739 onAfterClose(event.detail);
2740 }));
2741 }
2742 }, [
2743 onAfterAppendSlide,
2744 onAfterAppendSubHtml,
2745 onAfterClose,
2746 onAfterOpen,
2747 onAfterSlide,
2748 onBeforeClose,
2749 onBeforeNextSlide,
2750 onBeforeOpen,
2751 onBeforePrevSlide,
2752 onBeforeSlide,
2753 onContainerResize,
2754 onDragEnd,
2755 onDragMove,
2756 onDragStart,
2757 onHasVideo,
2758 onInit,
2759 onPosterClick,
2760 onSlideItemLoad,
2761 ]);
2762 React.useEffect(function () {
2763 registerEvents();
2764 var lightGallery$1 = lightGallery($lg.current, restProps);
2765 return function cleanup() {
2766 lightGallery$1.destroy();
2767 };
2768 }, []);
2769 return (React.createElement("div", { className: "lg-react-element " + (elementClassNames ? elementClassNames : ''), ref: $lg }, children));
2770 };
2771
2772 return LG;
2773
2774})));
2775//# sourceMappingURL=Lightgallery.umd.js.map