UNPKG

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