Kendo TreeView 移动 Parent 节点以更改排序顺序但不允许将 Parent 拖到 Child 节点下
Kendo TreeView Move Parent nodes to change the Sort Order but not allow a Parent to be dragged under a Child node
我有 Kendo 个 TreeView,其中 parent 个节点有 child 个节点。
我想要的规则是用户可以
- 将parent节点拖到当前位置的上方或下方,从而改变排序顺序
- 不允许将 parent 拖到另一个 parent 节点上
- 不允许将 parent 拖到任何 child 节点上
- DO 允许将 child 节点项拖到另一个 parent 节点下
我当然更喜欢javascript或jquery
此代码只是防止所有 parent 节点被拖动,因此这不是我想要的。有人有这方面的样品吗?
$(".k-treeview").data("kendoTreeView").bind("dragstart", function (e) {
if ($(e.sourceNode).parentsUntil(".k-treeview", ".k-item").length == 0) {
e.preventDefault();
}
});
根据答案更新
如果我将它放在我的 $(document).ready(function() { ...
中,似乎几乎所有代码都可以根据答案进行更正
但是如果我将该代码放在 onDrop 下,则不会被调用。
例如
var treeview = $("#treeview").kendoTreeView({
expanded: true,
dragAndDrop: true,
select: onSelect,
loadOnDemand: false,
dataSource: homogeneous,
dataTextField: "ReportGroupName",
template: kendo.template($("#treeview-template").html()) //,
,
onDrop: function(e) {
kendoTreeView = $(".k-treeview").data("kendoTreeView");
kendoTreeView.bind("drag", function (e) {
//Check if we're trying to add the node as a child
var dropAsChild = $(e.dropTarget).hasClass("k-in k-state-hover");
var sourceDataItem = kendoTreeView.dataItem(e.sourceNode);
var destinationDataItem = kendoTreeView.dataItem(e.dropTarget);
if ($(e.sourceNode).is(e.dropTarget)) {
//Dropping on itself
e.setStatusClass("k-denied");
} else if (destinationDataItem && !dropAsChild) {
//Dropping as a sibling... that's ok if it's the same parent
if (sourceDataItem.parent().uid != destinationDataItem.parent().uid) {
//Not the same parent
e.setStatusClass("k-denied");
}
} else {
e.setStatusClass("k-denied");
}
});
}
}).data("kendoTreeView");
图像
这是一张红色箭头指向 child 的图像,我要移动到另一个 parent(成为带有蓝色箭头的 parent 的 child)
dragstart
事件的问题是它不会为您提供放置目标,因为它在事件序列的早期。
实现此目的的最佳方法是根据源节点和目标节点拒绝删除操作。您可以通过在传递给 drag
事件的事件对象上调用 setStatusClass
(带有 k-denied
)来完成此操作。
var treeview = $("#treeview").kendoTreeView({
expanded: true,
dragAndDrop: true,
select: onSelect,
loadOnDemand: false,
dataSource: homogeneous,
dataTextField: "ReportGroupName",
template: kendo.template($("#treeview-template").html()),
drag: function (e) {
//Check if we're trying to add the node as a child
var kendoTreeView = $("#treeview").data("kendoTreeView");
var dropAsChild = $(e.dropTarget).hasClass("k-in k-state-hover");
var sourceDataItem = kendoTreeView.dataItem(e.sourceNode);
var destinationDataItem = kendoTreeView.dataItem(e.dropTarget);
if ($(e.sourceNode).is(e.dropTarget)) {
//Dropping on itself
e.setStatusClass("k-denied");
} else if (destinationDataItem && !dropAsChild) {
//Dropping as a sibling... that's ok if it's the same parent
if (sourceDataItem.parent().uid != destinationDataItem.parent().uid) {
//Not the same parent
e.setStatusClass("k-denied");
}
} else {
e.setStatusClass("k-denied");
}
}
}).data("kendoTreeView");
我现在无法测试上面的代码,所以它们可能存在一些错误......我相信你仍然会理解它背后的逻辑。
我们可以在拖动事件中检查e.statusClass。因此,如果元素作为子元素添加,请取消拖动。对 The_Black_Smurf 代码进行了一些更改。下面的代码对我有用
drag: function (e) {
//Check if are we adding node as a child
if(e.statusClass == "i-plus") {
e.setStatusClass("k-i-cancel"); //Cancel drop
return;
}
var kendoTreeView = $("#treeViewAttr").data("kendoTreeView");
var sourceDataItem = kendoTreeView.dataItem(e.sourceNode);
var destinationDataItem = kendoTreeView.dataItem(e.dropTarget);
if (destinationDataItem) {
if (sourceDataItem.parent()[0].uid != destinationDataItem.parent()[0].uid) {
e.setStatusClass("k-i-cancel");
}
}
}
在我的 kendo 树视图版本中 classes 命名不同,请阅读下面的 class 名称并根据您的 kendo 版本定义 class 名称.
根据 API 参考 kendoTreeView 拖动事件
预定义状态class是:
k-插入顶部
- 表示该项目将被插入到顶部。
k-插入中间
- 表示该项目将被插入
中间.
k-插入底部
- 表示项目将被插入
底部。
k-加法
- 表示该项目将是added/appended。
k-拒绝
- 表示无效操作。使用此 class 将
自动使drop操作无效,所以不会有
需要在drop事件中调用setValid(false)
这个最重要:-
请注意,从版本 2016.3.914 开始,预定义状态 classes 的命名约定为 k-i-className。自版本 2017.1.118 起,使用以下状态 classes:k-i-insert-up, k-i-insert-down, k-i-insert-middle, k-i-plus, k-i-cancel
.
请注意,e.statusClass
返回的状态 classes 没有 k-
前缀,但是通过 [=14] 设置预定义状态 class 时需要此前缀=].如果设置自定义状态 CSS class.
,则不需要前缀
我有 Kendo 个 TreeView,其中 parent 个节点有 child 个节点。
我想要的规则是用户可以
- 将parent节点拖到当前位置的上方或下方,从而改变排序顺序
- 不允许将 parent 拖到另一个 parent 节点上
- 不允许将 parent 拖到任何 child 节点上
- DO 允许将 child 节点项拖到另一个 parent 节点下
我当然更喜欢javascript或jquery
此代码只是防止所有 parent 节点被拖动,因此这不是我想要的。有人有这方面的样品吗?
$(".k-treeview").data("kendoTreeView").bind("dragstart", function (e) {
if ($(e.sourceNode).parentsUntil(".k-treeview", ".k-item").length == 0) {
e.preventDefault();
}
});
根据答案更新
如果我将它放在我的 $(document).ready(function() { ...
但是如果我将该代码放在 onDrop 下,则不会被调用。
例如
var treeview = $("#treeview").kendoTreeView({
expanded: true,
dragAndDrop: true,
select: onSelect,
loadOnDemand: false,
dataSource: homogeneous,
dataTextField: "ReportGroupName",
template: kendo.template($("#treeview-template").html()) //,
,
onDrop: function(e) {
kendoTreeView = $(".k-treeview").data("kendoTreeView");
kendoTreeView.bind("drag", function (e) {
//Check if we're trying to add the node as a child
var dropAsChild = $(e.dropTarget).hasClass("k-in k-state-hover");
var sourceDataItem = kendoTreeView.dataItem(e.sourceNode);
var destinationDataItem = kendoTreeView.dataItem(e.dropTarget);
if ($(e.sourceNode).is(e.dropTarget)) {
//Dropping on itself
e.setStatusClass("k-denied");
} else if (destinationDataItem && !dropAsChild) {
//Dropping as a sibling... that's ok if it's the same parent
if (sourceDataItem.parent().uid != destinationDataItem.parent().uid) {
//Not the same parent
e.setStatusClass("k-denied");
}
} else {
e.setStatusClass("k-denied");
}
});
}
}).data("kendoTreeView");
图像 这是一张红色箭头指向 child 的图像,我要移动到另一个 parent(成为带有蓝色箭头的 parent 的 child)
dragstart
事件的问题是它不会为您提供放置目标,因为它在事件序列的早期。
实现此目的的最佳方法是根据源节点和目标节点拒绝删除操作。您可以通过在传递给 drag
事件的事件对象上调用 setStatusClass
(带有 k-denied
)来完成此操作。
var treeview = $("#treeview").kendoTreeView({
expanded: true,
dragAndDrop: true,
select: onSelect,
loadOnDemand: false,
dataSource: homogeneous,
dataTextField: "ReportGroupName",
template: kendo.template($("#treeview-template").html()),
drag: function (e) {
//Check if we're trying to add the node as a child
var kendoTreeView = $("#treeview").data("kendoTreeView");
var dropAsChild = $(e.dropTarget).hasClass("k-in k-state-hover");
var sourceDataItem = kendoTreeView.dataItem(e.sourceNode);
var destinationDataItem = kendoTreeView.dataItem(e.dropTarget);
if ($(e.sourceNode).is(e.dropTarget)) {
//Dropping on itself
e.setStatusClass("k-denied");
} else if (destinationDataItem && !dropAsChild) {
//Dropping as a sibling... that's ok if it's the same parent
if (sourceDataItem.parent().uid != destinationDataItem.parent().uid) {
//Not the same parent
e.setStatusClass("k-denied");
}
} else {
e.setStatusClass("k-denied");
}
}
}).data("kendoTreeView");
我现在无法测试上面的代码,所以它们可能存在一些错误......我相信你仍然会理解它背后的逻辑。
我们可以在拖动事件中检查e.statusClass。因此,如果元素作为子元素添加,请取消拖动。对 The_Black_Smurf 代码进行了一些更改。下面的代码对我有用
drag: function (e) {
//Check if are we adding node as a child
if(e.statusClass == "i-plus") {
e.setStatusClass("k-i-cancel"); //Cancel drop
return;
}
var kendoTreeView = $("#treeViewAttr").data("kendoTreeView");
var sourceDataItem = kendoTreeView.dataItem(e.sourceNode);
var destinationDataItem = kendoTreeView.dataItem(e.dropTarget);
if (destinationDataItem) {
if (sourceDataItem.parent()[0].uid != destinationDataItem.parent()[0].uid) {
e.setStatusClass("k-i-cancel");
}
}
}
在我的 kendo 树视图版本中 classes 命名不同,请阅读下面的 class 名称并根据您的 kendo 版本定义 class 名称.
根据 API 参考 kendoTreeView 拖动事件
预定义状态class是:
k-插入顶部
- 表示该项目将被插入到顶部。
k-插入中间
- 表示该项目将被插入 中间.
k-插入底部
- 表示项目将被插入 底部。
k-加法
- 表示该项目将是added/appended。
k-拒绝
- 表示无效操作。使用此 class 将 自动使drop操作无效,所以不会有 需要在drop事件中调用setValid(false)
这个最重要:-
请注意,从版本 2016.3.914 开始,预定义状态 classes 的命名约定为 k-i-className。自版本 2017.1.118 起,使用以下状态 classes:k-i-insert-up, k-i-insert-down, k-i-insert-middle, k-i-plus, k-i-cancel
.
请注意,e.statusClass
返回的状态 classes 没有 k-
前缀,但是通过 [=14] 设置预定义状态 class 时需要此前缀=].如果设置自定义状态 CSS class.