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!
Do you have a simple overview for save/recall for example05?
What would the SQL table look like? Maybe I could get an idea of how to save/recall.
I’ve written a lot of PHP, but much less complex than config.php and save.php.
e.g. I’ve not used the $_REQUEST[‘p’]; variable before.
i wanted to know if this project of your support chrom?
Hello. interested in such a moment.
divs
A name = drag1
2 name = drag2
in drag2 table items normally carried and all is well
but could not find a way how I keep track of moving objects from drag2 in drag1
with the object should not be stored in a drag1 just have to do ie drag1 not Use draganddrop
should be executed after alert (‘drop div id;’ + rd.obj_old.id);
sorry for my bad language
@Nick – I will try to prepare more examples with save/recall funcionallity. Thank you for your suggestion. And answer regarding example05 – This example contains two DIV scrollable containers. Each contains HTML table. Maybe you can add another attribute to the existing database table to somehow define where DIV element belongs (to first or second container). This will be a small modification in save.php with additional parameter (perhaps container ID).
@Ian Tresman – Unfortunately, I’m not so familiar with Drupal CMS to embed REDIPS.drag as a Drupal module. But if someone has a goodwill to start, I will help.
@Kevin – Yes this is possible. Just add this two lines to your code:
The key is to add onmousedown event listener to the dynamically created DIV element – and that’s why rd.init() method is called at the end.
@Mohan – I’m just curious about dimensions of your HTML table? Does lag effect appear in any browser? If you have online example to show me the problem, I will gladly peek …
@oded – Curently it is not possible to drag table columns – only table rows. But as REDIPS.drag evolved from dragging table content to dragging rows, hope one of next releases will have option to drag table columns as well. And regarding project support – yes, I’m developing and supporting REDIPS.drag library. It is build from the scratch and I work on library in my spare time. My tools are Linux, Eclipse, JSLint and five browsers – FF, IE, Chrome, Opera and Safari – enough for fun ;)
@Egor – If I understood well, drag1 and drag2 are tables in your example. Each table contains DIV elements. Is your question how to detect a case when DIV element from TABLE id=”drag2″ is dropped to the TABLE id=”drag1″? And how to forbid dragging out elements from first table (elements from first table can be dragged only inside table itself – can’t go out)?
Hi Darko,
Thanks for making your code available. I really like how easy it is to implement on top of a standard table. Top marks!!
I’m just wondering how a user could resize a cell to cover one or more rows?
ie. Example 3, would allow a subject to cover 8 & 9am without having to have 2 table cells.
Hi Dbunic, Thanks for the codes! It really helped me a lot for my work! Cheers!
@Adam – Table content (in this case DIV elements) can be placed only to one table cell. DIV element can’t cover two cells. Anyway, after googling a while, I found many examples of how to merge table cell dynamically. So, with some JS logic you can merge table cells and rescan table layout with calling REDIPS.drag.init() method. init() method will recreate internal grid array with table cells coordinates and dimensions. This way, newly merged table cell will become visible to the REDIPS.drag lib.
@Kevin – I’m glad I could help.
Just the thing I was looking for… Thanks a ton!
Thanks a lot for what you did !
But what about a DoubleClick handler ? : )
@Peeer – Fortunately, latest REDIPS.drag version has built in myhandler_dblclicked() event handler. ondblclick event is attached to every DIV object inside table. Hope this is what you’re looking for.
how to get the config.php? because i already edit the school timetable with 3 type of function(subject, room & teacher) where i could save it but couldn’t retrieve it after open it again for the other two type of function(room & teacher)..pls help me
This is awesome !! Congrats and thanks !
Hi Nick,
I’m using your script with 6 DIV containers. I’m looking to save each container data at the same time using one button (save()). However when I’m using the save function it is only saving the DIV container that I have last clicked on. How would I modify Save_content, so that it does all DIV containers on the page at once (each table and DIV container has an id).
I’ve tried to work it out myself, but my understanding of javascript is poor.
@arif – config.php mentioned in a comment above is from example03 “School timetable”. Just download redips2.tar.gz to obtain redips-drag.js source code and all examples build on top of REDIPS.drag library.
@Duane – If save_content() is called without any parameter then it will scan all tables inside DIV container – no matter which table is clicked. On the other hand, if you have separate DIV containers then each DIV container is closed inside its own context and they are initialized separately (means that table index start from 0 for each DIV container). Here is example of how to prepare URL for separate table containers at once:
Before calling save_content() it is needed to change context with init() … This code will create URL for all tables. You can distinguish DIV container by DIV id because DIV element from first container can not be dropped to other DIV containers. Actually, id of DIV container can be incorporated into id of DIV element. Hope this answer will help you.
Hi Dbunic, what a brilliant script!
Say I was only using one column in a table with multiple rows, is it possible to create a function that adds a new item on a new row, and when an item is dragged to trash the row it was on is also removed?
Thanks Dbunic
Hello,
I want to use your script to program a chess board.
Is it possible to know the last move ?
Is it posible to move easy a piece by a javascript function ?
Thanks a lot !
Absolutely brilliant!!! Great job.
I just wanted to check if column drag and drop is also possible like row drag and drop?
Thanks a lot!
@tt – If I understood well, you want to dynamically add table rows (to the table with one column). In a moment of deleting DIV element, table row should also be deleted. Yes that is feasible, please see my post Adding table rows and columns in JavaScript where you can see live demo of how to add/remove table rows. Combining REDIPS.drag with insertRow / deleteRow you can achieve desired functionality.
@pascal – Wow, that sounds very cool! First it is needed to track all moves. That can be done with REDIPS.drag.myhandler_dropped() event handler. Here’s beginning of how to record chess moves:
source_cell and target_cell are references to the source and target table cell. Next it is needed to find out exact row / column for these table cells. My advice is to write a separate function which will return row / column position for the input table cell reference. After position values are known, you can push them to the array or even save with AJAX to the server. After all this work is done, finding out previous chess move will not be a problem. Maybe you already heared about Node.js which can perfectly fit for real-time applications. I will not promise, but I’m considering to implement some support for Node.js – like method which will move elements on the table …
@Rupam – At this moment it is possible to move only table rows. Table column is actually a set of table cells across all rows. It will be a little complicated to create support for dragging table columns. Of course, it is not impossible and it is already written on REDIPS.drag “wish list”. Thank you for using REDIPS.drag library.