The ability to drag and drop has been a staple of desktop applications for years. With the advent of Ajax, the ability to drag and drop has now found its way to web applications. In this entry I spice up the blogging application we've been building with the ability to drag comments to the trash. This is an appropriate feature to add as our own blogs here on java.net have been prone to spam attacks via the comments which require cleanup.
I'm going to continue from where the tutorial Using Ajax with Ruby on Rails [1] leaves off. However, I'll be using NetBeans 6.1 and Rails 2.0, so you may want to start with this updated version of the rubyweblog [2] project which has been updated to Rails 2.0 (the entire tutorial series is in the process of being updated).
Currently, the application does not provide the means to delete a comment. Now, I know this application is severely lacking any sort of user model or administrative interface, but my intent is to show how to do cool things with Rails, not create a replacement for roller [4], so I squeeze the features in where I can. In this case, I'm going to add a trash can icon to the page and allow users to drag comments to the trash for deletion.

Here we'll employ the draggable_element [5] helper, a Rails wrapper around the Scriptaculous Draggable [6]object, to make the comments draggable.
<% comment_id = "comment_#{comment.id}" %>
<li id=<%= comment_id %> >
<%= h comment.comment %><br>
<div style="color: #999; font-size: 8pt">
Posted on <%= comment.created_at.strftime("%B %d, %Y at %I:%M %p") %>
</div>
</li>
<%= draggable_element(comment_id, :revert=>true) %>#comments {
cursor: -moz-grab;
}
(trashfull.jpg) to the public/images directory of your rubyweblob project directory.<%= text_area 'comment', 'comment' %>
<%= image_tag "trash.jpg", :id=>'trash'%>
Here we'll use the drop_receiving_element [7] helper, a Rails wrapper around the Scriptaculous Droppables.add [8] method to give the comment a drop destination and call the action to delete the comment.
<%= drop_receiving_element('trash', # The id of the receiving element
:accept => "comment", # The CSS class of the dropped element
:with => "'comment=' + (element.id.split('_').last())", # The query string parameters
:url => {:action=>:trash_comment} # The action to call
)%>
<li class="comment" id=<%= comment_id %> >
def trash_comment
comment_id = params[:comment]
Comment.delete(comment_id)
render :update do |page|
page.replace_html "comment_#{comment_id}", ""
end
end
<% comment_id = "comment_#{comment.id}" %>
<div class="comment" id=<%= comment_id %> >
<li>
<%= h comment.comment %><br>
<div style="color: #999; font-size: 8pt">
Posted on <%= comment.created_at.strftime("%B %d, %Y at %I:%M %p") %>
</div>
</li>
</div>
<%= draggable_element(comment_id, :revert=>true) %>
(trashfull.jpg) to the public/images directory of your rubyweblob project directory.<script>
function fill_trash() {
$('trash').src = "/images/trashfull.jpg";
}
function empty_trash() {
$('trash').src = "/images/trash.jpg";
}
</script>
<%= drop_receiving_element('trash', # The id of the receiving element
:accept => "comment", # The CSS class of the dropped element
:with => "'comment=' + (element.id.split('_').last())", # The query string parameters
:url => {:action=>:trash_comment}, # The action to call
:onHover => "function() {fill_trash()}",
:complete => "empty_trash()"
)%>
<%= image_tag "trash.jpg", :id=>'trash', :onMouseOut=>"empty_trash()"%>And that should pretty much complete the drag and drop functionality. Remember to refresh the browser to pick up changes to Javascript. Also, Firebug [9] is your friend whenever you're working with Ajax and not seeing what you're expecting.
RubyWeblogDND.zip
[10]
Links:
[1] http://www.netbeans.org/kb/60/ruby/ajax.html
[2] http://weblogs.java.net/blog/bleonard/archive/2008/04/rails_drag_drop/rubyweblog.zip
[3] http://localhost:3000/posts
[4] http://rollerweblogger.org/project/
[5] http://railsapi.org/actionview-helpers-scriptaculoushelper-draggable_element
[6] http://script.aculo.us/docs/Draggable.html
[7] http://railsapi.org/actionview-helpers-scriptaculoushelper-drop_receiving_element
[8] http://script.aculo.us/docs/Droppables.add.html
[9] https://addons.mozilla.org/firefox/addon/1843
[10] http://weblogs.java.net/blog/bleonard/archive/2008/04/rails_drag_drop/RubyWeblogDND.zip