JavaScript自动生成博文目录导航

JavaScript自动生成博文目录导航http www cnblogs com xdp gacl p 3718879 html 为博客园添加目录的配置总结 http www cnblogs com jiangz p 3734968 html 孤傲苍狼只为成功找方法 不为失败找借口 JavaScript 自动生成博文目录导航 我们在写博客的时候 如

为博客园添加目录的配置总结

http://www.cnblogs.com/jiangz/p/3734968.html

JavaScript自动生成博文目录导航

  我们在写博客的时候,如果博文里面有目录,会给人结构清晰、一种一目了然的感觉,看目录就知道这篇博文要讲解的内容,并且点击目录标题就可以跳转到具体的内容,这样园友们在看博客的时候就可以很方便地浏览自己感兴趣的内容,但是遗憾的是博客园不支持博文目录的生成,好像也有园友给博客园提建议,希望能够像CSDN那样能够自动生成博文目录,但是不知道是什么原因,博客园一直都没有把这个功能加上去,既然没有,那我就自己做吧,研究了2天,总算是按照自己的设想做出来了,最终效果如下:

    JavaScript自动生成博文目录导航

下面来介绍一下这个小工具的实现。

一、功能描述

  这个小工具要实现的核心功能只有两个:

    1.自动生成博文目录。

    2.点击目录标题定位到标题对应的具体内容,就像使用word生成的目录那样。

1.1、自动生成博文目录

  小工具的第一个核心功能,就是通过代码自动抽取标题,然后再包装一下插入文档中。基本实现原理:首先要求博主在写博文的时候,将主标题和次级标题用 HTML标签中的 title tag(如:h1、h2、h3…)包起来;

  比如”1.1、自动生成博文目录“这个次级标题现在是段落的形式

JavaScript自动生成博文目录导航

  将”1.1、自动生成博文目录“设置成”标题3

JavaScript自动生成博文目录导航

JavaScript自动生成博文目录导航

  然后通过 JS 代码遍历整个包含博文正文的

,过滤出这些标签,再把它们组装成自定义列表的形式,再插入到HTML文档中,如下:

复制代码
 1 <dl>  2 <dt>一、JAVA流式输入/输出原理 
        dt>  3 <dt>二、输入输出流分类 
         dt>  4 <dt>三、节点流和处理流 
          dt>  5 <dd>3.1.节点流类型 
           dd>  6 <dd>3.2.处理流类型 
            dd>  7 <dt>四、InputStream(输入流) 
             dt>  8 <dd>4.1.InputStream的基本方法 
              dd>  9 <dt>五、OutputStream(输出流) 
               dt> 10 <dd>5.1.OutputStream的基本方法 
                dd> 11 <dt>六、Reader流 
                 dt> 12 <dd>6.1.Reader的基本方法 
                  dd> 13 <dt>七、Writer流 
                   dt> 14 <dd>7.1.Writer的基本方法 
                    dd> 15 <dt>八、节点流讲解 
                     dt> 16 <dt>九、处理流讲解 
                      dt> 17 <dd>9.1.第一种处理流——缓冲流(Buffering) 
                       dd> 18 <dd>9.2.第二种处理流——转换流 
                        dd> 19 <dd>9.3.第三种处理流——数据流 
                         dd> 20 <dd>9.4.打印流——Print 
                          dd> 21 <dd>9.5. 对象流——Object 
                           dd> 22 <dt>十、IO流总结 
                            dt> 23  
                             dl>
复制代码

  如果不加任何样式,它在浏览器中的默认显示效果如下:

    JavaScript自动生成博文目录导航

1.2、点击目录标题定位到标题对应的具体内容

常规实现方式:使用HTML的锚点链接

范例:使用HTML的锚点链接定位到具体的内容

