1'use strict'; 2 3function Utils() { } 4 5Utils.prototype = { 6 constructor: Utils, 7 isElementInView: function (element, fullyInView) { 8 if (!element || !window.jQuery) { 9 return false; 10 } 11 var $el = $(element); 12 if ($el.length === 0) { 13 return false; 14 } 15 var pageTop = $(window).scrollTop(); 16 var pageBottom = pageTop + $(window).height(); 17 var elementTop = $el.offset().top; 18 var elementBottom = elementTop + $el.height(); 19 20 if (fullyInView === true) { 21 return (pageTop < elementTop) && (pageBottom > elementBottom); 22 } else { 23 return (elementTop <= pageBottom) && (elementBottom >= pageTop); 24 } 25 } 26}; 27 28var utils = new Utils(); 29 30function loadYtScript() { 31 var tag = document.createElement('script'); 32 tag.src = "https://www.youtube.com/iframe_api"; 33 var firstScriptTag = document.getElementsByTagName('script')[0]; 34 if (firstScriptTag && firstScriptTag.parentNode) { 35 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 36 } 37} 38 39// Global player reference expected by YouTube API 40var player = null; 41var paused = true; 42var isMute = false; 43var firstPlay = true; 44var intervalId = null; 45var lastReportedPercent = 0; // store last percent sent to dataLayer (integer multiple of 10) 46 47function safeDataLayer() { 48 window.dataLayer = window.dataLayer || []; 49 return window.dataLayer; 50} 51 52function pushProgressIfNeeded(percentFloat) { 53 var percent = Math.floor(percentFloat); 54 // only report at 10%, 20%, ... 55 var bucket = Math.floor(percent / 10) * 10; 56 if (bucket > 0 && bucket !== lastReportedPercent) { 57 lastReportedPercent = bucket; 58 var dl = safeDataLayer(); 59 dl.push({ 60 'event': 'video_progress', 61 'video_progress': bucket + "%", 62 'content_name': 'Welcome to France Channel!', 63 'video_type': 'ad', 64 'video_url': 'https://www.youtube.com/watch?v=vyVeD3DYdzs', 65 'section_header': undefined, 66 'section_order': 2 67 }); 68 } 69} 70 71function checkPlayerStatus() { 72 if (!player || typeof player.getDuration !== 'function' || typeof player.getCurrentTime !== 'function') { 73 return; 74 } 75 76 try { 77 var duration = player.getDuration() || 0; 78 var elapsed = player.getCurrentTime() || 0; 79 80 if (duration <= 0) { 81 return; 82 } 83 84 var percent = (elapsed / duration) * 100; 85 // avoid NaN 86 if (isFinite(percent)) { 87 pushProgressIfNeeded(percent); 88 } 89 } catch (ex) { 90 // swallow errors to avoid breaking interval loop 91 if (window.console && console.error) { 92 console.error('checkPlayerStatus error', ex); 93 } 94 } 95} 96 97// YouTube API callback 98function onYouTubeIframeAPIReady() { 99 if (!document.getElementById('player')) { 100 return; 101 } 102 103 player = new YT.Player('player', { 104 height: '390', 105 width: '640', 106 videoId: 'vyVeD3DYdzs', 107 playerVars: { 108 'playsinline': 1 109 }, 110 events: { 111 'onReady': onPlayerReady, 112 'onStateChange': onPlayerStateChange 113 } 114 }); 115} 116 117function onPlayerReady(event) { 118 // play only on home page marker present 119 try { 120 if (document.querySelector('.home-2023')) { 121 play(event); 122 } 123 } catch (ex) { 124 // ignore 125 } 126} 127 128function onPlayerStateChange(event) { 129 // YT.PlayerState: -1 unstarted, 0 ended, 1 playing, 2 paused, 3 buffering, 5 cued 130 var state = event.data; 131 var iframeEl = document.querySelector('.yt-embedded'); 132 var inView = utils.isElementInView(iframeEl, false); 133 134 // Clear or start periodic progress checks only for playing state 135 if (state === YT.PlayerState.PLAYING && inView) { 136 paused = false; 137 if (intervalId === null) { 138 intervalId = setInterval(checkPlayerStatus, 4200); 139 } 140 } else if (state === YT.PlayerState.PAUSED || state === YT.PlayerState.ENDED) { 141 paused = true; 142 if (intervalId !== null) { 143 clearInterval(intervalId); 144 intervalId = null; 145 } 146 } 147 148 // user actions (do not fire for the very first automatic start) 149 if (!firstPlay) { 150 var action = ""; 151 if (state === YT.PlayerState.PAUSED) { 152 action = "video paused"; 153 } else if (state === YT.PlayerState.PLAYING) { 154 action = "video resumed"; 155 } else if (state === YT.PlayerState.BUFFERING) { 156 action = "video buffering"; 157 } 158 159 if (action) { 160 try { 161 var duration = (player && typeof player.getDuration === 'function') ? (player.getDuration() || 0) : 0;
162 var elapsed = (player && typeof player.getCurrentTime === 'function') ? (player.getCurrentTime() || 0) : 0; 163 var percent = duration > 0 ? ((elapsed / duration) * 100).toFixed(2) : 0; 164 165 var dl = safeDataLayer(); 166 dl.push({ 167 'event': 'video_user_action', 168 'video_progress': percent, 169 'content_name': 'Welcome to France Channel!', 170 'video_type': 'ad', 171 'video_url': 'https://www.youtube.com/watch?v=vyVeD3DYdzs', 172 'section_header': undefined, 173 'section_order': 2, 174 'video_engagement_action': action 175 }); 176 } catch (ex) { 177 // ignore 178 } 179 } 180 } 181} 182 183function play(event) { 184 if (!event || !event.target) { 185 return; 186 } 187 188 try { 189 // try to unmute and play 190 if (typeof event.target.unMute === 'function') { 191 event.target.unMute(); 192 isMute = false; 193 } 194 if (typeof event.target.playVideo === 'function') { 195 event.target.playVideo(); 196 } 197 198 if (firstPlay) { 199 var dl = safeDataLayer(); 200 dl.push({ 201 'event': 'video_start', 202 'content_name': 'Welcome to France Channel!', 203 'video_type': 'ad', 204 'video_url': 'https://www.youtube.com/watch?v=vyVeD3DYdzs', 205 'section_header': undefined, 206 'section_order': 2 207 }); 208 firstPlay = false; 209 } 210 } catch (ex) { 211 // ignore 212 } 213} 214 215function autoplay() { 216 var iframe = document.querySelector('.yt-embedded'); 217 var inView = utils.isElementInView(iframe, false); 218 219 if (!player || typeof player.playVideo !== 'function') { 220 return; 221 } 222 223 try { 224 if (inView) { 225 // attempt autoplay: mute first (many browsers allow muted autoplay) 226 if (paused) { 227 if (typeof player.mute === 'function') { 228 player.mute(); 229 isMute = true; 230 } 231 if (typeof player.playVideo === 'function') { 232 player.playVideo(); 233 } 234 } 235 236 if (firstPlay) { 237 var dl = safeDataLayer(); 238 dl.push({ 239 'event': 'video_start', 240 'content_name': 'Welcome to France Channel!', 241 'video_type': 'ad', 242 'video_url': 'https://www.youtube.com/watch?v=vyVeD3DYdzs', 243 'section_header': undefined, 244 'section_order': 2 245 }); 246 firstPlay = false; 247 } 248 } else { 249 // pause when out of view 250 if (typeof player.pauseVideo === 'function') { 251 player.pauseVideo(); 252 paused = true; 253 } 254 } 255 } catch (ex) { 256 // ignore 257 } 258} 259 260// expose helpers if needed 261window.loadYtScript = loadYtScript; 262window.autoplayYt = autoplay;
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.