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. @Ian – your page should work without any additional refresh. Please see

    Example 18: Simple element animation

    … where you can click on button and move DIV element right after page is loaded. If you have online script (or you can prepare JSFiddle demo) send me an URL and I’ll try to find the problem.

  2. Ok here is a link to a test page where I have the problem.
    http://www.nhlguru.net/index4test.php

    It is a pretty complicated page, but it is the “trade” table at the bottom of the page. When you drag and drop a player into the trade area, and click the trade button, he should move to the other side of the table (or one or more players on each side swap places).

    Drag works, but Move does not on 1st page load, but both work on re-load or refresh.
    script4.js is where the redips initialization and the redipsInit.move function are.
    I’m sure its something to do with the way I initialize it, but I’ve tried everything I can think of!
    Appreciate any help you can provide! Thanks.

  3. @Ian – On the first view, maybe the problem is because you have “min” and “source” lib loading in your page:

    <script type="text/javascript" src="redips-drag-min.js"></script>
    <script type="text/javascript" src="redips-drag-source.js"></script>
    

    Please try to remove line with “redips-drag-source.js” – for production you only need minimized JS file. Hope this will fix the problem, and if not please give me feedback so we can go further.

  4. That didn’t do it, but I played with it some more and methodically went over every step.
    Eventually found the problem. During my initial efforts to edit the script for my specific usage, I had at one point deleted the bit of code that gets the start position of the div to be moved.
    So, it wouldn’t work unless I refreshed the page, which apparently then got the start position and made the script work. So, for anyone else, don’t remove this code :)

    var pos; // current position as array
    pos = REDIPS.drag.getPosition(id); // get start position
    
  5. @Ian – I’m glad you found the problem and now everything works as expected. If you will have any additional questions, please be free to post a comment here.
    Cheers!

  6. I have a problem trying to use their library, I need to select the element, it will double or quadruple the element depending on the case, the draggable area to be detached he was considered a single element, so that every time he is drawn, all the other elements that were created with the first, are drawn together.
    They would also these element were ever cloned from the element of the top, see example I created in stackoverflow.

    http://stackoverflow.com/questions/31107495/working-with-drag-drop-redips

    Excuse the bad English, but do not speak English fluently…

  7. Hello, thank you for redips, it’s great!

    I have a question about it. I would like to move two cells as one group. Is it possible?

    I have time table for booking tables in restaurant. Rows are tables, columns are time (hour by hour). I have one reservation for example for 3 hours – 3 cells in same row and I would like to move these 3 cells to another row by one drag&drop.

    Is it possible somehow to group this cells?
    Thank you very much
    Jiri

  8. @Jiri – REDIPS.drag can move only one DIV element at a time. But it’s possible to select more elements and with REDIPS.dropped() event, move selected elements as well. Please see the following demo:

    Example 12: Select and move more elements

    Hope this demo will give you an idea how to use event handlers and solve the problem.

  9. Hi,
    It’s a very neat library that you provide, and I started using it for a little project of mine. I have one problem though: I manage to get elements to be draggable, but only once. Once dropped they loose their attribute. Please, have a look at the following fiddle, and let me know if you understand what the problem can be.
    http://jsfiddle.net/stephposs2013/bxd892kr/1/

    The reason behind the overwrite of the events is that I need to check if an area overlaps with the newly deposited element before it’s dropped.
    I’m very new to JS, so it’s very possible that I missed a trivial thing, but I’ve been struggling for a few days on this, and I can’t figure out what I did wrong.

    Thanks again for the great lib!

  10. @sposs – Please see updated link:

    http://jsfiddle.net/bxd892kr/2/

    The solution is in added line 101:

    REDIPS.drag.enableDrag(true, div);
    

    When DIV element is created from the ground, you also have to attach onmousedown, ontouchstart and ondblclick events. BTW very nice example and prepared example on jsFiddle is my favourite way of solving problems.

    Thank you for using REDIPS.drag library.

  11. Hello dbunic,

    i use your example 03 and it is very nice. My question is about the rows and subjects. It’s maybe possible that’s for one row only allowed to drop from each school subject only one subject per row?
    As example:
    Monday you can drop 1* Math, 1* physics and so on
    you can not drop 2* Math, 1*physics on monday
    I hope you understand me. I’m sory for my bad english.

    Thank you for your time

    Ullimon

  12. @ullimon – Restrictions you asked (per day) are possible to achieve in event.droppedBefore(). In case when rule is not satisfied, it’s enough to return “false” from droppedBefore() and dropped element will be returned to source cell. You will only need to write JS logic inside event handler to test for already dropped subjects.

  13. Hello!
    first thank you for redips I am learning with it, javascript and html and I have found it because of what I want to be able to build. Now what I am missing now is a save as button like you have for json format and plain query string for changes to the table, but instead, really just saves the text inside the bubbles. e.g you have these words : “elephant”, “I”, “want”, “an”, every one in its own cell. you put them in order in the tables like we already can and when we click save, we get : I want an elephant

    so lets say your example one, exactly that but with an extra save3 for text:

    Save : content of the first table (plain query string)
    Save2 : Save content of the first table (JSON format)
    Save3: Save content (plain text format)

    I cant figure out how to do that, anyone can point me to the right direction it will be very very much appreciated, thank you so much !

  14. Hallo,

    sorry for a maybe stupid question. I develop with meteor framework, so no php and sql.
    Is it possible to use your library there as well.

    Thanks for your feedback in advance

  15. I want to say ‘thank you’ for your library.
    How can i use this library for responsive table.
    Any help is appreciated.

  16. Hi,
    I have a stack of images (ex. deck of cards) in the table’s cell (the same absolute position, different z-index) and need to drag and drop them (one at a time) to other cells. If two or more images go to the same cell, they have to be stacked, as well as if I return an image to the original deck, it should go on top.
    Is it possible to do that?
    Thanks.

  17. Hello,

    I just have some questions about saving. I’m working on a POS table management layout project where the table can be customized and your library really helped. i just have some questions, how will i save it using servlets and beans that connects and saves it to the database. The idea of the saving itself is so hard for me to tackle. I hope to get a response from you

Leave a Comment