JavaScript drag and drop plus content shift

Demo is based on REDIPS.drag JavaScript library with enabled shift drop mode. After element is dropped to the cell, other elements will be shifted to make room. Animation is optional and can be turned off. The presented demo (with three tables – normal, colspan / rowspan and marked cells) can be a good start point for various sorting Web applications.


REDIPS.drag example21

Boolean public property animation.shift defines whether shift animation will be turned off or on. Default is off and table content will be shifted instantly. If animation is turned on, then dragging will not be possible while animation lasts. This was needed to prevent possible collisions between animation and dragging.

Drag and drop DIV element inside the same table will actually sort table content. Table content will be shifted to left or to the right side. If new element is dropped to the table, then table content will be shifted to the right. Repeating will result with accumulation of DIV elements in the bottom last table cell. Here is JavaScript code needed for shift table content:

var redipsInit,
    setTable,
    shiftMode,
    overflow,
    shiftAnimation,
    shiftAfter,
    toggleConfirm,
    counter = 0;

// redips initialization
redipsInit = function () {
    // reference to the REDIPS.drag library
    var rd = REDIPS.drag;
    // initialization
    rd.init();
    // set mode option to "shift"
    rd.dropMode = 'shift';
    // set animation loop pause
    rd.animation.pause = 20;
    // enable shift.animation
    rd.shift.animation = true;
    // set TD for overflow elements (initially)
    rd.shift.overflow = document.getElementById('overflow');
    // add counter to cloned element name
    // (after cloned DIV element is dropped to the table)
    rd.event.clonedDropped = function () {
        // increase counter
        counter++;
        // append to the DIV element name
        rd.obj.innerHTML += counter;
    };
};

// set current table
setTable = function (e) {
    var value = e.options[e.selectedIndex].value,
        tables = document.getElementById('drag').getElementsByTagName('table'),
        i;
    // loop goes through all fetched tables within drag container
    for (i = 0; i < tables.length; i++) {
        // skip mini table
        if (tables[i].id === 'mini') {
            continue;
        }
        // show selected table
        else if (tables[i].id === value) {
            tables[i].style.display = '';
        }
        // hide all other tables
        else {
            tables[i].style.display = 'none';
        }
    }
};

// set shift mode
shiftMode = function (radio) {
    REDIPS.drag.shift.mode = radio.value;
};

// set overflow
overflow = function (radio) {
    if (radio.value === 'user') {
        REDIPS.drag.shift.overflow = document.getElementById('overflow');
    }
    else {
        REDIPS.drag.shift.overflow = radio.value;
    }
};

// enable / disable animation
shiftAnimation = function (chk) {
    REDIPS.drag.shift.animation = chk.checked;
};

// enable / disable shift after element is deleted
shiftAfter = function (chk) {
    REDIPS.drag.shift.after = chk.value;
};

// toggles trash_ask parameter defined at the top
toggleConfirm = function (chk) {
    if (chk.checked === true) {
        REDIPS.drag.trash.question = 'Are you sure you want to delete DIV element?';
    }
    else {
        REDIPS.drag.trash.question = null;
    }
};

// add onload event listener
if (window.addEventListener) {
    window.addEventListener('load', redipsInit, false);
}
else if (window.attachEvent) {
    window.attachEvent('onload', redipsInit);
}

Label of cloned elements is increased on every element cloning. Please see how event.clonedDropped event handler was used. REDIPS.drag has many event handlers hooked in different stages to simplify needed customization.

