详解自动生成博客目录案例

有朋友在博客下面留言,询问博客目录是如何生成的。接下来就详细介绍实现过程

操作说明

关于博客目录自动生成,已经封装成catalog.js文件,只要引用该文件即可

//默认地,为页面上所有的h3标签生成目录
    <script src=""></script>
    //或者,为页面上所有class="test"的标签生成目录
    <script src="" data-seletor=".test"></script>
 如下图所示,打开HTML源代码编辑器,在最后引入js即可

详解自动生成博客目录案例

【功能简要说明】

1、点击目录项,对应章节标题将显示在可视区上方

2、滚动滚轮,目录项会对应章节标题的变化而相应地变化

3、点击目录右上角的关闭按钮,可以将目录缩小为"显示目录"四个字,双击缩小后的目录,可恢复默认状态

4、目录可以拖拽至任意地方

目录参照

首先,要确定的是,基于什么生成目录。是文章中的<h3>标签,还是文章中的class="list"的标签。所以,更人性化的做法是,将其作为参数,默认参数为<h3>标签

由于博客园的博文除了自己生成的博客内容外,博客园还会添加诸如评论、公告、广告等元素。所以,第一步要先定位博文

博文最终都处于id="cnblogs_post_body"的div中

详解自动生成博客目录案例

//DOM结构稳定后再操作 window.onload = function(){ /*设置章节标题函数*/ function setCatalog(){ //获取页面中所有的script标题 var aEle = document.getElementsByTagName('script'); //设置sel变量,用于保存其选择符的字符串值 var sel; //获取script标签上的data-selector值 Array.prototype.forEach.call(aEle,function(item,index,array){ sel = item.getAttribute('data-selector'); if(sel) return; }) //默认参数为h3标签 if(sel == undefined){ sel ='h3'; } //选取文章中所有的章节标题 var tempArray = document.querySelectorAll(sel); };

目录连接

  目录如何与章节进行对应呢,最常用的就是使用锚点。以基于文章中的<h3>标签生成目录为例,为每一个<h3>标签按照顺序添加锚点(#anchor1,#anchor2...)

//为每一个章节标题顺序添加锚点标识 Array.prototype.forEach.call(tempArray, function(item, index, array) { item.setAttribute('id','anchor' + (1+index)); });

目录显示

在文章左侧显示目录,目录显示的内容就是对应章节的题目

//设置全局变量Atitle保存添加锚点标识的标题项 var aTitle = setCatalog(); /*生成目录*/ function buildCatalog(arr){ //由于每个部件的创建过程都类似,所以写成一个函数进行服用 function buildPart(json){ var oPart = document.createElement(json.selector); if(json.id){oPart.setAttribute('id',json.id);} if(json.className){oPart.className = json.className;} if(json.innerHTML){oPart.innerHTML = json.innerHTML;} if(json.href){oPart.setAttribute('href',json.href);} if(json.appendToBox){ oBox.appendChild(oPart); } return oPart; } //取得章节标题的个数 len = arr.length; //创建最外层div var oBox = buildPart({ selector:'div', id:'box', className:'box' }); //创建关闭按钮 buildPart({ selector:'span', id:'boxQuit', className:'box-quit', innerHTML:'&times;', appendToBox:true }); //创建目录标题 buildPart({ selector:'h6', className:'box-title', innerHTML:'目录', appendToBox:true }); //创建目录项 for(var i = 0; i < len; i++){ buildPart({ selector:'a', className:'box-anchor', href:'#anchor' + (1+i), innerHTML:'['+(i+1)+']'+arr[i].innerHTML, appendToBox:true }); } //将目录加入文档中 document.body.appendChild(oBox); } buildCatalog(aTitle);

目录样式

  为目录设置样式,最外层div设置最小宽度和最大宽度。当目录项太宽时,显示...。由于最终要封装为一个js文件,所以样式采用动态样式的形式

/*动态样式*/ function loadStyles(str){ loadStyles.mark = 'load'; var style = document.createElement("style"); style.type = "text/css"; try{ style.innerHTML = str; }catch(ex){ style.styleSheet.cssText = str; } var head = document.getElementsByTagName('head')[0]; head.appendChild(style); } if(loadStyles.mark != 'load'){ loadStyles("h6{margin:0;padding:0;}\ .box{position: fixed; left: 10px;top: 60px;font:16px/30px '宋体'; border: 2px solid #ccc;padding: 4px; border-radius:5px;min-width:80px;max-width:118px;overflow:hidden;cursor:default;}\ .boxHide{border:none;width:60px;height:30px;padding:0;}\ .box-title{text-align:center;font-size:20px;color:#ccc;}\ .box-quit{position: absolute; right: 0;top: 4px;cursor:pointer;font-weight:bold;}\ .box-anchor{display:block;text-decoration:none;color:black; border-left: 3px solid transparent;padding:0 3px;margin-bottom: 3px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}\ .box-anchor:hover{color:#3399ff;}\ .box-anchorActive{color:#3399ff;text-decoration:underline;border-color:#2175bc};"); };

点击事件

为各目录项增加点击事件,使用事件代理,增加性能

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwffjf.html