UNPKG

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