4.2. Drag and Drop

简介:

4.2. Drag and Drop

在桌面应用中经常强调直接操纵屏幕上的对象的能力,但是对web界面来说更多的是强调操纵复杂DOM的能力。Script.aculo.us将这二者的特点结合起来提供了简单而又强大的界面拖拽支持。这意味着web开发者可以决定使用基本的拖拽功能,而不关心技术层面的东西。使用视觉效果时,要记得拖拽功能有时候并不是解决界面问题的最佳途径。但是如果需要,script.aculo.us可以做到!
4.2.1 . Draggables
Script.aculo.us 提供了一个 Draggable 的类,用来添加 DOM 元素实现拖拽的能力。在开始之前,新建一个模板文件, draggables.rhtml,  添加下面的代码:
<div id= "dragDIV"  class= "green box">drag</div> 

<%= javascript_tag  "new Draggable('dragDIV')" %> 
当页面被加载后 ([url]http://localhost:3000/chapter4/draggables[/url]),Javascript 声明了一个 Draggable 类的实例变量,跟元素的 ID 绑定在一起。现在你可以在页面内拖拽这个元素。注意它是怎么实现在移动中的轻度透明,这里使用了前面讲过的 Opacity 效果。
 
Rails 提供了 draggable_element helper 来实现拖拽,就像 Draggable.initialize,  第一个参数是元素的 ID    第二个参数是 hash 选项,   例如:
<div id= "helperDIV"  class= "green box">helper</div> 

<%= draggable_element :helperDIV %> 
draggable_element 输出的是一个<script>元素,在<script>标签里面有new Draggable的声明,如果你只想要这个Javascript的声明而不需要<script>标签,那么你可以使用draggable_element_js来替换draggable_element.例如:
 
<div id= "clickDIV"  class= "green box"
    <%= button_to_function  "Make draggable"
         draggable_element_js(:clickDIV) %> 
</div>
为了让给用户一个更好的体验,当鼠标经过可拖拽元素的位置是,改变鼠标指针形状。可以用CSS的鼠标指针属性来轻松实现:
<div  class= "green box" style= "cursor:move">drag</div>
当用户鼠标放到这个元素上面时,指针就变成了“可移动”的图标,指示这个元素可拖拽。当然, CSS 也可以不写在 div 里面,可以放在外部的 stylesheet 里。
 
4.2.1 .1. Draggable options
Effect.* 方法中, Draggable.initialize 用一个 JavaScript 表达式作为 hash 选项来定制它们的行为, draggable_element helper ruby 表达式作为 hash 选项,最后将其翻译成 Javascript 表达式。
revert 参数如果设置为true,那么元素在拖拽之后会回到原始位置。revert的设置也可以是一个function,指明拖拽结束后调用的功能。决定拖拽是否回到某一位置。例如:
<div id= "revertDIV"  class= "green box">revert</div> 

<%= draggable_element :revertDIV, :revert =>  true %> 
---------------------------------------------------------------------
<div id= "functionRevertDIV"  class= "green box"> function revert</div> 

<%= draggable_element :functionRevertDIV,  

     :revert => " function(el){ 

         return Position.page(el)[0] > 100; }" %> 
在第二段代码中,:revert后面的function用来指定元素拖拽结束后的位置。
这里,只有当拖动元素超过100像素(从窗口左侧开始算起)时,回被恢复到原来的位置,也就是说,它被拖拽后静止的范围只有长度为100像素高度不限,在窗口内的柱形区域。
 
Ghosting 参数,如果设置为true,会在拖拽时在原位置生成一个镜像,直到拖拽结束,镜像也随之消失:
<div id= "ghostingDIV"  class= "green box">ghosting</div> 

<%= draggable_element :ghostingDIV, :ghosting =>  true %> 
 
handle 允许你为要拖拽的元素内部加一个子元素,这个子元素作为拖拽的把手。它的值是一个JavaScript表达式,这个Javascript表达式以元素的 ID或者元素的引用作为参数。例如:
<div id= "handleDIV"  class= "green box"

  <span id= "myHandle">handle</span> 

</div> 

