Skip to content

Instantly share code, notes, and snippets.

@jim60105
Last active December 7, 2023 13:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jim60105/117549e3b413f4ec5aeed33095a53de2 to your computer and use it in GitHub Desktop.
Save jim60105/117549e3b413f4ec5aeed33095a53de2 to your computer and use it in GitHub Desktop.
在Blogger側邊欄建立Table of Contents (自動TOC目錄)
<!-- 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>
@jim60105
Copy link
Author

jim60105 commented Jan 9, 2021

Preview

toc_in

@jim60105
Copy link
Author

jim60105 commented Jan 9, 2021

注意

必須要讓小工具的上層div之高度填滿整頁,才能達到圖中效果
2021-01-10 02 06 58

@jim60105
Copy link
Author

在文章內的任一處插入以下程式碼,就能在文章內產生目錄

<nav id="toc_in_page"></nav>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment