lightgallery.umd.js 119 KB

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