(function($) {
//uri:http://caibaojian.com/scrollfix
//author:caibaojian
//website:http://caibaojian.com
//descirption:scroll and fixed some div
$.fn.scrollfix = function(options) {
return this.each(function() {
var opts = $.extend({}, $.fn.scrollfix.defaultoptions, options);
var obj = $(this),
base = this,
selftop = 0,
selfleft = 0,
totop = 0,
parentoffsetleft = 0,
parentoffsettop = 0,
outerheight,
outerwidth,
objwidth = 0,
placeholder = jquery('
'), //创建一个jquery对象
optstop = opts.distancetop, //定义到顶部的高度
endfix = 0; //开始停止固定的位置
var originalposition;
var originaloffsettop;
var originalzindex;
var lastoffsetleft = -1;
var isunfixed = true;
//如果没有找到节点,不进行处理
if (obj.length <= 0) {
return;
}
if (lastoffsetleft == -1) {
originalzindex = obj.css('z-index');
position = obj.css('position');
originalposition = obj.css('position');
originaloffsettop = obj.css('top');
}
var zindex = obj.css('zindex');
if (opts.zindex != 0) {
zindex = opts.zindex;
}
//获取相对定位或者绝对定位的父类
var parents = obj.parent();
var position = parents.css('position');
while (!/^relative|absolute$/i.test(position)) { //检测浮动元素的父类元素定位为'relative'或者'absolute',是的话退出,否则的话,执行循环,继续寻找它的父类
parents = parents.parent();
position = parents.css('position');
if (/^body|html$/i.test(parents[0].tagname)) break; //假如父类元素的标签为body或者html,说明没有找到父类为以上的定位,退出循环
}
var ie6 = !-[1, ] && !window.xmlhttprequest; //兼容ie6
var resizewindow = false;
function resetscroll() {
setunfixed();
selftop = obj.offset().top; //对象距离顶部高度
selfleft = obj.offset().left; //对象距离左边宽度
outerheight = obj.outerheight(); //对象高度
outerheight = parsefloat(outerheight) + parsefloat(obj.css('marginbottom').replace(/auto/, 0));
outerwidth = obj.outerwidth(); //对象外宽度
objwidth = obj.width();
var documentheight = $(document).height(); //文档高度
var starttop = $(opts.starttop), //开始浮动固定对象
startbottom = $(opts.startbottom),
tobottom, //停止滚动位置距离底部的高度
scrollheight; //对象滚动的高度
//计算父类偏移值
if (/^body|html$/i.test(parents[0].tagname)) { //当父类元素非body或者html时,说明找到了一个父类为'relative'或者'absolute'的元素,得出它的偏移高度
parentoffsettop = 0, parentoffsetleft = 0;
} else {
parentoffsetleft = parents.offset().left, parentoffsettop = parents.offset().top;
}
// 计算父节点的上边到顶部距离
// 如果 body 有 top 属性, 消除这些位移
var bodytotop = parseint(jquery('body').css('top'), 10);
if (!isnan(bodytotop)) {
optstop += bodytotop;
}
//计算停在底部的距离
if (!isnan(opts.endpos)) {
tobottom = opts.endpos;
} else {
tobottom = parsefloat(documentheight - $(opts.endpos).offset().top);
}
//计算需要滚动的高度以及停止滚动的高度
scrollheight = parsefloat(documentheight - tobottom - optstop), endfix = parsefloat(scrollheight - outerheight);
//计算顶部的距离值
if (starttop[0]) {
var starttopoffset = starttop.offset(),
starttoppos = starttopoffset.top;
selftop = starttoppos;
}
if (startbottom[0]) {
var startbottomoffset = startbottom.offset(),
startbottompos = startbottomoffset.top,
startbottomheight = startbottom.outerheight();
selftop = parsefloat(startbottompos + startbottomheight);
}
totop = selftop - optstop;
totop = (totop > 0) ? totop : 0;
var selfbottom = documentheight - selftop - outerheight;
//如果滚动停在底部的值不为0,并且自身到底部的高度小于上面这个值,不执行浮动固定
if ((tobottom != 0) && (selfbottom <= tobottom)) {
return;
}
}
function setunfixed() {
if (!isunfixed) {
lastoffsetleft = -1;
placeholder.css("display", "none");
obj.css({
'z-index': originalzindex,
'width': '',
'position': originalposition,
'left': '',
'top': originaloffsettop,
'margin-left': ''
});
obj.removeclass('scrollfixed');
isunfixed = true;
}
}
function onscroll() {
lastoffsetleft = 1;
var scrolltop = $(window).scrolltop();
if (opts.bottom != -1) {
scrolltop = scrolltop + $(window).height() - outerheight - opts.bottom;
}
if (scrolltop > totop && (scrolltop < endfix)) {
if (ie6) { //ie6则使用这个样式
obj.addclass(opts.baseclassname).css({
"z-index": zindex,
"position": "absolute",
"top": opts.bottom == -1 ? scrolltop + optstop - parentoffsettop : scrolltop - parentoffsettop,
"bottom": 'auto',
"left": selfleft - parentoffsetleft,
'width': objwidth
})
} else {
obj.addclass(opts.baseclassname).css({
"z-index": zindex,
"position": "fixed",
"top": opts.bottom == -1 ? optstop : '',
"bottom": opts.bottom == -1 ? '' : opts.bottom,
"left": selfleft,
"width": objwidth
});
}
placeholder.css({
'height': outerheight,
'width': outerwidth,
'display': 'block'
}).insertbefore(obj);
} else if (scrolltop >= endfix) {
obj.addclass(opts.baseclassname).css({
"z-index": zindex,
"position": "absolute",
"top": endfix - parentoffsettop + optstop,
'bottom': '',
"left": selfleft - parentoffsetleft,
"width": objwidth
});
placeholder.css({
'height': outerheight,
'width': outerwidth,
'display': 'block'
}).insertbefore(obj)
} else {
obj.removeclass(opts.baseclassname).css({
"z-index": originalzindex,
"position": "static",
"top": "",
"bottom": "",
"left": ""
});
placeholder.remove()
}
}
var timer = 0;
// if (isunfixed) {
resetscroll();
// }
$(window).on("scroll", function() {
if (timer) {
cleartimeout(timer);
}
timer = settimeout(onscroll, 0);
});
// 当发现调整屏幕大小时,重新执行代码
$(window).on("resize", function() {
if (timer) {
cleartimeout(timer);
}
timer = settimeout(function() {
isunfixed = false;
resetscroll();
onscroll();
}, 0);
});
})
}
$.fn.scrollfix.defaultoptions = {
starttop: null, //滑到这个位置顶部时开始浮动,默认为空
startbottom: null, //滑到这个位置末端开始浮动,默认为空
distancetop: 0, //固定在顶部的高度
endpos: 0, //停靠在底部的位置,可以为jquery对象
bottom: -1, //底部位置
zindex: 0, //z-index值
baseclassname: 'scrollfixed' //开始固定时添加的类
};
})(jquery);