1( function() { 2 3 var origin, position, stickyNav; 4 var links = []; 5 var anchors = []; 6 var margin = 10; 7 8 document.addEventListener( "DOMContentLoaded", initSticky ); 9 10 function initSticky() { 11 12 stickyNav = document.querySelector( "nav.sticky" ); 13 if ( ! stickyNav ) { return false } 14 origin = stickyNav.getBoundingClientRect().top; 15 16 document.querySelector( "html" ).classList.add( "has-sticky-nav" ); 17 links = stickyNav.querySelectorAll( "a" ); 18 links.forEach(function(el, i) { 19 el.addEventListener( "click", handleClick ); 20 var t = document.getElementById( el.getAttribute( "href" ).replace( "#", "" ) ); 21 if( t ) { 22 t.classList.add("sticky-anchor"); 23 anchors.push( t ); 24 } 25 }); 26 27 28 window.addEventListener("scroll", testSticky); 29 30 if("IntersectionObserver" in window) { 31 let options = { 32 root: null, 33 rootMargin: "-" + margin + "px", 34 threshold: 1 35 } 36 let observer = new IntersectionObserver(observerCallback, options); 37 38 anchors.forEach(function(el) { 39 observer.observe(el); 40 }); 41 } 42 } 43 44 function observerCallback(entries, observer) { 45 entries.forEach(function(entry) { 46 var top = entry.boundingClientRect.top; 47 entry.target.dataset.stickyFromTop = top; 48 49 // we need the last link where top < 0 50 var activeSection; 51 for( var i = anchors.length - 1; i >= 0; i-- ) { 52 if( ( anchors[i].dataset.stickyFromTop * 1 ) < ( margin + 1 ) ) { 53 activeSection = anchors[i]; 54 break; 55 } 56 } 57 var l = null; 58 if( !! activeSection ) { 59 l = stickyNav.querySelector("[href='#" + activeSection.id + "']"); 60 } 61 activateLink( l ); 62 63 }); 64 } 65 66 function activateLink(l) { 67 links.forEach(function(el, i) { 68 el.classList.remove("active"); 69 }); 70 if( l ) { 71 l.classList.add("active"); 72 } 73 } 74 75 function handleClick(e) { 76 e.preventDefault(); 77 var destination = document.querySelector( this.getAttribute("href") ); 78 if( destination ) { 79 document.querySelector( this.getAttribute("href") ).scrollIntoView({ 80 behavior: "smooth" 81 }); 82 activateLink(this); 83 } else { 84 // bad link 85 if( this.classList.contains("bad") ) { 86 this.classList.remove("bad"); 87 this.offsetHeight; // trigger a reflow to restart animation on consecutive clicks 88 } 89 this.classList.add("bad"); 90 } 91 } 92 93 94 function testSticky() { 95 if( window.scrollY >= origin ) { 96 stickyNav.classList.add("fixed"); 97 } else { 98 stickyNav.classList.remove("fixed"); 99 } 100 } 101 102 103})();
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.