Drag and drop table rows with JavaScript

REDIPS.drag was initially built to drag and drop table content. After publishing first version of REDIPS.drag, I received a lot of questions about dragging table rows also. Now is possible to drag and drop table rows as well as table content. First column and contained DIV element in this demo is a row handler, so you can try to drag table rows.


REDIPS.drag example15

It is very easy to define a row handler. Actually, it is only needed to place DIV element to the column (first, last or any other) and to define class=”drag row”. This DIV element will become a row handler. When row dragging begins, source row will change color and content will become transparent. This way, source row as start point is visible and obvious. It is possible to return row to the start point – in this case, event.rowDroppedSource() will be fired. In a moment when row is dropped to the destination table, source row will be removed. How REDIPS.drag works? The trick is to clone a mini table from the source table and to remove all rows except selected row. It looks like a row, but it is a table with only one row – a mini table. New functionality also brings new event handlers:

  1. event.rowChanged
  2. event.rowClicked
  3. event.rowCloned
  4. event.rowDeleted
  5. event.rowDropped
  6. event.rowDroppedBefore
  7. event.rowDroppedSource
  8. event.rowMoved
  9. event.rowNotCloned
  10. event.rowNotMoved
  11. event.rowUndeleted

Each event handler has access to the obj and objOld objects. For example, event.RowClicked() sees only obj object and this is reference to the source row. event.rowMoved() is fired in a moment when dragging starts and in this case, obj is reference to the mini table (previously mentioned) while objOld is reference to the source table row.

REDIPS.drag has a new method: rowOpacity(el, opacity, color) to change color and opacity of the source row and mini table. This way it is only needed to call rowOpacity() method in event handlers to have row effects like in this demo. Here is code for event.rowMoved() used in this demo:

rd.event.rowMoved = function () {
    // set opacity for moved row
    // rd.obj is reference of cloned row (mini table)
    rd.rowOpacity(rd.obj, 85);
    // set opacity for source row and change source row background color
    // rd.objOld is reference of source row
    rd.rowOpacity(rd.objOld, 20, 'White');
    // display message
    msg.innerHTML = 'Moved';
};

REDIPS.drag takes care about background color of table cells and table rows. When dragging begins, color of each table cell is saved to the array and returned in a moment of dropping or highlighting current table row. Source code of REDIPS.drag library with examples can be download from “download icon” below post title. If you want to see more drag and drop examples based on REDIPS.drag, click on Drag and Drop category.

Happy dragging and dropping!

