ElementorPro/assets/js/video-playlist.964a12bbea2078517f07.bundle.js
2024-07-07 01:00:30 +02:00

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