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!
owesome script
Hello Darko,
Please disregard my previous post about the “CANCEL” move event. I have figured it out. It took me a little to figure it. I had a bug in some over code which complicated my troubleshooting.
You have done a really great job with this code. I will be sending you a donation for sure! It’s very clear you put a lot a thought and clarity into your programming!
Great job!
Chris from Atlanta, Georgia, USA
Darko,
You should see a payment sent by PayPal.
If I get a chance, I may try to do this, but I was curious if you would consider this as a possible feature.
You offer “Switching content continuously” which is nice. However, it forces cell contents into multiple directions depending on the source cell. Is it possible to have a free-flow option? Just as if you have word-wrap on. As an example…If you insert a word into the middle of a sentence…the words continue to flow in a linear method. This of a photo gallery picture sorter when if I take a picture from the bottom and insert it more up to the top…all the photos remain in order allowing “insertion” of a new photo.
Just something to consider…I think it would be a worthwhile feature.
Again, great job!!! I’ve been looking for something like this that really works! for a long time.
Best,
Chris from Atlanta, Georgia, USA
Great job !! thanx
@joerg – If you want to change DIV element height depending on the current row height, here is how:
@Chris – I’m glad you solved the problem about “cancel move event” and thank you very much for a generous donation. It will help me to keep motivation and to carry on with developing REDIPS.drag library. Your donation is very appreciated. Thank you once again.
Your suggestion about “free-flow” dragging option seems OK and I will put it on “todo” list for the next lib release. In comparison to current drop options, “free-flow” will shift many elements to make a room for a new element and to keep the elements order. Thanks!
Darko,
You are certainly welcome and I can understand needing encouragement to support development of this kind. Again, I am very excited to have found your library as it has helped me greatly.
I look forward to any future enhancements that come about.
Best,
Chris
Hi, Is it possible to save the drag and drop changes (like aligment of control elements) of a broswer page and rendering the changes when the same broswer page is called the next time.
Regards
Hari.M
@HMuddada most anything is possible. It’s just a matter of coding it. You would most likely have to sweep through all the elements and read their properties and then post that back to a database to be used at a later time when you regenerate a webpage. I think that might be too much data for cookies. You could always use a cookie to reference the saved session/state.
@HMuddada – I agree with Chris. Cookies are not the best solution for storing great amount of data. Anyway in a fortcoming HTML5 standard, it will be possible to use web storage (it is like a cookies on stereoids) and web sql databases (not sure what’s the latest status) to save data on the client side. In the meanwhile the best option will be to save drag and drop changes to the database.
Hi
I’m just trying this out and it works great, good work. Just wondering is there a class which can have the item marked so it cannot move but still be able to click on it and cause an event?
Basically i want some info to popup when i click on marked items
Thanks
Anthony
Scrap the above question i just added the onclick event in the div element. But another question is, is it possible to delete the div through a button rather than having to drag to a ‘trash’ cell?
Thanks
Anthony
This is a really nice script, although I have had a little trouble figuring a few things out. One thing that seems like could make this a little bit better to understand is if custom attibutes were used instead of Classes. For example:
Then the Div can only be dragged if that attribute is set to 1 (or ‘true’, or whatever). Just a thought!
FYI, dragging a cloned object “off the table” does not work because the “cloned” property is wrong. It is not maintaining state because “cloned” is basically a global variable, and not a property of the object itself. I am only moving DIVs (and not ROWs), but I believe I fixed it by changing the reference to use and set obj.cloned, and then changing “moved = cloned = false;” to “moved = false;” inside handler_onmousedown.
So far is seems to be working perfectly and behaves like I need it too.
@Anthony – I’m glad you solved the problem with adding onclick event to the DIV element. Here is example of how to delete DIV element with a simple function. Input parameter is id of DIV element:
@Bryan – Custom attributes will be formally supported in HTML5 using the “data” attribute. The exact format will be data-*, where * can be replaced with the desired custom attribute name. So in this context HTML will look:
As I started developing REDIPS.drag library before HTML5 came near to the current state, I had to take care about passing HTML validation and not to use custom attributes. Anyway, your comment is OK and future REDIPS.drag releases will switch logic from class names to the custom attributes.
I’m trying to figure out how dragging a cloned object doesn’t work. Do you have prepared example to show? I will be very grateful if you can give a little more details about problematic example. “clone” inside REDIPS.drag is a current flag. In a moment when DIV element is clicked, this flag is set to false. When user moves DIV element, element will be moved or cloned (and “cloned” flag will be set to true). “cloned” flag is used in many points inside REDIPS.drag so I’m not sure to change this flag to the object property. If user script needs information if object is cloned or not, this can be added inside clone_div() method. Thanks for helping make REDIPS.drag a better library.
Hi, I have some script to add (new) elements to the table and I’ve created them with class “drag” but the code doesn’t recognize them for dragging – I assume because it only sees these when the initial code is run.
I can’t see a function to call to tell the code this is a new draggable element but I must be missing it somewhere – what should I call?
@Keith Z – Just call REDIPS.drag.init() to rescan DIV elements. New DIV element should behave like it was on table from beginning.
Hi Darko,
sorry for my late Thank you message. I was in the vacation for 3 weeks ;) Thank you very much for your help. It works great!
I have one more question. How can I change the size of the element which is located in the DIV element. Let’s say, I have an image in DIV. When I drag&drop a DIV from 1st row to 5th row, I want to have smaller image in the 5th row. But, when I drag&drop the DIV element from 5th row to 1st row back. I want to have again normal size image.
Thanks in advance,
Joerg.
Hello Darko!
My aspx is like this:
and my JS is like this:
But it does not work!
Help please!
@joerg – The same way as DIV height was changed, child element height can be changed too. rd.obj is reference of dragged DIV element. You can extend previous function like:
This way, DIV element and image inside DIV element will change height after element is dropped to the table row. Image width (and other style properties) can be changed as well.
@zhaowx – After DIV element was dynamically added to the table you should call REDIPS.drag.init() method to rescan table content.
Init method will assign event handlers to DIV element so it can react on mouse click. If you will still have problem with this example or any other question, don’t hesitate to ask.
yeah,it works!
really thanks!