(function($){ $.zui = $.zui || {} $.zui.emptyfn = function(){}; $.zui.aswidget = []; /* * core代码,定义增加一个插件的骨架 */ $.zui.addwidget = function(sname,osefdef){ //设置规范中的常量sflagname、seventname、soptsname $.zui.aswidget.push(sname); var w = $.zui[sname] = $.zui[sname] || {}; var sprefix = "zui" + sname w.sflagname = sprefix; w.seventname = sprefix + "event"; w.soptsname = sprefix + "opts"; w.__creator = $.zui.emptyfn; w.__destroyer = $.zui.emptyfn; $.extend(w,osefdef); w.fn = function(ele,opts){ var jqele = $(ele); jqele.data(w.soptsname,$.extend({},w.defaults,opts)); //如果该元素已经执行过了该插件,直接返回,仅相当于修改了配置参数 if(jqele.data(w.sflagname)){ return; } jqele.data(w.sflagname,true); w.__creator(ele); jqele.on(jqele.data(w.seventname)); }; w.unfn = function(ele){ w.__destroyer(ele); var jqele = $(ele);//移除监听事件 if(jqele.data(w.sflagname)){ jqele.off(jqele.data(w.seventname)); jqele.data(w.sflagname,false); } } } /* * draggable * 参数:obj{ * boffsetparentboundary:是否以定位父亲元素为边界, * oboundary:指定元素left和top的边界值,形如{iminleft:...,imaxleft:...,imintop:...,imaxtop:...},与上一个参数互斥 * fncomputeposition:扩展函数,返回形如{left:...,top:...}的对象 * } * 支持的自定义事件: * "draggable.start":drag起始,就是鼠标down后触发 * "draggable.move":drag过程中多次触发 * "draggable.stop":drag结束触发,就是鼠标up后触发 */ //注册draggable组件 $.zui.addwidget("draggable",{ defaults:{ boffsetparentboundary:false,//是否以定位父亲元素为边界 oboundary:null,//边界 fncomputeposition:null//计算位置的函数 }, __creator:function(ele){ var jqele = $(ele); jqele.data($.zui.draggable.seventname,{ mousedown:function(ev){ var jqthis = $(this); var opts = jqthis.data($.zui.draggable.soptsname); jqthis.trigger("draggable.start"); var ioffsetx = ev.pagex - this.offsetleft; var ioffsety = ev.pagey - this.offsettop; function fnmousemove (ev) { var opos = {}; if(opts.fncomputeposition){ opos = opts.fncomputeposition(ev,ioffsetx,ioffsety); }else{ opos.ileft = ev.pagex - ioffsetx; opos.itop = ev.pagey - ioffsety; } var oboundary = opts.oboundary; if(opts.boffsetparentboundary){//如果以offsetparent作为边界 var eparent = jqthis.offsetparent()[0]; oboundary = {}; oboundary.iminleft = 0; oboundary.imintop = 0; oboundary.imaxleft = eparent.clientwidth - jqthis.outerwidth(); oboundary.imaxtop = eparent.clientheight - jqthis.outerheight(); } if(oboundary){//如果存在oboundary,将oboundary作为边界 opos.ileft = opos.ileft < oboundary.iminleft ? oboundary.iminleft : opos.ileft; opos.ileft = opos.ileft > oboundary.imaxleft ? oboundary.imaxleft : opos.ileft; opos.itop = opos.itop < oboundary.imintop ? oboundary.imintop : opos.itop; opos.itop = opos.itop > oboundary.imaxtop ? oboundary.imaxtop : opos.itop; } jqthis.css({left:opos.ileft,top:opos.itop}); ev.preventdefault(); jqthis.trigger("draggable.move"); } var oevent = { mousemove:fnmousemove, mouseup:function(){ $(document).off(oevent); jqthis.trigger("draggable.stop"); } }; $(document).on(oevent); }}); } }); /* * panel * 参数:obj{ * iwheelstep:鼠标滑轮滚动时步进长度 * sboxclassname:滚动框的样式 * sbarclassname:滚动条的样式 * } */ $.zui.addwidget("panel",{ defaults : { iwheelstep:16, sboxclassname:"zuipanelscrollbox", sbarclassname:"zuipanelscrollbar" }, __creator:function(ele){ var jqthis = $(ele); //如果是static定位,加上relative定位 if(jqthis.css("position") === "static"){ jqthis.css("position","relative"); } jqthis.css("overflow","hidden"); //必须有一个唯一的直接子元素,给直接子元素加上绝对定位 var jqchild = jqthis.children(":first"); if(jqchild.length){ jqchild.css({top:0,position:"absolute"}); }else{ return; } var opts = jqthis.data($.zui.panel.soptsname); //创建滚动框 var jqscrollbox = $("
"); jqscrollbox.addclass(opts.sboxclassname); //创建滚动条 var jqscrollbar= $("
"); jqscrollbar.addclass(opts.sbarclassname); jqscrollbox.appendto(jqthis); jqscrollbar.appendto(jqthis); opts.itop = parseint(jqscrollbox.css("top")); opts.iwidth = jqscrollbar.width(); opts.iright = parseint(jqscrollbox.css("right")); //添加拖拽触发自定义函数 jqscrollbar.on("draggable.move",function(){ var opts = jqthis.data($.zui.panel.soptsname); fnscrollcontent(jqscrollbox,jqscrollbar,jqthis,jqchild,opts.itop,0); }); //事件对象 var oevent ={ mouseenter:function(){ fnfreshscroll(); jqscrollbox.css("display","block"); jqscrollbar.css("display","block"); }, mouseleave:function(){ jqscrollbox.css("display","none"); jqscrollbar.css("display","none"); } }; var smousewheel = "mousewheel"; if(!("onmousewheel" in document)){ smousewheel = "dommousescroll"; } oevent[smousewheel] = function(ev){ var opts = jqthis.data($.zui.panel.soptsname); var iwheeldelta = 1; ev.preventdefault();//阻止默认事件 ev = ev.originalevent;//获取原生的event if(ev.wheeldelta){ iwheeldelta = ev.wheeldelta/120; }else{ iwheeldelta = -ev.detail/3; } var imintop = jqthis.innerheight() - jqchild.outerheight(); //外面比里面高,不需要响应滚动 if(imintop>0){ jqchild.css("top",0); return; } var itop = parseint(jqchild.css("top")); var itop = itop + opts.iwheelstep*iwheeldelta; itop = itop > 0 ? 0 : itop; itop = itop < imintop ? imintop : itop; jqchild.css("top",itop); fnscrollcontent(jqthis,jqchild,jqscrollbox,jqscrollbar,0,opts.itop); } //记录添加事件 jqthis.data($.zui.panel.seventname,oevent); //跟随滚动函数 function fnscrollcontent(jqwrapper,jqcontent,jqfollowwrapper,jqflollowcontent,ioffset1,ioffset2){ var opts = jqthis.data($.zui.panel.soptsname); var rate = (parseint(jqcontent.css("top"))-ioffset1)/(jqcontent.outerheight()-jqwrapper.innerheight())//卷起的比率 var itop = (jqflollowcontent.outerheight()-jqfollowwrapper.innerheight())*rate + ioffset2; jqflollowcontent.css("top",itop); } //刷新滚动条 function fnfreshscroll(){ var opts = jqthis.data($.zui.panel.soptsname); var iscrollboxheight = jqthis.innerheight()-2*opts.itop; var irate = jqthis.innerheight()/jqchild.outerheight(); var iscrollbarheight = iscrollbarheight = math.round(irate*iscrollboxheight); //如果比率大于等于1,不需要滚动条,自然也不需要添加拖拽事件 if(irate >= 1){ jqscrollbox.css("height",0); jqscrollbar.css("height",0); return; } jqscrollbox.css("height",iscrollboxheight); jqscrollbar.css("height",iscrollbarheight); //计算拖拽边界,添加拖拽事件 var oboundary = {imintop:opts.itop}; oboundary.imaxtop = iscrollboxheight - math.round(irate*iscrollboxheight)+opts.itop; oboundary.iminleft = jqthis.innerwidth() - opts.iwidth - opts.iright; oboundary.imaxleft = oboundary.iminleft; fnscrollcontent(jqthis,jqchild,jqscrollbox,jqscrollbar,0,opts.itop); jqscrollbar.draggable({oboundary:oboundary}); } }, __destroyer:function(ele){ var jqele = $(ele); if(jqele.data($.zui.panel.sflagname)){ var opts = jqele.data($.zui.panel.soptsname); jqele.children("."+opts.sboxclassname).remove(); jqele.children("."+opts.sbarclassname).remove(); } } }); $.each($.zui.aswidget,function(i,widget){ unwidget = "un"+widget; var w = {}; w[widget] = function(args){ this.each(function(){ $.zui[widget].fn(this,args); }); return this; }; w[unwidget] = function(){ this.each(function(){ $.zui[widget].unfn(this); }); return this; } $.fn.extend(w); }); })(jquery);