UNPKG

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