SORTABLE + DRAGGABLE - CLONE Intelligent

by bizamajig

HTML

<script src="//code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<div class="draggables">
    <div>foo1</div>
    <div>foo2</div>
    <div>foo3</div>
    <div>foo4</div>
    <div>foo5</div>
</div>
<div class="draggables">
    <div>bar1</div>
    <div>bar2</div>
    <div>bar3</div>
    <div>bar4</div>
    <div>bar5</div>
</div>

<hr>

<div class="droppable new">

</div>

CSS

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

.draggables, .droppable {
    margin: 0 0 10px 0;
    padding: 10px;
    border: 1px solid;
}
.dragging {
    visibility:hidden;
}
.droppable.new { border: 1px dashed; }

JavaScript

var $draggingParent = null;

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: ' > div',
        connectWith: '.draggables, .droppable',
        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() {
    $( '.droppable' ).not( '.new' ).each( function() {
        if ( $(this).find( ' > div' ).length === 0) {
            $(this).remove();
        }
    });
}
$( function() {

  	initDraggable( $( '.draggables > div' ) );

  	$( '.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 );
		           ...