1/* JS for preset "Menu V2" */ 2(function() { 3 $(function() { 4 $('.menu-wrapper').each(function() { 5 initMenu($(this)) 6 }); 7 }); 8 9 // Make :active pseudo classes work on iOS 10 document.addEventListener("touchstart", function() {}, false); 11 12 var initMenu = function($menuWrapper) { 13 var $body = $('body'); 14 var $menu = $('.ed-menu', $menuWrapper); 15 var $menuLinks = $('a', $menu); 16 var $menuTrigger = $('.menu-trigger', $menuWrapper); 17 var $banner = $('.banner').first(); 18 19 var menuWrapperHeight = $menuWrapper.outerHeight(); 20 var bannerHeight = $banner.length ? $banner.outerHeight() : 0; 21 var smoothScrollOffset = 20; 22 23 toggleClassOnClick($body.add($menu), $menuTrigger, null, 'open open-menu'); // Keep open on $menu for backward compatibility 24 activateSmoothScroll($menuLinks.add($('.scroll a')), smoothScrollOffset); 25 addClassOnVisibleLinkTargets($menuLinks, 'active', 2 / 3); 26 handleSticky($menuWrapper, 'sticky', $banner); 27 }; 28 29 /** 30 * Observe element's height changes and reload the initMenu() function 31 * 32 * @param {HTMLElement} elm Element to observe 33 * @param {function} callback to call when elmement's height changed 34 */ 35 var observeHeightChange = function(elm, callback) { 36 if (!('ResizeObserver' in window) || elm == null) return; 37 38 var ro = new ResizeObserver(callback); 39 ro.observe(elm); 40 } 41 42 /** 43 * Toggles class on a target when a trigger is clicked 44 * 45 * @param {jQuery} $target The target to apply the CSS class to 46 * @param {jQuery} $trigger The Trigger 47 * @param {jQuery} $closeTrigger Optional close trigger 48 * @param {string} cssClass CSS Class to toggle on the target 49 */ 50 var toggleClassOnClick = function($target, $trigger, $closeTrigger, cssClass) { 51 52 // Reset in case class "open" was saved accidentally 53 $target.removeClass(cssClass); 54 $trigger.removeClass(cssClass); 55 56 // Click on trigger toggles class "open" 57 $trigger.off('.toggle').on('click.toggle', function() { 58 $(this).toggleClass(cssClass); 59 $target.toggleClass(cssClass); 60 }); 61 62 // Close target when link inside is clicked 63 $target.find('a').click(function() { 64 $target.removeClass(cssClass); 65 $trigger.removeClass(cssClass); 66 }); 67 68 if (!$closeTrigger || !$closeTrigger.length) { 69 return; 70 } 71 72 $closeTrigger.click(function() { 73 $target.removeClass(cssClass); 74 $trigger.removeClass(cssClass); 75 }); 76 }; 77 78 /** 79 * Smooth scroll to link targets 80 * 81 * @param {jQuery} $scrollLinks The links 82 * @param {jQuery} scrollOffset Offset to subtract from the scroll target position (e.g. for fixed positioned elements like a menu) 83 */ 84 var activateSmoothScroll = function($scrollLinks, scrollOffset) { 85 if (typeof scrollOffset === 'undefined') { 86 scrollOffset = 0; 87 } 88 89 var determineTarget = function($trigger, hash) { 90 if (hash == '#!next') { 91 return $trigger.closest('.ed-element').next(); 92 } 93 94 return $(hash); 95 } 96 97 $scrollLinks.click(function(e) { 98 var $target = determineTarget($(this), this.hash); 99 if (!$target.length) return; 100 e.preventDefault(); 101 102 viewport.scrollTo($target, 'top', 500, 0); 103 104 }); 105 }; 106 107 /** 108 * We are using the fill property on an element to pass user's choices from CSS to JavaScript 109 * 110 * @param {jQuery} $element 111 */ 112 var getStickyMode = function($element) { 113 var fillValue = getComputedStyle($element[0]).fill; 114 115 return fillValue === 'rgb(255, 0, 0)' ? 116 'sticky_banner' : 117 fillValue === 'rgb(0, 255, 0)' ? 118 'sticky_menu' : 119 fillValue === 'rgb(0, 0, 255)' ? 120 'sticky_instant' : 121 fillValue === 'rgb(255, 255, 255)' ? 122 'sticky_reverse' : 123 'sticky_none'; 124 }; 125 126 /** 127 * Adds a class to an element when not currently visible 128 * 129 * @param {jQuery} $element The element to handle stickyness for 130 * @param {string} cssClass The actual CSS class to be applied to the element when it's above a certain scroll position 131 * @param {jQuery} $banner A banner to reference the scroll position to 132 */ 133 var handleSticky = function($element, cssClass, $banner) { 134 var triggerPos = 0, 135 offset = 0; 136 var menuWrapperHeight = $element.outerHeight(); 137 var mode; 138 var prevScroll = 0; 139 $element.removeClass(cssClass); 140 var updateOffset = function() { 141 mode = getStickyMode($element); 142 if (!$element.hasClass(cssClass)) { 143 offset = $element.offset().top; 144 menuWrapperHeight = $element.outerHeight(); 145 } 146 if (mode === 'sticky_banner' && !$banner.length) { 147 mode = 'sticky_menu'; 148 } 149 if (mode === 'sticky_banner') { 150 triggerPos = $banner.offset().top + ($banner.length ? $banner.outerHeight() : $element.outerHeight()); 151 } 152 if (mode === 'sticky_menu' || mode === 'sticky_reverse') { 153 triggerPos = offset + $element.outerHeight(); 154 } 155 if (mode === 'sticky_instant') { 156 triggerPos = offset + 1; 157 } 158 } 159 viewport.observe('resize', updateOffset); 160 viewport.observe('animation.end', updateOffset); 161 observeHeightChange($element[0], updateOffset); 162 updateOffset(); 163 164 var toggleSpacer = function(toggle) { 165 document.body.style.setProperty('--spacer-height', toggle ? menuWrapperHeight + 'px' : ''); 166 }; 167 168 var handleScroll = function() { 169 if (!$element.length || mode === 'sticky_none') return; 170 171 var isReverse = mode === 'sticky_reverse', 172 curScroll = viewport.getScrollTop(); 173 174 if (triggerPos <= curScroll && (!isReverse || prevScroll > curScroll)) { 175 $element.addClass(cssClass); 176 toggleSpacer(true); 177 } else { 178 $element.removeClass(cssClass); 179 toggleSpacer(false); 180 } 181 182 prevScroll = curScroll; 183 }; 184 viewport.observe('scroll', handleScroll); 185 handleScroll(); 186 }; 187 188 /** 189 * Adds a class to links whose target is currently inside the viewport 190 * 191 * @param {jQuery} $links Link(s) to be observed 192 * @param {string} cssClass CSS Class to be applied 193 * @param {float} sectionViewportRatio Ratio by which the target should be within the viewport 194 */ 195 var addClassOnVisibleLinkTargets = function($links, cssClass, sectionViewportRatio) { 196 if (typeof sectionViewportRatio === 'undefined') { 197 sectionViewportRatio = 1 / 2; 198 } 199 200 var menuTargets = []; 201 var activeLink = $links.filter('.active:not(.wv-link-elm)').eq(0); 202 203 var links = $links.filter(function() { 204 var $target = $(this.hash); 205 if (!$target.length) { 206 return false;
207 } 208 209 // Cache offset position to improve performance (update on resize) 210 var updateOffset = function() { 211 $target.data('offset', $target.offset().top); 212 }; 213 214 viewport.observe('resize', updateOffset); 215 viewport.observe('animation.end', updateOffset); 216 updateOffset(); 217 218 menuTargets.push($target); 219 return true; 220 }); 221 222 // No hash links found, so don't handle it at all 223 if (!links.length) { 224 return; 225 } 226 227 var checkVisibility = function() { 228 $links.removeClass('active'); 229 230 // Check section position reversely 231 for (var i = menuTargets.length - 1; i >= 0; i--) { 232 var desiredScrollPosition = menuTargets[i].data('offset') - viewport.getHeight() * (1 - sectionViewportRatio); 233 if (viewport.getScrollTop() >= desiredScrollPosition && menuTargets[i][0].offsetParent !== null) { 234 links.eq(i).addClass(cssClass); 235 return; 236 } 237 } 238 239 // Fallback to originally active item 240 activeLink.addClass(cssClass); 241 }; 242 243 viewport.observe('scroll', checkVisibility); 244 checkVisibility(); 245 }; 246})(); 247/* End JS for preset "Menu V2" */ 248 249/* JS for preset "Counter" */ 250$(function() { 251 EasingFunctions = { 252 // no easing, no acceleration 253 linear: function(t) { 254 return t 255 }, 256 // accelerating from zero velocity 257 easeInQuad: function(t) { 258 return t * t 259 }, 260 // decelerating to zero velocity 261 easeOutQuad: function(t) { 262 return t * (2 - t) 263 }, 264 // acceleration until halfway, then deceleration 265 easeInOutQuad: function(t) { 266 return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t 267 }, 268 // accelerating from zero velocity 269 easeInCubic: function(t) { 270 return t * t * t 271 }, 272 // decelerating to zero velocity 273 easeOutCubic: function(t) { 274 return (--t) * t * t + 1 275 }, 276 // acceleration until halfway, then deceleration 277 easeInOutCubic: function(t) { 278 return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1 279 }, 280 // accelerating from zero velocity 281 easeInQuart: function(t) { 282 return t * t * t * t 283 }, 284 // decelerating to zero velocity 285 easeOutQuart: function(t) { 286 return 1 - (--t) * t * t * t 287 }, 288 // acceleration until halfway, then deceleration 289 easeInOutQuart: function(t) { 290 return t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t 291 }, 292 // accelerating from zero velocity 293 easeInQuint: function(t) { 294 return t * t * t * t * t 295 }, 296 // decelerating to zero velocity 297 easeOutQuint: function(t) { 298 return 1 + (--t) * t * t * t * t 299 }, 300 // acceleration until halfway, then deceleration 301 easeInOutQuint: function(t) { 302 return t < .5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t 303 } 304 } 305 306 $('[data-count]').each(function() { 307 var duration = 2000; 308 var interval = Math.floor(duration / 60); 309 var steps = Math.ceil(duration / interval); 310 var $target = $(this); 311 var offset = $target.offset().top; 312 var max = $target.data('count'); 313 $target.html('0'); 314 var started = false; 315 316 var startCounter = function() { 317 if (started) return; 318 319 started = true; 320 var i = 0, 321 handle; 322 handle = window.setInterval(function() { 323 $target.html(Math.round(max * EasingFunctions.easeOutCubic(i / steps))); 324 i++; 325 if (i == steps) { 326 $target.html(max); 327 window.clearInterval(handle); 328 } 329 }, interval); 330 }; 331 332 viewport.observe('scroll', function() { 333 if ((viewport.getScrollTop() + viewport.getHeight() / 1) > offset) { 334 startCounter(); 335 } 336 }); 337 }); 338}); 339/* End JS for preset "Counter" */ 340 341/* JS for preset "Content Slider" */ 342$(function() { 343 if (document.body.classList.contains('edit') || document.body.classList.contains('preview')) { 344 return; 345 } 346 347 viewport.promise('api.slick.ready', function() { 348 viewport.jQuery('.content-slider-wrap > .inner').slick({ 349 autoplay: true, 350 arrows: true, 351 prevArrow: '<button type="button" data-role="none" class="slick-prev" tabindex="0" role="button"></button>', 352 nextArrow: '<button type="button" data-role="none" class="slick-next" tabindex="0" role="button"></button>', 353 speed: 300, 354 autoplaySpeed: 3000, 355 dots: false, 356 adaptiveHeight: true, 357 fade: false 358 }); 359 }).requireSlick(); 360}); 361 362/* End JS for preset "Content Slider" */ 363 364/* JS for preset "Back to top button V3" */ 365(function() { 366 var initBackToTop = function() { 367 var $button = $('.back-to-top-button-icon'); 368 369 clickToTop($button); 370 371 // Show back to top only below the fold 372 viewport.observe('scroll', function() { 373 if (viewport.getScrollTop() > (viewport.getHeight() / 3)) { 374 $button.addClass('show'); 375 } else { 376 $button.removeClass('show'); 377 } 378 }); 379 }; 380 381 var clickToTop = function($trigger) { 382 $trigger.removeClass('show'); 383 384 $trigger.click(function(e) { 385 e.preventDefault(); 386 viewport.scrollTo(0, 'top', 500, 0); 387 }); 388 }; 389 390 $(initBackToTop); 391})(); 392/* End JS for preset "Back to top button V3" */ 393 394/* JS for preset "Typewriter" */ 395$(function() { 396 $('.tw-instance').each(function() { 397 typeWriter($(this)) 398 }); 399}); 400 401const typeWriter = function($twInstance) { 402 const $target = $twInstance; 403 const $tw_output = $('.tw-output', $target); 404 let index = 0, 405 isAdding = true 406 let text = []; 407 let current = 0; 408 let animationLoop = 0; 409 let writing_speed, 410 deleting_speed, 411 cursor_ticking, 412 pause, 413 pause_hover, 414 loop, 415 trigger, 416 isHovering; 417 418 // Wait for load 419 const ready = function(callback) { 420 var fn = function() { 421 callback(); 422 }; 423 424 if (window.readyState !== 'loading') { 425 fn(); 426 return; 427 } 428 document.addEventListener('DOMContentLoaded', fn); 429 }; 430 431 // Save the texts 432 $('.text-container .ed-element.ed-text', $target).text(function(index, currentcontent) { 433 text[index] = currentcontent; 434 }); 435 436 const typeWriterAnim = function() { 437 const timeoutId = setTimeout(() => { 438 if (String(timeoutId) !== $twInstance[0].dataset.timeoutId) return; 439 440 if (isHovering && pause_hover) { 441 typeWriterAnim(); 442 return; 443 } 444 445 //Stop animation when editing 446 if ($('.text-container .ed-element.ed-text', $target).hasClass('wv-editing')) { 447 typeWriterAnim(); 448 return; 449 } 450 451 if (text[current] !== undefined) { 452 $tw_output[0].innerHTML = text[current].substring(0, index); 453 } 454 455 if (isAdding) { 456 // adding text 457 if ($tw_output[0].innerHTML.length == 0) { 458 $tw_output.addClass("showAnim"); 459 $tw_output.removeClass("hideCursor"); 460 setTimeout(() => { 461 index++; 462 }, pause); 463 } else { 464 if (index > text[current].length) { 465 // no more text to add 466 isAdding = false;
467 468 // pause before starting deletion 469 $tw_output.addClass("showAnim"); 470 setTimeout(function() { 471 typeWriterAnim(); 472 }, pause); 473 return; 474 } else { 475 // increment index by 1 476 index++; 477 $tw_output.removeClass("showAnim"); 478 } 479 } 480 } else { 481 // removing text 482 if (index === 0) { 483 // blink again 484 $tw_output.addClass("showAnim"); 485 // no more text to remove 486 isAdding = true; 487 488 //Re-parsing settings (edit mode only) 489 if (document.body.classList.contains('edit')) { 490 handleSettingValues(); 491 reParseTexts(); 492 } 493 494 // handle loop 495 if (loop) { 496 current = (current + 1) % text.length; 497 } else { 498 current = (current + 1); 499 // keep looping on edit mode (just for show) 500 if (document.body.classList.contains('edit') && current === text.length) { 501 current = 0; 502 } 503 } 504 } else { 505 //keep last text visible (not on edit mode) 506 if (!document.body.classList.contains('edit')) { 507 if (loop === false && current === text.length - 1) { 508 $tw_output.removeClass("showAnim"); 509 $tw_output.addClass("hideCursor"); 510 return; 511 } 512 } 513 // decrement index by 1 514 index--; 515 $tw_output.removeClass("showAnim"); 516 } 517 } 518 typeWriterAnim(); 519 }, isAdding ? writing_speed : deleting_speed); 520 $twInstance[0].dataset.timeoutId = timeoutId; 521 } 522 523 // Parse and handle the values from preset 524 const handleSettingValues = function() { 525 const values = window.getComputedStyle($target[0], ':before').content.slice(1, -1).split('-'); 526 let ms_pattern = /[ms]\D/; 527 let parsedValues = []; 528 529 values.forEach(value => { 530 if (value === 'false' || value === "true") { 531 parsedValues.push(JSON.parse(value)); 532 } else if (ms_pattern.test(value)) { 533 parsedValues.push(parseFloat(value.replace('ms', ''))) 534 } else { 535 parsedValues.push(parseFloat(value.replace('s', '')) * 1000) 536 } 537 }); 538 539 writing_speed = parsedValues[0]; 540 deleting_speed = parsedValues[1]; 541 cursor_ticking = parsedValues[2]; 542 pause = parsedValues[3]; 543 pause_hover = parsedValues[4]; 544 loop = parsedValues[5]; 545 546 // Handle mouse hover 547 if (pause_hover) { 548 $tw_output[0].addEventListener(('mouseenter'), function() { 549 isHovering = true; 550 }); 551 $tw_output[0].addEventListener(('mouseleave'), function() { 552 isHovering = false; 553 }); 554 555 // Necessary for "pause on hover" (on edit mode) 556 $tw_output.addClass("pauseHover"); 557 } else { 558 $tw_output.removeClass("pauseHover"); 559 } 560 561 } 562 563 const reParseTexts = function() { 564 // Refresh text 565 text = []; 566 567 $('.text-container .ed-element.ed-text', $target).each(function(index, currentcontent) { 568 text[index] = $(currentcontent).text(); 569 }); 570 } 571 572 handleSettingValues(); 573 574 /** 575 * Get the trigger value 576 * We are using the fill property on an element to pass user's choices from CSS to JavaScript 577 * 578 * @param {jQuery} $element 579 */ 580 const getTrigger = function($element) { 581 let triggerValue = getComputedStyle($element[0]).fill; 582 583 return triggerValue === 'rgb(0, 255, 0)' ? 584 'scroll' : 585 'load'; 586 }; 587 588 //Play animation on "scroll into element" 589 const animationObserver = new IntersectionObserver((entries, observer) => { 590 entries.forEach(entry => { 591 if (entry.isIntersecting) { 592 animationLoop += 1; 593 if (animationLoop <= 1) { 594 typeWriterAnim(); 595 } 596 } 597 }) 598 }, { 599 root: document.window, 600 rootMargin: "0px", 601 }); 602 603 //Start animation 604 ready(function() { 605 606 //Initialize values if needed 607 writing_speed = isNaN(writing_speed) ? 200 : writing_speed 608 deleting_speed = isNaN(deleting_speed) ? 100 : deleting_speed 609 cursor_ticking = isNaN(cursor_ticking) ? 200 : cursor_ticking 610 pause = isNaN(pause) ? 500 : pause 611 pause_hover === undefined ? pause_hover = false : pause_hover; 612 loop === undefined ? loop = true : loop; 613 614 trigger = getTrigger($tw_output); 615 616 if (trigger === 'scroll') { 617 if (!document.body.classList.contains('edit')) { 618 animationObserver.observe($tw_output[0]); 619 } else { 620 typeWriterAnim(); 621 } 622 } 623 if (trigger === 'load') { 624 typeWriterAnim(); 625 } 626 }); 627}; 628/* End JS for preset "Typewriter" */
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.