text: ﻿(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 = $("<div style='position:absolute;display:none;line-height:0;'></div>");
  		jqScrollBox.addClass(opts.sBoxClassName);
  		//创建滚动条
  		var jqScrollBar= $("<div style='position:absolute;display:none;line-height:0;'></div>");
  		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);
  	