Instantly share code, notes, and snippets.
Last active
December 7, 2023 13:31
-
Save jim60105/117549e3b413f4ec5aeed33095a53de2 to your computer and use it in GitHub Desktop.
在Blogger側邊欄建立Table of Contents (自動TOC目錄)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. | |
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. --> | |
<!-- 將此文件內容完整貼於「版面配置」→「新增小工具」→「HTML/JavaScript」,標題命名為「目錄」--> | |
<div id="tocAnchor_sidebar" style="text-align:left;margin-bottom:10px"> | |
<nav id="toc_sidebar" style="font-size: large;"></nav> | |
</div> | |
<!--Tocbot: https://github.com/tscanlin/tocbot --> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.1.1/tocbot.min.js'></script> | |
<script> | |
(function () { | |
//UI調整 | |
var tocBox = document.getElementById("tocAnchor_sidebar").parentNode.parentNode; | |
var tocTitle = tocBox.getElementsByClassName("title")[0]; | |
var tocInner = document.getElementById("tocAnchor_sidebar").parentNode; | |
//位置初始化 | |
tocBox.style.position = "sticky"; | |
tocBox.style.zIndex = "1"; | |
tocBox.style.bottom = "1px"; | |
tocBox.style.top = "1px"; | |
tocBox.style.background = 'rgba(34, 34, 34, 0.867) none repeat scroll 0% 0%'; | |
tocBox.style.border = 'white 1px solid'; | |
tocBox.style.borderRadius = '10px'; | |
tocTitle.style.cursor = 'pointer'; | |
tocTitle.style.borderBottom = '0px'; | |
tocTitle.style.padding = '15px'; | |
tocInner.style.overflow = 'auto'; | |
tocInner.style.paddingTop = '0px'; | |
tocInner.style.border = '0px'; | |
tocInner.style.transition = 'all 1s ease 0s'; | |
//不是在文章中就隱藏 | |
if (window.location.pathname.search(/\.html$/) < 0) { | |
tocBox.style.display = "none"; | |
tocTitle.style.display = "none"; | |
return; | |
} else { | |
tocBox.style.display = ""; | |
tocTitle.style.display = ""; | |
} | |
//開閉清單 | |
function toctoggleDisplay(open) { | |
//沒有目錄 | |
var tocList = document.getElementsByClassName("toc-list")[0]; | |
if (tocList !== undefined && tocList.children.length == 0) { | |
tocList.innerText = "此頁沒有目錄喔!"; | |
} | |
if (open) { | |
//開啟清單 | |
tocInner.style.maxHeight = '90vh'; | |
tocInner.style.marginTop = '0px'; | |
tocTitle.style.borderBottom = '1px solid'; | |
} else { | |
//關閉清單 | |
tocInner.style.maxHeight = '0vh'; | |
tocInner.style.marginTop = '-15px'; | |
tocTitle.style.borderBottom = '0px'; | |
} | |
} | |
toctoggleDisplay(false); | |
//註冊滑鼠事件 | |
tocBox.addEventListener("mouseover", function () { | |
toctoggleDisplay(true); | |
}, false); | |
tocBox.addEventListener("mouseout", function () { | |
toctoggleDisplay(false); | |
}, false); | |
//TOC | |
//在headings加上id做為錨點 | |
var content = document.querySelector('.post-body'); | |
var headings = content.querySelectorAll('h1, h2, h3, h4, h5, h6, h7'); | |
var headingMap = {}; | |
Array.prototype.forEach.call(headings, function (heading) { | |
if (heading.classList.contains('toc-ignore')) return; | |
var id = heading.id ? heading.id : encodeURI(heading.textContent.trim().toLowerCase() | |
.split(' ').join('-').replace(/[!@#$%^&*():]/ig, '').replace(/\//ig, '-')); | |
headingMap[id] = !isNaN(headingMap[id]) ? ++headingMap[id] : 0; | |
if (headingMap[id]) { | |
heading.id = id + '-' + headingMap[id]; | |
} else { | |
heading.id = id; | |
} | |
}); | |
let option = { | |
// Where to render the table of contents. | |
tocSelector: '#toc_sidebar', | |
// Where to grab the headings to build the table of contents. | |
contentSelector: '.post-body', | |
// Which headings to grab inside of the contentSelector element. | |
headingSelector: 'h1, h2, h3, h4', | |
// Headings that match the ignoreSelector will be skipped. | |
ignoreSelector: '.toc-ignore', | |
// For headings inside relative or absolute positioned containers within content | |
hasInnerContainers: true, | |
// Main class to add to links. | |
linkClass: 'toc-link', | |
// Extra classes to add to links. | |
extraLinkClasses: '', | |
// Class to add to active links, | |
// the link corresponding to the top most heading on the page. | |
activeLinkClass: 'is-active-link', | |
// Main class to add to lists. | |
listClass: 'toc-list', | |
// Extra classes to add to lists. | |
extraListClasses: '', | |
// Class that gets added when a list should be collapsed. | |
isCollapsedClass: 'is-collapsed', | |
// Class that gets added when a list should be able | |
// to be collapsed but isn't necessarily collpased. | |
collapsibleClass: 'is-collapsible', | |
// Class to add to list items. | |
listItemClass: 'toc-list-item', | |
// How many heading levels should not be collpased. | |
// For example, number 6 will show everything since | |
// there are only 6 heading levels and number 0 will collpase them all. | |
// The sections that are hidden will open | |
// and close as you scroll to headings within them. | |
collapseDepth: 0, | |
// Smooth scrolling enabled. | |
scrollSmooth: true, | |
// Smooth scroll duration. | |
scrollSmoothDuration: 420, | |
// Callback for scroll end. | |
scrollEndCallback: null, | |
// Headings offset between the headings and the top of the document (this is meant for minor adjustments). | |
headingsOffset: 1, | |
// Timeout between events firing to make sure it's | |
// not too rapid (for performance reasons). | |
throttleTimeout: 50, | |
// Element to add the positionFixedClass to. | |
positionFixedSelector: null, | |
// Fixed position class to add to make sidebar fixed after scrolling | |
// down past the fixedSidebarOffset. | |
positionFixedClass: 'is-position-fixed', | |
// fixedSidebarOffset can be any number but by default is set | |
// to auto which sets the fixedSidebarOffset to the sidebar | |
// element's offsetTop from the top of the document on init. | |
fixedSidebarOffset: 'auto', | |
// includeHtml can be set to true to include the HTML markup from the | |
// heading node instead of just including the textContent. | |
includeHtml: false, | |
// orderedList can be set to false to generate unordered lists (ul) | |
// instead of ordered lists (ol) | |
orderedList: false, | |
// If there is a fixed article scroll container, set to calculate titles' offset | |
scrollContainer: null, | |
// prevent ToC DOM rendering if it's already rendered by an external system | |
skipRendering: true, | |
// Optional callback to change heading labels. | |
// For example it can be used to cut down and put ellipses on multiline headings you deem too long. | |
// Called each time a heading is parsed. Expects a string in return, the modified label to display. | |
// function (string) => string | |
headingLabelCallback: false, | |
// ignore headings that are hidden in DOM | |
ignoreHiddenElements: false, | |
// Optional callback to modify properties of parsed headings. | |
// The heading element is passed in node parameter and information parsed by default parser is provided in obj parameter. | |
// Function has to return the same or modified obj. | |
// The heading will be excluded from TOC if nothing is returned. | |
// function (object, HTMLElement) => object | void | |
headingObjectCallback: null, | |
// onclick function to apply to all links in toc. will be called with | |
// the event as the first parameter, and this can be used to stop, | |
// propagation, prevent default or perform action | |
onClick: null | |
}; | |
tocbot.init(option); | |
tocbot.refresh(); | |
if (!!document.getElementById('toc_in_page')) { | |
option.tocSelector = '#toc_in_page'; | |
tocbot.init(option); | |
tocbot.refresh(); | |
} | |
})(); | |
</script> |
在文章內的任一處插入以下程式碼,就能在文章內產生目錄
<nav id="toc_in_page"></nav>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Preview