Drag and Drop table content with JavaScript

Content of HTML table cells can be dragged to another cell or another table. It isn’t difficult to define onMouseMove handler and change top / left element styles to move the object. In case with tables, you will have to determine somehow target cell. Attaching onMouseOver handler on TD elements will not work, because browser doesn’t fire events to the elements below the dragged object.

Anyway, after taking care of the current scroll position and calculating TD positions, REDIPS.drag should work in recent major browsers like Google Chrome, Firefox, Safari, Internet Explorer, Opera and mobile devices as well. Click on image below, will open live demo where you can drag green, blue or orange bordered DIV elements, change properties (radio button and check-boxes) and click on “Save” button.

Download latest version redips2.tar.gz


REDIPS.drag example01

In this example “Save” button will scan table content, create query string and send to PHP page. Demo shows how to collect content and accept parameters on the server side. More about accepting parameters you can read at Reading multiple parameters in PHP. “Clone” elements (orange in this demo) will be duplicated first because of “redips-clone” keyword contained in class name. If you drop object on cell named “Trash”, object will be deleted from the table (with or without confirmation). Library has built in autoscroll and option to forbid landing to non empty cells or cells named with class “redips-mark”. Table can contain rowspan / colspan TDs and different background color for every cell.

Here are minimal steps to enable content dragging in table:

  • put <script type=”text/javascript” src=”redips-drag-min.js”></script> to the head section
  • initialize REDIPS.drag library: <body onload=”REDIPS.drag.init()”>
  • place table(s) inside <div id=”redips-drag”> to enable content dragging
  • place <div class=”redips-drag”>Hello World</div> to the table cell

Other features of REDIPS.drag library:

  • methods and data structure are defined in namespace (easier integration with other JS frameworks)
  • all JavaScript code is checked with ESLint
  • REDIPS.drag documentation generated with JsDoc Toolkit
  • drag and drop table rows
  • movable DIV element can contain other HTML code (images, forms, tables …)
  • forbidding or allowing TDs marked with class name “redips-mark”
  • option to define exceptions and allow dropping certain DIV elements to the marked cell
  • option to define single content cell on the table declared with “multiple” drop option
  • cloning
    • for unlimited cloning add “redips-clone” class name to the DIV object
      <div class=”redips-drag redips-clone”>Hello World</div>
    • to limit cloning and transform last object to the ordinary movable object add ‘climit1_X’ class name
      <div class=”redips-drag redips-clone climit1_4″>Hello World</div>
    • to limit cloning and transform last object to immovable object add ‘climit2_X’ class name
      <div class=”redips-drag redips-clone climit2_4″>Hello World</div>
    • where X is integer and defines number of cloned elements (in previous examples, each climit will allow only 4 cloned elements)
  • unlimited nested tables support
  • dropping objects only to empty cells
  • switch cell content
  • switching cell content continuously
  • overwrite TD content with dropped element
  • shift table content
  • table cell with “redips-trash” class name becomes trashcan
  • enabled handlers to place custom code on events: changed, clicked, cloned, clonedDropped, clonedEnd1, clonedEnd2, dblClicked, deleted, dropped, droppedBefore, finish, moved, notCloned, notMoved, shiftOverflow, relocateBefore, relocateAfter, relocateEnd, rowChanged, rowClicked, rowCloned, rowDeleted, rowDropped, rowDroppedBefore, rowDroppedSource, rowMoved, rowNotCloned, rowNotMoved, rowUndeleted, switched and undeleted
  • deleting cloned DIV if the cloned DIV is dragged outside of any table
  • enabling / disabling dragging
  • animation (move element/row to the destination cell/row)
  • added support for touch devices (touchstart, touchmove, touchend)

How REDIPS.drag works?

Script will search for DIV elements (with class name “redips-drag”) inside tables closed in <div id=”redips-drag”> and attach onMouseDown event handler. When user clicks with left mouse button on DIV element, onMouseMove and onMouseUp handlers will be attached to the document level.

While dragging DIV element, script changes its “left” and “top” styles. This is function of the onMouseMove handler. When user releases left mouse button, onMouseUp event handler will unlink onMouseMove and onMouseUp event handlers. This way, browser will listen and process mousemove events only when DIV element is dragged.

As I mentioned, onMouseDown is defined on the elements you want to drag. Elements beneath the dragged object will not be able to catch onMouseOver event. Why? Because you are dragging object and that object only can catch the onMouseOver event.

So, to detect destination table cells, script calculates all cell coordinates (with scroll page offset) and store them to the array. Array is searched inside onMouseMove handler and after left mouse button is released, DIV will drop to the current (highlighted) table cell.

In redips2.tar.gz package you will find many examples including example of how to save/recall table using PHP and MySQL. Package also contains and redips-drag-min.js – a compressed version of REDIPS.drag library (compressed with Google Closure Compiler).

Happy dragging and dropping!

