1(function($) { 2 'use strict'; 3 4 $(document).ready(function() { 5 // Move all modals to body first, before any other initialization 6 $('.mqg-reel-video-modal').each(function() { 7 var modal = $(this); 8 if (modal.parent()[0] !== document.body) { 9 modal.appendTo('body'); 10 } 11 modal.css({ 12 'position': 'fixed', 13 'z-index': '99999', 14 'left': '0', 15 'top': '0', 16 'width': '100vw', 17 'height': '100vh', 18 'margin': '0', 19 'padding': '0', 20 'display': 'none', 21 'background-color': 'rgba(0, 0, 0, 0.9)', 22 'justify-content': 'center', 23 'align-items': 'center' 24 }); 25 }); 26 27 $('.mqg-reel-video-wrapper').each(function() { 28 var wrapper = $(this); 29 var thumbnail = wrapper.find('.mqg-reel-thumbnail'); 30 var previewVideo = wrapper.find('.mqg-reel-preview-video'); 31 var wrapperId = wrapper.attr('id'); 32 var modalId = wrapperId; // Modal data-modal-id matches wrapper id 33 var modal = $('.mqg-reel-video-modal[data-modal-id="' + modalId + '"]'); 34 35 // If modal not found, it might already be in body 36 if (!modal.length) { 37 modal = $('body').find('.mqg-reel-video-modal[data-modal-id="' + modalId + '"]'); 38 } 39 40 // Still not found? Try to find by index (fallback) 41 if (!modal.length) { 42 var wrapperIndex = $('.mqg-reel-video-wrapper').index(wrapper); 43 modal = $('body').find('.mqg-reel-video-modal').eq(wrapperIndex); 44 } 45 46 var modalVideo = modal.find('video'); 47 var closeBtn = modal.find('.mqg-reel-video-modal-close'); 48 var videoUrl = wrapper.data('video-url'); 49 var hasThumbnail = wrapper.data('has-thumbnail') === 1; 50 var hoverTimeout; 51 var isPlayingPreview = false; 52 var previewVideoLoaded = false; 53 var modalVideoLoaded = false; 54 55 // Ensure modal is in body 56 if (modal.length && modal.parent()[0] !== document.body) { 57 modal.appendTo('body'); 58 modal.css({ 59 'position': 'fixed', 60 'z-index': '99999', 61 'left': '0', 62 'top': '0', 63 'width': '100vw', 64 'height': '100vh', 65 'margin': '0', 66 'padding': '0', 67 'display': 'none', 68 'background-color': 'rgba(0, 0, 0, 0.9)', 69 'justify-content': 'center', 70 'align-items': 'center' 71 }); 72 } 73 74 // Function to load preview video 75 function loadPreviewVideo() { 76 if (!previewVideoLoaded && videoUrl && previewVideo.length && previewVideo[0]) { 77 var videoEl = previewVideo[0]; 78 videoEl.src = videoUrl; 79 previewVideoLoaded = true; 80 return true; 81 } 82 return false; 83 } 84 85 // Function to load modal video 86 function loadModalVideo() { 87 if (!modalVideoLoaded && videoUrl && modalVideo.length && modalVideo[0]) { 88 var videoEl = modalVideo[0]; 89 videoEl.src = videoUrl; 90 modalVideoLoaded = true; 91 } 92 } 93 94 // Hover preview functionality 95 wrapper.on('mouseenter', function() { 96 if (!isPlayingPreview && hasThumbnail && videoUrl) { 97 hoverTimeout = setTimeout(function() { 98 // Load video if needed 99 var wasLoaded = loadPreviewVideo(); 100 101 // Hide thumbnail and show video 102 if (thumbnail.length) { 103 thumbnail.hide(); 104 } 105 previewVideo.show(); 106 107 if (previewVideo[0]) { 108 var videoElement = previewVideo[0]; 109 110 // Load video if source was just set 111 if (wasLoaded) { 112 videoElement.load(); 113 } 114 115 // Function to play video 116 function playVideo() { 117 if (isPlayingPreview) return; 118 119 videoElement.currentTime = 0; 120 var playPromise = videoElement.play(); 121 122 if (playPromise !== undefined) { 123 playPromise.then(function() { 124 isPlayingPreview = true; 125 126 // Stop after 10 seconds 127 setTimeout(function() { 128 if (videoElement && isPlayingPreview) { 129 videoElement.pause(); 130 videoElement.currentTime = 0; 131 isPlayingPreview = false; 132 } 133 }, 10000); 134 }).catch(function(e) { 135 console.log('Preview play failed:', e); 136 isPlayingPreview = false; 137 }); 138 } 139 } 140 141 // Try to play when ready 142 videoElement.addEventListener('canplay', function() { 143 playVideo(); 144 }, { once: true }); 145 146 videoElement.addEventListener('loadeddata', function() { 147 playVideo(); 148 }, { once: true }); 149 150 // Immediate attempt if already loaded 151 if (videoElement.readyState >= 3) { 152 playVideo(); 153 } else { 154 // Fallback attempts 155 setTimeout(function() { 156 if (!isPlayingPreview && videoElement.readyState >= 2) { 157 playVideo(); 158 } 159 }, 200); 160 161 setTimeout(function() { 162 if (!isPlayingPreview && videoElement.readyState >= 1) { 163 playVideo(); 164 } 165 }, 1000); 166 } 167 } 168 }, 300); 169 } 170 }); 171 172 wrapper.on('mouseleave', function() { 173 clearTimeout(hoverTimeout); 174 if (previewVideo[0]) { 175 previewVideo[0].pause(); 176 previewVideo[0].currentTime = 0; 177 isPlayingPreview = false;
178 } 179 if (hasThumbnail) { 180 if (thumbnail.length) { 181 thumbnail.show(); 182 } 183 previewVideo.hide(); 184 } 185 }); 186 187 // Click to open modal 188 wrapper.on('click', function(e) { 189 e.preventDefault(); 190 e.stopPropagation(); 191 192 // Ensure modal is in body 193 if (modal.length && modal.parent()[0] !== document.body) { 194 modal.appendTo('body'); 195 } 196 197 // Apply styles forcefully using attr style to override everything 198 var styleStr = 'position:fixed!important;z-index:99999!important;left:0!important;top:0!important;width:100vw!important;height:100vh!important;margin:0!important;padding:0!important;display:flex!important;background-color:rgba(0,0,0,0.9)!important;justify-content:center!important;align-items:center!important;'; 199 modal.attr('style', styleStr); 200 201 modal.addClass('active'); 202 203 // Re-get references 204 modalVideo = modal.find('video'); 205 closeBtn = modal.find('.mqg-reel-video-modal-close'); 206 207 // Load modal video 208 loadModalVideo(); 209 210 if (modalVideo[0]) { 211 var videoEl = modalVideo[0]; 212 var playAttempted = false; 213 var playTimeout = null; 214 215 // Clear any existing timeouts 216 if (window.mqgModalPlayTimeout) { 217 clearTimeout(window.mqgModalPlayTimeout); 218 window.mqgModalPlayTimeout = null; 219 } 220 221 // Reset video 222 videoEl.pause(); 223 videoEl.currentTime = 0; 224 225 function playModalVideo() { 226 if (playAttempted) return; // Prevent multiple plays 227 playAttempted = true; 228 229 // Clear timeout if it exists 230 if (playTimeout) { 231 clearTimeout(playTimeout); 232 playTimeout = null; 233 } 234 235 videoEl.currentTime = 0; 236 videoEl.play().catch(function(err) { 237 console.log('Modal play failed:', err); 238 playAttempted = false; // Reset on error so we can retry 239 }); 240 } 241 242 // Clone the function reference for removal 243 var playHandler = playModalVideo; 244 245 // Remove any existing listeners first (using cloned reference) 246 videoEl.removeEventListener('canplay', playHandler); 247 videoEl.removeEventListener('loadeddata', playHandler); 248 videoEl.removeEventListener('canplaythrough', playHandler); 249 250 // Load the video 251 videoEl.load(); 252 253 // Add listeners with once flag 254 videoEl.addEventListener('canplay', function() { 255 if (!playAttempted) playModalVideo(); 256 }, { once: true }); 257 258 videoEl.addEventListener('loadeddata', function() { 259 if (!playAttempted) playModalVideo(); 260 }, { once: true }); 261 262 videoEl.addEventListener('canplaythrough', function() { 263 if (!playAttempted) playModalVideo(); 264 }, { once: true }); 265 266 // Single fallback timeout - only if video is already ready 267 if (videoEl.readyState >= 3) { 268 playModalVideo(); 269 } else { 270 playTimeout = setTimeout(function() { 271 if (!playAttempted && videoEl.readyState >= 2) { 272 playModalVideo(); 273 } 274 }, 500); 275 window.mqgModalPlayTimeout = playTimeout; 276 } 277 } 278 279 $('body').css('overflow', 'hidden'); 280 }); 281 282 // Close modal function 283 function closeModal() { 284 var currentModalVideo = modal.find('video'); 285 if (currentModalVideo.length && currentModalVideo[0]) { 286 currentModalVideo[0].pause(); 287 currentModalVideo[0].currentTime = 0; 288 } 289 modal.removeClass('active'); 290 modal.css('display', 'none'); 291 $('body').css('overflow', ''); 292 } 293 294 // Close handlers 295 closeBtn.on('click', function(e) { 296 e.stopPropagation(); 297 e.preventDefault(); 298 closeModal(); 299 }); 300 301 modal.on('click', function(e) { 302 if ($(e.target).is(modal)) { 303 e.stopPropagation(); 304 closeModal(); 305 } 306 }); 307 308 $(document).on('keydown', function(e) { 309 if (e.keyCode === 27 && modal.hasClass('active')) { 310 closeModal(); 311 } 312 }); 313 }); 314 }); 315})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.