# Table Drag and Drop jQuery plugin

This page contains documentation and tests for the TableDnD jQuery plug-in. For more information and to post comments, please go to isocra.com.

If you have issues or bug reports, then you can post them at the TableDnD plug page.

## How do I use it?

1. Since TableDnD is a jquery pligin you will need to include jquery in your page first.

   No need for any downloads simply reference jQuery from the Google CDN (Content Distribution Network) All scripts are included at the bottom of the page, to facilitate quicker rendering of the HTML for more responsive pages. The following is the way we are linking to jQuery in the examples and this method can be recommended for use in your implementations too.

       <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

2. You will also need a copy of the TableDnD plugin (current version 0.9) which you can reference in the normal fashion, anywhere after jQuery.
3. In true jQuery style, the typical way to initialise the tabes is in the `$(document).ready` code black function. Use a selector to select your table and then call the following (You can optionally specify a set of properties (described below).

       tableDnD()

## A basic table

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:

## Settings

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)

## OnDrag custom table

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+" ";
                }
    	        $(table).parent().find('.result').text(debugStr);
    	    },
    		onDragStart: function(table, row) {
    			$(table).parent().find('.result').text("Started dragging row "+row.id);
    		}
    	});
    });

1 | One |  | V | C | N
2 | Two |  | V | C | N
3 | Three |  | V | C | N
4 | Four |  | V | C | N
5 | Five |  | V | C | N
6 | Six |  | V | C | N
7 | Seven |  | V | C | N
8 | Eight |  | V | C | N
9 | Nine |  | V | C | N
10 | Ten |  | V | C | N
11 | Eleven |  | V | C | N
12 | Twelve |  | V | C | N
13 | Thirteen |  | V | C | N
14 | Fourteen |  | V | C | N

## Communicating with the back-end

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 `serialize()`. 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.

Since version 0.9, instead of manually creating the serialized data string we instead use jQuery's param method which has the added benefit of url encoding the data string as well.

This third table demonstrates calling the serialize 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 (Can't drop on this row) |
5 | Five |
6 | Six (Can't drag this row) |
7 | Seven |

## Multiple tbody table

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 |

## Identify rows

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($.tableDnD.serialize());
            },
            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).

## Meta table (auto configure)

Basic example with extra fancy
row styles bot this trick really
only works with single column
because it looses the corumn
width when displaying a table
in block style unfortunately

Name | Start Date | End Date | Actions
--- | --- | --- | ---
Present Sprints
First round - in sprint | 2012-09-19 | 2012-09-27 |
Future Sprints
Second round | 2012-09-28 | 2012-10-04 |
Third round | 2012-10-04 | 2012-10-11 |
Fourth round | 2012-10-13 | 2012-10-20 |
Release prep | 2012-10-20 | 2012-10-27 |
Fifth run | 2012-10-27 | 2012-11-03 |
Sixth run | 2012-11-03 | 2012-11-10 |
Seventh run | 2012-11-10 | 2012-11-17 |
Release 2 prep | 2012-11-17 | 2012-11-24 |
Past Sprints
Backlog creation - complete | 2012-09-01 | 2012-09-08 |
No Sprints

Hide JSON

## Hierarchy table

This table allows row order to be dragged horizontally and placed in a hierarchy under a parent row (since version 0.9). We also get a chance to look at the new jsonize method for JSON serialized form of the data.

In the onDrop event handler we pass the JSON as data to jquery through a HTTP POST ajax call to the server:

        $.post("server/ajaxJSONTest.php", $.tableDnD.jsonize(), function (data) {
            $('#table-7-response').html('
    '+ data);
        });

On the back-end we have a PHP example that simply retrieves the JSON POST data from the built in stream php://input, decodes the payload and proceeds to build the hierarchy through recursion.

To keep the data simple and also stay compatible with the http variable methods as mentioned previously the data structure is formed with separate collections. If a parent has children the children first level are listed and if any of the children have subsequent children an additional collection is created for the first level of these.

The following hierarchy for example would generate 3 collections:

- 7.00
  - 7.01
  - 7.02
    - 7.03
- 7.04

In JSON the dataset looks like this:

Hide JSON

    {
    	"table-7": [
    		"7.00",
    		"7.04"
    	],
    	"7.00": [
    		"7.01",
    		"7.02"
    	],
    	"7.02": [
    		"7.03"
    	]
    }

We use the setting hierarchyLevel to indicate how many levels are supported, the example uses 4 levels deep. When populating the table you can use the the data-leve tag to indicate at which level the current row is represented at.

### Ajax result

Drag and drop in this table to test out hierarcies and using JSON payload.

7.0 One |
7.1 Two |
7.2 Three |
7.3 Four |
7.4 Five |
7.5 Six |
7.6 Seven |
7.7 Eight |
7.8 Nine |
7.9 Ten |
7.0 One |
7.1 Two |
7.2 Three |
7.3 Four |
7.4 Five |
7.5 Six |
7.6 Seven |
7.7 Eight |
7.8 Nine |
7.9 Ten |

Hide JSON