Drag and Drop table rows with AJAX, Scriptaculous and Prototype
* UPDATE: This’ll only work in Firefox (at time of writing. Other browsers may catch up)
Tables are like sooo last century, I know. Sometimes, though, you have data that is genuinely tabular and that you want the user to be able to reorder. I had this most recently with a tabular todo list that I was writing where I wanted the user to be able to priority order the actions by drag and drop.
Below, you’ll see four tables. You can drag items back and forth between tables 1 and 2, and between tables 3 and 4, but not 1 and 3 or 2 and 4 or 1 and 4 or 2 and 3. I’ve enabled the ‘ghosting’ effect on tables 1 and 2, but not on tables 3 and 4 - ghosting appears to screw up the layout a little once you’ve done some dragging.
|
Table 1
|
Table 3
|
||||||||||||||||
|
Table 2
|
Table 4
|
Neat. The question is how, right? The answer is Sciptaculous, which is a handy Javascript library for Ajax and special effects that takes most of the misery and the having-to-know-any-javascript out of writing dynamic web pages.
<!-- Javascript Includes -->
<script type="text/javascript" src="/script/prototype.js"></script>
<script type="text/javascript" src="/script/scriptaculous.js"></script>
<!-- Standard HTML -->
<table>
<tr><td>
<p>Table 1</p>
<table padding="10" border="1" bgcolor="#aaaaff">
<tr><th>Col1</th><th>Col2</th></tr>
<tbody id="table1">
<tr id="row_1"><td>Value1Table1</td><td>Value2Table1</td></tr>
<tr id="row_2"><td>Value3Table1</td><td>Value4Table1</td></tr>
</tbody>
</table>
</td>
<td>
<p>Table 3</p>
<table border="1" bgcolor="#aaaaff">
<tr><th>Col1</th><th>Col2</th></tr>
<tbody id="table3">
<tr id="row_1"><td>Value1Table3</td><td>Value2Table3</td></tr>
<tr id="row_2"><td>Value3Table3</td><td>Value4Table3</td></tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<p>Table 2</p>
<table border="1" bgcolor="#aaaaff">
<tr><th>Col1</th><th>Col2</th></tr>
<tbody id="table2">
<tr id="row_1"><td>Value1Table2</td><td>Value2Table2</td></tr>
<tr id="row_2"><td>Value3Table2</td><td>Value4Table2</td></tr>
<tr id="row_3"><td>Value5Table2</td><td>Value6Table2</td></tr>
</tbody>
</table>
</td><td>
<p>Table 4</p>
<table border="1" bgcolor="#aaaaff">
<tr><th>Col1</th><th>Col2</th></tr>
<tbody id="table4">
<tr id="row_1"><td>Value1Table4</td><td>Value2Table4</td></tr>
<tr id="row_2"><td>Value3Table4</td><td>Value4Table4</td></tr>
<tr id="row_3"><td>Value5Table4</td><td>Value6Table4</td></tr>
</tbody>
</table>
</td></tr></table>
<!-- Scriptaculous Magic -->
<script>
Sortable.create("table1", { tag:"tr", containment:["table1", "table2"], ghosting:true })
Sortable.create(”table2″, { tag:”tr”, containment:["table1", "table2"], ghosting:true })
Sortable.create(”table3″, { tag:”tr”, containment:["table3", "table4"]})
Sortable.create(”table4″, { tag:”tr”, containment:["table3", "table4"]})
</script>
(sed -e ’s/</\</g;s/>/\>/g’ is my new bff)
Simple, right? Only slight oddness is the use of the <tbody> tag, which is a kink of the Scriptaculous library. In the call to ‘Sortable.create’, we’ve passed the “id” of the <tbody> element in as the first parameter, identified <tr> tags as the things we want to be able to reorder with the ‘tag’ option, specified the Sortable elements between which rows can be dragged with the ‘containment’ option, and turned on the ghosting effect in the obvious way. Only gotchas are that the includes at the top have to be done in the order shown, and that the calls to Sortable.create have to appear after the element definitions (not only of the Sortable in question, but also of any elements identified in the ‘containment’ option).
But you’re thinking “this is worse than useless - when I refresh the page, the sorting resets”. And you’d be right. This is where Prototype comes in. A copy of Prototype is included when you download Scriptaculous, and it implements all the handy little Ajax bits. This post is getting a bit long now, so next time I’ll explain why:
new Ajax.Request('/some/action/url', {
method:'post', parameters:Sortable.serialize('table1')
})
is basically all you need to know to be able to persist the reordering.
codders says:
November 14th, 2007 at 8:49 pm
As sffubs and Maruf rightly point out, this only actual works in FireFox just at the minute. There’s a note on the Scriptaculous pages about it:
‘You can use Sortable.create on any container element that contains Block Elements, with the exception of TABLE, THEAD, TBODY and TR. This is a technical restriction with current browsers.’
I’m lucky enough not to have a copy of Internet Explorer on any of my machines. If your users insist on using a browser that doesn’t have this feature, the best you can do is replace the table rows with items in an (un)ordered list.
Drag and Drop table rows with AJAX, Scriptaculous and Prototype (Part II) : : talkingCode says:
November 16th, 2007 at 8:16 am
[...] Previous article Nov [...]
Editable table with Javascript, TableKit, AJAX and Rails : : talkingCode says:
December 10th, 2007 at 7:26 am
[...] and my tables. First drag and drop, then drag-select, and now click-to-edit values with date parsing magic. It’s like having a [...]