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. Hi,
    it appears that REDIPS lib is not specified when page is loaded. Please check your HEAD section in HTML page.

  2. This is my code in which i have putted all the REDIPS library in HTML page as below,

    but still I am getting error “Uncaught ReferenceError: REDIPS is not defined
    at onload (13:1)”

    How to resolve this error ?

  3. Hi,

    I was looking for how to save table content(example01) to MySQL and how to get the same table back by the parameters from MySQL. So, to keep save and retrive the positions of content in table.

    Thanks

  4. Hi,
    I was looking for a tool like this for hours and suddenly I stumbled upon this page. The tool seems great, but it doesn’t have one feature to make it officially a killer asset: there should be a way to merge selected neighboring cells and split them back if needed.
    Thanks for your great contribution!
    Cheers,
    Jonathan

  5. Hi

    I am creating a dragable and cloneable table — works perfectly. I am using hard coded table elements, and . All work well.

    However, if I save the table – only the hardcoded content saves — the only saves the default text, and the seems to only save “” (empty).

    Not sure what to check or what I might need to change — any pointers?

    Cheers
    Glen

  6. In my comment above it stripped out , and it should read:

    I am creating a dragable and cloneable table — works perfectly. I am using hard coded table elements, and text inputs such as and .

    However, if I save the table – only the hardcoded content saves the only saves the default text, and the seems to only save “” (empty).

    Not sure what to check or what I might need to change — any pointers?

    Sorry for the duplication

  7. Hi Glen,
    rd.saveContent() method reads DIV innerText property and that might be the reason why some texts (from input elements) are empty.

    I will suggest to copy saveContent() method (from redips-drag-source.js) to your script.js and add/modify functionality for saving additional data (from other elements).

  8. Hi @dbunic

    Hope you’re fine there
    I discovered your drag and drop library which is too good

    i was stuck in issue where i could not able allocate single single Item in multiple td(table data)

    suppose item-1 height is 20
    then it takes two vertical cells in table and set that

    suppose if item-2 height is 50
    then it takes five vertical cells in table and set that

    this is demo link which i am working on : https://jsfiddle.net/vijaysolankiii/tyrm6uv1/5/

    Hope you understand this

    Thanks

  9. Hi @dbunic
    Hope you are doing fine there i discovered your drag and drop library which is so amazing and helpful

    but i was stuck in minor issue can you please help me out

    here is issue

    when i have large item in table data (td) so it acquire space vertically in table
    like image have 40px height then it occupie two table cells vertically

    othere >> image have 70px height then it occupie three table cells vertically

    Hope you understand
    here is link of my current code
    https://jsfiddle.net/vijaysolankiii/tyrm6uv1/12/

    Thanks in Advance

  10. Hi Vijay,
    whole library was built on top of HTML table raster as a base. So, it’s not possible for a single DIV element to occupy few TD at once. However there is a way to merge TD cells first (when HTML table is generated or dynamically) and then DIV element can be dropped to this bigger TD.

    Anyway, in the following jsFiddle example you can manually mark two TD cells (by clicking on them) that are near to each other and then click on “Merge” button at the top. This will dynamically merge TD cells. Now you will be able to drop DIV element to this merged cell. This example uses one more lib to merge/split TD cells.

    https://jsfiddle.net/dbunic/cexn1wvn/94/

    So, there is maybe option to create JS code inside event handler to automatically merge TD cells before big DIV element is dropped and then after is moved out to split as it was before … but that would be out of the REDIPS.drag lib scope and probably to complicated.

  11. Issue 1: Have a table inside srollabe div. Scroll to the right and dragging a cell marks the target cell far to the left from cursor.

    Issue 2: I scale the container div (style.transform=”scale(0.6)”) and dragging the targe a cell marks the target cell far to the left from cursor.

    Any solution? Thanks

Leave a Comment