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. One more question wizard – is there any way to hide the number in a cell so the kids have to guess what the multiplicant or additive value is based on the answer? Is this a CSS thing or can it be done inline? I think it adds a challenge to randomly hide one or more of the values in the equation. My kids are so lazy….sheesh.

  2. @Steven – REDIPS.drag library is updated to version 5.0.5 and example25 is finished. Please go to “preview” section (link is below post title) and open “Math 4 kids”. Example works in two modes: hide result or hide first number (this can be switched with “mode” drop down menu). Number will be hided with “?” – it’s only needed to dblclick on DIV box to show the number.

    Merry Christmas to all you guys!

  3. That’s an amazing library, thanks! Very simple to use and very nice looking.
    One question: how can I use the “shift” function?

    Thanks again. : )

  4. @Enrichman – REDIPS.drag can be set to work in shift mode. It’s only needed to set dropMode after initialization:

    // reference to the REDIPS.drag library
    var rd = REDIPS.drag;
    // initialization
    rd.init();
    // set drop mode to "shift"
    rd.dropMode = 'shift';
    

    In that case DIV elements in table will be automatically shifted horizontally or vertically (depending on shift.mode property). It is also possible to shift table content manually with shiftCells method. Please peek to the documentation (link is below post title) where you will find a lot of code snippets …

  5. Your code is what i need to make my program works. At present I am making sample program with ScriptCase coz i am not good at programming, I am just learning from your code. I am trying to integrate and run your sample sample3 to my program but I just can not make it run. maybe because it looks for the 3 header files. Can you give me the code only in one file or script so that it will not anymore look for the other include statement? hope you can send me sample code so i can integrate it to my program of scheduling system.

    I want to run it in a single php code with all the functions in it.

    thanks

  6. @Maico – All code is placed to index.php and has been sent to you. It’s only needed to set username / password and database name at the top of index.php. Hope this will help you with your project.
    Cheers!

  7. Hi! I have a question: When I make onmousever is it possible view values from table. I am writing value with link into cell and I need view any values from table(s). Thanks.

    btw: yours codes are excelent

  8. Hi Sir dbunic,

    Just want to ask if it is possible to allow switching cell contents but at the same time only allow one div per tag? I tried allowing switching/switch dropmode, it works ok. But after some dragging tests, I noticed that the table cells allow two divs per cell. I tried the single class for which allows only one div per cell but it disables the dropmode (switch). Any way to make these two features on at the same time? Still reading the documentation, I probably just overlooked at it.

    Hope I expressed it well. As always, thanks for this great code.

    Regards,
    Kris

  9. This is really good.

    How can I save the setting on the page and send it across to database so that next time I open the page, I get the page with saved set of setting.

  10. @Lubo – Thanks! If you want to execute some task when destination cell is highlighted, please see event.changed(currentCell) handler. There you can place JavaScript code to read value from highlighted cell and to display it to another DOM element. Similar how is displayed current position in third table (upper left corner).

    @Kris – Unfortunately is not possible to have “single” and “switch” drop modes at the same time. If DIV elements are initially placed in order “one per cell”, then switch and switching drop modes should preserve this settings. It’s also possible to change drop modes in event handlers like it is in example 9 (single and shift mode). If cells are marked as “single” then dropping DIV element will not be able to already occupied cell (as is stated in your comment).

    @Varun – Please see example03 from redips2.tar.gz package. In readme file you will find simple instructions how to prepare local MySQL database to save table content. Anyway, built-in saveContent() method will scan table and prepare query string or JSON format for submitting to the server. You will find more info with code snippet in documentation.

  11. @David – Hope it’s not the browser issue but as I can see, it works. Here is how you can test it. Initially “Remove cloned element if dragged outside of any table” checkbox is checked. Now try to drag “Clone” element in last (third) table outside of any table and release mouse button (you can drag it down where are placed checkboxes). You will see that last possible TD will be highlighted but DIV element will not be dropped there. If you repeat whole process with unchecked “Remove cloned element …” checkbox, DIV element will be dropped to the last possible table cell.

  12. Hi, I am using Example 3: School timetable. First I get select from table and move cells from subject to timetable.Next I modify timetable to 5 columns.
    I need something like moving data from one select to more tables (values from 1 subject -> 2 timetable).
    What part of redips codes is suitable for this ?

    Apologize my english. Many thanks, Lubo

  13. @Lubo – Please see example 18 “Simple element animation” from redips2 package or on preview (link is below post title). After page is loaded, check on “Clone” checkbox and click on “Move” button. Orange DIV element is source and it will clone blue elements to random table position. Inside redips.move() method you will find how to move/clone DIV element. Similar code can be applied in your case as well. Here is snippet from example18/script.js file:

    // move/clone DIV element
    REDIPS.drag.moveObject({
        id: id,                           // id of object to move
        clone: redips.clone,              // clone option
        overwrite: redips.overwrite,      // overwrite target cell
        target: [0, rowIndex, cellIndex], // target position
        callback: redips.buttonEnable     // function to call after animation is over
    });
    

    redips.clone and redips.overwrite are boolean properties and they are set somewhere else in script.js file.

    PS
    Your English is fine (I’m neither a native english speaker) :)

  14. Thanks for reply. I would like send picture to you with my request. Maybe it will be a more clear. Is it possible ?

  15. regards to @David – Hope it’s not the browser issue but as I can see, it works. Here is how you can test it. Initially “Remove cloned element if dragged outside of any table” checkbox is checked. Now try to drag “Clone” element in last (third) table outside of any table and release mouse button (you can drag it down where are placed checkboxes). You will see that last possible TD will be highlighted but DIV element will not be dropped there. If you repeat whole process with unchecked “Remove cloned element …” checkbox, DIV element will be dropped to the last possible table cell.

    – I can’t get it to work, at least now how I’m intending, in all 3 browsers. –

  16. Hi David!
    Cloned DIV element will be deleted only in a process of cloning. Please try to clone DIV element and immediately drag it outside of any table – without any steps in a middle like dropping to the cell and dragging out (don’t forget to check “Remove cloned element if dragged outside of any table” checkbox). Your example shows normal behavior of REDIPS.drag lib because cloned DIV element is placed to the table and then is dropped out. After cloned DIV element is dropped to the cell, it will be treated as “normal” DIV element. So, “Remove cloned element if dragged outside of any table” refers to period when user still has pressed left mouse button – first drag of cloned DIV element.

Leave a Comment