lg-video.umd.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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.lgVideo = 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. var videoSettings = {
  35. autoplayFirstVideo: true,
  36. youTubePlayerParams: false,
  37. vimeoPlayerParams: false,
  38. wistiaPlayerParams: false,
  39. gotoNextSlideOnVideoEnd: true,
  40. autoplayVideoOnSlide: false,
  41. videojs: false,
  42. videojsOptions: {},
  43. };
  44. /**
  45. * List of lightGallery events
  46. * All events should be documented here
  47. * Below interfaces are used to build the website documentations
  48. * */
  49. var lGEvents = {
  50. afterAppendSlide: 'lgAfterAppendSlide',
  51. init: 'lgInit',
  52. hasVideo: 'lgHasVideo',
  53. containerResize: 'lgContainerResize',
  54. updateSlides: 'lgUpdateSlides',
  55. afterAppendSubHtml: 'lgAfterAppendSubHtml',
  56. beforeOpen: 'lgBeforeOpen',
  57. afterOpen: 'lgAfterOpen',
  58. slideItemLoad: 'lgSlideItemLoad',
  59. beforeSlide: 'lgBeforeSlide',
  60. afterSlide: 'lgAfterSlide',
  61. posterClick: 'lgPosterClick',
  62. dragStart: 'lgDragStart',
  63. dragMove: 'lgDragMove',
  64. dragEnd: 'lgDragEnd',
  65. beforeNextSlide: 'lgBeforeNextSlide',
  66. beforePrevSlide: 'lgBeforePrevSlide',
  67. beforeClose: 'lgBeforeClose',
  68. afterClose: 'lgAfterClose',
  69. rotateLeft: 'lgRotateLeft',
  70. rotateRight: 'lgRotateRight',
  71. flipHorizontal: 'lgFlipHorizontal',
  72. flipVertical: 'lgFlipVertical',
  73. autoplay: 'lgAutoplay',
  74. autoplayStart: 'lgAutoplayStart',
  75. autoplayStop: 'lgAutoplayStop',
  76. };
  77. var param = function (obj) {
  78. return Object.keys(obj)
  79. .map(function (k) {
  80. return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
  81. })
  82. .join('&');
  83. };
  84. var getVimeoURLParams = function (defaultParams, videoInfo) {
  85. if (!videoInfo || !videoInfo.vimeo)
  86. return '';
  87. var urlParams = videoInfo.vimeo[2] || '';
  88. urlParams =
  89. urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
  90. var defaultPlayerParams = defaultParams
  91. ? '&' + param(defaultParams)
  92. : '';
  93. // For vimeo last parms gets priority if duplicates found
  94. var vimeoPlayerParams = "?autoplay=0&muted=1" + defaultPlayerParams + urlParams;
  95. return vimeoPlayerParams;
  96. };
  97. /**
  98. * Video module for lightGallery
  99. * Supports HTML5, YouTube, Vimeo, wistia videos
  100. *
  101. *
  102. * @ref Wistia
  103. * https://wistia.com/support/integrations/wordpress(How to get url)
  104. * https://wistia.com/support/developers/embed-options#using-embed-options
  105. * https://wistia.com/support/developers/player-api
  106. * https://wistia.com/support/developers/construct-an-embed-code
  107. * http://jsfiddle.net/xvnm7xLm/
  108. * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
  109. * https://wistia.com/support/embed-and-share/sharing-videos
  110. * https://private-sharing.wistia.com/medias/mwhrulrucj
  111. *
  112. * @ref Youtube
  113. * https://developers.google.com/youtube/player_parameters#enablejsapi
  114. * https://developers.google.com/youtube/iframe_api_reference
  115. * https://developer.chrome.com/blog/autoplay/#iframe-delegation
  116. *
  117. * @ref Vimeo
  118. * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
  119. * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
  120. * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
  121. */
  122. var Video = /** @class */ (function () {
  123. function Video(instance) {
  124. // get lightGallery core plugin instance
  125. this.core = instance;
  126. this.settings = __assign(__assign({}, videoSettings), this.core.settings);
  127. return this;
  128. }
  129. Video.prototype.init = function () {
  130. var _this = this;
  131. /**
  132. * Event triggered when video url found without poster
  133. * Append video HTML
  134. * Play if autoplayFirstVideo is true
  135. */
  136. this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
  137. this.core.LGel.on(lGEvents.posterClick + ".video", function () {
  138. var $el = _this.core.getSlideItem(_this.core.index);
  139. _this.loadVideoOnPosterClick($el);
  140. });
  141. this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
  142. // @desc fired immediately before each slide transition.
  143. this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
  144. // @desc fired immediately after each slide transition.
  145. this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
  146. };
  147. /**
  148. * @desc Event triggered when a slide is completely loaded
  149. *
  150. * @param {Event} event - lightGalley custom event
  151. */
  152. Video.prototype.onSlideItemLoad = function (event) {
  153. var _this = this;
  154. var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
  155. // Should check the active slide as well as user may have moved to different slide before the first slide is loaded
  156. if (this.settings.autoplayFirstVideo &&
  157. isFirstSlide &&
  158. index === this.core.index) {
  159. // Delay is just for the transition effect on video load
  160. setTimeout(function () {
  161. _this.loadAndPlayVideo(index);
  162. }, 200);
  163. }
  164. // Should not call on first slide. should check only if the slide is active
  165. if (!isFirstSlide &&
  166. this.settings.autoplayVideoOnSlide &&
  167. index === this.core.index) {
  168. this.loadAndPlayVideo(index);
  169. }
  170. };
  171. /**
  172. * @desc Event triggered when video url or poster found
  173. * Append video HTML is poster is not given
  174. * Play if autoplayFirstVideo is true
  175. *
  176. * @param {Event} event - Javascript Event object.
  177. */
  178. Video.prototype.onHasVideo = function (event) {
  179. var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
  180. if (!hasPoster) {
  181. // All functions are called separately if poster exist in loadVideoOnPosterClick function
  182. this.appendVideos(this.core.getSlideItem(index), {
  183. src: src,
  184. addClass: 'lg-object',
  185. index: index,
  186. html5Video: html5Video,
  187. });
  188. // Automatically navigate to next slide once video reaches the end.
  189. this.gotoNextSlideOnVideoEnd(src, index);
  190. }
  191. };
  192. /**
  193. * @desc fired immediately before each slide transition.
  194. * Pause the previous video
  195. * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
  196. *
  197. * @param {Event} event - Javascript Event object.
  198. * @param {number} prevIndex - Previous index of the slide.
  199. * @param {number} index - Current index of the slide
  200. */
  201. Video.prototype.onBeforeSlide = function (event) {
  202. if (this.core.lGalleryOn) {
  203. var prevIndex = event.detail.prevIndex;
  204. this.pauseVideo(prevIndex);
  205. }
  206. };
  207. /**
  208. * @desc fired immediately after each slide transition.
  209. * Play video if autoplayVideoOnSlide option is enabled.
  210. *
  211. * @param {Event} event - Javascript Event object.
  212. * @param {number} prevIndex - Previous index of the slide.
  213. * @param {number} index - Current index of the slide
  214. * @todo should check on onSlideLoad as well if video is not loaded on after slide
  215. */
  216. Video.prototype.onAfterSlide = function (event) {
  217. var _this = this;
  218. var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
  219. // Do not call on first slide
  220. var $slide = this.core.getSlideItem(index);
  221. if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
  222. if ($slide.hasClass('lg-complete')) {
  223. setTimeout(function () {
  224. _this.loadAndPlayVideo(index);
  225. }, 100);
  226. }
  227. }
  228. };
  229. Video.prototype.loadAndPlayVideo = function (index) {
  230. var $slide = this.core.getSlideItem(index);
  231. var currentGalleryItem = this.core.galleryItems[index];
  232. if (currentGalleryItem.poster) {
  233. this.loadVideoOnPosterClick($slide, true);
  234. }
  235. else {
  236. this.playVideo(index);
  237. }
  238. };
  239. /**
  240. * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
  241. * @param {number} index - Index of the slide
  242. */
  243. Video.prototype.playVideo = function (index) {
  244. this.controlVideo(index, 'play');
  245. };
  246. /**
  247. * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
  248. * @param {number} index - Index of the slide
  249. */
  250. Video.prototype.pauseVideo = function (index) {
  251. this.controlVideo(index, 'pause');
  252. };
  253. Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
  254. var video = '';
  255. var videoInfo = this.core.galleryItems[index]
  256. .__slideVideoInfo || {};
  257. var currentGalleryItem = this.core.galleryItems[index];
  258. var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
  259. videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
  260. var commonIframeProps = "allowtransparency=\"true\"\n frameborder=\"0\"\n scrolling=\"no\"\n allowfullscreen\n mozallowfullscreen\n webkitallowfullscreen\n oallowfullscreen\n msallowfullscreen";
  261. if (videoInfo.youtube) {
  262. var videoId = 'lg-youtube' + index;
  263. var slideUrlParams = videoInfo.youtube[2]
  264. ? videoInfo.youtube[2] + '&'
  265. : '';
  266. // For youtube first parms gets priority if duplicates found
  267. var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
  268. var playerParams = youTubePlayerParams +
  269. (this.settings.youTubePlayerParams
  270. ? '&' + param(this.settings.youTubePlayerParams)
  271. : '');
  272. video = "<iframe allow=\"autoplay\" id=" + videoId + " class=\"lg-video-object lg-youtube " + addClass + "\" " + videoTitle + " src=\"//www.youtube.com/embed/" + (videoInfo.youtube[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
  273. }
  274. else if (videoInfo.vimeo) {
  275. var videoId = 'lg-vimeo' + index;
  276. var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
  277. video = "<iframe allow=\"autoplay\" id=" + videoId + " class=\"lg-video-object lg-vimeo " + addClass + "\" " + videoTitle + " src=\"//player.vimeo.com/video/" + (videoInfo.vimeo[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
  278. }
  279. else if (videoInfo.wistia) {
  280. var wistiaId = 'lg-wistia' + index;
  281. var playerParams = param(this.settings.wistiaPlayerParams);
  282. playerParams = playerParams ? '?' + playerParams : '';
  283. video = "<iframe allow=\"autoplay\" id=\"" + wistiaId + "\" src=\"//fast.wistia.net/embed/iframe/" + (videoInfo.wistia[4] + playerParams) + "\" " + videoTitle + " class=\"wistia_embed lg-video-object lg-wistia " + addClass + "\" name=\"wistia_embed\" " + commonIframeProps + "></iframe>";
  284. }
  285. else if (videoInfo.html5) {
  286. var html5VideoMarkup = '';
  287. for (var i = 0; i < html5Video.source.length; i++) {
  288. html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
  289. }
  290. if (html5Video.tracks) {
  291. var _loop_1 = function (i) {
  292. var trackAttributes = '';
  293. var track = html5Video.tracks[i];
  294. Object.keys(track || {}).forEach(function (key) {
  295. trackAttributes += key + "=\"" + track[key] + "\" ";
  296. });
  297. html5VideoMarkup += "<track " + trackAttributes + ">";
  298. };
  299. for (var i = 0; i < html5Video.tracks.length; i++) {
  300. _loop_1(i);
  301. }
  302. }
  303. var html5VideoAttrs_1 = '';
  304. var videoAttributes_1 = html5Video.attributes || {};
  305. Object.keys(videoAttributes_1 || {}).forEach(function (key) {
  306. html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
  307. });
  308. video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs ? 'video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n " + html5VideoMarkup + "\n Your browser does not support HTML5 video.\n </video>";
  309. }
  310. return video;
  311. };
  312. /**
  313. * @desc - Append videos to the slide
  314. *
  315. * @param {HTMLElement} el - slide element
  316. * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
  317. */
  318. Video.prototype.appendVideos = function (el, videoParams) {
  319. var _a;
  320. var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
  321. el.find('.lg-video-cont').append(videoHtml);
  322. var $videoElement = el.find('.lg-video-object').first();
  323. if (videoParams.html5Video) {
  324. $videoElement.on('mousedown.lg.video', function (e) {
  325. e.stopPropagation();
  326. });
  327. }
  328. if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
  329. try {
  330. return videojs($videoElement.get(), this.settings.videojsOptions);
  331. }
  332. catch (e) {
  333. console.error('lightGallery:- Make sure you have included videojs');
  334. }
  335. }
  336. };
  337. Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
  338. var _this = this;
  339. var $videoElement = this.core
  340. .getSlideItem(index)
  341. .find('.lg-video-object')
  342. .first();
  343. var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
  344. if (this.settings.gotoNextSlideOnVideoEnd) {
  345. if (videoInfo.html5) {
  346. $videoElement.on('ended', function () {
  347. _this.core.goToNextSlide();
  348. });
  349. }
  350. else if (videoInfo.vimeo) {
  351. try {
  352. // https://github.com/vimeo/player.js/#ended
  353. new Vimeo.Player($videoElement.get()).on('ended', function () {
  354. _this.core.goToNextSlide();
  355. });
  356. }
  357. catch (e) {
  358. console.error('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
  359. }
  360. }
  361. else if (videoInfo.wistia) {
  362. try {
  363. window._wq = window._wq || [];
  364. // @todo Event is gettign triggered multiple times
  365. window._wq.push({
  366. id: $videoElement.attr('id'),
  367. onReady: function (video) {
  368. video.bind('end', function () {
  369. _this.core.goToNextSlide();
  370. });
  371. },
  372. });
  373. }
  374. catch (e) {
  375. console.error('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
  376. }
  377. }
  378. }
  379. };
  380. Video.prototype.controlVideo = function (index, action) {
  381. var $videoElement = this.core
  382. .getSlideItem(index)
  383. .find('.lg-video-object')
  384. .first();
  385. var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
  386. if (!$videoElement.get())
  387. return;
  388. if (videoInfo.youtube) {
  389. try {
  390. $videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
  391. }
  392. catch (e) {
  393. console.error("lightGallery:- " + e);
  394. }
  395. }
  396. else if (videoInfo.vimeo) {
  397. try {
  398. new Vimeo.Player($videoElement.get())[action]();
  399. }
  400. catch (e) {
  401. console.error('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
  402. }
  403. }
  404. else if (videoInfo.html5) {
  405. if (this.settings.videojs) {
  406. try {
  407. videojs($videoElement.get())[action]();
  408. }
  409. catch (e) {
  410. console.error('lightGallery:- Make sure you have included videojs');
  411. }
  412. }
  413. else {
  414. $videoElement.get()[action]();
  415. }
  416. }
  417. else if (videoInfo.wistia) {
  418. try {
  419. window._wq = window._wq || [];
  420. // @todo Find a way to destroy wistia player instance
  421. window._wq.push({
  422. id: $videoElement.attr('id'),
  423. onReady: function (video) {
  424. video[action]();
  425. },
  426. });
  427. }
  428. catch (e) {
  429. console.error('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
  430. }
  431. }
  432. };
  433. Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
  434. var _this = this;
  435. // check slide has poster
  436. if (!$el.hasClass('lg-video-loaded')) {
  437. // check already video element present
  438. if (!$el.hasClass('lg-has-video')) {
  439. $el.addClass('lg-has-video');
  440. var _html = void 0;
  441. var _src = this.core.galleryItems[this.core.index].src;
  442. var video = this.core.galleryItems[this.core.index].video;
  443. if (video) {
  444. _html =
  445. typeof video === 'string' ? JSON.parse(video) : video;
  446. }
  447. var videoJsPlayer_1 = this.appendVideos($el, {
  448. src: _src,
  449. addClass: '',
  450. index: this.core.index,
  451. html5Video: _html,
  452. });
  453. this.gotoNextSlideOnVideoEnd(_src, this.core.index);
  454. var $tempImg = $el.find('.lg-object').first().get();
  455. // @todo make sure it is working
  456. $el.find('.lg-video-cont').first().append($tempImg);
  457. $el.addClass('lg-video-loading');
  458. videoJsPlayer_1 &&
  459. videoJsPlayer_1.ready(function () {
  460. videoJsPlayer_1.on('loadedmetadata', function () {
  461. _this.onVideoLoadAfterPosterClick($el, _this.core.index);
  462. });
  463. });
  464. $el.find('.lg-video-object')
  465. .first()
  466. .on('load.lg error.lg loadedmetadata.lg', function () {
  467. setTimeout(function () {
  468. _this.onVideoLoadAfterPosterClick($el, _this.core.index);
  469. }, 50);
  470. });
  471. }
  472. else {
  473. this.playVideo(this.core.index);
  474. }
  475. }
  476. else if (forcePlay) {
  477. this.playVideo(this.core.index);
  478. }
  479. };
  480. Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
  481. $el.addClass('lg-video-loaded');
  482. this.playVideo(index);
  483. };
  484. Video.prototype.destroy = function () {
  485. this.core.LGel.off('.lg.video');
  486. this.core.LGel.off('.video');
  487. };
  488. return Video;
  489. }());
  490. return Video;
  491. })));
  492. //# sourceMappingURL=lg-video.umd.js.map