1 2/*! Created by: Udo Schmal | https://www.gocher.me/ */ 3(function() { 4 'use strict'; 5 function youtube(el) { 6 var player, id; 7 // don't send referrer infos to external services 8 if (!document.querySelector('meta[name="referrer"]')) { 9 let meta = document.createElement('meta'); 10 meta.name = 'referrer'; 11 meta.content = 'no-referrer'; 12 document.head.appendChild(meta); 13 } 14 // get YouTube video id 15 if (el.dataset.src && el.dataset.src.length === 11) { 16 id = el.dataset.src; 17 } 18 el.dataset.type = 'youtube'; 19 let containerDiv = el.closest('div[id]'); 20 el.id = (containerDiv && containerDiv.id) ? containerDiv.id + '_' + id : id; 21 // show in popup, other defined target or replace el with player 22 var target = el.dataset.target || el.id; 23 // play video text link 24 var playTextLink = el.parentNode.parentNode.querySelector('[data-type="play"]'); 25 26 // create placeholder background image 27 var individualContent = false; 28 if (el.dataset.poster) { 29 if (el.dataset.poster === 'none') { 30 individualContent = true; 31 } else { 32 el.style.backgroundImage = "url('" + el.dataset.poster + "')"; 33 } 34 } else { 35 el.style.backgroundImage = "url('https://img.youtube.com/vi/" + id + "/sddefault.jpg')"; 36 } 37 if (el.dataset.width && el.dataset.height) { 38 el.style.width = el.dataset.width + 'px'; 39 el.style.height = el.dataset.height + 'px'; 40 el.style.paddingTop = '0'; 41 } 42 // show placeholder title 43 if (el.title) { 44 let title = document.createElement('div'); 45 title.className = 'title'; 46 title.appendChild(document.createTextNode(el.title)); 47 el.appendChild(title); 48 } 49 // show placeholder youtube like play button 50 if (!individualContent) { 51 var play = document.createElement('div'); 52 play.className = 'play'; 53 el.appendChild(play); 54 } 55 56 // create popup 57 function createPopup() { 58 var overlay = document.createElement('div'); 59 overlay.id = 'overlay'; 60 document.body.appendChild(overlay); 61 var content = document.createElement('div'); 62 content.id = 'popup-content'; 63 overlay.appendChild(content); 64 var close = document.createElement('span'); 65 close.className = 'popup-close'; 66 overlay.appendChild(close); 67 close.addEventListener('click', function (event) { 68 player.stopVideo(); 69 document.body.removeChild(overlay); 70 }); 71 return 'popup-content'; 72 } 73 // youtube player API 74 function onPlayerReady(event) { 75 event.target.playVideo(); 76 } 77 function onPlayerStateChange(event) { 78 if (event.data == window.YT.PlayerState.ENDED) { 79 player.stopVideo(); 80 document.body.removeChild(overlay); 81 } 82 } 83 // create youtube player 84 function createPlayer() { 85 window.YT.ready(function() { 86 var dest, obj = { 87 videoId: id, 88 host: 'https://www.youtube-nocookie.com', 89 events: { 90 'onReady': onPlayerReady 91 } 92 }; 93 var sizes = [ 94 { width: '426', height: '240' }, 95 { width: '640', height: '360' }, 96 { width: '854', height: '480' }, 97 { width: '1280', height: '720' }, 98 { width: '1920', height: '1080' } 99 ]; 100 if (target === 'popup') { 101 dest = createPopup(); 102 obj.events['onStateChange'] = onPlayerStateChange; 103 for(let i = 0; i < sizes.length; i++) { 104 if (sizes[i].width <= window.innerWidth) { 105 obj.height = sizes[i].height; 106 obj.width = sizes[i].width; 107 } else { 108 break; 109 } 110 } 111 } else { 112 dest = target; 113 for(let i = 0; i < sizes.length; i++) { 114 if (sizes[i].width >= el.offsetWidth) { 115 obj.height = sizes[i].height; 116 obj.width = sizes[i].width; 117 break; 118 } 119 } 120 } 121 // create YouTube player 122 player = new window.YT.Player(dest, obj); 123 }); 124 } 125 // show placeholder cookiebot preferences message 126 if (typeof(Cookiebot) !== 'undefined') { 127 let external = document.createElement('div'); 128 external.className = 'cookiebot'; 129 let language = document.documentElement.lang || 'en'; 130 let txt; 131 switch (language.substring(0, 2)) { 132 case 'de': txt = 'Bitte akzeptieren sie die Präferenzen-Cookies um dieses Video zu sehen.'; break; 133 case 'fr': txt = 'Veuillez accepter les préférences-cookies pour regarder cette vidéo.'; break; 134 case 'it': txt = 'Si prega di accettare i cookie delle preferenze per guardare questo video.'; break; 135 default: txt = 'Please accept preferences-cookies to wat
135ch this video.'; break; 136 } 137 external.appendChild(document.createTextNode(txt)); 138 let externalWrapper = null; 139 if (individualContent) { 140 externalWrapper = document.createElement('div'); 141 externalWrapper.className = 'cookiebotWrapper'; 142 externalWrapper.addEventListener('click', function (event) { 143 // show cookie settings 144 CookieConsent.renew(); 145 event.stopPropagation(); 146 }); 147 externalWrapper.appendChild(external); 148 el.appendChild(externalWrapper); 149 } else { 150 external.addEventListener('click', function (event) { 151 // show cookie settings 152 CookieConsent.renew(); 153 event.stopPropagation(); 154 }); 155 el.appendChild(external); 156 } 157 // check cookiebot consent 158 if (!Cookiebot.consent.preferences) { 159 console.log('cookiebot: preferences not accepted'); 160 external.style.display = 'block'; 161 window.addEventListener('CookiebotOnAccept', function (e) { 162 if (Cookiebot.consent.preferences) { 163 console.log('cookiebot: preferences accepted'); 164 // reload page because cookiebot breaks youtube www-widgetapi.js 165 localStorage.setItem('cookiebot-scroll', window.scrollY); 166 location.href = location.href; 167 external.style.display = 'none'; 168 } else{ 169 console.log('cookiebot: preferences not accepted'); 170 external.style.display = 'block'; 171 } 172 }); 173 if (playTextLink) { 174 playTextLink.classList.add('inactive'); 175 } 176 } else { 177 console.log('cookiebot: preferences accepted'); 178 if (externalWrapper) { 179 externalWrapper.style.display = 'none'; 180 } 181 external.style.display = 'none'; 182 if (playTextLink) { 183 playTextLink.addEventListener('click', load); 184 playTextLink.classList.add('active'); 185 } 186 } 187 } else { 188 let external = document.createElement('div'); 189 external.className = 'external'; 190 let language = document.documentElement.lang || 'en'; 191 let txt; 192 switch (language.substr(0,2)) { 193 case 'de': txt = 'Lädt externe Inhalte von YouTube'; break; 194 case 'fr': txt = 'Charger du contenu externe à partir de YouTube'; break; 195 case 'it': txt = 'Carica contenuti esterni da YouTube'; break; 196 case 'es': txt = 'Cargar contenido externo de YouTube'; break; 197 default: txt = 'Load external Content from YouTube'; break; 198 } 199 external.appendChild(document.createTextNode(txt)); 200 let externalWrapper = null; 201 if (individualContent) { 202 externalWrapper = document.createElement('div'); 203 externalWrapper.className = 'cookiebotWrapper'; 204 externalWrapper.appendChild(external); 205 el.appendChild(externalWrapper); 206 } else { 207 el.appendChild(external); 208 } 209 if (playTextLink) { 210 playTextLink.addEventListener('click', load); 211 playTextLink.classList.add('active'); 212 } 213 } 214 // load youtube external content 215 function load(event) { 216 event.stopPropagation(); 217 console.log('load: youtube external content'); 218 // init once 219 if (!document.getElementById('YouTubeApi')) { 220 // load YouTube API 221 var script = document.createElement('script'); 222 script.id = 'YouTubeApi'; 223 script.src = 'https://www.youtube.com/iframe_api'; 224 document.head.appendChild(script); 225 script.addEventListener('load', createPlayer); 226 } else { 227 createPlayer(); 228 } 229 if (target !== 'popup') { 230 // remove placeholder click event 231 play.removeEventListener('click', load); 232 } 233 } 234 if (individualContent) { 235 el.addEventListener('click', load); 236 } else { 237 play.addEventListener('click', load); 238 } 239 } 240 241 // Viewport prototype to trigger event if element moves into viewport the fist time 242 function Viewport(els, callback) { 243 this.els = els; 244 this.callback = callback; 245 this.active = false; 246 var self = this; 247 var hidden = []; 248 function alreadyObserved(el) { 249 for(var i=0; i<hidden.length; i++) { 250 if (el === hidden[i]) { 251 return true; 252 } 253 } 254 return false;
255 } 256 for (var i=0; i < els.length; i++) { 257 var el = els[i]; 258 // parent must have position attribute for getBoundingClientRect 259 let properties = window.getComputedStyle(el.parentNode); 260 if (!properties.getPropertyValue('position')) { 261 el.parentNode.style.position = 'relative'; 262 while(el && el.tagName.toLowerCase() !== 'body') { 263 if (window.getComputedStyle(el).display === "none") { 264 if (!alreadyObserved(el)) { 265 hidden.push(el); 266 var observer = new MutationObserver(function(mutations) { 267 if (mutations[0].target.style.display !== 'none') { 268 self.handleEvent(); 269 } 270 }); 271 observer.observe(el, { attributes: true }); 272 break; 273 } 274 } 275 el = el.parentNode; 276 } 277 } 278 } 279 this.handleEvent.bind(this); 280 // is already in viewport after dom ready 281 function ready(f){ 282 /complete|loaded/i.test(document.readyState) ? f() : setTimeout(function(){ready(f);},9); 283 } 284 ready(function(){self.handleEvent();}); 285 // add event listener to scroll event to check visibility change 286 document.addEventListener('scroll', this, true); 287 window.addEventListener('resize', this, true); 288 window.addEventListener('orientationchange', this, true); 289 290 } 291 292 Viewport.prototype = { 293 // check if element is visible 294 isVisible: function (el) { 295 var style = window.getComputedStyle(el); 296 return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length); 297 }, 298 // check if element is in viewport 299 isInViewport: function (el) { 300 var bounding = el.getBoundingClientRect(); 301 return ( 302 bounding.bottom >= 0 && 303 bounding.right >= 0 && 304 bounding.top <= (window.innerHeight || document.documentElement.clientHeight) && 305 bounding.left <= (window.innerWidth || document.documentElement.clientWidth) 306 ); 307 }, 308 // handle the visibility check and the resulting action 309 handleEvent: function () { 310 if (this.active === false) { 311 this.active = true; 312 for (var i=0; i < this.els.length; i++) { 313 if (this.isInViewport(this.els[i]) && this.isVisible(this.els[i])) { 314 this.callback(this.els[i]); 315 } 316 } 317 this.active = false; 318 } 319 } 320 }; 321 322 function ready(f){ 323 /complete|loaded/i.test(document.readyState) ? f() : setTimeout(function(){ready(f);},9); 324 } 325 ready(function() { 326 // scroll to position after reload page because cookiebot breaks youtube www-widgetapi.js 327 var scrollto = localStorage.getItem('cookiebot-scroll') || ''; 328 if (scrollto !== '') { 329 window.scroll(0, scrollto); 330 localStorage.setItem('cookiebot-scroll', ''); 331 } 332 // activate viewport for youtube loading 333 var media = document.querySelectorAll('.youtube[data-src]'); 334 if (media.length > 0) { 335 if ("IntersectionObserver" in window) { 336 // create intersection observer 337 let lazyobserver = new IntersectionObserver(function(entries, observer) { 338 for (var i=0; i < entries.length; i++) { 339 if (entries[i].isIntersecting) { 340 youtube(entries[i].target); 341 lazyobserver.unobserve(entries[i].target); 342 } 343 } 344 }, 345 { 346 threshold: [0.1], 347 // Set a minimum delay between notifications 348 delay: 100 349 }); 350 // start observing 351 for (var i=0; i < media.length; i++) { 352 lazyobserver.observe(media[i]); 353 } 354 } else { 355 // use eventListeners 356 new Viewport(media, youtube); 357 } 358 } 359 }); 360})();
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.