From fac6dc30f3ee94dbdab368db04bc0ac254fe6cf0 Mon Sep 17 00:00:00 2001 From: liuzhihang Date: Thu, 27 Oct 2022 09:23:43 +0800 Subject: [PATCH] =?UTF-8?q?toc=20js=20=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/assets/js/main.js | 151 ++++++++++++++++++++++++------------ 1 file changed, 103 insertions(+), 48 deletions(-) diff --git a/templates/assets/js/main.js b/templates/assets/js/main.js index 451ae62e..c46edd9f 100644 --- a/templates/assets/js/main.js +++ b/templates/assets/js/main.js @@ -23,56 +23,111 @@ document.addEventListener("DOMContentLoaded", function () { } } - function S() { - var t = document.getElementById("card-toc"), r = t.getElementsByClassName("toc-content")[0], - s = r.querySelectorAll(".toc-link"), c = document.getElementById("article-container"); + function scrollFnToDo() { + const $cardTocLayout = document.getElementById("card-toc"); + const $cardToc = $cardTocLayout.getElementsByClassName("toc-content")[0]; + const $tocLink = $cardToc.querySelectorAll(".toc-link"); + const $article = document.getElementById("article-container"); window.tocScrollFn = function () { return btf.throttle(function () { - var t = window.scrollY || document.documentElement.scrollTop; - e(t), i(t) - }, 100)() - }; - window.addEventListener("scroll", tocScrollFn); - var e = function (t) { - var e = c.clientHeight, n = document.documentElement.clientHeight, - o = (t - c.offsetTop) / (n < e ? e - n : document.documentElement.scrollHeight - n), - i = Math.round(100 * o), a = 100 < i ? 100 : i <= 0 ? 0 : i; - r.setAttribute("progress-percentage", a) - }, o = function () { - t.style.animation = "toc-close .2s", setTimeout(function () { - t.style.cssText = "opacity:''; animation: ''; right: ''" - }, 100) - }; - document.getElementById("mobile-toc-button").addEventListener("click", function () { - ("0" === window.getComputedStyle(t).getPropertyValue("opacity") ? n : o)() - }); - r.addEventListener("click", function (t) { - t.preventDefault(); - var e = t.target.classList.contains("toc-link") ? t.target : t.target.parentElement; - btf.scrollToDest(btf.getEleTop(document.getElementById(decodeURI(e.getAttribute("href")).replace("#", ""))), 300), window.innerWidth < 900 && o() - }); - var d = c.querySelectorAll("h1,h2,h3,h4,h5,h6"), u = "", i = function (n) { - if (0 === s.length || 0 === n) return !1; - var t, e, o = "", i = ""; - if (d.forEach(function (t, e) { - n > btf.getEleTop(t) - 80 && (o = "#" + encodeURI(t.getAttribute("id")), i = e) - }), u !== i) { - if (l && (t = o, window.history.replaceState && t !== window.location.hash && (t = t || location.pathname, e = GLOBAL_CONFIG_SITE.title, window.history.replaceState({ - url: location.href, title: e - }, e, t))), "" === o) return r.querySelectorAll(".active").forEach(function (t) { - t.classList.remove("active") - }), void (u = i); - u = i, r.querySelectorAll(".active").forEach(function (t) { - t.classList.remove("active") - }); - var a = s[i]; - a.classList.add("active"), setTimeout(function () { - var t, e; - t = a.getBoundingClientRect().top, e = r.scrollTop, t > document.documentElement.clientHeight - 100 && (r.scrollTop = e + 150), t < 100 && (r.scrollTop = e - 150) - }, 0); - for (var c = a.parentNode; !c.matches(".toc"); c = c.parentNode) c.matches("li") && c.classList.add("active") - } + const currentTop = window.scrollY || document.documentElement.scrollTop; + scrollPercent(currentTop) + findHeadPosition(currentTop); + }, 100)(); } + window.addEventListener("scroll", tocScrollFn); + + function scrollPercent(currentTop) { + const docHeight = $article.clientHeight; + const winHeight = document.documentElement.clientHeight; + const headerHeight = $article.offsetTop; + const scrollPercent = (currentTop - headerHeight) / + (winHeight < docHeight ? docHeight - winHeight : document.documentElement.scrollHeight - winHeight); + const scrollPercentRounded = Math.round(100 * scrollPercent); + const percentage = 100 < scrollPercentRounded ? 100 : scrollPercentRounded <= 0 ? 0 : scrollPercentRounded; + $cardToc.setAttribute("progress-percentage", percentage); + } + + var l = GLOBAL_CONFIG.isanchor + + function close() { + $cardTocLayout.style.animation = "toc-close .2s"; + setTimeout(function () { + $cardTocLayout.style.cssText = "opacity:''; animation: ''; right: ''"; + }, 100); + } + + function open() { + $cardTocLayout.style.cssText = "animation: toc-open .3s; opacity: 1; right: 45px"; + } + + // + document.getElementById("mobile-toc-button") + .addEventListener("click", function () { + ("0" === window.getComputedStyle($cardTocLayout).getPropertyValue("opacity") + ? open() + : close())(); + }); + // 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); + window.innerWidth < 900 && close(); + }); + + // 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 !1; + var t, + e, + o = "", + i = ""; + if ((list.forEach(function (ele, index) { + top > btf.getEleTop(ele) - 80 && + ((o = "#" + encodeURI(ele.getAttribute("id"))), (i = index)); + }), detectItem !== i) + ) { + if ( + (l && + ((t = o), + window.history.replaceState && + t !== window.location.hash && + ((t = t || location.pathname), + (e = GLOBAL_CONFIG_SITE.title), + window.history.replaceState( + {url: location.href, title: e}, + e, + t + ))), + "" === o) + ) + return ( + $cardToc.querySelectorAll(".active").forEach(function (t) { + t.classList.remove("active"); + }), + void (detectItem = i) + ); + (detectItem = i), + $cardToc.querySelectorAll(".active").forEach(function (t) { + t.classList.remove("active"); + }); + var a = $tocLink[i]; + a.classList.add("active"), + setTimeout(function () { + var t, e; + (t = a.getBoundingClientRect().top), + (e = $cardToc.scrollTop), + t > document.documentElement.clientHeight - 100 && + ($cardToc.scrollTop = e + 150), + t < 100 && ($cardToc.scrollTop = e - 150); + }, 0); + for (var c = a.parentNode; !c.matches(".toc"); c = c.parentNode) + c.matches("li") && c.classList.add("active"); + } + }; } var d = !1, n = function () { @@ -111,7 +166,7 @@ document.addEventListener("DOMContentLoaded", function () { f.style.overflow = "", f.style.paddingRight = "", btf.fadeOut(u, .5), d.classList.remove("open") } - adjustMenu(), document.getElementById("nav").classList.add("show"), GLOBAL_CONFIG_SITE.isPost ? (GLOBAL_CONFIG_SITE.isToc && S(), void 0 !== GLOBAL_CONFIG.noticeOutdate && (r = GLOBAL_CONFIG.noticeOutdate, (s = btf.diffDate(GLOBAL_CONFIG_SITE.postUpdate)) >= r.limitDay && ((a = document.createElement("div")).className = "post-outdate-notice", a.textContent = r.messagePrev + " " + s + " " + r.messageNext, c = document.getElementById("article-container"), "top" === r.position ? c.insertBefore(a, c.firstChild) : c.appendChild(a))), GLOBAL_CONFIG.relativeDate.post && I(document.querySelectorAll("#post-meta time"))) : (GLOBAL_CONFIG.relativeDate.homepage && I(document.querySelectorAll("#recent-posts time")), !GLOBAL_CONFIG.runtime || (i = document.getElementById("runtimeshow")) && (o = i.getAttribute("data-publishDate"), i.innerText = btf.diffDate(o) + " " + GLOBAL_CONFIG.runtime), (n = document.getElementById("last-push-date")) && (e = n.getAttribute("data-lastPushDate"), n.innerText = btf.diffDate(e, !0)), (t = document.querySelectorAll("#aside-cat-list .card-category-list-item.parent i")).length && t.forEach(function (t) { + adjustMenu(), document.getElementById("nav").classList.add("show"), GLOBAL_CONFIG_SITE.isPost ? (GLOBAL_CONFIG_SITE.isToc && scrollFnToDo(), void 0 !== GLOBAL_CONFIG.noticeOutdate && (r = GLOBAL_CONFIG.noticeOutdate, (s = btf.diffDate(GLOBAL_CONFIG_SITE.postUpdate)) >= r.limitDay && ((a = document.createElement("div")).className = "post-outdate-notice", a.textContent = r.messagePrev + " " + s + " " + r.messageNext, c = document.getElementById("article-container"), "top" === r.position ? c.insertBefore(a, c.firstChild) : c.appendChild(a))), GLOBAL_CONFIG.relativeDate.post && I(document.querySelectorAll("#post-meta time"))) : (GLOBAL_CONFIG.relativeDate.homepage && I(document.querySelectorAll("#recent-posts time")), !GLOBAL_CONFIG.runtime || (i = document.getElementById("runtimeshow")) && (o = i.getAttribute("data-publishDate"), i.innerText = btf.diffDate(o) + " " + GLOBAL_CONFIG.runtime), (n = document.getElementById("last-push-date")) && (e = n.getAttribute("data-lastPushDate"), n.innerText = btf.diffDate(e, !0)), (t = document.querySelectorAll("#aside-cat-list .card-category-list-item.parent i")).length && t.forEach(function (t) { t.addEventListener("click", function (t) { t.preventDefault(); this.classList.toggle("expand");