-
-
-
-
stickUp
-
a jQuery plugin
-
A simple plugin that "sticks" an element to the top of the browser window while scrolling past it, always keeping it in view. This plugin works on multi-page sites, but has additional features for one-pager layouts.
-
Visit GitHub
+
+
+
+
+
stickUp
+
a jQuery plugin
+
A simple plugin that "sticks" an element to the top of the browser window while scrolling past it, always keeping it in view. This plugin works on multi-page sites, but has additional features for one-pager layouts.
+
Visit GitHub
+
+
+
-
-
+
-
-
+
+
+
+
+
-
-
-
-
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
diff --git a/stickUp.js b/stickUp.js
index 7d9e861..9d8e2cd 100644
--- a/stickUp.js
+++ b/stickUp.js
@@ -1,122 +1,162 @@
-jQuery(
-function($) {
-
- $(document).ready(function(){
- var contentButton = [];
- var contentTop = [];
- var content = [];
- var lastScrollTop = 0;
- var scrollDir = '';
- var itemClass = '';
- var itemHover = '';
- var menuSize = null;
- var stickyHeight = 0;
- var stickyMarginB = 0;
- var currentMarginT = 0;
- var topMargin = 0;
- $(window).scroll(function(event){
- var st = $(this).scrollTop();
- if (st > lastScrollTop){
- scrollDir = 'down';
- } else {
- scrollDir = 'up';
- }
- lastScrollTop = st;
- });
- $.fn.stickUp = function( options ) {
- // adding a class to users div
- $(this).addClass('stuckMenu');
- //getting options
- var objn = 0;
- if(options != null) {
- for(var o in options.parts) {
- if (options.parts.hasOwnProperty(o)){
- content[objn] = options.parts[objn];
- objn++;
- }
- }
- if(objn == 0) {
- console.log('error:needs arguments');
- }
+// 问题:不支持一个页面中多个元素固定(已实现)
+// 不支持固定方向的设置
+// 不支持回调事件(已实现)
+// 单页模式下,调整的定位是基于part参数的(重构后是基于html元素的data-menu)
+// 目前而言,许多操作是实时的——比如每次都重新查找、计算DOM
+// 这种方法对网页变动比较大的情景是非常适用的,但比较耗费性能
+//
+// 目前为止,缺乏测试
+jQuery(function($) {
+ "use strict";
- itemClass = options.itemClass;
- itemHover = options.itemHover;
- if(options.topMargin != null) {
- if(options.topMargin == 'auto') {
- topMargin = parseInt($('.stuckMenu').css('margin-top'));
- } else {
- if(isNaN(options.topMargin) && options.topMargin.search("px") > 0){
- topMargin = parseInt(options.topMargin.replace("px",""));
- } else if(!isNaN(parseInt(options.topMargin))) {
- topMargin = parseInt(options.topMargin);
- } else {
- console.log("incorrect argument, ignored.");
- topMargin = 0;
- }
- }
- } else {
- topMargin = 0;
- }
- menuSize = $('.'+itemClass).size();
- }
- stickyHeight = parseInt($(this).height());
- stickyMarginB = parseInt($(this).css('margin-bottom'));
- currentMarginT = parseInt($(this).next().closest('div').css('margin-top'));
- vartop = parseInt($(this).offset().top);
- //$(this).find('*').removeClass(itemHover);
- }
- $(document).on('scroll', function() {
- varscroll = parseInt($(document).scrollTop());
- if(menuSize != null){
- for(var i=0;i < menuSize;i++)
- {
- contentTop[i] = $('#'+content[i]+'').offset().top;
- function bottomView(i) {
- contentView = $('#'+content[i]+'').height()*.4;
- testView = contentTop[i] - contentView;
- //console.log(varscroll);
- if(varscroll > testView){
- $('.'+itemClass).removeClass(itemHover);
- $('.'+itemClass+':eq('+i+')').addClass(itemHover);
- } else if(varscroll < 50){
- $('.'+itemClass).removeClass(itemHover);
- $('.'+itemClass+':eq(0)').addClass(itemHover);
- }
- }
- if(scrollDir == 'down' && varscroll > contentTop[i]-50 && varscroll < contentTop[i]+50) {
- $('.'+itemClass).removeClass(itemHover);
- $('.'+itemClass+':eq('+i+')').addClass(itemHover);
- }
- if(scrollDir == 'up') {
- bottomView(i);
- }
- }
- }
+ 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;
- if(vartop < varscroll + topMargin){
- $('.stuckMenu').addClass('isStuck');
- $('.stuckMenu').next().closest('div').css({
- 'margin-top': stickyHeight + stickyMarginB + currentMarginT + 'px'
- }, 10);
- $('.stuckMenu').css("position","fixed");
- $('.isStuck').css({
- top: '0px'
- }, 10, function(){
+ // 计算并给适当元素添加 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);
+ }
+ }
+ }
+ }
- if(varscroll + topMargin < vartop){
- $('.stuckMenu').removeClass('isStuck');
- $('.stuckMenu').next().closest('div').css({
- 'margin-top': currentMarginT + 'px'
- }, 10);
- $('.stuckMenu').css("position","relative");
- };
+ // 固定菜单栏目,使之固定(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;
+ });
+});
\ No newline at end of file