复制代码
 1 <html>  2 <head>  3 <title>使用HTML的锚点链接定位到具体的内容 
        title>  4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  5  
         head>  6 <body>  7 <h1>目录导航 
          h1>  8 <dl>  9  
            12 <dt><a href="#title0">一、JAVA流式输入/输出原理 
           a> 
            dt> 13 <dt><a href="#title1">二、输入输出流分类 
             a> 
              dt> 14 <dt><a href="#title2">三、节点流和处理流 
               a> 
                dt> 15 <dd><a href="#title3">3.1.节点流类型 
                 a> 
                  dd> 16 <dd><a href="#title4">3.2.处理流类型 
                   a> 
                    dd> 17 <dt><a href="#title5">四、InputStream(输入流) 
                     a> 
                      dt> 18 <dd><a href="#title6">4.1.InputStream的基本方法 
                       a> 
                        dd> 19 <dt><a href="#title7">五、OutputStream(输出流) 
                         a> 
                          dt> 20 <dd><a href="#title8">5.1.OutputStream的基本方法 
                           a> 
                            dd> 21 <dt><a href="#title9">六、Reader流 
                             a> 
                              dt> 22 <dd><a href="#title10">6.1.Reader的基本方法 
                               a> 
                                dd> 23 <dt><a href="#title11">七、Writer流 
                                 a> 
                                  dt> 24 <dd><a href="#title12">7.1.Writer的基本方法 
                                   a> 
                                    dd> 25 <dt><a href="#title13">八、节点流讲解 
                                     a> 
                                      dt> 26 <dt><a href="#title14">九、处理流讲解 
                                       a> 
                                        dt> 27 <dd><a href="#title15">9.1.第一种处理流——缓冲流(Buffering) 
                                         a> 
                                          dd> 28 <dd><a href="#title16">9.2.第二种处理流——转换流 
                                           a> 
                                            dd> 29 <dd><a href="#title17">9.3.第三种处理流——数据流 
                                             a> 
                                              dd> 30 <dd><a href="#title18">9.4.打印流——Print 
                                               a> 
                                                dd> 31 <dd><a href="#title19">9.5. 对象流——Object 
                                                 a> 
                                                  dd> 32 <dt><a href="#title20">十、IO流总结 
                                                   a> 
                                                    dt> 33  
                                                     dl> 34 <hr/> 35 <div style="background-color:Red; width:100%;height:150px;"> 36  
                                                       39 <h2 id="title0" name="title0">一、JAVA流式输入/输出原理 
                                                      h2> 40  
                                                       div> 41 <div style="background-color:Yellow; width:100%;height:150px;"> 42 <h2 name="title1" id="title1">二、输入输出流分类 
                                                        h2> 43  
                                                         div> 44 <div style="background-color:Silver; width:100%;height:150px;"> 45 <h2 name="title2" id="title2">三、节点流和处理流 
                                                          h2> 46 <h3 name="title3" id="title3">3.1.节点流类型 
                                                           h3> 47 <h3 name="title4" id="title4">3.2.处理流类型 
                                                            h3> 48  
                                                             div> 49 <div style="background-color:Aqua; width:100%;height:150px;"> 50 <h2 name="title5" id="title5">四、InputStream(输入流) 
                                                              h2> 51 <h3 name="title6" id="title6">4.1.InputStream的基本方法 
                                                               h3> 52  
                                                                div> 53 <div style="background-color:Fuchsia; width:100%;height:150px;"> 54 <h2 name="title7" id="title7">五、OutputStream(输出流) 
                                                                 h2> 55 <h3 name="title8" id="title8">5.1.OutputStream的基本方法 
                                                                  h3> 56  
                                                                   div> 57 <div style="background-color:Green; width:100%;height:150px;"> 58 <h2 name="title9" id="title9">六、Reader流 
                                                                    h2> 59 <h3 name="title10" id="title10">6.1.Reader的基本方法 
                                                                     h3> 60  
                                                                      div> 61 <div style="background-color:Blue; width:100%;height:150px;"> 62 <h2 name="title11" id="title11">七、Writer流 
                                                                       h2> 63 <h3 name="title12" id="title12">7.1.Writer的基本方法 
                                                                        h3> 64  
                                                                         div> 65 <div style="background-color:Olive; width:100%;height:150px;"> 66 <h2 name="title13" id="title13">八、节点流讲解 
                                                                          h2> 67  
                                                                           div> 68 <div style="background-color:Green; width:100%;height:150px;"> 69 <h2 name="title14" id="title14">九、处理流讲解 
                                                                            h2> 70 <h3 name="title15" id="title15">9.1.第一种处理流——缓冲流(Buffering) 
                                                                             h3> 71 <h3 name="title16" id="title16">9.2.第二种处理流——转换流 
                                                                              h3> 72 <h3 name="title17" id="title17">9.3.第三种处理流——数据流 
                                                                               h3> 73 <h3 name="title18" id="title18">9.4.打印流——Print 
                                                                                h3> 74 <h3 name="title19" id="title19">9.5. 对象流——Object 
                                                                                 h3> 75  
                                                                                  div> 76 <div style="background-color:Purple; width:100%;height:150px;"> 77 <h2 name="title20" id="title20">十、IO流总结 
                                                                                   h2> 78  
                                                                                    div> 79 <div style="height:130px;">  
                                                                                     div> 80 <div style="height:130px;">  
                                                                                      div> 81 <div style="height:130px;">  
                                                                                       div> 82  
                                                                                        body> 83  
                                                                                         html>
