JavaScript Drag and Drop example 3

School timetable is example of how to use REDIPS.drag library. Page layout contains two tables – left table with school subjects and timetable on the right. After subject is placed to timetable, button in the same color will be displayed next to the subject (clone object).

REDIPS.drag example03

Please note two checkboxes in upper left timetable corner. First checkbox is turned on by default to enable cloning subjects across a week. You can turn it off for placing single subject to timetable. If second checkbox is checked, then “subject report” will pop up if report button (button next to subjects in left table) is clicked. At the same time, all other subjects will be hidden. Clicking on any element in left or right table will show up all elements.

The following code shows event.dropped() event handler (with logic for cloning DIV elements across a week).

rd.event.dropped = function () {
    var objOld = rd.objOld,                // original object
        targetCell = rd.td.target,         // target cell
        targetRow = targetCell.parentNode, // target row
        i, objNew;                         // local variables
    // if checkbox is checked and original element is of clone type
    // then clone spread subjects to the week
    if (document.getElementById('week').checked === true &&
        objOld.className.indexOf('clone') > -1) {
        // loop through table cells
        for (i = 0; i < targetRow.cells.length; i++) {
            // skip cell if cell has some content
            // (first column is not empty because it contains label)
            if (targetRow.cells[i].childNodes.length > 0) {
                continue;
            }
            // clone DIV element
            objNew = rd.cloneObject(objOld);
            // append to the table cell
            targetRow.cells[i].appendChild(objNew);
        }
    }
    // print message only if target and source table cell differ
    if (rd.td.target !== rd.td.source) { 
        printMessage('Content has been changed!');
    }
    // show / hide report buttons
    reportButton();
};

Source code (including school timetable with save/recall table using PHP and MySQL) and detailed description of library can be found on Drag and drop table content with JavaScript.

