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!
Hi,
I have an issue on dragging and dropping. I am getting some information while dragging a DIV and dropping and saving some information. What happens is when I drag and drop a DIV over another, the events (mouseup, mousedown, mousemove) happens simultaneously on other DIV. So I am losing the correct information.
How to avoid this? No events happen for other DIV when i place the div over another DIV.
Is it done by logic?
Every DIV element has attached only onmousedown event handler – so the dragging can start. In a moment of clicking on a DIV, script attaches to the same DIV event handlers onmousemove and onmouseup. After releasing mouse button, script appends dragged DIV element to the current table cell (appendChild) and removes onmousemove and onmouseup event handlers.
So in your case, you drop a DIV element to the occupied table cell – I mean table cell already contains other DIV elements and they catch mouseup, mousedown, mousemove events. Can you confirm this?
I suppose, this can be in relation to the event bubbling / event propagation … In original, every DIV element has only onmouseup event handler so onmouseup event will be processed by the current element only.
Hope this informations will help you and please comment if anything has been left out or is not clear.
Hi,
This is a great little tool, however I have a question or two. Is there a way to have items that cross multiple rows or columns and still have drag and drop functionality.
IE. I want to use this to build an editable timeline where users can drag appointments etc and move them. So you would have time in 15 min intervals down the table and a user may have a 1 hour appointment. So the appointment would take up cells in 4 rows. Is there a way this can be done?
Also is there a way a user can click-drag to select the time period for the appointment initially?
@MPREZ,
unfortunately script is based on table cells only. You can prepare 15 min raster with table easily, but placing one DIV element across many rows / table cells will not be possible. On the other hand, you can emulate table content across more then one table cell with “rowspan”, but you will have to dynamically change underlying table while user drops appointments – it doesn’t sound simple. Sorry, but my script isn’t designed for asked functionality … :(
Thank you for your expression of interest in this script.
Kind regards.
Thanks dbunic,
I’ll have to experiment with a few ideas.
I’ll let you know if I work it out.
Cheers
I was so happy to find this and would like to ask the developer or anyone interested to help me out with a particular problem.
On my site I have photo albums which are dynamically generated from a Data base and the thumbnails are in an enclosing table where the rows and columns are generated at the server. So not all albums will have the same table structure although all tables will end up having an in each element.
For some reason I can’t get the drag drop behaviour to initiate even though I made sure to add an enclosing div tag for this table with id=drag and all div tags within table cells with class=drag t1. Some thumbnails may be larger than others so I ended up changing the width of the t1 class in the css file to auto.
If anyone can help me out on this it would be much appreciated. My ideal goal would be to drag and drop thumbnails and then send the list of parameters to an ASP page to have the array indexes saved to the database in a “order” column.
Thanks for this brilliant piece of java!!!
@JKoke – Generally speaking, dragging should work in your case, but it would be much easier if you can provide some preview link to see / locate where is the problem. I will gladly help. Cheers!
;)
hi, i’d like to ask how do u detect on which cell u drop the dragged element?
So I am having a little trouble with this… How exactly does one gather the value of the div dragged? I’ve been able to set up different divs using a script I currently have but I can’t figure out how to save the data to my server.
Basically, I’m making a form or an application using your API. The form is customizable though and allows users to move the content around. I just can’t figure out how to move it all over the place but retain the value.
Thanks!
@dizza – After page is loaded, scripts loops through all tables on the first level closed within DIV id=”drag” (childes of DIV element). Boundaries for ever table row are saved in the array. Coordinates of the moving object (current position) are compared with the row boundaries. After current row is found, within next loop script searches for the table cell beneath dragged element. Current table cell is remembered and moving object within current table cell triggers only few lines of the code. In the moment when dragged object crosses boundaries of the current table cell, script searches for the current row and current table cell (like described above). This way code is optimised and efficient.
@pros599 – To save DIV locations / positions to the database, every DIV element in table cell should have assigned id. In save_content() function tables are searched and query string is prepared. DIV location is compounded with index of table, row, cell and finally DIV id. Please look my post Reading multiple parameters in PHP how to detach index values concatenated with “_”. If you have any other questions, I will gladly help you.
Hi,
I saved the div location inside the database.From this information , How will i display the div contents in a dynamically generated table
Hi dbunic
I like very much your smart tool! Just a little input. There are other tools with which table’s can be edited like “move row’s up and down”, “insert new row’s”, “delete row’s”. Your tool is cell oriented. Wouldn’t it be great to get both functionalities in one tool instead of combining two JavaScript’s? E.g. move cell content into new row.
Best regards
Hi, i like your script. Managed to make it work with mysql. I want to ask if its posible to make Marked cell just for divs with certain class or id.
For example i have one big table with all kinds of fruits. But i want other table to accept only apples.
Is there any help available for ASP? I am trying to achieve this functionality with ASP. I want to save the dragged cell to database so that next time the user logs in he gets the saved position of the changed cells from the database.
Please help on this.
Thanks
AG
Hi Dbunic:
I’m trying to add a div container of one of the tables within the div drag to put it into another position of my site, but then does not drag. What should I do?
@hlas – If you have nested loops to generate tables, rows and cells then saved information in format id_table_row_cell will be fine. First fetch saved table content to the array. You can create associative array where keys can be “locations” table_row_cell (without DIV id). Values of array members can be another array with DIV id and DIV text. So within nested loops, prepare table_row_cell “array key” and try to fetch value from the associative array. If value is found, then script should create DIV content with an id and text, otherwise table cell should be empty.
@jofo – You are right. It will be nice to have common functionalities inside one API. But, “drag and drop” API as you mentioned is cell oriented and I tried to cover all kind of HTML tables – with spanned rows and columns. I’m not sure but inserting row in “colspan” table isn’t so simple and that can lead to code growing … Anyway, I will consider your idea. Thank you for commenting on my blog.
@ceolic – I will try to enable marked table cells for specified DIV elements. This implies user definition of array with DIV ids and class names. ID and class name pairs will define allowed content for the marked table cells.
@AG – “Drag and drop” script will work no matter of back-end engine. My background is mostly LAMP, so I wrote examples with PHP … Generally speaking, your ASP script will only have to accept parameters and save them to the database. Next you need to create three nested loops like I mention in reply to hlas. I hope that someone with better ASP skills will help you.
@Locutus – If you have link to show, I will try to help you.
Hi dbunic
thanks for your answer. In case of spanned rows and columns it’s not as easy – I agree. But please allow me one thought / question / suggestion. Isn’t the HTML table often generated by a skript out of a DB table? Of course also in this case rows and colums can be spanned. But how does the user add new objects if all cells are full?
Can you recommend a API for merging / disconnectiong cells and adding / deleting rows?
Best regards
The link to my test page is: http://tvdeluxe.5dim.es/dragdrop/
Right upper table is in a div inside DIV id = “drag”, so both tables are next to each other, but I can not move the div’s inside the table to and from it (between both two tables)
Actually one of the tables are generated dynamically with php and its elements must should be dragged to another table in order to create a TV grid.
Thanks
@jofo – I think that a good starting point can be my previous post Adding table rows & columns in JavaScript. You will see that adding / deleting table rows is really easy to achieve. Hope this can help.
@Locutus – Script initializes only first child nodes (tables) of DIV id=”drag”, tables in deeper hierarchy are ignored. So in your case you should comment two lines in init method. Original loop at line 110 looks:
for (i = 0, j = 0; i < tables_nodeList.length; i++) { // include only child tables of DIV id="drag", tables in deeper hierarchy are ignored if (tables_nodeList[i].parentNode.id === 'drag') { tables[j] = tables_nodeList[i]; j++; } } ... and you should comment "if" lines like: for (i = 0, j = 0; i < tables_nodeList.length; i++) { // include only child tables of DIV id="drag", tables in deeper hierarchy are ignored //if (tables_nodeList[i].parentNode.id === 'drag') { tables[j] = tables_nodeList[i]; j++; //} } Now, all three tables will work.
Thanks dbunic. I´ll try it.