复制代码

  这是使用HTML锚点链接的解决方案,也是一种常规的实现方式,这种方案我觉得用户体验不怎么好,跳转到具体内容的时候速度太快了,没有一种平滑过度的效果。

JavaScript实现方式

  实现原理:首先通过调用 DOM 方法,判断出浏览器滚动条(scroll bar)的当前位置,记为 currentPos;然后计算出目标标题(target title)的距页面顶端的距离,记为 finalPos;最后通过一定的算法实现平滑过度。

二、源代码

  下面是这个JS工具的相关源代码:

2.1 js代码

复制代码
 1 /*  2  功能:生成博客目录的JS工具  3  测试:IE8,火狐,google测试通过  4  孤傲苍狼  5  2014-5-11  6 */  7 var BlogDirectory = {  8 /*  9  获取元素位置,距浏览器左边界的距离(left)和距浏览器上边界的距离(top)  10 */  11 getElementPosition:function (ele) {  12 var topPosition = 0;  13 var leftPosition = 0;  14 while (ele){  15 topPosition += ele.offsetTop;  16 leftPosition += ele.offsetLeft;  17 ele = ele.offsetParent;  18  }  19 return {top:topPosition, left:leftPosition};  20  },  21  22 /*  23  获取滚动条当前位置  24 */  25 getScrollBarPosition:function () {  26 var scrollBarPosition = document.body.scrollTop || document.documentElement.scrollTop;  27 return scrollBarPosition;  28  },  29  30 /*  31  移动滚动条,finalPos 为目的位置,internal 为移动速度  32 */  33 moveScrollBar:function(finalpos, interval) {  34  35 //若不支持此方法,则退出  36 if(!window.scrollTo) {  37 return false;  38  }  39  40 //窗体滚动时,禁用鼠标滚轮  41 window.onmousewheel = function(){  42 return false;  43  };  44  45 //清除计时  46 if (document.body.movement) {  47  clearTimeout(document.body.movement);  48  }  49  50 var currentpos =BlogDirectory.getScrollBarPosition();//获取滚动条当前位置  51  52 var dist = 0;  53 if (currentpos == finalpos) { 
       //到达预定位置,则解禁鼠标滚轮,并退出  54 window.onmousewheel = function(){  55 return true;  56  }  57 return true;  58  }  59 if (currentpos < finalpos) { 
       //未到达,则计算下一步所要移动的距离  60 dist = Math.ceil((finalpos - currentpos)/10);  61 currentpos += dist;  62  }  63 if (currentpos > finalpos) {  64 dist = Math.ceil((currentpos - finalpos)/10);  65 currentpos -= dist;  66  }  67  68 var scrTop = BlogDirectory.getScrollBarPosition();//获取滚动条当前位置  69 window.scrollTo(0, currentpos);//移动窗口  70 if(BlogDirectory.getScrollBarPosition() == scrTop)//若已到底部,则解禁鼠标滚轮,并退出  71  {  72 window.onmousewheel = function(){  73 return true;  74  }  75 return true;  76  }  77  78 //进行下一步移动  79 var repeat = "BlogDirectory.moveScrollBar(" + finalpos + "," + interval + ")";  80 document.body.movement = setTimeout(repeat, interval);  81  },  82  83     htmlDecode:function (text){  84 var temp = document.createElement("div");  85 temp.innerHTML = text;  86 var output = temp.innerText || temp.textContent;  87 temp = null;  88 return output;  89  },  90  91 /*  92  创建博客目录,  93  id表示包含博文正文的 div 容器的 id,  94  mt 和 st 分别表示主标题和次级标题的标签名称(如 H2、H3,大写或小写都可以!),  95  interval 表示移动的速度  96 */  97 createBlogDirectory:function (id, mt, st, interval){  98 //获取博文正文div容器  99 var elem = document.getElementById(id); 100 if(!elem) return false; 101 //获取div中所有元素结点 102 var nodes = elem.getElementsByTagName("*"); 103 //创建博客目录的div容器 104 var divSideBar = document.createElement('DIV'); 105 divSideBar.className = 'sideBar'; 106 divSideBar.setAttribute('id', 'sideBar'); 107 var divSideBarTab = document.createElement('DIV'); 108 divSideBarTab.setAttribute('id', 'sideBarTab'); 109  divSideBar.appendChild(divSideBarTab); 110 var h2 = document.createElement('H2'); 111  divSideBarTab.appendChild(h2); 112 var txt = document.createTextNode('目录导航'); 113  h2.appendChild(txt); 114 var divSideBarContents = document.createElement('DIV'); 115 divSideBarContents.style.display = 'none'; 116 divSideBarContents.setAttribute('id', 'sideBarContents'); 117  divSideBar.appendChild(divSideBarContents); 118 //创建自定义列表 119 var dlist = document.createElement("dl"); 120  divSideBarContents.appendChild(dlist); 121 var num = 0;//统计找到的mt和st 122 mt = mt.toUpperCase();//转化成大写 123 st = st.toUpperCase();//转化成大写 124 //遍历所有元素结点 125 for(var i=0; i 
       
         ) 
        126 
         {  
        127 
        if(nodes[i].nodeName == mt|| nodes[i].nodeName == 
         st)  
        128 
         {  
        129 
        // 
        获取标题文本 
        130 
        var nodetext = nodes[i].innerHTML.replace(/<\/?[^>]+>/g,""); 
        // 
        innerHTML里面的内容可能有HTML标签,所以用正则表达式去除HTML的标签 
        131 nodetext = nodetext.replace(/ /ig, ""); 
        // 
        替换掉所有的  
        132 nodetext = 
         BlogDirectory.htmlDecode(nodetext);  
        133 
        // 
        插入锚  
        134 nodes[i].setAttribute("id", "blogTitle" + 
         num);  
        135 
        var 
         item;  
        136 
        switch 
        (nodes[i].nodeName)  
        137 
         {  
        138 
        case mt: 
        // 
        若为主标题  
        139 item = document.createElement("dt" 
        );  
        140 
        break 
        ;  
        141 
        case st: 
        // 
        若为子标题 
        142 item = document.createElement("dd" 
        );  
        143 
        break 
        ;  
        144 
         }  
        145 
        146 
        // 
        创建锚链接 
        147 
        var itemtext = 
         document.createTextNode(nodetext);  
        148 
         item.appendChild(itemtext);  
        149 item.setAttribute("name" 
        , num);  
        150 item.onclick = 
        function(){ 
        // 
        添加鼠标点击触发函数 
        151 
        var pos = BlogDirectory.getElementPosition(document.getElementById("blogTitle" + 
        this.getAttribute("name" 
        )));  
        152 
        if(!BlogDirectory.moveScrollBar(pos.top, interval)) 
        return 
        false 
        ;  
        153 
         };  
        154 
        155 
        // 
        将自定义表项加入自定义列表中 
        156 
         dlist.appendChild(item);  
        157 num++ 
        ;  
        158 
         }  
        159 
         }  
        160 
        161 
        if(num == 0) 
        return 
        false 
        ;  
        162 
        /* 
        鼠标进入时的事件处理 
        */ 
        163 divSideBarTab.onmouseenter = 
        function 
        (){  
        164 divSideBarContents.style.display = 'block' 
        ;  
        165 
         }  
        166 
        /* 
        鼠标离开时的事件处理 
        */ 
        167 divSideBar.onmouseleave = 
        function 
        () {  
        168 divSideBarContents.style.display = 'none' 
        ;  
        169 
         }  
        170 
        171 
         document.body.appendChild(divSideBar);  
        172 
         }  
        173 
        174 
        };  
        175 
        176 window.οnlοad= 
        function 
        (){  
        177 
        /* 
        页面加载完成之后生成博客目录 
        */ 
        178 BlogDirectory.createBlogDirectory("cnblogs_post_body","h2","h3",20 
        );  
        179 } 
       
