4.2. Drag and Drop-阿里云开发者社区

开发者社区> 余二五> 正文

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 helperruby表达式作为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)还是通过Railshelper(drop_receiving_elementdrop_receiving_element_js)创建的droppable的大部分选项我们在前面一节都了解了。然而当我们用helper创建droppable时,还有很多可用的附加选项。也就是说,所有的link_to_remote选项,例如updateurl(第三章讲述过的)也是可用的,这些选项被用来创建一个onDrop调用的function来执行droppableAjax调用:
<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中,以控制只有当draggableCSS类型在其中时才被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>标签,liul(无序的项目)或者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参数设定为truescript.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的来用,但是item12_person3就不好了:
<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,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
4072 0
怎么设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程
6933 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4502 0
windows server 2008阿里云ECS服务器安全设置
最近我们Sinesafe安全公司在为客户使用阿里云ecs服务器做安全的过程中,发现服务器基础安全性都没有做。为了为站长们提供更加有效的安全基础解决方案,我们Sinesafe将对阿里云服务器win2008 系统进行基础安全部署实战过程! 比较重要的几部分 1.
5465 0
阿里云服务器远程登录用户名和密码的查询方法
阿里云服务器远程连接登录用户名和密码在哪查看?阿里云服务器默认密码是什么?云服务器系统不同默认用户名不同
444 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
16849 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
1132 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
3229 0
+关注
12906
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载