1function inMobileMode() { 2 var mobilenav = document.getElementById('mobilenav'); 3 return !!( mobilenav.offsetWidth || mobilenav.offsetHeight || mobilenav.getClientRects().length ); 4} 5 6document.addEventListener("DOMContentLoaded", () => { 7 8 // Toggle slideNav 9 document.querySelectorAll('.menu').forEach(menu => { 10 menu.addEventListener('click', () => { 11 document.body.classList.toggle('slideNav'); 12 }); 13 }); 14 15 16 // Close slideNav when clicked outside navContainer 17 document.addEventListener('click', checkTarget, false); 18 document.addEventListener('touchstart', checkTarget, false); 19 function checkTarget(event) { 20 if(document.body.classList.contains('slideNav') && 21 !document.querySelector('#navContainer').contains(event.target) && 22 !document.querySelector('#mobilenav .menu').contains(event.target)) { 23 document.body.classList.remove('slideNav'); 24 } 25 } 26 27 28 // Expand current page / current page ancestor T1 items in mobile nav 29 var open_nav = document.querySelector('#navContainer li.on'); 30 if( open_nav ) { 31 open_nav.classList.add('open'); 32 var dropdown = open_nav.querySelector('ul'); 33 if( dropdown ) { 34 dropdown.style.height = dropdown.scrollHeight + "px"; 35 } 36 } 37 38 39 // Expand T1 dropdowns when + clicked 40 document.querySelectorAll('#navContainer li>span').forEach(nav_span => { 41 nav_span.addEventListener('click', () => { 42 if( inMobileMode() ) { 43 if(nav_span.parentElement.classList.contains('open')) { 44 nav_span.previousElementSibling.style.height = "0px"; 45 } else { 46 var scroll_height = nav_span.previousElementSibling.scrollHeight; 47 nav_span.previousElementSibling.style.height = scroll_height + "px"; 48 } 49 nav_span.parentElement.classList.toggle('open'); 50 } 51 }); 52 }); 53 54 55 // Toggle 'scroll' class on header when menu sticks 56 let header = document.querySelector('body>header'); 57 window.addEventListener( 'scroll', () => { 58 let element = inMobileMode() ? document.querySelector('#brand') : document.querySelector('#ancillary'); 59 if ( window.pageYOffset >= element.offsetHeight ) { 60 header.classList.add( 'sticky' ); 61 } else { 62 header.classList.remove( 'sticky' ); 63 } 64 }); 65 66 67 68 // On touch devices, expand dropdowns on first tap 69 // Make sure selector is added in stylesheet 70 function is_touch_device() { 71 var prefixes = ' -webkit- -moz- -o- -ms- '.split(' '); 72 var mq = function (query) { 73 return window.matchMedia(query).matches; 74 } 75 if(('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints > 0) || window.DocumentTouch && document instanceof DocumentTouch) { 76 return true; 77 } 78 var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''); 79 return mq(query); 80 } 81 82 if( is_touch_device() ) { 83 document.querySelectorAll( '#mainnav>ul>li>a' ).forEach( elem => { 84 elem.addEventListener( 'touchstart', () => { 85 if( !inMobileMode() ) { 86 var parent = elem.parentElement; 87 if( parent.contains( parent.querySelector( 'ul' ) ) ) { 88 if( !parent.classList.contains( 'tapped' ) ) { 89 event.preventDefault(); 90 document.querySelector( '#mainnav>ul>li.tapped' )?.classList.remove('tapped'); 91 parent.classList.add( 'tapped' ); 92 } 93 } 94 } 95 }); 96 }); 97 } 98 99 100 // Smooth scroll to anchor tag 101 document.querySelectorAll('a[href^="#"]:not([href="#"])').forEach( anchor => { 102 anchor.addEventListener('click', (e) => { 103 e.preventDefault(); 104 105 let target = document.querySelector( anchor.getAttribute('href') ); 106 let header = document.querySelector( 'body>header' ).offsetHeight; // optional header height offset 107 let offset = target.getBoundingClientRect().top + window.pageYOffset - header; 108 109 ws_scroll_to( target, offset ); 110 }); 111 }); 112 113 // ScrollTo function with callback to set focus 114 function ws_scroll_to( target, offset ) { 115 let fixed_offset = offset.toFixed(); 116 117 function ws_on_scroll() { 118 if ( window.pageYOffset.toFixed() === fixed_offset ) { 119 window.removeEventListener( 'scroll', ws_on_scroll ); 120 ws_set_focus( target ); 121 } 122 } 123 124 window.addEventListener( 'scroll', ws_on_scroll ); 125 window.scrollTo({ 126 top: offset, 127 behavior: 'smooth' 128 });
129 } 130 131 function ws_set_focus( target ) { 132 target.focus(); // try to set focus 133 if( document.activeElement != target ) { 134 target.setAttribute( 'tabindex', '-1' ); // if focus wasn't set, set tabindex to make the element focusable 135 target.focus({ 136 preventScroll: true 137 }); 138 } 139 } 140 141 142 143 // Animations 144 var offset = inMobileMode() ? 50 : 120; 145 const elements = document.querySelectorAll('#hero h1, #cta h2, #welcome h2, .pageHeader strong, .translate-left, .translate-right, .translate-up, .translate-down, .scale-in, #hero'); 146 147 function intersectionObserver() { 148 var theRootMargin = '-' + offset + 'px 0px -' + offset + 'px 0px'; 149 const config = { rootMargin: theRootMargin, threshold: 0 }; 150 let observer = new IntersectionObserver(entries => { 151 entries.forEach((entry) => { 152 if (entry.intersectionRatio > 0) { 153 entry.target.classList.add("animated"); 154 observer.unobserve(entry.target); 155 } else { 156 entry.target.classList.remove("animated"); 157 } 158 }); 159 }, config); 160 elements.forEach((element) => { 161 observer.observe(element); 162 }); 163 } 164 165 intersectionObserver(); 166 167 168 // Stop animations during window resize event 169 var timer; 170 window.addEventListener('resize', () => { 171 document.body.classList.add('stop-transitions'); 172 clearTimeout(timer); 173 timer = setTimeout(() => { 174 document.body.classList.remove('stop-transitions'); 175 }, 500); 176 }, true); 177 178 179});
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.