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 const initMenu = function($menuWrapper) { 13 const $body = $('body'); 14 const $menu = $('.ed-menu', $menuWrapper); 15 const $menuLinks = $('a', $menu); 16 const $menuTrigger = $('.menu-trigger', $menuWrapper); 17 const $banner = $('.banner').first(); 18 19 const smoothScrollOffset = 20; 20 21 // Set aria attributes 22 $menuTrigger.attr({ 23 'aria-expanded': 'false', 24 'aria-controls': $menu.attr('id'), 25 }); 26 27 toggleClassOnClick($body.add($menu), $menuTrigger, null, 'open open-menu'); // Keep open on $menu for backward compatibility 28 activateSmoothScroll($menuLinks.add($('.scroll a')), smoothScrollOffset); 29 addClassOnVisibleLinkTargets($menuLinks, 'active', 2 / 3); 30 handleSticky($menuWrapper, 'sticky', $banner); 31 }; 32 33 /** 34 * Observe element's height changes and reload the initMenu() function 35 * 36 * @param {HTMLElement} elm Element to observe 37 * @param {function} callback to call when elmement's height changed 38 */ 39 const observeHeightChange = function(elm, callback) { 40 if (!('ResizeObserver' in window) || elm == null) return; 41 42 const ro = new ResizeObserver(callback); 43 ro.observe(elm); 44 } 45 46 /** 47 * Toggles class on a target when a trigger is clicked 48 * 49 * @param {jQuery} $target The target to apply the CSS class to 50 * @param {jQuery} $trigger The Trigger 51 * @param {jQuery} $closeTrigger Optional close trigger 52 * @param {string} cssClass CSS Class to toggle on the target 53 */ 54 const toggleClassOnClick = function($target, $trigger, $closeTrigger, cssClass) { 55 56 // Reset in case class "open" was saved accidentally 57 $target.removeClass(cssClass); 58 $trigger.removeClass(cssClass).attr('aria-expanded', 'false'); 59 60 // Click on trigger toggles class "open" 61 $trigger.off('.toggle').on('click.toggle', function() { 62 const isExpanded = $(this).attr('aria-expanded') === 'true'; 63 $(this).toggleClass(cssClass).attr('aria-expanded', !isExpanded); 64 $target.toggleClass(cssClass); 65 }); 66 67 // Close target when link inside is clicked 68 $target.find('a').click(function() { 69 $target.removeClass(cssClass); 70 $trigger.removeClass(cssClass).attr('aria-expanded', 'false'); 71 }); 72 73 if (!$closeTrigger || !$closeTrigger.length) { 74 return; 75 } 76 77 $closeTrigger.click(function() { 78 $target.removeClass(cssClass); 79 $trigger.removeClass(cssClass).attr('aria-expanded', 'false'); 80 }); 81 }; 82 83 /** 84 * Smooth scroll to link targets 85 * 86 * @param {jQuery} $scrollLinks The links 87 * @param {jQuery} scrollOffset Offset to subtract from the scroll target position (e.g. for fixed positioned elements like a menu) 88 */ 89 const activateSmoothScroll = function($scrollLinks, scrollOffset) { 90 if (typeof scrollOffset === 'undefined') { 91 scrollOffset = 0; 92 } 93 94 const determineTarget = function($trigger, hash) { 95 if (hash == '#!next') { 96 return $trigger.closest('.ed-element').next(); 97 } 98 99 return $(hash); 100 } 101 102 $scrollLinks.click(function(e) { 103 const $target = determineTarget($(this), this.hash); 104 if (!$target.length) return; 105 e.preventDefault(); 106 107 viewport.scrollTo($target, 'top', 500, 0); 108 109 }); 110 }; 111 112 /** 113 * We are using the fill property on an element to pass user's choices from CSS to JavaScript 114 * 115 * @param {jQuery} $element 116 */ 117 const getStickyMode = function($element) { 118 const fillValue = getComputedStyle($element[0]).fill; 119 120 return fillValue === 'rgb(255, 0, 0)' ? 121 'sticky_banner' : 122 fillValue === 'rgb(0, 255, 0)' ? 123 'sticky_menu' : 124 fillValue === 'rgb(0, 0, 255)' ? 125 'sticky_instant' : 126 fillValue === 'rgb(255, 255, 255)' ? 127 'sticky_reverse' : 128 'sticky_none'; 129 }; 130 131 /** 132 * Adds a class to an element when not currently visible 133 * 134 * @param {jQuery} $element The element to handle stickyness for 135 * @param {string} cssClass The actual CSS class to be applied to the element when it's above a certain scroll position 136 * @param {jQuery} $banner A banner to reference the scroll position to 137 */ 138 const handleSticky = function($element, cssClass, $banner) { 139 let triggerPos = 0, 140 offset = 0; 141 let menuWrapperHeight = $element.outerHeight(); 142 let mode; 143 let prevScroll = 0; 144 $element.removeClass(cssClass); 145 146 const toggleSpacer = function(toggle) { 147 document.body.style.setProperty('--spacer-height', toggle ? menuWrapperHeight + 'px' : ''); 148 }; 149 150 const handleScroll = function() { 151 if (!$element.length || mode === 'sticky_none') return; 152 //if (!$element.length || mode === 'sticky_none' || mode === 'sticky_instant') return; 153 154 const isReverse = mode === 'sticky_reverse', 155 curScroll = viewport.getScrollTop(); 156 157 if (triggerPos <= curScroll && (!isReverse || prevScroll > curScroll)) { 158 $element.addClass(cssClass); 159 toggleSpacer(true); 160 } else { 161 $element.removeClass(cssClass); 162 toggleSpacer(false); 163 } 164 165 prevScroll = curScroll; 166 }; 167
168 const updateOffset = function() { 169 mode = getStickyMode($element); 170 menuWrapperHeight = $element.outerHeight(); 171 if (!$element.hasClass(cssClass)) { 172 offset = $element.offset().top; 173 } 174 if (mode === 'sticky_banner' && !$banner.length) { 175 mode = 'sticky_menu'; 176 } 177 if (mode === 'sticky_banner') { 178 triggerPos = $banner.offset().top + ($banner.length ? $banner.outerHeight() : $element.outerHeight()); 179 } 180 if (mode === 'sticky_menu' || mode === 'sticky_reverse') { 181 triggerPos = offset + $element.outerHeight(); 182 } 183 if (mode === 'sticky_instant') { 184 triggerPos = offset; 185 } 186 187 handleScroll(); 188 } 189 190 viewport.observe('resize', updateOffset); 191 viewport.observe('animation.end', updateOffset); 192 observeHeightChange($element[0], updateOffset); 193 updateOffset(); 194 195 viewport.observe('scroll', handleScroll); 196 handleScroll(); 197 }; 198 199 /** 200 * Adds a class to links whose target is currently inside the viewport 201 * 202 * @param {jQuery} $links Link(s) to be observed 203 * @param {string} cssClass CSS Class to be applied 204 * @param {float} sectionViewportRatio Ratio by which the target should be within the viewport 205 */ 206 const addClassOnVisibleLinkTargets = function($links, cssClass, sectionViewportRatio) { 207 if (typeof sectionViewportRatio === 'undefined') { 208 sectionViewportRatio = 1 / 2; 209 } 210 211 const menuTargets = []; 212 const activeLink = $links.filter('.active'); 213 214 const links = $links.filter(function() { 215 const $target = $(this.hash); 216 if (!$target.length) { 217 return false; 218 } 219 220 // Cache offset position to improve performance (update on resize) 221 const updateOffset = function() { 222 $target.data('offset', $target.offset().top); 223 }; 224 225 viewport.observe('resize', updateOffset); 226 viewport.observe('animation.end', updateOffset); 227 updateOffset(); 228 229 menuTargets.push($target); 230 return true; 231 }); 232 233 // No hash links found, so don't handle it at all 234 if (!links.length) { 235 return; 236 } 237 238 const checkVisibility = function() { 239 $links.removeClass('active'); 240 241 // Check section position reversely 242 for (let i = menuTargets.length - 1; i >= 0; i--) { 243 const desiredScrollPosition = menuTargets[i].data('offset') - viewport.getHeight() * (1 - sectionViewportRatio); 244 if (viewport.getScrollTop() >= desiredScrollPosition && menuTargets[i][0].offsetParent !== null) { 245 links.eq(i).addClass(cssClass); 246 return; 247 } 248 } 249 250 // Fallback to originally active item 251 activeLink.addClass(cssClass); 252 }; 253 254 viewport.observe('scroll', checkVisibility); 255 checkVisibility(); 256 }; 257})(); 258/* End JS for preset "Menu V2" */ 259 260/* JS for preset "Counter V2" */ 261$(function() { 262 EasingFunctions = { 263 // no easing, no acceleration 264 linear: function(t) { 265 return t 266 }, 267 // accelerating from zero velocity 268 easeInQuad: function(t) { 269 return t * t 270 }, 271 // decelerating to zero velocity 272 easeOutQuad: function(t) { 273 return t * (2 - t) 274 }, 275 // acceleration until halfway, then deceleration 276 easeInOutQuad: function(t) { 277 return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t 278 }, 279 // accelerating from zero velocity 280 easeInCubic: function(t) { 281 return t * t * t 282 }, 283 // decelerating to zero velocity 284 easeOutCubic: function(t) { 285 return (--t) * t * t + 1 286 }, 287 // acceleration until halfway, then deceleration 288 easeInOutCubic: function(t) { 289 return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1 290 }, 291 // accelerating from zero velocity 292 easeInQuart: function(t) { 293 return t * t * t * t 294 }, 295 // decelerating to zero velocity 296 easeOutQuart: function(t) { 297 return 1 - (--t) * t * t * t 298 }, 299 // acceleration until halfway, then deceleration 300 easeInOutQuart: function(t) { 301 return t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t 302 }, 303 // accelerating from zero velocity 304 easeInQuint: function(t) { 305 return t * t * t * t * t 306 }, 307 // decelerating to zero velocity 308 easeOutQuint: function(t) { 309 return 1 + (--t) * t * t * t * t 310 }, 311 // acceleration until halfway, then deceleration 312 easeInOutQuint: function(t) { 313 return t < .5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t 314 } 315 } 316 317 $('[data-count]').each(function() { 318 var $target = $(this); 319 var offset = 0; 320 321 var duration = 2000; 322 var interval = Math.floor(duration / 60); 323 var steps = Math.ceil(duration / interval); 324 var max = $target.data('count'); 325 326 var run = false, handle; 327 328 // Cache offset position to improve performance (update on resize) 329 var updateOffset = function() { 330 offset = $target.offset().top + $target.height()/2; 331 }; 332 viewport.observe('resize', updateOffset); 333 viewport.observe('animation.end', updateOffset); 334 updateOffset(); 335 336 var resetCounter = function() { 337 $target.html('0'); 338 run = false;
339 }; 340 341 var finishCounter = function() { 342 $target.html(max); 343 window.clearInterval(handle); 344 }; 345 346 var startCounter = function() { 347 if (run) return; 348 349 run = true; 350 var i = 0; 351 handle = window.setInterval(function() { 352 var newCount = Math.round(max * EasingFunctions.easeOutCubic(++i / steps)); 353 if (newCount >= max) { 354 return finishCounter(); 355 } 356 $target.html(newCount); 357 }, interval); 358 }; 359 360 var checkVisiblity = function() { 361 var t = viewport.getScrollTop(); 362 var h = viewport.getHeight(); 363 if (t < offset && offset < t+h) { 364 !run && startCounter(); 365 } else { 366 run && resetCounter(); 367 } 368 }; 369 370 viewport.observe('scroll', checkVisiblity); 371 checkVisiblity(); 372 }); 373}); 374/* End JS for preset "Counter V2" */ 375 376/* JS for preset "Marquee V2" */ 377$(function() { 378 $('.marquee-wrap').attr('data-items', $('.marquee-wrap > .inner').children().length); 379}); 380/* End JS for preset "Marquee 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.