178 thoughts on “Drag and drop table rows with JavaScript”

  1. Hello,
    When i use Example 16, there is a left div and a right div,

    when i put a draggable div in the right part, in a table cel (with html) like:
    ns1.2a

    its invisble. So i tried putting ns1.2a
    No luck.
    Tried examining your other examples to see what could be the problem – but this seems to work in other examples.
    Could you please explain how i can put a draggable div inside a cell in the “right” container with html

    Best Regard,
    Ugur

  2. @Ugur Yilmaz – The example16 is somehow specific comparing to other examples in package. In the moment when DIV element is dropped to the right section, AJAX call is executed to fetch the content of DIV element. Inner HTML of DIV element is overwritten with content from AJAX response. If you test this example localy, there can be a problem as you discribed. You can either test example16 from your local web server of you can see it in action from Preview link below post title.

  3. hi dbunic is there event to cancel the drop like you did
    in regular cell – return false myhandler_dropped_before .

    because i didnt find .

  4. @oded – Version 4.6.6 is published today with implemented myhandler_row_dropped_before() event handler. Just return false from this method and row drop will be canceled. Cheers!

  5. Hi, I use this tool for about a year, is very useful!
    But I’ve a little problem: there is a tag in a cell and his value is loaded from database.
    At onblur event I save new textarea value. But when I drag table row textarea returns the value equal to the previous.
    Is there a way to update table content?
    p.s. sorry for the english, I’m italian :)

  6. @pat – So, you have TEXTAREA element in table cell and in a moment of dragging row its content is returned to previous value? I placed simple TEXTAREA in example15, changed content, dragged and didn’t notice such a problem. Maybe “onblur” registred event in your page is fired twice and replaces TEXTAREA content. It will be much easier if you can prepare example to show unwanted behaviour … And your english is just fine – I’m your neighbour from Croatia ;)

  7. Thanks,
    probably there was a script version problem. I’ve uploaded the last redips-drag-min.js and changed something for using a “groups and table rows” (example 19) and now it works very well!

    Can I have more than one main table side by side and drag rows between them?
    Thanks

  8. @pat – Placing tables side by side should be possible. Please see Example 3: School timetable (static) where tables are placed in “left” and “right” DIV containers and styled with float to left … and I’m glad you solved previously mentioned issue.

  9. Hi,

    First let me say, this is a wonderfull library. I’m currently playing around with it, but I still have a question. When will column dragging be introduced officially? Is it possible to use a temporary ‘hack’ to introduced it?

  10. @Arevico – Column dragging is in my plans and I hope it will be implemented during this year. It’s a bigger code modification so I need more time. But unfortunately, we have finishing phase of main project on my full time job – and it’s a quite time-consuming. I’m not sure I can make a quick hack to allow correct column dragging functionality. Element/row dragging logic is dispersed across the code so modification is not easy. Sorry if this doesn’t sound nice, but I’ve tried to be honest. Thanks!

  11. Damn good work, dbunic. Well done.

    I was almost giving up on a small app I want to develop when I stumbled on this and it may actually do the trick. Some questions, though:
    1. Is the cell content editable?
    2. Can I use the cell to set variable, so I can make calculations like a spreadsheet?

    Thank you a lot for this!

  12. Hi Zax! I’m glad you like my work. Here are answers to your questions:
    1)
    TD element can contain form elements like input boxes or textarea – if needed. Or you can prepare your own utility JS function to change innerHTML property of TD element. So, speaking generally, yes cell content can be editable.

    2)
    If you want to store some numerical values to the table cell (that will be hidden), maybe you can use input elements like:

    <input type="hidden" name="a1" value="1234"/>
    

    Drag and drop DIV elements to such table cells should not affect or delete INPUT elements. It depends of what you want to achive there may be other solutions like storing values to the class name, using JavaScript array for each table cell and so on.

  13. Hi dbunic,

    I’m not able to drag drop rows which are created dynamically? Can you please help me with this?

  14. @serioushavok – Here is JS code to dynamically append table rows to first table in this example – example15.

    First set id to the table:

    <table class="tbl1" id="tbl1">
    

    Add button to call append_row() function:

    <input type="button" value="Append row" onclick="append_row()"/>
    

    … and add the following code to the script.js file

    var append_row,
        create_cell;
    
    // append row to the table
    append_row = function () {
        // table reference
        var tbl = document.getElementById('tbl1'),
            // append table row
            row = tbl.insertRow(tbl.rows.length),
            // define number of columns from second row (first row has colspan)
            cols = tbl.rows[1].cells.length,
            i;
        // insert table cells to the new row
        for (i = 0; i < cols; i++) {
            create_cell(row.insertCell(i), i, 'cdark');
        }
        // set class name for new table row
        row.className = 'rl';
    };
    
    // create DIV element and append to the table cell
    create_cell = function (cell, col, style) {
        var node;
        // first column (create row handler)
        if (col === 0) {
            // create DIV element and set class names for row handler
            node = document.createElement('div');
            node.setAttribute('class', 'drag row');
            node.setAttribute('className', 'drag row');
            // enable row handler DIV element
            REDIPS.drag.enable_drag(true, node);
            // set TD style for row handler
            style = 'rowhandler';
        }
        // empty cells for other columns
        else {
            node = document.createTextNode('');
        }
        // set TD class names
        cell.setAttribute('class', style);
        cell.setAttribute('className', style);
        // append empty text node or DIV element to the table cell
        cell.appendChild(node);
    };
    

    Hope this codes will help you to implement dynamic row appending.

  15. Hi dbunic,

    This is a wonderful example of drag & drop! I am interested to develop a PHP/MySQL driven system on iPad using your example. The problem is that once the touchmove is triggered, the DIV is no longer movable, instead the touch scroll was activated. After a page refresh, it worked again. See the video here: http://www.youtube.com/watch?v=FrgevUhIm2U

    I am looking into the redips-drag-min.js file but not sure what to tweak. If you’d look into it or give me a clue, that would be great! I really appreciate your work.

  16. @Eric – It seems that Safari Mobile loses registered event listeners (traditional model) assigned to the DIV element. I have prepared version 4.6.10 where this problems should be fixed. Please download latest version and try. Hope now everything will be fine.

  17. When i click and drag rows with IE instead of the row dragging with the mouse it just appears at the bottom of the table, this works in FF and Chrome but not in IE.

    What would be the cause of this?

  18. @Dave – In which IE version you have a problem? REDIPS.drag is tested to work in IE8+ FF4+, Chrome10+, Opera11+ and Safari5+. Can you please send more details about your browser version – thanks!

Leave a Comment