DND - INTELLIGENT DROP ZONES

by bizamajig

HTML

<script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<ul id="draggables">

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

</ul>

<hr>

<ul class="droppable new">

</ul>

CSS

ul { list-style: none; }
li { cursor: pointer; }

#draggables, .droppable {
    border: 1px solid;
    padding: 10px;
}

.dragging
{
    visibility:hidden;
}

.droppable.new { border: 1px dashed; }

JavaScript

var $draggingParent = null;

$(function() {
    
    initDraggable($('#draggables > li'));
       
        
    $("#draggables").droppable({    
    drop: function(ev, ui) {
        if($draggingParent[0] === $(ui.helper).parent()[0])
        {
            //dragged from draggables to draggables
            $(ui.draggable).removeClass('dragging');
        }
        else
        {            
            if(ui.draggable.parent())
            var $clone = $(ui.draggable).clone();
            $(ui.draggable).remove();
            $clone.removeClass();
            $clone.removeAttr('style');
            initDraggable($clone);
            $(this).append($clone);        
        }
    }
});
    
    initDroppableSort($('.droppable'));
    
});

function initDraggable($element)
{
    $($element).draggable({
        connectToSortable: '.droppable',     
        revert: function(droppableObj)
        {
            if(droppableObj === false)
             {                
                $(this).removeClass('dragging');
                return true;
             }
             else
             {              
                return false;
             }
        },
        helper: 'clone',
        start: function(e, ui)
        {           
            $draggingParent = $(this).parent();
           $(this).addClass('dragging');
        }
    });
}

function initDroppableSort($element) {
    
    $element.sortable({
       items: 'li',
        connectWith: ".droppable,#draggables",
        revert: true,
       stop: function(event, ui) {
           $(ui.item).removeClass('dragging');
            $('.dragging').remove();
            if($(this).hasClass('new')) {
                var clone = $(this).clone();                
                clone.empty();
                $(this).after(clone);
                $(this).removeClass('new');
                initDroppableSort( clone );
            }            
            cleanUp();
        }
    });
    
}

function cleanUp() {
    
 ...