2
votes

Basically I have a list of draggable items and initially one droppable element for them to be dragged into. When an item is dragged into the droppable, the droppable is cloned (before the item is appended) and appended as a new droppable area.

Take a look at this stripped down fiddle: http://jsfiddle.net/DKBU9/1/ (omitted sortable())

HTML

<ul id="draggables">

    <li>foo1</li>
    <li>foo2</li>
    <li>foo3</li>

</ul>

<ul class="droppable new">

</ul>

JS

$('#draggables > li').draggable({
    appendTo: 'document',
    revert: 'invalid'
});

$('.droppable > li').draggable({
    appendTo: 'document',
    revert: 'invalid'
});

$('#draggables').droppable({
    accept: '.droppable > li',
    drop: function(event, ui) {
        ui.draggable.detach().css({top: 0,left: 0}).appendTo($(this));
    } 
});

$('.droppable').droppable({
    accept: '#draggables > li',
    drop: function(event, ui) {
        if($(this).hasClass('new')) {
            var clone = $(this).clone(true, true);
            $(this).removeClass('new').after(clone);
        }
        ui.draggable.detach().css({top: 0,left: 0}).appendTo($(this));    
    }
});

As you can see, the dragging and dropping works for the initial elements, but is not preserved in the clone. I thought clone(true, true) copied matched and child elements and their event handlers.

I even tried putting the above JS in a function and running that function in the drop events, but I got nothing.

Ultimately I want to be able to drag and drop between the "pool" list and the cloned lists and between the cloned lists themselves, as well as sort the items within the cloned lists.

1

1 Answers

3
votes

Take a look at this fiddle.

You will need to set the droppable event handler again. I think that the clone(true) (i.e. with data and events) confuses things somewhat. Have a look at this answer. Specifically:

I think it is not very safe to copy an element that has a plugin applied to it, unless you are 100% sure that the way the plugin was designed and coded could support multiple DOM elements using the same plugin instance.

In this case it is simpler to just add the droppable event after clone.

The new function is:

function initDrop($element)
{
    $element.droppable({
        accept: '#draggables > li',
        drop: function(event, ui) {
            if($(this).hasClass('new')) {
                var clone = $(this).clone();                
                $(this).after(clone);
                $(this).removeClass('new');
                initDrop( clone );
            }
            ui.draggable.detach().css({top: 0,left: 0}).appendTo($(this));    
        }
    });
}

Also have a look at this question which also found that cloned item was not droppable (have a look at the workaround as well in case it is useful to you).