连接到 fancytree 的 sortable 在拖放时忘记了它的位置
sortable connected to fancytree is forgetting its position upon drag and drop
我正在尝试以特定方式连接 fancytree and a JQueryUI sortable,这样就可以实现:
- fancytree 节点可以在 fancytree 中重新排列
- 可排序项可以在可排序项中重新排列
- 可以将 fancytree 节点作为克隆拖放到 sortable 上,并且
- 可以将可排序的项目作为克隆放在 fancytree 上以创建新的 fancytree 节点
我现在拥有的代码可以完成所有这些工作,但有一个问题我正在解决;当我将一个可排序节点拖到 fancytree 时,它不会保留其在可排序节点中的位置;它移动到最后。
我正在寻找的是:正是这个示例代码中显示的行为,但是当从 sortable 拖动到 fancytree 时,sortable 项目保留其位置。
这是一个 fiddle 我的代码:
这是代码本身(与 fiddle 相同,也许可以节省一些点击...):
<html>
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script
src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/skin-win8/ui.fancytree.min.css" rel="stylesheet">
<!-- <script src="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/jquery.fancytree-all-deps.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/jquery.fancytree-all.min.js"></script>
</head>
<body>
<div id="tree"></div>
<ul id="mylist">
<li class="ui-state-default tonga">Item 1</li>
<li class="ui-state-default tonga">Item 2</li>
<li class="ui-state-default tonga">Item 3</li>
<li class="ui-state-default tonga">Item 4</li>
<li class="ui-state-default tonga">Item 5</li>
<li class="ui-state-default tonga">Item 6</li>
<li class="ui-state-default tonga">Item 7</li>
</ul>
<script type="text/javascript">
$(function(){ // on page load
$("#tree").fancytree({
debugLevel: 0,
selectMode: 1,
extensions: ["dnd"],
source: [
{title: "Node 1", key: "1", "baloney": 44},
{title: "Folder 2", key: "2", folder: true, children: [
{title: "Node 2.1", key: "3", myOwnAttr: "abc"},
{title: "Node 2.2", key: "4"}
]}
],
dnd: {
dragStart: function(node, data) {
return true;
},
dragEnter: function(node, data) {
return true;
},
dragDrop: function(node, data) {
if ( !data.otherNode ) {
// it's a draggable from outside the fancytree
node.addNode({title: "Hello butt"}, data.hitMode);
return;
} else {
// SOLUTION: this line enables reorder inside tree
data.otherNode.moveTo(node, data.hitMode);
}
},
initHelper: function(sourceNode, data) {
var helper = data.ui.helper;
var foo = $(helper).find(".fancytree-title")[0].innerHTML;
$(helper).find(".fancytree-drag-helper-img").remove();
$(helper).find(".fancytree-title").replaceWith('<li class="ui-state-default tonga">'+foo+"</li>");
},
updateHelper: function(sourceNode, data) {
},
draggable: {
appendTo: "body",
connectToSortable: "#mylist",
revert: "invalid",
containment: "document"
}
},
});
$("#mylist").sortable(
{
connectWith: "#mylist",
//containment: "parent"
}
).disableSelection();
$(".tonga").draggable({
revert: true,
helper: "clone",
connectToFancytree: true
});
$(".tonga").draggable({
revert: false,
helper: "original",
connectToSortable: "#mylist"
});
});
</script>
</body>
</html>
我想我已经明白了。一些事情需要返工。
首先需要处理sortable对象的out
事件,存储item是否已经超出sortable的范围,也就是因为某些原因重新排序列表:
$("#mylist").sortable({
connectWith: "#mylist",
out: function(event, ui) {
// store the original index of the sortable item only if we are moving the mouse (extra events fire which mess this up)
if (event.originalEvent.type === "mousemove") {
$(ui.item).data('drugout', true);
}
}
}).disableSelection();
然后需要将一些事件侦听器添加到可拖动对象中。 start
处理程序存储可拖动项的原始索引。 stop
处理程序确定该项目是否已超出可排序范围。如果该项目已超出可排序范围,则它会将该项目重新插入到其先前的索引处,从而有效地保留列表的顺序:
$(".tonga").draggable({
revert: true,
helper: "clone",
connectToFancytree: true,
start: function(event, ui) {
$(event.target).data('previndex', $(event.target).index());
},
stop: function(event, ui) {
if ($(event.target).data('drugout')) {
var originalIndex = $(event.target).data('previndex');
$("#mylist li:last").insertBefore($("#mylist li:eq(" + originalIndex + ")"));
}
}
});
这个 JSFiddle 有一个工作示例。
$(function() { // on page load
$("#tree").fancytree({
debugLevel: 0,
selectMode: 1,
extensions: ["dnd"],
source: [{
title: "Node 1",
key: "1",
"baloney": 44
},
{
title: "Folder 2",
key: "2",
folder: true,
children: [{
title: "Node 2.1",
key: "3",
myOwnAttr: "abc"
},
{
title: "Node 2.2",
key: "4"
}
]
}
],
dnd: {
dragStart: function(node, data) {
return true;
},
dragEnter: function(node, data) {
return true;
},
dragDrop: function(node, data) {
if (!data.otherNode) {
// it's a draggable from outside the fancytree
node.addNode({
title: "Hello butt"
}, data.hitMode);
return;
} else {
// SOLUTION: this line enables reorder inside tree
data.otherNode.moveTo(node, data.hitMode);
}
},
initHelper: function(sourceNode, data) {
var helper = data.ui.helper;
var foo = $(helper).find(".fancytree-title")[0].innerHTML;
$(helper).find(".fancytree-drag-helper-img").remove();
$(helper).find(".fancytree-title").replaceWith('<li class="ui-state-default tonga">' + foo + "</li>");
},
updateHelper: function(sourceNode, data) {},
draggable: {
appendTo: "body",
connectToSortable: "#mylist",
revert: "invalid",
containment: "document"
}
},
});
$("#mylist").sortable({
connectWith: "#mylist",
out: function(event, ui) {
if (event.originalEvent.type === "mousemove") {
$(ui.item).data('drugout', true);
}
}
}).disableSelection();
$(".tonga").draggable({
revert: true,
helper: "clone",
connectToFancytree: true,
start: function(event, ui) {
$(event.target).data('previndex', $(event.target).index());
},
stop: function(event, ui) {
if ($(event.target).data('drugout')) {
var originalIndex = $(event.target).data('previndex');
$("#mylist li:last").insertBefore($("#mylist li:eq(" + originalIndex + ")"));
}
}
});
$(".tonga").draggable({
revert: false,
helper: "original",
connectToSortable: "#mylist"
});
});
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/skin-win8/ui.fancytree.min.css" rel="stylesheet">
<!-- <script src="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/jquery.fancytree-all-deps.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/jquery.fancytree-all.min.js"></script>
</head>
<body>
<div id="tree"></div>
<ul id="mylist">
<li class="ui-state-default tonga">Item 1</li>
<li class="ui-state-default tonga">Item 2</li>
<li class="ui-state-default tonga">Item 3</li>
<li class="ui-state-default tonga">Item 4</li>
<li class="ui-state-default tonga">Item 5</li>
<li class="ui-state-default tonga">Item 6</li>
<li class="ui-state-default tonga">Item 7</li>
</ul>
</body>
我正在尝试以特定方式连接 fancytree and a JQueryUI sortable,这样就可以实现:
- fancytree 节点可以在 fancytree 中重新排列
- 可排序项可以在可排序项中重新排列
- 可以将 fancytree 节点作为克隆拖放到 sortable 上,并且
- 可以将可排序的项目作为克隆放在 fancytree 上以创建新的 fancytree 节点
我现在拥有的代码可以完成所有这些工作,但有一个问题我正在解决;当我将一个可排序节点拖到 fancytree 时,它不会保留其在可排序节点中的位置;它移动到最后。
我正在寻找的是:正是这个示例代码中显示的行为,但是当从 sortable 拖动到 fancytree 时,sortable 项目保留其位置。
这是一个 fiddle 我的代码:
这是代码本身(与 fiddle 相同,也许可以节省一些点击...):
<html>
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script
src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/skin-win8/ui.fancytree.min.css" rel="stylesheet">
<!-- <script src="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/jquery.fancytree-all-deps.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/jquery.fancytree-all.min.js"></script>
</head>
<body>
<div id="tree"></div>
<ul id="mylist">
<li class="ui-state-default tonga">Item 1</li>
<li class="ui-state-default tonga">Item 2</li>
<li class="ui-state-default tonga">Item 3</li>
<li class="ui-state-default tonga">Item 4</li>
<li class="ui-state-default tonga">Item 5</li>
<li class="ui-state-default tonga">Item 6</li>
<li class="ui-state-default tonga">Item 7</li>
</ul>
<script type="text/javascript">
$(function(){ // on page load
$("#tree").fancytree({
debugLevel: 0,
selectMode: 1,
extensions: ["dnd"],
source: [
{title: "Node 1", key: "1", "baloney": 44},
{title: "Folder 2", key: "2", folder: true, children: [
{title: "Node 2.1", key: "3", myOwnAttr: "abc"},
{title: "Node 2.2", key: "4"}
]}
],
dnd: {
dragStart: function(node, data) {
return true;
},
dragEnter: function(node, data) {
return true;
},
dragDrop: function(node, data) {
if ( !data.otherNode ) {
// it's a draggable from outside the fancytree
node.addNode({title: "Hello butt"}, data.hitMode);
return;
} else {
// SOLUTION: this line enables reorder inside tree
data.otherNode.moveTo(node, data.hitMode);
}
},
initHelper: function(sourceNode, data) {
var helper = data.ui.helper;
var foo = $(helper).find(".fancytree-title")[0].innerHTML;
$(helper).find(".fancytree-drag-helper-img").remove();
$(helper).find(".fancytree-title").replaceWith('<li class="ui-state-default tonga">'+foo+"</li>");
},
updateHelper: function(sourceNode, data) {
},
draggable: {
appendTo: "body",
connectToSortable: "#mylist",
revert: "invalid",
containment: "document"
}
},
});
$("#mylist").sortable(
{
connectWith: "#mylist",
//containment: "parent"
}
).disableSelection();
$(".tonga").draggable({
revert: true,
helper: "clone",
connectToFancytree: true
});
$(".tonga").draggable({
revert: false,
helper: "original",
connectToSortable: "#mylist"
});
});
</script>
</body>
</html>
我想我已经明白了。一些事情需要返工。
首先需要处理sortable对象的out
事件,存储item是否已经超出sortable的范围,也就是因为某些原因重新排序列表:
$("#mylist").sortable({
connectWith: "#mylist",
out: function(event, ui) {
// store the original index of the sortable item only if we are moving the mouse (extra events fire which mess this up)
if (event.originalEvent.type === "mousemove") {
$(ui.item).data('drugout', true);
}
}
}).disableSelection();
然后需要将一些事件侦听器添加到可拖动对象中。 start
处理程序存储可拖动项的原始索引。 stop
处理程序确定该项目是否已超出可排序范围。如果该项目已超出可排序范围,则它会将该项目重新插入到其先前的索引处,从而有效地保留列表的顺序:
$(".tonga").draggable({
revert: true,
helper: "clone",
connectToFancytree: true,
start: function(event, ui) {
$(event.target).data('previndex', $(event.target).index());
},
stop: function(event, ui) {
if ($(event.target).data('drugout')) {
var originalIndex = $(event.target).data('previndex');
$("#mylist li:last").insertBefore($("#mylist li:eq(" + originalIndex + ")"));
}
}
});
这个 JSFiddle 有一个工作示例。
$(function() { // on page load
$("#tree").fancytree({
debugLevel: 0,
selectMode: 1,
extensions: ["dnd"],
source: [{
title: "Node 1",
key: "1",
"baloney": 44
},
{
title: "Folder 2",
key: "2",
folder: true,
children: [{
title: "Node 2.1",
key: "3",
myOwnAttr: "abc"
},
{
title: "Node 2.2",
key: "4"
}
]
}
],
dnd: {
dragStart: function(node, data) {
return true;
},
dragEnter: function(node, data) {
return true;
},
dragDrop: function(node, data) {
if (!data.otherNode) {
// it's a draggable from outside the fancytree
node.addNode({
title: "Hello butt"
}, data.hitMode);
return;
} else {
// SOLUTION: this line enables reorder inside tree
data.otherNode.moveTo(node, data.hitMode);
}
},
initHelper: function(sourceNode, data) {
var helper = data.ui.helper;
var foo = $(helper).find(".fancytree-title")[0].innerHTML;
$(helper).find(".fancytree-drag-helper-img").remove();
$(helper).find(".fancytree-title").replaceWith('<li class="ui-state-default tonga">' + foo + "</li>");
},
updateHelper: function(sourceNode, data) {},
draggable: {
appendTo: "body",
connectToSortable: "#mylist",
revert: "invalid",
containment: "document"
}
},
});
$("#mylist").sortable({
connectWith: "#mylist",
out: function(event, ui) {
if (event.originalEvent.type === "mousemove") {
$(ui.item).data('drugout', true);
}
}
}).disableSelection();
$(".tonga").draggable({
revert: true,
helper: "clone",
connectToFancytree: true,
start: function(event, ui) {
$(event.target).data('previndex', $(event.target).index());
},
stop: function(event, ui) {
if ($(event.target).data('drugout')) {
var originalIndex = $(event.target).data('previndex');
$("#mylist li:last").insertBefore($("#mylist li:eq(" + originalIndex + ")"));
}
}
});
$(".tonga").draggable({
revert: false,
helper: "original",
connectToSortable: "#mylist"
});
});
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/skin-win8/ui.fancytree.min.css" rel="stylesheet">
<!-- <script src="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/jquery.fancytree-all-deps.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/jquery.fancytree@2.27/dist/jquery.fancytree-all.min.js"></script>
</head>
<body>
<div id="tree"></div>
<ul id="mylist">
<li class="ui-state-default tonga">Item 1</li>
<li class="ui-state-default tonga">Item 2</li>
<li class="ui-state-default tonga">Item 3</li>
<li class="ui-state-default tonga">Item 4</li>
<li class="ui-state-default tonga">Item 5</li>
<li class="ui-state-default tonga">Item 6</li>
<li class="ui-state-default tonga">Item 7</li>
</ul>
</body>