UNPKG

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