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. @pascal – myhandler_row_moved() is called in a moment when row is started to move. Instead of calling alert(), please try with a simple function to display a message. For example:

    // display a message in a moment when table row is moved
    REDIPS.drag.myhandler_row_moved = function () {
    	document.getElementById('message').innerHTML = 'Row moved';
    };
    

    You will also have to create a <div id=”message”></div> to see the message. The same can be done with other event handlers. alert() can bring some mess because you are starting to drag a row and in that moment popup appears and take over control. I assume that taking control with appearing popup causes the problem.

  2. thx,

    I have another problem :
    I wan’t to use your script in a page where the rows haven’t the same height. But I’ve seen in the css file that your script works only if all the rows have the same height.
    Is there a way ?

    Thank you

  3. @pascal – REDIPS.drag should work with table rows of different height. If you drop several DIV objects (in this demo) to the same table cell, then you will get higher row. This table row will behave as other table rows no matter of its height. Anyway, if you have example to show described problem, I would try to help. Cheers!

  4. I have a problem:
    My situation is similar to your example but having more tables. I just want the rows can be drag-n-drop within table, but not across tables.

    I have tried using div(drag1, drag2, … ) to enclose each table, and use div “drag” as the outermost div to enclose all the tables. It works ok if all the tables can be shown in IE. But if the IE vertical scrollbar orccur, the coordination of the mini table is incorrect.

    How can I do to solve the problem?

    Thanks.

  5. @Dino – Instead of DIV (DIV1, DIV2 …) structure, you can create seaprated DIV containers like in example08. Please download latest redips2.tar.gz package (version 4.1.1 – bug fixing) and close each table in its own DIV drag container. For example:

    <div id="drag1">
      <table>
        ...
        ...
      </table>
    </div>
    
    <div id="drag2">
      <table>
        ...
        ...
      </table>
    </div>
    
    ...
    ...
    

    … and finally this drag containers should be initialized:

    // reference to the REDIPS.drag
    var rd = REDIPS.drag;
    // DIV container initialization
    rd.init('drag1');
    rd.init('drag2');
    ...
    

    Hope this will help.
    Cheers!

  6. Hi dbunic,

    What I did was just you say in your reply that lead to my problem. In IE7, It works OK if all the tables can be shown in a view. But if the height of the page is longer than the IE browser, the coordination of the mini table is incorrect. But it works OK in Firefox all the way. Any other way to fix the problem ? Thanks.

  7. @Dino – Can you show me the page (or if you prefere zip and send)? The problem might be related to the CSS or maybe HTML page doesn’t have defined valid DOCTYPE or maybe REDIPS.drag lib has to be polished … It will be much easier if I can peek to the problematic page. Thanks!

  8. Very nice library. I’ve just started playing with it and so far it looks like it’ll save me a LOT of time. Thanks Darko!

    A couple things I noticed. I’m testing it in IE7 and I see one error when I get down to the last row in the upper table. The line of code
    color = ‘grey’;

    in “function last_row()” errors out since IE doesn’t appear to know this color. It likes:

    color = ‘Gray’;

    just fine though!

    Anyway, thanks for the code. the library looks nice but even if I don’t use it, I’ll be learning a lot from it!

    Regards,
    Greg

  9. I ran into another issue when dropping the library into a real life project. Somewhere there’s a conflict. When the row starts dragging, the drag row shows up below the source table and doesn’t track the mouse. I’ve been reading posts since I’m sure others have run into this before. Do you know why this might happen?

  10. One other thing I noticed. At present the rows behavior is hard coded to use the colors in the example for the drag div. It would be nice if you could pick up what these values are set to at run time. As an example, there’s a link below to the appearance I’ve hacked the code to use instead. The images on the left hand side are being used instead of the blue box. Until I hacked on redips-drag.js though, it kept putting in the border and background. I don’t really like hacking it though since I’d like to keep up to date with your progress in the future.

    http://img696.imageshack.us/img696/2907/draganddrop.gif

  11. OK, my issue with the drag was not having the XHTML declaration. I added that in and things are running fine now.

    A little more detail. The lines I had to change in redips-drag.js were 99 and 100 to make the borders match what was needed:

    border = 'solid',           // (string) border style for enabled element
    border_disabled = 'dotted', // (string) border style for disabled element
    

    The background color issue was actually in the example specific js file.

  12. @Greg Palmer – I will fix color to Grey instead of grey – thanks (I thought it’s not a case sensitive name). I’m glad you solve the problem regarding dragging table row. If doctype declaration is not defined, then browser will probably switch to the quirks mode and dragging will not function properly.

    Styles for border and border_disabled are exposed as public parameters so they can be defined after REDIPS.drag initialization. For example:

    // reference to the REDIPS.drag library
    var rd = REDIPS.drag;
    // initialization
    rd.init();
    // set border style for enabled element
    rd.border = 'none';
    // set border for disabled element (default is dotted)
    rd.border_disabled = 'none';
    

    I hope these properties are what you’re looking for. Cheers!

  13. Beautiful dbunic, I don’t know if the color is case sensitive, I think it’s the British English “grey” versus American English “gray.” Kind of curious since most platforms support both variants.

    Thanks much for pointing out those properties, I completely missed them, and yes, they were exactly what I was looking for!

  14. I gave it a try, it works great!

    One deviation from your example above was that I had to set the border and border_disabled properties before the init call. When they were set after the init call, the initial rendering displayed a border which disappearred once I dragged a row.

    So everything’s working just the way I want now. Bless you for making this library available!

  15. @Greg Palmer – You are right, I made a typo it should be gray (I fixed example15). Here is a snippet from W3C Recommendation – 4.1. Basic color keywords:

    The list of basic color keywords is: aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, and yellow. The color names are case-insensitive.

    And regarding border and border_disabled properties. Your comment is correct. This properties should go before calling rd.init() because init method calls enable_drag method and there is a code which uses defined styles for element borders. So the lines should be:

    // reference to the REDIPS.drag library
    var rd = REDIPS.drag;
    // set border style for enabled element
    rd.border = 'none';
    // set border for disabled element (default is dotted)
    rd.border_disabled = 'none';
    // initialization (border and border_disabled should go before initialization)
    rd.init();
    

    Thank you very much for commenting and using REDIPS.drag library.
    Cheers!

    PS in a week or two I will release new version with animation feature – a new method to move element with certain id to the desired table cell. It could be useful for nodeJS … ;)

  16. Hi ,

    Thank you for providing this example, wanted this feature to implement in our application.

    I have tried this example to have it in my jsp. I see all the .js and .css files are loading. But when I drag the rows I get below java script errors. Am unable to understand the reason of the error. The same thing is working if I use the example given in the downloads.

    Thanks in advance for the help.

    msg is undefined
    msg.innerHTML = ‘Row clicked’; script.js (line 63)

    msg is undefined
    msg.innerHTML = ‘Row moved’; script.js (line 79)

    el is null
    el.redips_dragrow_id=id;return el;}};r…le_mini===undefined){table_mini=obj;}
    redips…-min.js (line 35)
    el is null

  17. Hello,
    I´ve two questions:
    Is there an option to sort a table like this with BUTTONS?
    For example:

    Cell 1

    Cell 2

    When clicking a button now, it moves the cell with the clicked button on the 1st position of the row!
    Is that possible or easy to do? Because i´ve a table with more than 300 entries an drag+dop is necessary, but sometimes it takes very long!

    And 2nd:
    Is there an easy way to locate the current position of a cell in the table? Col-Row output for example?
    Or a live-view of the position?

    I´m sorry for all these questions! :D

    Thanks, Fidelis

  18. Thanks for the beautiful library. Just got one question, I was wondering how can i do such operation

    $('#hdindex1').val($(this).attr("id"));
    

    through one the events for instance i would like to add value of id which is one of the fields of the row in the table when
    (rd.myhandler_row_dropped = function () { )
    is fired
    I appreciate if you give the clue

Leave a Comment