Using Ruby on Rails Sortable List

For an application I am developing I wanted to allow for the position of various items to be drag and drop changeable via Ajax calls. So I started looking around the internet for Ruby on Rails examples doing this as I remembered seeing examples on the internet. I found this website: script.aculo.us – web 2.0 javascript demos This article provided me with a good foundation for taking a crack at this.

So the first thing I want to show is the code in the episodes Model:
class Episode < ActiveRecord::Base
belongs_to
:season
belongs_to :episode_type
belongs_to :format
belongs_to :genre
belongs_to :group

acts_as_list :column => :number, :scope => ‘season_id = #{season_id} AND episode_type_id = #{episode_type_id}’

validates_presence_of :name, :message => ” cannot be blank”
validates_numericality_of :duration, :number, :parts, :size, :only_integer => true, :message => ” must be a number”

end

The line to focus on is that which is in green. The acts_as_list function is a neat little function that effectively gives every episode List like functionality. A list of those methods is available here:
http://rubyonrails.org/api/classes/ActiveRecord/Acts/List/InstanceMethods.html

So this automates the database functions to properly update the list, and I tell it that the column that determines the order is the :number column, I also define a strict scope so that even if a Season has movies associated with it, those movies are seperated from the episodes and of course I only want Episodes from the same season.

Now moving on to what you all are waiting for, here is some code from the Anime Manager that uses the sortable_element function. In this version I have stripped a lot of my filtering so it just print out every entry associated with a season, this array is generated in the controller per the MVC model.

<ul id=“episodes”>

<li id=“item_”>#


<%= sortable_element ‘episodes’,
:update => ‘episodes’,
:url => { :controller => “admin”, :action => “order” }
%>

Notice the areas I have colored red, note how they match. This is required, the first parameter of sortable_element is the id of the list we are making sortable. In the next section Ill show you how to have more then one sortable list on a page. The next thing to look at it is the value of the :update parameter in the sortable_element function. As is appropriate in UI development it is often nessecary to define the area to put a message to determine whether the operation was successful. This can be any element on the HTML page, in this case I have it pointing back to the same block that its monitoring. The reason for this is that in my code, I update the list as a whole to reflect the new order of the that list.

We could modify the call to sortable_element function like below to show an effect on once the operation has been completed. You will recognize this from the code above:
<%= sortable_element ‘episodes’,
:update => ‘episodes’,
:complete => visual_effect( :highlight, “episodes” ),
:url => { :controller => “admin”, :action => “order” }
%>

Here upon completion we add a visual_effect that highlights the designated block of HTML on the page. Once again I have it pointing at the episodes list, but it could be any element you want with an id.

Now lets say in addition to a OnComplete effect you also want to give the user some means of knowing that the operation is preceeding. Well as with all Ajax effect in Rails you can use the :loading parameter to provide some visual effect to show activity. I tend to prefer the user of a spinner control, so we’ll modify the code a little.

<ul id=“episodes”>

<li id=“item_”>
#

<span id=“progress” style=“display: none;”>
<%= image_tag “spinner-blue.gif” %> Updating List – Please Wait


<%= sortable_element ‘episodes’,
:update => ‘episodes’,
:loading => “Element.show( ‘progress’ )”,
:complete => visual_effect( :highlight, “episodes” ),
:url => { :controller => “admin”, :action => “order” }
%>

So what this will do is when you move a list element it will make a call to the server to perform the indicated action. And at the same time Client Side Javascript will set the display of the ‘progress’ div tag to “”, effectively showing it. Then once the Ajax call is complete the desired HTML block will be highlighted to notify the user the server has completed its task. However, their is a problem here.

We only want to show the Progress DIV to the user when an operation is occuring. Otherwise we would be telling the to ‘Please Wait’ all the time after one list move, not good UI design. So how can we have two effects on completion. Well its really quite easy, we use a hash. Below is the code, that also hides the progress DIV once the operation completes, note the syntax:

<%= sortable_element ‘episodes’,
:update => ‘episodes’,
:loading => “Element.show( ‘progress’ )”,
:complete => { visual_effect( :highlight, “episodes” ),
“Element.hide( ‘progress’ )” },
:url => { :controller => “admin”, :action => “order” }
%>

Its that easy!!! And just by looking at that you can understand how to make multiple JS calls for each Ajax event. But I caution you not to go overboard as a website that shows 80 Please Wait messages is not a website with a good UI.

Thats really all there is to it, there are more options for sortable_element so I recommend reading up on exactly what the function can offer you and your web application. I hope this tutorial was helpful.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s