xml 代码
- Drag and Drop and Sortable Elements
- 两种不同的drag-and-drop行为模式:在同一列中移动、在两列之间移动。两种不同的drag-and-drop行为模式:在同一列中移动、在两列之间移动。 无论是那一种,你必须能够指明三种型态的actors :无论是那一种,你必须能够指明三种型态的actors :
- 原本的容器。原本的容器。
- 目的地容器。目的地容器。 (当是在同一个容器中移动时,两个是相同的) (当是在同一个容器中移动时,两个是相同的)
- 能被移动的物件。能被移动的物件。
- 另外,你需要指明行为模式:另外,你需要指明行为模式:
- 当物件被拉时,要做什麽?当物件被拉时,要做什么?
- 当物件被放下时,要做什麽?当物件被放下时,要做什么?
- 当移动完成时,要传送什麽讯息给server ?当移动完成时,要传送什么讯息给server ?
- 我们利用一个待办事项的范例来说明在两个container之间的移动。我们利用一个待办事项的范例来说明在两个container之间的移动。
- 首先是view的部份:首先是view的部份:
- drag_demo.rhtml
- <h2>待办事项h2> <h2>待办事项h2>
- <div id='pending_todos'> <div id='pending_todos'>
- <%= render :partial=>'pending_todos' %> <%= render :partial=>'pending_todos' %>
- div>
- <h2>已完成事项h2> <h2>已完成事项h2>
- <div id='completed_todos'> <div id='completed_todos'>
- <%= render :partial=>'completed_todos' %> <%= render :partial=>'completed_todos' %>
- div>
- 在每一个<div>中我们都有指定id这个属性,这样我们才可以将行为与目标繫结在一起。在每一个<div>中我们都有指定id这个属性,这样我们才可以将行为与目标系结在一起。 而在<div>中都是一个partial 。而在<div>中都是一个partial 。 这些partial中的内容都是<ul>与<ul>的id 。这些partial中的内容都是<ul>与<ul>的id 。
- _p ending _ todos.rhtml
- <ul id='pending_todo_list'> <ul id='pending_todo_list'>
- <% @pending_todos.each do |item| %> <% @pending_todos.each do |item| %>
- <% domid = 'todo_#{item.id}' %> <% domid = 'todo_#{item.id}' %>
- <li class='pending_todo' id='<%=domid%>'><%= item.name %> li> <li class='pending_todo' id='<%=domid%>'><%= item.name %> li>
- <%= draggable_element(domid, :ghosting=>true, :revert=>true) %> <%= draggable_element(domid, :ghosting=>true, :revert=>true) %>
- <% end %> <% end %>
- ul>
- 在上面的partial中建立了一个<ul>与数个<li> 。在上面的partial中建立了一个<ul>与数个<li> 。 每一个<li>都有一个独立的id ,与相同的class 。每一个<li>都有一个独立的id ,与相同的class 。 而每一个<li>也都有一个drag-and-drop helper : draggable_element 。而每一个<li>也都有一个drag-and-drop helper : draggable_element 。 这个helper需要这个可被拖曳的物件的id ,以及几个选项:这个helper需要这个可被拖曳的物件的id ,以及几个选项:
- :ghosting => true/false #当true ,表示物件在被拖曳时,呈现50%的不透明, # false表示100%的不透明。 :ghosting => true/false #当true ,表示物件在被拖曳时,呈现50%的不透明, # false表示100%的不透明。
- :revert => true/false #当true ,表示物件被移动后,会先移回原位,然后再消失。 :revert => true/false #当true ,表示物件被移动后,会先移回原位,然后再消失。
- # false ,表示物件会直接消失。 # false ,表示物件会直接消失。
- 我们会到主页,我们要标示两个容器,让物件可以被放置(drop) 。我们会到主页,我们要标示两个容器,让物件可以被放置(drop) 。 我们将使用drop_receiving_element helper 。我们将使用drop_receiving_element helper 。
- drag_demo.rhtml
- <%=drop_receiving_element('pending_todos'
- :accept => 'completed_todo' :accept => 'completed_todo'
- :complete => “$('spinner').hide();” :complete => “$('spinner').hide();”
- :before => “$('spinner').show();” :before => “$('spinner').show();”
- :hoverclass => “hover', :hoverclass => “hover',
- :with => “'todotodo=' + encodeURIComponent(element.id.split('_').last())”, :with => “'todo=' + encodeURIComponent(element.id.split('_').last())”,
- :url => {:action=>:todo_pending, :id=>@user})%> :url => {:action=>:todo_pending, :id=>@user})%>
- <%=drop_receiving_element('completed_todos'
- :accept => 'pending_todo' :accept => 'pending_todo'
- :complete => “$('spinner').hide();” :complete => “$('spinner').hide();”
- :before => “$('spinner').show();” :before => “$('spinner').show();”
- :hoverclass => “hover', :hoverclass => “hover',
- :with => “'todotodo=' + encodeURIComponent(element.id.split('_').last())”, :with => “'todo=' + encodeURIComponent(element.id.split('_').last())”,
- :url => {:action=>:todo_completed, :id=>@user})%> :url => {:action=>:todo_completed, :id=>@user})%>
- 这个helper定义一个目标DOM element来容纳物件,以及定义在d&d的event行为模式。这个helper定义一个目标DOM element来容纳物件,以及定义在d&d的event行为模式。 除了定义接受方的id外,还有下列的选项:除了定义接受方的id外,还有下列的选项:
- :accept=> string #可以被放入的物件的CSS class名称。 :accept=> string #可以被放入的物件的CSS class名称。
- :before=>snippet #在与server端沟通前,要执行的JS 。 :before=>snippet #在与server端沟通前,要执行的JS 。
- :complete=>snippet #在与server端沟通完成后,要执行的JS 。 :complete=>snippet #在与server端沟通完成后,要执行的JS 。
- :hoverclass=>string #当滑鼠到一个可被移动的物件上时(hover ),外观的CSS class定义。 :hoverclass=>string #当滑鼠到一个可被移动的物件上时(hover ),外观的CSS class定义。
- :with=>snippet #建立要传送给server的parameter的JS 。 :with=>snippet #建立要传送给server的parameter的JS 。
- :url=>url
- :update=>string #在完成XHR call后,要修改的DOM element 。 :update=>string #在完成XHR call后,要修改的DOM element 。
- 在我们的例子中,两个container中的物件可以互相移动,而Drag-and-Drop的目的就是让被容纳的物件可以可以重新分类。在我们的例子中,两个container中的物件可以互相移动,而Drag-and-Drop的目的就是让被容纳的物件可以可以重新分类。 所以我们希望XHR request是在物件放置到另一个container的时候才触发,而不是在原本的container中也会触发。所以我们希望XHR request是在物件放置到另一个container的时候才触发,而不是在原本的container中也会触发。 在draggable_element helper中我们指明revert属性,如果物件被移到其他不是可接受的container时,他会回到原位,而不会触发任何的XHR 。在draggable_element helper中我们指明revert属性,如果物件被移到其他不是可接受的container时,他会回到原位,而不会触发任何的XHR 。
- 我们利用draggable item的DOM id ,来撷取这个物件的database id 。我们利用draggable item的DOM id ,来撷取这个物件的database id 。 这个with属性拥有一段JS code ,我们会给这段JS code一个DOM element ,就是我们拖曳的那个物件,并统一给这个物件一个变数名称为element 。这个with属性拥有一段JS code ,我们会给这段JS code一个DOM element ,就是我们拖曳的那个物件,并统一给这个物件一个变数名称为element 。 在我们的例子中,可拖曳的物件我们定义他的DOM id是todo_database id ,所以当我们要传讯息给server时,我们就去掉todo_ ,只传database id 。在我们的例子中,可拖曳的物件我们定义他的DOM id是todo_database id ,所以当我们要传讯息给server时,我们就去掉todo_ ,只传database id 。
- 在主页中,我们也定义了一些CSS ,来定义container与被拖曳物件的外型。在主页中,我们也定义了一些CSS ,来定义container与被拖曳物件的外型。
- drag_demo.rhtml
- <style>
- .hover { .hover {
- background-color: #888888; background-color: #888888;
- }
- #pending_todos ul, li, #completed_todos ul li { #pending_todos ul, li, #completed_todos ul li {
- list-style: none; list-style: none;
- cursor: -moz-grab; cursor: -moz-grab;
- }
- #pending_todos, #completed_todos{ #pending_todos, #completed_todos{
- border: 1px solid gray; border: 1px solid gray;
- }
- style>
- 当滑鼠在可被拖曳的物件上时,会套用hover class ,让物件被highlight 。当滑鼠在可被拖曳的物件上时,会套用hover class ,让物件被highlight 。 而第二个class是定义当滑鼠在container中的li element时(就是可被拖曳的元件啦),滑鼠指标会使用-moz-grab这个造型,就是手抓的造型。而第二个class是定义当滑鼠在container中的li element时(就是可被拖曳的元件啦),滑鼠指标会使用-moz-grab这个造型,就是手抓的造型。 最后一个class只是定义container的造型。最后一个class只是定义container的造型。
- 如果你想要建立一个可排序的列表,让你在一个container中,只是改变内部物件的排列顺序,并通知server他们的顺序。如果你想要建立一个可排序的列表,让你在一个container中,只是改变内部物件的排列顺序,并通知server他们的顺序。 要建立这样的功能,你只需要建立一个Html的list ,并且指明当顺序改变时,该如何做。要建立这样的功能,你只需要建立一个Html的list ,并且指明当顺序改变时,该如何做。 剩下的, Helper会帮你完成。剩下的, Helper会帮你完成。
- <ul id='priority_todos'> <ul id='priority_todos'>
- <% for todo in @todos %> <% for todo in @todos %>
- <li id='todo_<%= todo.id %>'> <%= todo.name %> li> <li id='todo_<%= todo.id %>'> <%= todo.name %> li>
- <% end %> <% end %>
- ul>
- <%= sortable_element 'priority_todos'', url=>{:action => 'sort_todos'} %> <%= sortable_element 'priority_todos'', url=>{:action => 'sort_todos'} %>
- 这个sortable_element Helper可以使用所有的Prototype的选项。这个sortable_element Helper可以使用所有的Prototype的选项。
- Script.aculo.us提供一个JS方法,称为Sortable.serialize 。 Script.aculo.us提供一个JS方法,称为Sortable.serialize 。 他会取得一个list ,并传回一个JSON ,其中会有一个目前内容物件的顺序的id列表,回传给server 。他会取得一个list ,并传回一个JSON ,其中会有一个目前内容物件的顺序的id列表,回传给server 。 这个id不是DOM element的id喔,他会脱去第一个underscore('_') ,然后传回后面的字串。这个id不是DOM element的id喔,他会脱去第一个underscore('_') ,然后传回后面的字串。 在我们的例子中,就会传回database id 。在我们的例子中,就会传回database id 。 可是这样会有一个问题,如果我们的DOM id是priority_todo_id时,他就会回传todo_id ,如果要解决这个问题,你可以利用:format这个选项,自己撰写regular expression 。可是这样会有一个问题,如果我们的DOM id是priority_todo_id时,他就会回传todo_id ,如果要解决这个问题,你可以利用:format这个选项,自己撰写regular expression 。 此外,你还有一些选项可以选择:此外,你还有一些选项可以选择:
- :constraint => value #你可以选择拖曳的方向是水平(:horizontal)或垂直(:vertical) 。 :constraint => value #你可以选择拖曳的方向是水平(:horizontal)或垂直(:vertical) 。
- :overlap=>value #计算可拖曳物件在水平或垂直方向的重叠。 :overlap=>value #计算可拖曳物件在水平或垂直方向的重迭。
- :tag=> string #在container中的什麽element可以被排序(预设是li) 。 :tag=> string #在container中的什么element可以被排序(预设是li) 。
- :containment=>target #将每个或一组element当作container ,预设是原来的container 。 :containment=>target #将每个或一组element当作container ,预设是原来的container 。
- :only=>string #一个或一组CSS class名称,过滤可拖曳物件。 :only=>string #一个或一组CSS class名称,过滤可拖曳物件。
- :scroll=>boolean #当可拖曳的物件数量多时,在拖曳物件时,要不要出现scroll bar 。 :scroll=>boolean #当可拖曳的物件数量多时,在拖曳物件时,要不要出现scroll bar 。
- :tree=>boolean #是否要使用树状列表,这表示你可以建立多层次的列表,然后在不同层之间拖曳。 :tree=>boolean #是否要使用树状列表,这表示你可以建立多层次的列表,然后在不同层之间拖曳。