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 );
...