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. @Satya – msg is reference to the DIV element where messages like Row moved, Row dropped are displayed. If you don’t need “messages” then delete lines regarding msg variable. Errors that you mention in comment, maybe indicate some initialization problem. My advice is to start from working example and then cut out unecessary code in step by step.

    @Fidels – Table cells and table rows can be moved to the target location with move_object() public method. Inside redips2.tar.gz I prepared example18 “Simple element animation / row” to demonstrate how to move table elements and table rows. You can also view more complex demo Drag and drop table content plus animation

    P.S.
    You just post the code and I will do the rest ;)

    @maani – In a moment of dropping table row, myhandler_row_dropped() event handler is fired. Here is example of how to retrieve id of row (actually id of DIV element with class=”drag row”). I also added example of how to retrieve id of dropped element.

    // reference to the REDIPS.drag library
    var rd = REDIPS.drag;
    
    // element dropped
    rd.myhandler_dropped = function () {
      // id of dropped element
      var row_id = rd.obj.id;
    }
    
    // row dropped
    rd.myhandler_row_dropped = function () {
      // id of DIV element with class="drag row"
      var row_id = rd.obj.redips_dragrow_id;
    }
    

    With id of row handler <div id=”row1″ class=”drag row”> you can go up through the DOM hierarcy to find the row if you like.

    // define start element
    var el = rd.obj
    // loop up until TR element is found
    while (el && el.nodeName !== 'TR') {
      el = el.parentNode;
    }
    
  2. I have a drag and drop table that I perform a “search” on. This search hides (tr.style.display=’none’) rows that do not contain a td with part of the search word. After the search is performed I receive an error in the drag and drop code. the error is this:
    ‘undefined’ is not an object (evaluating ‘tables[table].rows’)

    I have narrowed it down to line 1368 in version 4.3.5.
    The problem is that “table” is null. In the above code where table is set table_old is also null. However in the do while loop ending on line 1345 the value for table is correct (77 of 78 in tables array)

    Can you please help me figure this out?
    Thanks!

  3. @Chris – I made modification in set_trc() and calculate_cells() to support hidden table rows. Please download latest redips2.tar.gz (version 4.3.6) and try your example. Hope this will solve the problem.
    Cheers!

  4. hi..thank you a lot for this tool that proved very helpful in my application
    my question is about cloning rows..i tried to add clone class to the tag but it gave me some unwanted results, and the same thing happened when i tried clone_shiftKey..all that i want is when i move a row it will be cloned in the same table
    thank you in advance

  5. @nabil – I’m sorry, but current version of REDIPS.drag doesn’t support row cloning. Fortunately, code is prepared and that will be added soon in future release. Thanks!

  6. Hi.. Iam using the drag and drop example which you have provided. It’s great.. Iam using the function rd.myhandler_dropped_before. I am checking some conditions in it.. If the conditions are not true, then i have to cancel the drop.. Can u pls tell me how to cancel the function or to stop the object from being dropped..
    Thanks..

  7. @Nisha – This feature is added in new lib release. Please download latest redips2.tar.gz package. To cancel element drop, just return boolean “false” from myhandler_dropped_before() event handler.

  8. hi

    It’s really great plugin, i need help for following scenario. I have created different tables as per sequence mention into database e.g. 5 tasks (rows) under one sequence. its work perfectly. but when i create new table and add to drag div using jquery, i can not drop row to newly created table. any one know how to do this?
    Thanks…

  9. @Parimal – After table is added to the drag area <div id=”drag”> you will have to call REDIPS.drag.init() or rd.init() (if you set reference to the REDIPS.drag lib) to initialize newly added table.

  10. Hi Darko, thanks for sharing your sophisticated work.
    Just wondering if you can advise me how to achieve the following:
    I would like to have 2 tables, both sortable. The first table would be a “content holder” from which would be possible only to clone/copy content to the second table. The second table would be kind of “whish list”, initially empty with an option to delete content from. It would not be possible to copy the same content from the first table more than once until that content is deleted from the second table.

    Thanks

    p.s. i know this is a lot to ask for, so please feel free to ignore it if you find it the same :)

  11. Hi thanks for reply, but i am executing following code on add new sequence button. still doesn’t work drag and drop into new table.

    var newseq = parseInt($("#drag table:last").attr("id")) + 1;
               
    $("").appendTo($("#drag"));
    REDIPS.drag.init();
    
  12. @darije – Features like cloning and deleting table rows will be included in REDIPS.drag very soon. I already have it prepared in my working version, and it will be published next week. Please wait a few days. Thanks!

    @Parimal – Hmm, it should work unless something else causing eventual conflict. I need a closer look for analyse. Do you have this example online (or can you prepare static page and send) to show me the problem?

  13. Thanks a lot Darko!
    (it’s always a kind of funny to practice english with fellow croatian :)

  14. Hi

    Thanks for reply, now its working after making following changes but I am not sure is it good practice or not?
    Here I am adding blank row with class name deleteme.

    $("#redips_clone").before($(""));
    $("table tr.deleteme td").text("new sequence #" + newseq + ". Drag row here to add new sequence");
    REDIPS.drag.init();
    
    
    // here I am removing row with class name 'deleteme' as
    // we don't need blank row any more int this table
    
    rd.myhandler_row_dropped = function () {
        // display message
        //msg.innerHTML = 'Row dropped';
    
        rowdropped($(selector));
    
        $("table tr.deleteme").remove()
    };
    
  15. @darije – Cloning and deleting table rows is now implemented in new REDIPS.drag version – 4.5.0+ Inside redips2.tar.gz package you will find example20 where table rows can be cloned with SHIFT key (as well as DIV elements inside tables). Cloning table row is also possible with “clone” class name. For example, if div element contains classes like <div class=”drag row clone”> then this row will have clone option by default. If you will have any further questions, don’t hesitate to contact me so we can discuss on croatian ;)

    @Parimal – I didn’t realize that your table was without table cells / rows. To properly initialize tables, table shouldn’t be “empty” – it should contain at least one row (with table cells). Anyway, please download latest redips2.tar.gz package and take a look at the example20. Second table contains one “empty” row – this is special row marked as “empty”. Inside script.js you will find the following line:

    // mark row in second table as empty
    rd.row_empty('tbl2', 1);
    

    Hope this is what you want to achieve …

  16. hello dbunic, great work!

    I have implemented a button that inserts a blank table row at the bottom of my table.
    The new rows will support draggable divs, however I run into a problem when I go to click “save” and request the div locations.

    Is it possible to combine a “new row” button, with row cloning, and a “save” button?

  17. i figured out that the save function from example 1’s script.js works well with cloned rows.

    Here is a snippet i am working with that will insert a new row based on whatever the first row is…, but the new rows are not draggable yet

    my goal for the button is to insert a new blank row which is draggable. i think there is a better way but this is a work in progress

    function addRow(tableID) {
        var table = document.getElementById(tableID);
        var rowCount = table.rows.length;
        var row = table.insertRow(rowCount);
        var colCount = table.rows[0].cells.length;
        for(var i=0; i<colCount; i++) {
            var newcell = row.insertCell(i);
            newcell.innerHTML = table.rows[0].cells[i].innerHTML;
        }
    }
    

    drop

    and

    table

    Trash

Leave a Comment