Table Drag and Drop JQuery plugin




I’ve been using JQuery for a while now and really agree with its tag line that it’s the “The Write Less, Do More, JavaScript Library”. We’ve also got this code for dragging and dropping table rows that has proved very popular, so it seemed natural to combine the two and wrap up the table drag and drop as a JQuery plugin.

Why have another plugin?

Dragging and dropping rows within a table can’t be handled by general purpose drag and drop utilities for a number of reasons, not least because you need to move the whole row, not just the cell that receives the mouse events. Re-parenting the row also requires specific code. Sadly also, effects like fadeIn and fadeOut don’t work well with table rows on all browsers, so we have to go for simpler effects.

What does it do?

This TableDnD 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.

How do I use it?

  1. Download Download jQuery (version 1.2 or above), then the TableDnD plugin (current version 0.5).
  2. Reference both scripts in your HTML page in the normal way.
  3. In true jQuery style, the typical way to initialise the tabes is in the $(document).ready function. Use a selector to select your table and then call tableDnD(). You can optionally specify a set of properties (described below).
1 One some text
2 Two some text
3 Three some text
4 Four some text
5 Five some text
6 Six some text

The HTML for the table is very straight forward (no Javascript, pure HTML):

<table id="table-1" cellspacing="0" cellpadding="2">
    <tr id="1"><td>1</td><td>One</td><td>some text</td></tr>
    <tr id="2"><td>2</td><td>Two</td><td>some text</td></tr>
    <tr id="3"><td>3</td><td>Three</td><td>some text</td></tr>
    <tr id="4"><td>4</td><td>Four</td><td>some text</td></tr>
    <tr id="5"><td>5</td><td>Five</td><td>some text</td></tr>
    <tr id="6"><td>6</td><td>Six</td><td>some text</td></tr>
</table>

To add in the “draggability” all we need to do is add a line to the $(document).ready(...) function
as follows:

<script type="text/javascript">
$(document).ready(function() {
    // Initialise the table
    $("#table-1").tableDnD();
});
</script>

In the example above we’re not setting any parameters at all so we get the default settings. There are a number
of parameters you can set in order to control the look and feel of the table and also to add custom behaviour
on drag or on drop. The parameters are specified as a map in the usual way and are described below:

onDragStyle
This is the style that is assigned to the row during drag. There are limitations to the styles that can be
associated with a row (such as you can’t assign a border—well you can, but it won’t be
displayed). (So instead consider using onDragClass.) The CSS style to apply is specified as
a map (as used in the jQuery css(...) function).
onDropStyle
This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations
to what you can do. Also this replaces the original style, so again consider using onDragClass which
is simply added and then removed on drop.
onDragClass
This class is added for the duration of the drag and then removed when the row is dropped. It is more
flexible than using onDragStyle since it can be inherited by the row cells and other content. The default
is class is tDnD_whileDrag. So to use the default, simply customise this CSS class in your
stylesheet.
onDrop
Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table
and the row that was dropped. You can work out the new order of the rows by using
table.tBodies[0].rows.
onDragStart
Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the
table and the row which the user has started to drag.
scrollAmount
This is the number of pixels to scroll if the user moves the mouse cursor to the top or bottom of the
window. The page should automatically scroll up or down as appropriate (tested in IE6, IE7, Safari, FF2,
FF3 beta)

This second table has has an onDrop function applied as well as an onDragClass. The javascript to set this up is
as follows:

$(document).ready(function() {

	// Initialise the first table (as before)
	$("#table-1").tableDnD();

	// Make a nice striped effect on the table
	$("#table-2 tr:even').addClass('alt')");

	// Initialise the second table specifying a dragClass and an onDrop function that will display an alert
	$("#table-2").tableDnD({
	    onDragClass: "myDragClass",
	    onDrop: function(table, row) {
            var rows = table.tBodies[0].rows;
            var debugStr = "Row dropped was "+row.id+". New order: ";
            for (var i=0; i<rows.length; i++) {
                debugStr += rows[i].id+" ";
            }
	        $(#debugArea).html(debugStr);
	    },
		onDragStart: function(table, row) {
			$(#debugArea).html("Started dragging row "+row.id);
		}
	});
});
 
1 One
2 Two
3 Three
4 Four
5 Five
6 Six
7 Seven
8 Eight
9 Nine
10 Ten
11 Eleven
12 Twelve
13 Thirteen
14 Fourteen

What to do afterwards?

Generally once the user has dropped a row, you need to inform the server of the new order. To do this, we’ve
added a method called serialise(). It takes no parameters but knows the current table from the
context. The method returns a string of the form tableId[]=rowId1&tableId[]=rowId2&tableId[]=rowId3
You can then use this as part of an Ajax load.

This third table demonstrates calling the serialise function inside onDrop (as shown below). It also
demonstrates the “nodrop” class on row 3 and “nodrag” class on row 5, so you can’t pick up row 5 and
you can’t drop any row on row 3 (but you can drag it).

    $('#table-3').tableDnD({
        onDrop: function(table, row) {
            alert($.tableDnD.serialize());
        }
    });

Ajax result

Drag and drop in this table to test out serialise and using JQuery.load()

1 One
2 Two
3 Three (Can’t drop on this row)
4 Four
5 Five (Can’t drag this row)
6 Six

This table has multiple TBODYs. The functionality isn’t quite working properly. You can only drag the rows inside their
own TBODY, you can’t drag them outside it. Now this might or might not be what you want, but unfortunately if you then drop a row outside its TBODY you get a Javascript error because inserting after a sibling doesn’t work. This will be fixed in the next version. The header rows all have the classes “nodrop” and “nodrag” so that they can’t be dragged or dropped on.

H1 H2 H3
4.1 One
4.2 Two
4.3 Three
4.4 Four
4.5 Five
4.6 Six
H1 H2 H3
5.1 One
5.2 Two
5.3 Three
5.4 Four
5.5 Five
5.6 Six
H1 H2 H3
6.1 One
6.2 Two
6.3 Three
6.4 Four
6.5 Five
6.6 Six

The following table demonstrates the use of the default regular expression. The rows have IDs of the
form table5-row-1, table5-row-2, etc., but the regular expression is /[^\-]*$/ (this is the same
as used in the NestedSortable plugin for consistency).
This removes everything before and including the last hyphen, so the serialised string just has 1, 2, 3 etc.
You can replace the regular expression by setting the serializeRegexp option, you can also just set it
to null to stop this behaviour.

    $('#table-5').tableDnD({
        onDrop: function(table, row) {
            alert($('#table-5').tableDnDSerialize());
        },
        dragHandle: "dragHandle"
    });
  1 One some text
  2 Two some text
  3 Three some text
  4 Four some text
  5 Five some text
  6 Six some text

In fact you will notice that I have also set the dragHandle on this table. This has two effects: firstly only
the cell with the drag handle class is draggable and secondly it doesn’t automatically add the cursor: move
style to the row (or the drag handle cell), so you are responsible for setting up the style as you see fit.

Here I’ve actually added an extra effect which adds a background image to the first cell in the row whenever
you enter it using the jQuery hover function as follows:

    $("#table-5 tr").hover(function() {
          $(this.cells[0]).addClass('showDragHandle');
    }, function() {
          $(this.cells[0]).removeClass('showDragHandle');
    });

This provides a better visualisation of what you can do to the row and where you need to go to drag it (I hope).

Version History

0.2 2008-02-20 First public release
0.3 2008-02-27 Added onDragStart option
Made the scroll amount configurable (default is 5 as before)
0.4 2008-03-28 Fixed the scrollAmount so that if you set this to zero then it switches off this functionality
Fixed the auto-scrolling in IE6 thanks to Phil
Changed the NoDrop attribute to the class “nodrop” (so any row with this class won’t allow dropping)
Changed the NoDrag attribute to the class “nodrag” (so any row with this class can’t be dragged)
Added support for multiple TBODYs–though it’s still not perfect
Added onAllowDrop to allow the developer to customise this behaviour
Added a serialize() method to return the order of the rows in a form suitable for POSTing back to the server
0.5 2008-07-11 Now supports having a column as a drag handle (specify a class for the dragHandle option when configuring).

Improved the serialize method to use a default (but also settable in the options) regular expression for generating the serialized string. The default is /[^\-]*$/ which will remove everything before a final hyphen, so item-s1 becomes s1.

Added $(’…’).tableDnDUpdate() to cause the table to update its rows so the drag and drop functionality works if, for example, you’ve added a row.

Added $(’…’).tableDnDSerialize() which allows you to serialize a table from any javascript code.

Removed remaining $ and replaced with jQuery so that it should work with Prototype and Scriptaculous

Tags: , ,

212 Responses to “Table Drag and Drop JQuery plugin”

  1. Nathan Says:

    Thank you kindly, this is working nicely for me!

    I have a table that I am refreshing (as in, totally wiping the HTML and replacing it) every few seconds from a server using AJAX, and after every refresh I am calling the $(”#table-1″).tableDnD() method over and over. First off, is the best way to handle things? Or is there a way to trigger the function once when the page first loads, and not have to keep calling it?

    Another thing that happens for me in this case is: you start dragging a row, then it snaps back to its original position after the table gets refreshed (the server hasn’t picked up on the change in position yet because the onDrop() method hasn’t been called yet)… luckily though it will still put it in its correct place once you release the mouse. I want to figure out a way to disable my refresh from replacing the HTML once a drag has begun — it seems that I could apply the onDragClass method and then check the DOM for that in the refresh method, but is that the best way to handle this idea?

    By the way I noticed that this plugin was scrolling the page for me in Firefox if I had a table that was running off the page; great work!

  2. Nathan Says:

    Just wanted to say, in my case I need to know the id of of the row that the drag & dropped row was dropped onto, here is how I handled that:

        	onDrop: function(table, row) {
               	var rows = table.tBodies[0].rows;
    			var droppedon = "";
    
    			if (rows.length < 2)
    				return false;
    
    			if (rows[0].id == row.id)   // dragged to the top, replaced the first one
    				droppedon = rows[1].id;
    			else if (rows[rows.length-1].id == row.id)  // dragged to the bottom, replaced the last one
    				droppedon = rows[rows.length-2].id;
    			else	                           // search for where it was dropped on
               		for (var i=0; i0 && rows[i-1].id == row.id)
    						droppedon = rows[i].id;
    			if (droppedon!="")
    				return true; // so something
    			return false;
        	}
    
  3. Nathan Says:

    Hmm, that else statement should state:

    else // search for where it was dropped on
               		for (var i=0; i0 && rows[i-1].id == row.id)
    						droppedon = rows[i].id;
    

    Okay, sorry for so many comments, I just really like your plugin!

  4. Nathan Says:

    Hmm, that else statement should state: (I’ll try again!)

    else	// search for where it was dropped on
     for (var i=0; i 0 && rows[i-1].id == row.id)
       droppedon = rows[i].id;
    

    Okay, sorry for so many comments, I just really like your plugin!

  5. Nathan Says:

    Agh, something is up with your comments, here is what I am trying to put right after the for() statement:

    i f ( i > 0 & & r o w s [ i - 1 ] . i d = = r o w . i d )

  6. Nathan Says:

    Okay, let me try that one more time, here is my full function:

    var rowsBeforeDragAndDrop;

    // called upon every refresh
    function InitiateDragAndDrop() {

    rowsBeforeDragAndDrop = $(’#queueContent’).children();

    $(”#queueTable”).tableDnD({
    //onDragClass: “myDragClass”,
    onDrop: function(table, row) {
    var rows = table.tBodies[0].rows;
    var droppedon = “”;

    if (rows.length 2 ) {
    for ( var i=1; i < rows.length-1; i++ ) {
    if ( rows[i].id == row.id && rows[i-1].id == rowsBeforeDragAndDrop[i].id )
    droppedon = rows[i-1].id;
    else if ( rows[i].id == row.id && rows[i+1].id == rowsBeforeDragAndDrop[i].id )
    droppedon = rows[i+1].id;
    }
    }
    if (droppedon!=”")
    return ChangeOrder(”switch?uid1=”+row.id+”&uid2=”+droppedon);
    return false;
    }
    });
    }

  7. Nathan Says:

    I give up, here is my function — I think it’s right:
    http://pastebin.com/d3ccbe0ad
    It behaves pretty well with my “refresh” and multiple sorts.

    Again, thank you and I apologize for posting so many freakin comments!

  8. Nathan Says:

    I can see the extra style being applied from the CSS class, but I can’t see it through the DOM:
    onDragClass: “myDragClass”,
    Maybe something is up with my implementation….

  9. Nathan Says:

    Meant to add, alert($(”#queueTable”).attr(’class’)); never reports the “myDragClass” mid-drag.

  10. DenisH Says:

    Hi Nathan,

    If you refresh the table (that is, replace all the HTML) then yes, you do have to call TableDnD() again. There shouldn’t be any memory leakages as far as I know, but it might be an issue. I haven’t built any systems where I need to refresh the table constantly.

    To solve the refresh-in-the-middle-of-dragging problem, there’s now a new config option in version 0.3. You can specify an onDragStart function that will be called when the user first presses the mouse down. You could use this to disable refreshing until the drag is finished?

  11. Sorting table rows with jQuery and ColdFusion « musings Says:

    […] using the jQuery sortables plugin. I was asked how this could be done with table rows. The jQuery TableDnD plugin comes to the […]

  12. DenisH Says:

    Hi aliaspooryorik, thanks for the link to your article and how to serialise the results. I ought to add a serialise method really, I’ll do that in the next release :-)

  13. Kevin Says:

    Will this have row ghosting and serializing soon? Like the Sortables, anything being dragged should be ghosted… if you know what I mean.

  14. DenisH Says:

    It will have serialization soon(ish) when we have time, but ghosting is more difficult. Table rows are not like DIVs and SPANs and can’t be moved in quite the same way–which is why there’s a separate plug-in for doing the table row sorting.

  15. Skylog » Blog Archive » links for 2008-02-29 Says:

    […] Table Drag and Drop JQuery plugin | Isocra (tags: jquery) […]

  16. ShaunS Says:

    How would I go about adding support for sub-levels?

    Example:

    Main 1
    Main 2
    Main 3
        Sub 1
        Sub 2
        Sub 3
    Main 4
        Sub 1
    

    And have the ability to move the sub-elements to other sub-elements or main-elements.

  17. Ajax Noticias Novidades tudo sobre Ajax » Arquivo » Drag e Drop em tabelas com jQuery Says:

    […] TableDnD é uma extensão para jQuery que permite criares o efeito de drag e drop em cada fila da tua tabela.Dá jeito para quando queres ter uma lista de tarefas, e queres deixar os teus users poderem reorganizar a lista. Partilhar esta Entrada (Ninguem Votou)  Loading … […]

  18. Table Drag and Drop JQuery plugin | Isocra Says:

    […] Table Drag and Drop JQuery plugin | Isocra AJAX Scripts Add comments Table Drag and Drop JQuery plugin | Isocra. […]

  19. Snowcore Says:

    It’s very powerful thing, thanks a lot!

  20. Deja Vu Says:

    Why don’t you make the nodrag/nodrop classes instead of attributes that prevent the markup from being valid ?

  21. Deja Vu Says:

    That would be nice to be able to determinate if the row hasn’t moved.

    For instance, I’m actually adding a “dropped” class to the moved elements with onDrop function, but this gets applied even if the row didn’t really change position in the table.

    Nice work anyhow.

  22. Famic Says:

    I’ve been tweeking a bit the script to have the nodrag/nodrop via classes, it goes like this :

                // John Tarr added to ignore rows that I've added the NoDnD attribute to (Header rows)
                var nodrop = $(row).hasClass("nodrop");
                if (nodrop == false) {  //There is no NoDnD attribute on rows I want to drag
    
                // John Tarr: added to ignore rows that I've added the NoDnD attribute to (Category and Header rows)
                var nodrag = $(rows[i]).hasClass("nodrag");
                if (nodrag == false) { //There is no NoDnD attribute on rows I want to drag
    

    Feel free to implement this in the next version if you like valid html ;)

  23. DenisH Says:

    Hi Famic,

    Thanks for that. I’m actually working on a new version that has a callback method so that yo can decide whether to allow drop or not–that way you can use classes or any logic you like. Including support for sub-levels as requested by ShaunS.

    I agree that using classes is cleaner than non-standard html attributes though, so thanks for the input.

  24. Famic Says:

    One other cool feature would be to mix this with some multiselection plugins and be able to grab several rows and move them at once… Dunno if how hard that could be, though. Just throwing in ideas ;)

  25. Frameshift Says:

    Also that would be quite useful to be able to trigger the drag’n'drop only from a specific … To prevent inplace editors to conflit with this drag’n'drop option

  26. Frameshift Says:

    I meant a specific “td” but I put the bracets around it :/

  27. Famic Says:

    I’ve tweaked the script again to have a “dragger” td and let the other td’s inactive…

    // John Tarr: added to ignore rows that I've added the NoDnD attribute to (Category and Header rows)
    	    var nodrag = $(rows[i]).hasClass("nodrag");
                if (nodrag == false) { //There is no NoDnD attribute on rows I want to drag
    		    jQuery(".dragger").css("cursor", "move");
                        jQuery(rows[i]).mousedown(function(ev) {
                        if (jQuery(ev.target).hasClass("dragger")) {
                            jQuery.tableDnD.dragObject = this;
                            jQuery.tableDnD.currentTable = table;
                            jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
                            if (config.onDragStart) {
                                // Call the onDrop method if there is one
                                config.onDragStart(table, this);
                            }
                            return false;
                        }
                    }) // Store the tableDnD object
    

    It might not be the best way to do it, but it works fine…

  28. Logan Says:

    nice work!
    currently, I am building a web-based information system which need one feature like this, but it requires drag and drop on tbody tags rather than on tr tags.
    here is one sample html

    Dragging and dropping Tbody within a table

    Tbody 1 Title
    this is title

    Tbody 1 Title
    this is title

    Tbody 2 Title
    this is title

    Tbody 2 Title
    this is title

    Tbody 3 Title
    this is title

    Tbody 3 Title
    this is title

    I need to be able to drag the whole tbody and move upward or downward, just like doing on the rows.
    how can I do it?
    thanks in advaned

  29. Logan Says:

    oops, the html of table got striped. let me clarify here, there is a table has one thead tag, serveral tbody tags in it.

  30. DenisH Says:

    Hi Logan, that’s pretty difficult! At the moment the code is all about taking one particular row and moving it within the table, to move whole TBODYs you’d need to change the code to work at the TBODY level instead. You might find it easier to start with the raw (non-jquery) code which you can then adapt as you need.

    I’m working on integrating what Famic has posted and adding a callback method. I was also going to look into the impact of having multiple TBODYs, but I’m afraid that I’m planning to add TBODY dragging or multi-selection just yet.

  31. Rick Faircloth Says:

    Hi, Nathan…

    Good job on the plug-in.

    I would like to use it, but when I grab a row to move it, the browser window begins to scroll up and doesn’t stop.

    Any ideas about this problem?

    I’m using IE7.

    Thanks,

    Rick

  32. Rick Faircloth Says:

    Oops, wrong author reference.
    Should have been, “Hi, DenisH” ! Sorry

    Rick

  33. Lesmana Says:

    Well done! I spent the better part of a frustrating day trying to get row dragging to work with jQuery UI a few months ago and finally gave up.

    I did catch a bug; radio boxes reset to defaults when their containing row is dragged. This only happens in IE, not Firefox or Safari. I reported it as a bug in the issue queue at plugins.jquery.com, as well.

  34. Paul Says:

    Just in case anyone is confused as to why something like

    .myDragClass {
    background: #ffc;
    }

    isn’t working, you’ll need:

    .myDragClass td {
    background: #ffc;
    }

  35. Serhio Says:

    Is anyone create some php id script update? I was trying to link eveything but unsuccessful… :(

  36. Just Says:

    Just to say : thanks ;).

  37. iSmart Says:

    Hi! Thnx 4 script.

    It would be great to know (a flag 0/1 or something like it) after drop, row order was changed or not (i.e. when row position ondragstart = row position ondrop).

  38. Jaha Says:

    Thank you for this!

    Any progress on implementing the serialization? I would like to pass the new results into cf, like:

    http://aliaspooryorik.wordpress.com/2008/02/21/sortable-list-with-jquery-and-coldfusion/

    but without serialization im not sure how to go about doing it. Any suggestions would be great.

  39. Jaha Says:

    nevermind they had the info on the site i previously posted

    I am interested in the ghosting though, has anyone made any progress?

  40. nathan Says:

    Whoop, sorry didn’t think you’d publish all my random thoughts!

    Just wanted to put in a feature request, it would be cool if you could do some sort of like sortable groupings.

    How would I go about adding support for sub-levels?
    Main 1
    Main 2
    Main 3
    Sub 1
    Sub 2
    Sub 3
    Main 4
    Sub 1
    And have the ability to move the sub-elements to other sub-elements or main-elements.

    This would be extremely nice; personally, I would want to sometimes disable sub-elements from jumping to other main-elements, but still sortable within their original main-element.

  41. DenisH Says:

    Hi folks, sorry for the lack of progress, we’ve been busy on other things. A new version is just being tested which will include the ability to register methods that get called to determine whether rows can be dragged and whether they can be dropped on other rows.

    We’re also planning on implementing a serialize method. Currently the plan is to work in the same way as the Sortables plugin, so serialize() will return “table1[]=rowId1&table1[]=rowId4&table1[]=rowId2&table1[]=rowId3″ (assuming the table ID is table1 and row 4 has been dragged to be after row 1). Is that what people want? If not, then let us know how you’d like it to be.

  42. nathan Says:

    Sounds great DenisH, the thing I like about this plugin so much is just how simplistic its usage is, so easy to add into what I already have.

  43. Khara Says:

    Is there a way to disable certain rows (tr) from being moved?

  44. DenisH Says:

    Yes, if you add an attribute called “NoDrag” to the row, so you have
    … then the row shouldn’t be draggable, however this means that the HTML isn’t strictly correct, so in the next version I’m going to change this so that you can use a class instead, or define your own method. But for now, that should work fine.

  45. Simon Says:

    DenisH, thank you so much for this plugin! It works great.

    I do have a question, though: The code seems to be checking for the first tbody in each affected table. In the project that we are working on we have tables with multiple tbodies, each with a header row and some content rows. When I apply tableDnD() to one of these tables, only the first tbody becomes sortable. - We need to sort the rows within all tbodies. (We don’t even want to drag rows across the different tbodies, only within each tbody)

    Do you have a suggestion for how we can achieve this with your plugin?

  46. DenisH Says:

    Yup, that’s a bug. We ought to check all the TBODYs but at the moment it only checks the first one. If you have a look through the source code for tbodies[0].rows and add in an extra loop to go round all the tbodies, then that should work. We will aim to fix this in a new release shortly.

  47. kai Says:

    Thanks for the script, very useful!

    I am running into an issue though. When I used this script on a html page with the table full rendered, works great, but when I use this script on a table generated via JS the DnD magic doesn’t get bound to table.

    $(document).ready(function(){

    buildMyTable(”table-1″);

    $(”#table-1″).tableDnD();

    });

    I suspect it has to do with the sequence of events, thanks again.

  48. DenisH Says:

    Hi Kai,

    I think you’re right. It will be to do with the sequence of events. if buildMyTable is using any sort of Ajax or anything asynchronous to build the table then it won’t all be there by the time that you call tableDnD(). But you should be able to call it inside buildMyTable as the last line or so.

    Have you tried using FireBug and putting some breakpoints to see what’s going on?

  49. kai Says:

    Hi DenisH,

    Yes, buildMyTable makes an async call to jQuery’s .load() method:

    $(”#table-1″).load(”/lib/whohasmydata.cfm”);

    I actually tried:

    $(”#table-1″).load(”/lib/whohasmydata.cfm”);
    $(”#table-1″).tableDnD();

    Then:

    $(”#table-1″).load(”/lib/whohasmydata.cfm”).tableDnd();

    Still no luck. Ahh i c, I had no idea FireBug let you debug JS, that’s great, thanks!

    Well, at least I know I’m going down the right path. Thanks agains.

  50. DenisH Says:

    Hi Kai, right so the problem you’ve got is that the load is asynchronous, but returns immediately. What you need to do is change this to:

    // Load takes 3 parameters: url, data, callback. The callback is called when the url has been loaded
    $(”#table-1″).load(”/lib/whohasmydata.cfm”, null, function() {
        // this is called when the load is complete
        $(”#table-1″).tableDnd();
        // I think it should work if you do $(this).tableDnD(), but I haven’t tested it
    });
    
  51. kai Says:

    Perfect! That’s what I was missing, wicked awesome ;)

    Thanks again for your help…

  52. Phil Says:

    A little fix for IE6.
    Dragging a TR makes the page always “scroll down”. With this fix you can scroll up and down.
    Change Line 135:

        if (document.all) {
            // Windows version
            yOffset=document.body.scrollTop;
        }
    

    To:

        if (document.all) {
            // Windows version
            //yOffset=document.body.scrollTop;
            if (typeof document.compatMode != 'undefined' &&
                 document.compatMode != 'BackCompat') {
               yOffset = document.documentElement.scrollTop;
            }
            else if (typeof document.body != 'undefined') {
               yOffset=document.body.scrollTop;
            }
    
        }
    
  53. centralb Says:

    Is background-color one of the properties that cannot be set?

    We’d like to have a unique color for the row being dragged, have tried onDragStyle, onDragClass, and onDropStyle to no effect.

    Great tool!

    Thank you

  54. DenisH Says:

    Hi Centralb, you can set the class or the style of the row being dragged. If you look at table-2 above you’ll see that we’ve set the onDragClass to be myDragClass. This is defined as follows:

    tr.myDragClass td {
        color: yellow;
        background-color: black;
    }
    

    So this says that any TD inside a row that is of class myDragClass should be displayed as shown.

    Hope this helps

  55. JayJay Says:

    Wow, thanks man! You saved my life with this. I had huge problems in my CMS with interface + nested sortables. It was clunky, didn’t work at all in IE7 with TinyMCE loaded at the same time and in FF it required the equivalent of a flight certificate to maneuver correctly.

    Yours just work and I have it working nested even! (Of course you can’t drag table rows from one table to another, but I have another mechanism for that, so this is exactly what I want).

    Somehow playing around with ul and li list-items always brings disappointment to my life, whereas tables are the way to go if you want it hasslefree. So thanks!

  56. DenisH Says:

    Hi folks, finally we’ve got version 0_4 out of the door. It incorporates many of the suggestions and fixes suggested in the comments above. So thanks to all and keep those comments coming!

  57. nathan Says:

    Thanks Denis, I enjoy experimenting with all these new features!

  58. Zbynja Says:

    Hi, your plug-in is really brilliant !! I love it!
    Thank you much for your effort.

  59. iHao Says:

    good job.
    just i needed!

  60. Sara Says:

    Perfect! Just what I am looking for. Could you possibly provide a sample bit of code where you click a ’submit’ button after sorting to submit a serialized list of the sorted table to a php script? I see how you do it with ajax on each drop, but that would be more calls than I need to the database. (Sorry if what I am asking for is obvious - I am a jQuery n00b!)

  61. smilypie Says:

    Denis nice work on this plugin!

    @Sara - you could populate just one hidden field with the jquery serialised list after every drop and then access that field after posting the form. Alternatively (and i find this easier to work with), if you only need to know the new arrangement of id’s you could try adding the unique id to each row via a hidden form field, for example:

    First Row Content
    Second Row Content

    Where each value is the database id. After you submit the form, the rearranged id’s in their new order should be available as an array $_POST[’row_id’]; Hope that made sense…

  62. andy Says:

    This is really great plugin. I have been able to get some php behind it and update list order for a form generator. Now I just need to figure out how to do the following:

    after I add a new element to table-1 I am able to delete and sort rows. I want to be able to call serialize without starting the drag and drop. ie. add form field (6) delete form field (2). submit form -fire serialize function.

    I just can’t figure out how to access the serialize function even if the tr elements did not change position (were not dragged)

    any suggestions??

    great work on this plugin

  63. DenisH Says:

    Hi Andy and Sara,

    I must admit I hadn’t anticipated people wanting to call serialize from outside the onDrop, but I think you can achieve the same thing with the following lines:

    	jQuery.tableDnD.currentTable = document.getElementById("table-3"); // use your table ID obviously
    	alert(jQuery.tableDnD.serialize());
    

    Basically all you need to do is ensure that currentTable is initialized to the right document element and then serialize() works as required.

    In the next version I’ll wrap this up more neatly.

  64. sb Says:

    This is great. Simple, light-weight, easy to implement. Thank you!

  65. James Nylen Says:

    Nice work. I wanted to define a specific class as a dragHandle, so I made the following changes:

        build: function(options) {
            // Make sure options exists
            options = options || {};
            // Set up the defaults if any
    
            this.each(function() {
                // Remember the options
                this.tableDnDConfig = {
                    dragHandle: options.dragHandle ? options.dragHandle : "td", ///// added this
                    onDragStyle: options.onDragStyle,
                    onDropStyle: options.onDropStyle,
    
    ...
    
        makeDraggable: function(table) {
            // Now initialise the rows
            var rows = table.rows; //getElementsByTagName("tr")
            var config = table.tableDnDConfig;
            for (var i=0; i<rows.length; i++) {
                // To make non-draggable rows, add the nodrag class (eg for Category and Header rows)
    			// inspired by John Tarr and Famic
                var nodrag = $(rows[i]).hasClass("nodrag");
                if (! nodrag) { //There is no NoDnD attribute on rows I want to drag
                    jQuery(rows[i]).mousedown(function(ev) {
                        if (jQuery(ev.target).is(config.dragHandle)) { ///// changed this
                            jQuery.tableDnD.dragObject = this;
                            jQuery.tableDnD.currentTable = table;
    
    ...
    

    That way the existing functionality will be the same, unless you specify a dragHandle selector.

  66. James Nylen Says:

    Oh - I also removed the .style(”cursor”, “move”) wherever that was. I think when I used {dragHandle: “.drag”} the whole row still had the move cursor, and I’d rather do that in my stylesheet anyway.

  67. Andrew Says:

    I have added a enable/disable function to this drag and drop, i would like if you could impliment one for future releases, i will post mine but it might not be the best way of doing it. I have also taken out the .css(”cursor”, “move”) aswell and added in my own css class to make it easier to remove on disable and to make the code look prettier. (I don’t like inline css)

    Here is the link to the code, the highlighted bits are the changes.

    http://pastebin.com/f4e702774

  68. Jeroen Says:

    Hi there,

    This is truely awesome work! I’m quite new ot this, but is it possible to handle this as a questionnaire and have the results ’sorting’ send to a db for evaluation?

    Thanks in advance!

  69. uweiss Says:

    in reply to DenisH’s post April 28th, 2008 at 9:30 pm

    If a row is being dragged at the moment on another table, the currentTable variable will be overwritten and we get problems. In that case, here’s an external javascript function for serialization, which of course may be changed for other serialization formats

    function serializeTableOrdering(table) {
      if (table) {
        var result = "";
        var tableId = table.id;
        var rows = table.rows;
        for (var i=0; i 0) result += "&";
            result += tableId + '[]=' + rows[i].id;
        }
        return result;
      }
      return "";
    }
    

    cheers

  70. Francois Levesque Says:

    Hi there,

    Thanks for this great plugin. It’s the closest I’ve found to what I needed for a project. However, my table has several dynamic options, where some cells have checkboxes and other cells are clickable. Basically, what I needed was a way to tell tableDnD to ignore certain cells when rearranging. Luckily I was able to get this working easily by changing one line in your plugin. So I thought I’d share it here for others to enjoy >.<:

    Line 111, in makeDraggable
    if (ev.target.tagName == “TD” && !$(ev.target).hasClass(”nodrag”)) {

    It basically just checks for an additional class flag in the cell.

    Tested in FF2 and IE6.

    Thanks again!

  71. John Says:

    Thanks man, I’ve been looking for something like this since Noah built his boat. Yours is the only stable one out there, works A1 in FF and IE7.

    Very cool, very easy to install, very nice. Thanks!

  72. Joe D'Agostino Says:

    Awesome work. How about a drag drop for columns?

  73. Ewald Says:

    Hi there, I just wanted to say you’ve done a great job with this plugins!

    I’ve got a little suggestion though. Would it be possible improving the serialize() function a bit so I could also see in which tbody certain rows are?

  74. Yuri Says:

    Hello,

    I’ve did a little modification in serialize(). It now supports an optional parameter name that’s used for the name as url query.
    Usefull when you have several table’s on one page that are processed by the same ajax script.

        serialize: function(name) {
            if (jQuery.tableDnD.currentTable) {
                var result = "";
                var rows = jQuery.tableDnD.currentTable.rows;
                name = (name) ? name : jQuery.tableDnD.currentTable.id;
                for (var i=0; i 0) result += "&";
                    result += name + '[]=' + rows[i].id;
                }
                return result;
            } else {
                return "Error: No Table id set, you need to set an id on your table and every row";
            }
        }
    

    example:

    onDrop: function(table, row) {
          $('#surface_profiles_order_result').load("ajax.php?action=order&type=some_type&" + $.tableDnD.serialize('id'));
    }
    
  75. Foppe Hemminga Says:

    You want to replace $ by jQuery in lines 108 and 261.

  76. DenisH Says:

    Hi all, thanks for all the feedback. I’m working on the next version which will include many of the enhancements including regexp in the serialize method, another serialize method that you can call on any table so $(’….’).tableDnDSerialize(), also better handling of multiple tbodies and possibly dragging between tables.

    Unfortunately I don’t intend to handle dragging columns (because columns aren’t draggable things in HTML, it would potentially be possible to make column header cells draggable and then move the rest of the column cells on drop, but that sounds like quite a bit of work). I’m afraid that I can’t really generate server-side code examples for all possible cases either. That’s rather up to you.

  77. Jacob Abshire Says:

    I have a question. I am needing this to run on a page that is also running prototype and scriptaculous. I had to use a jQuery.noConflict(); to allow my jQuery to work when using the edit in place. I tested this with your tableDnD and it broke it. Any ideas?

  78. erkunt karabulut Says:

    hi,
    i have a problem.
    i did some changes on onDrop code

    $(document).ready(function() {
    
    	$('#table-3').tableDnD({
    	    onDrop: function(table, row) {
    
     		   document.write("");
    
            }
    
    	}); 
    
    });
    

    like this. but it does not work. where is my fail.

    sorry my english
    thank you for all

  79. erkunt karabulut Says:

    into the document.write is

    document.write();

  80. erkunt karabulut Says:

    sorry into the document.write is not seen.

    in it there is input hidden tag. value is serialize

  81. DenisH Says:

    Hi erkunt,

    document.write() only works when you’re initially generating the document. It won’t work when the document is already generated. If you want to replace some HTML, then use $(”…..”).html(”<input type=’hidden’ name=’hiddenInput’ value=’something’/>”) but you have to specify where you want it to in the “…..” bit. Look at the jquery documentation for examples.

  82. DenisH Says:

    Hi Jacob, sorry for not getting back to you earlier.

    In the current public version, there are two places where I’ve forgotten to replace $ with jQuery (lines 108 and 261). This was kindly pointed out a week ago or so by Foppe Hemminga. If you change these, it should work. If not, let me know and exactly what error message you get (or symptom or whatever) and I’ll try and fix it in the next version which is almost ready for release.

  83. Sven Says:

    OK, this work great until i add the part:

    // Initialise the second table specifying a dragClass and an onDrop function that will display an alert
    $("#GridView1").tableDnD({
    	onDragClass: "myDragClass",
    	onDrop: function(table, row) {
    		var rows = table.tBodies[0].rows;
    		var debugStr = "Row dropped was "+row.id+". New order: ";
    		for (var i=0; i<rows.length; i++) {
    		debugStr += rows[i].id+" ";
    		}
    		$(#debugArea).html(debugStr);
    		},
    		onDragStart: function(table, row) {
    		$(#debugArea).html("Started dragging row "+row.id);
    	}
    });
    

    I also added:
    tr.myDragClass td { background-color: #336699; } in my style sheet.

    But all functionality is simply gone dead. Any ideas what I’m missing. I’ve been throug the whole long discussion but can’t seem to find the bugger. !?

  84. Sven Says:

    I also did add the debugArea …

  85. Sven Says:

    OK, located it to being problems with ‘invalid character’ at these lines:

    $(#debugArea).html(debugStr);

    and

    $(#debugArea).html(”Started dragging row “+row.id);

    I’m using IE 7 Windows XP. Implemented the code in ASP.NET. But it works fine until I add that part of the script. So somehow it doesn’t like some character in those lines. I suspect it to be either the $ or the #.

    Any clues, anyone?

  86. Sven Says:

    My bummer!

    Had to add in the GridView1_RowCreated event handler:

    if (e.Row.RowType == DataControlRowType.DataRow)
    {
         e.Row.Attributes.Add("id", e.Row.RowIndex.ToString());
    }
    
  87. Sven Says:

    AND remove the # character in the $(#debugArea).html(”string”) lines;

  88. Lucas Says:

    Hey DenisH. I love this addon. I was working on creating my own for a few days, but keeping track of cursor location was getting to troublesome. Unfortunately, the rows I am working with do not contain text, they contain links to other pages, which in turn contains the text. I am unable to drag the linked text inside my rows and was wondering if there was a work around for this situation. Again, thanks for the help and keep up the good work!

  89. DenisH Says:

    Hi Lucas, in order not to interfere with links and form fields, the code deliberately doesn’t let you drag anything other than the table cells. I’m guessing that your table only contains cells with links in which is why you can’t drag the rows. So the trick I think is to add an extra drag “handle” cell at the beginning or end of each row. You could even put an image in the cell to indicate that that’s where the user should drag from. This cell, because it doesn’t have any links in should allow the row to be dragged.

    I’m working on a new version which will specifically supports drag handles, but I’m afraid it’s not quite completed yet.

    If this doesn’t work, or I’ve guessed wrong. Post back with some example rows

  90. Lucas Says:

    I may have to take your suggestion and create a dragging “handle” beside each row. Another thing that I noticed was occurring is, for my table to be draggable with your addon it must consist of tags. I am working with the Django framework and the administrative tables it creates all use tags instead. I am not sure if this is something you could implement, but it is something to consider.

  91. Lucas Says:

    I have tried adding a drag icon, but it will not allow me to drag the row by clicking on the icon. I have also tried adding the words “Drag” next to the icon, and it will let me drag that text, which is a good thing. Unfortunately, I do not like the color black in this table, so i wrapped the text in a font tag to change its color. By adding this font color, I am no longer able to drag the row by clicking on the word “Drag”. Do you have any suggestions on how to remedy this situation?

  92. Lucas Says:

    Also, your serialize command does not work for me because my table rows are created generic, with no row id on them. Would it be possible to implement a different way to serialize the tables without depending on them having their own unique identifiers?

  93. DenisH Says:

    Hi Lucas, for the drag icons, the way to do it is to use CSS. Definitely don’t use a FONT tag, that is deprecated in HTML 4 and XHTML. Instead, add a class to the cell, for example <td class="dragHandle"> </td>. This creates a cell with a non-breaking space in it (so that the border is all drawn correctly but there’s no visible text.

    Now in the stylesheet or style section of the header you can add a background image. Something like:

    td.dragHandle {
    	background-image: url(images/drag.gif);
    	background-repeat: no-repeat;
    	background-position: center center;
    }
    

    This adds a single centered background image. You can also set the width if you need to here.

    As for serializing rows without IDs, I’m afraid you’ll have to write your own code to do this. Iterating over the rows in a table is not difficult either in Javascript or using jQuery. Then you can grab whichever bits of information from your rows that you need.

  94. Tabelle "Sortable" machen mit Scriptaculous - AJAX (Asynchronous JavaScripting and XML) Forum Says:

    […] Vielleicht hilft das ja: Table Drag and Drop JQuery plugin | Isocra […]

  95. Sunil kumar Says:

    I have requirement , there i need to drag a keyword from on div tag.. and i need to drop in editor. Is it possible , if possible can any one tell me how can i do it?

  96. Nathan Says:

    I set this up alongside the “Live Query” plugin: http://brandonaaron.net/docs/livequery/
    Result: works great!

    What I have is an AJAX table which is being refreshed every X seconds — with this LiveQuery I can just totally replace the table’s HTML, without having to re-initialize this tableDnD plugin every time.

    This plugin been working great ever since the first release, so I wanted to say thanks again.

    I am very eager for maybe having a way of setting special rules for hierarchical sorting.
    (so you can specify which rows can be dragged where, more precisely than what you added for v0.4)

  97. Nathan Says:

    Could I make another request? How would I go about setting up a table where I could select multiple rows, and then drag/drop the entire selected group at once? Is there any way to get a box I can kind of draw with my mouse cursor that will select multiple rows for this purpose? I am thinking in the same fashion that the Windows Explorer works for selecting files in a folder, that would help for huge lists that need a lot of custom sorting very quickly.

  98. Rey Bango Says:

    @DenisH Man I wish I would’ve known about your plugin before. I needed something like this for a project! :) I’ll be announcing it to the jQuery mailing list and Twitter acct. I hope you keep enhancing it. This a feature that’s constantly being requested and I would suggest you contact jQuery UI team lead Paul Bakaus to chat about this. He and I were discussing this very same functionality for a future release of jQuery UI. Reach me via email if you’d like an intro.

    Rey - jQuery Team

  99. Bryan Says:

    Hi,

    This is really a great tool…

  100. Bryan Says:

    Hi,

    I was able to run the plugin using a simple html file only.
    I tried to incorporate it to a joomla 1.5 page and it was
    not running.
    This is the error from firebug:

    $(”#left_d”).tableDnD is not a function
    (no name)()index.php (line 24)
    ready()jquery-1.2.6.min…. (line 27)
    ready()jquery-1.2.6.min…. (line 27)
    nodeName([function()], function(), undefined)jquery-1.2.6.min…. (line 21)
    ready()jquery-1.2.6.min…. (line 27)
    [Break on this error]$(”#left_d”).tableDnD();

    and this is my code:

    $(document).ready(function(){
    alert(”document is ready”);//this is working
    $(”#left_d”).tableDnD();
    alert($.tableDnD.serialize());
    });

  101. DenisH Says:

    Hi Bryan, if it says that tableDnD is not a function then that suggests that the jquery.tablednd.js file is not being read in properly (you can check this easily in FireBug by going to the script tab and then in the pull-down menu next to “Inspect” you should see jquery.tablednd.js. If it’s not there, that’s your problem.

    Alternatively if it is there, then it might be due to a clash with other Javascript libraries that redefine the $ (e.g. Prototype or Scriptaculous). There is a known bug in the current release where $ is used directly. Have a look at this comment by Foppe above. You would also need to call jQuery.noConflict(); so that it doesn’t clash. Having said that since in your code the document.ready function works, my guess is that the jquery.tablednd.js just isn’t being loaded properly.

  102. jQuery Table sorter | Paul Richards Says:

    […] Table Drag and Drop Web site […]

  103. Bryan Says:

    @DenisH thank you for the immediate. i tried to follow your suggestion in firebug and you are right. it is really my problem actually and not with the plugin. i mistakenly typed the filename for jquery.tablednd.js.

    i really do appreciate your effort in helping me solved my problem. you are really a great man. keep up the good work.

  104. Bryan Says:

    @Denish [thank you for the immediate reply] i mean. sorry for the typo error on the previous post. :)

  105. Juraj Says:

    Hi,

    Having a problem with making this work. File is included without errors but then I try to make a table sortable, Firebug says:

    ob.toString is not a function
    [Break on this error] var nodrag = $(rows[i]).hasClass(”nodrag”);
    js (line 139)
    $ is not a function
    [Break on this error] var nodrag = $(rows[i]).hasClass(”nodrag”);

    Perhaps worth mentioning that Im not using standard “$” but “$j” instead to call jQuery.

    Many thanks,
    Juraj

  106. Juraj Says:

    follow up :) :

    I commented out “nodrag” class checks, i.e:
    var nodrag = false; //$(rows[i]).hasClass(”nodrag”);

    since I wont have any rows which are not draggable anyway. This seems to solve my problem.

    Any ideas?

    J.

  107. DenisH Says:

    Hi Juraj,

    I reckon this is due to the bug in the code to do with the fact that I’ve left $(…) in two places in the plugin. If you look at the post from Foppe it tells you which lines to change. If you change them to jQuery then it should work fine. I’ve fixed this in the alpha of the next release but need to do some more testing before I make it public. Sorry!

  108. Juraj Says:

    Yes I just realised as I wasnt sure what you are allowed to use inside a jQuery plugin and came here to make 3rd post :D

    All working now.

    Excellent plugin. Pint of beer for you ;)

    Juraj

  109. Juraj Says:

    Not sure if anyone requested this but “refresh” would be useful as well as I keep dynamically adding rows.

    Cheers
    Juraj

  110. djot Says:

    -
    Hi,

    found a typo, that has to be corrected on both the website and in the JS-file itself

    Please change “serialise” to “serialize” everywhere!!

    thx for the plugin anyway ;)

    djot
    -

  111. Neville Franks Says:

    Hi Dennis,
    Thanks for this great JQuery add-on which I am putting to very good use in a Windows Desktop app.

    I’ve added: if ( ev.button == 1 && ev.target.tagName == “TD” )
    to the mousedown() function as I use a context menu on right click and also don’t feel that drag&drop should work with the right button. Maybe you could add an option for this in the future.

    Could you also please include the code posted by Andrew on May 5th, 2008 at 8:05 am which lets us disable table d&d.

    Keep up the great work,
    Neville

  112. Collection Of Cool And Free Ajax Scripts | badeziner Says:

    […] Table Drag and Drop JQuery plugin […]

  113. nickD Says:

    djot, ’serialise’ is a perfectly correct spelling in *all* other parts of the world :-)
    (just a friendly dig, no offence meant)

    Many thanks Dennis for your great work.

    Cheers,
    Nick

  114. tgogoi Says:

    Hey Dennis, I wondering is anyone knows of a way to make the table scrollable inside a scrollable div. I mean just like how window scrolls when I drag to the edge of the window, Is there a way to scroll once I hit the edge of the scrollable div?

    Thanks for any help!!!

  115. arian Says:

    i am trying to make a drop down table …
    everything works fine but i couldn’t figure it out how i can get the id of dropped row.
    i can update db table with only one query only if i have the starting row id which i can get easily by using row.id and the dropped row id ( which i don’t know how i can get ???) .
    please relpy if there is an easy way to find the dropped row id.

    All thanks to Dennis for this very useful plugin

    arian

  116. Pawel - Poland Says:

    Is there any way to drop rows but ony when you hold mouse on one particular column. I don’t know are mine explanations clear - In standard version if there is few columns, to drag a row you can grab any column and move all row up or down, I want make dragging work only if you grab one column.

    Sorry for poor english :)

  117. links for 2008-07-04 « toonz Says:

    […] Table Drag and Drop JQuery plugin | Isocra (tags: jquery table drag) […]

  118. roScripts - Webmaster resources and websites Says:

    Table Drag and Drop JQuery plugin | Isocra…

    I ve been using JQuery for a while now and really agree with its tag line that it s the The Write Less Do More JavaScript Library We ve also got this…

  119. Jesús Ricarte - Blog » Blog Archive » Tablas más usables con jQuery Says:

    […] Table Drag and Drop: Como su propio nombre indica, permite arrastrar mover las filas de una tabla para ordenarlas a gusto del usuario. […]

  120. Steven Hoefel Says:

    Pawel (And Lucas who was creating the dragHandle),
    To make only one column do the dragging you can do this:
    change makeDraggable line:
    if (ev.target.tagName == “TD”)
    to:
    if (ev.target.tagName == “TD” && ev.target.className == “drag”) {
    or… check the ID or another className and then the code will only activate on that specific TD.

  121. Steven Hoefel Says:

    Forget what I just wrote and look for Famic’s post on “dragger”; much tidier.

  122. Nils Ellingsen Says:

    Huge thanks!
    I am new to CakePHP and Prototype (but I’m a jQuery addict), and had some problems getting it to work on a quite complex page wich used ajax pagination (from CakePHP), ajax form insertion into the same table (with ajax helper) and reloading the whole pagination-div with jQuery, including some visual effects thrown in.

    Here’s what I had to do:
    Make sure prototype and scriptaculous is loaded before jquery and tablednd.js, then execute a javascript-codeblock:
    jQuery.noConflict(); right after including the jQuery-files.
    Do not use custom noConflict variable-names, stick with the default and it seems to work quite nice (and that’s a lot of js-code working together at the same time! :)).

  123. pligg.com Says:

    JQuery Drag and Drop…

    Rearanjeaza randurile unui tabel prin Drag and Drop cu libraria jQuery…

  124. DenisH Says:

    At long, long last here’s the latest version of the plugin. It now supports drag handles and cleverer serialization. It should also now work properly with Scriptaculous and Prototype.

    I had hoped to add in multi-table drag and better support for multiple tbodies, but decided it was better to get this release out than hang on any longer.

    DenisH

  125. links for 2008-07-12 | JeremiahTolbert.com Says:

    […] Table Drag and Drop JQuery plugin | Isocra (tags: jquery javascript plugin tables) […]

  126. 20080713 網摘 - Google 虛擬世界 - 網絡暴民 Jacky’s Blog Says:

    […] Table Drag and Drop JQuery plugin […]

  127. arian Says:

    Thanks Denish :)

  128. Adam Says:

    I am trying to implement a table like table-5 above and when the page loads all of the cells contain the image until I hover over the row then move the mouse. Basically the cells do not look like table-5 until after I hover over each row once. Is this something I need to fix in my CSS code or in the onload of the HTML page?

  129. Adam Says:

    Never mind I figured out what I did wrong.

    I need to create a blank style to start out with.

  130. James Byers Says:

    We wanted to make everything draggable except links and form elements. In particular, we wanted text in the row to drag like everything else. We did this by changing:

    if (ev.target.tagName == “TD”) {

    to:

    if (ev.target.tagName != “A” && ev.target.tagName != “INPUT” && ev.target.tagName != “BUTTON” && ev.target.tagName != “SELECT” && ev.target.tagName != “TEXTAREA”) {

    This seems to work, though a full solution would traverse from the current element up until the TD and verify it doesn’t hit one of these elements on the way. This additional check would prevent issues where foo is draggable when it should be a link.

  131. James Byers Says:

    “foo” in my previous comment should have looked like <a…><b>foo</b></a>

  132. Drag & Drop via JQuery & Ajax --> Geht nicht :( - php.de Says:

    […] die DnD funktioniert auch einfach nicht. Ich bin dabei anhand folgendes Tutorials vorgegangen: Table Drag and Drop JQuery plugin | Isocra Hatte vielleicht schon mal jemand ein ähnliches Problem? Gruß Thomas __________________ […]

  133. Cesar Says:

    @DenisH great work on this script, but my question is, im trying to use your example of table 3, when im finished sorting i want to save the new order values to my database, you seem to have done it (sort of) in your example, im new to ajax, is it possible to see the code on how the ajax load is working, since its usiing php to display the new values thats all i really need.

  134. DenisH Says:

    hi DenisH, great plugin there, really enjoy it.
    I have a problem though, have been cracking my head try to get the re-arranged new position update to the database, using asp, classic asp I mean.
    Come across the tips on how to do it in coldfusion, but still couldn’t figure out how to do it in asp, anyone here can shade some light on this?

    Thanks guys.

  135. kahfei Says:

    Oops..sorry, not sure why my comment appear as posted by DenisH, :-). the above comment is from me.

  136. DenisH Says:

    Hi Kahfei,

    If you need to update a database using ASP, JSP, PHP, ColdFusion or whatever, then you have two choices, you can use an Ajax call to inform the server whenever the user drops a row, or you can have a button that sends a form back to the server so the user can do a “Save”. For the Ajax call, have a look at table-3 to see how that’s done. Once you’ve dragged, the results of the server-side PHP are shown on the right hand side and you can click on the link to see the source. If you use a button, then it would work in much the same way. Put the results of the serialize() call on the end of the URL and the server will get the data you need.

    If you were using VBScript (not my usual language, so apologies if it is a bit clunky) you could do something like this:

    dim iCount
    if (request("table-3[]").count > 0) then
    	' If we've been posted some updates, update the database
    	set oConn = server.createObject("ADODB.Connection")
    	oConn.open sConnStr
    
    	' sSQL = "UPDATE mytable SET displayOrder = 0"
    	' oConn.execute(sSQL)
    	for iCount = 1 to request("table-3[]").count
    		dim rowId
    		rowId = request.queryString("table-3[]")(iCount)
    		if (rowId <> "") then
    			sSQL = "UPDATE mytable SET displayOrder = " & iCount & " WHERE rowId = " & rowId
    			oConn.execute(sSQL)
    		end if
    	next
    
    	oConn.close
    	set oConn = nothing
    end if
    

    Hope this helps!

  137. Ravi Says:

    >>>0.5 2008-07-11 Now supports having a column as a drag handle

    So you mean columns are switchable by dragging now???

  138. DenisH Says:

    No, dragging columns would be tricky because each row would have to be changed. By “drag handle” I mean that you can put an icon or something in a column and then only drag rows using that column. See table-5 above.

  139. kahfei Says:

    Hi DenisH,

    Million thanks, will try to adapt that to my code. :-)

  140. euro Says:

    great thing :)

    one little question..
    how can i submit the form via POST? this would be just great - if there’s some easy solution.
    tried some jquery-ajax function, but they dint work

    thx

  141. Fiaz Says:

    Is there a way of detecting an actual change? By clicking on a row and NOT dragging it still makes the ajax call, i am wondering if there is a way to detect whether the row ordering had in fact changed.

  142. DenisH Says:

    One of the things that is still lacking in this plug-in is some sort of tollerance so that a drag of less than, say 5px, up or down wouldn’t trigger the onDrag code–or if you drop the row where it was originally.

    For now I’m afraid you’ll just have to remember the original order and then check it before doing the Ajax call. You can do this pretty simply by storing the string returned from serialize as say originalOrder. Then in your onDrop code, call serialize again and see if the new order is the same as the original one. If it is, do nothing, otherwise replace the originalOrder with the new one and call your Ajax.

    Hope this helps.

  143. Fiaz Says:

    Yep.. i store the original order in the onDragStart event and compare in the onDrop event. Thanks! :)

  144. Fiaz Says:

    Another query… is it possible to remove tablednd from a table using javascript? I want to be able to turn ordering off and on, i can turn it on.. i need a way to turn it off wthout a page reload.
    Thanks

  145. Kev Says:

    Hi, im trying to integrate this plugin with another (Flexigrid), however when the format of this table is:

    .
    .

    is it possible to use the tableDnD() function in this way?

  146. Kev Says:

    sorry was trying to write table and tbody, is it possible for the table drag and drop plugin to work in this way?

    .
    .

  147. Roger Says:

    Hi. I’m trying to store the original order through the onDragStart event and only update if the original order is different than the order onDrop. I’ve tried a couple different ways with no success. Any help would be appreciated. Thanks! :)

  148. Paul Richards Says:

    Just a quick note, if you add a semi colon to the end of line 374 you are then able to use Dean Edwards packer to get the plug-in down to 3kb instead of 17kb.

  149. Zbiór skryptów AJAX/Javascript/Dhtml. (50+) | Darmowe skrypty, programowanie, informacje domeny Says:

    […] Table Drag and Drop […]

  150. Zbiór skryptów AJAX/Javascript/Dhtml. (50+) | Darmowe skrypty, programowanie, informacje domeny Says:

    […] Table Drag and Drop […]

  151. ralphjoson » Blog Archive » Cool jquery plugins Says:

    […] Table Drag and Drop - This TableDnD plugin allows the user to reorder rows within a table […]

  152. Nino Dafonte Says:

    Hi folks!

    I´ve started to use this plugin last week (congratulations to DenisH for his work).
    The thing was that I needed to use the tablednd inside a scrolled div.
    I´ve made the changes to get it working this way and I will let them here for anyone that has the same needs than me.

    best regards to everyone!

    ——————————————————–
    I added a new option to inform the plugin which is the name of the container:

    	        ....
                    serializeRegexp: /[^\-]*$/, // The regular expression to use to trim row IDs
    		serializeParamName: null, // If you want to specify another parameter name instead of the table ID
                    dragHandle: null, // If you give the name of a class here, then only Cells with this class will be draggable
                    containerDiv: null //  bottomBorder) {
    			container.scrollTop(container.scrollTop() + config.scrollAmount);
    		}
    
    		if (mousePos.y  jQuery.tableDnD.oldY;
                // update the old value
                jQuery.tableDnD.oldY = y;
                // update the style to show we're dragging
    			if (config.onDragClass) {
    				dragObj.addClass(config.onDragClass);
    			} else {
    	            dragObj.css(config.onDragStyle);
    			}
                // If we're over a row then move the dragged row to there so that the user sees the
                // effect dynamically
    			var offsetx = jQuery.tableDnD.mouseOffset.y + container.scrollTop() - 10;
                            // this number (the 10 in the line above) is a FIX to adjust the mouseover, feel free to change it to wherever you need
    			var currentRow = jQuery.tableDnD.findDropTargetRow(dragObj, y + offsetx);
                if (currentRow) {
                    // TODO worry about what happens when there are multiple TBODIES
                    if (movingDown && jQuery.tableDnD.dragObject != currentRow) {
                        jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling);
                    } else if (! movingDown && jQuery.tableDnD.dragObject != currentRow) {
                        jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow);
                    }
                }
            }
    	// END NINDAF FIX
    
            return false;
        },
    
  153. Nino Dafonte Says:

    sorry for the latest post, the code is … i don´t know what happened, i will post a link to the sources late at night,

  154. Nino Dafonte Says:

    TableDnd in Scrolled Div, Part 1:

    adding a new option to the plugin:

    this.each(function() {
                // This is bound to each matching table, set up the defaults and override with user options
                this.tableDnDConfig = jQuery.extend({
                    onDragStyle: null,
                    onDropStyle: null,
    				// Add in the default class for whileDragging
    				onDragClass: "tDnD_whileDrag",
                    onDrop: null,
                    onDragStart: null,
                    scrollAmount: 5,
    				serializeRegexp: /[^\-]*$/, // The regular expression to use to trim row IDs
    				serializeParamName: null, // If you want to specify another parameter name instead of the table ID
                    dragHandle: null, // If you give the name of a class here, then only Cells with this class will be draggable
                    containerDiv: null
                }, options || {});
                // Now make the rows draggable
                jQuery.tableDnD.makeDraggable(this);
            });
    
  155. Nino Dafonte Says:

    TableDnd in Scrolled Div, Part 2

    replace mousemove function:

    mousemove: function(ev) {
            if (jQuery.tableDnD.dragObject == null) {
                return;
            }
    
            var dragObj = jQuery(jQuery.tableDnD.dragObject);
            var config = jQuery.tableDnD.currentTable.tableDnDConfig;
            var mousePos = jQuery.tableDnD.mouseCoords(ev);        
    
            //auto scroll the window
    		// FIX TO CHANGE SCROLL TO DIV INSTEAD THE ENTIRE DOCUMENT - NINDAF
    		var container 	= config.containerDiv;
    		var yOffset = container.scrollTop();
    		var windowHeight = container.innerHeight();
    		var y = mousePos.y - jQuery.tableDnD.mouseOffset.y;		
    
    		var upperBorder = container.position().top;
    		var bottomBorder = container.position().top + container.innerHeight();		
    
    		if (mousePos.y > bottomBorder) {
    			container.scrollTop(container.scrollTop() + config.scrollAmount);
    		}
    
    		if (mousePos.y  jQuery.tableDnD.oldY;
                // update the old value
                jQuery.tableDnD.oldY = y;
                // update the style to show we're dragging
    			if (config.onDragClass) {
    				dragObj.addClass(config.onDragClass);
    			} else {
    	            dragObj.css(config.onDragStyle);
    			}
                // If we're over a row then move the dragged row to there so that the user sees the
                // effect dynamically
    			var offsetx = jQuery.tableDnD.mouseOffset.y + container.scrollTop() - 15;
    			var currentRow = jQuery.tableDnD.findDropTargetRow(dragObj, y + offsetx);
                if (currentRow) {
                    // TODO worry about what happens when there are multiple TBODIES
                    if (movingDown && jQuery.tableDnD.dragObject != currentRow) {
                        jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling);
                    } else if (! movingDown && jQuery.tableDnD.dragObject != currentRow) {
                        jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow);
                    }
                }
            }
    		// END NINDAF FIX
    
            return false;
        },
    
  156. Kutay Says:

    Hi, when I put div tags between the td tags, I still have functionality but I can only start dragging from the very bottom or very top of the row. I mean that I have to click maybe 1 or 2 pixels from the bottom border. Same applies for the top either. However, I want to start dragging the row no matter where I click (usually the middle). Is there any workaround for that?

  157. Rowan Says:

    Would be helpful to serialize table data to a JS object instead of a string.

        serializeTableToObject: function(table) {
            var result = {};
            var tableId = table.id;
            var rows = table.rows;
            result[tableId] = [];
            for (var i=0; i<rows.length; i++) {
                var rowId = rows[i].id;
                if (rowId && rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) {
                    rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0];
                }
    
                result[tableId][i] = rowId;
            }
            return result;
        }
    
  158. Thomas Angelbo Christensen Says:

    Great work DenisH!

    Are you by any chance planning an update to the plug-in some time in the near future? I’d hate to see this one lost, without it at least reaching version 1.0!

    How much work have you done performance-wise? It seems a bit sluggish on tables containing more than 50 rows.

  159. Aaron Says:

    Hi DenisH,

    I must say that jQuery’s plugin is simple, minimalistic and fantastic!. I only want to know: What kind of license is it on? Is it GPL/MIT like jQuery? Can I use it in a commercial / non-commercial proyect?

  160. Julie Says:

    Thank you so much! This is wonderful!

  161. Vinicius Cruz » jQuery, o que é isso? Says:

    […] pode agilizar ainda mais no desenvolvi