<%= draggable_element :handleDIV, :handle =>  "'myHandle'" %> 
看到了么,这里myHandle被放在双重引号里,这是因为JavaScript表达式要将其作为字符串来执行。
 
change 选项后面跟一个function,这个function会在整个拖拽的过程中时刻被调用。Fuction的调用就像是以拖拽作为参数的:
<div id= "changeDIV"  class= "green box">change</div> 

<%= draggable_element :changeDIV, :change => " function(draggable) { 

  draggable.element.innerHTML=draggable.currentDelta(  ); 

}" %> 

这段代码实现的功能:当你拖动这个green box时,里面会根据拖拽的位置时时显示其坐标。
 
constraint, 如果设置为horizontal(水平)或者vertical(垂直),会约束元素拖动的角度。这个元素ID是作为JavaScript表达式中的参数的,所以要在DOM元素ID加上两对引号:
<div id= "constraintDIV"  class= "green box">constraint</div> 

<%= draggable_element :constraintDIV, :constraint =>  "'vertical'" %> 
snap 是让元素像是在格子化的画面上拖拽,如果snap设置为false(默认设置),那么不会有这种效果,如果将值设为一个整数n, 元素会在拖拽时跳到最近的与其间隔为n像素的一个格子里。这个值也可以被设定为一个数组形式[x,y],这样横轴和纵轴方向都会被不同的值限制住。Snap的值也可以设置为一个functionfunction会传递元素当前位置的坐标(是以其开始位置的偏移量,而不是其绝对坐标),返回snap坐标,例如:
<div id= "snapDIV_50" class= "green box">snap to 50</div>
<%= draggable_element :snapDIV_50, :snap => 50 %>
<div id= "snapDIV_50_100" class= "green box">snap to 50,100</div>
<%= draggable_element :snapDIV_50_100, :snap => '[50,100]' %>
---------------
<div id= "snapDIV_function" class= "green box">snap to function</div>
<%= draggable_element :snapDIV_function, :snap => " function(x, y) {
  new_x = (x > 100) ? 100 : ((x < 0) ? 0 : x);
  new_y = (y > 100) ? 100 : ((y < 0) ? 0 : y);
   return [ new_x, new_y ];
}" %>
最后一个示例证实了为snap选项定义一个function的功效,同时使用xy两个维度的值从0-100,结果实现了拖拽只能在一个小方框内进行。
4.2.2 . Droppables
Droppable  可以让 DOM 元素接受一个拖拽过来的目标元素并执行某些动作,例如 Ajax 调用,用 javascript 建立一个 droppable ,使用 Dropables.add:
<div id= "dropDIV" class= "pink box">drop</div>
<%= javascript_tag "Droppables.add('dropDIV', {hoverclass:'hover'})" %>
第二个参数是一个hash选项,更多细节参见Droppable options这节。Rails helper使用drop_receiving_elementdrop_receiving_element_js来生成droppable.例如:
<div id= "dropHelperDIV"  class= "pink box">drop here.</div> 

<%= drop_receiving_element :dropHelperDIV, :hoverclass => 'hover' %> 
drop_receiving_element_js helper  drop_receiving_element不是一回事,它不被夹在<script>标签中,而是直接输出javascript代码。
 
droppable 没必要接受每种拖拽元素,下面的提供的一些droppable选项可以用来决定什么时候接受draggable.
 
4.2.2 .1. Droppable options
hoverclass 是一个被加在 droppable 属性中的类的类名,当可接受的拖拽元素在 droppable 上停留时,   告诉用户 droppable 是活跃的。我们在上一节中已经看了几个例子了。
 
accept 后面是一个 CSS 的类别,可以是字符串或者是一个字符串数组。如果提供了这个选项, droppable 只会接受 CSS 类别属于 accept 后面集合中的拖拽元素。例如:
<div id= "dragGreen"  class= "green box">drag</div> 

<%= draggable_element :dragGreen, :revert =>  true %> 

  

<div id= "dragPink"  class= "pink box">drag</div> 

<%= draggable_element :dragPink, :revert =>  true %> 

  

<div id= "dropAccept"  class= "pink box">drop here (green only).</div> 

