
3.2 拖放(Draggable)
拖放组件用于实现指定元素的拖放,它能使元素随着鼠标而移动。本节将介绍拖放组件的使用方法,向读者介绍如何将拖放元素限制在指定的容器中以及如何让拖放元素在网格中快速移动。
3.2.1 拖放的使用方法
拖放的默认配置定义在$.fn.draggable.defaults中。
1. 创建拖放
使用标记创建拖放的方法如下:
01 <div id="dd" class="easyui-draggable" data-options="handle:'#title'" style="width:100px"> 02 <div id="title" style="background:#ccc;">拖放元素</div> 03 </div>
通过JavaScript创建拖放的方法如下:
01 <div id="dd" style="width:100px "> 02 <div id="title" style="background:#ccc;"> 拖放元素</div> 03 </div> 04 $('#dd').draggable({ 05 handle:'#title' 06 });
2. 拖放属性
拖放组件常用属性说明见表3.2。
表3.2 拖放常用属性说明

handle指定的是开始拖动时可被选中的元素,例如我们在一个可被拖动的容器内定义两个元素e1和e2:
01 <div class="drag-container"> 02 <p id="e1">元素1</p> 03 <p id="e2">元素2</p> 04 </div>
当handle属性设置为元素1的选择器时,只有当鼠标放到元素1上才可以拖动该容器。如果不设置handle的值,那么将鼠标放到容器的任意位置都可拖动该容器。
edge属性设置的是拖动元素内不可被拖动的区域宽度,默认设置为0意味着整个元素都可被拖动,详细解释如图3.3所示。

图3.3 edge属性详解
proxy属性其实就是设置元素拖动过程中的展示值,读者可以理解为拖动元素有两个值,第一个为其存储值(初始化时显示的值),第二个为其展示值(拖动时显示的值)。如果设置proxy参数为null,此时展示值即为存储值,当设置proxy参数为clone时展示值为存储值的一个克隆元素,开发者也可以使用函数自定义拖动过程中的展示值。例如下面我们设置元素拖动时在其外部显示一个边框,部分代码如下:
01 <body> 02 <div id="dd" style="width:100px;height:100px "> 03 <div id="title"> 拖放元素</div> 04 </div> 05 </body> 06 <script> 07 $(function(){ 08 $('#dd').draggable({ 09 proxy: function(source){ 10 var p = $('<div style="border:1px solid #ccc;width:100px"></div>'); 11 p.html($(source).html()).appendTo('body'); 12 return p; 13 }, 14 handle:'#title', 15 }); 16 }); 17 </script>
最终显示结果如图3.4所示。

图3.4 proxy属性演示
3. 拖放事件
拖放常用事件说明见表3.3。
表3.3 拖放常用事件说明

拖放事件的参数e为一个事件对象,拖放事件触发的时间顺序以及详细讲解如图3.5所示。

图3.5 拖放事件流程图
4. 拖放方法
拖放常用方法说明见表3.4。
表3.4 拖放常用方法说明

3.2.2 容器内拖放
【本节详细代码参见随书源码:\源码\easyui\example\c3\ innerDraggable.html】
通过上一节的学习,我们已经可以创建一个简单的拖放组件,并且我们通过鼠标可以将其拖放至页面的任意位置,本节将介绍如何将拖放组件的拖放区域限制在指定的容器中。实现该功能首先需要确定指定容器的边界,当将元素拖动到容器边界外时,需要重新设置元素的位置。部分代码如下:
01 <style> 02 #border{ 03 border:1px solid; 04 width:500px; 05 height:300px; 06 } 07 </style> 08 <body> 09 <div id="border"> 10 <div id="dd" style="width:60px;height:16px"> 11 <div id="title" style="background:#ccc;width:60px;height:16px">拖放元素 12 </div> 13 </div> 14 </div> 15 </body> 16 <script> 17 $(function(){ 18 $('#dd').draggable({ 19 proxy: function(source){ 20 var p = $('<div style="border:1px solid;"></div>'); 21 p.html($(source).html()).appendTo('body'); 22 return p; 23 }, 24 handle:'#title', 25 onDrag:function(e){ 26 var d = e.data;//获取事件对象的data属性 27 var c = $(d.target);//获取拖动元素的jquery对象 28 var p = $(d.parent);//获取拖动元素的父元素的jquery对象 29 //获取父元素的边界 30 var p_left = p.offset().left; 31 var p_top = p.offset().top; 32 var p_right = p.width()+p.offset().left; 33 var p_bottom = p.height()+p.offset().top; 34 //拖动元素的位置 35 var left = d.left; 36 var top = d.top; 37 //调整元素位置 38 if (left < p_left){ 39 left = p_left 40 } 41 if (top < p_top){ 42 top = p_top 43 } 44 if (left + c.outerWidth() > p_right){ 45 left = p_right - c.outerWidth(); 46 } 47 if (top + c.outerHeight() > p_bottom){ 48 top = p_bottom - c.outerHeight(); 49 } 50 d.left = left; 51 d.top = top; 52 } 53 }); 54 }); 55 </script>
此时元素只能在其父元素容器范围内拖动,最终运行结果如图3.6所示。

图3.6 指定容器内拖放
3.2.3 快速拖放
快速拖放也称为snap拖放,之前的章节介绍的拖放可以随着用户的鼠标实时移动,但是在一些列表以及网格中,我们更希望元素可以在每一行或每一格之间移动,而不是随着鼠标实时移动,也就是说只有当鼠标移动超过指定的距离时才会产生拖动行为。快速拖动的使用非常简单,例如设计一个在20×20的网格中快速拖放的元素,部分代码如下。
01 $('#dd').draggable({ 02 proxy: function(source){ 03 var p = $('<div style="border:1px solid;"></div>'); 04 p.html($(source).html()).appendTo('body'); 05 return p; 06 }, 07 onDrag:function(e){ 08 var d = e.data; 09 d.left = convert (d.left); 10 d.top = convert (d.top); 11 function convert (v){ 12 var r = parseInt(v/20)*20;//当前位置转换为20的倍数 13 /*当前位置在20倍数的基础上移动距离是否超过10px 14 如果超过的话就直接移动20px,否则保持当前位置*/ 15 if (Math.abs(v % 20) > 10){ 16 r += v > 0 ? 20 : -20; 17 } 18 return r; 19 } 20 } 21 });