The TableDnD jQuery plugin allows the user to reorder rows within a table, for example if they represent an ordered list (tasks by priority for example). Individual rows can be marked as non-draggable and/or non-droppable (so other rows can’t be dropped onto them). Rows can have as many cells as necessary and the cells can contain form elements.
This is a great plugin at all, but needs some attention in case of usability. The default behavior of the plugin is passing over the drag-n-drop “ghosting” effect. (You can see an example here: http://www.gimiti.com/kltan/demo/jTree/)
It is difficult to make the ghosting work with this plugin but I found a very simple solution to do it. I used a small amount of CSS a Javascript code to reach a better usability behavior when a user drag-n-drop a table row.
The main concept was to mimic the ghosting effect in my project.
I used the following CSS lines.
/* This declarations makes a draghandle icon (a small crosshair) visible in the first cell of a table row */
td.dragHandle {padding-left:17px;}
td.showDragHandle {padding-left:17px; background:url(arrow_all_thin.png) no-repeat center center; cursor: move;}
/* The followings will format the entire table row when a user is dragging it */
tr.myDragClass td {background-color: #fff; padding-left:2px;} /* change the background color all of the table cells in the row to white */
tr.myDragClass td a {color: #aaa;} /* change the text color to grey, or just lighter - note: I'm using links in the TDs */
tr.myDragClass td img, tr.myDragClass td .taskDelete, tr.myDragClass td.napok div {display:none;} /* Do not display any of the images and other informations in the cells. Just show the most important information for dragging and dropping. Other information, icons, etc may confuse the user. */
tr.myDragClass td span, tr.myDragClass td span span {padding:0;} /* Pull the information closer to the drag icon */
After that formatting I played with the plugin itself. I set up it on the following way.
var oldSibling;
$("#todoList").tableDnD({
onDragClass: "myDragClass",
onDragStart: function(table, cell) {
// Saving the row under the dragged one
oldSibling=$(cell).parents("tr").next();
//Set the CSS class immediately to show the "ghosting" like effect when the user clicks on the row
$(cell).parents("tr").addClass("myDragClass");
},
onDrop: function(table, row) {
var aHtml=$("a", row).html();
var f=$.getUrlVar('f');
if(confirm("\nAre you sure to move \""+aHtml+"\" task?")) {
// Here comes the AJAX call
$("#cover").show();
$("#ajaxMessage").show();
document.getElementById("cover").style.width="100%";
document.getElementById("cover").style.height=docHeight()+"px";
$("#bigCal").load("setTask.php?f="+f+"&orig="+row.title+"&"+$.tableDnD.serializeT(), function(){
$("#cover").hide();
$("#ajaxMessage").fadeOut(200);
});
}
else {
//If the user Cancel the moving we have to take back the row to the original place
$(row).insertBefore(oldSibling);
}
},
dragHandle: "dragHandle"
});
As you can see I made the drag-n-drop cancel functionality also.
TODO: Handle the oldSibling if the moved row was the last row in the table.
Do you have any thoughts or question?
Tags: javascript, jquery, tableDND, twitter, usability

great addon mate
only question where does the js code go?
in the tablednd.js file or in the actual page?
The JS goes to the actual page. (or any external JS which will handle your table and linked in the page).
The JS code is defining tableDND for a table with ID=todoList.