<%= drop_receiving_element :dropAccept, :hoverclass =>  "hover"

     :accept => 'green' %> 

containment限制droppable只接受ID属于containment指定的元素ID数组的拖拽元素。这个ID会作为JavaScript表达式中的参数来执行,所以DOM元素的ID要用两对引号。例如:
<div id= "one"

    <div id= "dragGreen2"  class= "green box">drag</div> 

    <%= draggable_element :dragGreen2, :revert =>  true %> 

</div> 

  

<div id= "two"

    <div id= "dragPink2"  class= "pink box">drag</div> 

    <%= draggable_element :dragPink2, :revert =>  true %> 

</div> 

  

<div id= "dropContainment"  class= "pink box">drop here.</div> 

<%= drop_receiving_element :dropContainment, :hoverclass =>  "hover"

:containment =>  "'one'" %> 

 
onHover选项是当拖拽元素被拖到droppable上时引发的一段function。这个调用有3个参数: draggable, droppableoverlap(二者的重叠的百分比度)。看一个没有参数情况下的实例:
<div id= "dropOnHover"  class= "pink box">drop</div> 

<%= drop_receiving_element :dropOnHover, :hoverclass =>  "hover"

      :onHover =>  "function(  ){ $('dropOnHover').update('hover!'); }" %> 
 
下面这个是3个参数都使用的实例:
<div id= "dropOnHover"  class= "pink box">drop</div> 

<%= drop_receiving_element :dropOnHover, :hoverclass =>  "hover",  

      :onHover => " function(draggable, droppable, overlap){  

         $('dropOnHover').update('you dragged ' + draggable.id +  

              ' over ' + droppable.id + ' by ' + overlap +  

              ' percent'); }" %> 
onDrop是当你将拖拽元素放到droppable上面放手时,droppable接受拖拽元素并发生动作。这个调用有两个参数:拖动元素和droppable元素,例如:
<div id= "dropOnDrop"  class= "pink box">drop</div> 

<%= drop_receiving_element :dropOnDrop, :hoverclass =>  "hover"

    :onDrop => " function(drag, drop){  

       alert('you dropped ' + drag.id + ' on ' + drop.id) }" %> 
4.2.2 .2. Droppables with Ajax
不管你是通过 JavaScript(Droppables.add) 还是通过 Rails helper(drop_receiving_element drop_receiving_element_js) 创建的 droppable 的大部分选项我们在前面一节都了解了。然而当我们用 helper 创建 droppable 时,还有很多可用的附加选项。也就是说,所有的 link_to_remote 选项,例如 update url (第三章讲述过的)也是可用的,这些选项被用来创建一个 onDrop 调用的 function 来执行 droppable Ajax 调用:
<div id= "drag"  class= "green box">drag</div> 

<%= draggable_element :drag, :revert =>  true %> 

  

<div id= "drop"  class= "pink box">drop</div> 

<%= drop_receiving_element :drop, :hoverclass =>  "hover"

     :update =>  "status", :url => { :action =>  "receive_drop" } %> 

  

<div id= "status"></div> 

这里:url选项,里面有个指向receive_dropaction,我们需要在chapter4_controller.rb中定义:
def receive_drop 

  render :text =>  "you dropped element id #{params[:id]}" 

end 
 
除非用:with选项来指明传递的draggable,不然drop_receiving_elementAjax调用会自动接收draggableid作为请求的id参数。
 
4.2.3 . Sortables
sortable 是建立在draggabledroppable基础之上的,当你将一个元素往下拖的时候,你可以同时给出其他元素的拖拽行为,让他们在画面上重新排列。
 
使用JavascriptSortable.create创建一个sortable
<ul id= "list"

  <li>Buy milk</li> 

  <li>Take out trash</li> 

  <li>Make first million</li> 

</ul> 

  

<%= javascript_tag  "Sortable.create('list')" %> 
当然,Rails也提供了helper来完成这个任务:sortable_elementsortable_element_js.就像产生其他拖拽效果元素相关的helper一样,第一个参数是目标DOM元素,第二个是optionshash选项,用来控制行为。其他可用的选项有:
hoverclass
      传递给 droppable, 指定的这些 CSS 类型加到 droppable 中,以控制只有当 draggable CSS 类型在其中时才被 droppable 所接受。
 
