1/** 2 * YouTube Feature Image Replace 3 * 4 * Handles video overlay functionality for posts with video content. 5 * When a user clicks on a featured image with a video overlay, 6 * it replaces the image with an embedded YouTube video. 7 */ 8 9document.addEventListener('DOMContentLoaded', function() { 10 initVideoOverlay(); 11}); 12 13function initVideoOverlay() { 14 // Handle clicks on the play button or anywhere on the video wrapper 15 var videoWrappers = document.querySelectorAll('.postPhotoWrapper.video-enabled'); 16 17 videoWrappers.forEach(function(wrapper) { 18 wrapper.addEventListener('click', function(e) { 19 e.preventDefault(); 20 e.stopPropagation(); 21 22 var photoAndCaption = wrapper.closest('.postPhotoAndCaption'); 23 var img = wrapper.querySelector('img'); 24 var videoUrl = img.getAttribute('data-video-url'); 25 var videoContainer = wrapper.querySelector('.video-container'); 26 var caption = photoAndCaption.querySelector('.postDetailImageCaption'); 27 28 if (!videoUrl) { 29 console.log('No video URL found'); 30 return; 31 } 32 33 // Extract YouTube video ID from various URL formats 34 var videoId = extractYouTubeId(videoUrl); 35 36 if (!videoId) { 37 console.log('Could not extract YouTube video ID from:', videoUrl); 38 return; 39 } 40 41 // Create YouTube embed URL 42 var embedUrl = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1&rel=0&modestbranding=1'; 43 var iframe = '<iframe src="' + embedUrl + '" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>'; 44 45 // Start smooth transition: fade out image, overlay, and caption simultaneously 46 var overlay = wrapper.querySelector('.article-video-overlay'); 47 48 // Use vanilla JS fade out 49 fadeOut(img, 300); 50 if (overlay) fadeOut(overlay, 300); 51 if (caption) fadeOut(caption, 300); 52 53 // After everything fades out completely, prepare and show video 54 setTimeout(function() { 55 videoContainer.classList.add('show'); 56 videoContainer.innerHTML = iframe; 57 videoContainer.style.display = 'none'; 58 fadeIn(videoContainer, 400); 59 }, 300); 60 }); 61 }); 62} 63 64function extractYouTubeId(url) { 65 // Handle various YouTube URL formats 66 var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/; 67 var match = url.match(regExp); 68 return (match && match[7].length == 11) ? match[7] : false; 69} 70 71// Vanilla JS fade out function 72function fadeOut(element, duration) { 73 if (!element) return; 74 75 var opacity = 1; 76 var interval = 10; 77 var gap = interval / duration; 78 79 element.style.opacity = opacity; 80 81 var fading = setInterval(function() { 82 opacity -= gap; 83 84 if (opacity <= 0) { 85 opacity = 0; 86 element.style.display = 'none'; 87 clearInterval(fading); 88 } 89 90 element.style.opacity = opacity; 91 }, interval); 92} 93 94// Vanilla JS fade in function 95function fadeIn(element, duration) { 96 if (!element) return; 97 98 var opacity = 0; 99 var interval = 10; 100 var gap = interval / duration; 101 102 element.style.opacity = opacity; 103 element.style.display = 'block'; 104 105 var fading = setInterval(function() { 106 opacity += gap; 107 108 if (opacity >= 1) { 109 opacity = 1; 110 clearInterval(fading); 111 } 112 113 element.style.opacity = opacity; 114 }, interval); 115}
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.