jquery draggable +sortable with custom html on drop event?

14,315

Solution 1

Check this DEMO http://jsfiddle.net/yeyene/7fEQs/8/

You can customize your dropped element as you wish.

$(function() {
    $( "#draggable li" ).draggable({
        connectToSortable: "#sortable",
        helper: "clone",
        revert: "invalid"
    });

    $( "#sortable" ).sortable({
        revert: true,
        receive: function(event, ui) {
            var html = [];
            $(this).find('li').each(function() {
                html.push('<div class="toggle">'+$(this).html()+'</div>');
            });
            $(this).find('li').replaceWith(html.join(''));
        }
    });
});

Solution 2

This is a very basic example but should be applicable for several different cases. I took the jQuery UI Draggable + Sortable example and besides the .sortable() widget I bound the .droppable() widget to the <ul id="sortable"> element. Even though not the smartest way in the drop event of the droppable widget I check the value of a variable to identify the origin of the moved element. (does it come from the sortable list or from one of my draggables?) If it does come from one of the draggables I change the HTML of it to what I want. Otherwise it remains the same (because you just rearrange the order of the sortable)

HTML

<ul>
    <li id="draggable" class="ui-state-highlight">Drag me down</li>
</ul>
<br />
<br />
<br />
<ul id="sortable">
    <li class="ui-state-default">Item 1</li>
    <li class="ui-state-default">Item 2</li>
    <li class="ui-state-default">Item 3</li>
    <li class="ui-state-default">Item 4</li>
    <li class="ui-state-default">Item 5</li>
</ul>

JS

$(function () {
     var origin = 'sortable';
     $("#sortable").droppable({
         drop: function (event, ui) {
             if (origin === 'draggable') {
                 ui.draggable.html('<span>Look at this new fancy HTML!</span>');
                 console.log(ui.draggable);
                 origin = 'sortable';
             }
         }
     }).sortable({
         revert: true
     });
     $("#draggable").draggable({
         connectToSortable: "#sortable",
         helper: "clone",
         revert: "invalid",
         start: function () {
             origin = 'draggable';
         }
     });

 });

jsfiddle for demonstration

Quite a boring example because the new HTML is static. But let's say you have a custom helper for each draggable and this should become your new HTML. Therefore you e.g. have stored some HTML fragments in an array and choose the matching entry suitable to the index or what so ever. This would somehow look like that:

var helpersArr = ['<input type="text" />', '<input type="file" />', '<input type="submit" value="Save" />'];
var helper;
//draggable
helper: function () {
    helper = helpersArr[$(this).index()];
    return helper;
}
//dropppable drop function
ui.draggable.html(helper);

jsfiddle for second example

Pretty sure you could also achieve the same result by avoiding the helper variable and use ui.helper instead but I couldn't figure out how to get the HTML portion of it. If this doesn't work how you need it, just inform me. Altogether I think you can use my examples as a start for different goals concerning to change the HTML of the dropped element.

Solution 3

I had a similar problem that required a far more elaborate outcome. My system was dragging from a div on the left that contained other divs with form element names and ids, which dropped into a sortable div on the right that was to become a webform. Because I needed the div on the right to closely resemble the contents of a form without extra markup, using an unordered list was out of the question unless I wanted to do a bunch of "scrubbing" on the way into the database. No thanks. In my example, when I drag from the list on the left, I have to use the id of the dragged element to look up a number of things via ajax, and then place a label, form element, and validation into the list on the left based on the results of that ajax. For clarity's sake, I removed the ajax from my example.

So, in essence, you're taking two side-by-side divs, doing draggable and sortable with list connection. The key is that there are callback functions in Sortable that you have to make use of. The "Receive" callback will fire only when a new element is added to the sortable list. This is important, because you have to differentiate so your change doesn't occur on sort as well. You can't solely use "receive" though, because if you try to manipulate the html in that callback, you'll affect the list your dragging from, not the list you're dragging TO. To keep track of whether it's a list add or a drag, I set a variable called "newlement" in $.data to 1 if its a list add, which I then check in the update callback to see if I should effect the dragged html or not. In my case, I don't want to do anything to an element that's dragged.

So, the HTML:

<div class='master_list'>
  <div id="2">First Name</div>
  <div id="3">Last Name</div>
</div>

<div id="webform_container">
</div>

And the jQuery:

$( ".master_list div" ).draggable({
    connectToSortable: "#webform_container",
    helper: "clone",
    revert: "invalid"
});


$( "#webform_container" ).sortable({
    revert: true,
    cursor: 'pointer',
    placeholder: "placeholderdiv",
    connectWith: '.master_list',
    start: function() {
            /* Clear the value of newelement at start */
        $(this).data('newelement', 0);
    },
    receive: function(event, ui) {
            /* Get id from function and pass to the update to do stuff with */
        $(this).data('id', ui.item[0].id);
            /* Set value of newelement to 1 only when new element is added to list */
        $(this).data('newelement', 1);
    },
    update: function(event, ui) {
        /* If newelement ==1, this is a new element to the list, transform it */
        if ($(this).data('newelement') == 1) {
            var fieldname = ui.item.text();
            ui.item.html('your new html here');         
        }
    }

});

Solution 4

Check out the documentation on sortable. You can use the ui element to change the html of the dropped object

http://jqueryui.com/demos/sortable/#event-update

you can also see examples of connected lists here and the events that are fired

http://jqueryui.com/demos/sortable/#connect-lists

The update event is where you would change the html of the element.

Share:
14,315
Jean Michael
Author by

Jean Michael

Updated on June 28, 2022

Comments

  • Jean Michael
    Jean Michael almost 2 years

    Change html when drop element in droppable area.

    Something like this: http://the-stickman.com/files/jquery/draggable-sortable.html

    But when I drop element change placed html.

    Other Example: I have 2 lists first draggable list and second droppable list, when i drag element from a first list and i drop this element into a second list, the element will be cloned to the second list

    dragging:

    <a href="#">test</a>
    

    drop:

    <a href="#">test</a>
    

    i want to change this html to

    dragging:

    <a href="#">test</a>
    

    drop:

    <div class="toggle"><a href="#">test</a></div>
    
  • Admin
    Admin about 9 years
    this is what I am looking for, except I want to load html from the server/db. Can you please share the Ajax, how you're avoiding the scrubbing and appending.
  • Admin
    Admin about 9 years
    Hi, rather than this var helpersArr = ['<input type="text" />', '<input type="file" />', '<input type="submit" value="Save" />']; can you share how to load this from the server/ajax, i.e. making the filled items dynamic?