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