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. @ajay mishra – Unfortunately I’m not so familiar with JSP, but hope someone will post a simple solution in JSP. Generally speaking, REDIPS.drag will post variables as any HTML form. It’s only needed to accept variable on the server side. Here is example of query string:

    p[]=d1_1_0&p[]=d2_1_2&p[]=d3_1_3&...
    

    or it can be in JSON form:

    p=[["d1",1,0],["d2",1,2],["d3",1,3],...
    

    So, if you can accept posted variables from HTML page then it will be no difference to accept “p” variable from REDIPS.drag lib.

  2. I define a object to reference to REDIPS.drag:

    var rd = REDIPS.drag;
    rd.init();
    

    When I was debugging in firefox, I got this error:

    TypeError: rd is undefined
    [Break On This Error] 	
    
    rd.init();
    

    Please explain to me, thank you!

  3. @Phuong Tran Tuan – REDIPS.drag should be initialized after page is completely loaded. In your case it’s possible that init() method is called before redips-drag-min.js is loaded. Here is startup routine that should work:

    // define redips_init method
    var redips_init = function () {
        REDIPS.drag.init();
    };
    
    // add onload event listener
    if (window.addEventListener) {
        window.addEventListener('load', redips_init, false);
    }
    else if (window.attachEvent) {
        window.attachEvent('onload', redips_init);
    }
    
    
    				
  4. @SH – Here is PHP example how to process JSON data:

    // accept JSON parameter (and Un-quote string if needed)
    $p = stripslashes($_REQUEST['p']);
    // decode JSON object (it shouldn't be decoded as associative array)
    $arr = json_decode($p);
    // open loop through each array element
    foreach ($arr as $p){
        // set id, row index and cell index
        $id = $p[0];
        $row = $p[1];
        $cell = $p[2];
        // instead of print, you can store accepted parameteres to the database
        print "Id=$id Row=$row Cell=$cell
    "; }

    This is multiple-parameters-json.php from example01 so it’s already included in redips2.tar.gz package.

  5. thanks for your comment. But what i mean is: After i stored all information in an database…
    I read them, and now i want to set all stored parts back to the timetable so that the new loaded timetable show me all information in the right place.

  6. @SH – OK, now I understand. Restoring saved positions of DIV elements can be done with a little help of server side. After user saves current state to the database and next day opens timetable, PHP (or ASPX, JSP, Perl …) script can dynamically generate HTML table with all DIV elements already placed in table cell. Once user has so prepared table it can continue editing DIV elements. This is exactly how example03 works from redisp2.tar.gz package. Sure, to have demo working, please read readme.txt how to configure PHP/MySQL.

  7. I’m not good at english…. My question: how can I delete item from left column atfer move this one ? I need for my using delete moved item in left column. Thanks. Lubo

  8. @Lubo – In this demo, left column contains “clone” type DIV elements. In the moment of dragging, new DIV element will be cloned and number of cloned DIV elements is not limited. But it’s possible to set limit of cloned DIV elements – please see REDIPS.drag documentation – Appendix A and example02.

    On the other hand, you can place custom code in event.clonedDropped() event handler to delete cloning source. This code will delete clone source after dropping first cloned element to the table:

    rd.event.clonedDropped= function () {
        // set reference to the source DIV element
        var source = rd.objOld;
        // delete clone source DIV element
        source.parentNode.removeChild(source);
    };
    

    Hope this tips will be helpful for you.

  9. Hello Darko, your samples are great. I am working with example03 and example01. When I work with the example03 and I have replaced code as you write in file ajax/readme.txt my IE ver 8.0 has error. This happened after Save:

    Message: Object expected
    Line: 86
    Char: 1
    Code: 0
    URI: ...localhost/REDIPS_drag/example03/index.php
    

    But items from table are inserted. Where is the problem ?
    Mozilla works correct.

  10. @Lubo – Printed error may be related to the missing element like DIV id=”message”. Please take a look to the printMessage() function and try to comment out every call of this function (it’s not crucial). I have prepared example03/ajax demo locally and test in IE8 but can’t force the described error.

  11. Thanks for the cool work!
    This example is close to what I am needing, except that the blocks on the left, such as ‘History’ would represent a grid such as 3×4. When I drag the History grid into the table, I need History to fill in 3 columns and 4 rows in the table.

    Is that possible with this “REDIPS.drag” library?

  12. @Jon – So, you will have a big table on the right to allow filling 3×4 cells ;). Automatic cloning of dropped DIV elements is out of REDIPS.drag domain. As you can see in example03, filling a row is placed within event.dropped() event handler. The only trick is to clone DIV element with cloneObject() method and append to table cell. Harder part is to loop through right table and to define 3×4 rectangle depend on target cell. You can start from example03 and try to add row loop (because in this School timetable example, DIV elements are expanded through single row and therefore is needed only one loop).

    Bottom “if” line and reportButton() is not needed for your case and this can be removed.

  13. Hi dbunic,

    Great work on the examples! I really enjoy using them and I’m learning quite a bit of Javascript from them! But alas, I have a question.

    In this example, you have it set up so that the user can click and drag any course into their timetable. But what I was wondering was if there was a way to check and see if a cell already has a specific course (for example, Monday at 11:00 has English) and then preventing that same course to be added again during that same day and leaving that cell empty (so English at any other time on Monday would be rejected).

    I can’t figure out what exactly I need to do so that I can create this validation. Please help!

  14. Also, I have done something similar to this, but with the use of buttons and tags. I’m pretty sure the logic is sort of the same, but it’s different since this involves dragging and dropping and it’s dynamic and what I made was clicking a button and then clicking on a tag so that the value stored in a variable would be set to a paragraph within a table cell (for example, clicking on a button that has a value of “English” stores that value in a variable and then clicking on a paragraph tag would set the value of it to “English”).

    Am I on the right track?

  15. Hi Saro!
    If you want to execute checks before dropping DIV element to the table you can place your JavaScript code in droppedBefore(targetCell) event handler. Here is small example how to use it:

    // event handler invoked before DIV element is dropped to the table cell
    rd.event.droppedBefore = function (targetCell) {
        // id of dropped DIV element (only two first chars)
        // cloned elements contain cNN suffix
        var id = rd.obj.id.substr(0, 2);
        // targetCell is reference of TD where DIV will be dropped
        ...
        ...
        // here goes JS code to test already dropped DIV elements to the same column
        // and if DIV with the same first two chars of ID is found then return false
        return false
        ...
        ...
    };
    

    So, if “false” is returned from this event handler, then DIV element will not be dropped to the highlighted cell. In this example is needed to compare first two chars of ID. Source element for Physics have id=”ph” but all cloned elements will have phc0, phc1, phc2 …

  16. Hey again!

    So while I appreciate the help and ideas that you’ve shared, I’ve got another problem. I’m trying to code the line where you wrote “// targetCell is reference of TD where DIV will be dropped”. The problem with this is that I have no idea how to interpret this as javascript code! I’m very new to javascript and would like to be more knowledgeable on the subject. So I’ve done quite a bit of research to try to figure out how to get this done, but it seems like no one has tried to do this themselves before and therefore, there’s no completed reference to check upon!

    Also, for the lines where it state “// here goes JS code to test already dropped DIV elements to the same column and if DIV with the same first two chars of ID is found then return false”, I can only guess that it’s some form of a long and tedious if statement? What I’ve done so far is give all the “<” td “&rt;” tags an id that corresponds to their day and position and have tried an example where if (id == “some substr value” && document.getElementById(“monday1”).innerHTML == “some substr value”) would then return false and create an alert if the user tried to drop the same value onto the same day but at a later time. Please tell me if I’m on the right track!

    Thanks in advance!

  17. @Saro – Here is complete JS code that will prevent dropping subject to the column which already contains the same school subject. Just copy-n-paste this event handler to the script.js file and you will not be able to have two “Physics” in the same column:

    // prevent two subjects in the same column
    rd.event.droppedBefore = function (targetCell) {
            // ID of dropped DIV element (only first two chars)
        var id = rd.obj.id.substr(0, 2),
            // reference to the target table
            tbl = rd.findParent('TABLE', targetCell),
            // set column where DIV element is dropped
            col = targetCell.cellIndex,
            // local variables
            subject, cell, i;
        // loop goes through all rows in target table
        for (i = 0; i < tbl.rows.length; i++) {
            // define cell in a target column
            cell = tbl.rows[i].cells[col];
            // cell can be undefined in case of colspan (lunch row)
            if (cell !== undefined) {
                // skip target cell if is the same as source cell
                // DIV belongs to source cell in droppedBefore stage
                if (cell === rd.td.source) {
                    continue;
                }
                // each cell can have only one subject
                subject = cell.getElementsByTagName('div')[0];
                // if subject exists and is the same as dropped DIV element
                if (subject !== undefined && id === subject.id.substr(0, 2)) {
                    return false;
                }
            }
        }
    };
    
  18. I want to do for ex arts lesson has 3 hour on a week how to stop after 3 hour distribute
    this is puts for every lesson 5 hour from monday to friday automaticly.so every lessons has different hour a week one leson 3 hour another lesson 5 hour if you dont want to use trash how to distribute like that

Leave a Comment