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. Hi dbunic,

    I need one more thing..

    When i picking the left table subject , that can be drop only to the particular period. It must satisfied some constrains like below:

    For example ” Art ” subject can only place in Friday not to other days .. also the mathematics period cannot be placed at the last period of a day (it must place any period expect the last period).. like that..

    Can it possible ?

    Pls help me

  2. @Prabu – Table can be dynamically added to the “drag” container. After table is added, just call REDIPS.drag.init() method. Example 0: AJAX / jQuery modification shows scenario where table is loaded on button click using jQuery.

    REDIPS.drag has options to define dropping rules. Please see:
    Example 7: A B C D
    Example 7: E F
    I also wrote REDIPS.drag documentation – Appendix A where you can find explanation with examples for mark and only class name keywords.
    Cheers!

  3. Hi Dbunic! You’ve been really helpful but I still got one problem: I add some information along with the subjects like name of the professor and room number, but I don’t know how to pass this additional information to db_save and store it to timetable table. How can I do that? Thanks.

  4. @Prabu – If you can prepare standalone example or send me URL of your online example I will gladly help you. In case of standalone example, prepare your code so I can unzip it and test with local Apache/PHP.

    I suppose that problems are related to REDIPS.drag initialization but can’t be sure without peek to the code.

    @David Roa – You’re welcome and thanks! ;)

    @rosie – One way can be to append professor id and room number to the DIV id. In this case, DIV id can look (please note it’s used dash, not underscore):

    <div id="1234-2-22">Mr. Brown, room 22<div>
    

    On the server side, DIV id should be decomposed:

    foreach ($arr as $p) {
        // detach values from combined parameters
        // $tbl parameter is ignored because saving goes only from table 1
        list($sub_id, $row, $col) = explode('_', $p);
        // $sub_id contains professor id and room number
        list($sub_id, $prof_id, $room) = explode('-', $sub_id);
        // discard clone id part from the sub_id
        $sub_id = substr($sub_id, 0, 2);
        // insert to the database
        ...
        ...
    }
    

    This is only an idea, but it should be feasible … If you will have further questions, don’t hesitate to ask. Cheers!

  5. dbunic it’s not working. I tried to echo it, it always says undefined offset. I did it like this:

    config.php

    <div id="$id-$prof-$room">
    

    db_save.php

    list($sub_id, $prof, $room) = explode('-', $sub_id);
    echo $prof;
    

    Where am I doing it wrong?

  6. @rosie – My guess is that you have somewhere glitch in code and it’s not easy to fix it without having access to all parts. Anyway, I have prepared example with $prof and $room so you can try to use this modification.

  7. Hi dbunic!
    I was able to save into timetable (database table) the additional information I wanted to add, so that when printing the subjects to timetable (grid) I don’t have to refer to other table but the timetable alone and also so I could delete the list of subjects in the left. (I hope you understand what I mean). But when I clone the elements the information is deleted leaving it (DIV) blank. What I’m just trying to achieve here is to be able to delete the subjects in the left side without the subjects in the timetable being affected.

    Thanks.

  8. @rosie – I’m glad you succeeded to save additional data to the database. Maybe the problem is related to the SQL select. If subject is deleted from database, then SQL to retrieve grid table could not join redips_timetable with redips_subject data. Here is original SQL from example03:

    select
    concat(t.tbl_row,'_',t.tbl_col) as pos,
    t.tbl_id,
    t.sub_id,
    s.sub_name
    
    from
    redips_timetable t,
    redips_subject s
    
    where
    t.sub_id = s.sub_id
    

    Instead of inner join, you can try with left join:

    select
    concat(t.tbl_row,'_',t.tbl_col) as pos,
    t.tbl_id,
    t.sub_id,
    ifnull(s.sub_name, t.sub_id)
    
    from
    redips_timetable t left join redips_subject s on (t.sub_id = s.sub_id)
    

    This should retrieve data from redips_timetable regardless of state in redips_subject db table.

    Hope this was your question.
    Cheers!

  9. Hi dbunic. It’s still not working.

    subjects:

    $subjects = sqlQuery("select SubjectID, Subject, Instructor, CollegeID, Course, Year, Section
    from subjects
    where CollegeID='$_SESSION[college]'
    order by SubjectID");
    

    timetable:

    $rs = sqlQuery("select concat(t.tbl_row,'_',t.tbl_col) as pos, t.tbl_id, t.sub_id, t.subject, t.instructor, t.college, t.course, t.year, t.section
    from timetable t left join subjects s on (t.sub_id = s.SubjectID)
    where t.room='$idid'");
    

    I can drag the subjects just fine but when I clone it using shift key the data saved in timetable columns are deleted except the data in sub_id, tbl_id and pos columns. Is there another way to delete the subjects without affecting the timetable?

    I’m sorry to bother you this much. Thanks.

  10. @rosie – It will be much easier if you can send/show me the live example. Please try to make database dump with mysqldump utility and zip it together with Web scripts (PHP and JS files). I will prepare your example locally on my LAMP computer and try to fix the problem. Hope this will not be a problem for you. Here is how you can save database content on Linux host:

    # subject table
    mysqldump -p -u<username> <database> subjects > /tmp/subjects.sql
    
    # subject table
    mysqldump -p -u<username> <database> timetable > /tmp/timetable.sql
    
  11. It’s very kind of you but I don’t think it’s a good idea. My codes are messy plus I already altered a lot. I just want to have an option to delete the list of subjects on the left but I think that’s impossible right now. I’ll just stick to your old code. Thank you so much. :)

  12. @rosie – OK, but I have one more idea that may help you. Instead of deletion subject from the left table, you can hide them. Here is how:

    1) Expand db table subjects with column display char(1):

    ALTER TABLE subjects ADD COLUMN display char(1) NOT NULL DEFAULT 'Y' AFTER sub_name
    

    All existing subject should have Y value in display column.

    2) Modify subjects() function in config.php to retrieve only visible subjects:

    // returned array is compound of nested arrays
    $subjects = sqlQuery("select sub_id, sub_name from subjects where display = 'Y' order by sub_name");
    

    3) Try to update subjects as hidden:

    update subjects set display = 'N' where sub_id = 'hi'
    

    Timetable (on the right) should stay intact while subject from the left table is not shown.

    Hope this will do the trick ;)
    Cheers!

  13. @wethuu – REDIPS.drag library allows drag and drop DIV elements across one or many tables. DIV element can be resized in a moment of dropping DIV to the table. Here is JS code where DIV element will be resized to the full width of the target cell (can be useful if table cells have different width):

    // event handler invoked before DIV element is dropped to the table cell
    rd.myhandler_dropped_before = function (target_cell) {
        // set new width to the dropped DIV element
        var width = target_cell.offsetWidth;
        // set width and reset height value
        rd.obj.style.width = (width - 2) + 'px';
        rd.obj.style.height = '';
    };
    
  14. Hi Bunic,

    This is rami from Chennai, India.

    Here we are trying to develop redips drag and drop control in mvc3 but not getting filled cell values to the controller .
    Do you have any idea about this in mvc3.

    Pls let me know.

  15. @rami reddy – I’m entirely new to the ASP.Net MVC3 framework (my scripting background is PHP). Anyway, REDIPS.drag is developed in a way to be completely independent from server side. With a few customizations it should fit to the MVC3 as well.

    So, if you need to send information to the server for each DIV element drop, you can write small JS code inside myhandler_drop event handler. Here code snippet from example03/ajax/script.js file:

    // save - after element is dropped
    rd.myhandler_dropped = function () {
        // get element position (method returns array with current and source positions)
        var pos = rd.get_position();
        // save table content
        send_request('ajax/db_save.php?p=' + rd.obj.id + '_' + pos.join('_'));
    };
    

    As you can see, on each element drop REDIPS.drag can fire AJAX call to the server and save element position. It’s also possible to lock dropped element until AJAX callback unlock dropped element. Displayed code is from redips2.tar.gz package.

    @upravitelj – Thanks … or I can say “Hvala” on Croatian ;)

Leave a Comment