Thomas Fuchs
Hi, I'm Thomas Fuchs. I'm the author of Zepto.js, of script.aculo.us, and I'm a Ruby on Rails core alumnus. With Amy Hoy I'm building cheerful software, like Freckle Time Tracking and Every Time Zone and write books like Retinafy.me.
   Want me to speak at your conference? Contact me!

AJAX-enabled shopping cart, the movie

July 2nd, 2005

With the new drag-and-drop helpers coming with Ruby on Rails 0.13, you’ll be able to silly easily do stuff like this:

You know the drill, watch the video!

The above demo amounts to about 25 lines of code, including database acccess, session-based cart storage, add/remove items handling and the view rendering code (static HTML and CSS not counted).

It relies on the brand new draggable_element and drop_receiving_element helpers, that internally use the script.aculo.us libraries.

The code for making the product images draggable look like this:


<% for product in @products %>
  <%= image_tag "/images/products/product#{product.id}",
        :id => "product_#{product.id}",
        :alt => product.title,
        :class => "products"  %>
  <%= draggable_element "product_#{product.id}", :revert => true %>
<% end %>

And the cart drop handling code amounts to two helper calls:


<%= drop_receiving_element "cart",
      :update => "items", :url => { :action => "add" },
      :accept => "products", :hoverclass => "cart-active",
      :loading => "Element.show('indicator')",
      :complete => "Element.hide('indicator')" %>
<%= drop_receiving_element "wastebin",
      :update => "items", :url => { :action => "remove" },
      :accept => "cart-items", :hoverclass => "wastebin-active",
      :before => "Element.hide(element)",
      :loading => "Element.show('indicator')",
      :complete => "Element.hide('indicator')" %>

A partial serves to list the items in the cart:


<% session[:cart].each do |product,quantity| %>
<div>
  <% quantity.times do |i| %>
    <%= image_tag "/images/products/product#{product}",
          :class => "cart-items",
          :id => "item_#{product}_#{i}" %>
    <%= draggable_element "item_#{product}_#{i}",
          :revert => true %>
  <% end %>
  <span class="title">
  <%= Product.find(product).title + " (#{quantity})" %>
  </span>
</div><% end %>

Hope you put this stuff to good use!