handle
      传递给 droppable,  当元素之间会发生交互作用时(例如链接或者是表单元素)这个选项是非常有用的,例如:
<ul id= "listHandle"

  <li><span  class= "handle">x</span> Buy milk</li> 

  <li><span  class= "handle">x</span> Take out trash</li> 

  <li><span  class= "handle">x</span> Make first million</li> 

</ul> 

  

<%= sortable_element :listHandle, :handle => 'handle' %> 
拖放那个x时,发生重新排列。
ghosting
也是传递给draggables.例如:
<ul id= "listGhosting"

  <li>Buy milk</li> 

  <li>Take out trash</li> 

  <li>Make first million</li> 

</ul> 

<%= sortable_element :listGhosting, :ghosting =>  true %> 

 
在原位置产生镜像,拖拽结束后消失
constraint and overlap
他们一起工作来决定sortable运作的方向:垂直(默认)vertical或水平horizontalconstraint是传递给draggable的,它决定元素的拖拽方向。overlap传递给droppable,droppable只有当draggable元素覆盖在其上50%时产生作用。例如:

<ul id="listHorizontal">
  <li style="display: inline; margin-right: 10px;">Buy milk</li>
  <li style="display: inline; margin-right: 10px;">Take out trash</li>
  <li style="display: inline; margin-right: 10px;">Make first million</li>
</ul>
  
<%= sortable_element :listHorizontal,
     :constraint => 'horizontal',
     :overlap    => 'horizontal' %>
 
tag
设定 sortable 元素的标签类型,默认情况下是 <li> 标签, li ul( 无序的项目 ) 或者 ol (有序的项目)中的项目。如果你要设定 sortable 元素是其他的例如图像或者是 div 标签时,要用 tag 选项标识出来:
<div id= "listTag"

  <div>Buy milk</div> 

  <div>Take out trash</div> 

  <span>Make first million</span> 

</div> 

  

<%= sortable_element :listTag, :tag => 'div' %> 
这里有个<span>标签,它不属于sortable的元素。不参与拖拽
only
限制sortable元素的CSS 类型为给定的CSS类型或类型数组。例如:
<ul id= "listOnly"

  <li  class= "sortable">Buy milk</li> 

  <li  class= "sortable">Take out trash</li> 

  <li>Make first million</li> 

</ul> 

  

<%= sortable_element :listOnly, :only => 'sortable' %> 

 
containment
用来使元素的拖拽在多个容器中进行。一个容器只会接受那些在 containment 中指定的父类元素,这个指定元素的方法可以使用元素的 ID 或者是 ID 数组。
<ul id= "list1"

  <li>Buy milk</li> 

  <li>Take out trash</li> 

</ul> 

  

<ul id= "list2"

  <li>Make first million</li> 

</ul> 

  

<%= sortable_element :list1, :containment => ['list1', 'list2'] %> 

<%= sortable_element :list2, :containment => ['list1', 'list2'] %> 

 
dropOnEmpty
当你有2sortable容器,你希望元素可以在这两个容器之间拖动时可以使用dropOnEmpty,默认情况下,是不允许将另一个容器中的元素拖拽到一个空的容器中的。但是当dropOnEmpty设定为true时,情况就改变了。例如:
<ul id= "listFull">
    <li id= "thing_1">Buy milk</li>
    <li id= "thing_2">Take out trash</li>
    <li id= "thing_3">Make first million</li>
</ul>
  
<ul id= "listEmpty">
</ul>
  
<%= sortable_element :listFull,
     :containment => ['listFull', 'listEmpty'],
     :dropOnEmpty => true %>
<%= sortable_element :listEmpty,
     :containment => ['listFull', 'listEmpty'],
     :dropOnEmpty => true %>
