Drag and Drop table content with JavaScript

Content of HTML table cells can be dragged to another table 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 destination table cell. Attaching onMouseOver handler on table cells will not work, because browser doesn't fire events to the elements beneath the dragged object. :(

Anyway, after taking care of the current scroll position and calculating table cells positions, here is example that should work in FireFox 3, Internet Explorer 6 / 7 / 8 and Google Chrome. Please try to drag green, blue or orange bordered objects, change properties (radio button and check-boxes) and click on "Save" button. Funny, isn't it?

You can not drop here
Drag
and
drop
content
with
JavaScript
Table2
and
Drag
drop
table
with
JavaScript

Table3
Clone
(1) Clone
(2) Clone
Trash
Save content of the first table (it will only show accepted parameters)
Enable dropping to already taken table cells
Disable dropping to already taken table cells
Switch content
Remove cloned object if dragged outside of any table
Confirm before delete object
Enable dragging

You can try another example built on this Drag and Drop library.

"Save" button will scan tables, create query string and send to the PHP page. Demo shows how to collect table content and accept parameters on the server side. More about accepting parameters you can read in my post Reading multiple parameters in PHP. Orange object "Clone" will be duplicated first because of "clone" keyword in his class name. If you drop object on cell named "Trash", object will be deleted from the table (with or without confirmation). Script has built in autoscroll and option to forbid landing to non empty cells or cells named with class "forbid". Table can contain rowspan / colspan cells and different background color for every cell.

Here are minimal steps to enable content dragging in table:

  • put <script type="text/javascript" src="drag.js"></script> to the head section
  • place table(s) inside <div id="drag"> to enable content dragging
  • add .drag{position: relative;} class to CSS file
  • place <div class="drag">Hello World</div> to the table cell

Other features of drag.js:

  • functions and data structure are defined in namespace (easier integration with other JS frameworks)
  • JSLint: No problems found in drag.js (tough one, huh)
  • movable div element can contain form elements and links
  • forbidding or allowing table cells marked with class name "mark" (depends on "marked_cell" parameter)
  • option to define exceptions and allow certain DIV elements to the marked table cell
  • option to define single content cell on the table declared with "multiple" drop option
  • cloning
    • for unlimited cloning add "clone" class name to the div object
      <div class="drag clone">Hello World</div>
    • to limit cloning and transform last object to the ordinary movable object add 'climit1_X' class name
      <div class="drag clone climit1_4">Hello World</div>
    • to limit cloning and transform last object to immovable object add 'climit2_X' class name
      <div class="drag 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)
  • allowed nested tables
  • dropping objects only to empty cells
  • switching content of table cells
  • table cell with "trash" class name becomes trashcan
  • enabled handlers to place custom code on events: clicked, moved, not moved, dropped, switched, cloned, cloned end1, cloned end2, deleted and undeleted
  • deleting cloned div if the cloned div is dragged outside of any table
  • enabling / disabling dragging

How drag.js works?

Script will search for div elements (with class name "drag") inside tables closed in <div id="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 "left" and "top" styles of the object. 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 mouse move events only when user holds left mouse button on div element.

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 table cell coordinates (with scroll page offset) and store them to arrays. Arrays are searched inside onMouseMove handler and after left mouse button is released, object will drop to the current (highlighted) table cell.

In redips2.tar.gz (21KB) package you will find several examples including example how to save/recall table using PHP and MySQL. Instead of using well commented drag.js (in production) from the package, I will suggest to compress it first. Compression will cut out comments and unnecessary space. Finally, drag.js will function as the original but with 50% smaller size.

Happy dragging and dropping!


Bookmark and Share

230 Responses to “Drag and Drop table content with JavaScript”

  1. HKad says:

    I am not sure whats wrong, but this still doesnt work. However this is what i was able to figure it out. When you call myhandler_dropped call looks like target cell looses its DIV tag as a result doesnt get picked up by save_content() as result i never see last drop cell's DIV tag when i alert query variable in save_content function.

  2. senthil says:

    hi, i used this drag and drop clone concept, it works fine in all browsers except opera browser... is there any hacking code for opera browser or want to specify any width for the dragging div..? in opera browser even dragging the div also not acceptable...? give me some solutions to drag the div in opera browser to solve the problem...

  3. Danny says:

    Great stuff.

    I was looking for all the other draggables/droppables implementations with jQuery and the other frameworks, and all look too complex for my taste.

    This looks great.

    One suggestion, although my guess is that it may not be that easy to implement, would be to allow a sortable style behavior. Right now if I have a one column table, with say, 20 objects and I want to move the last one to be in the second place, while pushing all of the other down, I cannot do it (as far as I could tell).

    Anyways, thanks a lot for sharing this.

  4. Usama says:

    thank you very much
    truly i didn't try it but really thanks

  5. Garwain says:

    Mr dbunic,
    I've been using your wonderfull script, but I want to upgrade it with radio buttons. This comes with some difficulties I cannot overcome.

    1. When dragged, the selected radio button is reset. Is there a way to keep the radio button checked while dragging and dropping?

    2. I read your post about checking which checkboxes are ticked. Can this be implemented in the resulting query string as well? I'm saving the positions, but I'd like to save which radio button is checked as well.

    Thanks for looking into this!

  6. Greg says:

    Absolutely amazing code. Exactly that I need. Thank you.

  7. Andy says:

    I want to have a table cell that, when clone is dragged onto it, the cloned element gets added to all the cells in that row. Can someone point me in the right direction? Thanks!

  8. Fatih says:

    hey, cool script
    i have discoverd the script for two days but i have a problem with reordering. i didn't find correct way to reorder when single-cell drag-dropping. Dragged divs is always pushed last position in td.(always appen last did not insert) is anyone know the way to solve this problem? Thanks

  9. Rocky says:

    How can I click on a button and reset one of the div's to go back to default position that it started from?

  10. Poz says:

    Excellent code, does almost everything I need it to!

    However I'm having an issue with the scrolling when inside a container. Am I doing something wrong or is it not possible to scroll according to it's parent container?

    e.g. I have my "drag" div inside an asp.net panel control and at present the panel is not scrollable when dragging near it's boundaries.

    Any help would be greatly appreciated.

    Thanks.

Leave a Reply