draggable.js源码分析

draggable.js源码分析

CSS jQuery Gmail 
Java代码   收藏代码
  1. /** 
  2.  * draggable - jQuery EasyUI 
  3.  *  
  4.  * Licensed under the GPL: 
  5.  *   http://www.gnu.org/licenses/gpl.txt 
  6.  * 
  7.  * Copyright 2010 stworthy [ [email protected] ]  
  8.  */  
  9. (function($){  
  10.     //预存移动变量方法  
  11.     function drag(e){  
  12.         var opts = $.data(e.data.target, 'draggable').options;  
  13.         //中间变量  
  14.         var dragData = e.data;  
  15.         //拖动后的left=原先的left+拖动位移  
  16.         var left = dragData.startLeft + e.pageX - dragData.startX;  
  17.         var top = dragData.startTop + e.pageY - dragData.startY;  
  18.           
  19.         if (opts.deltaX != null && opts.deltaX != undefined){  
  20.             left = e.pageX + opts.deltaX;//如果有点击位移,左坐标直接等于鼠标位置+偏移  
  21.         }  
  22.         if (opts.deltaY != null && opts.deltaY != undefined){  
  23.             top = e.pageY + opts.deltaY;  
  24.         }  
  25.         //如果拖动对象有父对象,对于计算出来的left和top要加上父对象的left和top  
  26.         if (e.data.parnet != document.body) {  
  27.             if ($.boxModel == true) {//只针对盒子模型进行设置  
  28.                 left += $(e.data.parent).scrollLeft();  
  29.                 top += $(e.data.parent).scrollTop();  
  30.             }  
  31.         }  
  32.           
  33.         if (opts.axis == 'h') {//如果是水平拖动 则只改left  
  34.             dragData.left = left;  
  35.         } else if (opts.axis == 'v') {//如果是垂直,则只改top  
  36.             dragData.top = top;  
  37.         } else {  
  38.             dragData.left = left;  
  39.             dragData.top = top;  
  40.         }  
  41.     }  
  42.     //实现位移变化的函数  
  43.     function applyDrag(e){  
  44.         var opts = $.data(e.data.target, 'draggable').options;  
  45.         var proxy = $.data(e.data.target, 'draggable').proxy;//获取拖动对象的proxy对象,proxy就是我们在拖动时候随鼠标移动的对象  
  46.         if (proxy){  
  47.             proxy.css('cursor', opts.cursor);  
  48.         } else {  
  49.             proxy = $(e.data.target);  
  50.             $.data(e.data.target, 'draggable').handle.css('cursor', opts.cursor);  
  51.         }  
  52.         proxy.css({//最主要方法,该方法使得对象被拖动  
  53.             left:e.data.left,  
  54.             top:e.data.top  
  55.         });  
  56.     }  
  57.     //3按下鼠标时候执行的方法  
  58.     function doDown(e){  
  59.         var opts = $.data(e.data.target, 'draggable').options;//获取拖动对象中option配置信息  
  60.         //拖和放是对应的,现在来设置放对象  
  61.         var droppables = $('.droppable').filter(function(){//如果放对象和托对象是一个对象,则不拖动  
  62.             return e.data.target != this;  
  63.         }).filter(function(){//如何不是同一个对象  
  64.             var accept = $.data(this'droppable').options.accept;  
  65.             if (accept){//如果目标地设置了接收对象,则只有符合接收条件的对象才能被拖进来  
  66.                 return $(accept).filter(function(){  
  67.                     return this == e.data.target;  
  68.                 }).length > 0//只要有一个匹配就ok了  
  69.             } else {  
  70.                 return true//如果目标地,没设置接受对象,则所有对象都可以被拖进来。  
  71.             }  
  72.         });  
  73.         $.data(e.data.target, 'draggable').droppables = droppables;  
  74.           
  75.         var proxy = $.data(e.data.target, 'draggable').proxy;//获取拖动对象的proxy对象,proxy就是我们在拖动时候随鼠标移动的对象  
  76.         if (!proxy){//如果没有专门配置一个proxy  
  77.             if (opts.proxy){//看看option中是否有proxy,如果有  
  78.                 if (opts.proxy == 'clone'){//proxy为'clone'  
  79.                     proxy = $(e.data.target).clone().insertAfter(e.data.target);//复制当前dom,并查到当前dom后面  
  80.                 } else {  
  81.                     proxy = opts.proxy.call(e.data.target, e.data.target);//如果为一个函数,则调用这个函数返回值  
  82.                 }  
  83.                 $.data(e.data.target, 'draggable').proxy = proxy;//同事把opts.里面的proxy协会到拖动对象的draggable缓存配置里面去。  
  84.             } else {//如果哪里都没有的话  
  85.                 proxy = $(e.data.target);//proxy对象就是本身了  
  86.             }  
  87.         }  
  88.           
  89.         proxy.css('position''absolute');//因为是拖动,所以要absolute  
  90.         //开始拖动,改变拖动对象的一些属性值,放在中间变量中  
  91.         drag(e);  
  92.         //将对象的属性值进行更新,实现拖动效果  
  93.         applyDrag(e);  
  94.         //调用开始拖动函数  
  95.         opts.onStartDrag.call(e.data.target, e);  
  96.         return false;  
  97.     }  
  98.     //移动事件注册方法  
  99.     function doMove(e){  
  100.           
  101.         drag(e);  
  102.         if ($.data(e.data.target, 'draggable').options.onDrag.call(e.data.target, e) != false){  
  103.             applyDrag(e);  
  104.         }  
  105.           
  106.         var source = e.data.target;  
  107.         $.data(e.data.target, 'draggable').droppables.each(function(){  
  108.             var dropObj = $(this);  
  109.             var p2 = $(this).offset();  
  110.             if (e.pageX > p2.left && e.pageX < p2.left + dropObj.outerWidth()//判断是否已经拖动到目标区域内  
  111.                     && e.pageY > p2.top && e.pageY < p2.top + dropObj.outerHeight()){  
  112.                 if (!this.entered){ //触发移进事件,并设置移动标志量  
  113.                     $(this).trigger('_dragenter', [source]);  
  114.                     this.entered = true;  
  115.                 }  
  116.                 $(this).trigger('_dragover', [source]);//触发目标对象的over事件  
  117.             } else {  
  118.                 if (this.entered){//否则在判断下是否是从目标对象内移除,并设置标志量  
  119.                     $(this).trigger('_dragleave', [source]);  
  120.                     this.entered = false;  
  121.                 }  
  122.             }  
  123.         });  
  124.           
  125.         return false;  
  126.     }  
  127.       
  128.     function doUp(e){  
  129.         drag(e);  
  130.           
  131.         var proxy = $.data(e.data.target, 'draggable').proxy;  
  132.         var opts = $.data(e.data.target, 'draggable').options;  
  133.         if (opts.revert){  
  134.             if (checkDrop() == true){//如果进入了目标对象  
  135.                 removeProxy();  
  136.                 $(e.data.target).css({  
  137.                     position:e.data.startPosition,  
  138.                     left:e.data.startLeft,  
  139.                     top:e.data.startTop  
  140.                 });  
  141.             } else {  
  142.                 if (proxy){  
  143.                     proxy.animate({  
  144.                         left:e.data.startLeft,  
  145.                         top:e.data.startTop  
  146.                     }, function(){  
  147.                         removeProxy();  
  148.                     });  
  149.                 } else {  
  150.                     $(e.data.target).animate({  
  151.                         left:e.data.startLeft,  
  152.                         top:e.data.startTop  
  153.                     }, function(){  
  154.                         $(e.data.target).css('position', e.data.startPosition);  
  155.                     });  
  156.                 }  
  157.             }  
  158.         } else {//如果没有reverte设置,直接修改拖动dom的位置即可。  
  159.             $(e.data.target).css({  
  160.                 position:'absolute',  
  161.                 left:e.data.left,  
  162.                 top:e.data.top  
  163.             });  
  164.             removeProxy();//移除proxy对象  
  165.             checkDrop();  
  166.         }  
  167.           
  168.           
  169.           
  170.         opts.onStopDrag.call(e.data.target, e);  
  171.           
  172.         function removeProxy(){  
  173.             if (proxy){  
  174.                 proxy.remove();  
  175.             }  
  176.             $.data(e.data.target, 'draggable').proxy = null;  
  177.         }  
  178.         //该方法检验是否将对象拖动到目标对象内,如果拖动进去了,触发目标对象的_drop事件,并设置进入标志。  
  179.         function checkDrop(){  
  180.             var dropped = false;  
  181.             //对drop对象进行遍历操作  
  182.             $.data(e.data.target, 'draggable').droppables.each(function(){  
  183.                 var dropObj = $(this);  
  184.                 var p2 = $(this).offset();  
  185.                 if (e.pageX > p2.left && e.pageX < p2.left + dropObj.outerWidth()//如果移进了一个目标对象  
  186.                         && e.pageY > p2.top && e.pageY < p2.top + dropObj.outerHeight()){  
  187.                     if (opts.revert){//如果revert是true,就会还原  
  188.                         $(e.data.target).css({  
  189.                             position:e.data.startPosition,  
  190.                             left:e.data.startLeft,  
  191.                             top:e.data.startTop  
  192.                         });  
  193.                     }  
  194.                     $(this).trigger('_drop', [e.data.target]);  
  195.                     dropped = true;  
  196.                     this.entered = false;  
  197.                 }  
  198.             });  
  199.             return dropped;  
  200.         }  
  201.           
  202.         $(document).unbind('.draggable');//接触document上的事件,否则移动结束后,元素还是会变位置的  
  203.         return false;  
  204.     }  
  205.     //1,注册draggable方法到$()上  
  206.     $.fn.draggable = function(options){  
  207.         if (typeof options == 'string'){//option为字符串的时候,进行处理  
  208.             switch(options){  
  209.             case 'options':  
  210.                 return $.data(this[0], 'draggable').options;//为option,实际是获取,该对象缓存数据中名为draggable中的options对象,可以参考jquery $data()方法  
  211.             case 'proxy':  
  212.                 return $.data(this[0], 'draggable').proxy;//获取缓存中的proxy  
  213.             case 'enable'://执行禁止拖动操作。  
  214.                 return this.each(function(){  
  215.                     $(this).draggable({disabled:false});  
  216.                 });  
  217.             case 'disable'://允许拖动  
  218.                 return this.each(function(){  
  219.                     $(this).draggable({disabled:true});  
  220.                 });  
  221.             }  
  222.         }  
  223.           
  224.         return this.each(function(){    //通过调用$().draggable()方法来实现拖动  
  225. //          $(this).css('position','absolute');  
  226.               
  227.             var opts;  
  228.             var state = $.data(this'draggable');//获取对象上在缓存中存放的draggable对象,首次肯定为空  
  229.             if (state) {  
  230.                 state.handle.unbind('.draggable');  
  231.                 opts = $.extend(state.options, options);  
  232.             } else {  
  233.                 opts = $.extend({}, $.fn.draggable.defaults, options || {});//合并配置参数,来源为默认配置+传递进来的参数  
  234.             }  
  235.               
  236.             if (opts.disabled == true) {  //如果参数中含有禁止拖动的配置,则返回  
  237.                 $(this).css('cursor''default');  
  238.                 return;  
  239.             }  
  240.               
  241.             var handle = null;    //handle是实际触发拖动的对象  
  242.             if (typeof opts.handle == 'undefined' || opts.handle == null){  
  243.                 handle = $(this);  //handle为空,则默认为调用对象数组中本身的子元素  
  244.             } else {  
  245.                 handle = (typeof opts.handle == 'string' ? $(opts.handle, this) : handle);//如果为字符串,包装成本身jquery对象和本身两个对象。  
  246.             }  
  247.             $.data(this'draggable', {  //把opts信息更新到子元素的缓存中的draggable对象中  
  248.                 options: opts,  
  249.                 handle: handle  
  250.             });  
  251.               
  252.             // bind mouse event using event namespace draggable  
  253.             handle.bind('mousedown.draggable', {target:this}, onMouseDown); //注册拖动对象的mousedown事件,后面的.draggable是为事件注册一个命名空间,好处是unbind(.draggable)=unbind(.mousedown)+unbind(.mouseover)  
  254.             handle.bind('mousemove.draggable', {target:this}, onMouseMove);//注册鼠标滑动事件  //注意this代表的是$()元素中的每一个子dom元素  
  255.               
  256.             function onMouseDown(e) {  
  257.                 if (checkArea(e) == falsereturn;    
  258.   
  259.                 var position = $(e.data.target).position();//获取被拖动元素的top 和left  
  260.                 var data = {  //封装data 对象,记录width,height,pageX,pageY,left 和top是为了方便计算拖动后的位置  
  261.                     startPosition: $(e.data.target).css('position'), //absolute  or relative or active  
  262.                     startLeft: position.left,   
  263.                     startTop: position.top,   
  264.                     left: position.left,  
  265.                     top: position.top,  
  266.                     startX: e.pageX, //鼠标点击时的x坐标  
  267.                     startY: e.pageY, //鼠标点击时的y坐标  
  268.                     target: e.data.target, //子dom  
  269.                     parent: $(e.data.target).parent()[0//拖动对象的父dom  
  270.                 };  
  271.                   
  272.                 $(document).bind('mousedown.draggable', data, doDown); //在document上绑定三个鼠标事件。根据事件的下传特性,当在目标对象上执行drap.就会触发document上的drap.  
  273.                 $(document).bind('mousemove.draggable', data, doMove); //以下主要分析doDown,doMove 和doUp的实现过程  
  274.                 $(document).bind('mouseup.draggable', data, doUp);  
  275.             }  
  276.               
  277.             function onMouseMove(e) {  //move事件主要是当鼠标移动到可以拖拽元素上,鼠标形状进行改变  
  278.                 if (checkArea(e)){  
  279.                     $(this).css('cursor', opts.cursor);  
  280.                 } else {  
  281.                     $(this).css('cursor''default');  
  282.                 }  
  283.             }  
  284.               
  285.             // check if the handle can be dragged  判断鼠标拖动点,离handle的四面八方是否小于设置的adge,如果有一边小于则不拖动  
  286.             function checkArea(e) {  
  287.                 var offset = $(handle).offset();  
  288.                 var width = $(handle).outerWidth();  
  289.                 var height = $(handle).outerHeight();  
  290.                 var t = e.pageY - offset.top;  
  291.                 var r = offset.left + width - e.pageX;  
  292.                 var b = offset.top + height - e.pageY;  
  293.                 var l = e.pageX - offset.left;  
  294.                   
  295.                 return Math.min(t,r,b,l) > opts.edge;  
  296.             }  
  297.               
  298.         });  
  299.     };  
  300.       
  301.     $.fn.draggable.defaults = {  //2默认配置信息  
  302.             proxy:null// 'clone' or a function that will create the proxy object,   
  303.                         // the function has the source parameter that indicate the source object dragged.  
  304.             revert:false,//该属性是设置拖动后自动还原效果,试一下就知道了  
  305.             cursor:'move',  
  306.             deltaX:null,//鼠标点击拖动对象时候,proxy的位移,称作德尔塔  
  307.             deltaY:null,  
  308.             handle: null,  
  309.             disabled: false,  
  310.             edge:0,  
  311.             axis:null,  // v or h  水平还是垂直方向拖动  
  312.               
  313.             onStartDrag: function(e){},  
  314.             onDrag: function(e){},  
  315.             onStopDrag: function(e){}  
  316.     };  
  317. })(jQuery);  

http://kalllx.iteye.com/blog/830917

你可能感兴趣的:(JS)