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,如需转载请自行联系原作者
目录
相关文章
|
2月前
ALTER MATERIALIZED VIEW
Use the ALTER MATERIALIZED VIEW statement to modify an existing materialized view in one or more of the following ways: To change its storage characteristics To change its refresh method, mode, or time To alter its structure so that it is a different type of materialized view To enable or disabl
13 0
|
3月前
|
JavaScript API UED
drag / drop
"拖放"(Drag and Drop)是一种常见的计算机操作方式,指将一个对象从一处移动到另一处,通常通过鼠标或触摸屏手势来实现。这种操作方式在许多应用程序中被广泛采用,例如在文件管理器中移动文件,在图像编辑器中调整图片大小和位置等。 拖放操作的步骤一般如下:
20 6
|
5月前
|
JavaScript
Vue Drag and Drop
Vue Drag and Drop
when click one item in table Select at least one column to perform the search
when click one item in table Select at least one column to perform the search
when click one item in table Select at least one column to perform the search
手动调用cx-table.focus和a.focus方法的效果比较
手动调用cx-table.focus和a.focus方法的效果比较
102 0
手动调用cx-table.focus和a.focus方法的效果比较
Qt实现鼠标拖放(drag/drop)
Qt实现鼠标拖放(drag/drop)
196 0
|
关系型数据库 MySQL
truncate table 和 drop table 的一点坑
网上一搜这个关键字,得到的结果大多都是delete、truncate、drop之间的区别 但是今天我们要讲的内容,是我们在生产环境中遇到的真实案例 互联网公司一般对大表,都会采用分区表或者物理分表吧,这里主要描述的是分表的删除过程中的问题 案例一 环境MySQL5.
3976 0