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 const $menu = $target.filter('.ed-menu'); 64 $(this).toggleClass(cssClass).attr('aria-expanded', !isExpanded); 65 $target.toggleClass(cssClass); 66 67 // Set focus to menu on open 68 if (!isExpanded) { 69 $menu.attr('tabindex', '0'); 70 const focusMenu = () => { 71 $menu.focus(); 72 $menu.off('transitionend', focusMenu); 73 }; 74 $menu.on('transitionend', focusMenu); 75 } 76 77 $menu[0].addEventListener( 78 'blur', 79 function() { 80 $menu[0].removeAttribute('tabindex'); 81 }, { 82 once: true 83 } 84 ); 85 }); 86 87 // Close target when link inside is clicked 88 $target.find('a').click(function() { 89 $target.removeClass(cssClass); 90 $trigger.removeClass(cssClass).attr('aria-expanded', 'false'); 91 }); 92 93 if (!$closeTrigger || !$closeTrigger.length) { 94 return; 95 } 96 97 $closeTrigger.click(function() { 98 $target.removeClass(cssClass); 99 $trigger.removeClass(cssClass).attr('aria-expanded', 'false'); 100 }); 101 }; 102 103 /** 104 * Smooth scroll to link targets 105 * 106 * @param {jQuery} $scrollLinks The links 107 * @param {jQuery} scrollOffset Offset to subtract from the scroll target position (e.g. for fixed positioned elements like a menu) 108 */ 109 const activateSmoothScroll = function($scrollLinks, scrollOffset) { 110 if (typeof scrollOffset === 'undefined') { 111 scrollOffset = 0; 112 } 113 114 const determineTarget = function($trigger, hash) { 115 if (hash == '#!next') { 116 return $trigger.closest('.ed-element').next(); 117 } 118 // Prevent invalid selectors 119 try { 120 return $(hash); 121 } catch (e) { 122 return $(); 123 } 124 } 125 126 $scrollLinks.click(function(e) { 127 const $target = determineTarget($(this), this.hash); 128 if (!$target.length) return; 129 e.preventDefault(); 130 131 viewport.scrollTo($target, 'top', 500, 0); 132 133 }); 134 }; 135 136 /** 137 * We are using the fill property on an element to pass user's choices from CSS to JavaScript 138 * 139 * @param {jQuery} $element 140 */ 141 const getStickyMode = function($element) { 142 const fillValue = getComputedStyle($element[0]).fill; 143 144 return fillValue === 'rgb(255, 0, 0)' ? 145 'sticky_banner' : 146 fillValue === 'rgb(0, 255, 0)' ? 147 'sticky_menu' : 148 fillValue === 'rgb(0, 0, 255)' ? 149 'sticky_instant' : 150 fillValue === 'rgb(255, 255, 255)' ? 151 'sticky_reverse' : 152 'sticky_none'; 153 }; 154 155 /** 156 * Adds a class to an element when not currently visible 157 * 158 * @param {jQuery} $element The element to handle stickyness for 159 * @param {string} cssClass The actual CSS class to be applied to the element when it's above a certain scroll position 160 * @param {jQuery} $banner A banner to reference the scroll position to 161 */ 162 const handleSticky = function($element, cssClass, $banner) { 163 let triggerPos = 0, 164 offset = 0; 165 let menuWrapperHeight = $element.outerHeight(); 166 let mode; 167 let prevScroll = 0; 168 $element.removeClass(cssClass); 169 170 const toggleSpacer = function(toggle) { 171 document.body.style.setProperty('--spacer-height', toggle ? menuWrapperHeight + 'px' : ''); 172 }; 173 174 const handleScroll = function() { 175 if (!$element.length || mode === 'sticky_none') return; 176 //if (!$element.length || mode === 'sticky_none' || mode === 'sticky_instant') return; 177 178 const isReverse = mode === 'sticky_reverse', 179 curScroll = viewport.getScrollTop(); 180 181 if (triggerPos <= curScroll && (!isReverse || prevScroll > curScroll)) { 182 $element.addClass(cssClass); 183 toggleSpacer(true); 184 } else { 185 $element.removeClass(cssClass); 186 toggleSpacer(false); 187 } 188 189 prevScroll = curScroll; 190 }; 191
192 const updateOffset = function() { 193 mode = getStickyMode($element); 194 menuWrapperHeight = $element.outerHeight(); 195 if (!$element.hasClass(cssClass)) { 196 offset = $element.offset().top; 197 } 198 if (mode === 'sticky_banner' && !$banner.length) { 199 mode = 'sticky_menu'; 200 } 201 if (mode === 'sticky_banner') { 202 triggerPos = $banner.offset().top + ($banner.length ? $banner.outerHeight() : $element.outerHeight()); 203 } 204 if (mode === 'sticky_menu' || mode === 'sticky_reverse') { 205 triggerPos = offset + $element.outerHeight(); 206 } 207 if (mode === 'sticky_instant') { 208 triggerPos = offset; 209 } 210 211 handleScroll(); 212 } 213 214 viewport.observe('resize', updateOffset); 215 viewport.observe('animation.end', updateOffset); 216 observeHeightChange($element[0], updateOffset); 217 updateOffset(); 218 219 viewport.observe('scroll', handleScroll); 220 handleScroll(); 221 }; 222 223 /** 224 * Adds a class to links whose target is currently inside the viewport 225 * 226 * @param {jQuery} $links Link(s) to be observed 227 * @param {string} cssClass CSS Class to be applied 228 * @param {float} sectionViewportRatio Ratio by which the target should be within the viewport 229 */ 230 const addClassOnVisibleLinkTargets = function($links, cssClass, sectionViewportRatio) { 231 if (typeof sectionViewportRatio === 'undefined') { 232 sectionViewportRatio = 1 / 2; 233 } 234 235 const menuTargets = []; 236 const activeLink = $links.filter('.active'); 237 238 const links = $links.filter(function() { 239 // Prevent invalid selectors 240 let $target; 241 try { 242 $target = $(this.hash); 243 } catch (e) { 244 return false; 245 } 246 if (!this.hash || !$target.length) { 247 return false; 248 } 249 250 // Cache offset position to improve performance (update on resize) 251 const updateOffset = function() { 252 $target.data('offset', $target.offset().top); 253 }; 254 255 viewport.observe('resize', updateOffset); 256 viewport.observe('animation.end', updateOffset); 257 updateOffset(); 258 259 menuTargets.push($target); 260 return true; 261 }); 262 263 // No hash links found, so don't handle it at all 264 if (!links.length) { 265 return; 266 } 267 268 const checkVisibility = function() { 269 $links.removeClass('active'); 270 271 // Check section position reversely 272 for (let i = menuTargets.length - 1; i >= 0; i--) { 273 const desiredScrollPosition = menuTargets[i].data('offset') - viewport.getHeight() * (1 - sectionViewportRatio); 274 if (viewport.getScrollTop() >= desiredScrollPosition && menuTargets[i][0].offsetParent !== null) { 275 links.eq(i).addClass(cssClass); 276 return; 277 } 278 } 279 280 // Fallback to originally active item 281 activeLink.addClass(cssClass); 282 }; 283 284 viewport.observe('scroll', checkVisibility); 285 checkVisibility(); 286 }; 287})(); 288/* End JS for preset "Menu V2" */ 289 290/* ---- particles.js config ---- */ 291 292/* 293The MIT License (MIT) 294 295Copyright (c) 2015, Vincent Garreau 296 297Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 298 299The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 300 301THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 302*/ 303 304$(function() { 305 if (document.body.classList.contains('edit') || document.body.classList.contains('preview')) { 306 return; 307 } 308 309 particlesJS("particles-js", { 310 "particles": { 311 "number": { 312 "value": 100, 313 "density": { 314 "enable": true, 315 "value_area":1000 316 } 317 }, 318 "color": { 319 "value": ["#fff"] 320 }, 321 322 "shape": { 323 "type": "circle", 324 "stroke": { 325 "width": 0, 326 "color": "#fff" 327 }, 328 "polygon": { 329 "nb_sides": 5 330 }, 331 "image": { 332 "src": "img/github.svg", 333 "width": 100, 334 "height": 100 335 } 336 }, 337 "opacity": { 338 "value": 0.6, 339 "random": false, 340 "anim": { 341 "enable": false, 342 "speed": 1, 343 "opacity_min": 0.1, 344 "sync": false 345 } 346 }, 347 "size": { 348 "value": 2, 349 "random": true, 350 "anim": { 351 "enable": false, 352 "speed": 40, 353 "size_min": 0.1, 354 "sync": false 355 } 356 }, 357 "line_linked": { 358 "enable": true, 359 "distance": 120, 360 "color": "#ffffff", 361 "opacity": 0.4, 362 "width": 1 363 }, 364 }, 365 "interactivity": { 366 "detect_on": "canvas", 367 "events": { 368 "onhover": { 369 "enable": true, 370 "mode": "grab" 371 }, 372 "onclick": { 373 "enable": false 374 }, 375 "resize": true 376 }, 377 "modes": { 378 "grab": { 379 "distance": 140, 380 "line_linked": { 381 "opacity": 1 382 } 383 }, 384 "bubble": { 385 "distance": 400, 386 "size": 40, 387 "duration": 2, 388 "opacity": 8, 389 "speed": 3 390 }, 391 "repulse": { 392 "distance": 200, 393 "duration": 0.4 394 }, 395 "push": { 396 "particles_nb": 4 397 }, 398 "remove": { 399 "particles_nb": 2 400 } 401 } 402 }, 403 "retina_detect": true 404 }); 405});
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.