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

TOC目录

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

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

  • 标题1
  • 标题2
    • 标题2.1
    • 标题2.2
      • 标题2.2.1

...

在看了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

输出结构如下:

转换成带有toc的html,JavaScript生成TOC相关推荐

  1. 将字符转换成带有圆圈的字符

    将字符转换成带有圆圈的字符 private string Convert(int m) { switch (m) { case 1: return "①"; case 2: ret ...

  2. html转换成pdf工具-wkhtmltopdf、Python生成PDF(pdfkit库)

    文章目录 一.html转换成pdf工具-wkhtmltopdf 1. 什么是wkhtmltopdf 2. 如何使用它? 3. 常见问题 error while loading shared libra ...

  3. 数字货币转换成大写货币金额的JAvascript代码

    用JavaScript编写了一功能函数,完成如下功能: 1.对一给定字符串,如:1234.55,转换成正确的中文货币描述:如:人民币壹仟贰佰叁拾四元五角五分 2.输入的字符串形式可以是以下几种:带分隔 ...

  4. js生成html转换成图片保存,js将html生成为图片,并保存在本地

    html生成图片的方式有很多种,有的需要下载安装插件,如phantomjs .显得未免麻烦了些,有的又是通过后台来实现的,但个人感觉没必要做这种交互,也没必要在服务端生成这些零时文件,那么问题来了,有 ...

  5. 一连串数字怎么转换成二维码?数字生成二维码如何制作?

    当我们使用二维码内容做成数字时该如何制作呢,比如做成标签码,序号码,号码牌等等,都可以使用数字二维码来展示,那么如何操作才能将一连串数字做成二维码呢?下面给大家分享一下数字静态二维码和数字微信活码的制 ...

  6. oracle显示上午下午,如何把时间转换成带有上下午字样的格式?

    转换干嘛??前台传入以指定格式,用to_date或者前台语言比如java,可以转入oracle的日期类型插入 从数据库中取出,可以to_char格式化, to_char(date,fmt,param) ...

  7. word转换成pdf,包括导航目录和图片不变黑

    1.word转换成pdf,包括导航目录和图片不变黑: 有些时候将word转换成pdf,我们会发现生成的文件要么不带导航目录,要么就是图片显示有问题,比如变黑.变黑是因为某些图片在作图时修改了透明度,因 ...

  8. Python 中 PyQt5 + pycharm 调用 Qt Designer,将.ui文件转换成 .py 文件

    From:https://blog.csdn.net/qq_40666028/article/details/81069878 基于Qt Designer 和 pyuic 开发 UI 界面的方法:ht ...

  9. android 半透明色值_Android 色值转换成透明度色值

    在日常的android开发过程中,UI设计师一般都会或多或少的做一些不同透明度的背景,从而提高交互效果. 一般这个时候设计师们都会丢给我们一个色值,然后告诉我们,透明度30%,40% ....... ...

  10. IOS系统自带方法将汉语转换成拼音

    //汉字转换成拼音:系统自带方法 //创建字符串 NSString *str = @"邵亚启"; 1.桥接转换成C的字符串 CFStringRef aCFString = (__b ...

最新文章

  1. mysql plsql循环语句吗,Oracle PLSQL 在游标中用while循环实例程序
  2. Jquery_操作cookies
  3. 如何通过引入硬注意力机制来学习视觉问答任务?
  4. Grunt手表错误 - 等待...致命错误:观看ENOSPC
  5. mybatis 批量查询参数语句
  6. boostrap 鼠标滚轮滑动图片_16种基于Bootstrap的css3图片hover效果
  7. 点击显示底框颜色,默认显示第一个。
  8. 第1章 程序设计和C语言
  9. SQL 使用总结四(关于索引)
  10. (三)MapReducer运行流程
  11. Apache配置问题
  12. android设备离线授权方案,Android平台离线打包授权登陆插件配置
  13. php常用数组,php常用数组函数
  14. TCL语言编译器安装及使用
  15. 易语言编程入门教程学习
  16. 【2014-08-23】Beyong Coding
  17. php开源小程序直播,微信小程序直播
  18. wps删除分节符导致前面格式变乱的解决方案
  19. 股票量化分析工具QTYX使用攻略系列——双底形态选股
  20. 使用hapi 要具备什么知识

热门文章

  1. Android 10.0第三方app根据包名设置为横屏显示
  2. json在线解析(json在线解析)
  3. 在线图片裁剪,关于使用cropperjs踩过的坑
  4. [经典论道] 人工智能的四大哲学问题
  5. 常有不规则动词的过去式和过去分词…
  6. Unity 编辑器扩展教程
  7. 固态硬盘系统经常假死_使用固态硬盘装Win10经常假死怎么解决
  8. 后端和前端有什么区别,哪个工资高?
  9. 蓝桥杯练习 杨辉三角形
  10. excel 如何删除有颜色的行