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 destination cell. Attaching onMouseOver handler on TD elements 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 TD positions, here is example that should work in FF3+, IE8+, Google Chrome 10+, Safari 5+ and Opera 11+. Click on image below, will open Example 01 with live demo.

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 Version 5.1.0 redips2.tar.gz

REDIPS.drag example01

“Save” button will scan table content, create query string and send to the 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 the 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:

  • functions and data structure are defined in namespace (easier integration with other JS frameworks)
  • JSLint: No problems found in redips-drag-source.js (tough one, huh)
  • 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 (160KB) package you will find 27 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,095 thoughts on “Drag and Drop table content with JavaScript

  1. @Vlad – Well, my guess is that it can be done using some styles to the TD cell. Please see example13 where circle and rectangle DIV elements are dropped in the same cell.

    @mie – Hi, to save DIV elements you’ll have to create service (using servlet, PHP …) that can read JSON data (preferred). REDIPS.drag library already contains method for scanning table and preparing data in JSON format. Just click on the “Save2” button on example1 to see the output from REDIPS.drag.saveContent()

  2. Hello:

    Great product, but I’m having a little problem. I have six tables sitting next to each other. Two of them are off screen, so when I scroll to bring the tables into view, I guess it wants to keep its original position, not counting for the offset. Is there any way to fix this?

    For example, you can see it happening in your Example 06. Move the scroll bar to the right and try dragging and dropping. It fails.

    Thank you so much in advance.


  3. Hello everyone.

    I’m trying to use Example 01, although i can’t get cell to drag.

    I’m trying to adapt this example to my code, so I put some of “index.html” code into my .html, I’ve put all the scripts and copied the .css and .js . Tha tables appear, everything is nice and well formated, the real only problema I’ve got is that I’m not able to drag.

    Any tips or help?

  4. Hello, first of all thanks for Redips, it is a really fantastic library!
    I’m trying to insert (or delete) an item in the table by clicking a specific button (bypassing the drag and drop system).
    Using as a basis the example 24 (table editor) i’m not able to get anything.
    Is it possible to obtain this? Should I use cloneObject method?

    Thanks so much

  5. @Maurizio – To delete DIV element you can use deleteObject(el) metod. Here is example from documentation:

    // delete DIV element in event.dropped() event handler
    rd.event.dropped = function () {
    // delete DIV element with id="d1"

    On the other hand, if you want to dynamically add new DIV elements to the table, it’s needed to run enableDrag() method. Here is example how to reinitialize all DIV elements on the HTML table:

    // init DIV elements in dragging area (including newly added DIV element)
    // DIV initialization will work if table node stays intact (table is not generated dynamically) 

    It’s also possible to init only new added element (please see docs for enableDrag())

  6. Hi Dear

    I have some problem with Drag & Drop these script. When i Return Data from ajax and php with whole html table design, then it is now working drag script. So please can you help me. How can do solve it for these problem?

  7. Hi.

    In example 23 is is possible to pre populate the ‘drop_list’, and still have the ability to add and remove new and existing entries ?

    I’ve tried using JS to append a new to the drop_list and this works, but I then don’t have the ability to remove the entry.. if needed.

    Any idea how I can do that ?

  8. Hot to retrieve data and fill table

    Based in example #3, i store data into 2 columns, Grupocodigo (the object code) and Position.
    i create this function, and call it from redips.init part:

    function cargagrupos(rd) {
        var xhttp=new XMLHttpRequest();
        var url = 'llamadasajax/leerhorario'; //---> use your appropriate ajax call to retrieve data!!
        xhttp.onreadystatechange = function() {
        if (xhttp.readyState == 4 && xhttp.status == 200) {
          //document.getElementById("demo").innerHTML = xhttp.getResponseHeader('Last-Modified');
          var datos = JSON.parse(xhttp.responseText);
          //loop to read data and move each item to cell
          datos.forEach(function(valor) {
                var grupocodigo = valor['Grupocodigo']; //lectura desde b.d.
                var objeto = grupocodigo.substring(0,3); //el objeto fuente
                var objetodom = document.getElementById(objeto);
                //leemos y procesamos la posicion
                var posicion1 = valor['Posicion'];        
                var posicion = posicion1.split(',').map(function(item) {
                    return parseInt(item, 10);
                //insertamos en posición  
                var objNew = rd.cloneObject(objetodom);        
                obj: objNew,
                target: [posicion[0],posicion[1],posicion[2]]  //table,row,cell
      xhttp.open("GET", url, true);
  9. very nice product but only one simple problem I am facing is how to find the column and row number of a cell during dropping something into it. I tried my best but didn’t find a suitable solution.

  10. @Murad Khan – You can use rd.td.target property to access target TD element. From this reference is possible to read cellIndex property and go to parent element TR for rowIndex.

    Please see docs for “td” property in Field Summary section.

  11. I am working on timetable module. Dragging subjects to the table works fine on my localhost but does not work on live server. I do not get even a JavaScript error but still it is not working.
    Please help me in this regard.

  12. Hi Mareena,
    if you can provide URL for your public site, I’ll try to see where is the problem.

  13. How can i get the ID of a target DIV?
    I can get the ID div of my draggable DIV but not my droppable target?
    Its is possible?

  14. Can you please give me your contact? I have a lot of questions to do. Thank you :)

  15. it works great on plain html.
    is it posible that your scripts also will work on asp.net with Master page with twitter Boostrap?
    (Example 9: Single and shift mode)

Leave a Comment