Drag and Drop table content with JavaScript

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)
  • 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!

1,195 thoughts on “Drag and Drop table content with JavaScript”

  1. Good afternoon:
    It is possible? I do click on the image after that change to other image.
    Thanks
    Elizabeth

  2. Hi Darko:
    I solved this question above, I used obj.innerHTML = ”; to chage the object. I am learning a little javascript .
    Thanks
    Elizabeth

  3. First announcement. Drag and drop code is rewritten and wrapped in it’s own namespace. Now it should be safer (without collisions) to integrate this JS code with other frameworks. Huh …

    @Stephen – Code is rewritten. It works in IE8 without any error for me. Please try the latest version and I hope this will solve IE8 problem.

    @Allan – I will try to prepare example of how to save and dynamically create HTML table from saved content order. You mentioned on/off toggle, actually that means to remove onclick events from DIV elements … hmm, that could be “freeze” button :)

    @Phillip – Unfortunatelly, you can move only one DIV element at time. Moving whole row is not possible.

    @Elizabeth – I’m glad you solved problem. As you can see, JavaScript is not so hard to learn.

  4. Ok, so here is my problem,

    on my page i have this script, plus a live search script, to return search results (like google suggest)

    if my search results are outputed in a table (which they are) (and the search results are outputted inside the drag div) then

    all my draggable divs stop dragging…

    In other words, if a table is created in the drag div, after page load, then all the draggable divs stop dragging….

    can anyone help me ?

    P.S My plan is to have live search results created, which can then be dragged into another table… if i can get the above to work, then the rest should be fairly strait forward….

  5. How do you start a drag and drop table with multiple items/elements in the same row and column? I see the combination of id, table, row, and col when the save button is clicked. I can also see the html that creates the initial table in your example. I’ve played with the js and html and can’t see a ready method to start with multiple elements in a single row/column position. What did I miss here. Great script btw. Most logical structure I’ve found. Thanks.

  6. @Stephen – I think the bug with IE8 is solved. The problem was with row spaned table and row offsetHeight. Instead of comparing current top and bottom row bounds with mouse Y position, set_tcr uses top bound of current row and top bound of next row.

    @Allan – “Enable dragging” feature is added. If you uncheck “Enable dragging”, then every DIV element will be frozen and dragging will be disabled.

    @Calumk – Hm, tables collection initalized in “init” is live node list. That can be the reason why dragging stopped after new table was inserted. Code is changed and live node list is replaced with static array. Please try new redips package. Anyway, more about live node list can be read on my post NodeList objects in the DOM are live.

    @Bob – I’m sorry, but only one DIV element can be dragged at a time. No matter if table cell contains more then one DIV element.

  7. Thanks, but im slightly confused, what redips package do you suggest I try, I thought this was the latest
    (http://www.redips.net/my/tar/redips2.tar.gz)

    OK, so by calling init() after the new table has been inserted, I can regain drag drop controls of the original divs, but I still cant control the newly created divs, in the new table…

    “Please try new redips package” – sorry what package are you refering to?

    and how would you suggest I change the drag.js file, to work with live nodes?

  8. @Calumk – I updated drag.js yesterday and overwrite http://www.redips.net/my/tar/redips2.tar.gz with latest version. If you downloaded package few days ago, please download now to retrieve latest JS code. You will see version number and date release at the top of the drag.js file.

    In case if you still have problem, then I will try to correct it.
    Regards!

  9. Hi,

    I have been trying your drag and drop functionality and all worked fine until I tried to stick in a hyperlink within a div with the drag t1 class. Is there a way to enable hyperlinks within a draggable div?

    Thanks

  10. great code, got one slight issue if you can help, i’m using this within .NET enviroment, doesn’t seem to render the same, and i’m only recreating your sample download but in a master page scenario, any ideas?

  11. Ok, so I’ve updated and well, the behaviour has changed s little, its hard to explain, so I made a screen capture….

    basically:
    the bottom boxes now sort of work, but the first one that is moved after a table change is “off center / origin”
    and once the new table is removed.

    below is all my files for this script, obviously with out the database connect script…. to duplicate my errors, simply copy a table into the bottom of the livesearch.php script…
    ( or hook it up to a database)

    Thanks!

  12. @Dimitri – Well, if you can explain with more details about your problem, I will gladly help.

    @Calumk – you have to call REDIPS.drag.init() after new table is inserted. DIV elements in new table need to have drag class also.

  13. I liked your work
    I need a help and I hope u can help me.

    I am start working to create an online drawing tool using javascript
    this tool should look like Paint.Net program.

    I have create a table contaning the images that u can draw with(line, rectangle,circle,…) and on the right side of the table is the drawing space( a cell)

    I used the consept of Drag and Drop.
    I need to save the drawing space as an image and save it in my website database.

    I need some one to help me with this project.

    Thank u.

  14. @dbunic

    Its really a wonderful effort …
    I need a help with this drag.js I used drag’n’drop in my project for choosing the fields from available fields.

    I am cloning the original object and once dropped in some other area i need to access the both original and cloned object.

    I’m able to access only cloned draggble object alone after dropped by using myhandler_dropped function with obj object. But i need to remove the drag option and to change some css option for original element from available fields to avoid dragging again, once he dropped the cloned element.

    I need help from you to do this… At least to get both original and cloned element access after dropping. Is it possible?? if yes how??

  15. Guys, jslint finally replayed “No problems found in drag.js” Oh, thank you …
    That was really a relief.
    ;)

    @Nora – No problem, please give me more details, and I will try to help.

    @Calumk – I’m glad it works … Nice work!

    @Senthil – Script is upgraded. Now you have “obj” and “obj_old” objects so it’s possible to change previously clicked object in myhandler_dropped. This will be useful in case with cloning as you mentioned …

  16. @dbunic,
    Great work.. Now i can able to access both old and new objects with the updated source..
    I have 1 more problem.. Is there any function to remove draggable option dynamically?? Because i need to remove dragging option for the original element once the user dragged for the first time..After that he should not able to drag and clone again..

  17. your effort is really good.. I need a help with this drag.js I used drag’n’drop in my project… drag_option has three options like multiple,single, and switch… multiple and switch is worked properly but i dont know how to use single in drag_option….?? will u help me..?

Leave a Comment