39 thoughts on “JavaScript drag and drop plus content shift

  1. Hello Darko,

    I really hope you don’t hate me for this. :) Just an additional suggestion to help make this even better.

    It would seem more intuitive that once a drag & drop to the trash object has been completed, that all remaining cells be shifted back one to occupy the most recently deleted cell. Perhaps this could be a Boolean property?

    Presently, it leaves the end-user guessing about that “empty box” mid-stream with all the other cells. I find end-users wanting to manually shift cells to back-fill the deleted one.

    Thanks for considering and kind regards,

    Chris

  2. @Chris – First I’m glad you like how shift works. It’s very useful option and new feature moved REDIPS.drag library to the new level. On my first guess, filling the gap after element is deleted should not be a problem to add. In next several days I will prepare new version with a boolean property as you suggest.
    Cheers!

  3. @Chris – REDIPS.drag is upgraded with new feature (ver. 4.5.4). If public property shift_after is set to true, then table content will be shifted after DIV element is moved to the trash cell. Hope this will be fine, cheers!

  4. Hello Darko! Congrats for your great work.

    I’m trying out with your example 9, and I wonder if there’s a function that could make a dragged object return to its first position.

    I want to drag an object to a table cell, and then, make that object return (or appear) in its first position with a click.

    Is it possible? Thanks in advance!

  5. @dbunic – Thanks for your reply! The code works, but I want the dragged object to return to the same specific position.

    Take your example 9. There are four draggable objects and four dropzones. If you add the function undo on clicking a draggable, it returns to the last position, so that means that if you have dragged it from another dropzone (and not the initial position or mark cell) it returns to that dropzone. And what I want is that the dragged object returns always to its original mark cell.

    How do I do this?

    Many thanks.

  6. @David – You are right, Undo will return DIV element to the last position, not to initial position. Anyway, on Drag and drop table content plus animation post (example17) is already implemented JavaScript code for returning DIV elements to the initial position. Please try to move DIV elements and then click on Reset button. All DIV elements will be returned to initial positions regardless of moved rows. In initialization phase, start_positions() function saves locations while reset() function returns elements. I hope this code can be reused for your case.

  7. @dbunic – I’ve been trying out hard, but I can’t reuse that for example 9… When I click a dragged object, all the dragged objects return to their initial positions. But I only want the dragged object that I click to return. Is it possible?

    Many thanks!

  8. @David – Example09 is modified and dblclick on element will return DIV element to initial position. Please click on preview link below post title and try example09. Hope this improvement will be helpful.

  9. Hi Darko,

    Wonderful stuff and you have done a great job here!

    I have a question, I’m using the shift content feature to arrange the sequence of photos in a photo album. It works great. Only that I’m not able to save the new photo arrangement to the server.

    In each cell, I have photo ID and photo order. At each drop, I handle rd.myhandler_dropped event such that I loop through the cells in the table and update the photo order in each cell with a new order number.

    However when I click on ‘Save Photo Order’ button and postback, at the server side I’m still getting the old photo ID and photo order values (as per before arranging the photos). I can’t seem to capture the new values for the photo orders.

    Do you have any suggestions for my problem? Or is there a better way of achieving the objective here? I’m using ASP .Net + VB.

    Thanks in advanced.

  10. @Yenyen – REDIPS.drag contains a primitive save_content() function which scans table(s) and prepares a query string for submitting to the server. It’s only important to set ID for each DIV element. Please take a look to Example01 – Three tables to see how content of first table is sent to the server (save button is placed below tables). Better solution is to use JSON and I hope in next period save_content() will speak JSON.

  11. Hi Darko,

    I have set the photo ID to the ID attribute of each DIV, parse the content that is sent via save_content() and save the photo order at the server side. It is working now, thank you so much!

  12. Dear dbunic

    I want to implement this on my page. can simply add the above javascript in my page and how should i provide my div id or table id. is there any jquery you have created which i should download and add in my page or simply by adding above javascript it works please provide me steps to implement this

  13. @Yenyen – I’m glad your problem is solved and saving pictures is working.

    @surat narayan tripathi – REDIPS.drag is a library needed to include in HTML page. After redips-drag-min.js is included, above script will configure (behaviour) of drag and drop. Here are minimal steps needed for drag and drop to work:

    * put <script type="text/javascript" src="redips-drag-min.js"></script> in head
    * 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
    

    Instead of initialization in body onload, you can write JS code in separate script.js file (like I did in all examples inside redips2.tar.gz package – except example0).

  14. Hello Darko,

    Great library you have here, and thanks for making it available to us.

    I’m new to Redips drag-n-drop and can’t resolve a problem I’m having with my code. Basically, my code includes a section header with a draggable handle on the right and a clickable image on the left that will mark the entire section for deletion. I’m not sure if the HTML won’t get messed up here, but here’s the code:

    —–

    Intro

    Lorem ipsum dolor sit amet

    Verse

    Lorem ipsum dolor sit amet

    —–

    What I can’t figure out is why I can’t successfully attach a jQuery “delegate” click event handler to “a.section_del_btn”. It seems as if the Redips drag-n-drop code prevents the “delegate” function on the “a” tag/element from working. What a click on the anchor link (image) will do is to toggle the image “src” between “check.png” and “uncheck.png”.

    Would you by any chance have any suggestion on how to go about it?

    Would appreciate any suggestions you may have on this.

    Thanks in advance!

  15. Hi Darko,

    I’m unable to include the sample code/ structure here for you to see. I’m sorry.

  16. Hi Oscar!

    You can email me JS code to attach it to your comment.

    Anyway, onclick event of DIV element is reserved for dragging and there can’t be another listener for that event.
    But you can place your custom code inside:

    myhandler_clicked()
    myhandler_dblclicked()
    

    event handlers to be executed on DIV element click (or on double click).

  17. hi Darko,
    I have two checkbox in my form page, I have to give value like R & W , I want store one value, pls help me.

Leave a Comment