1,195 thoughts on “Drag and Drop table content with JavaScript”

  1. Perhaps this needs to be be highlighted in the documentation.
    When creating a row to drag, there must be a TD element with a class=”rowhandler” if this is not present, then the library will create an empty row with no data when you drag and drop.
    I don’t know if this is by design or not…
    Its easy to replicate, simply create a table with basic tr and TD elements, create a TD element with class=”drag row” and then run the init script. You will be able to drag the row, but on drop it will then create an empty row with TD elements that are empty.

  2. @James Ostrowick – In REDIPS.drag documentation – Appendix A is specified how to set a row drag handler:

    http://www.redips.net/javascript/redips-drag-documentation-appendix-a/#redips_rowhandler

    Please pay attention that TD should have class=”rowhandler” (to disable other DIV elements to be able to drop in) and inside should be a DIV element with class=”drag row”.

    With “Appendix A” page, I tried to cover all keywords (mostly class names) that are important for this lib. There you will find a keyword list and examples that should be useful when using REDIPS.drag library.

    Thanks!

  3. i think it will be very helfull (especially for me) if there are the video about step by step to construct it (cherish)

  4. Hi Darko,
    at first thanks for this great script.
    the script works perfect, but in “chrome mobile” for android the touch event doesnt work?
    regards
    Apo

  5. @ryzky – I will try to prepare HOWTO video in the next period. Thanks for advice.

    @apo – REDIPS.drag is primarily developed for desktop browsers. I made some improvements for Mobile devices but there is still need some work/testing to do. Currently a known bug related to wrong calculation TD exists on mobile devices when page is zoomed. Hope future package releases will be more polished for browsers on Android / iPhone. Thank you for understanding.

  6. Hi dbunic
    I am using 2 of your scripts: drag-and-drop & table(merge/split).
    unfortunately, I found that I can not simply put them together.
    I have tried but if these 2 scripts both exist, redips.init will overwrite REDIPS.drag.init().
    Is there any suggestion for me?

    Thanks again for your great scripts.

  7. @Brad – REDIPS.drag and REDIPS.table should be possible to use in the same time. Please see example 24 “Table editor” (a working demo that uses both libraries). Source code is placed in example24/script.js file. Hope this will be helpful.

  8. Hi,

    I am trying to incorporate your drag and drop javascript into my website, but I am using a magnify and shrink javascript to change the size of the table. The boxOffset in your drag routine doesn’t change the offsets though.

    Is there a magnifier that works with your routines?

    Thanks,

    George

  9. dbunic i need your help.. how can i save position after drag and drop into sql database?

  10. @George – As I wrote in a comment above, REDIPS.drag is primarily written for desktop browsers. For phones and tables it will work as long as zooming is disabled with the following meta line:

    <meta name="viewport" content="width=device-width, user-scalable=no"/>
    

    In the next period I will try to see where is the problem with offset calculation and why page zooming doesn’t affect object position.

    @Shakirin – If you want to save DIV positions to the database, please see example03: School timetable. saveContent() method will scan all DIV elements in table and return result as classic query string or JSON format. You will have to accept this parameter on the server side and write it to the database. To restore table content, use PHP/ASPX or any other script and dynamically create HTML table with DIV elements. All this can be found in example03 folder inside redips2.tar.gz package.

  11. Dear Sir,

    I liked this lib, I went through all the examples. As the name indicates “drag and drop” it is very nice, it is very fast. But I could not find the examples like spread-sheet, “copy-cut-paste” for group of cells. It has row drag and drop but not the multipal cell drag drop. It will be very helpful for me. I am triying to develop some thing like spread sheet using this lib.

    Thanks,
    snk.

  12. Hi, from the example above, when a cell is dragged over the table all the cells for which dropping is allowed are highlighted in orange. So far so good. However, if I continue my dragging going over some forbidden cells (for example, the first row of the first table: “you can not drop here”), the last allowed cell remains highlighted and if I finally drop my dragged cell over some forbidden one it is dropped back into this last highlighted cell, wherever it was. I’m not sure this is what a user would like to have, in general. Is it possible to force the dragged cell to go back to its original position when drop fails instead to be put into a cell which only depends on the path followed by the mouse during dragging?

    thanks

    Davide

  13. dear dbunic, I’m using your library for a fairly complex web site and I’ve noticed that by choosing dropMode=’switch’ the option rd.hover.colorTd works well, colouring the background of the cells hovered by the dragged one. However, if I choose dropMode=’switch’ it seems that rd.hover.colorTd does not work anymore. I only changed the option dropMode, nothing else. Is there anything I have to take into account when changing option from ‘switching’ to ‘switch’? I thought the difference between the two was only on drop, and nothing should change while dragging but it seems this is not true, at least as far as colorTd is concerned.

    thanks

    Davide

  14. Hi great script, I have the following case, I have 6 tables into the same div and all of them can drag and drop between each other, but I want that all tables can drop rows only into one of the tables and not between them. How can I restrict the drop function only to one table out of the six?

  15. i have tried working in e.g. #21 the simple one it great but it wasn’t supported on the mobile devices that i have tried on

    is there any way i can make it work on mobiles ??

  16. This is a really useful example. But I am looking to make those Divs stretchable something we look in scheduler where we have drag and drop with re sizable. No doubt this one was of great help for me but please can you help me to achieve re-sizing of divs across html cells ??

  17. Dear Sir,

    I wish to add two things to the script but can’t seem to work it out.
    First after dropping the div I would like to auto save so bypassing having to click on save.

    The second is i woud to pass the value of the name tag of the dropped DIV.
    can i do something like:

    var yeid = REDIPS.drag.current_cell.getAttribute(‘name’);
    and;
    window.open(‘multiple-parameters.php?’ + table_content + ‘_’ + yeid);

    Any advice would be much appreciated.

    Thanks,

    Frits

Leave a Comment