jQuery nested sortable list
jQuery Sortable for nested lists, where the connected list as source has no nested features.
by Rolf Friedrich
HTML
<label>Cursor At:</label>
<label id="cursor"></label>
<h3>
Targetlist
</h3>
<ul class="items">
<li class="item unsortable">Unsortable Item </li>
<li class="item">Item 1</li>
<li class="item nested">Item 2</li>
<li class="item nested">Item 3</li>
<li class="item">Item 4</li>
<li class="item">Item 5</li>
</ul>
<h3>
Sourcelist
</h3>
<ul class="items secondlist">
<li class="item">Source item</li>
<li class="item">Source item</li>
<li class="item">Source item</li>
<li class="item">Source item</li>
</ul>
CSS
ul,
.items,
.secondlist {
list-style: none outside none;
margin-bottom: 20px;
padding: 0;
width: 100%;
position: relative;
}
.item {
background: #fff;
border: 1px solid #ddd;
cursor: move;
/* height: 50px; */
line-height: 50px;
padding: 0 10px;
width: 50%;
}
.item.unsortable {
cursor: default;
background: #fff;
}
.item:hover{
background: #d8ffdf;
}
.item:has(ol):hover{
background: #fff;
}
.item.unsortable:hover{
cursor: disabled;
background: #ffb7b7;
}
.nested {
margin-left: 20px;
width: 50%;
}
.dragHover {
border-color: blue;
color: blue;
}
.placeholder {
background: #fff;
border: 1px dashed #ccc;
height: 50px;
width: 50%;
}
.placeholder-nested {
background: #fff;
border: 1px dashed #ccc;
height: 50px;
width: 480px;
margin-left: 20px;
}
.secondlist{
min-height: 4rem;
}
JavaScript
$(".items").sortable({
items :".item:not(.unsortable)",
connectWith: ".items",
placeholder: "placeholder",
targetList : null,
update: function(event, ui) {
// update
},
start: function(event, ui) {
if(ui.helper.hasClass('nested')){
ui.placeholder.removeClass('placeholder');
ui.placeholder.addClass('placeholder-nested');
}
else{
ui.placeholder.removeClass('placeholder-nested');
ui.placeholder.addClass('placeholder');
}
},
sort: function(event, ui) {
var pos;
if(ui.helper.hasClass('nested') ){
pos = ui.position.left+20;
$('#cursor').text(ui.position.left+20);
}
else{
pos = ui.position.left;
$('#cursor').text(ui.position.left);
}
if( ( pos >= 32 && !ui.helper.hasClass('nested') ) ){
ui.placeholder.removeClass('placeholder');
ui.placeholder.addClass('placeholder-nested');
ui.helper.addClass('nested');
}
else if( (pos < 25 && ui.helper.hasClass('nested')) ){
ui.placeholder.removeClass('placeholder-nested');
ui.placeholder.addClass('placeholder');
ui.helper.removeClass('nested');
}
},
stop: function(event, ui ){
if( ui.helper == null && ui.item[0].closest('ul').classList.contains('secondlist') ){
ui.item.removeClass('nested');
}
},
remove: function(event, ui) {
var secondList = ui.item[0].closest('ul').classList.contains('secondlist');
if( secondList ) {
ui.item[0].classList.remove('nested');
}
}
});