Reputation: 380
I need to do something like this example in SortableJs doc but in addition I also need Nested Sortables lists. This is not a problem, I've achived.
The wrong part is that I must implement a costraint in nested groups, because I need to avoid neasted groups. A group cannot be neasted inside another group. A single element can be neasted inside a group.
Let see an image, this is ok, we have two groups (item2 and item5) with some single elements inside
But, this is forbidden for my project, a group inside a grop (item5 in item2)
I'd try to control things by the events: 'onChoose', 'onStart', 'onEnd', 'onAdd', 'onUpdate', 'onSort', 'onRemove', 'onChange', 'onUnchoose'. But without results.
Here is my code:
<div id="nested" class="row">
<div id="example2-left" class="list-group nested-sortable col-sm-5">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2
<div class="list-group nested-sortable"></div>
</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 4</div>
<div class="list-group-item">Item 5
<div class="list-group nested-sortable"></div>
</div>
<div class="list-group-item">Item 6</div>
</div>
<div id="example2-right" class="list-group col-sm-5">
<div class="list-group-item">Item 1</div>
<div class="list-group-item">Item 2</div>
<div class="list-group-item">Item 5</div>
<div class="list-group-item">Item 3</div>
<div class="list-group-item">Item 6</div>
</div>
</div>
and the js
$(document).ready(function() {
var nestedSortables = [].slice.call(document.querySelectorAll('.nested-sortable'));
for (var i = 0; i < nestedSortables.length; i++) {
new Sortable(nestedSortables[i], {
group: 'shared',
animation: 150,
fallbackOnBody: true,
swapThreshold: 0.65,
// trying to control elements
onChange: function(e) {
console.log('Left: onChange');
console.log(e);
e.preventDefault();
return false;
},
onUnchoose: function(e) {
console.log('Left: onUnchoose');
console.log(e);
e.preventDefault();
return false;
},
});
}
new Sortable($('#example2-right')[0], {
group: 'shared',
animation: 150,
onUnchoose: function(e) {
console.log('Right: onUnchoose');
console.log(e);
e.preventDefault();
return false;
},
onAdd: function(e) {
console.log('Right: onAdd');
console.log(e);
e.preventDefault();
return false;
},
onChange: function(e) {
console.log('Right: onChange');
console.log(e);
e.preventDefault();
return false;
},
});
});
Upvotes: 3
Views: 1802
Reputation: 83
Sorry I'm late to the party. This might help.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sortable demo</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
</head>
<body>
<div id="nested1" class="container">
<div id="nestedDemo" class="list-group col nested-sortable">
<div data-sortable-id="list_group_1" class="mb-1 list-group-item nested-1 list_group" style="background-color:rgba(0,130,200,0.2);"><span id="list_group_1" style="font-size:130%;">Group 1</span>
<div class="list-group nested-sortable">
<div data-sortable-id="grp_1_list_1" class="mb-1 list-group-item nested-2 list">Group 1 list 1</div>
<div data-sortable-id="grp_1_list_2" class="mb-1 list-group-item nested-2 list">Group 1 list 2</div>
<div data-sortable-id="grp_1_list_3" class="mb-1 list-group-item nested-2 list">Group 1 list 3</div>
<div data-sortable-id="grp_1_list_4" class="mb-1 list-group-item nested-2 list">Group 1 list 4</div>
</div>
</div>
<div></div>
<div data-sortable-id="list_group_2" class="mb-1 list-group-item nested-1 list_group" style="background-color:rgba(60,180,75,0.2)"><span id="list_group_2" style="font-size:130%;">Group 2</span>
<div class="list-group nested-sortable">
<div data-sortable-id="grp_2_list_5" class="mb-1 list-group-item nested-2 list">Group 2 list 5</div>
<div data-sortable-id="grp_2_list_6" class="mb-1 list-group-item nested-2 list">Group 2 list 6</div>
<div data-sortable-id="grp_2_list_7" class="mb-1 list-group-item nested-2 list">Group 2 list 7</div>
<div data-sortable-id="grp_2_list_8" class="mb-1 list-group-item nested-2 list">Group 2 list 8</div>
</div>
</div>
<div></div>
<div data-sortable-id="list_9" class="mb-1 list-group-item nested-1 list">list 9</div>
<div data-sortable-id="list_10" class="mb-1 list-group-item nested-1 list">list 10</div>
</div>
<div style="padding: 0" class="col-12">
</div>
</div>
<script src="https://raw.githack.com/SortableJS/Sortable/master/Sortable.js"></script>
<script>
// Nested demo
let nestedSortables = [].slice.call(document.querySelectorAll('.nested-sortable'));
var draggedDepth = 0;
// Loop through each nested sortable element
for (let i = 0; i < nestedSortables.length; i++) {
new Sortable(nestedSortables[i], {
group: 'nested',
pull: function (to, from) {
console(from.el.children.length);
},
animation: 300,
fallbackOnBody: true,
swapThreshold: 0.65,
// Event when you move an item in the list or between lists
onMove: function (/**Event*/evt, /**Event*/originalEvent) {
/////Explore evt object
console.dir(evt.related);
///// some useful stuff
console.dir(evt.related.offsetParent.classList.value);
console.dir(evt.dragged.dataset.sortableId);
///// check if target parent class has list_group
const sentence = evt.related.offsetParent.classList.value;
const word = 'list_group';
result = sentence.includes(word);
///// check if dragged parent class target has list_group
const sentence1 = evt.dragged.dataset.sortableId;
result1 = sentence1.includes(word);
//Refuse if criteria is wrong (eg. group cannot nest inside another group)
if(result == true){
if(result1 == true ){
return false;
}
}else{
}
},
///// (php) Send new order to DB
onUpdate:function(evt){
var xhr = false;
xhr = new XMLHttpRequest();
if (xhr) {
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
// some stuff here
}
}
xhr.open("POST", "post.php", true);
xhr.send(JSON.stringify(serialize(root)));
}
},
});
}
const nestedQuery = '.nested-sortable';
const identifier = 'sortableId';
const root = document.getElementById('nestedDemo');
function serialize(sortable) {
let serialized = [];
let children = [].slice.call(sortable.children);
for (let i in children) {
let nested = children[i].querySelector(nestedQuery);
serialized.push({
id: children[i].dataset[identifier],
children: nested ? serialize(nested) : []
});
}
return serialized
}
///// Save original list if needed
let reset_list = JSON.stringify(serialize(root));
console.log(reset_list);
</script>
</body>
</html>
Upvotes: 0