scroll
可以让 sortables 被放在一个有滚动游标的区域里,拖拽元素会自动调整游标。完了完成这个有滚动游标容器的功能,必须设定容器的 style=”overflow: scroll” , 而且 scroll 选项应该设置为容器的 id 。这个 id 会作为 Javascript 表达式运行的参数,所以必须加两对引号。还必须通过 Position.includeScrollOffsets 参数设定为 true script.aculo.us 中的 scrolling 功能激活,例如:
<div id= "container" style= "overflow: scroll; height: 200px;"

  <ul id= "listScroll"

    <% 20.times  do |i| %> 

      <li>Buy milk</li> 

      <li>Take out trash</li> 

      <li>Make first million</li> 

    <% end %> 

  </ul> 

</div> 

  

<%= javascript_tag  "Position.includeScrollOffsets = true" %> 

<%= sortable_element :listScroll, :scroll =>  "'container'" %> 

 
 
 
onChange
当拖拽元素使得其排列顺序发生改变时就调用该参数设定的内容。这个调用以拖拽的元素作为其参数:
<ul id= "listChange"

  <li>Buy milk</li> 

  <li>Take out trash</li> 

  <li>Make first million</li> 

</ul> 

  

<%= sortable_element :listChange, 

     :onChange =>  "function(el) { alert(el.innerHTML); }" %> 

 
onUpdate
当拖拽结束 sortable 顺序发生改变时被调用,这个调用以容器作为其参数:
<ul id= "listUpdate">
  <li>Buy milk</li>
  <li>Take out trash</li>
  <li>Make first million</li>
</ul>
  
<%= sortable_element :listUpdate,
     :onUpdate => "function(el) { alert(el.innerHTML); }" %>
<%#似乎不工作%>
4.2.3 .1. Ajax-enabled sortables
对于 droppable 来说, sortable_element helper 也可以使用常见的 Ajax 选项,例如 link_to_remote 中提供的 Ajax 选项一样。默认情况下,当建立 Ajax 调用时,对于 action 的调用会以连续的 sortable 元素作为参数。在使用时, sortable 元素的 ID 应该按这样的风格来命名: Sortable.serialize:  唯一的 ID 标识应该放到后面,前面可以加上下划线。例如 item_1,person_2 _3 都可以作为好的 ID 的来用,但是 item1 2_person 3 就不好了:
<ul id= "listAjax"

  <li id= "item_1">Buy milk</li> 

  <li id= "item_2">Take out trash</li> 

  <li id= "item_3">Make first million</li> 

</ul> 

  

<%= sortable_element :listAjax, 

     :url      => { :action => 'repeat' }, 

     :complete =>  "alert(request.responseText);" %> 
这段代码意思是,当重新排序列表时引发Ajax调用repeat这个action,使用listAjax数组作为参数包含了在当前顺序下(发送重新排列后)sortable元素的所有ID,为了让这段代码能够正确运行,在controller里定义repeat action,显示调用时发送的参数情况。
def repeat 

  render :text => params.inspect 

end 

  




本文转自 fsjoy1983 51CTO博客,原文链接:http://blog.51cto.com/fsjoy/91700,如需转载请自行联系原作者
目录
相关文章
|
5月前
|
JavaScript API UED
drag / drop
"拖放"(Drag and Drop)是一种常见的计算机操作方式,指将一个对象从一处移动到另一处,通常通过鼠标或触摸屏手势来实现。这种操作方式在许多应用程序中被广泛采用,例如在文件管理器中移动文件,在图像编辑器中调整图片大小和位置等。 拖放操作的步骤一般如下:
29 6
|
5月前
|
JavaScript
Vue Drag and Drop
Vue Drag and Drop
63 0
|
10月前
|
API
drag事件
drag事件
82 0
手动调用cx-table.focus和a.focus方法的效果比较
手动调用cx-table.focus和a.focus方法的效果比较
114 0
手动调用cx-table.focus和a.focus方法的效果比较
Qt实现鼠标拖放(drag/drop)
Qt实现鼠标拖放(drag/drop)
220 0
|
关系型数据库 MySQL
truncate table 和 drop table 的一点坑
网上一搜这个关键字,得到的结果大多都是delete、truncate、drop之间的区别 但是今天我们要讲的内容,是我们在生产环境中遇到的真实案例 互联网公司一般对大表,都会采用分区表或者物理分表吧,这里主要描述的是分表的删除过程中的问题 案例一 环境MySQL5.
4038 0