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!
@Hadailton – I made modification of example06 to show how to identify scrollable container after element is dropped. Complete source code is in redips2.tar.gz package and here is myhandler_dropped() snippet.
@Mistic – I agree that column/row coordinates in case of dynamically created tables are not so appropriate for saving. This is a minor modification in save_content() method. Instead of this line:
Put this line and you will get “TD id” “DIV id” pairs.
Of course, every TD should have defined id.
@Kevin – If you add clone class name to the DIV element then this element will clone infinite number of elements. However if you add clone climit1_1 classes then only one element will be cloned and original element will be still drag-able (contrary to clone climit2_1 where original element becomes steady).
Hi dbunic, let me clarify myself in more details to the program im trying to create. I would like to make the original object undraggable once you drag a clone of it on to a table. You need to drag that clone to the “Trash” button so that the original object can draggable again to create a clone when dragging to the table.
Sorry for being so unclear in my previous post! Thank you very much!
@Kevin – So, if I understood well, you want only one kind of elements on the table. First, table contains clone type elements. If cloned element exists, then original element shoud be unmovable (disabled). If cloned element is deleted (moved to the trash) then original element becomes enabled for new cloning. This logic should somehow provide only one type of elements on the table.
HI dbunic! Yup, that’s correct! Any form of help will be appreciated!
Hi,
I have a little problem with this script. Is there any way to set element in 1 of 2 cells?
I tried something like:
But of course it doesn’t work (i mean, i can put element only in cell_2).
I would be greatful for any tip
@Kevin – OK, here is code that should enable only one instance of cloned elements on the table. If you replace example03/script.js with this code, School timetable could use only one subject from the right table.
@Rie – Here is snippet from example07
First two lines defines DIV id=”a” and DIV id=”b” to be the only elements allowed for table cells with class name “last”. This special cells should have “only” class name also. So, “a” and “b” are IDs of DIV elements while “last” is the table cell class name. Please see example07 for more details.
Thank you very much!! It’s working!
I apologize if i didnt say it clearly enough. I’ll try explain what would i get:
Have two elements: ‘A’ and ‘B’
The element ‘A’ can be put in cell ‘A’ or cell ‘Z’
The element ‘B’ can be put in cell ‘B’ or cell ‘Z’
Every another element can be put in cell ‘…’ or cell ‘Z’
In other words, i would have two tables. In the first one, elements can be put on special positions/cells
In the second one, elements can be put everywhere.
I know that my english isnt perfect, but i hope that u got my point
Incredible code!!!!!!
Hello, I have been trying to use this drag and drop script all day but I haven’t been able to get it working. The CSS works fine but the JavaScripts don’t seem to be working. When I open the examples in the download folder in IE8 it works fine but when I open in my application, the cells don’t drag, I don’t know what I am doing wrong. Please help.
Thanks
@Kevin – I’m glad it works, cheers!
@Rie – You can mark special table cells with a class name “mark”. For example TD class=”mark mycell” … “mark” marks cell to be forbidden for every element while “mycell” class name will be used to create dropping exception. Imagine the following rules:
This means that TD class=”mark mycell” will be forbidden for every element except DIV elements with id=”a” and id=”b”. So you can mark table cells and make exceptions whatever you like. If you define exception rules on the following way:
… only DIV id=”a” will have access to the TD class=”mark mycell1″ and only DIV id=”b” will have access to the TD class=”mark mycell2″. In described scenario, “cell Z” doesn’t have to be marked at all – because every DIV element have access to “cell Z”.
Hope this examples will give you a hint how to “mark” special cells in table, and how to define exceptions. example02 with green and orange elements is based on similar rules, so you can peek to the source code for more details.
@AGK – Very very nice calendar! Thank you for showing your work based on REDIPS.drag lib!
@Oyinlola – The error might be related to the initialization problem. Maybe paths to the redips-drag-min.js are not correct and browser “doesn’t see” js file. Before every lib release I make tests with IE8, Chrome10, Opera11 and Firefox3, so problem must be local. Anyway, if you have online work in progress, please show me and I would gladly help.
And sorry for delay. I was working on drag and drop table rows and releasing new version of REDIPS.drag library. Here are changes made in version 4.0.0
– added support for drag and drop table rows
– added example15 to show drag rows functionality
– private method set_color() renamed to set_position()
– created private method set_bgcolor() – accepts color as array
– created private method get_bgcolor() – returns color as array
– added public parameter “mode” (readonly) with values “cell” and “row” (REDIPS.drag working mode)
– added private methods row_clone() and row_drop()
– added event handlers for drag-n-drop table rows
myhandler_row_clicked()
myhandler_row_moved()
myhandler_row_notmoved()
myhandler_row_dropped()
myhandler_row_dropped_source()
myhandler_row_changed()
– added special class name “rowhandler” to enable highlighting rows when dragging row across row handler column (but disable when dragging table content)
– special class names are: drag, row, mark, only, single, rowhandler
– enable_drag() modified to accept DIV id or DIV object
– when row is moved then obj is reference to the cloned row, while obj_old is reference to the source row
– added property redips_rowspan to the table nodeList to mark tables that contains rowspaned cells
– redips_rowspan is defined inside init_tables()
– optimization in set_trc() method
1) search for rowspaned cells only if table contains rowspaned cells
2) after cell is found, test if Y is inside current cell – this should prevent case where TD border > 1px and upper colspaned row like in example15 (loop unnecessary went up to the top table top)
– fixed BUG – when table cell has shrunk, forbidden cell in the last row was lit (example15)
– added public method row_opacity(el, opacity, color)
I want to arrange a set of existing .jpg images and their captions. No scrolling, no cloning.
All of the .jpgs are in a folder, and their filenames correspond to a $username (e.g. “$username”.”jpg”) in my SQL table.
With only one example script of using PHP/SQL, it will be harder to accomplish – since all the other scripts don’t save, and do go into great detail about scrolling and cloning.
I will work on it, but if you could put another PHP/SQL example script, I can make sure I am going on the right path.
I want to save and recall SQL data with example03.
example03 has the features and layout that best fits my use.
example01 has the “save”, but I want to use “save” (and read) with example03.
I am able to populate jpg images in each ! I even made them clickable to URLs! (The links open when I drag/drop to table2! Which is OK, startling, but OK.)
@Nick – I’m glad you’ve managed to modify example03 for your needs. If you have any other question regarding REDIPS.drag lib, I would gladly answer. Anyway, thank you for feedback, and one of next examples will cover save/recall table content to the database.
Cheers!
Save/recall table content is what I’m waiting for!
redips is a friendly set of complex scripts. The .js is not easy to edit, but also fairly straightforward to make sense of after a bit of study.
But Save/recall table content is very important for all examples. Perhaps a module that can be used (or not) with all examples, like its own .js script sitting in the directory, like the script.js or style.css.
Be nice to see the REDIPS.drag javascript library implemented as a Drupal module. They have a draggable table row module, (see http://drupal.org/project/draggableviews ) but not drag and drop cells. This would allow draggable image galleries.
Hi dbunic, I had another question for you!
Is it possible for me to create a dynamic drag button onto the table when I first load the page.
For example, I create a dynamic drag button as follow:
And I append this newly created div into a td cell. The button appear but it cannot be dragged. Is there any way for me to make the button draggable ?
Thank you very much!
Hi. Wonderful application. but i have a question. y isit tat when i populate large amount of data the draggin is laggin? with the same table n lesser amount of data it works fine. any idea how i can overcome tis? any help is appreciated. cheers for the wonderful app :)
can i drag column as i drag rows?