Jq-滚动条插件写法(一)

最近这水平越来越退步,想写个js组件,但一直担搁,退而求次之,搞个jq插件还是可以滴。没想到,想半天不得其法,没办法,只能参考一个吧。以下看客不要太认真全是抄来的。

原始地址:

 

jscoll 的优点就不一一列举了,说一下缺点:

1. 众多灵活的参数配置,在灵活的背后牺牲了傻瓜操作可控性, 让一些不懂css的程序员,不懂jq的美工,咬牙切齿,遂有重写一个的想法。

2. jscoll的js代码虽然没有加密混淆,但是2字母式的变量名,让我望其却步,可维护可扩展性,无从谈起。

3. css全是内联style式的,这种虽然必杀效果的同时,也杀了页面可维护性,而且利用css属性选择器的特性,jq的配置参数没必要这么烦琐。

 

一、jq插件的写法:

1. 第一种是直接挂在$这个工厂函数上的。

jQuery.extend:  对jQuery对象本身扩展,不需要实例jq对象就可以使用 。
$.extend({
    add: function(a, b){
        return a + b;
    }
});

//这是多个扩展的写法,如果是一个的话,则是:

$.add = function(a, b){
    return a - b;
}; 

 

//调用时:

alert($.add(3, 4)); 

 

 

2. 第二种是需要应用在jq对象上的,所以是另外一种写法:

$.fn.extend({
    color: function(val){
        if(val == undefined){
            return $(this).css('color');
        } else {
            return $(this).css('color', val);
        }
    }
});

//要是只扩展一个的话:

$.fn.color = function(){

   //do something

}

//调用时:

$('#text').color('#f00') 

 

默认的滚动条,样式过于单一,又不是动态修改,故而废之,重新来一个:

在写插件之前,必先写html结构样式,大概解释一下:

reset