176 thoughts on “JavaScript Drag and Drop example 3”

  1. @Razmataz – Cloning from cloned elements is possible. Please try example11 – actually copy HTML of circle clone DIV element to the mini table above and reload page. You will see that cloned mini table will contain circle element with remain clone option. So technically it’s possible, but the lib will not take care about unique ID set of DIV elements. There still needs some work to do.

    In a new version, “overwrite” code around line 1037 will be replaced with a function and exposed as a empty_cell() public method. Here is JavaScript code:

    /**
     * Method removes elements from table cell.
     * @param {HTMLElement} td Table cell from which all elements will be deleted.
     * @example
     * // set REDIPS.drag reference
     * var rd = REDIPS.drag;
     * // search for TABLE element (from cell reference)
     * tbl = rd.empty_cell(td);
     * @return {Boolean} Returns false if input element is not table cell.
     * @public
     * @function
     * @name REDIPS.drag#empty_cell
     */
    empty_cell = function (td) {
        var i,  // local variable
            cn; // number of child nodes 
        // if td is not table cell element then return false
        if (td.nodeName !== 'TD') {
            return false;
        } 
        // define childnodes length before loop
        // (not in loop because NodeList objects in the DOM are live)
        cn = td.childNodes.length;
        // delete all child nodes from td
        for (i = 0; i < cn; i++) {
            td.removeChild(td.childNodes[0]);
        }
    };
    

    Please be free to add a comment to improve this method. Thanks in advance.

  2. Great work!

    I’m trying to use this example for a prototype scheduler (internship assignment), however i have a little problem (i think). I disabled the rule that a cell may only contain 1 item (so now it can contain more), but now the left bar with subjects can also contain more than one, what not really usable is. Is it possible so that 1 table can have more items in a cell, and that another table is unable to do that?

    >is it also possible to add a class to cells, so that those cells cannot contain more than 1 item? Or should i just change script.js so that it behaves that way?

    Offcourse thanks again for this great javascript library! Great that it works for most/all browsers!

  3. It’s possible to do switch between two div in two tables separate by containers?

  4. @Rub3s – I’m glad your problem is solved!

    @Cristian Juvé – If you have separated drag containers then you will be unable to drop DIV element to other container. Please see Example 8: Tables in separated containers. Anyway, several tables can belong to the same drag container (like in “School timetable” example) and elements can be exchanged among them.

  5. Great code and great example! But I can’t figure out how to add Saturday and Sunday safely I can get them to display, but can’t drag items into their fields. Any help/ideas? Big Thanks

  6. @Andrew – You have to expand table with two columns. Added table cells must automatically be available for drag and drop action. Just be sure that newly added cells don’t have mark class name because this class has special meaning. If cell is marked with mark class name then this table cell is forbidden for dropping elements. On the same way table header is defined to not accept any DIV element.

  7. Thanks for the comments. Still no luck.
    I’ve created the extra columns in the table exactly how you have it in your code. Saturday works fine, but Sunday doesn’t work at all. I’ve also updated the config file too to loop to COL<=7. I've added:
    Saturday
    Sunday
    What if I wanted to do month. Is there code that knows that week is only 7 days, so 0-6 works only.
    Thanks

  8. @Andrew – Maybe the problem is due to DIV#drag dimensions. Please add the following style to the style.css file:

    #drag {
        border: 1px solid lime;
    }
    

    This will make DIV#drag visible. So if DIV#drag is smaller then table, then some columns may not work. Just set correct width to the drag region and dragging should work fine.

  9. The CSS. One thing I didn’t really bother to check into. Thank you so much, Hope this question and answer helps out others!! Thanks

  10. Hi dbunic. I’m trying to use this timetable for a project but I have a problem. I want to add subjects and this subjects have a corresponding code like eng 0 for english. But I don’t know how to do this because of the parsing of id in the code. I hope you understand what I mean and sorry for my english.

  11. @rosie – Adding new subjects should not be a problem. Please see database.sql file. redips_subject table uses char(2) as table key – you only need to define key for new subject and insert it to the table. After subject is inserted, it should be displayed on the left side right away. Here is example of how to add two subjects:

    insert into redips_subject values 
    ('ge','Geography'),
    ('sc','Science');
    

    example03 uses subject id as class name so you will need to add colors for new subjects to the style.css file as well.

    .ge {
    	background-color: red;
    }
    .sc {
    	background-color: lime;
    }
    
  12. Thanks dbunic. I have one more question. I want to add a login feature, how can I make the table read only?

  13. @rosie – You can disable table with following method:

    REDIPS.drag.enable_table(false, 'tbl1');
    

    First parameter is boolean true/false while second parameter is table class name. This method can disable/enable more tables at once.

  14. Hi dbunic! it’s me again. Is there a way to merge table cells that have the same subject and put back the cells when dragged or deleted? I know I’m asking too much but I’m just hoping. Thanks.

  15. @rosie – REDIPS.drag library is primarily focused on drag and drop DIV elements / table rows. Currently there is no option to merge/split table cells.

  16. Regards dbunic!!!

    Thanks for your awesome work!!! it’s fantastic!!!!

    My situation is the next:

    I have an “input hide” element inside a div drag and i wish get access to their value and send it into the ‘q’ string when save function is called.

    I was reviewing the save function and i suppose i can get the value when set reference to the child node but i don’t have much idea. Can you help me please? Thanks again and my apologies for my bad english.

    I hope you understand my trouble.

    Regards from Mexico!!!!

  17. I want to be able to delete subjects from table1 when dragged to trash like the subjects in table2. How can I do that?

  18. @David Roa – Here is modification of save_content() method. First declare two variables at the method top (hidden input element and its value):

    var hinput, v;
    

    Inside the loop that iterates through DIV elements replace the original code with this:

    // childNode should be DIV with containing "drag" class name
    if (cn.nodeName === 'DIV' && cn.className.indexOf('drag') > -1) {
        // collect input elements within DIV element
        hinput = cn.getElementsByTagName('input');
        // set value of hidden input element
        // (suppose that there is only one hidden input element)
        v = hinput[0] !== undefined ? hinput[0].value : '';
        // prepare query string-
        query += pname + '[]=' + cn.id + '_' +  r + '_' + c + '_' + v + '&';
        // push values for DIV element as Array to the Array
        JSONobj.push([cn.id, r, c, v]);
    }
    

    I assumed that each DIV element will contain only one hidden input element. If not, then only value of the first hidden input element will be added to the “p” parameter. Hope this code snippet will give you an idea of how to append needed data to the output query string.

    @rosie – Please download latest redips2.tar.gz package version 4.6.11+. Here is code to delete clone type element from the right table:

    // called after element is moved to the trash cell
    rd.myhandler_deleted = function (cloned) {
        var el;
        // if cloned element is directly moved to the trash
        if (cloned) {
            // set reference to the original DIV element
            el = rd.obj_old;
            // remove original DIV element
            el.parentNode.removeChild(el);
        }
    };
    

    In short, if cloned DIV is directly moved to the trash then script will delete cloned and original element. Reference of original element is stored in REDIPS.drag.obj_old public property.

  19. Hi,

    I want to load table 1 (left side) dynamically using jquery ajax or javascript ajax.

    when i was tried the ajax /load the drag option for left table1 was disabled .

    Pls help me to load the left table(table one content) dynamically..

    Thanks

Leave a Comment