Drag and Drop table content with JavaScript

More...

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+. Please try to drag green, blue or orange bordered DIV elements, change properties (radio button and check-boxes) and click on "Save" button.
Version 5.0.6
Download redips2.tar.gz
You can not drop here
Drag
and
drop
content
with
JavaScript
Table2
and
Drag
drop
table
with
JavaScript
Table3
Clone
(1) Clone
(2) Clone
Trash
Save content of the first table (plain query string)
Save content of the first table (JSON format)
Enable dropping to already taken table cells
Disable dropping to already taken table cells
Switch content
Switching content continuously
Overwrite content
Remove cloned element if dragged outside of any table
Confirm delete
Enable dragging

"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 "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). Script has built in autoscroll and option to forbid landing to the non empty cells or cells named with class "forbid". 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="drag"> to enable content dragging
  • place <div class="drag">Hello World</div> to the table cell

Other features of redips-drag.js:

  • functions and data structure are defined in namespace (easier integration with other JS frameworks)
  • JSLint: No problems found in redips-drag.js (tough one, huh)
  • REDIPS.drag documentation generated with JsDoc Toolkit
  • drag and drop table rows
  • movable div element can contain form elements, images and links
  • forbidding or allowing TDs marked with class name "mark" (depends on "marked_cell" parameter)
  • 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 "clone" class name to the DIV object
      <div class="drag clone">Hello World</div>
    • to limit cloning and transform last object to the ordinary movable object add 'climit1_X' class name
      <div class="drag clone climit1_4">Hello World</div>
    • to limit cloning and transform last object to immovable object add 'climit2_X' class name
      <div class="drag 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 "trash" class name becomes trashcan
  • enabled handlers to place custom code on events: clicked, moved, not moved, dropped, switched, changed, cloned, cloned end1, cloned end2, not cloned, deleted 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.js works?

Script will search for DIV elements (with class name "drag") inside tables closed in <div id="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 (159KB) 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.

Happy dragging and dropping!

This entry was posted on April 6, 2009 and is filed under Drag and Drop, JavaScript

Related posts

