Dynamic Web Development with Seaside

20.5Drag and Drop

The script.aculo.us library comes with sophisticated support for drag and drop. You can define DOM elements to be draggable and (other) DOM elements to accept drags. script.aculo.us provides a something called sortables which are very easy to use. They enable you to specify XHTML elements whose children can be sorted. As seen in the figure below, we are going to use sortables to enable end-users to reorder their todo items.

Reorder the items in the todo list

To implement sortable todo items we need to change two parts of the application. First we need to assign a passenger to every list-item. Think of every item in our todo list being represented by an XHTML list-item and that we have to tell Seaside how to make that mapping so that it can automatically track the order of the items:

ToDoListView>>renderItem: anItem on: html
html listItem
passenger: anItem; "<-- added"
class: 'done' if: anItem isDone;
class: 'overdue' if: anItem isOverdue;
with: [
html checkbox
onChange: (html scriptaculous updater
id: listId;
triggerForm: (html scriptaculous element up: 'form');
callback: [ :ajaxHtml | self renderItemsOn: ajaxHtml ]);
value: anItem done;
callback: [ :value | anItem done: value ].
html text: anItem title ]

In our example this is the unordered list, that should be made sortable. We attach the sortable script to the list and assign an SUSortable>>onUpdate: handler that uses an AJAX request to serialize the changed order of list-items and triggers the associated Seaside callback.

ToDoListView>>renderContentOn: html
self renderHeadingOn: html.
html form: [
html unorderedList
id: (listId := html nextId);
script: (html scriptaculous sortable "<-- added"
onUpdate: (html scriptaculous request
triggerSortable: listId
callback: [ :items | self model items: items ]));
with: [ self renderItemsOn: html ].
html submitButton
text: 'Save'.
html submitButton
callback: [ self add ];
text: 'Add' ].
html render: editor

There are a number of other options available on the sortable.

  • SUSortable>>constraint: — Set it to #horizontal or #vertical to constrain dragging to be in the horizontal or vertical direction only.
  • SUSortable>>ghosting — If set to true, the dragged element will appear faded and a clone will stay at the old place, instead of directly dragging the original element.
  • SUSortable>>handle: — Restrict the selection of child elements to those with the given CSS class.
  • SUSortable>>tag: — Sets the kind of tag (of the child elements of the container) that will be made sortable. The default is li (as it is in our example), you have to provide the XHTML tag if you use something other than an ordered or unordered list.

For more advanced uses of drag and drop have a look at the examples that come bundled with Seaside. SUSortableTest demonstrates a single sortable list. SUSortableDoubleTest demonstrates two sortable lists side by side, where you can reorder the individual items as well as move items from one side to the other. SUSortableDoubleTest demonstrates a small shop, where you drag items into a cart, and from to cart to a trash bin. This example also shows how to combine drag and drop operations with graphical effects to give users feedback about their actions.

Note that drag and drop operations are not yet that common in the context of web applications. End users might not discover them unless you give them an explicit indication that they can drag and drop parts of your user-interface, for instance you can try adding the following to your style method:

li { cursor: move; }

Copyright © 19 March 2024 Stéphane Ducasse, Lukas Renggli, C. David Shaffer, Rick Zaccone
This book is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 license.

This book is published using Seaside, Magritte and the Pier book publishing engine.