/** * Note: This is complex initialization, but it is necessary for Gutenberg and Elementor compatibility. There are some known issues in Gutenberg that require this complex setup. */ var playerInit = []; // Event listener for when the DOM content is loaded document.addEventListener('DOMContentLoaded', function () { const overlayMask = document.createElement('div'); overlayMask.className = 'overlay-mask'; // Select all embed wrappers with the class 'ep-embed-content-wraper' let embedWrappers = document.querySelectorAll('.ep-embed-content-wraper'); // Initialize the player for each embed wrapper embedWrappers.forEach(wrapper => { initPlayer(wrapper); }); // Mutation observer to detect any changes in the DOM const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { const addedNodes = Array.from(mutation.addedNodes); addedNodes.forEach(node => { traverseAndInitPlayer(node); }); }); }); // Start observing changes in the entire document body and its subtree observer.observe(document.body, { childList: true, subtree: true }); // Recursive function to traverse the DOM and initialize the player for each embed wrapper function traverseAndInitPlayer(node) { if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains('ep-embed-content-wraper')) { initPlayer(node); } if (node.hasChildNodes()) { node.childNodes.forEach(childNode => { traverseAndInitPlayer(childNode); }); } } }); // Function to initialize the player for a given wrapper function initPlayer(wrapper) { const playerId = wrapper.getAttribute('data-playerid'); // Get the options for the player from the wrapper's data attribute let options = document.querySelector(`[data-playerid='${playerId}']`)?.getAttribute('data-options'); if (!options) { return false; } // Parse the options string into a JSON object if (typeof options === 'string') { try { options = JSON.parse(options); } catch (e) { return; } } else { return; } if (!options.poster_thumbnail) { wrapper.style.opacity = "1"; } // Create DOM elements from the icon strings const pipPlayIconElement = document.createElement('div'); pipPlayIconElement.className = 'pip-play'; pipPlayIconElement.innerHTML = ''; pipPlayIconElement.style.display = 'none'; const pipPauseIconElement = document.createElement('div'); pipPauseIconElement.className = 'pip-pause'; pipPauseIconElement.innerHTML = ''; const pipCloseElement = document.createElement('div'); pipCloseElement.className = 'pip-close'; pipCloseElement.innerHTML = ''; // Check if the player has not been initialized for this wrapper if (playerId && !wrapper.classList.contains('plyr-initialized')) { let selector = `[data-playerid='${playerId}'] .ose-embedpress-responsive`; if (options.self_hosted && options.hosted_format === 'video') { selector = `[data-playerid='${playerId}'] .ose-embedpress-responsive video`; } else if (options.self_hosted && options.hosted_format === 'audio') { selector = `[data-playerid='${playerId}'] .ose-embedpress-responsive audio`; wrapper.style.opacity = "1"; } // Set the main color of the player document.querySelector(`[data-playerid='${playerId}']`).style.setProperty('--plyr-color-main', options.player_color); document.querySelector(`[data-playerid='${playerId}'].custom-player-preset-1, [data-playerid='${playerId}'].custom-player-preset-3, [data-playerid='${playerId}'].custom-player-preset-4`)?.style.setProperty('--plyr-range-fill-background', '#ffffff'); // Set the poster thumbnail for the player if (document.querySelector(`[data-playerid='${playerId}'] iframe`)) { document.querySelector(`[data-playerid='${playerId}'] iframe`).setAttribute('data-poster', options.poster_thumbnail); } if (document.querySelector(`[data-playerid='${playerId}'] video`)) { document.querySelector(`[data-playerid='${playerId}'] video`).setAttribute('data-poster', options.poster_thumbnail); } // Define the controls to be displayed const controls = [ 'play-large', options.restart ? 'restart' : '', options.rewind ? 'rewind' : '', 'play', options.fast_forward ? 'fast-forward' : '', 'progress', 'current-time', 'duration', 'mute', 'volume', 'captions', 'settings', options.pip ? 'pip' : '', 'airplay', options.download ? 'download' : '', options.fullscreen ? 'fullscreen' : '', ].filter(control => control !== ''); // Detect if we're on iOS const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; // Detect if this is a YouTube video const isYouTube = document.querySelector(`[data-playerid='${playerId}'] iframe[src*="youtube"]`) !== null; // For iOS YouTube videos, we need to use fallback fullscreen instead of native // because webkitEnterFullscreen() doesn't work on iframes const shouldUseFallbackFullscreen = isIOS && isYouTube; // Create a new Plyr player instance with the specified options and controls const player = new Plyr(selector, { controls: controls, seekTime: 10, poster: options.poster_thumbnail, storage: { enabled: true, key: 'plyr_volume' }, displayDuration: true, tooltips: { controls: options.player_tooltip, seek: options.player_tooltip }, hideControls: options.hide_controls, // iOS fullscreen configuration - use fallback for YouTube on iOS fullscreen: { enabled: options.fullscreen !== false, fallback: true, iosNative: !shouldUseFallbackFullscreen // Disable iosNative for YouTube on iOS }, // Enable playsinline for iOS devices to allow custom controls playsinline: true, youtube: { ...(options.autoplay && { autoplay: options.autoplay }), ...(options.start && { start: options.start }), ...(options.end && { end: options.end }), ...(options.rel && { rel: options.rel }), ...(options.fullscreen && { fs: options.fullscreen }) }, vimeo: { byline: false, portrait: false, title: false, speed: true, transparent: false, controls: false, ...(options.t && { t: options.t }), ...(options.vautoplay && { autoplay: options.vautoplay }), ...(options.autopause && { autopause: options.autopause }), ...(options.dnt && { dnt: options.dnt }), } }); playerInit[playerId] = player; // iOS YouTube fullscreen fix: Ensure iframe has proper attributes if (shouldUseFallbackFullscreen) { const iframe = document.querySelector(`[data-playerid='${playerId}'] iframe[src*="youtube"]`); if (iframe) { // Ensure the iframe allows fullscreen iframe.setAttribute('allowfullscreen', ''); iframe.setAttribute('webkitallowfullscreen', ''); iframe.setAttribute('mozallowfullscreen', ''); // Add iOS-specific class for styling iframe.classList.add('ios-youtube-iframe'); // Listen for fullscreen events to handle iOS-specific behavior player.on('enterfullscreen', () => { // Force viewport meta tag update for better fullscreen experience const viewport = document.querySelector('meta[name="viewport"]'); if (viewport) { const originalContent = viewport.getAttribute('content'); viewport.setAttribute('data-original-content', originalContent); viewport.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover'); } }); player.on('exitfullscreen', () => { // Restore original viewport meta tag const viewport = document.querySelector('meta[name="viewport"]'); if (viewport && viewport.hasAttribute('data-original-content')) { viewport.setAttribute('content', viewport.getAttribute('data-original-content')); viewport.removeAttribute('data-original-content'); } }); } } // Mark the wrapper as initialized wrapper.classList.add('plyr-initialized'); const posterElement = wrapper.querySelector('.plyr__poster'); if (posterElement) { const interval = setInterval(() => { if (posterElement && posterElement.style.backgroundImage) { wrapper.style.opacity = '1'; clearInterval(interval); } }, 200); } } // Check for the existence of the player's pip button at regular intervals const pipInterval = setInterval(() => { let playerPip = document.querySelector(`[data-playerid="${playerId}"] [data-plyr="pip"]`); if (playerPip) { clearInterval(pipInterval); let options = document.querySelector(`[data-playerid="${playerId}"]`).getAttribute('data-options'); options = JSON.parse(options); if (!options.self_hosted) { const iframeSelector = document.querySelector(`[data-playerid="${playerId}"] .plyr__video-wrapper`); // Add click event listener to toggle the pip mode playerPip.addEventListener('click', () => { iframeSelector.classList.toggle('pip-mode'); let parentElement = iframeSelector.parentElement; while (parentElement) { parentElement.style.zIndex = '9999'; parentElement = parentElement.parentElement; } }); if (options.pip) { iframeSelector.appendChild(pipPlayIconElement); iframeSelector.appendChild(pipPauseIconElement); iframeSelector.appendChild(pipCloseElement); const pipPlay = document.querySelector(`[data-playerid="${playerId}"] .plyr__video-wrapper .pip-play`); const pipPause = document.querySelector(`[data-playerid="${playerId}"] .plyr__video-wrapper .pip-pause`); const pipClose = document.querySelector(`[data-playerid="${playerId}"] .plyr__video-wrapper .pip-close`); pipClose.addEventListener('click', () => { iframeSelector.classList.remove('pip-mode'); }); iframeSelector.addEventListener('click', () => { const ariaPressedValue = document.querySelector(`[data-playerid="${playerId}"] .plyr__controls [data-plyr="play"]`).getAttribute('aria-pressed'); if (ariaPressedValue === 'true') { pipPause.style.display = 'none'; pipPlay.style.display = 'flex'; } else { pipPlay.style.display = 'none'; pipPause.style.display = 'flex'; } }); } } } }, 200); }