931 Responses to Drag and Drop table content with JavaScript

  1. dbunic says:

    @Bruce996 - REDIPS.drag is updated and version 4.6.17 is published. Please see example 18 Simple element animation. Two options "clone" and "overwrite" are added in move_object() method. Now is possible to move element, clone element and overwrite content in target cell.

    @Ron - Yes, REDIPS.drag will work properly only if browser is switched to the strict mode. Otherwise undefined behaviour (like in your description) may occure. After you have posted comments about your case, I wrote a line about it in REDIPS.drag documentation - Appendix A to prevent similar mistakes in the future.

    So, whole library is based on strict mode and unfortunately there is not a way to step back. This is must for a cross-browser compatibility. Quirks mode is not a standard and browsers interprete quirks mode on different way. My suggestion will be to add an effort and migrate HTML to the strict mode. From my experience, after triggering page to the strict mode some (not all) CSS styles will be broken and should be corrected. There should not be so much damage - hope I'm right ...

    @Bruno Jesus - Your comment makes sense. find_cell() should get cell index from last row and not from the first row. I also fixed code for lastInRow case:

    // last in row (cell index for current row)
    case 'lastInRow':
        ri = el.parentNode.rowIndex;
        ci = tbl.rows[ri].cells.length - 1;
        break;
    

    Changes are applied in latest redips2.tar.gz package since 4.6.17 version. Thank you for contributing to REDIPS.drag library. Cheers!

  2. Alex says:

    Hi Darko,
    thanks again for this amazing plugin.
    I'm try to lock the first table header & some left colums and i've found this script:

    http://www.matts411.com/post/super_tables/.

    Do you think is possible to merge your Drag&Drop tool with the over linked tool?

    Thanks in advice!!!
    Alex

  3. dbunic says:

    @Alex - Grid tool you mentioned will not work out of the box with the REDIPS.drag library. As I can see it uses z-index to set two layers. After I added DIV element it's not displayed on the page beacuse it is sent to the back with z-index.

    So it's possible to tweak "Super tables" CSS to make it work with REDIPS.drag. On the other hand you may evaluate the time needed for tweaking Super tables and time needed to make fixed headers on your own way.
    ;)

  4. Alex says:

    Hi Darko,

    thanks for the tip. ;)

  5. Pingback: Drag and Drop table content with JavaScript | Html cool | Scoop.it

  6. stan says:

    Nice work on this library!

    I am wondering if it is extensible to define specific tables. For example:

    Two tables in the same drag container can exchange cell content, but is it possible to define the drag-and-drop parameters for each of those tables? For instance, how would I set drop_option = 'single' for one table and drop_option = 'multiple' for the other table in the same container/view?

    Thank you very much!

    Stan

  7. dbunic says:

    @stan - Yes it's possible to mix drop option with a little help of event handlers. In a moment when DIV element is moved, "drop option" can be set (depending on table source, DIV contanier or any other rule). Please see example 9 Single and shift mode where singe and shift modes are used. JS code is simple and easy to understand, so I hope it will be a good example to start.

  8. stan says:

    Thank you for pointing this out - yes, I see how this is achieved now. It would be great to be able to initiate each tables' parameters (where they are different than the set default) using an init function with arguments for each table instead of building that logic into the methods directly, but this solution will do the trick!

    Do you have plans on extending the multi-select capabilities? For example:
    - click item to select, and use shift-click and control-click to select additional items
    - with drop_option as 'single', drag multi-selection into an empty cell and drop each item into its own cell following, skipping over cells already filled

    Thanks again Darko, this script is incredibly flexible and very friendly to visual customizations!

    Cheers,
    Stan

  9. dbunic says:

    @stan - I already have an example with multi select option. Please see example 12 Select and move more elements. Well, it's not exactly what you asked but the example shows how to select several DIV elements and how to move them to the target cell of dropped DIV element. You can start from this example and build logic for many target cells. It's a bit tricky to define several target cells especially in a case of single drop option. Script should pick only empty target cells.

    Anyway, simple example for "multi-select and move" would be to have two tables with the same dimensions. DIV elements can be freely moved inside table but in moment of moving DIV element to the other table, selected DIV elements can be moved to the same cells in other table ...

    Please take a look to the example18 Simple element animation also, it might be helpful for your case.

    Thanks for using REDIPS.drag library.
    Cheers!

  10. stan says:

    Thanks again for the quick reply Darko :)

  11. perritos says:

    Hi dbunic, great work!
    I need to drop more DIV in a cell table, but I need to manage the order position of each one. I've found only the multiple_drop property that allow to put in the top or bottom of list, but nothing that put the DIV in a specified position.
    It 'a solution available that allows this?
    Thanks in advance

  12. dbunic says:

    @perritos - Yes you are right. Order of elements in a table cell can be defined only with multiple_drop option. Dropped DIV element will be placed to the top or to the bottom. There's no option for placing DIV element to the middle or say to some exact position.

    The main power of REDIPS.drag is simplicity in "dropping layout" creation. Tables are simple - TR/TD elements with applying styles can result with really different looks.

    So, maybe you can use nested tables. Inside cell place another table if DIV order is important. This is just an idea (or workaround) that might help for your case.

  13. Alex says:

    Hi,
    insanely awesome app! Wondering if someone can help me with clone and retaining property. For example I have:

    <div id="test1" class="drag clone">Hi</div>
    

    on the CSS I have:

    #test1{background-color: yellow;}
    

    However when I drag this to the target cell, although it clone the text it did not retain the property (ie the yellow background goes away).

    Probably a simple overlook by me but can someone help!
    thanks in advance.
    Alex

  14. AbdelHamid says:

    Hi thanks for the Greet script, however I found that in the exemple 23 concerning the save to database, the max length for elements is 3, even if you change the redips.code_length to another value it still always be 3.

    So is there a solution to pass for exemple value like 10000 or any thigns that is bigger than 3 digits

  15. Chris says:

    Hi and thanks for this script. I think it will help me with a project. But I need help in understanding how I can save it to MySQL. How should the query be written?

    Thanks,
    Chris

  16. Krishna says:

    Hi ,

    I think i am at right place to fulfill my actual requirement, Can any solve my problem. Please see below list of points.

    1. Initially am have the input fields on the left/right side. On drag and drop on any table the fields will be displayed and width and height of the fields will change some time I have to place the Rich Control also,

    Can any please help me.

  17. Juan Carniglia says:

    Great code!! I used it to develop a "Gantt Like" application, and so far so good. I added a left arrow and right arrow to each side of every drag, in order to grow or shrink each "task" (changing the TD's rowspan dinamically). I am now working on allowing this same feature but using resizable from Jquery UI. Any ideas on this?

    Thank you very much.

  18. barry says:

    Great product just having a little problem, maybe I am missing something.
    I have 2 tables and can drag and drop cell content within each one and also between them.

    I am also able to drag and drop rows within each table, I can also drag and drop rows between tables.

    My question is how can I switch off the dragging and dropping of rows between the tables while keeping this functionality in each.

    Many thanks

  19. kabeeyim says:

    I saved my database to the original position as well as a drag show in the first place

  20. Pingback: Drag and drop table content with JavaScript » Web Design

Leave a Reply

Your email address will not be published. Required fields are marked *

*

In case of posting HTML tags or JavaScript code please convert special characters to HTML entities.
Especially pay attention to convert "<" character to "&lt;" entity!