转换成带有toc的html,JavaScript生成TOC

本人为Javascript菜鸟,有问题请指正...

TOC目录

最近用Flask搭建个人博客在制作文章显示页面时,需要在前端页面生成TOC。就打算自己写一个JavaScript脚本。

需要生成的目标HTML代码如下:

...

在看了JavaScript权威指南这本书后,发现其中虽然有例子生成TOC,但是并没有显示层级。不过,其中有一个记录TOC各个锚点序号的好方法:

# 使用一个数组报错

var sectionNumbers = [0,0,0,0,0,0]

# 取各级标题的level,如

的level为1

var level = parseInt(header.tagName.charAt(1));

# 当处理一个标签后,计算加1

sectionNumbers[level-1]++

# 然后去当前序号 比如序号为2.1.1

sectionNumber = sectionNumbers.slice(0,level).join('.')

分析算法逻辑

吹牛B之前需要打草稿,写代码之前也如此。

刚开始很纠结如何生成有层级结构的HTML代码,最后发现可以使用设计模式中的组合模式来完成这一功能。具体点就是将li节点看作叶子节点,ul节点看错作容器。那么就有一下限制:

只有ul节点可以插入li节点

li节点需要插入子节点,就需要创建一个ul子节点,让子节点去插入li节点

ul与它的li子节点level相同

如果当前节点需要处理一个header,就需要作出以下判断:

判断自己为ul节点还是li节点

如果为ul节点,且待处理的header的level与自己相同,那么就直接生成一个li节点并插入;如果待处理的header的level比自己大,那么就找到子节点,交给子节点去处理。

如果为li节点,且待处理的header的level比自己大,那么就取li节点的ul节点,交给ul节点去处理

一直向下去处理header,直到插入成功

代码实现

为了尽量减少代码的污染,使用Fucntion.call(args)方式了动态的给节点添加属性:

var sectionNumbers = [0, 0, 0, 0, 0, 0];

function Toc() {

this.headers = $(this).find(':header');

var ul = document.createElement('ul');

this.toc = TocObj.call(ul, 1);

for(var i = 0; i < this.headers.length; i++) {

// if(i > 1) break;

this.toc.add(this.headers[i]);

}

console.log(this.toc);

}

function TocObj(level) {

this.level = level;

this.num = 0;

this.add = function(header) {

var flag = this.tagName == 'UL'; // ul节点和li节点处理header的方式不通过

var level = parseInt(header.tagName.charAt(1));

if(flag) { // 只有ul节点才能插入li

if(this.num == 0 || level == this.level) {

var link = document.createElement('a');

link.href = '';

link.innerHTML = header.innerHTML;

sectionNumbers[level-1]++;

for(var i = level; i < sectionNumbers.length; i++) sectionNumbers[i] = 0;

link.href = "#TOC" + sectionNumbers.slice(0, level).join('.');

var li = document.createElement('li');

li.insertBefore(link, li.firstChild);

this.num++;

this.appendChild(TocObj.call(li, level));

} else if(level > this.level){

if(this.num == 0) {

throw new Error("level error 1");

}

var lastChild = this.lastChild;

lastChild.add(header); // 让ul节点的li节点去处理header

}

} else { // li节点让它的ul子节点去插入li

if(level == this.level) {

throw new Error("level error 2");

} else if(level > this.level){

if(this.num == 0) { // 没有ul子节点,就创建一个

var ul = document.createElement('ul');

this.appendChild(ul);

this.num++;

TocObj.call(ul, level).add(header); // 注意设置level

} else {

var lastChild = this.lastChild;

lastChild.add(header); //让ul节点去处理这个header

}

}

}

}

return this;

}

var toc = document.getElementsByClassName('post')[0];

Toc.call(toc);

效果展示

对于有以下结构的HTML代码:

标题1

标题1.1

标题1.2

标题2

标题2.1

标题2.1.1

标题3

标题4

标题5

输出结构如下:

bVtfQh

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值