在不同的浏览器上默认的拖拽能解决的问题相当少,所以有很多的框架都能实现这么个功能.使用拖拽行为能很好的改善用户体验,尤其是在购物的时候能让用户感到很新奇和体面.Script.aculo.us使用了三个类实现拖拽和排序,它们是Draggable,Droppable,Sortable.要实现一个完整的拖拽行为,需要Draggable,和Droppable的配合使用,由于这连个类的方法比较多,我只选取比较实用的几个方法进行介绍.还是老规矩,先看看Demo:http://www1.qcxy.hb.cn/qphy/Script_Aculo_Us/DragDrop.html
Draggable
new Draggable("DraggableId"[,options])
主要选项
- snap:推拽的最小单位,默认为false,可以是数组或者函数,将这个属性设置为[50,50],意味着最小的位移单位是50px,50px,如果设置为一个函数,这个函数的参数为(x,y),这个x,y指示当前的绝对坐标,函数应该返回二维数组,上面的例子中的Drag(UnAcceptable)推拽到页面的左上角是就会"吸附"上去,就是因为函数的作用,详细见源码
- revert:推拽完毕之后是否回到原来的位置,默认为false,也可以是一个函数,这个函数必须返回true/false
- handle:"提手",移动整个块的时候通常不需要在整个块的区域都可以拖拽,比如移动一个栏目,通常只需要拖拽标题(比如Google的个性化主页),将该属性设置为标题的Id
- ghosting:推拽的过程中是否显示"影子",默认为false
- constraint:限制能拖动的方向,默认的两个方向都可以,可以设置为"vertical","horizontal"的任意
- zindex:"影子"的z-Index属性
- scroll:拖拽出视图范围是否显示自动滚动
- scrollSensitivity/scrollSpeed:默认值分为为20/15,控制滚动的敏感度和滚动速度
- delay:拖拽前的延时,开始拖拽后经过这个时间才"回过神来"
这里需要说明的是并非所有的标签都支持该行为,详细的情况请参阅官方文档
API
- onStart:开始拖拽调用该函数,接受两个参数(obj,oEvent)前者是$(DraggableId),后者是当前事件的event对象
- onDrag:在拖拽过程中反复的调用该函数,同样接受两个参数(obj,oEvent)
- change:在onDrag后调用,也会反复调用
- onEnd:拖拽行为结束调用,即鼠标弹起时激发
- destroy():该方法销毁元素的拖拽行为
Droppables
Droppables(注意是复数形式)是一个抽象类,不能被实例化,只有一些静态方法,常用的方法有add和move,分别增加可放置元素,和去除可放置元素
add方法:Dropables.add("ContainerId"[,options]),常用的选项
- accept: 数组或者字符串,表示该容器接受的元素的className的集合,默认的任何元素都接收
- hoverclass:当符合接受要求的元素拖至容器上时,其className
- onDrop():被拖拽的符合要求的元素在这里放置时调用该函数,接受三个参数(draggable,droppable,oEvent),draggable是被拖拽元素,droppable是被放置元素,oEvent当前事件对象
remove("ContainerId"),该方法去除容器的放置行为
(上面例子的源代码)
Sortable
Sortable是一组可以通过拖拽交换位置的元素,可以先看看实例(http://www1.qcxy.hb.cn/qphy/Script_Aculo_Us/Sortables.html),同样不能被实例化,常用方法create(),serialize(),destroy().下面是create("ContainerId"[,options])的常用选项
- ghosting:拖动时是否显示"影子",默认为false
- constraint:允许的拖动方向,默认为两个方向都可以,值为"horizontal","vertical"中的任一
- tag:能被拖动元素的标签,默认为"li"
- hoverclass:拖动经过可以放置的位置是,可放置的元素的className
- dropOnEmpty:默认为false,是否在空的元素上放置
- handle/delayscroll/scrollSensitivity/scrollSpeed::同Draggable
- containment:数组,存放所有的放置元素的ID,参见实例的最后一个例子
- onUpdate():该方法接受参数$("ContainerId"),在拖动到可放置位置是调用该方法
- onChange():结束拖拽行为时调用该方法,接受参数element,表示被拖拽的元素
serialize(sortable)方法:该方法返回当前容器内元素的次序,但是要求子元素的id必须以"item_"开头,且返回格式有讲究,看下面的例子
<div id="horizontalSortable" class="item" style="margin-top:20px; height:40px;">
<div id="item_5">IE</div>
<div id="item_6">FireFox</div>
<div id="item_7">Safari</div>
<div id="item_8">Opera</div>
</div>
Sortable.create("horizontalSortable",
{
ghosting:true,
tag:'div',
constraint:'horizontal',
hoverclass:'hoverClass2'
});
Sortable.serialize('horizontalSortable')
//-->horizontalSortable[]=5&horizontalSortable[]=6&horizontalSortable[]=7&horizontalSortable[]=8
最后看一个例子,前面提到的containment选项在某些情况下很有用,比如要实现两个容器里的元素可以互相交换子元素,即从一个容器拖至令一个容器中.来看下面的例子
Sortable.create('sortUlLeft',{containment:['sortUlLeft','sortUlRight'], dropOnEmpty:true,ghosting:true,constraint:false,hoverclass:'hoverClass'});
Sortable.create('sortUlRight',{containment:['sortUlLeft','sortUlRight'], dropOnEmpty:true,ghosting:true,constraint:false,hoverclass:'hoverClass'});
</script>
上面的例子可以实现sortUlLeft,和sortUlRight的子元素互相交换