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)
- for unlimited cloning add “redips-clone” class name to the DIV object
- 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!
i Darko your latest update are wonderful …i wanted to know
if you are planing to do columns drag and drop soon?
10x oded
Hi, is there posibility to have for example table 10(rows) x 10(columns). I want to drag on first row on second cell and do drag to 5th cell . The result will be, that in first row columns 2,3,4,5 will have some content. I mean option that a can fill content in one row by dragging, not only switching content or copy content, but whole the row or some part of row will be filled by some content.
Lukas
@oded – With enabling row dragging, the code is mostly prepared for column dragging. Row cloning compared to column cloning is easier because JavaScript has deleteRow and insertRow functions. Row cloning is in my plans and I hope it will be finished in next several months. It all depends about my free time.
@Lukas – REDIPS.drag has option to drag table rows – if this was your question. Please see Drag and drop table rows with JavaScript post. If you want to move more DIV elements at once, maybe Example 12: Select and move more elements will be interesting for you.
@dbunic Sorry, just seeing your response. I think I got pretty much all of the default functionality working, I just had some stuff set up wrong. Some of my custom changes might not be working, but that is obviously on me. :)
However, I didn’t think I changed redips-drag.js at all, but after I did my development and switched it to use redips-drag-min.js for file size, some of my stuff no longer worked – including the cloned items not deleting. So I compared my file to the original, and I have 15 differences that make it work correctly. I can send you my file if you want, but I don’t see an email address anywhere.
@Bryan – I will be grateful if you can show complete example (if is possible) to demonstrate needed changes in redips-drag.js source. You can find my email on About page. And of course, I’m glad you customized REDIPS.drag library for your needs. Cheers!
a new question!
in ie,
js like :
this ddd cannot drag!
The question should be this:
I have a table,the aaa can drag after REDIPS.drag.init();
now, I want to add a new cell and make it dragged,so I REDIPS.drag.init(); again!
It works in FF,but not in IE.
please help!
First of all, thanks for your work, it looks really amazing!
I was wondering if the following is possible:
One table with, let’s say, 20 elements, each of one of 4 categories, say A, B, C, D (some element belongs to category A, another belongs to category B etc.)
Another table with particular cells accepting only elements from a specified category, say row 1 col 1 accepts only elements from category A, row 1 col 2 – elements from category B and so forth.
Could you provide some clues on whether it is possible or where to look to implement it?
Thanks in advance!
@zhaowx – After table is dynamically changed, calling REDIPS.init() should scan all tables within <div id=”drag”> and dragging in new rows should work. Which IE is problematic (IE version)? If you have online example / demo to show, it will be much easier to identify possible bug in REDIPS.drag library.
@tomee – Target cells can be marked with class names mark and only to accept specified DIV elements. With cloned elements is a bit complicated because dropping rules should apply after DIV element is cloned. If your example doesn’t include cloning, then you have clean situation. Please take a look to the following examples for illustration:
Example 2: Green and orange elements
Example 7: A B C D
Wonderful work!
Is it possible to handle touchstart, touched and touchmove event handlers to make it work on touch devices ? Can this functionality be included in the default package ?
Thank you for your hard work.
@Alex – REDIPS.drag listens mouse events on DIV objects: onmousedown, mousemove and mouseup. I think there should not be a problem to add touchstart, touchmove and touchend as well. Thank you for pointing to touch events and I will try to improve REDIPS.drag library to work with touch devices. Stay tuned ;)
Darko, very beautiful library, does it have some option like jQuery UI sortable’s “distance” – it starts dragging not immediately, but after the first X pixels of the drag. It will be very useful with links inside the cell – then you can remove the nodrag limitation over the links and inputs inside the table.
From the UI documentation: “Tolerance, in pixels, for when sorting should start. If specified, sorting will not start until after mouse is dragged beyond distance. Can be used to allow for clicks on elements within a handle.”
Greets from Bulgaria
Looks like the drag and drop of rows (example 9) doesn’t work when you have table header tags (). Guess this might be the case with all examples. Is there a workaround for the use of TH tags at the top of tables, which should be the case anyway in most markup?
@todorov – I agree that sortable distance can be very useful as some tolerance to prevent instant element switching. Unfortunately, REDIPS.drag currently doesn’t have such nice feature. But did you try shift drop option which can be more suitable for sorting elements in table. Please see example14 which demonstrates difference between switching and shift drop option. Post JavaScript drag and drop plus content shift explains “shift” option with more details.
Thank you for your comment.
@Jeremy – TH and dragging rows should work. If you have prepared offline example, just gzip it and attach to mail. Anyway, I will send you modified example15 where you will see TH cells in upper table. You can modify that source and send me back so we can discuss further. Thanks!
Very good job!
I was wondering if it was possible to change the drag and drop behaviour with some parameters: In your examples, when you Drag&Drop an item to a container with something inside, it adds the item under the other items, even if the container is very large. Is it possible to give a parameter like top, bottom, left, right without modifying redips-drag.js to give a different behaviour for a cell?
Ex: if I want to select some items from a table and drag them to an horizontal panel?
Thank you!
@Gaël – REDIPS.drag doesn’t have option for arranging dropped DIV elements inside table cells. But if you have wide enough table cell for horizontal panel, just add float:left style to the DIV elements
and they will be placed side by side.
Thanks for this awesome source. I would like to know if its possible to have only a border of each td draggable and not the inner content, Im would like to embed media into a td but cannot play the media with the current td dragging.
Thank you for your answer! So with some few new function, I should be able to place items by sorting them according to the X,Y mouse position in the panel too. Thank you for you tip! Gaël