目录悬浮
This commit is contained in:
parent
e6b0407b07
commit
10ac27a069
|
@ -77,24 +77,36 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
|
||||
// 滚动处理
|
||||
const scrollFnToDo = function () {
|
||||
let $cardTocLayout = document.getElementById("card-toc");
|
||||
// let $cardToc = $cardTocLayout.getElementsByClassName("toc-content")[0];
|
||||
// let $tocLink = $cardToc.querySelectorAll(".toc-link");
|
||||
let $article = document.getElementById("article-container");
|
||||
|
||||
// let scrollPercent;
|
||||
// if (GLOBAL_CONFIG.htmlType === 'post') {
|
||||
// scrollPercent = function (currentTop) {
|
||||
// const docHeight = $article.clientHeight;
|
||||
// const winHeight = document.documentElement.clientHeight;
|
||||
// const headerHeight = $article.offsetTop;
|
||||
// const contentMath = (docHeight > winHeight) ? (docHeight - winHeight) : (document.documentElement.scrollHeight - winHeight)
|
||||
// const scrollPercent = (currentTop - headerHeight) / (contentMath);
|
||||
// const scrollPercentRounded = Math.round(100 * scrollPercent);
|
||||
// const percentage = 100 < scrollPercentRounded ? 100 : scrollPercentRounded <= 0 ? 0 : scrollPercentRounded;
|
||||
// $cardToc.setAttribute("progress-percentage", percentage);
|
||||
// };
|
||||
// }
|
||||
const isToc = GLOBAL_CONFIG.htmlType === 'post';
|
||||
const isAnchor = true;
|
||||
const $article = document.getElementById("article-container");
|
||||
|
||||
if (!($article && (isToc || isAnchor))) return
|
||||
|
||||
let $tocLink, $cardToc, scrollPercent, autoScrollToc, isExpand
|
||||
|
||||
if (isToc) {
|
||||
|
||||
const $cardTocLayout = document.getElementById("card-toc");
|
||||
$cardToc = $cardTocLayout.getElementsByClassName("toc-content")[0];
|
||||
$tocLink = $cardToc.querySelectorAll(".toc-link");
|
||||
|
||||
// const $tocPercentage = $cardTocLayout.querySelector(".toc-percentage");
|
||||
isExpand = $cardToc.classList.contains("is-expand");
|
||||
|
||||
scrollPercent = function (currentTop) {
|
||||
const docHeight = $article.clientHeight;
|
||||
const winHeight = document.documentElement.clientHeight;
|
||||
const headerHeight = $article.offsetTop;
|
||||
const contentMath = (docHeight > winHeight) ? (docHeight - winHeight) : (document.documentElement.scrollHeight - winHeight);
|
||||
const scrollPercent = (currentTop - headerHeight) / (contentMath);
|
||||
const scrollPercentRounded = Math.round(scrollPercent * 100);
|
||||
const percentage = (scrollPercentRounded > 100) ? 100 : (scrollPercentRounded <= 0) ? 0 : scrollPercentRounded;
|
||||
// $tocPercentage.textContent = percentage
|
||||
$cardToc.setAttribute("progress-percentage", percentage);
|
||||
};
|
||||
|
||||
|
||||
window.mobileToc = {
|
||||
open: () => {
|
||||
|
@ -110,79 +122,90 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
}
|
||||
|
||||
// toc 元素点击
|
||||
// $cardToc.addEventListener("click", e => {
|
||||
// e.preventDefault();
|
||||
// const target = e.target.classList.contains("toc-link") ? e.target : e.target.parentElement;
|
||||
//
|
||||
// btf.scrollToDest(
|
||||
// btf.getEleTop(
|
||||
// document.getElementById(
|
||||
// decodeURI(target.getAttribute("href")).replace("#", "")
|
||||
// )
|
||||
// ),
|
||||
// 300
|
||||
// );
|
||||
// if (window.innerWidth < 900) {
|
||||
// window.mobileToc.close();
|
||||
// }
|
||||
// });
|
||||
$cardToc.addEventListener("click", e => {
|
||||
e.preventDefault();
|
||||
const target = e.target.classList;
|
||||
if (target.contains('toc-content')) return;
|
||||
const $target = e.target.classList.contains("toc-link") ? e.target : e.target.parentElement;
|
||||
|
||||
btf.scrollToDest(btf.getEleTop(document.getElementById(decodeURI($target.getAttribute("href")).replace("#", ""))), 300);
|
||||
if (window.innerWidth < 900) {
|
||||
window.mobileToc.close()
|
||||
}
|
||||
});
|
||||
|
||||
autoScrollToc = item => {
|
||||
const activePosition = item.getBoundingClientRect().top
|
||||
const sidebarScrollTop = $cardToc.scrollTop
|
||||
if (activePosition > (document.documentElement.clientHeight - 100)) {
|
||||
$cardToc.scrollTop = sidebarScrollTop + 150
|
||||
}
|
||||
if (activePosition < 100) {
|
||||
$cardToc.scrollTop = sidebarScrollTop - 150
|
||||
}
|
||||
};
|
||||
}
|
||||
// find head position & add active class
|
||||
// const list = $article.querySelectorAll("h1,h2,h3,h4,h5,h6");
|
||||
// let detectItem = "";
|
||||
// const findHeadPosition = function (top) {
|
||||
//
|
||||
// if (0 === $tocLink.length || 0 === top) {
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// let currentId = "";
|
||||
// let currentIndex = "";
|
||||
//
|
||||
// list.forEach(function (ele, index) {
|
||||
// if (top > btf.getEleTop(ele) - 80) {
|
||||
// currentId = "#" + encodeURI(ele.getAttribute("id"));
|
||||
// currentIndex = index
|
||||
// }
|
||||
//
|
||||
// })
|
||||
// if (detectItem === currentIndex) {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// detectItem = currentIndex
|
||||
//
|
||||
// $cardToc.querySelectorAll(".active").forEach(i => {
|
||||
// i.classList.remove("active")
|
||||
// })
|
||||
//
|
||||
// if (currentId === "") {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// const currentActive = $tocLink[currentIndex]
|
||||
// currentActive.classList.add("active")
|
||||
//
|
||||
// setTimeout(() => {
|
||||
// autoScrollToc(currentActive)
|
||||
// }, 0)
|
||||
//
|
||||
// if (isExpand) return
|
||||
// let parent = currentActive.parentNode
|
||||
//
|
||||
// for (; !parent.matches(".toc"); parent = parent.parentNode) {
|
||||
// if (parent.matches("li")) parent.classList.add("active")
|
||||
// }
|
||||
// }
|
||||
const list = $article.querySelectorAll("h1,h2,h3,h4,h5,h6");
|
||||
let detectItem = "";
|
||||
const findHeadPosition = function (top) {
|
||||
|
||||
// window.tocScrollFn = function () {
|
||||
// return btf.throttle(function () {
|
||||
// let currentTop = window.scrollY || document.documentElement.scrollTop;
|
||||
// // scrollPercent(currentTop)
|
||||
// findHeadPosition(currentTop);
|
||||
// }, 100)();
|
||||
// };
|
||||
// window.addEventListener("scroll", tocScrollFn);
|
||||
if (0 === $tocLink.length || 0 === top) {
|
||||
return false
|
||||
}
|
||||
|
||||
let currentId = "";
|
||||
let currentIndex = "";
|
||||
|
||||
list.forEach(function (ele, index) {
|
||||
if (top > btf.getEleTop(ele) - 80) {
|
||||
const id = ele.id
|
||||
currentId = id ? "#" + encodeURI(id) : ""
|
||||
currentIndex = index
|
||||
}
|
||||
|
||||
})
|
||||
if (detectItem === currentIndex) {
|
||||
return
|
||||
}
|
||||
|
||||
if (isAnchor) btf.updateAnchor(currentId);
|
||||
|
||||
detectItem = currentIndex
|
||||
|
||||
if (isToc) {
|
||||
$cardToc.querySelectorAll(".active").forEach(i => {
|
||||
i.classList.remove("active")
|
||||
});
|
||||
if (currentId === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentActive = $tocLink[currentIndex];
|
||||
|
||||
currentActive.classList.add("active");
|
||||
|
||||
setTimeout(() => {
|
||||
autoScrollToc(currentActive)
|
||||
}, 0);
|
||||
|
||||
if (isExpand) return;
|
||||
let parent = currentActive.parentNode;
|
||||
|
||||
for (; !parent.matches(".toc-list"); parent = parent.parentNode) {
|
||||
if (parent.matches("li")) parent.classList.add("active")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.tocScrollFn = function () {
|
||||
return btf.throttle(function () {
|
||||
let currentTop = window.scrollY || document.documentElement.scrollTop;
|
||||
scrollPercent(currentTop)
|
||||
findHeadPosition(currentTop);
|
||||
}, 100)();
|
||||
};
|
||||
window.addEventListener("scroll", tocScrollFn);
|
||||
};
|
||||
|
||||
const tabsFn = {
|
||||
|
|
|
@ -179,6 +179,17 @@ const btf = {
|
|||
}
|
||||
|
||||
return actualTop
|
||||
},
|
||||
|
||||
updateAnchor: (anchor) => {
|
||||
if (anchor !== window.location.hash) {
|
||||
if (!anchor) anchor = location.pathname
|
||||
const title = "123111111111"
|
||||
window.history.replaceState({
|
||||
url: location.href,
|
||||
title: title
|
||||
}, title, anchor)
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -1,13 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<!-- 侧边栏 -->
|
||||
<div class="aside-content" id="aside-content" th:fragment="aside(widgets)"
|
||||
th:if="${theme.config.sidebar.location != 'hide-aside' && not #strings.isEmpty(widgets)}">
|
||||
|
||||
<!-- 侧栏部件不确定都有什么 -->
|
||||
<!-- 侧栏部件,不包含 toc 则直接遍历 -->
|
||||
<th:block th:if="${not #strings.contains(widgets, 'toc')}">
|
||||
<th:block th:each="widget : ${#strings.listSplit(widgets, ',')}">
|
||||
<th:block th:replace="'modules/widgets/aside/'+ ${widget}"/>
|
||||
</th:block>
|
||||
</th:block>
|
||||
|
||||
<!-- 侧栏部件,toc 之后的组件需要被 sticky_layout 包裹 -->
|
||||
<th:block th:if="${#strings.contains(widgets, 'toc')}">
|
||||
|
||||
<th:block th:each="widget : ${#strings.listSplit(#strings.substringBefore(widgets, 'toc'), ',')}">
|
||||
|
||||
<th:block th:replace="'modules/widgets/aside/'+ ${widget}"/>
|
||||
</th:block>
|
||||
|
||||
<!-- toc 之后的组件需要被 sticky_layout 包裹 -->
|
||||
<div class="sticky_layout">
|
||||
<th:block th:replace="modules/widgets/aside/toc :: toc"/>
|
||||
|
||||
<th:block th:each="widget : ${#strings.listSplit(#strings.substringAfter(widgets, 'toc'), ',')}">
|
||||
<th:block th:replace="'modules/widgets/aside/'+ ${widget}"/>
|
||||
</th:block>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
|
||||
</div>
|
||||
|
|
|
@ -47,10 +47,9 @@
|
|||
});
|
||||
tocbot.init({
|
||||
tocSelector: '.toc-content',
|
||||
contentSelector: '.post-content',
|
||||
contentSelector: content,
|
||||
headingSelector: headerEl,
|
||||
hasInnerContainers: true,
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue