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 141 var toggleSpacer = function(toggle) { 142 document.body.style.setProperty('--spacer-height', toggle ? menuWrapperHeight + 'px' : ''); 143 }; 144 145 var handleScroll = function() { 146 if (!$element.length || mode === 'sticky_none') return; 147 148 var isReverse = mode === 'sticky_reverse', 149 curScroll = viewport.getScrollTop(); 150 151 if (triggerPos <= curScroll && (!isReverse || prevScroll > curScroll)) { 152 $element.addClass(cssClass); 153 toggleSpacer(true); 154 } else { 155 $element.removeClass(cssClass); 156 toggleSpacer(false); 157 } 158 159 prevScroll = curScroll; 160 }; 161
162 var updateOffset = function() { 163 mode = getStickyMode($element); 164 menuWrapperHeight = $element.outerHeight(); 165 if (!$element.hasClass(cssClass)) { 166 offset = $element.offset().top; 167 } 168 if (mode === 'sticky_banner' && !$banner.length) { 169 mode = 'sticky_menu'; 170 } 171 if (mode === 'sticky_banner') { 172 triggerPos = $banner.offset().top + ($banner.length ? $banner.outerHeight() : $element.outerHeight()); 173 } 174 if (mode === 'sticky_menu' || mode === 'sticky_reverse') { 175 triggerPos = offset + $element.outerHeight(); 176 } 177 if (mode === 'sticky_instant') { 178 triggerPos = offset; 179 } 180 181 handleScroll(); 182 } 183 184 viewport.observe('resize', updateOffset); 185 viewport.observe('animation.end', updateOffset); 186 observeHeightChange($element[0], updateOffset); 187 updateOffset(); 188 189 viewport.observe('scroll', handleScroll); 190 handleScroll(); 191 }; 192 193 /** 194 * Adds a class to links whose target is currently inside the viewport 195 * 196 * @param {jQuery} $links Link(s) to be observed 197 * @param {string} cssClass CSS Class to be applied 198 * @param {float} sectionViewportRatio Ratio by which the target should be within the viewport 199 */ 200 var addClassOnVisibleLinkTargets = function($links, cssClass, sectionViewportRatio) { 201 if (typeof sectionViewportRatio === 'undefined') { 202 sectionViewportRatio = 1 / 2; 203 } 204 205 var menuTargets = []; 206 var activeLink = $links.filter('.active:not(.wv-link-elm)').eq(0); 207 208 var links = $links.filter(function() { 209 var $target = $(this.hash); 210 if (!$target.length) { 211 return false; 212 } 213 214 // Cache offset position to improve performance (update on resize) 215 var updateOffset = function() { 216 $target.data('offset', $target.offset().top); 217 }; 218 219 viewport.observe('resize', updateOffset); 220 viewport.observe('animation.end', updateOffset); 221 updateOffset(); 222 223 menuTargets.push($target); 224 return true; 225 }); 226 227 // No hash links found, so don't handle it at all 228 if (!links.length) { 229 return; 230 } 231 232 var checkVisibility = function() { 233 $links.removeClass('active'); 234 235 // Check section position reversely 236 for (var i = menuTargets.length - 1; i >= 0; i--) { 237 var desiredScrollPosition = menuTargets[i].data('offset') - viewport.getHeight() * (1 - sectionViewportRatio); 238 if (viewport.getScrollTop() >= desiredScrollPosition && menuTargets[i][0].offsetParent !== null) { 239 links.eq(i).addClass(cssClass); 240 return; 241 } 242 } 243 244 // Fallback to originally active item 245 activeLink.addClass(cssClass); 246 }; 247 248 viewport.observe('scroll', checkVisibility); 249 checkVisibility(); 250 }; 251})(); 252/* End JS for preset "Menu V2" */ 253 254/* JS for preset "Counter V2" */ 255$(function() { 256 EasingFunctions = { 257 // no easing, no acceleration 258 linear: function(t) { 259 return t 260 }, 261 // accelerating from zero velocity 262 easeInQuad: function(t) { 263 return t * t 264 }, 265 // decelerating to zero velocity 266 easeOutQuad: function(t) { 267 return t * (2 - t) 268 }, 269 // acceleration until halfway, then deceleration 270 easeInOutQuad: function(t) { 271 return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t 272 }, 273 // accelerating from zero velocity 274 easeInCubic: function(t) { 275 return t * t * t 276 }, 277 // decelerating to zero velocity 278 easeOutCubic: function(t) { 279 return (--t) * t * t + 1 280 }, 281 // acceleration until halfway, then deceleration 282 easeInOutCubic: function(t) { 283 return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1 284 }, 285 // accelerating from zero velocity 286 easeInQuart: function(t) { 287 return t * t * t * t 288 }, 289 // decelerating to zero velocity 290 easeOutQuart: function(t) { 291 return 1 - (--t) * t * t * t 292 }, 293 // acceleration until halfway, then deceleration 294 easeInOutQuart: function(t) { 295 return t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t 296 }, 297 // accelerating from zero velocity 298 easeInQuint: function(t) { 299 return t * t * t * t * t 300 }, 301 // decelerating to zero velocity 302 easeOutQuint: function(t) { 303 return 1 + (--t) * t * t * t * t 304 }, 305 // acceleration until halfway, then deceleration 306 easeInOutQuint: function(t) { 307 return t < .5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t 308 } 309 } 310 311 $('[data-count]').each(function() { 312 var $target = $(this); 313 var offset = 0; 314 315 var duration = 2000; 316 var interval = Math.floor(duration / 60); 317 var steps = Math.ceil(duration / interval); 318 var max = $target.data('count'); 319 320 var run = false, handle; 321 322 // Cache offset position to improve performance (update on resize) 323 var updateOffset = function() { 324 offset = $target.offset().top + $target.height()/2; 325 }; 326 viewport.observe('resize', updateOffset); 327 viewport.observe('animation.end', updateOffset); 328 updateOffset(); 329 330 var resetCounter = function() { 331 $target.html('0'); 332 run = false;
333 }; 334 335 var finishCounter = function() { 336 $target.html(max); 337 window.clearInterval(handle); 338 }; 339 340 var startCounter = function() { 341 if (run) return; 342 343 run = true; 344 var i = 0; 345 handle = window.setInterval(function() { 346 var newCount = Math.round(max * EasingFunctions.easeOutCubic(++i / steps)); 347 if (newCount >= max) { 348 return finishCounter(); 349 } 350 $target.html(newCount); 351 }, interval); 352 }; 353 354 var checkVisiblity = function() { 355 var t = viewport.getScrollTop(); 356 var h = viewport.getHeight(); 357 if (t < offset && offset < t+h) { 358 !run && startCounter(); 359 } else { 360 run && resetCounter(); 361 } 362 }; 363 364 viewport.observe('scroll', checkVisiblity); 365 checkVisiblity(); 366 }); 367}); 368/* End JS for preset "Counter V2" */ 369 370/* JS for preset "Cookie Bar V2" */ 371$(function() { 372 if (!$('body').is('.edit')) { 373 $('.cookie-close').click(function(e) { 374 e.preventDefault(); 375 $('.cookie-bar').hide(); 376 createCookie('cookieBar', true, 0.5); 377 }); 378 } 379 380 var preview = false; 381 382 var listener = function() { 383 if (!preview && document.body.classList.contains('preview')) { 384 console.log("entering preview"); 385 preview = true; 386 } else if (preview && !document.body.classList.contains('preview')) { 387 console.log("leaving preview"); 388 $('.cookie-bar').show(); 389 preview = false; 390 } 391 requestAnimationFrame(listener); 392 }; 393 394 requestAnimationFrame(listener); 395 396 if (document.body.classList.contains('edit') || document.body.classList.contains('preview')) { 397 return; 398 } 399 400 // Cookie bar 401 if (readCookie('cookieBar') !== null) { 402 $('.cookie-bar').hide(); 403 } else { 404 $('.cookie-bar').show(); 405 } 406 407 function readCookie(name) { 408 var nameEQ = name + "="; 409 var ca = document.cookie.split(';'); 410 for (var i = 0; i < ca.length; i++) { 411 var c = ca[i]; 412 while (c.charAt(0) == ' ') c = c.substring(1, c.length); 413 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); 414 } 415 return null; 416 } 417 418 function createCookie(name, value, days) { 419 if (days) { 420 var date = new Date(); 421 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); 422 var expires = "; expires=" + date.toGMTString(); 423 } else var expires = ""; 424 document.cookie = name + "=" + value + expires + "; path=/"; 425 } 426}); 427 428/* End JS for preset "Cookie Bar V2" */
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.