+
{%- for text in panels.keys() %}
diff --git a/docs/theme/Header.jinja b/docs/theme/Header.jinja
index c8322df..1b719cf 100644
--- a/docs/theme/Header.jinja
+++ b/docs/theme/Header.jinja
@@ -4,12 +4,12 @@
{% set title = title or page.title %}
diff --git a/docs/theme/NavTop.jinja b/docs/theme/NavTop.jinja
index 7ee0052..f9ecc87 100644
--- a/docs/theme/NavTop.jinja
+++ b/docs/theme/NavTop.jinja
@@ -11,7 +11,7 @@
diff --git a/docs/theme/TocPage.jinja b/docs/theme/TocPage.jinja
index bca5c92..754b624 100644
--- a/docs/theme/TocPage.jinja
+++ b/docs/theme/TocPage.jinja
@@ -2,7 +2,9 @@
{% macro render_sub_items(pages) %}
{%- for section in pages %}
-
{{ section.name }}
+
+ {{ section.name }}
+
{% if section.level <= max_depth -%}
{{ render_sub_items(section.children) }}
{%- endif %}
@@ -11,7 +13,9 @@
diff --git a/docs/theme/TocPage.js b/docs/theme/TocPage.js
index 3ce5e02..77bad1e 100644
--- a/docs/theme/TocPage.js
+++ b/docs/theme/TocPage.js
@@ -1,49 +1,97 @@
import { on } from "./jxui.js";
const ACTIVE = "active";
-const SEL_TARGET = ".cd-toc-page a";
+const SEL_BACKTOTOP = ".cd-back-to-top"
+const SEL_PAGETOC = ".cd-toc-page"
+const SEL_TARGET = `${SEL_PAGETOC} a`;
const SEL_ACTIVE = `${SEL_TARGET}.${ACTIVE}`;
-const SEL_SECTIONS = "main.page section[id]";
+const SEL_PAGE = "#main.page";
+const SEL_SECTIONS = `${SEL_PAGE} section[id]`;
+const DESKTOP_THRESHOLD = 1024;
on("click", SEL_TARGET, handleClick);
+on("click", SEL_BACKTOTOP, backToTop);
-function handleClick (event, target) {
- deActivateAll();
- target.classList.add(ACTIVE);
+function handleClick(event, target) {
+ removeHighlight();
+ setTimeout(function () { updateHighlight(target) }, 10);
}
-/* =========================================================== */
+function updateHighlight (elem) {
+ if (window.innerWidth > DESKTOP_THRESHOLD && !elem?.classList.contains(ACTIVE)) {
+ removeHighlight();
+ if (!elem) return;
+ elem.classList.add(ACTIVE);
+ }
+}
-function deActivateAll() {
+function removeHighlight () {
document.querySelectorAll(SEL_ACTIVE).forEach(function (node) {
node.classList.remove(ACTIVE);
});
}
+function resetNavPosition () {
+ var pagetoc = document.querySelector(SEL_TOC);
+ pagetoc?.scroll({ top: 0 });
+}
+
+export function backToTop () {
+ window.scrollTo({ top: 0, behavior: "smooth" });
+ resetNavPosition();
+}
+
export function scrollSpy() {
- const labels = {};
- Array.from(document.querySelectorAll(SEL_TARGET)).forEach(function(aNode){
- labels[aNode.href.split("#").slice(-1)] = aNode;
- });
+ const sections = Array.from(document.querySelectorAll(SEL_SECTIONS));
- function observe(entries) {
- for(const entry of entries) {
- if (entry.isIntersecting) {
- const aNode = labels[entry.target.id];
- if (aNode) {
- deActivateAll();
- aNode.classList.add(ACTIVE)
- }
+ function matchingNavLink(elem) {
+ if (!elem) return;
+ var index = sections.indexOf(elem);
+
+ var match;
+ while (index >= 0 && !match) {
+ var sectionId = sections[index].getAttribute("id");
+ if (sectionId) {
+ match = document.querySelector(`${SEL_PAGETOC} [href="#${sectionId}"]`);
}
+ index--;
}
+ return match;
}
- const observer = new IntersectionObserver(observe, {rootMargin: "-50% 0px"});
- const sections = document.querySelectorAll(SEL_SECTIONS);
- console.log(labels);
- console.log(sections);
- for (let i=0; i
(i.rootBounds.bottom + i.rootBounds.top) / 2;
}
+
+ function prevElem(elem) {
+ var index = sections.indexOf(elem);
+ if (index <= 0) {
+ return null;
+ }
+ return sections[index - 1];
+ }
+
+ const PAGE_LOAD_BUFFER = 1000;
+
+ function navHighlight(entries) {
+ entries.forEach(function (entry) {
+ if (entry.isIntersecting) {
+ updateHighlight(matchingNavLink(entry.target));
+ } else if (entry.time >= PAGE_LOAD_BUFFER && belowBottomHalf(entry)) {
+ updateHighlight(matchingNavLink(prevElem(entry.target)));
+ }
+ });
+ }
+
+ const observer = new IntersectionObserver(navHighlight, {
+ threshold: 0,
+ rootMargin: "0% 0px -95% 0px"
+ });
+
+ sections.forEach(function (elem) {
+ observer.observe(elem);
+ })
+ observer.observe(document.querySelector(SEL_PAGE));
}
document.addEventListener("DOMContentLoaded", scrollSpy);