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,057 thoughts on “Drag and Drop table content with JavaScript

  1. Sorry for my English... I am french...
    Just simple question but I no find answer : how to limit at dropped div to only empty td ?
    My idea is to use your plugin for the children can move de words for do the good sentence...

    Thanks

    Claude

  2. How to limit only one div by td ?
    In fact dropped div only in empty td ?

    Sorry for my English... I am french...

    Thanks

    Claude

  3. I'm using pretty large tables representing cabinets in which I drag'n drop equipments. It works pretty well and your library is terrific.
    All my cabinets are tables and inside a div. In order to ave a better visibility, I can change the zoom style of my div from 1 down to 0.5. For example if you change your example1 adding to your div style="zoom:0.8;" it becomes very difficult to drop under the mouse.
    Any suggestions?

  4. Am wondering does this work with touch? Meaning tablets and phones? Your examples are great! I would love to use this for my new site/application.

    Let me know if you can use this using your fingers.

  5. Would like to use Example 3: School timetable as basis. I would like to extend example 3 to have tooltips on each draggable object. Tooltips is done in Example 16: AJAX, hover, sticky, dragging, but I can't figure out how what to change in example 3 to make it work. Any hints?

  6. English:
    Hello, first "THANKS", excellent so they have managed to do, but I have a doubt, how I can have a predefined table and load the positions from a database?
    Thanks

    Spanish:
    Hola, primeramente "GRACIAS", excelente lo que han logrado hacer, pero tengo una duda, ¿como puedo tener una tabla predefinida y cargar las posiciones desde una base de datos?
    Gracias 😉

  7. firstly, I would like to thank you for sharing. it is very helpfull and usefull.
    I want to use school time table with drag & drop. I have a problem. I use jquery and bootstrap. Timetable is not working with these.
    I think there are some conflicts but i could not find.
    Note: I use metronic admin bootstrap themplate.
    Please help me.
    Thank you for everthing.

  8. Hi, i have implemented your library on a asp.net mvc5 site. I kinda works but i have a question/problem. My dragable item only shows as draggable after i refresh the page. So when i have logged in is is NOT dragable. Only after I refresh the page the item becomes dragable. How do i solve this?

  9. @Claude - If you want to drop DIV elements only to empty cells, please set REDIPS.drag.dropMode to "single". In example01, set radio button to "Disable dropping to already taken table cells" and demo will work in single mode.

    @Amaury - Zooming only DIV elements will disorder table calculation, so my suggestion is to prepare smaller table (without "zoom" style) or to zoom-out whole page. This way drag-n-drop should work nicely.

    @Jeff - REDIPS.drag was initially designed for desktop PC, but it should work for tablets as well - with more or less luck. 😉

    @Jan - With some medium JS skills, you can reuse tooltips from example16. During page initialization, setEvents() method will attach mouseover and mouseout event handlers to all DIV elements. So, this method is a good start point for extracting tooltip functionality.

    @Abraham - If you want to combine REDIPS.drag and database on the backend, please take a look to the example03. To start playing, you will have to read docs and prepare local MySQL database. I have also prepared new version on the GitHub with mysqli API and that will be published on this site soon.

    @Orhan - The latest version of Bootstrap defines a "mark" CSS class, which causes styling issues when used with REDIPS.drag library. New version 5.1 is ready (for now only on GitHub) and all CSS used with REDIPS.drag are renamed:

    drag - renamed to redips-drag
    mark - renamed to redips-mark
    clone - renamed to redips-clone
    only - renamed to redips-only
    single - renamed to redips-single
    trash - renamed to redips-trash
    rowhandler - renamed to redips-rowhandler
    row - renamed to redips-row
    nolayout - renamed to redips-nolayout
    noautoscroll - renamed to redips-noautoscroll
    nodrag - renamed to redips-nodrag
    

    This should resolve problems related with Bootstrap.

    @morten - Your problem may be related to the REDIPS.drag initialization. Please try with page inspection (Chrome has nice Developer tools - F12) to see if redips-drag-min.js is loaded. You can also print lines with console.log() near to rd.init() to check initialization.

  10. i need a code in java script. to take 5 values from the Html(name,lastname, job, address, phno,), by entering this values , i have display them in table form,, i am very thankful to them who send me the code,

    thank you,
    chaitanya.

  11. I get this:

    Uncaught TypeError:
    Cannot read property 'appendChild' of nullredips-drag-min.js:62
    REDIPS.drag.init(index):19 onload
    
  12. HI.
    Looking at example23, each entry has an id and this is used as the $p[] valule.
    Is it possible to add additional values to this so they get passed as $q[], $r[] etc ?
    I'd like to add `data-usr` `data-loc` and `data-phone`

    Thanks

  13. Hi.

    Again using example 23 as the base. Is it possible to make it so only one of each entry can be dragged into the drop zone ? currently I could have multiple copies of each entry.

    I only want one of each !

    Thanks

  14. @sai chaitanya - Hope someone will help and post needed JS code. Cheers!

    @morten - The problem might be related to missing dragging area defined with DIV id="drag". To be more precise, you can include redips-drag-source.js file instead of "min" version and error message will be easier to understand.

    @Tom - Please try to add "climit2_0" class to each DIV element on the left side like:

    <div id="i01" class="drag clone climit2_0" ...
    

    More about climit classes can be read on REDIPS.drag documentation - Appendix A. There can be other way to enable only one drop of the same DIV elements ... like custom JS code inside droppedBefore() event handler. If "false" is returned from this even handler, then dropped DIV element will be canceled.

  15. if (!document.getElementById('redips_clone')) {
        redipsClone = document.createElement('div');
        redipsClone.id = 'redips_clone';
        redipsClone.style.width = redipsClone.style.height = '1px';
        dragContainer.appendChild(redipsClone); // THIS LINE FAILS
    }
    
  16. @morten - The problem is related to the drag container and it seems that your HTML is lacking of DIV id="drag". Please check your HTML because the error is showing in initialization phase.

Leave a Comment