forked from LiranCohen/stickUp
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathstickUp.js
162 lines (147 loc) · 6.45 KB
/
stickUp.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// 问题:不支持一个页面中多个元素固定(已实现)
// 不支持固定方向的设置
// 不支持回调事件(已实现)
// 单页模式下,调整的定位是基于part参数的(重构后是基于html元素的data-menu)
// 目前而言,许多操作是实时的——比如每次都重新查找、计算DOM
// 这种方法对网页变动比较大的情景是非常适用的,但比较耗费性能
//
// 目前为止,缺乏测试
jQuery(function($) {
"use strict";
var Context = function() {},
_ctxList = {},
lastScrollTop = 0;
Context.prototype = {
// 配置参数
dataProperty: 'data-menu',
itemClass: '',
itemHover: '',
marginTop: 0,
beforeStick: null,
afterStick: null,
beforeUnstick: null,
afterUnstick: null,
// 预留参数
region: 'top',
// 自动计算值
// 私有参数
_selector: '',
_jqDom: null,
_menuItems: [],
_height: 0,
_parentMarginTop: 0,
_top: 0,
_marginBottom: 0,
onScroll: function(scrollDir, varscroll) {
var contentView = null,
testView = null,
_me = this;
// 计算并给适当元素添加 itemHover 类
if ( !! _me._menuItems && _me._menuItems.length > 0) {
var offset = null,
contentTop = 0,
tmp_menuTarget = null;
for (var i = 0; i < _me._menuItems.length; i++) {
tmp_menuTarget = $('#' + $(_me._menuItems[i]).attr(_me.dataProperty));
offset = tmp_menuTarget.offset();
contentTop = !! offset ? offset.top : 0;
// 之前這裡定義了一個bottomView
// 会在每次执行这个地方的时候都去创建一个函数
// 实际上是很没必要的性能损耗,所以这里将代码移动下面
if (scrollDir == 'down' &&
varscroll > contentTop - 50 &&
varscroll < contentTop + 50) {
_me._jqDom.find('.' + _me.itemClass).removeClass(_me.itemHover);
_me._jqDom.find('.' + _me.itemClass + ':eq(' + i + ')').addClass(_me.itemHover);
}
if (scrollDir == 'up') {
// 这里就是原来的bottomView代码
contentView = tmp_menuTarget.height() * 0.4;
testView = contentTop - contentView;
if (varscroll > testView) {
_me._jqDom.find('.' + _me.itemClass).removeClass(_me.itemHover);
_me._jqDom.find('.' + _me.itemClass + ':eq(' + i + ')').addClass(_me.itemHover);
} else if (varscroll < 50) {
_me._jqDom.find('.' + _me.itemClass).removeClass(_me.itemHover);
_me._jqDom.find('.' + _me.itemClass + ':eq(0)').addClass(_me.itemHover);
}
}
}
}
// 固定菜单栏目,使之固定(fixed)
if (_me._top < varscroll + _me.marginTop) {
if ( !! _me.beforeStick) _me.beforeStick.call(_me);
_me._jqDom.addClass('isStuck');
if ( !! _me.afterStick) _me.afterStick.call(_me);
_me._jqDom.next().closest('div').css({
'margin-top': _me._height + _me._marginBottom + _me._parentMarginTop + 'px'
}, 10);
_me._jqDom.css("position", "fixed");
_me._jqDom.css({
top: '0px'
}, 10);
};
// 菜單欄目,使之不固定(relative)
if (varscroll + _me.marginTop < _me._top) {
if ( !! _me.beforeUnstick) _me.beforeUnstick.call(_me);
_me._jqDom.removeClass('isStuck');
if ( !! _me.afterUnstick) _me.afterUnstick.call(_me);
_me._jqDom.next().closest('div').css({
'margin-top': _me._parentMarginTop + 'px'
}, 10);
_me._jqDom.css("position", "relative");
};
}
};
Context._init_ = function(dom, option, instance) {
instance = instance || new Context();
var _me = instance,
objn = 0;
_me._jqDom = $(dom);
//getting options
if ( !! option) {
_me._menuItems = _me._jqDom.find('[' + _me.dataProperty + ']');
if (option.topMargin != null) {
if (option.topMargin == 'auto') {
_me.marginTop = parseInt(_me._jqDom.css('margin-top'));
} else {
if (isNaN(option.topMargin) && option.topMargin.search("px") > 0) {
_me.marginTop = parseInt(option.topMargin.replace("px", ""));
} else if (!isNaN(parseInt(option.topMargin))) {
_me.marginTop = parseInt(option.topMargin);
} else {
console.log("incorrect argument, ignored.");
_me.marginTop = 0;
}
}
} else {
_me.marginTop = 0;
}
_me.itemClass = option.itemClass;
_me.itemHover = option.itemHover;
} else {
console.log('warm:needs arguments');
}
_me.dataProperty = option.dataProperty || _me.dataProperty;
_me.region = option.region || _me.region;
_me._height = parseInt(_me._jqDom.height());
_me._marginBottom = parseInt(_me._jqDom.css('margin-bottom'));
_me._parentMarginTop = parseInt(_me._jqDom.next().closest('div').css('margin-top'));
_me._top = parseInt(_me._jqDom.offset().top);
_ctxList[_me._selector] = _me;
};
// 初始化各类参数,即解析options的值
$.fn.stickUp = function(options) {
if (!_ctxList[this.selector])
Context._init_(this, options);
}
// 頁面滾動事件
$(document).on('scroll', function() {
var scrollOffest = parseInt($(document).scrollTop()),
scrollDir = scrollOffest > lastScrollTop ? 'down' : 'up';
for (var i in _ctxList) {
_ctxList[i].onScroll(scrollDir, scrollOffest);
}
lastScrollTop = scrollOffest;
});
});