*{margin:0;padding:0;}
body
{font:12px/2 arial;background:#333;}

例子准备包在最外层容器,以及里边内容的容器,.jkscool-wrap 是写relative 的原因是为了右边滚动条的定位,而.jkscoll-cont写relative的目的是为了内容的滚动。

.jk-scrolldemo{width:700px;padding:1px;margin:20px auto;border:1px solid #ccc;background:#fff;}
.jkscroll-wrap
{position:relative;padding:0;height:200px;overflow:hidden;}
.jkscroll-cont
{position:relative;padding-right:15px;top:0px;z-index:9999;}

里边要滚动内容的样式,没有什么特别之处:

.jkscroll-text{padding:5px;}
.jkscroll-text p
{margin-bottom:10px;}

滚动条的样式,这里边比较讲究,首先来说,.jkscroll-bar 的position:absolute,这个是有来历的,由于外层是position:relative,所以里层是absolute的话,则会以外层的左上角为位移参考对齐。当然外层只写position:relative,不写top,left两值。如果写这两个值又是怎么会事呢?如果写上这两个值,则表示以:以这个元素的本来应该在的位置为布局参照原点。

 

还有一种情况是,只是一个position:absolute;外层没有position:relative,这时会找寻那个点为参考呢?这时候的原则是:如果某父级元素中有relative者,则以某父级元素为参考原点,如果没有position:relative,则以body为参考原点。如果position:absolute外层没有relative时,这两个布局上是没有区别的。

 

当然最后一种情况是:外层是:position:absolute;里边是position:relative,那会是什么情况?按着原来的原则,absolute会参考body为布局原点,relative会参考他本来应该在的位置为布局原点,这时候其实就是参考外层左上角为布局原点。

当然该是上个栗子的时候了:

搞懂上面这些,下面的css一切尽在掌握中,基本没有什么可点可圈之处。实在懒得图片都用原来的,只不过多了几个颜色值,如果那一天这个站点灰飞烟灭,那只会显示几个颜色块。

.jkscroll-bar{position:absolute;top:0px;right:0px;width:15px;height:100%;background:url(http://app.soche8.com/show/jscoll/s_bg2.gif) repeat-y right 0 #edf7fa;z-index:10000;}
.jkscroll-bar-top,.jkscroll-bar-bot
{position:absolute;height:15px;left:0px;width:100%;cursor:pointer;background:url(http://app.soche8.com/show/jscoll/s_bg2.gif) no-repeat 0 0 #bbdef6;}
.jkscroll-bar-top
{top:0px;}
.jkscroll-bar-bot
{bottom:0px;background-position:0 -15px;}
.jkscroll-bar-mid
{position:absolute;top:15px;width:13px;height:100px;border:1px solid #A3C3D5;background:url(http://app.soche8.com/show/jscoll/s_bg2.gif) repeat-y -45px 0 #e0f1fc;}
.jkscroll-bar-mid-hover
{background:url(http://app.soche8.com/show/jscoll/s_bg2.gif) repeat-y -58px 0 #dceffc;}

当然中间还有一点css sprite的东西,不用多介绍了吧。

下面是结构:

<div class="jk-scrolldemo">
    <div class="jkscroll-wrap">
        <div class="jkscroll-cont">
            <div class="jkscroll-text">
                <p>“部长将带队50人的司局级干部调研组,深入每个省区对保障房开工率进行现场检查。”一位接近住建部的人士向记者透露,针对保障性安居工程开工“掺水”和质量问题,住建部将对地方的保障安居工程建设进行摸底调研。</p>
                <p>上述人士介绍,检查方式分两步,先是市级部门自查,统计信息上报省建设厅,各省的建设厅派督察组对地方抽样检查,核实情况;再有以住建部部长姜伟新为代表的部司级领导组成的50人的督察组还将深入地方调研,确保数据的准确性。</p>
                <p>据悉,此次督察全面遵守住建部要求的“三个开工”标准,即1/3浇筑地基、1/3超出地面、1/3主体结构完工。不达标,不计入计算开工率范畴。</p>
                <p>中国房地产研究会副会长陈国强表示,按照新的开工率计算标准来核算的话,肯定有很多地方政府的项目开工率达不到要求,被挤出水分,这相当于住建部对开工率进行一次重算。</p>
                <p>11月22日,由国家住房和城乡建设部部长姜伟新带队的保障性安居工程建设督察组前往宁夏考察,拉开了住建部督察各地保障性安居工程建设工作的序幕。</p>
                <p>据悉,此次督察全面遵守住建部要求的“三个开工”标准,即1/3浇筑地基、1/3超出地面、1/3主体结构完工。不达标,不计入计算开工率范畴。</p>
                <p>中国房地产研究会副会长陈国强表示,按照新的开工率计算标准来核算的话,肯定有很多地方政府的项目开工率达不到要求,被挤出水分,这相当于住建部对开工率进行一次重算。</p>
                <p>11月22日,由国家住房和城乡建设部部长姜伟新带队的保障性安居工程建设督察组前往宁夏考察,拉开了住建部督察各地保障性安居工程建设工作的序幕。</p>
                <p>据悉,此次督察全面遵守住建部要求的“三个开工”标准,即1/3浇筑地基、1/3超出地面、1/3主体结构完工。不达标,不计入计算开工率范畴。</p>
                <p>中国房地产研究会副会长陈国强表示,按照新的开工率计算标准来核算的话,肯定有很多地方政府的项目开工率达不到要求,被挤出水分,这相当于住建部对开工率进行一次重算。</p>
                <p>11月22日,由国家住房和城乡建设部部长姜伟新带队的保障性安居工程建设督察组前往宁夏考察,拉开了住建部督察各地保障性安居工程建设工作的序幕。</p>
            </div>
        </div>
        <!-- /主显内容区域 -->
        <div class="jkscroll-bar">
            <div class="jkscroll-bar-top"></div>
            <div class="jkscroll-bar-mid"></div>
            <div class="jkscroll-bar-bot"></div>
        </div>
        <!-- /注意这块 -->
    </div>
</div>

这里边有说明的是,“注意这块”,部分是将来append进来的,但是在界面布局初期,为了最终的效果调试是要写上的。

最终静态页面的效果:

说了半天,下面才是本文的重点:

二、 开始写:

上半部分是创建一个匿名函数,目的就是为了我们继续无耻的使用'$'符号,下半部分是本插件的调用。这里边的 this 指的是 要调用的那个DOM元素,这里是:$('.jkscroll-wrap') ,所以这就是前面准备的“注意这里”,删除空格后添加到 $('.jkscroll-wrap')的后半部分。当然原来的肯定要删除。

(function($){
    $.fn.jikeyScrollerBar = function(options){        
        //添加滚动条DOM结构
        var jkScrollCont = this.append('<div class="jkscroll-bar"><div class="jkscroll-bar-top"></div><div class="jkscroll-bar-mid"></div><div class="jkscroll-bar-bot"></div></div>');
                
    };
})(jQuery);

//插件调用
$('.jkscroll-wrap').jikeyScrollerBar();

 

这里又有一个问题,jq操作增加DOM的几个方法:

append: 插入到里边内容的后边。那要是前边呢,则是:prepend.

如:

//原始:<p>I would like to say: </p>
$("p").prepend("<b>Hello</b>");

//结果:
//
<p><b>Hello</b>I would like to say: </p>

 那要是在自身的前边后边插入呢:

//往后插:
//
原始:<p>I would like to say: </p>
$("p").after("<b>Hello</b>");

//结果:
//
<p>I would like to say: </p><b>Hello</b>

//往前插:
//
原始:<p>I would like to say: </p>
$("p").before("<b>Hello</b>");

//结果:
//
<b>Hello</b><p>I would like to say: </p>

 好多人感觉写js,jq小东西无从下手,其实说白了一文不值,写插件过程就是:1. 先创建可编辑DOM元素 -> 2. 用jq找到要操作DOM元素 -> 3. 对DOM元素进行初始化处理(就是刚打开页面的时候极端值的设置) -> 4. 与用户发生交互时的事件定制 -> 5. 完善其它遗漏 -> 6. 完成发布。

大概就这样,用jq写插件众多好处是:jq选择器是他的强项,兼容性问题基本不用考虑,调用方便。

坏处是:由于受到jq本身性能等问题的影响,如果没有js基础,驾驭不好jq,就会造成连环式的恶劣后果。所以,插件也是不好写的。

刚才弄了半天就是完成第1步,创建可编辑的DOM元素,

下来完成第2步,用jq寻找要操作的DOM元素,根据this.append返回的对象,得到以下所要用到的需要操作的jq对象。

var jkBar = jkScrollCont.find('.jkscroll-bar');
    jKBarTop = jkScrollCont.find('.jkscroll-bar-top'), //顶部按钮
    jKBarMid = jkScrollCont.find('.jkscroll-bar-mid'), //中间滚动条
    jKBarBot = jkScrollCont.find('.jkscroll-bar-bot'), //底部按钮
    jKCont = jkScrollCont.find('.jkscroll-cont'); //内容区域

第3步:进行初始化处理,由于滚动的内容跟滚动条要形成一定的关系,所以滚动条的高度也要动态的设置,至于为什么这样写,没看懂抄的。jKBarMid.hover();是为滚动条添加a:hover效果,没有什么特别的意义。

var currentTop = 0, //滚动条当前距顶部的高度
    jkBarBtnWidth = jkBar.width(); //按钮的宽度
    wrapH = jkScrollCont.height(), //容器的高度
    contH = jKCont.height(), //内容的实际高度
    jkBarH = (wrapH - 2 * jkBarBtnWidth) * wrapH / contH; //滚动条高度

//以下都是做为初始化数据
jkBarH < 10 && (jkBarH = 10);
jKBarMid.height(jkBarH);

jKBarMid.hover(function(){
    $(this).addClass('jkscroll-bar-mid-hover');
}, function(){
    $(this).removeClass('jkscroll-bar-mid-hover');
});
                
//如果内容高度小于等于容器的高度时,隐藏滚动条
if(contH <= wrapH){
    jKCont.css('padding-right', 0);
    jkBar.hide();
}

第4步:交互事件的定制,这里边主要是jq事件 bind,live,delegate几个区别,有兴趣看看,delegate http://article.yeeyan.org/view/213582/179910。

//滚动条绑定滚动事件
jkBar.delegate('div', 'mousedown', function(e){ //为什么要采取 delegate http://article.yeeyan.org/view/213582/179910
    var pageY = e.pageY, //鼠标的位置
        jkBarTop = parseInt($(this).css('top')); //中间滚动条当前的高度
        
    $(document).mousemove(function(e2){
        currentTop = jkBarTop + e2.pageY - pageY;
        setMidTop();
        
        //拖动时取消选择文本
        window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty(); 
    });
    
    $(document).mouseup(function(){
        $(document).unbind();
    });
    
    return false;   
});
        
//设置高度
function setMidTop(){
    
    currentTop < jkBarBtnWidth && (currentTop = jkBarBtnWidth); //防止拖出向上按钮
    currentTop > wrapH - jkBarBtnWidth - jkBarH && (currentTop = wrapH - jkBarBtnWidth - jkBarH); //防止拖出向下按钮
    jKBarMid.css({top: currentTop}); //设置滚动条离顶的距离
    
    var jkContTop = ((currentTop - jkBarBtnWidth) * contH)/(wrapH - 2 * jkBarBtnWidth);
    
    jKCont.css({top: -jkContTop}); //设置内容离顶的距离
};

 到此的效果是:

 

posted @ 2011-12-02 11:44  豪情  阅读(10642)  评论(3编辑  收藏  举报