PageSourceSearch

https://stifterverband-hex-methodenbericht.netlify.app/site_libs/quarto-html/quarto.js

js stifterverband-hex-methodenbericht.netlify.app collected 2026-10-03 11:27:21 UTC 26,885 bytes, 847 lines download raw bytes

1import * as tabsets from "./tabsets/tabsets.js";
2import * as axe from "./axe/axe-check.js";
3
4const sectionChanged = new CustomEvent("quarto-sectionChanged", {
5  detail: {},
6  bubbles: true,
7  cancelable: false,
8  composed: false,
9});
10
11const layoutMarginEls = () => {
12  // Find any conflicting margin elements and add margins to the
13  // top to prevent overlap
14  const marginChildren = window.document.querySelectorAll(
15    ".column-margin.column-container > *, .margin-caption, .aside"
16  );
17
18  let lastBottom = 0;
19  for (const marginChild of marginChildren) {
20    if (marginChild.offsetParent !== null) {
21      // clear the top margin so we recompute it
22      marginChild.style.marginTop = null;
23      const top = marginChild.getBoundingClientRect().top + window.scrollY;
24      if (top < lastBottom) {
25        const marginChildStyle = window.getComputedStyle(marginChild);
26        const marginBottom = parseFloat(marginChildStyle["marginBottom"]);
27        const margin = lastBottom - top + marginBottom;
28        marginChild.style.marginTop = `${margin}px`;
29      }
30      const styles = window.getComputedStyle(marginChild);
31      const marginTop = parseFloat(styles["marginTop"]);
32      lastBottom = top + marginChild.getBoundingClientRect().height + marginTop;
33    }
34  }
35};
36
37window.document.addEventListener("DOMContentLoaded", function (_event) {
38  // Recompute the position of margin elements anytime the body size changes
39  if (window.ResizeObserver) {
40    const resizeObserver = new window.ResizeObserver(
41      throttle(() => {
42        layoutMarginEls();
43        if (
44          window.document.body.getBoundingClientRect().width < 990 &&
45          isReaderMode()
46        ) {
47          quartoToggleReader();
48        }
49      }, 50)
50    );
51    resizeObserver.observe(window.document.body);
52  }
53
54  const tocEl = window.document.querySelector('nav.toc-active[role="doc-toc"]');
55  const sidebarEl = window.document.getElementById("quarto-sidebar");
56  const leftTocEl = window.document.getElementById("quarto-sidebar-toc-left");
57  const marginSidebarEl = window.document.getElementById(
58    "quarto-margin-sidebar"
59  );
60  // function to determine whether the element has a previous sibling that is active
61  const prevSiblingIsActiveLink = (el) => {
62    const sibling = el.previousElementSibling;
63    if (sibling && sibling.tagName === "A") {
64      return sibling.classList.contains("active");
65    } else {
66      return false;
67    }
68  };
69
70  // dispatch for htmlwidgets
71  // they use slideenter event to trigger resize
72  function fireSlideEnter() {
73    const event = window.document.createEvent("Event");
74    event.initEvent("slideenter", true, true);
75    window.document.dispatchEvent(event);
76  }
77
78  const tabs = window.document.querySelectorAll('a[data-bs-toggle="tab"]');
79  tabs.forEach((tab) => {
80    tab.addEventListener("shown.bs.tab", fireSlideEnter);
81  });
82
83  // dispatch for shiny
84  // they use BS shown and hidden events to trigger rendering
85  function distpatchShinyEvents(previous, current) {
86    if (window.jQuery) {
87      if (previous) {
88        window.jQuery(previous).trigger("hidden");
89      }
90      if (current) {
91        window.jQuery(current).trigger("shown");
92      }
93    }
94  }
95
96  // tabby.js listener: Trigger event for htmlwidget and shiny
97  document.addEventListener(
98    "tabby",
99    function (event) {
100      fireSlideEnter();
101      distpatchShinyEvents(event.detail.previousTab, event.detail.tab);
102    },
103    false
104  );
105
106  // Track scrolling and mark TOC links as active
107  // get table of contents and sidebar (bail if we don't have at least one)
108  const tocLinks = tocEl
109    ? [...tocEl.querySelectorAll("a[data-scroll-target]")]
110    : [];
111  const makeActive = (link) => tocLinks[link].classList.add("active");
112  const removeActive = (link) => tocLinks[link].classList.remove("active");
113  const removeAllActive = () =>
114    [...Array(tocLinks.length).keys()].forEach((link) => removeActive(link));
115
116  // activate the anchor for a section associated with this TOC entry
117  tocLinks.forEach((link) => {
118    link.addEventListener("click", () => {
119      if (link.href.indexOf("#") !== -1) {
120        const anchor = link.href.split("#")[1];
121        const heading = window.document.querySelector(
122          `[data-anchor-id="${anchor}"]`
123        );
124        if (heading) {
125          // Add the class
126          heading.classList.add("reveal-anchorjs-link");
127
128          // function to show the anchor
129          const handleMouseout = () => {
130            heading.classList.remove("reveal-anchorjs-link");
131            heading.removeEventListener("mouseout", handleMouseout);
132          };
133
134          // add a function to clear the anchor when the user mouses out of it
135          heading.addEventListener("mouseout", handleMouseout);
136        }
137      }
138    });
139  });
140
141  const sections = tocLinks.map((link) => {
142    const target = link.getAttribute("data-scroll-target");
143    if (target.startsWith("#")) {
144      return window.document.getElementById(decodeURI(`${target.slice(1)}`));
145    } else {
146      return window.document.querySelector(decodeURI(`${target}`));
147    }
148  });
149
150  const sectionMargin = 200;
151  let currentActive = 0;
152  // track whether we've initialized state the first time
153  let init = false;
154
155  const updateActiveLink = () => {
156    // The index from bottom to top (e.g. reversed list)
157    let sectionIndex = -1;
158    if (
159      window.innerHeight + window.pageYOffset >=
160      window.document.body.offsetHeight
161    ) {
162      // This is the no-scroll case where last section should be the active one
163      sectionIndex = 0;
164    } else {
165      // This finds the last section visible on screen that should be made active
166      sectionIndex = [...sections].reverse().findIndex((section) => {
167        if (section) {
168          return window.pageYOffset >= section.offsetTop - sectionMargin;
169        } else {
170          return false;
171        }
172      });
173    }
174    if (sectionIndex > -1) {
175      const current = sections.length - sectionIndex - 1;
176      if (current !== currentActive) {
177        removeAllActive();
178        currentActive = current;
179        makeActive(current);
180        if (init) {
181          window.dispatchEvent(sectionChanged);
182        }
183        init = true;
184      }
185    }
186  };
187
188  const inHiddenRegion = (top, bottom, hiddenRegions) => {
189    for (const region of hiddenRegions) {
190      if (top <= region.bottom && bottom >= region.top) {
191        return true;
192      }
193    }
194    return false;
195  };
196
197  const categorySelector = "header.quarto-title-block .quarto-category";
198  const activateCategories = (href) => {
199    // Find any categories
200    // Surround them with a link pointing back to:
201    // #category=Authoring
202    try {
203      const categoryEls = window.document.querySelectorAll(categorySelector);
204      for (const categoryEl of categoryEls) {
205        const categoryText = categoryEl.textContent;
206        if (categoryText) {
207          const link = `${href}#category=${encodeURIComponent(categoryText)}`;
208          const linkEl = window.document.createElement("a");
209          linkEl.setAttribute("href", link);
210          for (const child of categoryEl.childNodes) {
211            linkEl.append(child);
212          }
213          categoryEl.appendChild(linkEl);
214        }
215      }
216    } catch {
217      // Ignore errors
218    }
219  };
220  function hasTitleCategories() {
221    return window.document.querySelector(categorySelector) !== null;
222  }
223
224  function offsetRelativeUrl(url) {
225    const offset = getMeta("quarto:offset");
226    return offset ? offset + url : url;
227  }
228
229  function offsetAbsoluteUrl(url) {
230    const offset = getMeta("quarto:offset");
231    const baseUrl = new URL(offset, window.location);
232
233    const projRelativeUrl = url.replace(baseUrl, "");
234    if (projRelativeUrl.startsWith("/")) {
235      return projRelativeUrl;
236    } else {
237      return "/" + projRelativeUrl;
238    }
239  }
240
241  // read a meta tag value
242  function getMeta(metaName) {
243    const metas = window.document.getElementsByTagName("meta");
244    for (let i = 0; i < metas.length; i++) {
245      if (metas[i].getAttribute("name") === metaName) {
246        return metas[i].getAttribute("content");
247      }
248    }
249    return "";
250  }
251
252  async function findAndActivateCategories() {
253    // Categories search with listing only use path without query
254    const currentPagePath = offsetAbsoluteUrl(
255      window.location.origin + window.location.pathname
256    );
257    const response = await fetch(offsetRelativeUrl("listings.json"));
258    if (response.status == 200) {
259      return response.json().then(function (listingPaths) {
260        const listingHrefs = [];
261        for (const listingPath of listingPaths) {
262          const pathWithoutLeadingSlash = listingPath.listing.substring(1);
263          for (const item of listingPath.items) {
264            const encodedItem = encodeURI(item);
265            if (
266              encodedItem === currentPagePath ||
267              encodedItem === currentPagePath + "index.html"
268            ) {
269              // Resolve this path against the offset to be sure
270              // we already are using the correct path to the listing
271              // (this adjusts the listing urls to be rooted against
272              // whatever root the page is actually running against)
273              const relative = offsetRelativeUrl(pathWithoutLeadingSlash);
274              const baseUrl = window.location;
275              const resolvedPath = new URL(relative, baseUrl);
276              listingHrefs.push(resolvedPath.pathname);
277              break;
278            }
279          }
280        }
281
282        // Look up the tree for a nearby linting and use that if we find one
283        const nearestListing = findNearestParentListing(
284          offsetAbsoluteUrl(window.location.pathname),
285          listingHrefs
286        );
287        if (nearestListing) {
288          activateCategories(nearestListing);
289        } else {
290          // See if the referrer is a listing page for this item
291          const referredRelativePath = offsetAbsoluteUrl(document.referrer);
292          const referrerListing = listingHrefs.find((listingHref) => {
293            const isListingReferrer =
294              listingHref === referredRelativePath ||
295              listingHref === referredRelativePath + "index.html";
296            return isListingReferrer;
297          });
298
299          if (referrerListing) {
300            // Try to use the referrer if possible
301            activateCategories(referrerListing);
302          } else if (listingHrefs.length > 0) {
303            // Otherwise, just fall back to the first listing
304            activateCategories(listingHrefs[0]);
305          }
306        }
307      });
308    }
309  }
310  if (hasTitleCategories()) {
311    findAndActivateCategories();
312  }
313
314  const findNearestParentListing = (href, listingHrefs) => {
315    if (!href || !listingHrefs) {
316      return undefined;
317    }
318    // Look up the tree for a nearby linting and use that if we find one
319    const relativeParts = href.substring(1).split("/");
320    while (relativeParts.length > 0) {
321      const path = relativeParts.join("/");
322      for (const listingHref of listingHrefs) {
323        if (listingHref.startsWith(path)) {
324          return listingHref;
325        }
326      }
327      relativeParts.pop();
328    }
329
330    return undefined;
331  };
332
333  const manageSidebarVisiblity = (el, placeholderDescriptor) => {
334    let isVisible = true;
335    let elRect;
336
337    return (hiddenRegions) => {
338      if (el === null) {
339        return;
340      }
341
342      // Find the last element of the TOC
343      const lastChildEl = el.lastElementChild;
344
345      if (lastChildEl) {
346        // Converts the sidebar to a menu
347        const convertToMenu = () => {
348          for (const child of el.children) {
349            child.style.opacity = 0;
350            child.style.overflow = "hidden";
351            child.style.pointerEvents = "none";
352          }
353
354          nexttick(() => {
355            const toggleContainer = window.document.createElement("div");
356            toggleContainer.style.width = "100%";
357            toggleContainer.classList.add("zindex-over-content");
358            toggleContainer.classList.add("quarto-sidebar-toggle");
359            toggleContainer.classList.add("headroom-target"); // Marks this to be managed by headeroom
360            toggleContainer.id = placeholderDescriptor.id;
361            toggleContainer.style.position = "fixed";
362
363            const toggleIcon = window.document.createElement("i");
364            toggleIcon.classList.add("quarto-sidebar-toggle-icon");
365            toggleIcon.classList.add("bi");
366            toggleIcon.classList.add("bi-caret-down-fill");
367
368            const toggleTitle = window.document.createElement("div");
369            const titleEl = window.document.body.querySelector(
370              placeholderDescriptor.titleSelector
371            );
372            if (titleEl) {
373              toggleTitle.append(
374                titleEl.textContent || titleEl.innerText,
375                toggleIcon
376              );
377            }
378            toggleTitle.classList.add("zindex-over-content");
379            toggleTitle.classList.add("quarto-sidebar-toggle-title");
380            toggleContainer.append(toggleTitle);
381
382            const toggleContents = window.document.createElement("div");
383            toggleContents.classList = el.classList;
384            toggleContents.classList.add("zindex-over-content");
385            toggleContents.classList.add("quarto-sidebar-toggle-contents");
386            for (const child of el.children) {
387              if (child.id === "toc-title") {
388                continue;
389              }
390
391              const clone = child.cloneNode(true);
392              clone.style.opacity = 1;
393              clone.style.pointerEvents = null;
394              clone.style.display = null;
395              toggleContents.append(clone);
396            }
397            toggleContents.style.height = "0px";
398            const positionToggle = () => {
399              // position the element (top left of parent, same width as parent)
400              if (!elRect) {
401                elRect = el.getBoundingClientRect();
402              }
403              toggleContainer.style.left = `${elRect.left}px`;
404              toggleContainer.style.top = `${elRect.top}px`;
405              toggleContainer.style.width = `${elRect.width}px`;
406            };
407            positionToggle();
408
409            toggleContainer.append(toggleContents);
410            el.parentElement.prepend(toggleContainer);
411
412            // Process clicks
413            let tocShowing = false;
414            // Allow the caller to control whether this is dismissed
415            // when it is clicked (e.g. sidebar navigation supports
416            // opening and closing the nav tree, so don't dismiss on click)
417            const clickEl = placeholderDescriptor.dismissOnClick
418              ? toggleContainer
419              : toggleTitle;
420
421            const closeToggle = () => {
422              if (tocShowing) {
423                toggleContainer.classList.remove("expanded");
424                toggleContents.style.height = "0px";
425                tocShowing = false;
426              }
427            };
428
429            // Get rid of any expanded toggle if the user scrolls
430            window.document.addEventListener(
431              "scroll",
432              throttle(() => {
433                closeToggle();
434              }, 50)
435            );
436
437            // Handle positioning of the toggle
438            window.addEventListener(
439              "resize",
440              throttle(() => {
441                elRect = undefined;
442                positionToggle();
443              }, 50)
444            );
445
446            window.addEventListener("quarto-hrChanged", () => {
447              elRect = undefined;
448            });
449
450            // Process the click
451            clickEl.onclick = () => {
452              if (!tocShowing) {
453                toggleContainer.classList.add("expanded");
454                toggleContents.style.height = null;
455                tocShowing = true;
456              } else {
457                closeToggle();
458              }
459            };
460          });
461        };
462
463        // Converts a sidebar from a menu back to a sidebar
464        const convertToSidebar = () => {
465          for (const child of el.children) {
466            child.style.opacity = 1;
467            child.style.overflow = null;
468            child.style.pointerEvents = null;
469          }
470
471          const placeholderEl = window.document.getElementById(
472            placeholderDescriptor.id
473          );
474          if (placeholderEl) {
475            placeholderEl.remove();
476          }
477
478          el.classList.remove("rollup");
479        };
480
481        if (isReaderMode()) {
482          convertToMenu();
483          isVisible = false;
484        } else {
485          // Find the top and bottom o the element that is being managed
486          const elTop = el.offsetTop;
487          const elBottom =
488            elTop + lastChildEl.offsetTop + lastChildEl.offsetHeight;
489
490          if (!isVisible) {
491            // If the element is current not visible reveal if there are
492            // no conflicts with overlay regions
493            if (!inHiddenRegion(elTop, elBottom, hiddenRegions)) {
494              convertToSidebar();
495              isVisible = true;
496            }
497          } else {
498            // If the element is visible, hide it if it conflicts with overlay regions
499            // and insert a placeholder toggle (or if we're in reader mode)
500            if (inHiddenRegion(elTop, elBottom, hiddenRegions)) {
501              convertToMenu();
502              isVisible = false;
503            }
504          }
505        }
506      }
507    };
508  };
509
510  const tabEls = document.querySelectorAll('a[data-bs-toggle="tab"]');
511  for (const tabEl of tabEls) {
512    const id = tabEl.getAttribute("data-bs-target");
513    if (id) {
514      const columnEl = document.querySelector(
515        `${id} .column-margin, .tabset-margin-content`
516      );
517      if (columnEl)
518        tabEl.addEventListener("shown.bs.tab", function (event) {
519          const el = event.srcElement;
520          if (el) {
521            const visibleCls = `${el.id}-margin-content`;
522            // walk up until we find a parent tabset
523            let panelTabsetEl = el.parentElement;
524            while (panelTabsetEl) {
525              if (panelTabsetEl.classList.contains("panel-tabset")) {
526                break;
527              }
528              panelTabsetEl = panelTabsetEl.parentElement;
529            }
530
531            if (panelTabsetEl) {
532              const prevSib = panelTabsetEl.previousElementSibling;
533              if (
534                prevSib &&
535                prevSib.classList.contains("tabset-margin-container")
536              ) {
537                const childNodes = prevSib.querySelectorAll(
538                  ".tabset-margin-content"
539                );
540                for (const childEl of childNodes) {
541                  if (childEl.classList.contains(visibleCls)) {
542                    childEl.classList.remove("collapse");
543                  } else {
544                    childEl.classList.add("collapse");
545                  }
546                }
547              }
548            }
549          }
550
551          layoutMarginEls();
552        });
553    }
554  }
555
556  // Manage the visibility of the toc and the sidebar
557  const marginScrollVisibility = manageSidebarVisiblity(marginSidebarEl, {
558    id: "quarto-toc-toggle",
559    titleSelector: "#toc-title",
560    dismissOnClick: true,
561  });
562  const sidebarScrollVisiblity = manageSidebarVisiblity(sidebarEl, {
563    id: "quarto-sidebarnav-toggle",
564    titleSelector: ".title",
565    dismissOnClick: false,
566  });
567  let tocLeftScrollVisibility;
568  if (leftTocEl) {
569    tocLeftScrollVisibility = manageSidebarVisiblity(leftTocEl, {
570      id: "quarto-lefttoc-toggle",
571      titleSelector: "#toc-title",
572      dismissOnClick: true,
573    });
574  }
575
576  // Find the first element that uses formatting in special columns
577  const conflictingEls = window.document.body.querySelectorAll(
578    '[class^="column-"], [class*=" column-"], aside, [class*="margin-caption"], [class*=" margin-caption"], [class*="margin-ref"], [class*=" margin-ref"]'
579  );
580
581  // Filter all the possibly conflicting elements into ones
582  // the do conflict on the left or ride side
583  const arrConflictingEls = Array.from(conflictingEls);
584  const leftSideConflictEls = arrConflictingEls.filter((el) => {
585    if (el.tagName === "ASIDE") {
586      return false;
587    }
588    return Array.from(el.classList).find((className) => {
589      return (
590        className !== "column-body" &&
591        className.startsWith("column-") &&
592        !className.endsWith("right") &&
593        !className.endsWith("container") &&
594        className !== "column-margin"
595      );
596    });
597  });
598  const rightSideConflictEls = arrConflictingEls.filter((el) => {
599    if (el.tagName === "ASIDE") {
600      return true;
601    }
602
603    const hasMarginCaption = Array.from(el.classList).find((className) => {
604      return className == "margin-caption";
605    });
606    if (hasMarginCaption) {
607      return true;
608    }
609
610    return Array.from(el.classList).find((className) => {
611      return (
612        className !== "column-body" &&
613        !className.endsWith("container") &&
614        className.startsWith("column-") &&
615        !className.endsWith("left")
616      );
617    });
618  });
619
620  const kOverlapPaddingSize = 10;
621  function toRegions(els) {
622    return els.map((el) => {
623      const boundRect = el.getBoundingClientRect();
624      const top =
625        boundRect.top +
626        document.documentElement.scrollTop -
627        kOverlapPaddingSize;
628      return {
629        top,
630        bottom: top + el.scrollHeight + 2 * kOverlapPaddingSize,
631      };
632    });
633  }
634
635  let hasObserved = false;
636  const visibleItemObserver = (els) => {
637    let visibleElements = [...els];
638    const intersectionObserver = new IntersectionObserver(
639      (entries, _observer) => {
640        entries.forEach((entry) => {
641          if (entry.isIntersecting) {
642            if (visibleElements.indexOf(entry.target) === -1) {
643              visibleElements.push(entry.target);
644            }
645          } else {
646            visibleElements = visibleElements.filter((visibleEntry) => {
647              return visibleEntry !== entry;
648            });
649          }
650        });
651
652        if (!hasObserved) {
653          hideOverlappedSidebars();
654        }
655        hasObserved = true;
656      },
657      {}
658    );
659    els.forEach((el) => {
660      intersectionObserver.observe(el);
661    });
662
663    return {
664      getVisibleEntries: () => {
665        return visibleElements;
666      },
667    };
668  };
669
670  const rightElementObserver = visibleItemObserver(rightSideConflictEls);
671  const leftElementObserver = visibleItemObserver(leftSideConflictEls);
672
673  const hideOverlappedSidebars = () => {
674    marginScrollVisibility(toRegions(rightElementObserver.getVisibleEntries()));
675    sidebarScrollVisiblity(toRegions(leftElementObserver.getVisibleEntries()));
676    if (tocLeftScrollVisibility) {
677      tocLeftScrollVisibility(
678        toRegions(leftElementObserver.getVisibleEntries())
679      );
680    }
681  };
682
683  window.quartoToggleReader = () => {
684    // Applies a slow class (or removes it)
685    // to update the transition speed
686    const slowTransition = (slow) => {
687      const manageTransition = (id, slow) => {
688        const el = document.getElementById(id);
689        if (el) {
690          if (slow) {
691            el.classList.add("slow");
692          } else {
693            el.classList.remove("slow");
694          }
695        }
696      };
697
698      manageTransition("TOC", slow);
699      manageTransition("quarto-sidebar", slow);
700    };
701    const readerMode = !isReaderMode();
702    setReaderModeValue(readerMode);
703
704    // If we're entering reader mode, slow the transition
705    if (readerMode) {
706      slowTransition(readerMode);
707    }
708    highlightReaderToggle(readerMode);
709    hideOverlappedSidebars();
710
711    // If we're exiting reader mode, restore the non-slow transition
712    if (!readerMode) {
713      slowTransition(!readerMode);
714    }
715  };
716
717  const highlightReaderToggle = (readerMode) => {
718    const els = document.querySelectorAll(".quarto-reader-toggle");
719    if (els) {
720      els.forEach((el) => {
721        if (readerMode) {
722          el.classList.add("reader");
723        } else {
724          el.classList.remove("reader");
725        }
726      });
727    }
728  };
729
730  const setReaderModeValue = (val) => {
731    if (window.location.protocol !== "file:") {
732      window.localStorage.setItem("quarto-reader-mode", val);
733    } else {
734      localReaderMode = val;
735    }
736  };
737
738  const isReaderMode = () => {
739    if (window.location.protocol !== "file:") {
740      return window.localStorage.getItem("quarto-reader-mode") === "true";
741    } else {
742      return localReaderMode;
743    }
744  };
745  let localReaderMode = null;
746
747  const tocOpenDepthStr = tocEl?.getAttribute("data-toc-expanded");
748  const tocOpenDepth = tocOpenDepthStr ? Number(tocOpenDepthStr) : 1;
749
750  // Walk the TOC and collapse/expand nodes
751  // Nodes are expanded if:
752  // - they are top level
753  // - they have children that are 'active' links
754  // - they are directly below an link that is 'active'
755  const walk = (el, depth) => {
756    // Tick depth when we enter a UL
757    if (el.tagName === "UL") {
758      depth = depth + 1;
759    }
760
761    // It this is active link
762    let isActiveNode = false;
763    if (el.tagName === "A" && el.classList.contains("active")) {
764      isActiveNode = true;
765    }
766
767    // See if there is an active child to this element
768    let hasActiveChild = false;
769    for (const child of el.children) {
770      hasActiveChild = walk(child, depth) || hasActiveChild;
771    }
772
773    // Process the collapse state if this is an UL
774    if (el.tagName === "UL") {
775      if (tocOpenDepth === -1 && depth > 1) {
776        // toc-expand: false
777        el.classList.add("collapse");
778      } else if (
779        depth <= tocOpenDepth ||
780        hasActiveChild ||
781        prevSiblingIsActiveLink(el)
782      ) {
783        el.classList.remove("collapse");
784      } else {
785        el.classList.add("collapse");
786      }
787
788      // untick depth when we leave a UL
789      depth = depth - 1;
790    }
791    return hasActiveChild || isActiveNode;
792  };
793
794  // walk the TOC and expand / collapse any items that should be shown
795  if (tocEl) {
796    updateActiveLink();
797    walk(tocEl, 0);
798  }
799
800  // Throttle the scroll event and walk peridiocally
801  window.document.addEventListener(
802    "scroll",
803    throttle(() => {
804      if (tocEl) {
805        updateActiveLink();
806        walk(tocEl, 0);
807      }
808      if (!isReaderMode()) {
809        hideOverlappedSidebars();
810      }
811    }, 5)
812  );
813  window.addEventListener(
814    "resize",
815    throttle(() => {
816      if (tocEl) {
817        updateActiveLink();
818        walk(tocEl, 0);
819      }
820      if (!isReaderMode()) {
821        hideOverlappedSidebars();
822      }
823    }, 10)
824  );
825  hideOverlappedSidebars();
826  highlightReaderToggle(isReaderMode());
827});
828
829tabsets.init();
830axe.init();
831
832function throttle(func, wait) {
833  let waiting = false;
834  return function () {
835    if (!waiting) {
836      func.apply(this, arguments);
837      waiting = true;
838      setTimeout(function () {
839        waiting = false;
840      }, wait);
841    }
842  };
843}
844
845function nexttick(func) {
846  return setTimeout(func, 0);
847}

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.