UNPKG

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