You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					222 lines
				
				6.4 KiB
			
		
		
			
		
	
	
					222 lines
				
				6.4 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								const headroomChanged = new CustomEvent("quarto-hrChanged", {
							 | 
						||
| 
								 | 
							
								  detail: {},
							 | 
						||
| 
								 | 
							
								  bubbles: true,
							 | 
						||
| 
								 | 
							
								  cancelable: false,
							 | 
						||
| 
								 | 
							
								  composed: false,
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								window.document.addEventListener("DOMContentLoaded", function () {
							 | 
						||
| 
								 | 
							
								  let init = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function throttle(func, wait) {
							 | 
						||
| 
								 | 
							
								    var timeout;
							 | 
						||
| 
								 | 
							
								    return function () {
							 | 
						||
| 
								 | 
							
								      const context = this;
							 | 
						||
| 
								 | 
							
								      const args = arguments;
							 | 
						||
| 
								 | 
							
								      const later = function () {
							 | 
						||
| 
								 | 
							
								        clearTimeout(timeout);
							 | 
						||
| 
								 | 
							
								        timeout = null;
							 | 
						||
| 
								 | 
							
								        func.apply(context, args);
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!timeout) {
							 | 
						||
| 
								 | 
							
								        timeout = setTimeout(later, wait);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function headerOffset() {
							 | 
						||
| 
								 | 
							
								    // Set an offset if there is are fixed top navbar
							 | 
						||
| 
								 | 
							
								    const headerEl = window.document.querySelector("header.fixed-top");
							 | 
						||
| 
								 | 
							
								    if (headerEl) {
							 | 
						||
| 
								 | 
							
								      return headerEl.clientHeight;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      return 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function footerOffset() {
							 | 
						||
| 
								 | 
							
								    const footerEl = window.document.querySelector("footer.footer");
							 | 
						||
| 
								 | 
							
								    if (footerEl) {
							 | 
						||
| 
								 | 
							
								      return footerEl.clientHeight;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      return 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function updateDocumentOffsetWithoutAnimation() {
							 | 
						||
| 
								 | 
							
								    updateDocumentOffset(false);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function updateDocumentOffset(animated) {
							 | 
						||
| 
								 | 
							
								    // set body offset
							 | 
						||
| 
								 | 
							
								    const topOffset = headerOffset();
							 | 
						||
| 
								 | 
							
								    const bodyOffset = topOffset + footerOffset();
							 | 
						||
| 
								 | 
							
								    const bodyEl = window.document.body;
							 | 
						||
| 
								 | 
							
								    bodyEl.setAttribute("data-bs-offset", topOffset);
							 | 
						||
| 
								 | 
							
								    bodyEl.style.paddingTop = topOffset + "px";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // deal with sidebar offsets
							 | 
						||
| 
								 | 
							
								    const sidebars = window.document.querySelectorAll(
							 | 
						||
| 
								 | 
							
								      ".sidebar, .headroom-target"
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    sidebars.forEach((sidebar) => {
							 | 
						||
| 
								 | 
							
								      if (!animated) {
							 | 
						||
| 
								 | 
							
								        sidebar.classList.add("notransition");
							 | 
						||
| 
								 | 
							
								        // Remove the no transition class after the animation has time to complete
							 | 
						||
| 
								 | 
							
								        setTimeout(function () {
							 | 
						||
| 
								 | 
							
								          sidebar.classList.remove("notransition");
							 | 
						||
| 
								 | 
							
								        }, 201);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (window.Headroom && sidebar.classList.contains("sidebar-unpinned")) {
							 | 
						||
| 
								 | 
							
								        sidebar.style.top = "0";
							 | 
						||
| 
								 | 
							
								        sidebar.style.maxHeight = "100vh";
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        sidebar.style.top = topOffset + "px";
							 | 
						||
| 
								 | 
							
								        sidebar.style.maxHeight = "calc(100vh - " + topOffset + "px)";
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // allow space for footer
							 | 
						||
| 
								 | 
							
								    const mainContainer = window.document.querySelector(".quarto-container");
							 | 
						||
| 
								 | 
							
								    if (mainContainer) {
							 | 
						||
| 
								 | 
							
								      mainContainer.style.minHeight = "calc(100vh - " + bodyOffset + "px)";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // link offset
							 | 
						||
| 
								 | 
							
								    let linkStyle = window.document.querySelector("#quarto-target-style");
							 | 
						||
| 
								 | 
							
								    if (!linkStyle) {
							 | 
						||
| 
								 | 
							
								      linkStyle = window.document.createElement("style");
							 | 
						||
| 
								 | 
							
								      window.document.head.appendChild(linkStyle);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    while (linkStyle.firstChild) {
							 | 
						||
| 
								 | 
							
								      linkStyle.removeChild(linkStyle.firstChild);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (topOffset > 0) {
							 | 
						||
| 
								 | 
							
								      linkStyle.appendChild(
							 | 
						||
| 
								 | 
							
								        window.document.createTextNode(`
							 | 
						||
| 
								 | 
							
								      section:target::before {
							 | 
						||
| 
								 | 
							
								        content: "";
							 | 
						||
| 
								 | 
							
								        display: block;
							 | 
						||
| 
								 | 
							
								        height: ${topOffset}px;
							 | 
						||
| 
								 | 
							
								        margin: -${topOffset}px 0 0;
							 | 
						||
| 
								 | 
							
								      }`)
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (init) {
							 | 
						||
| 
								 | 
							
								      window.dispatchEvent(headroomChanged);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    init = true;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // initialize headroom
							 | 
						||
| 
								 | 
							
								  var header = window.document.querySelector("#quarto-header");
							 | 
						||
| 
								 | 
							
								  if (header && window.Headroom) {
							 | 
						||
| 
								 | 
							
								    const headroom = new window.Headroom(header, {
							 | 
						||
| 
								 | 
							
								      tolerance: 5,
							 | 
						||
| 
								 | 
							
								      onPin: function () {
							 | 
						||
| 
								 | 
							
								        const sidebars = window.document.querySelectorAll(
							 | 
						||
| 
								 | 
							
								          ".sidebar, .headroom-target"
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        sidebars.forEach((sidebar) => {
							 | 
						||
| 
								 | 
							
								          sidebar.classList.remove("sidebar-unpinned");
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        updateDocumentOffset();
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      onUnpin: function () {
							 | 
						||
| 
								 | 
							
								        const sidebars = window.document.querySelectorAll(
							 | 
						||
| 
								 | 
							
								          ".sidebar, .headroom-target"
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        sidebars.forEach((sidebar) => {
							 | 
						||
| 
								 | 
							
								          sidebar.classList.add("sidebar-unpinned");
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        updateDocumentOffset();
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								    headroom.init();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let frozen = false;
							 | 
						||
| 
								 | 
							
								    window.quartoToggleHeadroom = function () {
							 | 
						||
| 
								 | 
							
								      if (frozen) {
							 | 
						||
| 
								 | 
							
								        headroom.unfreeze();
							 | 
						||
| 
								 | 
							
								        frozen = false;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        headroom.freeze();
							 | 
						||
| 
								 | 
							
								        frozen = true;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Observe size changed for the header
							 | 
						||
| 
								 | 
							
								  const headerEl = window.document.querySelector("header.fixed-top");
							 | 
						||
| 
								 | 
							
								  if (headerEl && window.ResizeObserver) {
							 | 
						||
| 
								 | 
							
								    const observer = new window.ResizeObserver(
							 | 
						||
| 
								 | 
							
								      throttle(updateDocumentOffsetWithoutAnimation, 50)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    observer.observe(headerEl, {
							 | 
						||
| 
								 | 
							
								      attributes: true,
							 | 
						||
| 
								 | 
							
								      childList: true,
							 | 
						||
| 
								 | 
							
								      characterData: true,
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    window.addEventListener(
							 | 
						||
| 
								 | 
							
								      "resize",
							 | 
						||
| 
								 | 
							
								      throttle(updateDocumentOffsetWithoutAnimation, 50)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    setTimeout(updateDocumentOffsetWithoutAnimation, 500);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // fixup index.html links if we aren't on the filesystem
							 | 
						||
| 
								 | 
							
								  if (window.location.protocol !== "file:") {
							 | 
						||
| 
								 | 
							
								    const links = window.document.querySelectorAll("a");
							 | 
						||
| 
								 | 
							
								    for (let i = 0; i < links.length; i++) {
							 | 
						||
| 
								 | 
							
								      links[i].href = links[i].href.replace(/\/index\.html/, "/");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Fixup any sharing links that require urls
							 | 
						||
| 
								 | 
							
								    // Append url to any sharing urls
							 | 
						||
| 
								 | 
							
								    const sharingLinks = window.document.querySelectorAll(
							 | 
						||
| 
								 | 
							
								      "a.sidebar-tools-main-item"
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    for (let i = 0; i < sharingLinks.length; i++) {
							 | 
						||
| 
								 | 
							
								      const sharingLink = sharingLinks[i];
							 | 
						||
| 
								 | 
							
								      const href = sharingLink.getAttribute("href");
							 | 
						||
| 
								 | 
							
								      if (href) {
							 | 
						||
| 
								 | 
							
								        sharingLink.setAttribute(
							 | 
						||
| 
								 | 
							
								          "href",
							 | 
						||
| 
								 | 
							
								          href.replace("|url|", window.location.href)
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Scroll the active navigation item into view, if necessary
							 | 
						||
| 
								 | 
							
								    const navSidebar = window.document.querySelector("nav#quarto-sidebar");
							 | 
						||
| 
								 | 
							
								    if (navSidebar) {
							 | 
						||
| 
								 | 
							
								      // Find the active item
							 | 
						||
| 
								 | 
							
								      const activeItem = navSidebar.querySelector("li.sidebar-item a.active");
							 | 
						||
| 
								 | 
							
								      if (activeItem) {
							 | 
						||
| 
								 | 
							
								        // Wait for the scroll height and height to resolve by observing size changes on the
							 | 
						||
| 
								 | 
							
								        // nav element that is scrollable
							 | 
						||
| 
								 | 
							
								        const resizeObserver = new ResizeObserver((_entries) => {
							 | 
						||
| 
								 | 
							
								          // The bottom of the element
							 | 
						||
| 
								 | 
							
								          const elBottom = activeItem.offsetTop;
							 | 
						||
| 
								 | 
							
								          const viewBottom = navSidebar.scrollTop + navSidebar.clientHeight;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // The element height and scroll height are the same, then we are still loading
							 | 
						||
| 
								 | 
							
								          if (viewBottom !== navSidebar.scrollHeight) {
							 | 
						||
| 
								 | 
							
								            // Determine if the item isn't visible and scroll to it
							 | 
						||
| 
								 | 
							
								            if (elBottom >= viewBottom) {
							 | 
						||
| 
								 | 
							
								              navSidebar.scrollTop = elBottom;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // stop observing now since we've completed the scroll
							 | 
						||
| 
								 | 
							
								            resizeObserver.unobserve(navSidebar);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        resizeObserver.observe(navSidebar);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								});
							 |