复制代码

2.2. CSS样式代码

复制代码
 1 /*生成博客目录的CSS*/  2 #sideBar{  3  font-size:12px;  4  font-family:Arial, Helvetica, sans-serif;  5  text-align:left;  6  position:fixed;/*将div的位置固定到距离top:50px,right:0px的位置,这样div就会处在最右边的位置,距离顶部50px*/  7  top:50px;  8  right:0px;  9  width: auto; 10  height: auto; 11 } 12 #sideBarTab{ 13  float:left; 14  width:30px; 15  border:1px solid #e5e5e5; 16  border-right:none; 17  text-align:center; 18  background:#ffffff; 19 } 20 21 #sideBarContents{ 22  float:left; 23  overflow:auto; 24  overflow-x:hidden;!important; 25  width:200px; 26  min-height:108px; 27  max-height:460px; 28  border:1px solid #e5e5e5; 29  border-right:none; 30  background:#ffffff; 31 } 32 #sideBarContents dl{ 33  margin:0; 34  padding:0; 35 } 36 37 #sideBarContents dt{ 38  margin-top:5px; 39  margin-left:5px; 40 } 41 42 #sideBarContents dd, dt { 43  cursor: pointer; 44 } 45 46 #sideBarContents dd:hover, dt:hover { 47  color:#A7995A; 48 }
