这可能是一种复杂的答案,并不完全是您想要的,或者更多。
最初的部分问题是很难访问嵌套列表。因为它们里面没有项目并且基本上呈现给ul,而height 则为0。我建议你让block 他们至少有一些高度。
我还删除了填充并将其手动添加回li 以提供任务和子任务之间的空间关系。我开始将列表与更多类分开,parent 和 child,这样我就可以知道我在设计和使用哪个。
parent 和 child 关系本质上适用于 2 个可排序列表,它们恰好是嵌套的。因此,我为$(".parent").sortable() 和$(".child").sortable() 创建了选项,以帮助组织它们。这也可以让我们根据任务类型或来源地接受或拒绝(取消)可分类项目。
这绝不是完美的,我在这里和那里发现了很多奇怪的小错误,但核心元素是能够对任务和子任务进行排序以及将子任务拖到另一个任务。
到目前为止的工作示例:https://jsfiddle.net/Twisty/sv9qdpLb/
HTML
<div id="container">
<h2>Tasks</h2>
<ul id="list" class="parent sortable">
<li id="t1" class="task" data-id="l1">
Task 1 <span class="add-subTask-button ui-icon ui-icon-plus"></span>
<ul class="child sortable"></ul>
</li>
<li id="t2" class="task" data-id="l2">
Task 2 <span class="add-subTask-button ui-icon ui-icon-plus"></span>
<ul class="child sortable">
<li id="t2_1" class="subTask" data-id="l2-1">
Sub Task 1 <span class="remove-subTask-button ui-icon ui-icon-minus"></span>
</li>
<li id="t2_2" class="subTask" data-id="l2-2">
Sub Task 2 <span class="remove-subTask-button ui-icon ui-icon-minus"></span>
</li>
</ul>
</li>
<li id="t3" class="task" data-id="l3">
Task 3 <span class="add-subTask-button ui-icon ui-icon-plus"></span>
<ul class="child sortable"></ul>
</li>
</ul>
</div>
如果您查看演示,您会发现它们大部分都是ul 和li 样式列表。是的,您可以使用其他东西,但是将每个列表项视为其本身、列表中的对象项并调整其数据和 ID 等属性会更容易。
CSS
#container {
width: 600px;
margin: 30px auto;
}
ul.parent {
font-size: 18px;
width: 200px;
margin: 0;
padding: 0;
}
ul.parent li {
list-style: none;
margin-bottom: 2px;
padding-left: 3px;
border: 1px solid #999;
border-radius: 6px;
position: relative;
}
ul.parent li span.ui-icon {
position: absolute;
top: .25em;
right: 2px;
left: auto;
cursor: pointer;
}
ul.child {
display: block;
font-size: 14px;
padding-left: 30px;
min-height: 1em;
}
ul.child li {
list-style: none;
border: 1px solid #bbb;
margin-bottom: 1px;
}
.placeholder {
background: yellow;
height: 1em;
}
.handle {
background: orange;
width: 20px;
height: 20px;
float: left;
margin: 0 5px 10px 5px;
}
.container {
overflow: hidden
}
我在这里没有做太多改动,只是做了一些更具体的事情。我还添加了边框,为用户提供视觉队列或了解分组及其关系。
jQuery
$(document).ready(function() {
// Make tasks sortable
function fullSerial() {
var par = {};
$.each($("#list").sortable("toArray"), function(key, val) {
par[val] = $("#" + val + " .child").sortable("toArray");
});
return par;
}
$(".parent").sortable({
placeholder: 'placeholder',
connectWith: ".sortable",
over: function(e, ui) {
if (ui.item.hasClass("subTask")) {
$(".parent").sortable("cancel");
}
}
});
$(".child").sortable({
placeholder: 'placeholder',
accept: ".child",
connectWith: ".sortable",
}).disableSelection();
$(".sortable").on("sortupdate", function() {
//console.log($(".sortable").sortable("serialize"));
console.log(fullSerial());
});
$(".add-subTask-button").click(function() {
var task = $(this).parent();
var taskName = prompt("Enter Sub Task Name.");
var newId = task.attr("id") + "_" + (task.find("ul.child li").length + 1);
var subTask = $("<li>", {
id: newId,
class: "subTask",
"data-id": newId
}).html(taskName + "<span class='remove-subTask-button ui-icon ui-icon-minus'></span>");
task.find(".child").append(subTask).sortable("refresh");
});
$(".remove-subTask-button").click(function() {
var subTask = $(this).parent();
var ulElem = subTask.parent();
subTask.remove();
ulElem.sortable("refresh");
});
});
通过测试,我发现serialize 方法不适用于嵌套的可排序列表。所以我做了一个函数来构建一个任务对象,其中包含一组子任务作为每个任务的元素。我怀疑使用JSON.serialize() 可能会为您提供可以传递的东西,但您始终可以操纵fullSerial 从对象而不是对象本身返回序列化字符串。
您可以看到两个可排序的。由于您的 OP 并不清楚您是否希望将子任务变成任务,因此试图阻止此类活动。我在receive 中尝试了相同的代码,它应该恢复排序......但两者都没有。此外,如果你足够狡猾,你可以将整个任务和它的子任务拖到一个子任务位置。
为了能够进行更深入的测试,我添加了一种动态添加项目并动态生成/删除子任务的方法。
我希望这会有所帮助。正如我前面所说,它可能超出您的需要,但您的问题会导致复杂的答案。即使没有添加元素。
更新
防止Task被拖入Sub Task的例子:https://jsfiddle.net/Twisty/sv9qdpLb/4/
$(".child").sortable({
placeholder: 'placeholder',
connectWith: ".sortable",
receive: function(e, ui) {
if (ui.item.hasClass("task")) {
ui.sender.sortable("cancel");
}
}
});