UNPKG

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