侧边栏滚动导航事件
// TODO
$(function() {
var ctrl = {
scrollHandler: function() {
var self = this;
var win = $(window);
var docs = $('.docs');
var navContainer = $('#J-nav');
var navItem = $('.nav-section-item');
// heaerHeight 除外其他的干扰因素, outerHeight属性是计算包含内外边距在内的高度
var headerHeight = $('.documentation').outerHeight() + $('.topbar').outerHeight();
// 设置位置参数列表, 包含每个锚点距离正文顶部的高度
var positions = [];
// h3是标记标签
$('h3', docs).each(function() {
var current = $(this);
var text = current.text();
var anchor = text.split(' ')[0];
positions.push(parseInt(current.offset().top)); // 获取每个锚点距离正文的高度
navItem.filter('[href="#'+ anchor +'"]').attr('rel', positions.length - 1);
});
var positionLength = positions.length;
// 设置防抖节点, 在一定时间内滚动不做处理
var timer;
// 监听window的滚动事件
win.scroll(function() {
// 获取正文被卷去的高度
var scrollTop = win.scrollTop();
navContainer.css('top', scrollTop >= headerHeight ? 0 : Math.min(headerHeight, headerHeight - scrollTop));
// 防止重复设置侧边整体的位置
if (self.noscroll) {
self.noscroll = false;
return;
}
// 延迟函数是防抖的写法, 延迟函数内部才是主要内容
if (timer) clearTimeout(timer);
timer = setTimeout(function() {
for (var i = 0; i < positionLength; i++) {
if (scrollTop < positions[0]) {
self.backNav();
return;
}
if ( (positions[i] <= scrollTop) && (positions[i + 1] > scrollTop) ) {
self.selectNav(i);
}
}
}, 50);
});
// 主动触发某个事件
win.trigger('scroll');
},
// 设置观察者事件==> 监听各种点击事件
observer: function() {
var self = this;
self.addAnchors(); // 添加
self.addNav(); // 生成侧边的导航栏
var navItem = $('.nav-section-item');
var navTitle = $('.nav-section-title');
var gotoTop = $('#gototop');
// 点击侧边子标题事件
navItem.on('click', function() {
var current = $(this);
var index = current.attr('rel');
navItem.removeClass('active');
current.addClass('active');
self.selectNav(index);
});
// 点击侧边栏主标题事件
navTitle.on('click', function() {
var current = $(this);
self.selectNav(current.next().attr('rel'));
self.noscroll = true;
});
// 返回顶部事件
gotoTop.on('click', function() {
$('body').get(0).scrollTop = 0;
});
// 注册滚动监听事件
self.scrollHandler();
},
// add anchors 生成正文的锚点标签
addAnchors: function() {
var docs = $('.docs');
$('h3', docs).each(function() {
var current = $(this);
var anchor = current.text().split(' ')[0];
current.before('<a name="'+ anchor +'"></a>');
});
},
// add nav
addNav: function() {
var docs = $('.docs');
var navContainer = $('#J-nav');
var newNav = '';
var hash = (function() {
var result = {};
var currentItem;
$('h1, h2, h3', docs).each(function() {
var current = $(this);
var tagName = this.tagName.toLowerCase(); // 标签转小写
var text = current.text();
var anchor = text.split(' ')[0];
if (tagName === 'h1') {
if (text !== 'Constructor' && text !== 'Configuring Defaults') {
currentItem = result[text] = result[text] || [];
current.before('<a name="'+ text.replace(' ', '') +'"></a>');
}
}
else if (tagName === 'h2') {
currentItem = result[text] = result[text] || [];
current.before('<a name="'+ text.replace(' ', '') +'"></a>');
}
else if (tagName === 'h3') {
currentItem.push(anchor);
}
});
return result;
})();
for (var cat in hash) {
if (hash.hasOwnProperty(cat)) {
newNav += '<div class="nav-section">';
newNav += '<div class="nav-section-title"><a href="#'+ cat.replace(' ', '') +'">'+ cat +'<\/a><\/div>';
$.each(hash[cat], function(index, name) {
newNav += '<a class="nav-section-item" href="#'+ name +'">'+ name +'<\/a>';
});
newNav += '<\/div>';
}
}
navContainer.html(newNav);
},
// select nav
selectNav: function(index) {
var navContainer = $('#J-nav');
var navItem = $('.nav-section-item', navContainer);
navItem.eq(navContainer.data('menuon')).removeClass('active').parent().removeClass('active');
navItem.eq(index).addClass('active').parent().addClass('active');
navContainer.data('menuon', index);
},
// nav init
backNav: function() {
var navContainer = $('#J-nav');
var navSection = $('.nav-section', navContainer);
var navItem = $('.nav-section-item', navContainer);
navSection.removeClass('active');
navItem.removeClass('active');
navSection.eq(0).addClass('active');
navContainer.data('menuon', 0);
},
// 插入 皮肤事件
insertSkin: function() {
var skindemo = $('#J-skin-demo'); // 这是一个用 display: none 制作的模板
var h1 = $('h1');
h1.each(function() {
var current = $(this);
if (current.text() === 'Skin') {
// 标记物后面插入模板
current.next().after(skindemo);
// 将模板显示出来
skindemo.removeAttr('style');
}
});
},
prettyprint: function() {
$('pre').addClass('prettyprint linenums');
window.prettyPrint && prettyPrint();
},
// 初始化标签
init: function() {
ctrl.observer();
ctrl.prettyprint();
ctrl.insertSkin();
}
};
ctrl.init();
});
html部分:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="docs">
<div class="nav" id="J-nav">
<div class="nav-section active">
<div class="nav-section-title">Attributes</div>
<a class="nav-section-item active" href="#header">header</a>
<a class="nav-section-item" href="#footer">footer</a>
<a class="nav-section-item" href="#dataSource">dataSource</a>
<a class="nav-section-item" href="#locator">locator</a>
</div>
<div class="nav-section">
<div class="nav-section-title">Methods</div>
<a class="nav-section-item">previous</a>
<a class="nav-section-item">next</a>
</div>
</div>
<div class="content">
<!-- h1 算是一整页的内容 -->
<h1>Constructor</h1>
<!-- h2 是一级标题 -->
<a name="Commonlyused"></a>
<h2>Commonly used</h2>
<!-- h3 是二级标题 -->
<a name="dataSource"></a>
<h3>dataSource <em>array | string | object | function</em></h3>
</div>
</div>
<!-- 返回顶部的图标 -->
<div id="gototop">Top</div>
</body>
</html>
网友评论