1317 lines
49 KiB
JavaScript
1317 lines
49 KiB
JavaScript
/*! elementor-pro - v3.21.0 - 30-04-2024 */
|
|
"use strict";
|
|
(self["webpackChunkelementor_pro"] = self["webpackChunkelementor_pro"] || []).push([["video-playlist"],{
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/base-tabs.js":
|
|
/*!*****************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/base-tabs.js ***!
|
|
\*****************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports["default"] = void 0;
|
|
// Copied from the core, original path: elementor/assets/dev/js/frontend/handlers/base-tabs.js.
|
|
class baseTabs extends elementorModules.frontend.handlers.Base {
|
|
getDefaultSettings() {
|
|
return {
|
|
selectors: {
|
|
tablist: '[role="tablist"]',
|
|
tabTitle: '.e-tab-title',
|
|
tabContent: '.e-tab-content'
|
|
},
|
|
classes: {
|
|
active: 'e-active'
|
|
},
|
|
showTabFn: 'show',
|
|
hideTabFn: 'hide',
|
|
toggleSelf: true,
|
|
hidePrevious: true,
|
|
autoExpand: true,
|
|
keyDirection: {
|
|
ArrowLeft: elementorFrontendConfig.is_rtl ? 1 : -1,
|
|
ArrowUp: -1,
|
|
ArrowRight: elementorFrontendConfig.is_rtl ? -1 : 1,
|
|
ArrowDown: 1
|
|
}
|
|
};
|
|
}
|
|
getDefaultElements() {
|
|
const selectors = this.getSettings('selectors');
|
|
return {
|
|
$tabTitles: this.findElement(selectors.tabTitle),
|
|
$tabContents: this.findElement(selectors.tabContent)
|
|
};
|
|
}
|
|
activateDefaultTab(videoId) {
|
|
const settings = this.getSettings();
|
|
if (!settings.autoExpand || 'editor' === settings.autoExpand && !this.isEdit) {
|
|
return;
|
|
}
|
|
const defaultActiveTab = this.getEditSettings('activeItemIndex') || videoId || 1,
|
|
originalToggleMethods = {
|
|
showTabFn: settings.showTabFn,
|
|
hideTabFn: settings.hideTabFn
|
|
};
|
|
|
|
// Toggle tabs without animation to avoid jumping.
|
|
this.setSettings({
|
|
showTabFn: 'show',
|
|
hideTabFn: 'hide'
|
|
});
|
|
this.changeActiveTab(defaultActiveTab);
|
|
|
|
// Return back original toggle effects.
|
|
this.setSettings(originalToggleMethods);
|
|
}
|
|
handleKeyboardNavigation(event) {
|
|
const tab = event.currentTarget,
|
|
$tabList = jQuery(tab.closest(this.getSettings('selectors').tablist)),
|
|
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
|
|
$tabs = $tabList.find(this.getSettings('selectors').tabTitle),
|
|
isVertical = 'vertical' === $tabList.attr('aria-orientation');
|
|
switch (event.key) {
|
|
case 'ArrowLeft':
|
|
case 'ArrowRight':
|
|
if (isVertical) {
|
|
return;
|
|
}
|
|
break;
|
|
case 'ArrowUp':
|
|
case 'ArrowDown':
|
|
if (!isVertical) {
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
break;
|
|
case 'Home':
|
|
event.preventDefault();
|
|
$tabs.first().trigger('focus');
|
|
return;
|
|
case 'End':
|
|
event.preventDefault();
|
|
$tabs.last().trigger('focus');
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
const tabIndex = tab.getAttribute('data-tab') - 1,
|
|
direction = this.getSettings('keyDirection')[event.key],
|
|
nextTab = $tabs[tabIndex + direction];
|
|
if (nextTab) {
|
|
nextTab.focus();
|
|
} else if (-1 === tabIndex + direction) {
|
|
$tabs.last().trigger('focus');
|
|
} else {
|
|
$tabs.first().trigger('focus');
|
|
}
|
|
}
|
|
deactivateActiveTab(tabIndex) {
|
|
const settings = this.getSettings(),
|
|
activeClass = settings.classes.active,
|
|
activeFilter = tabIndex ? '[data-tab="' + tabIndex + '"]' : '.' + activeClass,
|
|
$activeTitle = this.elements.$tabTitles.filter(activeFilter),
|
|
$activeContent = this.elements.$tabContents.filter(activeFilter);
|
|
$activeTitle.add($activeContent).removeClass(activeClass);
|
|
$activeTitle.attr({
|
|
tabindex: '-1',
|
|
'aria-selected': 'false'
|
|
});
|
|
$activeContent[settings.hideTabFn]();
|
|
$activeContent.attr('hidden', 'hidden');
|
|
}
|
|
activateTab(tabIndex) {
|
|
const settings = this.getSettings(),
|
|
activeClass = settings.classes.active,
|
|
$requestedTitle = this.elements.$tabTitles.filter('[data-tab="' + tabIndex + '"]'),
|
|
$requestedContent = this.elements.$tabContents.filter('[data-tab="' + tabIndex + '"]'),
|
|
animationDuration = 'show' === settings.showTabFn ? 0 : 400;
|
|
$requestedTitle.add($requestedContent).addClass(activeClass);
|
|
$requestedTitle.attr({
|
|
tabindex: '0',
|
|
'aria-selected': 'true'
|
|
});
|
|
$requestedContent[settings.showTabFn](animationDuration, () => elementorFrontend.elements.$window.trigger('resize'));
|
|
$requestedContent.removeAttr('hidden');
|
|
}
|
|
isActiveTab(tabIndex) {
|
|
return this.elements.$tabTitles.filter('[data-tab="' + tabIndex + '"]').hasClass(this.getSettings('classes.active'));
|
|
}
|
|
bindEvents() {
|
|
this.elements.$tabTitles.on({
|
|
keydown: event => {
|
|
// Support for old markup that includes an `<a>` tag in the tab.
|
|
if (jQuery(event.target).is('a') && `Enter` === event.key) {
|
|
event.preventDefault();
|
|
}
|
|
|
|
// We listen to keydowon event for these keys in order to prevent undesired page scrolling.
|
|
if (['End', 'Home', 'ArrowUp', 'ArrowDown'].includes(event.key)) {
|
|
this.handleKeyboardNavigation(event);
|
|
}
|
|
},
|
|
keyup: event => {
|
|
switch (event.key) {
|
|
case 'ArrowLeft':
|
|
case 'ArrowRight':
|
|
this.handleKeyboardNavigation(event);
|
|
break;
|
|
case 'Enter':
|
|
case 'Space':
|
|
event.preventDefault();
|
|
this.changeActiveTab(event.currentTarget.getAttribute('data-tab'));
|
|
break;
|
|
}
|
|
},
|
|
click: event => {
|
|
event.preventDefault();
|
|
this.changeActiveTab(event.currentTarget.getAttribute('data-tab'));
|
|
}
|
|
});
|
|
}
|
|
onInit() {
|
|
super.onInit(...arguments);
|
|
|
|
// This.activateDefaultTab();
|
|
}
|
|
|
|
changeActiveTab(tabIndex) {
|
|
const isActiveTab = this.isActiveTab(tabIndex),
|
|
settings = this.getSettings();
|
|
if ((settings.toggleSelf || !isActiveTab) && settings.hidePrevious) {
|
|
this.deactivateActiveTab();
|
|
}
|
|
if (!settings.hidePrevious && isActiveTab) {
|
|
this.deactivateActiveTab(tabIndex);
|
|
}
|
|
if (!isActiveTab) {
|
|
this.activateTab(tabIndex);
|
|
}
|
|
}
|
|
}
|
|
exports["default"] = baseTabs;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/event-trigger.js":
|
|
/*!*********************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/event-trigger.js ***!
|
|
\*********************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js");
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports["default"] = triggerEvent;
|
|
var _playlistEvent = _interopRequireDefault(__webpack_require__(/*! ./playlist-event */ "../modules/video-playlist/assets/js/frontend/playlist-event.js"));
|
|
// Functions to get objects for the playlist event object.
|
|
function getEventTabsObject(widgetObject) {
|
|
const currentInnerTabsTitleElements = widgetObject.elements.$innerTabs.filter('.e-active').find('.e-inner-tabs-wrapper .e-inner-tab-title');
|
|
if (currentInnerTabsTitleElements.length) {
|
|
const activeInnerTabTitleElement = currentInnerTabsTitleElements.filter('.e-inner-tab-active');
|
|
return {
|
|
name: activeInnerTabTitleElement.text().trim(),
|
|
index: activeInnerTabTitleElement.index() + 1
|
|
};
|
|
}
|
|
return {
|
|
name: 'none',
|
|
index: 'none'
|
|
};
|
|
}
|
|
function getEventPlaylistObject(widgetObject, positionInVideoList) {
|
|
const currentVideoIndex = positionInVideoList || widgetObject.currentPlaylistItemIndex;
|
|
return {
|
|
name: widgetObject.getElementSettings('playlist_title'),
|
|
currentItem: currentVideoIndex,
|
|
amount: widgetObject.playlistItemsArray.filter(video => video.videoType !== 'section').length
|
|
};
|
|
}
|
|
function getEventVideoObject(widgetObject, positionInVideoList) {
|
|
const currentVideoIndex = positionInVideoList || widgetObject.currentPlaylistItemIndex,
|
|
currentVideo = widgetObject.playlistItemsArray[currentVideoIndex - 1];
|
|
return {
|
|
provider: currentVideo.videoType,
|
|
url: currentVideo.videoUrl,
|
|
title: currentVideo.videoTitle,
|
|
duration: currentVideo.videoDuration
|
|
};
|
|
}
|
|
async function getEventEventObject(widgetObject, eventType, eventTrigger, positionInVideoList) {
|
|
const currentVideoIndex = positionInVideoList || widgetObject.currentPlaylistItemIndex,
|
|
currentVideo = widgetObject.playlistItemsArray[currentVideoIndex - 1];
|
|
return {
|
|
type: eventType,
|
|
time: await currentVideo.playerInstance.getCurrentTime(),
|
|
element: widgetObject.$element,
|
|
trigger: eventTrigger,
|
|
watchCount: currentVideo.playerInstance.watchCount
|
|
};
|
|
}
|
|
async function triggerEvent(widgetObject, eventType, eventTrigger, positionInVideoList) {
|
|
const currentEvent = new _playlistEvent.default({
|
|
event: await getEventEventObject(widgetObject, eventType, eventTrigger, positionInVideoList),
|
|
tab: getEventTabsObject(widgetObject),
|
|
playlist: getEventPlaylistObject(widgetObject, positionInVideoList),
|
|
video: getEventVideoObject(widgetObject, positionInVideoList)
|
|
});
|
|
jQuery('body').trigger('elementor-video-playList', currentEvent);
|
|
}
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/handler.js":
|
|
/*!***************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/handler.js ***!
|
|
\***************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js");
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports["default"] = void 0;
|
|
var _baseTabs = _interopRequireDefault(__webpack_require__(/*! ./base-tabs */ "../modules/video-playlist/assets/js/frontend/base-tabs.js"));
|
|
var _playerYoutube = _interopRequireDefault(__webpack_require__(/*! ./player-youtube */ "../modules/video-playlist/assets/js/frontend/player-youtube.js"));
|
|
var _playerVimeo = _interopRequireDefault(__webpack_require__(/*! ./player-vimeo */ "../modules/video-playlist/assets/js/frontend/player-vimeo.js"));
|
|
var _playerHosted = _interopRequireDefault(__webpack_require__(/*! ./player-hosted */ "../modules/video-playlist/assets/js/frontend/player-hosted.js"));
|
|
var _scrollUtils = __webpack_require__(/*! ./scroll-utils */ "../modules/video-playlist/assets/js/frontend/scroll-utils.js");
|
|
var _innerTabs = __webpack_require__(/*! ./inner-tabs */ "../modules/video-playlist/assets/js/frontend/inner-tabs.js");
|
|
var _urlParams = __webpack_require__(/*! ./url-params */ "../modules/video-playlist/assets/js/frontend/url-params.js");
|
|
var _eventTrigger = _interopRequireDefault(__webpack_require__(/*! ./event-trigger */ "../modules/video-playlist/assets/js/frontend/event-trigger.js"));
|
|
class VideoPlaylistHandler extends _baseTabs.default {
|
|
getDefaultSettings() {
|
|
const defaultSettings = super.getDefaultSettings(),
|
|
selectors = {
|
|
tabsWrapper: '.e-tabs-items-wrapper',
|
|
tabsItems: '.e-tabs-items',
|
|
toggleVideosDisplayButton: '.e-tabs-toggle-videos-display-button',
|
|
videos: '.e-tabs-content-wrapper .e-tab-content',
|
|
innerTabs: '.e-tabs-inner-tabs .e-tab-content',
|
|
imageOverlay: '.elementor-custom-embed-image-overlay'
|
|
};
|
|
return {
|
|
...defaultSettings,
|
|
selectors: {
|
|
...defaultSettings.selectors,
|
|
...selectors
|
|
}
|
|
};
|
|
}
|
|
getDefaultElements() {
|
|
const elements = super.getDefaultElements(),
|
|
selectors = this.getSettings('selectors');
|
|
return {
|
|
...elements,
|
|
$tabsWrapper: this.findElement(selectors.tabsWrapper),
|
|
$tabsItems: this.findElement(selectors.tabsItems),
|
|
$toggleVideosDisplayButton: this.findElement(selectors.toggleVideosDisplayButton),
|
|
$videos: this.findElement(selectors.videos),
|
|
$innerTabs: this.findElement(selectors.innerTabs),
|
|
$imageOverlay: this.findElement(selectors.imageOverlay)
|
|
};
|
|
}
|
|
initEditorListeners() {
|
|
super.initEditorListeners();
|
|
this.editorListeners.push({
|
|
event: 'elementorPlaylistWidget:fetchVideoData',
|
|
to: elementor.channels.editor,
|
|
callback: e => {
|
|
this.getCurrentPlayerSelected().setVideoProviderData().then(() => {
|
|
e.currentItem = this.getCurrentItemSelected();
|
|
elementor.channels.editor.trigger('elementorPlaylistWidget:setVideoData', e);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
bindEvents() {
|
|
super.bindEvents();
|
|
|
|
// Handle the click on the image overlay.
|
|
this.elements.$imageOverlay.on({
|
|
click: e => {
|
|
// Remove image overlay if the user clicked it and play the video in case it is not playing.
|
|
e.currentTarget.remove();
|
|
this.getCurrentPlayerSelected().play();
|
|
}
|
|
});
|
|
|
|
// Handle the inner tab functionality.
|
|
this.elements.$innerTabs.on({
|
|
click: event => {
|
|
(0, _innerTabs.handleInnerTabs)(event, this);
|
|
}
|
|
});
|
|
|
|
// Handle scroll on the right panel to make the "shadows" effect when the panel is scrollable.
|
|
this.elements.$tabsItems.on({
|
|
scroll: event => {
|
|
(0, _scrollUtils.handleVideosPanelScroll)(this.elements, event);
|
|
}
|
|
});
|
|
|
|
// Handle the closing/opening right panel in mobile mode.
|
|
this.elements.$toggleVideosDisplayButton.on({
|
|
click: event => {
|
|
jQuery(event.target).toggleClass('rotate-up');
|
|
jQuery(event.target).toggleClass('rotate-down');
|
|
this.elements.$tabsWrapper.slideToggle('slow');
|
|
}
|
|
});
|
|
}
|
|
onInit() {
|
|
super.onInit(...arguments);
|
|
this.playlistId = this.getID();
|
|
|
|
// Handle watched videos.
|
|
this.storageKey = 'watched_videos_' + this.getID();
|
|
const storageObject = elementorFrontend.storage.get(this.storageKey);
|
|
if (storageObject) {
|
|
this.watchedVideosArray = JSON.parse(storageObject);
|
|
} else {
|
|
this.watchedVideosArray = [];
|
|
}
|
|
this.watchedIndication = this.getElementSettings('show_watched_indication');
|
|
|
|
// Handle indication for scrolling in the right panel.
|
|
(0, _scrollUtils.handleVideosPanelScroll)(this.elements);
|
|
|
|
// Handle the video player functionality, includes "on load" and "next up".
|
|
this.isAutoplayOnLoad = 'yes' === this.getElementSettings('autoplay_on_load');
|
|
this.isAutoplayNextUp = 'yes' === this.getElementSettings('autoplay_next');
|
|
this.isFirstVideoActivated = true;
|
|
this.createPlaylistItems();
|
|
|
|
// Handle display for show more/less button.
|
|
this.isCollapsible = this.getElementSettings('inner_tab_is_content_collapsible');
|
|
this.innerTabsHeightLimit = this.getElementSettings('inner_tab_collapsible_height');
|
|
|
|
// Keep track of the element that supposed to be paused since the user selected other video.
|
|
this.currentPlayingPlaylistItemIndex = 1;
|
|
|
|
// Handle the first initial activation of the video in the playlist.
|
|
this.activateInitialVideo();
|
|
|
|
// Handle Inner Tab activation in edit mode.
|
|
this.activateInnerTabInEditMode();
|
|
}
|
|
onEditSettingsChange(propertyName) {
|
|
// The condition will be true when the user clicks the widget to open the edit panel.
|
|
if ('panel' === propertyName) {
|
|
// The boolean below will prevent running twice the activateDefaultTab function when widget first load and user click the item to play it.
|
|
this.preventTabActivation = true;
|
|
}
|
|
if ('activeItemIndex' !== propertyName) {
|
|
return;
|
|
}
|
|
if (this.preventTabActivation) {
|
|
this.preventTabActivation = false;
|
|
return;
|
|
}
|
|
this.activateDefaultTab();
|
|
}
|
|
activateInitialVideo() {
|
|
this.isPageOnLoad = true;
|
|
const isLazyLoad = !!this.getElementSettings('lazy_load'),
|
|
initialTabIndex = (0, _urlParams.handleURLParams)(this.playlistId, this.playlistItemsArray);
|
|
let isUrlParamsExist = false;
|
|
if (initialTabIndex) {
|
|
this.currentPlaylistItemIndex = initialTabIndex;
|
|
this.currentPlayingPlaylistItemIndex = initialTabIndex;
|
|
isUrlParamsExist = true;
|
|
} else {
|
|
this.currentPlaylistItemIndex = 1;
|
|
this.currentPlayingPlaylistItemIndex = 1;
|
|
}
|
|
|
|
// When there are no url parameters and on-load is on, the video should be played, means the url parameters should be set.
|
|
if (this.isAutoplayOnLoad && !isUrlParamsExist) {
|
|
(0, _urlParams.setVideoParams)(this.playlistId, this.playlistItemsArray, this.currentPlaylistItemIndex);
|
|
}
|
|
if (isUrlParamsExist) {
|
|
this.$element[0]?.scrollIntoView({
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
this.handleFirstVideoActivation(isLazyLoad);
|
|
}
|
|
|
|
/*
|
|
The scenarios for playing the first video after page load:
|
|
- lazy load off - video will load on page load before user scroll video to view.
|
|
- lazy load on - video will load when user scroll the video to view.
|
|
*/
|
|
handleFirstVideoActivation(isLazyLoad) {
|
|
if (!isLazyLoad) {
|
|
this.activateDefaultTab(this.currentPlaylistItemIndex);
|
|
|
|
// No need to use the observer since "lazy load is" off.
|
|
return;
|
|
}
|
|
const playlistElement = document.querySelector('.elementor-element-' + this.playlistId + ' .e-tabs-main-area'),
|
|
observer = elementorModules.utils.Scroll.scrollObserver({
|
|
callback: event => {
|
|
if (event.isInViewport) {
|
|
this.activateDefaultTab(this.currentPlaylistItemIndex);
|
|
observer.unobserve(playlistElement);
|
|
}
|
|
}
|
|
});
|
|
observer.observe(playlistElement);
|
|
}
|
|
getCurrentItemSelected() {
|
|
return this.playlistItemsArray[this.currentPlaylistItemIndex - 1];
|
|
}
|
|
getCurrentPlayerSelected() {
|
|
return this.getCurrentItemSelected().playerInstance;
|
|
}
|
|
getCurrentPlayerPlaying() {
|
|
return this.playlistItemsArray[this.currentPlayingPlaylistItemIndex - 1].playerInstance;
|
|
}
|
|
|
|
// Handle video selection.
|
|
isVideoShouldBePlayed() {
|
|
// When user select other video, the current video will be paused if is playing.
|
|
if (this.currentPlayingPlaylistItemIndex !== this.currentPlaylistItemIndex) {
|
|
if (this.getCurrentPlayerPlaying()) {
|
|
this.getCurrentPlayerPlaying().pause();
|
|
}
|
|
this.currentPlayingPlaylistItemIndex = this.currentPlaylistItemIndex;
|
|
|
|
// When user select the same video, the current video will be paused if is playing.
|
|
} else if (this.getCurrentPlayerPlaying().isVideoPlaying) {
|
|
this.getCurrentPlayerPlaying().pause();
|
|
return false;
|
|
}
|
|
|
|
// When none of the videos are playing, the selected video should be played.
|
|
return true;
|
|
}
|
|
activateInnerTabInEditMode() {
|
|
if (this.isEdit && this.getEditSettings('innerActiveIndex')) {
|
|
const innerTabActivated = this.getEditSettings('innerActiveIndex'),
|
|
innerTabs = jQuery(this.elements.$innerTabs.eq(this.currentPlaylistItemIndex - 1).find('.e-inner-tab-title a'));
|
|
innerTabs[innerTabActivated].click();
|
|
}
|
|
}
|
|
|
|
// Handle video creation including event listeners and playing video if needed.
|
|
handleVideo(playListItem) {
|
|
// If the video already created (visited once), then just play it if it's not playing already, otherwise pause it.
|
|
if (playListItem.playerInstance) {
|
|
if (this.isVideoShouldBePlayed()) {
|
|
// Remove image overlay if first video item is playing without clicking the image overlay.
|
|
if (1 === this.currentPlaylistItemIndex && this.elements.$imageOverlay) {
|
|
this.elements.$imageOverlay.remove();
|
|
}
|
|
this.playVideoAfterCreation(playListItem);
|
|
}
|
|
} else {
|
|
// If the video is not created yet (first visit), then create the video instance and the event listeners.
|
|
const players = {
|
|
youtube: _playerYoutube.default,
|
|
vimeo: _playerVimeo.default,
|
|
hosted: _playerHosted.default
|
|
};
|
|
|
|
// Initiating player object.
|
|
// The second parameter holds the video item when event trigger occur with setTimeout.
|
|
playListItem.playerInstance = new players[playListItem.videoType](playListItem, this.currentPlaylistItemIndex);
|
|
playListItem.playerInstance.create().then(() => {
|
|
if (this.isVideoShouldBePlayed()) {
|
|
this.playVideoOnCreation(playListItem);
|
|
}
|
|
|
|
// Handle the functionality when video full screen mode changes.
|
|
playListItem.playerInstance.handleFullScreenChange(isEnterFullScreenMode => {
|
|
// Trigger event when enter/exit full screen mode.
|
|
(0, _eventTrigger.default)(this, isEnterFullScreenMode ? 'videoFullScreen' : 'videoExitFullScreen', 'click');
|
|
});
|
|
|
|
// Handle the functionality when video play.
|
|
playListItem.playerInstance.handlePlayed(() => {
|
|
const currentPlaylistItem = this.getCurrentItemSelected();
|
|
let videoTrigger = 'click';
|
|
if (currentPlaylistItem.isAutoplayOnLoad) {
|
|
videoTrigger = 'onLoad';
|
|
playListItem.isAutoplayOnLoad = false;
|
|
} else if (currentPlaylistItem.isAutoPlayNextUp) {
|
|
videoTrigger = 'nextVideo';
|
|
}
|
|
|
|
// Trigger event when video started.
|
|
(0, _eventTrigger.default)(this, currentPlaylistItem.playerInstance.isVideoPausedLocal ? 'videoResume' : 'videoStart', videoTrigger);
|
|
});
|
|
|
|
// Handle the functionality when video ended.
|
|
playListItem.playerInstance.handleEnded(() => {
|
|
// Trigger event when video ended.
|
|
(0, _eventTrigger.default)(this, 'videoEnded', 'click');
|
|
|
|
// Handle the indication for videos that have been watched and ended.
|
|
if (this.watchedIndication) {
|
|
this.elements.$tabTitles.filter('.e-active').addClass('watched-video');
|
|
}
|
|
const endedVideoId = this.getCurrentItemSelected().dataItemId;
|
|
if (!this.watchedVideosArray.includes(endedVideoId) && this.watchedIndication) {
|
|
this.watchedVideosArray.push(this.getCurrentItemSelected().dataItemId);
|
|
elementorFrontend.storage.set(this.storageKey, JSON.stringify(this.watchedVideosArray));
|
|
}
|
|
|
|
// Handle "next up" functionality.
|
|
if (this.isAutoplayNextUp) {
|
|
// If there are more videos in the list, play next video.
|
|
if (this.playlistItemsArray.length >= ++this.currentPlaylistItemIndex) {
|
|
// Handle the logic for playing next video.
|
|
while ('section' === this.getCurrentItemSelected().videoType) {
|
|
this.currentPlaylistItemIndex++;
|
|
|
|
// When last video in the playlist ended, we reset the this.currentPlaylistItemIndex to the last playlist item index.
|
|
if (this.playlistItemsArray.length < this.currentPlaylistItemIndex) {
|
|
this.currentPlaylistItemIndex = this.playlistItemsArray.length;
|
|
return;
|
|
}
|
|
}
|
|
this.changeActiveTab(this.currentPlaylistItemIndex, true);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Handle the functionality when video paused.
|
|
// The handlePaused will trigger event with setTimeout, positionInVideoList will keep track for the paused video when selecting other video.
|
|
playListItem.playerInstance.handlePaused(positionInVideoList => {
|
|
// Trigger event when video paused.
|
|
(0, _eventTrigger.default)(this, 'videoPaused', 'click', positionInVideoList);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
// Handle the actual playing of the video that already exists (already created before).
|
|
playVideoAfterCreation(playListItem) {
|
|
playListItem.playerInstance.play();
|
|
}
|
|
|
|
// Handle the actual playing of the video when the video is created.
|
|
playVideoOnCreation(playListItem) {
|
|
// Play the video according to "on load" and "next up" indications.
|
|
if (this.isAutoplayOnLoad) {
|
|
playListItem.isAutoplayOnLoad = true;
|
|
|
|
// Mute the initiated video when "autoplay onload" and then play.
|
|
playListItem.playerInstance.mute();
|
|
playListItem.playerInstance.play();
|
|
this.isAutoplayOnLoad = false;
|
|
} else if (!this.isFirstVideoActivated) {
|
|
playListItem.isAutoPlayNextUp = true;
|
|
playListItem.playerInstance.play();
|
|
}
|
|
this.isFirstVideoActivated = false;
|
|
}
|
|
createPlaylistItems() {
|
|
this.playlistItemsArray = [];
|
|
this.elements.$videos.each((index, tabContent) => {
|
|
const playListItem = {};
|
|
const $tabContent = jQuery(tabContent);
|
|
playListItem.videoUrl = $tabContent.attr('data-video-url');
|
|
playListItem.videoType = $tabContent.attr('data-video-type');
|
|
playListItem.videoTitle = $tabContent.attr('data-video-title');
|
|
playListItem.videoDuration = $tabContent.attr('data-video-duration');
|
|
playListItem.tabContent = tabContent;
|
|
playListItem.dataTab = index + 1;
|
|
playListItem.dataItemId = this.getElementSettings().tabs[index]._id;
|
|
this.playlistItemsArray.push(playListItem);
|
|
});
|
|
|
|
// When the page loads,the code checks which videos already watched and adding a class accordingly.
|
|
if (this.watchedVideosArray.length > 0 && this.watchedIndication) {
|
|
this.watchedVideosArray.forEach(watchedVideoId => {
|
|
const watchedPlaylistItem = this.playlistItemsArray.find(playlistItem => playlistItem.dataItemId === watchedVideoId);
|
|
this.elements.$tabTitles.filter('[data-tab="' + watchedPlaylistItem.dataTab + '"]').addClass('watched-video');
|
|
});
|
|
}
|
|
}
|
|
changeActiveTab(tabIndex, isVideoSelectedAutomatically) {
|
|
super.changeActiveTab(tabIndex);
|
|
if (this.playlistItemsArray[tabIndex - 1] && this.playlistItemsArray[tabIndex - 1].videoType !== 'section') {
|
|
this.currentPlaylistItemIndex = parseInt(tabIndex);
|
|
if (isVideoSelectedAutomatically) {
|
|
this.currentPlayingPlaylistItemIndex = this.currentPlaylistItemIndex;
|
|
}
|
|
|
|
// Handle on creation of the video and working with it.
|
|
this.handleVideo(this.getCurrentItemSelected(), isVideoSelectedAutomatically);
|
|
|
|
// Set Video params in url only if its not the first video when page load.
|
|
if (!this.isPageOnLoad) {
|
|
(0, _urlParams.setVideoParams)(this.playlistId, this.playlistItemsArray, this.currentPlaylistItemIndex);
|
|
}
|
|
this.isPageOnLoad = false;
|
|
|
|
// Handle the display for the inner tabs buttons as long there are actually inner tabs.
|
|
if (jQuery(this.elements.$innerTabs.eq(tabIndex - 1)).find('.e-inner-tab-content').length > 0) {
|
|
const innerTabsContent = this.elements.$innerTabs.filter('.e-active').find('.e-inner-tab-content');
|
|
(0, _innerTabs.handleInnerTabsButtonsDisplay)(innerTabsContent.toArray(), this.isCollapsible, this.innerTabsHeightLimit);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
exports["default"] = VideoPlaylistHandler;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/inner-tabs.js":
|
|
/*!******************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/inner-tabs.js ***!
|
|
\******************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js");
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports.handleInnerTabs = handleInnerTabs;
|
|
exports.handleInnerTabsButtonsDisplay = handleInnerTabsButtonsDisplay;
|
|
exports.onTabContentButtonsClick = onTabContentButtonsClick;
|
|
var _eventTrigger = _interopRequireDefault(__webpack_require__(/*! ./event-trigger */ "../modules/video-playlist/assets/js/frontend/event-trigger.js"));
|
|
function toggleInnerTabs(event, clickedTab, widgetObject) {
|
|
const activeTabWrapper = event.currentTarget,
|
|
tabTitles = activeTabWrapper.querySelectorAll('.e-inner-tab-title');
|
|
if (clickedTab.hasClass('e-inner-tab-active') || tabTitles.length < 2) {
|
|
return;
|
|
}
|
|
const tabsContents = activeTabWrapper.querySelectorAll('.e-inner-tab-content');
|
|
tabTitles.forEach(tabTitle => {
|
|
tabTitle.classList.toggle('e-inner-tab-active');
|
|
});
|
|
tabsContents.forEach(tabContent => {
|
|
tabContent.toggleAttribute('hidden');
|
|
tabContent.classList.toggle('e-inner-tab-active');
|
|
});
|
|
handleInnerTabsButtonsDisplay(Array.from(tabsContents), widgetObject.isCollapsible, widgetObject.innerTabsHeightLimit);
|
|
|
|
// Trigger event when tab open.
|
|
(0, _eventTrigger.default)(widgetObject, 'tabOpened', 'click');
|
|
}
|
|
function handleInnerTabs(event, widgetObject) {
|
|
const clickedTarget = event.target;
|
|
const clickedTagType = clickedTarget.tagName;
|
|
|
|
// Handle click on tab on desktop mode.
|
|
if (clickedTarget.classList.contains('e-inner-tab-title-text')) {
|
|
event.preventDefault();
|
|
const $clickedTab = jQuery(clickedTarget).parent('.e-inner-tab-title');
|
|
toggleInnerTabs(event, $clickedTab, widgetObject);
|
|
}
|
|
|
|
// Handle click on tab on mobile mode.
|
|
if (clickedTarget.classList.contains('e-tab-mobile-title')) {
|
|
const $clickedTab = jQuery(clickedTarget);
|
|
toggleInnerTabs(event, $clickedTab, widgetObject);
|
|
}
|
|
|
|
// Handle click on show-less buttons in tab content.
|
|
if ('button' === clickedTagType.toLowerCase()) {
|
|
onTabContentButtonsClick(event, widgetObject);
|
|
}
|
|
}
|
|
function handleInnerTabsButtonsDisplay(tabsContents, isCollapsible, innerTabsHeightLimit) {
|
|
if (!isCollapsible) {
|
|
return;
|
|
}
|
|
const activeInnerTab = tabsContents.filter(tabsContent => tabsContent.classList.contains('e-inner-tab-active')),
|
|
innerTabScrollableHeight = activeInnerTab[0].querySelector('.e-inner-tab-text > div').offsetHeight,
|
|
innerTabsLimitHeight = parseInt(innerTabsHeightLimit.size);
|
|
if (innerTabsLimitHeight && innerTabScrollableHeight > innerTabsLimitHeight) {
|
|
activeInnerTab[0].classList.add('show-inner-tab-buttons');
|
|
}
|
|
}
|
|
function onTabContentButtonsClick(event, widgetObject) {
|
|
const $tabsContent = jQuery(event.currentTarget).find('.e-inner-tab-content'),
|
|
$activeTabContent = $tabsContent.filter('.e-inner-tab-active'),
|
|
buttonsElements = $activeTabContent.find('button');
|
|
buttonsElements.toggleClass('show-button');
|
|
$activeTabContent.toggleClass('show-full-height');
|
|
const eventType = $activeTabContent.hasClass('show-full-height') ? 'tabExpanded' : 'tabCollapsed';
|
|
|
|
// Trigger event when collapsed/expanded clicked.
|
|
(0, _eventTrigger.default)(widgetObject, eventType, 'click');
|
|
}
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/player-base.js":
|
|
/*!*******************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/player-base.js ***!
|
|
\*******************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports["default"] = void 0;
|
|
class PlayerBase {
|
|
constructor(playlistItem, videoIndex) {
|
|
this.playlistItem = playlistItem;
|
|
this.positionInVideoList = videoIndex;
|
|
}
|
|
formatDuration(duration) {
|
|
const dateObj = new Date(duration * 1000),
|
|
hours = dateObj.getUTCHours(),
|
|
minutes = dateObj.getUTCMinutes(),
|
|
seconds = dateObj.getSeconds();
|
|
if (hours !== 0) {
|
|
return `${hours.toString()}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|
}
|
|
return `${minutes.toString()}:${seconds.toString().padStart(2, '0')}`;
|
|
}
|
|
}
|
|
exports["default"] = PlayerBase;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/player-hosted.js":
|
|
/*!*********************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/player-hosted.js ***!
|
|
\*********************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js");
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports["default"] = void 0;
|
|
var _playerBase = _interopRequireDefault(__webpack_require__(/*! ./player-base */ "../modules/video-playlist/assets/js/frontend/player-base.js"));
|
|
class playerHosted extends _playerBase.default {
|
|
constructor(playlistItem, videoIndex) {
|
|
super(playlistItem, videoIndex);
|
|
this.playerObject = null;
|
|
this.watchCount = 0;
|
|
this.isVideoPlaying = false;
|
|
this.isVideoPausedLocal = false;
|
|
this.isVideoSeeking = false;
|
|
this.isVideoEnded = false;
|
|
this.isReady = false;
|
|
}
|
|
create() {
|
|
const videoPromise = new Promise(resolve => {
|
|
const video = document.createElement('video');
|
|
video.setAttribute('controls', '');
|
|
const text = document.createTextNode('Sorry, your browser doesn\'t support embedded videos.');
|
|
const source = document.createElement('source');
|
|
source.setAttribute('src', this.playlistItem.videoUrl);
|
|
source.setAttribute('type', 'video/' + this.playlistItem.videoUrl.split('.').pop());
|
|
video.appendChild(source);
|
|
video.appendChild(text);
|
|
this.playerObject = video;
|
|
this.playlistItem.tabContent.querySelector('div').replaceWith(this.playerObject);
|
|
this.playerObject.addEventListener('canplay', () => {
|
|
// Indication that the video is loaded and can be played and paused.
|
|
this.isReady = true;
|
|
resolve();
|
|
});
|
|
|
|
// Seeked event indicates that the seeking has been finished, so we reset the boolean for that.
|
|
this.playerObject.addEventListener('seeked', () => {
|
|
this.isVideoSeeking = false;
|
|
});
|
|
|
|
// Seeking event indicates that the seeking is currently happening, so we change the boolean.
|
|
this.playerObject.addEventListener('seeking', () => {
|
|
clearTimeout(this.seekTimeOut);
|
|
this.isVideoSeeking = true;
|
|
});
|
|
});
|
|
return videoPromise;
|
|
}
|
|
handleEnded(callback) {
|
|
this.playerObject.addEventListener('ended', () => {
|
|
this.watchCount++;
|
|
// This property will prevent automatic pause trigger when video ended.
|
|
this.isVideoEnded = true;
|
|
this.isVideoPlaying = false;
|
|
callback(this.playlistItem);
|
|
});
|
|
}
|
|
handlePaused(callback) {
|
|
this.playerObject.addEventListener('pause', () => {
|
|
// Prevent pause trigger when the user is seeking video or when the video automatically trigger pause event when ended.
|
|
this.seekTimeOut = setTimeout(() => {
|
|
if (!this.isVideoSeeking && !this.isVideoEnded) {
|
|
callback(this.positionInVideoList);
|
|
|
|
// Indication to know when there is a resume trigger event.
|
|
this.isVideoPausedLocal = true;
|
|
} else {
|
|
this.isVideoEnded = false;
|
|
}
|
|
}, 30);
|
|
});
|
|
}
|
|
handlePlayed(callback) {
|
|
this.playerObject.addEventListener('play', () => {
|
|
// Prevent play trigger when user is seeking video.
|
|
if (!this.isVideoSeeking) {
|
|
callback(this.playlistItem);
|
|
}
|
|
});
|
|
}
|
|
handleFullScreenChange(callback) {
|
|
// Wrapping with jQuery to easily listen all 3 prefixed screen change.
|
|
jQuery(this.playerObject).on('webkitfullscreenchange mozfullscreenchange fullscreenchange', () => {
|
|
callback(document.fullscreenElement);
|
|
});
|
|
}
|
|
getCurrentTime() {
|
|
return this.playerObject.currentTime;
|
|
}
|
|
play() {
|
|
if (!this.isReady) {
|
|
return;
|
|
}
|
|
this.isVideoPlaying = true;
|
|
this.playerObject.play();
|
|
}
|
|
pause() {
|
|
if (!this.isReady) {
|
|
return;
|
|
}
|
|
this.isVideoPlaying = false;
|
|
this.playerObject.pause();
|
|
}
|
|
mute() {
|
|
this.playerObject.muted = true;
|
|
}
|
|
}
|
|
exports["default"] = playerHosted;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/player-vimeo.js":
|
|
/*!********************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/player-vimeo.js ***!
|
|
\********************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js");
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports["default"] = void 0;
|
|
var _playerBase = _interopRequireDefault(__webpack_require__(/*! ./player-base */ "../modules/video-playlist/assets/js/frontend/player-base.js"));
|
|
class playerVimeo extends _playerBase.default {
|
|
constructor(playlistItem, videoIndex) {
|
|
super(playlistItem, videoIndex);
|
|
this.apiProvider = elementorFrontend.utils.vimeo;
|
|
this.playerObject = null;
|
|
this.watchCount = 0;
|
|
this.isVideoInFullScreenChange = false;
|
|
this.isReady = false;
|
|
}
|
|
create() {
|
|
this.currentVideoID = this.apiProvider.getVideoIDFromURL(this.playlistItem.videoUrl);
|
|
return new Promise(resolve => {
|
|
this.apiProvider.onApiReady(apiObject => {
|
|
const playerOptions = {
|
|
id: this.currentVideoID,
|
|
autoplay: false
|
|
};
|
|
this.playerObject = new apiObject.Player(this.playlistItem.tabContent.querySelector('div'), playerOptions);
|
|
|
|
// Indication that the video is loaded and can be played and paused.
|
|
this.playerObject.ready().then(() => {
|
|
this.isReady = true;
|
|
resolve();
|
|
});
|
|
});
|
|
});
|
|
}
|
|
handleEnded(callback) {
|
|
this.playerObject.on('ended', () => {
|
|
this.watchCount++;
|
|
callback(this.playlistItem);
|
|
});
|
|
}
|
|
handlePaused(callback) {
|
|
this.playerObject.on('pause', event => {
|
|
// Prevent "pause" event trigger when page loads with vimeo video and when vimeo video ended, or when entering/exiting full-screen mode.
|
|
if (0 === event.percent || event.percent >= 1 || this.isVideoInFullScreenChange) {
|
|
return;
|
|
}
|
|
callback(this.positionInVideoList);
|
|
});
|
|
}
|
|
handlePlayed(callback) {
|
|
this.playerObject.on('play', () => {
|
|
if (this.isVideoInFullScreenChange) {
|
|
// Full screen change ended with all the extra events (pause and play).
|
|
this.isVideoInFullScreenChange = false;
|
|
return;
|
|
}
|
|
callback(this.playlistItem);
|
|
});
|
|
}
|
|
handleFullScreenChange(callback) {
|
|
this.playerObject.element.addEventListener('fullscreenchange', () => {
|
|
callback(document.fullscreenElement);
|
|
this.isVideoInFullScreenChange = true;
|
|
});
|
|
}
|
|
getCurrentTime() {
|
|
return this.playerObject.getCurrentTime().then(seconds => seconds);
|
|
}
|
|
play() {
|
|
if (!this.isReady) {
|
|
return;
|
|
}
|
|
this.playerObject.play();
|
|
}
|
|
pause() {
|
|
if (!this.isReady) {
|
|
return;
|
|
}
|
|
this.playerObject.pause();
|
|
}
|
|
mute() {
|
|
this.playerObject.setMuted(true);
|
|
}
|
|
async setVideoProviderData() {
|
|
if (!this.currentVideoID && 9 === !this.currentVideoID.length) {
|
|
return;
|
|
}
|
|
const videoId = await this.playerObject.getVideoId();
|
|
const response = await fetch('https://vimeo.com/api/v2/video/' + videoId + '.json');
|
|
const videoData = await response.json();
|
|
this.playlistItem.duration = this.formatDuration(videoData[0].duration);
|
|
this.playlistItem.video_title = videoData[0].title;
|
|
this.playlistItem.thumbnail = {
|
|
url: videoData[0].thumbnail_medium
|
|
};
|
|
return this.playlistItem;
|
|
}
|
|
}
|
|
exports["default"] = playerVimeo;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/player-youtube.js":
|
|
/*!**********************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/player-youtube.js ***!
|
|
\**********************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
|
|
|
|
var _interopRequireDefault = __webpack_require__(/*! @babel/runtime/helpers/interopRequireDefault */ "../node_modules/@babel/runtime/helpers/interopRequireDefault.js");
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports["default"] = void 0;
|
|
var _playerBase = _interopRequireDefault(__webpack_require__(/*! ./player-base */ "../modules/video-playlist/assets/js/frontend/player-base.js"));
|
|
class playerYoutube extends _playerBase.default {
|
|
constructor(playlistItem, videoIndex) {
|
|
super(playlistItem, videoIndex);
|
|
this.apiProvider = elementorFrontend.utils.youtube;
|
|
this.playerObject = null;
|
|
this.watchCount = 0;
|
|
this.isVideoPlaying = false;
|
|
this.isVideoPausedLocal = false;
|
|
this.isVideoEnded = false;
|
|
this.seekSequenceArray = [];
|
|
this.pauseCurrentTime = null;
|
|
this.isReady = false;
|
|
}
|
|
create() {
|
|
this.currentVideoID = this.apiProvider.getVideoIDFromURL(this.playlistItem.videoUrl);
|
|
const videoPromise = new Promise(resolve => {
|
|
this.apiProvider.onApiReady(apiObject => {
|
|
const playerOptions = {
|
|
width: '773',
|
|
videoId: this.currentVideoID,
|
|
playerVars: {
|
|
rel: 0,
|
|
showinfo: 0,
|
|
ecver: 2
|
|
},
|
|
events: {
|
|
onReady: () => {
|
|
// Indication that the video is loaded and can be played and paused.
|
|
this.isReady = true;
|
|
resolve();
|
|
}
|
|
}
|
|
};
|
|
this.playerObject = new apiObject.Player(this.playlistItem.tabContent.querySelector('div'), playerOptions);
|
|
this.playerObject.addEventListener('onStateChange', event => {
|
|
// Buffering state.
|
|
if (3 === event.data) {
|
|
// When user is seeking we want to prevent triggering for "pause" and "play".
|
|
// Seeking means a sequence as [2,3], so we check that 2 (pause) is exist before adding "3" (buffering).
|
|
// If there is no "2", it means that this is not a seeking event and we can reset the array.
|
|
if (2 === this.seekSequenceArray[this.seekSequenceArray.length - 1]) {
|
|
this.seekSequenceArray.push(3);
|
|
} else {
|
|
this.seekSequenceArray = [];
|
|
clearTimeout(this.seekTimeOut);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|
|
return videoPromise;
|
|
}
|
|
handleEnded(callback) {
|
|
this.playerObject.addEventListener('onStateChange', event => {
|
|
// Ended state.
|
|
if (0 === event.data) {
|
|
this.watchCount++;
|
|
|
|
// Prevent "video start" event when we seek to "0" on video ended event.
|
|
// We seek to "0" to prevent the display of suggested videos by youtube when video ended.
|
|
this.isVideoEnded = true;
|
|
event.target.seekTo(0);
|
|
event.target.stopVideo();
|
|
this.isVideoPlaying = false;
|
|
callback();
|
|
}
|
|
});
|
|
}
|
|
handlePaused(callback) {
|
|
this.playerObject.addEventListener('onStateChange', event => {
|
|
// Pause state.
|
|
if (2 === event.data) {
|
|
// The pause event can be the start of seek event ([2,3] sequence) so we reset the sequence array and adding 2.
|
|
this.seekSequenceArray = [];
|
|
this.seekSequenceArray.push(2);
|
|
// Save the current time when pause event occur.
|
|
this.pauseCurrentTime = this.playerObject.playerInfo.currentTime;
|
|
|
|
// We use here a setTimeout, since we don't want to fire the pause event before we can be sure that its not part of seek event.
|
|
this.seekTimeOut = setTimeout(() => {
|
|
if (2 === this.seekSequenceArray.length && 2 === this.seekSequenceArray[0] && 3 === this.seekSequenceArray[1]) {
|
|
this.seekSequenceArray = [];
|
|
clearTimeout(this.seekTimeOut);
|
|
} else {
|
|
callback(this.positionInVideoList);
|
|
// Indication to know when there is a resume trigger event.
|
|
this.isVideoPausedLocal = true;
|
|
}
|
|
}, 1000);
|
|
}
|
|
});
|
|
}
|
|
handlePlayed(callback) {
|
|
this.playerObject.addEventListener('onStateChange', event => {
|
|
// Prevent "video start" event when we seek to "0" on video ended event.
|
|
if (1 === event.data && !this.isVideoEnded) {
|
|
// Prevent "play" event when it is a seek event ([2,3] sequence).
|
|
if (!(2 === this.seekSequenceArray.length && 2 === this.seekSequenceArray[0] && 3 === this.seekSequenceArray[1])) {
|
|
callback();
|
|
}
|
|
} else {
|
|
this.isVideoEnded = false;
|
|
}
|
|
});
|
|
}
|
|
handleError(callback) {
|
|
this.playerObject.addEventListener('onError', () => {
|
|
callback();
|
|
});
|
|
}
|
|
handleFullScreenChange(callback) {
|
|
this.playerObject.h.addEventListener('fullscreenchange', () => {
|
|
callback(document.fullscreenElement);
|
|
});
|
|
}
|
|
getCurrentTime() {
|
|
const currentTime = this.pauseCurrentTime ? this.pauseCurrentTime : this.playerObject.playerInfo.currentTime;
|
|
this.pauseCurrentTime = null;
|
|
return currentTime;
|
|
}
|
|
play() {
|
|
if (!this.isReady) {
|
|
return;
|
|
}
|
|
this.isVideoPlaying = true;
|
|
this.playerObject.playVideo();
|
|
}
|
|
pause() {
|
|
if (!this.isReady) {
|
|
return;
|
|
}
|
|
this.isVideoPlaying = false;
|
|
this.playerObject.pauseVideo();
|
|
}
|
|
mute() {
|
|
this.playerObject.mute();
|
|
}
|
|
async setVideoProviderData() {
|
|
if (!this.isReady) {
|
|
return;
|
|
}
|
|
if (this.currentVideoID && 11 === this.currentVideoID.length) {
|
|
this.playlistItem.thumbnail = {
|
|
url: 'https://img.youtube.com/vi/' + this.playerObject.getVideoData().video_id + '/maxresdefault.jpg'
|
|
};
|
|
this.playlistItem.video_title = this.playerObject.getVideoData().title;
|
|
this.playlistItem.duration = this.formatDuration(this.playerObject.getDuration());
|
|
} else {
|
|
this.playlistItem.thumbnail = {
|
|
url: ''
|
|
};
|
|
this.playlistItem.video_title = '';
|
|
this.playlistItem.duration = '';
|
|
}
|
|
}
|
|
}
|
|
exports["default"] = playerYoutube;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/playlist-event.js":
|
|
/*!**********************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/playlist-event.js ***!
|
|
\**********************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports["default"] = void 0;
|
|
// State transfer object
|
|
class PlaylistEvent {
|
|
constructor(_ref) {
|
|
let {
|
|
event,
|
|
tab,
|
|
playlist,
|
|
video
|
|
} = _ref;
|
|
this.event = {
|
|
type: event.type || '',
|
|
time: event.time || 0,
|
|
element: event.element,
|
|
trigger: event.trigger || '',
|
|
watchCount: event.watchCount || 0
|
|
};
|
|
this.tab = {
|
|
name: tab.name,
|
|
index: tab.index
|
|
};
|
|
this.playlist = {
|
|
name: playlist.name,
|
|
currentItem: playlist.currentItem,
|
|
amount: playlist.amount
|
|
};
|
|
this.video = {
|
|
provider: video.provider,
|
|
url: video.url,
|
|
title: video.title,
|
|
duration: video.duration
|
|
};
|
|
}
|
|
}
|
|
exports["default"] = PlaylistEvent;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/scroll-utils.js":
|
|
/*!********************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/scroll-utils.js ***!
|
|
\********************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports.handleVideosPanelScroll = handleVideosPanelScroll;
|
|
// Handle the display of top/bottom shadows in playlist item's panel.
|
|
function handleVideosPanelScroll(elements, event) {
|
|
if (!event) {
|
|
if (elements.$tabsItems[0].offsetHeight < elements.$tabsItems[0].scrollHeight) {
|
|
elements.$tabsWrapper.addClass('bottom-shadow');
|
|
}
|
|
return;
|
|
}
|
|
if (event.target.scrollTop > 0) {
|
|
elements.$tabsWrapper.addClass('top-shadow');
|
|
} else {
|
|
elements.$tabsWrapper.removeClass('top-shadow');
|
|
}
|
|
if (event.target.offsetHeight + event.target.scrollTop >= event.target.scrollHeight) {
|
|
elements.$tabsWrapper.removeClass('bottom-shadow');
|
|
} else {
|
|
elements.$tabsWrapper.addClass('bottom-shadow');
|
|
}
|
|
}
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../modules/video-playlist/assets/js/frontend/url-params.js":
|
|
/*!******************************************************************!*\
|
|
!*** ../modules/video-playlist/assets/js/frontend/url-params.js ***!
|
|
\******************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", ({
|
|
value: true
|
|
}));
|
|
exports.handleURLParams = handleURLParams;
|
|
exports.setVideoParams = setVideoParams;
|
|
// Handling the functionality for existing/not-existing url params.
|
|
function handleURLParams(playlistId, playlistItemsArray) {
|
|
const params = new URLSearchParams(location.search),
|
|
playlistName = params.get('playlist'),
|
|
defaultTabIndex = 1;
|
|
|
|
// When there is no data in params, the first video in the list should be active by returning false.
|
|
if (!playlistName) {
|
|
return false;
|
|
}
|
|
|
|
// When there is data in params, we return the tab number for the video.
|
|
if (playlistName === playlistId) {
|
|
const videoId = params.get('video');
|
|
const videoItem = playlistItemsArray.find(playlistItem => videoId === playlistItem.dataItemId),
|
|
tabIndex = videoItem ? videoItem.dataTab : defaultTabIndex;
|
|
if (!tabIndex) {
|
|
setVideoParams(playlistId, playlistItemsArray, defaultTabIndex);
|
|
}
|
|
return tabIndex || false;
|
|
}
|
|
}
|
|
|
|
// Setting the playlist id and video id on the url.
|
|
function setVideoParams(playlistId, playlistItemsArray, videoId) {
|
|
const params = new URLSearchParams(location.search);
|
|
params.set('playlist', playlistId);
|
|
params.set('video', playlistItemsArray[videoId - 1].dataItemId);
|
|
history.replaceState({}, '', location.pathname + '?' + params);
|
|
}
|
|
|
|
/***/ })
|
|
|
|
}]);
|
|
//# sourceMappingURL=video-playlist.964a12bbea2078517f07.bundle.js.map
|