1const headroomChanged = new CustomEvent("quarto-hrChanged", { 2 detail: {}, 3 bubbles: true, 4 cancelable: false, 5 composed: false, 6}); 7 8const announceDismiss = () => { 9 const annEl = window.document.getElementById("quarto-announcement"); 10 if (annEl) { 11 annEl.remove(); 12 13 const annId = annEl.getAttribute("data-announcement-id"); 14 window.localStorage.setItem(`quarto-announce-${annId}`, "true"); 15 } 16}; 17 18const announceRegister = () => { 19 const annEl = window.document.getElementById("quarto-announcement"); 20 if (annEl) { 21 const annId = annEl.getAttribute("data-announcement-id"); 22 const isDismissed = 23 window.localStorage.getItem(`quarto-announce-${annId}`) || false; 24 if (isDismissed) { 25 announceDismiss(); 26 return; 27 } else { 28 annEl.classList.remove("hidden"); 29 } 30 31 const actionEl = annEl.querySelector(".quarto-announcement-action"); 32 if (actionEl) { 33 actionEl.addEventListener("click", function (e) { 34 e.preventDefault(); 35 // Hide the bar immediately 36 announceDismiss(); 37 }); 38 } 39 } 40}; 41 42window.document.addEventListener("DOMContentLoaded", function () { 43 let init = false; 44 45 announceRegister(); 46 47 // Manage the back to top button, if one is present. 48 let lastScrollTop = window.pageYOffset || document.documentElement.scrollTop; 49 const scrollDownBuffer = 5; 50 const scrollUpBuffer = 35; 51 const btn = document.getElementById("quarto-back-to-top"); 52 const hideBackToTop = () => { 53 btn.style.display = "none"; 54 }; 55 const showBackToTop = () => { 56 btn.style.display = "inline-block"; 57 }; 58 if (btn) { 59 window.document.addEventListener( 60 "scroll", 61 function () { 62 const currentScrollTop = 63 window.pageYOffset || document.documentElement.scrollTop; 64 65 // Shows and hides the button 'intelligently' as the user scrolls 66 if (currentScrollTop - scrollDownBuffer > lastScrollTop) { 67 hideBackToTop(); 68 lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop; 69 } else if (currentScrollTop < lastScrollTop - scrollUpBuffer) { 70 showBackToTop(); 71 lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop; 72 } 73 74 // Show the button at the bottom, hides it at the top 75 if (currentScrollTop <= 0) { 76 hideBackToTop(); 77 } else if ( 78 window.innerHeight + currentScrollTop >= 79 document.body.offsetHeight 80 ) { 81 showBackToTop(); 82 } 83 }, 84 false 85 ); 86 } 87 88 function throttle(func, wait) { 89 var timeout; 90 return function () { 91 const context = this; 92 const args = arguments; 93 const later = function () { 94 clearTimeout(timeout); 95 timeout = null; 96 func.apply(context, args); 97 }; 98 99 if (!timeout) { 100 timeout = setTimeout(later, wait); 101 } 102 }; 103 } 104 105 function headerOffset() { 106 // Set an offset if there is are fixed top navbar 107 const headerEl = window.document.querySelector("header.fixed-top"); 108 if (headerEl) { 109 return headerEl.clientHeight; 110 } else { 111 return 0; 112 } 113 } 114 115 function footerOffset() { 116 const footerEl = window.document.querySelector("footer.footer"); 117 if (footerEl) { 118 return footerEl.clientHeight; 119 } else { 120 return 0; 121 } 122 } 123 124 function dashboardOffset() { 125 const dashboardNavEl = window.document.getElementById( 126 "quarto-dashboard-header" 127 ); 128 if (dashboardNavEl !== null) { 129 return dashboardNavEl.clientHeight; 130 } else { 131 return 0; 132 } 133 } 134 135 function updateDocumentOffsetWithoutAnimation() { 136 updateDocumentOffset(false); 137 } 138 139 function updateDocumentOffset(animated) { 140 // set body offset 141 const topOffset = headerOffset(); 142 const bodyOffset = topOffset + footerOffset() + dashboardOffset(); 143 const bodyEl = window.document.body; 144 bodyEl.setAttribute("data-bs-offset", topOffset); 145 bodyEl.style.paddingTop = topOffset + "px"; 146 147 // deal with sidebar offsets 148 const sidebars = window.document.querySelectorAll( 149 ".sidebar, .headroom-target" 150 );
151 sidebars.forEach((sidebar) => { 152 if (!animated) { 153 sidebar.classList.add("notransition"); 154 // Remove the no transition class after the animation has time to complete 155 setTimeout(function () { 156 sidebar.classList.remove("notransition"); 157 }, 201); 158 } 159 160 if (window.Headroom && sidebar.classList.contains("sidebar-unpinned")) { 161 sidebar.style.top = "0"; 162 sidebar.style.maxHeight = "100vh"; 163 } else { 164 sidebar.style.top = topOffset + "px"; 165 sidebar.style.maxHeight = "calc(100vh - " + topOffset + "px)"; 166 } 167 }); 168 169 // allow space for footer 170 const mainContainer = window.document.querySelector(".quarto-container"); 171 if (mainContainer) { 172 mainContainer.style.minHeight = "calc(100vh - " + bodyOffset + "px)"; 173 } 174 175 // link offset 176 let linkStyle = window.document.querySelector("#quarto-target-style"); 177 if (!linkStyle) { 178 linkStyle = window.document.createElement("style"); 179 linkStyle.setAttribute("id", "quarto-target-style"); 180 window.document.head.appendChild(linkStyle); 181 } 182 while (linkStyle.firstChild) { 183 linkStyle.removeChild(linkStyle.firstChild); 184 } 185 if (topOffset > 0) { 186 linkStyle.appendChild( 187 window.document.createTextNode(` 188 section:target::before { 189 content: ""; 190 display: block; 191 height: ${topOffset}px; 192 margin: -${topOffset}px 0 0; 193 }`) 194 ); 195 } 196 if (init) { 197 window.dispatchEvent(headroomChanged); 198 } 199 init = true; 200 } 201 202 // initialize headroom 203 var header = window.document.querySelector("#quarto-header"); 204 if (header && window.Headroom) { 205 const headroom = new window.Headroom(header, { 206 tolerance: 5, 207 onPin: function () { 208 const sidebars = window.document.querySelectorAll( 209 ".sidebar, .headroom-target" 210 ); 211 sidebars.forEach((sidebar) => { 212 sidebar.classList.remove("sidebar-unpinned"); 213 }); 214 updateDocumentOffset(); 215 }, 216 onUnpin: function () { 217 const sidebars = window.document.querySelectorAll( 218 ".sidebar, .headroom-target" 219 ); 220 sidebars.forEach((sidebar) => { 221 sidebar.classList.add("sidebar-unpinned"); 222 }); 223 updateDocumentOffset(); 224 }, 225 }); 226 headroom.init(); 227 228 let frozen = false; 229 window.quartoToggleHeadroom = function () { 230 if (frozen) { 231 headroom.unfreeze(); 232 frozen = false; 233 } else { 234 headroom.freeze(); 235 frozen = true; 236 } 237 }; 238 } 239 240 window.addEventListener( 241 "hashchange", 242 function (e) { 243 if ( 244 getComputedStyle(document.documentElement).scrollBehavior !== "smooth" 245 ) { 246 window.scrollTo(0, window.pageYOffset - headerOffset()); 247 } 248 }, 249 false 250 ); 251 252 // Observe size changed for the header 253 const headerEl = window.document.querySelector("header.fixed-top"); 254 if (headerEl && window.ResizeObserver) { 255 const observer = new window.ResizeObserver(() => { 256 setTimeout(updateDocumentOffsetWithoutAnimation, 0); 257 }); 258 observer.observe(headerEl, { 259 attributes: true, 260 childList: true, 261 characterData: true, 262 }); 263 } else { 264 window.addEventListener( 265 "resize", 266 throttle(updateDocumentOffsetWithoutAnimation, 50) 267 ); 268 } 269 setTimeout(updateDocumentOffsetWithoutAnimation, 250); 270 271 // fixup index.html links if we aren't on the filesystem 272 if (window.location.protocol !== "file:") { 273 const links = window.document.querySelectorAll("a"); 274 for (let i = 0; i < links.length; i++) { 275 if (links[i].href) { 276 links[i].dataset.originalHref = links[i].href; 277 links[i].href = links[i].href.replace(/\/index\.html/, "/"); 278 } 279 } 280 281 // Fixup any sharing links that require urls 282 // Append url to any sharing urls 283 const sharingLinks = window.document.querySelectorAll( 284 "a.sidebar-tools-main-item, a.quarto-navigation-tool, a.quarto-navbar-tools, a.quarto-navbar-tools-item" 285 ); 286 for (let i = 0; i < sharingLinks.length; i++) { 287 const sharingLink = sharingLinks[i]; 288 const href = sharingLink.getAttribute("href"); 289 if (href) { 290 sharingLink.setAttribute( 291 "href", 292 href.replace("|url|", window.location.href) 293 ); 294 } 295 } 296 297 // Scroll the active navigation item into view, if necessary 298 const navSidebar = window.document.querySelector("nav#quarto-sidebar"); 299 if (navSidebar) { 300 // Find the active item 301 const activeItem = navSidebar.querySelector("li.sidebar-item a.active"); 302 if (activeItem) { 303 // Wait for the scroll height and height to resolve by observing size changes on the 304 // nav element that is scrollable 305 const resizeObserver = new ResizeObserver((_entries) => { 306 // The bottom of the element 307 const elBottom = activeItem.offsetTop;
308 const viewBottom = navSidebar.scrollTop + navSidebar.clientHeight; 309 310 // The element height and scroll height are the same, then we are still loading 311 if (viewBottom !== navSidebar.scrollHeight) { 312 // Determine if the item isn't visible and scroll to it 313 if (elBottom >= viewBottom) { 314 navSidebar.scrollTop = elBottom; 315 } 316 317 // stop observing now since we've completed the scroll 318 resizeObserver.unobserve(navSidebar); 319 } 320 }); 321 resizeObserver.observe(navSidebar); 322 } 323 } 324 } 325});
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.