bolo-fantastic/toc-post.ftl

328 lines
11 KiB
Plaintext

<#--
Bolo - A stable and beautiful blogging system based in Solo.
Copyright (c) 2020, https://github.com/adlered
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<div>
<div id="toc"></div>
</div>
<script src="https://www.zeekling.cn/cdn/js/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script>
// initToc()
// function initToc() {
// var toc = $(".post-article ul").first();
// $("#toc").html(toc);
// initRelationship()
// tocFixed()
// }
$(document).ready(function () {
$('#toc').html('');
var postDirectoryBuild = function () {
var postChildren = function children(childNodes, reg) {
var result = [],
isReg = typeof reg === 'object',
isStr = typeof reg === 'string',
node, i, len;
for (i = 0, len = childNodes.length; i < len; i++) {
node = childNodes[i];
if ((node.nodeType === 1 || node.nodeType === 9) &&
(!reg ||
isReg && reg.test(node.tagName.toLowerCase()) ||
isStr && node.tagName.toLowerCase() === reg)) {
result.push(node);
}
}
return result;
},
createPostDirectory = function (article, directory, isDirNum) {
var contentArr = [],
titleId = [],
levelArr, root, level,
currentList, list, li, link, i, len;
levelArr = (function (article, contentArr, titleId) {
var titleElem = postChildren(article.childNodes, /^h\d$/),
levelArr = [],
lastNum = 1,
lastRevNum = 1,
count = 0,
guid = 1,
id = 'directory' + (Math.random() + '').replace(/\D/, ''),
lastRevNum, num, elem;
while (titleElem.length) {
elem = titleElem.shift();
contentArr.push(elem.innerHTML);
num = +elem.tagName.match(/\d/)[0];
if (num > lastNum) {
levelArr.push(1);
lastRevNum += 1;
} else if (num === lastRevNum ||
num > lastRevNum && num <= lastNum) {
levelArr.push(0);
lastRevNum = lastRevNum;
} else if (num < lastRevNum) {
levelArr.push(num - lastRevNum);
lastRevNum = num;
}
count += levelArr[levelArr.length - 1];
lastNum = num;
elem.id = elem.id || (id + guid++);
titleId.push(elem.id);
}
if (count !== 0 && levelArr[0] === 1) levelArr[0] = 0;
return levelArr;
})(article, contentArr, titleId);
currentList = root = document.createElement('ul');
dirNum = [0];
for (i = 0, len = levelArr.length; i < len; i++) {
level = levelArr[i];
if (level === 1) {
list = document.createElement('ul');
if (!currentList.lastElementChild) {
currentList.appendChild(document.createElement('li'));
}
currentList.lastElementChild.appendChild(list);
currentList = list;
dirNum.push(0);
} else if (level < 0) {
level *= 2;
while (level++) {
if (level % 2) dirNum.pop();
currentList = currentList.parentNode;
}
}
dirNum[dirNum.length - 1]++;
li = document.createElement('li');
link = document.createElement('a');
link.href = '#' + titleId[i];
link.innerHTML = !isDirNum ? contentArr[i] :
dirNum.join('.') + ' ' + contentArr[i];
li.appendChild(link);
currentList.appendChild(li);
}
directory.appendChild(root);
};
createPostDirectory(document.getElementById('post-article'), document.getElementById('toc'), false);
};
//建立关联关系
function initRelationship() {
var win = $(window);
var anchors = $('#toc').find('a');
var offset = 200; //偏移量看情况调
win.on('scroll', function () {
var scrollTop = win.scrollTop();
anchors.each(function (i, v) {
var that = $(v);
var id = that.attr('href');
var target = $(id);
if (scrollTop >= target.offset().top - offset) {
anchors.removeClass('active');
anchors.parent().removeClass("lit-active");
that.addClass('active');
that.parent().addClass("lit-active");
}
})
})
}
postDirectoryBuild();
initRelationship();
var dir = $("#toc");
var postdiv = $(".article-content");
var offsetLength = dir.offset().top;
$(document).scroll(function () {
var distance = offsetLength - $(window).scrollTop();
if (distance <= 0) {
if (!dir.hasClass('directory-fixed')) {
dir.addClass('directory-fixed');
}
} else if (distance > 0) {
if (dir.hasClass('directory-fixed')) {
dir.removeClass('directory-fixed');
}
}
});
});
function initRelationship() {
var win = $(window);
var anchors = $('#toc').find('a');
var offset = 200; //偏移量看情况调
win.on('scroll', function () {
var scrollTop = win.scrollTop();
anchors.each(function (i, v) {
var that = $(v);
var id = that.attr('href');
var target = $(id);
if (scrollTop >= target.offset().top - offset) {
anchors.removeClass('active');
anchors.parent().removeClass("lit-active");
that.addClass('active');
that.parent().addClass("lit-active");
}
})
})
}
function tocFixed() {
var dir = $("#toc");
var postdiv = $(".article-content");
var offsetLength = dir.offset().top;
$(document).scroll(function () {
var distance = offsetLength - $(window).scrollTop();
if (distance <= 0) {
if (!dir.hasClass('directory-fixed')) {
dir.addClass('directory-fixed');
}
} else if (distance > 0) {
if (dir.hasClass('directory-fixed')) {
dir.removeClass('directory-fixed');
}
}
});
}
</script>
<style>
#toc {
/*position: fixed;*/
/*left: 44%;*/
display: inline-block;
text-align: left;
margin-top: 20px;
padding-bottom: 20px;
/*width: 260px;*/
/*margin-left: 330px;*/
}
.toc-fixed {
position: fixed;
z-index: 0;
left: 50%;
display: inline-block;
text-align: left;
width: 260px;
top: 40px;
}
#toc > ul:before {
content: "";
position: absolute;
top: 0;
left: 0px;
bottom: 0;
width: 3px;
opacity: .2;
z-index: 1;
}
#toc li, #toc ul {
margin: 0;
padding-left: 0;
list-style: none;
padding-top: 0.3rem;
}
#toc > ul {
position: relative;
}
#toc > ul li::before {
position: relative;
top: 0;
left: -2px;
display: inline-block;
width: 7px;
height: 7px;
content: '';
border-radius: 50%;
z-index: 100;
opacity: 0.5;
vertical-align: middle;
}
#toc > ul > li:hover::before {
opacity: 1;
}
.lit-active::before {
opacity: 1 !important;
}
#toc > ul > li > a {
font-weight: bold;
}
#toc ul li a {
display: inline-table;
white-space: -moz-pre-wrap;
vertical-align: middle;
}
#toc ul li a {
margin-left: -5px;
white-space: nowrap;
width: 200px;
padding-left: 15px;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#toc ul li ul li a {
margin-left: -15px;
white-space: nowrap;
width: 200px;
padding-left: 30px;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#toc ul li ul li ul li a {
display: inline-block;
margin-left: -15px;
padding-left: 35px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 200px;
}
.directory-fixed {
position: fixed;
top: 0rem;
}
</style>