1/** 2 * Greyd.Blocks Frontend Script for Layout Blocks Background Feature. 3 * 4 * This file is loaded in the frontend only. 5 */ 6(function() { 7 8 jQuery(function() { 9 10 if (typeof $ === 'undefined') $ = jQuery; 11 12 /** 13 * backgrounds and lazyload 14 * split from theme default.js 'icons' function 15 */ 16 greyd.backgrounds.init(); 17 18 /** 19 * lazyload 20 * split from theme default.js 'icons' function 21 * combined with removed 'front-video-lazyload.js' 22 */ 23 greyd.lazyload.init(); 24 25 /** 26 * css animations 27 * refactored from theme default.js 'vc_anim' function 28 */ 29 greyd.cssAnims.init(); 30 31 // console.log("Frontend Backgrounds Script: loaded"); 32 } ); 33 34} )(jQuery); 35 36/** 37 * Backgrounds 38 */ 39function onYouTubeIframeAPIReady() { 40 41 greyd.backgrounds.initYoutubeVideos(); 42 43 /** 44 * Call theme function aswel because the theme's 45 * 'onYouTubeIframeAPIReady' is overwritten by this. 46 */ 47 if (typeof icons !== 'undefined' && 48 typeof icons.initYoutubeVideos === 'function') { 49 icons.initYoutubeVideos() 50 } 51 52} 53greyd.backgrounds = new function() { 54 55 // all backgrounds 56 this.bgs = {}; 57 58 this.init = function() { 59 60 // check for backgrounds 61 if ($('.greyd-background').length == 0) { 62 // console.warn("no backgrounds found"); 63 return; 64 } 65 66 // get all backgrounds 67 var youtubefound = false; 68 $('.greyd-background').each(function() { 69 // get background (or parent) id 70 var id = $(this).attr('id'); 71 var that = $(this); 72 while (typeof id === 'undefined') { 73 // search the next parent with id 74 that = that.parent(); 75 // console.log(that); 76 if (that.length == 0) id = ""; 77 else id = that.attr('id'); 78 } 79 if (id == "") return; 80 81 // get resize behaviour 82 var resize = false; 83 if ($(this).hasClass('bg_full') || $(this).hasClass('bg_window')) 84 resize = true; 85 // get scroll parallax 86 var scroll = []; 87 $('#'+id+' .bg_vparallax').each(function() { 88 scroll.push({ 89 container: this, 90 scroll: 'vparallax', 91 speed: $(this).data('bg_parallax_speed'), 92 enable_mobile: $(this).data('bg_parallax_enable_mobile') 93 }); 94 }); 95 $('#'+id+' .bg_hparallax').each(function() { 96 scroll.push({ 97 container: this, 98 scroll: 'hparallax', 99 speed: $(this).data('bg_parallax_speed'), 100 enable_mobile: $(this).data('bg_parallax_enable_mobile') 101 }); 102 }); 103 // get video 104 var video = false; 105 $('#'+id+' .bg_video').each(function() { 106 video = { 107 src: $(this).children(0).data('bg_video_src'), 108 video_id: $(this).children(0).data('bg_video_id'), 109 video_aspect: $(this).children(0).data('bg_video_ar'), 110 container_id: $(this).children(0).children(0).attr('id'), 111 }; 112 if (video.src == "youtube") youtubefound = true; 113 }); 114 115 // add 116 if (!greyd.backgrounds.bgs[id]) { 117 greyd.backgrounds.bgs[id] = { 118 container: this, 119 resize: resize, 120 scroll: scroll, 121 video: video 122 }; 123 } 124 }); 125 if (youtubefound) { 126 if (typeof YT === 'undefined') { 127 var tag = document.createElement('script'); 128 tag.src = "https://www.youtube.com/iframe_api"; 129 var firstScriptTag = document.getElementsByTagName('script')[0]; 130 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 131 } 132 else this.initYoutubeVideos(); 133 } 134 135 this.addEvents(); 136 // console.log('Backgrounds Script: loaded'); 137 } 138 139 this.initYoutubeVideos = function() { 140 // check all backgrounds 141 for (var id in greyd.backgrounds.bgs) { 142 var bg = greyd.backgrounds.bgs[id]; 143 // check for youtube video 144 if (bg.video && bg.video.src == "youtube") { 145 bg.video.player = new YT.Player(bg.video.container_id, { 146 height: '100%', 147 width: '100%', 148 videoId: bg.video.video_id, 149 playerVars: { 150 autoplay: '1', 151 loop: '1', 152 controls: '0', 153 modestbranding: '1', 154 disablekb: '1' 155 }, 156 events: { 157 'onReady': greyd.backgrounds.onPlayerReady, 158 'onStateChange': greyd.backgrounds.onPlayerStateChange 159 } 160 }); 161 } 162 } 163 } 164 this.onPlayerReady = function(event) { 165 // console.log("player ready"); 166 event.target.mute(); 167 event.target.playVideo(); 168 greyd.backgrounds.resize(); 169 } 170 this.onPlayerStateChange = function(event) { 171 if (event.data == YT.PlayerState.ENDED) { 172 event.target.seekTo(0); 173 event.target.playVideo(); 174 } 175 } 176 177 this.addEvents = function() { 178 // scroll and resize 179 $(window).scroll(this.scroll); 180 $(window).resize(this.resize); 181 this.resize(); 182 } 183 184 this.resize = function () { 185 // console.log("resizing"); 186 for (var id in greyd.backgrounds.bgs) { 187 var bg = greyd.backgrounds.bgs[id]; 188 if (bg.resize) { 189 // console.log("background resizing");
190 greyd.backgrounds.resizeBackground(bg); 191 } 192 if (bg.video) { 193 // console.log("video resizing"); 194 greyd.backgrounds.resizeVideo(bg); 195 } 196 } 197 greyd.backgrounds.scroll(); 198 } 199 this.resizeBackground = function(bg) { 200 // console.log(bg.container); 201 var margin = -($(bg.container).parent()[0].getBoundingClientRect().left); 202 margin += $('body')[0].getBoundingClientRect().left; 203 204 //if the margin is greater than half the window-width, chances are the bg sits outside the viewport 205 if ( Math.abs(parseInt(margin)) * 2 <= window.innerWidth ) { 206 if ( Math.abs(parseInt(margin)) !== 0 ) { 207 $(bg.container).css('left', margin); 208 $(bg.container).css('right', margin); 209 } 210 } 211 } 212 this.resizeVideo = function(bg) { 213 // console.log(bg.video); 214 var pheight = $(bg.container).css('height').replace("px",""); 215 var pwidth = $(bg.container).css('width').replace("px",""); 216 217 var ar = bg.video.video_aspect.split("/"); 218 ar = ar[0]/ar[1]; // ar = 16/9; 219 var height = pheight; 220 var width = height * (ar); 221 var margin_left = margin_top = 0; 222 223 if (width >= pwidth) { 224 margin_left = (pwidth - width) / 2; 225 } 226 else { 227 width = pwidth; 228 height = width / (ar); 229 margin_top = (pheight - height) / 2; 230 } 231 232 // resize 233 var iframe = typeof bg.video.container_id === 'undefined' ? $(bg.container).find('iframe') : $("#"+bg.video.container_id); 234 console.log(iframe); 235 if ( iframe && iframe.length ) { 236 iframe.css('height', height+"px"); 237 iframe.css('width', width+"px"); 238 iframe.css('margin-left', margin_left+"px"); 239 iframe.css('margin-top', margin_top+"px"); 240 } 241 else { 242 setTimeout( function() { 243 iframe = $(bg.container).find('iframe'); 244 // console.log(iframe); 245 bg.video.container_id = iframe.attr('id'); 246 iframe.css('height', height+"px"); 247 iframe.css('width', width+"px"); 248 iframe.css('margin-left', margin_left+"px"); 249 iframe.css('margin-top', margin_top+"px"); 250 }, 100 ); 251 } 252 } 253 254 this.scroll = function () { 255 // console.log("scrolling"); 256 var is_mobile = ($('html').hasClass('ios') || $('html').hasClass('android')); 257 var viewportTop = $(window).scrollTop(); 258 var viewportHeight = $(window).height(); 259 var viewportBottom = viewportTop + viewportHeight; 260 261 for (var id in greyd.backgrounds.bgs) { 262 if (greyd.backgrounds.bgs[id].scroll.length > 0) { 263 // all parallax layers 264 var background = greyd.backgrounds.bgs[id]; 265 for (var i=0; i<background.scroll.length; i++) { 266 // scroll parallax layer 267 var bg = background.scroll[i].container; 268 var scroll = background.scroll[i].scroll; 269 var speed = background.scroll[i].speed; 270 var enable_mobile = background.scroll[i].enable_mobile; 271 if (!is_mobile || (is_mobile && enable_mobile)) { 272 // enable on desktop and check mobile 273 var elementTop = $(bg).offset().top; 274 var elementHeight = $(bg).outerHeight(); 275 if (viewportBottom-elementTop > 0 && viewportTop-elementTop < elementHeight) { 276 // console.log(viewportBottom-elementTop); 277 var delta = (viewportHeight - elementHeight) / 2; 278 var pos = ((viewportBottom-elementTop-elementHeight-delta)*(speed/100.0)); 279 if (scroll == "vparallax") { 280 // vertical parallax 281 if ($(bg).hasClass('div_parallax')) 282 $(bg).children(0).css('transform', 'translateY('+pos.toFixed(2)+'px)'); 283 else 284 $(bg).css('background-position-y', pos.toFixed(2)+'px'); 285 } 286 if (scroll == "hparallax") { 287 // horizontal parallx 288 if ($(bg).hasClass('div_parallax')) 289 $(bg).children(0).css('transform', 'translateX('+pos.toFixed(2)+'px)'); 290 else 291 $(bg).css('background-position-x', pos.toFixed(2)+'px'); 292 } 293 } 294 } 295 296 } 297 } 298 } 299 300 } 301 302} 303 304/** 305 * Lazyloading. 306 * Updated to use intersection observer, no jQuery. 307 * - background images 308 * - videos 309 * - fonts (todo) 310 */ 311greyd.lazyload = new function() { 312 313 this.setup = { 314 lazyload: 'false', 315 }; 316 317 this.observer = false; 318 319 this.init = function() { 320 321 // get setup 322 if (typeof greyd.setup.lazyload !== 'undefined') { 323 this.setup.lazyload = greyd.setup.lazyload; 324 } 325 326 // Stop loading if Lazyloading is disabled and there is no video to load. 327 if (this.setup.lazyload == 'false' && document.querySelectorAll('video[data-src]:not([src])') === 0) return; 328 329 // check for elements to lazyload 330 var elements = document.querySelectorAll('.bg_image:not(.visible), video[data-src]:not([src])'); 331 if (elements.length === 0) { 332 // console.warn("no lazyload elements found"); 333 return; 334 } 335 336 if (!greyd.lazyload.observer) { 337 // define the observer 338 greyd.lazyload.observer = new IntersectionObserver( 339 function onIntersection(entries, opts) { 340 // console.log(entries, opts);
341 entries.forEach(entry => { 342 343 if (entry.isIntersecting) { 344 345 /** 346 * Background image lazy loading. 347 */ 348 if (entry.target.classList.contains('bg_image')) { 349 var bg = entry.target; 350 // console.log(bg); 351 352 if (typeof bg.dataset.srcset !== 'undefined') { 353 // get best img from srcset 354 var srcset = JSON.parse(bg.dataset.srcset); 355 var newset = { 356 src: getComputedStyle(bg, false).backgroundImage.replace('url("', '').replace('")',''), 357 newsrc: '' 358 }; 359 var width = window.screen.width * window.devicePixelRatio; 360 for (var i in srcset) { 361 if (i > width && newset.src != srcset[i]) { 362 newset.newsrc = srcset[i]; 363 break; 364 } 365 } 366 if (newset.newsrc == '' && newset.src != srcset['full']) { 367 newset.newsrc = srcset['full']; 368 } 369 // switch images 370 if (typeof newset.newsrc !== 'undefined' && newset.newsrc != '') { 371 // set image 372 bg.style.backgroundImage = 'url('+newset.newsrc+')'; 373 // load other images with the same src 374 elements.forEach( (element) => { 375 if (!element.classList.contains('visible')) { 376 var src = getComputedStyle(element, false).backgroundImage.replace('url("', '').replace('")',''); 377 if (src == newset.src) { 378 // set image 379 element.style.backgroundImage = 'url('+newset.newsrc+')'; 380 // remove observer 381 element.classList.add('visible'); 382 greyd.lazyload.observer.unobserve(element); 383 } 384 } 385 } ); 386 } 387 } 388 389 // remove from observer 390 bg.classList.add('visible'); 391 greyd.lazyload.observer.unobserve(bg); 392 393 } 394 395 /** 396 * Video lazy loading. 397 * moved from 'front-video-lazyload.js' 398 * 399 * If the property 'preload' is set to 'auto' or 'none' the video 'src' is 400 * lazyloaded by 'data-src' via an IntersectionObserver. 401 * 402 * @link https://web.dev/lazy-loading-video/ 403 * @see render_block() @ greyd_blocks/inc/render.php 404 * 405 * @since 1.2.5 406 */ 407 if ( entry.target.tagName.toLowerCase() == "video" ) { 408 // console.log( "Lazy loading video: ", entry.target.dataset.src ); 409 410 // load entry 411 entry.target.src = entry.target.dataset.src; 412 entry.target.load(); 413 414 // remove from observer 415 delete entry.target.dataset.src; 416 greyd.lazyload.observer.unobserve(entry.target); 417 } 418 419 } 420 421 } ); 422 }, 423 { 424 threshold: 0, // percentage of target's visible area. Triggers "onIntersection" 425 } 426 ); 427 } 428 429 // add all elements to observer 430 elements.forEach( (element) => { 431 greyd.lazyload.observer.observe( element ); 432 } ); 433 434 // console.log('Lazyload Script: loaded'); 435 } 436 437} 438 439 440/** 441 * CSS Animations ported from VC. 442 * Updated to use intersection observer, no jQuery. 443 */ 444greyd.cssAnims = new function() { 445 446 this.observer = false; 447 448 this.init = function() { 449 450 // check for animations 451 var objs = document.querySelectorAll('.animate-when-almost-visible'); 452 if (objs.length === 0) { 453 // console.warn("no css animations found"); 454 return; 455 } 456 457 if (!greyd.cssAnims.observer) { 458 // define the observer 459 greyd.cssAnims.observer = new IntersectionObserver( 460 function onIntersection(entries, opts) { 461 // console.log(entries, opts); 462 entries.forEach(entry => { 463 // triggered class 464 var triggerClass = "start-animation"; 465 if (entry.isIntersecting && !entry.target.classList.contains(triggerClass)) { 466 // console.log("trigger animation") 467 entry.target.classList.add(triggerClass); 468 entry.target.classList.add("animated"); 469 // remove from observer 470 greyd.cssAnims.observer.unobserve(entry.target); 471 } 472 } ); 473 }, 474 { 475 threshold: 0, // percentage of target's visible area. Triggers "onIntersection" 476 } 477 ); 478 } 479 480 // add all elements with css animation to observer 481 objs.forEach( (element) => { 482 greyd.cssAnims.observer.observe( element ); 483 } ); 484 485 // console.log('css Animations Script: loaded'); 486 } 487 488};
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.