复制代码

2.3.由JavaScript动态生成的HTML代码结构如下

复制代码
 1 <div id="sideBar" class="sideBar">  2 <div id="sideBarTab">  3 <h2>目录导航 
        h2>  4  
         div>  5 <div id="sideBarContents" style="display: none;">  6 <dl>  7 <dt name="0">一、功能描述 
          dt>  8 <dd name="1">1.1、自动生成博文目录 
           dd>  9 <dd name="2">1.2、点击目录标题定位到标题对应的具体内容 
            dd> 10 <dt name="3">二、源代码 
             dt> 11 <dd name="4">2.1 js代码 
              dd> 12 <dd name="5">2.2. CSS样式代码 
               dd> 13 <dt name="6">三、JS工具的使用 
                dt> 14 <dd name="7">3.1、后台管理的相关设置 
                 dd> 15 <dd name="8">3.2、博文标题样式设置 
                  dd> 16 <dt name="9">四、总结 
                   dt> 17  
                    dl> 18  
                     div> 19  
                      div>
复制代码

三、JS工具的使用

3.1、后台管理的相关设置

  进入到博客后台管理,点击设置

  JavaScript自动生成博文目录导航

然后在这里添加CSS样式代码,将上面的CSS样式代码直接copy到这里即可

  JavaScript自动生成博文目录导航

在这里添加javascript脚本,将上面的JS源代码直接copy到这里即可

  JavaScript自动生成博文目录导航

点击【保存】按钮,完成设置

3.2、博文标题样式设置

将博文标题的样式设置成标题

  JavaScript自动生成博文目录导航

例如:

将”三、JS工具的使用”这个一级标题的标题样式设置成【标题2】

  JavaScript自动生成博文目录导航

将”3.1、后台管理的相关设置”这个二级标题的标题样式设置成【标题3】

  JavaScript自动生成博文目录导航

  这样执行这段代码时就会生成如下图所示的博客目录了

1 window.οnlοad=function(){ 2 /*页面加载完成之后生成博客目录*/ 3 BlogDirectory.createBlogDirectory("cnblogs_post_body","h2","h3",20); 4 }

    JavaScript自动生成博文目录导航

  生成的目录导航在紧挨着页面最右边的滚动条,鼠标移动到【目录导航】时就会显示生成的目录内容,鼠标离开就自动隐藏目录

    JavaScript自动生成博文目录导航

  点击目录上的标题就会平滑跳转到该标题对应的具体内容。

四、总结

  开发这个小工具的过程中还是遇到了不少的细节问题的,好在都解决了,目前做出来的效果总体来说还算比较满意,现在将代码分享出来给朋友们,可以自由修改和使用,希望对广大朋友们有所帮助吧!




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/206075.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午4:32
下一篇 2026年3月19日 下午4:32


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号