chunks
6 months ago
vendor
9 months ago
admin.build.js
7 months ago
admin.js
9 months ago
analytics-tracker.js
9 months ago
analytics.build.js
6 months ago
blocks.build.js
6 months ago
carousel.js
1 year ago
documents-viewer-script.js
3 years ago
feature-notices.js
7 months ago
front.js
6 months ago
frontend.build.js
9 months ago
gallery-justify.js
9 months ago
gutneberg-script.js
1 year ago
index.html
7 years ago
initCarousel.js
2 years ago
initplyr.js
9 months ago
instafeed.js
7 months ago
lazy-load.js
6 months ago
license.js
7 months ago
meetup-timezone.js
6 months ago
preview.js
9 months ago
settings.js
6 months ago
sponsored.js
9 months ago
initplyr.js
317 lines
| 1 | /** |
| 2 | * 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. |
| 3 | */ |
| 4 | var playerInit = []; |
| 5 | |
| 6 | |
| 7 | // Event listener for when the DOM content is loaded |
| 8 | document.addEventListener('DOMContentLoaded', function () { |
| 9 | |
| 10 | |
| 11 | const overlayMask = document.createElement('div'); |
| 12 | overlayMask.className = 'overlay-mask'; |
| 13 | |
| 14 | |
| 15 | // Select all embed wrappers with the class 'ep-embed-content-wraper' |
| 16 | let embedWrappers = document.querySelectorAll('.ep-embed-content-wraper'); |
| 17 | |
| 18 | // Initialize the player for each embed wrapper |
| 19 | embedWrappers.forEach(wrapper => { |
| 20 | initPlayer(wrapper); |
| 21 | }); |
| 22 | |
| 23 | // Mutation observer to detect any changes in the DOM |
| 24 | const observer = new MutationObserver(mutations => { |
| 25 | mutations.forEach(mutation => { |
| 26 | const addedNodes = Array.from(mutation.addedNodes); |
| 27 | addedNodes.forEach(node => { |
| 28 | traverseAndInitPlayer(node); |
| 29 | }); |
| 30 | }); |
| 31 | }); |
| 32 | |
| 33 | // Start observing changes in the entire document body and its subtree |
| 34 | observer.observe(document.body, { childList: true, subtree: true }); |
| 35 | |
| 36 | // Recursive function to traverse the DOM and initialize the player for each embed wrapper |
| 37 | function traverseAndInitPlayer(node) { |
| 38 | if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains('ep-embed-content-wraper')) { |
| 39 | initPlayer(node); |
| 40 | } |
| 41 | |
| 42 | if (node.hasChildNodes()) { |
| 43 | node.childNodes.forEach(childNode => { |
| 44 | traverseAndInitPlayer(childNode); |
| 45 | }); |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | |
| 50 | }); |
| 51 | |
| 52 | |
| 53 | // Function to initialize the player for a given wrapper |
| 54 | function initPlayer(wrapper) { |
| 55 | const playerId = wrapper.getAttribute('data-playerid'); |
| 56 | |
| 57 | // Get the options for the player from the wrapper's data attribute |
| 58 | let options = document.querySelector(`[data-playerid='${playerId}']`)?.getAttribute('data-options'); |
| 59 | |
| 60 | |
| 61 | |
| 62 | if (!options) { |
| 63 | return false; |
| 64 | } |
| 65 | |
| 66 | // Parse the options string into a JSON object |
| 67 | if (typeof options === 'string') { |
| 68 | try { |
| 69 | options = JSON.parse(options); |
| 70 | } catch (e) { |
| 71 | return; |
| 72 | } |
| 73 | } else { |
| 74 | return; |
| 75 | } |
| 76 | |
| 77 | |
| 78 | if (!options.poster_thumbnail) { |
| 79 | wrapper.style.opacity = "1"; |
| 80 | } |
| 81 | |
| 82 | // Create DOM elements from the icon strings |
| 83 | const pipPlayIconElement = document.createElement('div'); |
| 84 | pipPlayIconElement.className = 'pip-play'; |
| 85 | pipPlayIconElement.innerHTML = '<svg width="20" height="20" viewBox="-0.15 -0.112 0.9 0.9" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin" class="jam jam-play"><path fill="#fff" d="M.518.357A.037.037 0 0 0 .506.306L.134.08a.039.039 0 0 0-.02-.006.038.038 0 0 0-.038.037v.453c0 .007.002.014.006.02a.039.039 0 0 0 .052.012L.506.37A.034.034 0 0 0 .518.358zm.028.075L.174.658A.115.115 0 0 1 .017.622.109.109 0 0 1 0 .564V.111C0 .05.051 0 .114 0c.021 0 .042.006.06.017l.372.226a.11.11 0 0 1 0 .189z"/></svg>'; |
| 86 | pipPlayIconElement.style.display = 'none'; |
| 87 | |
| 88 | |
| 89 | const pipPauseIconElement = document.createElement('div'); |
| 90 | pipPauseIconElement.className = 'pip-pause'; |
| 91 | pipPauseIconElement.innerHTML = '<svg fill="#fff" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 2.5 2.5" xml:space="preserve"><path d="M1.013.499 1.006.5V.499H.748a.054.054 0 0 0-.054.054v1.394c0 .03.024.054.054.054h.266a.054.054 0 0 0 .054-.054V.553a.054.054 0 0 0-.054-.054zm.793 1.448V.553a.054.054 0 0 0-.054-.054L1.745.5V.499h-.258a.054.054 0 0 0-.054.054v1.394c0 .03.024.054.054.054h.265a.054.054 0 0 0 .054-.054z"/></svg>'; |
| 92 | |
| 93 | const pipCloseElement = document.createElement('div'); |
| 94 | pipCloseElement.className = 'pip-close'; |
| 95 | pipCloseElement.innerHTML = '<svg width="20" height="20" viewBox="0 0 0.9 0.9" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M.198.198a.037.037 0 0 1 .053 0L.45.397.648.199a.037.037 0 1 1 .053.053L.503.45l.198.198a.037.037 0 0 1-.053.053L.45.503.252.701A.037.037 0 0 1 .199.648L.397.45.198.252a.037.037 0 0 1 0-.053z" fill="#fff"/></svg>'; |
| 96 | |
| 97 | // Check if the player has not been initialized for this wrapper |
| 98 | if (playerId && !wrapper.classList.contains('plyr-initialized')) { |
| 99 | |
| 100 | |
| 101 | let selector = `[data-playerid='${playerId}'] .ose-embedpress-responsive`; |
| 102 | |
| 103 | |
| 104 | if (options.self_hosted && options.hosted_format === 'video') { |
| 105 | selector = `[data-playerid='${playerId}'] .ose-embedpress-responsive video`; |
| 106 | } |
| 107 | else if (options.self_hosted && options.hosted_format === 'audio') { |
| 108 | selector = `[data-playerid='${playerId}'] .ose-embedpress-responsive audio`; |
| 109 | wrapper.style.opacity = "1"; |
| 110 | } |
| 111 | |
| 112 | |
| 113 | // Set the main color of the player |
| 114 | document.querySelector(`[data-playerid='${playerId}']`).style.setProperty('--plyr-color-main', options.player_color); |
| 115 | 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'); |
| 116 | |
| 117 | // Set the poster thumbnail for the player |
| 118 | if (document.querySelector(`[data-playerid='${playerId}'] iframe`)) { |
| 119 | document.querySelector(`[data-playerid='${playerId}'] iframe`).setAttribute('data-poster', options.poster_thumbnail); |
| 120 | } |
| 121 | if (document.querySelector(`[data-playerid='${playerId}'] video`)) { |
| 122 | document.querySelector(`[data-playerid='${playerId}'] video`).setAttribute('data-poster', options.poster_thumbnail); |
| 123 | } |
| 124 | |
| 125 | // Define the controls to be displayed |
| 126 | const controls = [ |
| 127 | 'play-large', |
| 128 | options.restart ? 'restart' : '', |
| 129 | options.rewind ? 'rewind' : '', |
| 130 | 'play', |
| 131 | options.fast_forward ? 'fast-forward' : '', |
| 132 | 'progress', |
| 133 | 'current-time', |
| 134 | 'duration', |
| 135 | 'mute', |
| 136 | 'volume', |
| 137 | 'captions', |
| 138 | 'settings', |
| 139 | options.pip ? 'pip' : '', |
| 140 | 'airplay', |
| 141 | options.download ? 'download' : '', |
| 142 | options.fullscreen ? 'fullscreen' : '', |
| 143 | |
| 144 | ].filter(control => control !== ''); |
| 145 | |
| 146 | // Detect if we're on iOS |
| 147 | const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; |
| 148 | |
| 149 | // Detect if this is a YouTube video |
| 150 | const isYouTube = document.querySelector(`[data-playerid='${playerId}'] iframe[src*="youtube"]`) !== null; |
| 151 | |
| 152 | // For iOS YouTube videos, we need to use fallback fullscreen instead of native |
| 153 | // because webkitEnterFullscreen() doesn't work on iframes |
| 154 | const shouldUseFallbackFullscreen = isIOS && isYouTube; |
| 155 | |
| 156 | |
| 157 | |
| 158 | // Create a new Plyr player instance with the specified options and controls |
| 159 | const player = new Plyr(selector, { |
| 160 | controls: controls, |
| 161 | seekTime: 10, |
| 162 | poster: options.poster_thumbnail, |
| 163 | storage: { |
| 164 | enabled: true, |
| 165 | key: 'plyr_volume' |
| 166 | }, |
| 167 | displayDuration: true, |
| 168 | tooltips: { controls: options.player_tooltip, seek: options.player_tooltip }, |
| 169 | hideControls: options.hide_controls, |
| 170 | // iOS fullscreen configuration - use fallback for YouTube on iOS |
| 171 | fullscreen: { |
| 172 | enabled: options.fullscreen !== false, |
| 173 | fallback: true, |
| 174 | iosNative: !shouldUseFallbackFullscreen // Disable iosNative for YouTube on iOS |
| 175 | }, |
| 176 | // Enable playsinline for iOS devices to allow custom controls |
| 177 | playsinline: true, |
| 178 | youtube: { |
| 179 | ...(options.autoplay && { autoplay: options.autoplay }), |
| 180 | ...(options.start && { start: options.start }), |
| 181 | ...(options.end && { end: options.end }), |
| 182 | ...(options.rel && { rel: options.rel }), |
| 183 | ...(options.fullscreen && { fs: options.fullscreen }) |
| 184 | }, |
| 185 | vimeo: { |
| 186 | byline: false, |
| 187 | portrait: false, |
| 188 | title: false, |
| 189 | speed: true, |
| 190 | transparent: false, |
| 191 | controls: false, |
| 192 | ...(options.t && { t: options.t }), |
| 193 | ...(options.vautoplay && { autoplay: options.vautoplay }), |
| 194 | ...(options.autopause && { autopause: options.autopause }), |
| 195 | ...(options.dnt && { dnt: options.dnt }), |
| 196 | } |
| 197 | }); |
| 198 | |
| 199 | playerInit[playerId] = player; |
| 200 | |
| 201 | |
| 202 | // iOS YouTube fullscreen fix: Ensure iframe has proper attributes |
| 203 | if (shouldUseFallbackFullscreen) { |
| 204 | const iframe = document.querySelector(`[data-playerid='${playerId}'] iframe[src*="youtube"]`); |
| 205 | if (iframe) { |
| 206 | // Ensure the iframe allows fullscreen |
| 207 | iframe.setAttribute('allowfullscreen', ''); |
| 208 | iframe.setAttribute('webkitallowfullscreen', ''); |
| 209 | iframe.setAttribute('mozallowfullscreen', ''); |
| 210 | |
| 211 | // Add iOS-specific class for styling |
| 212 | iframe.classList.add('ios-youtube-iframe'); |
| 213 | |
| 214 | // Listen for fullscreen events to handle iOS-specific behavior |
| 215 | player.on('enterfullscreen', () => { |
| 216 | // Force viewport meta tag update for better fullscreen experience |
| 217 | const viewport = document.querySelector('meta[name="viewport"]'); |
| 218 | if (viewport) { |
| 219 | const originalContent = viewport.getAttribute('content'); |
| 220 | viewport.setAttribute('data-original-content', originalContent); |
| 221 | viewport.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover'); |
| 222 | } |
| 223 | }); |
| 224 | |
| 225 | player.on('exitfullscreen', () => { |
| 226 | // Restore original viewport meta tag |
| 227 | const viewport = document.querySelector('meta[name="viewport"]'); |
| 228 | if (viewport && viewport.hasAttribute('data-original-content')) { |
| 229 | viewport.setAttribute('content', viewport.getAttribute('data-original-content')); |
| 230 | viewport.removeAttribute('data-original-content'); |
| 231 | } |
| 232 | }); |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | |
| 237 | |
| 238 | // Mark the wrapper as initialized |
| 239 | wrapper.classList.add('plyr-initialized'); |
| 240 | |
| 241 | const posterElement = wrapper.querySelector('.plyr__poster'); |
| 242 | |
| 243 | if (posterElement) { |
| 244 | const interval = setInterval(() => { |
| 245 | if (posterElement && posterElement.style.backgroundImage) { |
| 246 | wrapper.style.opacity = '1'; |
| 247 | clearInterval(interval); |
| 248 | } |
| 249 | }, 200); |
| 250 | |
| 251 | } |
| 252 | |
| 253 | } |
| 254 | |
| 255 | // Check for the existence of the player's pip button at regular intervals |
| 256 | const pipInterval = setInterval(() => { |
| 257 | |
| 258 | let playerPip = document.querySelector(`[data-playerid="${playerId}"] [data-plyr="pip"]`); |
| 259 | if (playerPip) { |
| 260 | clearInterval(pipInterval); |
| 261 | |
| 262 | let options = document.querySelector(`[data-playerid="${playerId}"]`).getAttribute('data-options'); |
| 263 | |
| 264 | options = JSON.parse(options); |
| 265 | if (!options.self_hosted) { |
| 266 | |
| 267 | const iframeSelector = document.querySelector(`[data-playerid="${playerId}"] .plyr__video-wrapper`); |
| 268 | |
| 269 | // Add click event listener to toggle the pip mode |
| 270 | playerPip.addEventListener('click', () => { |
| 271 | iframeSelector.classList.toggle('pip-mode'); |
| 272 | |
| 273 | let parentElement = iframeSelector.parentElement; |
| 274 | while (parentElement) { |
| 275 | parentElement.style.zIndex = '9999'; |
| 276 | parentElement = parentElement.parentElement; |
| 277 | } |
| 278 | |
| 279 | }); |
| 280 | |
| 281 | |
| 282 | |
| 283 | if (options.pip) { |
| 284 | iframeSelector.appendChild(pipPlayIconElement); |
| 285 | iframeSelector.appendChild(pipPauseIconElement); |
| 286 | iframeSelector.appendChild(pipCloseElement); |
| 287 | const pipPlay = document.querySelector(`[data-playerid="${playerId}"] .plyr__video-wrapper .pip-play`); |
| 288 | const pipPause = document.querySelector(`[data-playerid="${playerId}"] .plyr__video-wrapper .pip-pause`); |
| 289 | const pipClose = document.querySelector(`[data-playerid="${playerId}"] .plyr__video-wrapper .pip-close`); |
| 290 | |
| 291 | pipClose.addEventListener('click', () => { |
| 292 | iframeSelector.classList.remove('pip-mode'); |
| 293 | }); |
| 294 | |
| 295 | |
| 296 | iframeSelector.addEventListener('click', () => { |
| 297 | const ariaPressedValue = document.querySelector(`[data-playerid="${playerId}"] .plyr__controls [data-plyr="play"]`).getAttribute('aria-pressed'); |
| 298 | |
| 299 | if (ariaPressedValue === 'true') { |
| 300 | pipPause.style.display = 'none'; |
| 301 | pipPlay.style.display = 'flex'; |
| 302 | } else { |
| 303 | pipPlay.style.display = 'none'; |
| 304 | pipPause.style.display = 'flex'; |
| 305 | } |
| 306 | }); |
| 307 | |
| 308 | } |
| 309 | |
| 310 | |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | }, 200); |
| 315 | |
| 316 | } |
| 317 |