一、教程内容
需要用Jquery实现根据文章内容自动生成侧边栏导航的功能,具体的来说有以下的需求:
1、能自动生成文章h1-h5标签的标题
2、点击标题能跳转到对应的位置
3、如果文章过长,下滑后导航要保持在右侧
4、如果没有标题,需要用“无文章目录”填充目录区域。
二、具体操作
HTML
<div id="category-ct" class="global-card card-side">
<div class="card-side-title">
<b>文章目录</b>
</div>
<ul class="card-body">
<div id="category">
<div id="c-default" style="display:none;font-size:14px;text-align:center;color:#242424;line-height:20px;margin-top: 10px;padding-top: 5px;">
无文章目录
</div>
</div>
</ul>
</div>
1、自动生成文章h1-h5标题
只需要遍历文章内容,找到h1-h5的文字内容,然后加入到右侧的id="category"里面即可。
2、点击标题跳转位置
有四种方法,第四种最好。
【方法1】给锚点文本添加id,使用<a href="#">目录文字</a>来定位。
<a href="#c1">目录</a>
<h1 id="c1">需要跳转的标题</h1>
然而这样做会使得浏览器URL变为:
http://www.bewindoweb.cn/122.html#c1
并产生一条历史记录,如果多次跳转,想返回上一页面,则需要返回N次点过的锚点URL,才能返回。
【方法2】添加一个空的锚点,使用name定位,同样使用<a href="#">目录文字</a>来定位。
<a href="#c1">目录</a>
<a name="c1"></a>
<h1>需要跳转的标题</h1>
缺点非常多,首先添加了不必要的空文本,外观会显示为一个空行(当然可以用CSS调整),其次name只对a标签起作用,最后仍然有方法1的问题。
【方法3】使用js定位。
onclick="javascript:document.getElementById('c1').scrollIntoView()"
很好,不改变URL,同时能跳转,但是比较突兀。
【方法4】使用jquery定位。
$(document).on('click', '.cbtn', function(e) {
$('html,body').animate({scrollTop: $("#" + this.name).offset().top}, 500);
});
将按钮加个.cbtn
的class,把要跳转的id保存在name
属性里,然后用animate
模拟滚动条滑动跳转,平滑跳转到需要的位置。
3、如果文章过长,下滑后导航要保持在右侧
和“返回顶部”按钮的思路一致,当滚动到一定程度(看不到目录,也就是滚动距离超过了目录div离浏览器上边距的距离),就将目录的div固定在右侧。
var navH = $("#category-ct").offset().top;
//滚动条事件
$(window).scroll(function(){
//获取滚动条的滑动距离
var scroH = $(this).scrollTop();
//滚动条的滑动距离大于等于定位元素距离浏览器顶部的距离,就固定
if(scroH>=navH){
$("#category-ct").css({position: 'fixed'});
$("#category-ct").animate({top: '30px'},1000);
}
else{
$("#category-ct").css({position: 'static',top:'0px'});
}
});
这里还加了个缓慢下降的效果,不过经常当返回顶部时,top不会变回0px,不知道为什么。
4、如果没有标题,需要用“无文章目录”填充目录区域。
如果没搜索到h1-h5,那么就将“无文章目录”的CSS置为显示即可。
三、完整代码
<script>
$(function(){
var notdefault = 0;
$('.card-article-text').find('h1,h2').each(function(index,item){
notdefault = 1;
$(this).attr('id','c'+index);
var headerText=$(this).text();
var tagName=$(this)[0].tagName.toLowerCase();
var tagIndex=parseInt(tagName.charAt(1));
//设置不同等级header的排列及缩进样式
if (tagIndex == 1)//href="#c'+index+'"
$('#category').append($('<a name=c'+index+' class="cbtn article-ch'+tagIndex+'" >'+headerText+'</a>'));
else
$('#category').append($('<a name=c'+index+' class="cbtn article-ch'+tagIndex+'" >> '+headerText+'</a>'));
});
if (notdefault == 0){
$('#c-default').css('display','block');
}
var navH = $("#category-ct").offset().top;
//滚动条事件
$(window).scroll(function(){
//获取滚动条的滑动距离
var scroH = $(this).scrollTop();
//滚动条的滑动距离大于等于定位元素距离浏览器顶部的距离,就固定
if(scroH>=navH){
$("#category-ct").css({position: 'fixed'});
$("#category-ct").animate({top: '30px'},1000);
}
else{
$("#category-ct").css({position: 'static',top:'0px'});
}
});
$(document).on('click', '.cbtn', function(e) {
$('html,body').animate({scrollTop: $("#" + this.name).offset().top}, 500);
//document.getElementById($(this).attr('name')).scrollIntoView()
// onclick="javascript:document.getElementById('+'\'c3\''+').scrollIntoView()
});
});
</script>