元素固定插件

/**
 * 元素固定插件 by sunhaochen
 * create time 2017-11-1 16:39:40
 * **********参数说明***********
 * topSpace 固定元素上面的间距,譬如前面已经有一个固定元素了,此时就不能覆盖到前面的固定元素,把这个值设置为前面元素的高度就可以了
 * bottomLimit 向下滚动时,当下面有不能覆盖的元素时,就把固定元素固定在这里,不再随滚动条固定,以不覆盖下面的元素,譬如站点的脚部模块
 * topSpace bottomLimit 参数属性的有效值为像素值、数值、html元素、jQuery包装的html元素
 * topSpace 为元素时取该元素的高度
 * bottomLimit 为元素时取该元素的距html文档顶端高度
 * ******回调函数*******
 * stickBefore 固定前回调
 * stickAfter 固定后回调
 * unStickBefore 解除固定前回调
 * unStickAfter 解除固定后回调
 * **********参数说明***********
 * @param  {[object]} args [配置参数]
 * @return {[object]}      [jQ对象]
 */
$.fn.stickUp = function(args){
    var w = window;
	var w_w = $(w).width();
	var w_h = $(w).height();
	var p_h = $('body,html').height();
	var options = $.extend({
		topSpace : 0,
		bottomLimit : p_h,
		stickBefore : $.noop,
		stickAfter : $.noop,
		unStickBefore : $.noop,
		unStickAfter : $.noop
	},args||{});
	lastScrolDirction = 0;
	var paramIsErro = false;
	for ( var k in options ){
		if ( $.inArray(k,['topSpace','bottomLimit']) ){
			if ( typeof options[k] === 'string' ) {
				options[k] = parseFloat(options[k]);
				if ( isNaN(options[k]) ){
					paramIsErro = true;
				}
			} else if ( !options[k] ) {
				paramIsErro = true;
			} else if ( typeof options[k] === 'object' ) {
				if ( (options[k].length && !options[k][0].tagName) || (!options[k].length && !options[k].tagName) ) {
					paramIsErro = true;
				} else {
					if ( options[k][0].tagName ){
						if ( k === 'topSpace' ){
							options[k] = options[k].outerHeight();
						} else if ( k === 'bottomLimit' ) {
							options[k] = options[k].offset().top;
						}
					}
				}
			}
		}
	}
	if ( paramIsErro ){
		console.error('topSpace、bottomLimit参数属性的有效值为像素值、数值、html元素、jQuery包装的html元素');
	}
	options.topSpace = parseFloat(options.topSpace);
	options.bottomLimit = parseFloat(options.bottomLimit);
	var task = [];
	this.each(function(){
		var that = this;
		var $t = $(that);
		var e_w = $t.outerWidth();
		var e_h = $t.outerHeight();
		that.originPosi = {
			position: $t.css('position'),
			top: $t.css('top'),
			right: $t.css('right'),
			bottom: $t.css('bottom'),
			left: $t.css('left'),
			margin: $t.css('margin'),
			cssFloat: $t.css('cssFloat')
		}
		// 占位空容器
		var $emptyPlace = $('<div>').insertBefore(that).css($.extend({width:e_w,height:e_h,display:'none'},that.originPosi));
		var e_p = $t.offset();
		task.push(function(dir){
			var w_t = $(w).scrollTop();
			var e_t = $(that).offset().top;
			var topSpace = options.topSpace;
			// 限定顶部到下端区域
			var conda = w_t + topSpace + e_h < options.bottomLimit;
			var condb = w_t + topSpace > e_p.top;
			if ( dir === 'up' ){
				var condc = true;
			} else {
				var condc = w_t >= e_t - topSpace;
			}
			$emptyPlace.show();
			// console.log(conda , condb , condc)
			if ( conda && condb && condc ) {
				options.stickBefore.call({node: that,place: $emptyPlace});
				$t.css({
					position: 'fixed',
					margin: 0,
					top: topSpace,
					left: e_p.left
				});
				options.stickAfter.call({node: that,place: $emptyPlace});
			} else if ( options.bottomLimit && e_t > e_p.top && w_t + w_h > options.bottomLimit ) {
				options.stickBefore.call({node: that,place: $emptyPlace});
				// 减去元素用于定位的父节点到达文档顶部的高度,因为absolute是相对于含有定位属性的父节点来定位的
				var e_offset_parent = _offset_parent($t,{top:0,left:0});
				// 到达下端限定不容许覆盖元素
				$t.css({
					position: 'absolute',
					margin: 0,
					top: options.bottomLimit - e_h - e_offset_parent.top,
					left: e_p.left - e_offset_parent.left
				});
				options.stickAfter.call({node: that,place: $emptyPlace});
			} else {
				options.unStickBefore.call({node: that,place: $emptyPlace});
				$(that).css(that.originPosi);
				$emptyPlace.hide();
				options.unStickAfter.call({node: that,place: $emptyPlace});
			}
		})
	});
	function _offset_parent($t,n){
		var $p = $t.offsetParent();
		if ( $p.is('body') ) {
			return n;
		} else {
			return _offset_parent($p,{
				top : $p.offset().top + n.top,
				left : $p.offset().left + n.left
			});
		}
	}
	$(w).scroll(function(){
		var win_top = $(w).scrollTop();
		var dir = lastScrolDirction > win_top ? 'up' : 'down';
		lastScrolDirction = win_top
		for ( var i = 0; i < task.length; i++ ) {
			task[i](dir);
		}
	}).scroll();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值