PageSourceSearch

https://hclwizard.org/site_libs/quarto-nav/quarto-nav.js

js hclwizard.org collected 2026-09-24 18:34:15 UTC 9,636 bytes, 325 lines download raw bytes

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.