我正在尝试弄清楚如何仅回滚未成功移动的文件夹节点。下面的代码是我正在尝试做的一个例子。当您选择了几个文件夹并将它们移动到另一个文件夹时,就会出现问题。如果其中一个目录无法移动,我希望能够将其回滚到原始父目录。
不幸的是,$.jstree.rollback(data.rlbk);
会将所有选中的文件夹回滚到之前的位置。
$("#tree").jstree({...}).bind("move_node.jstree", function (e, data) {
// process all selected nodes directory
data.rslt.o.each(function (i) {
// Send request.
var move = $.parseJSON($.ajax({
url: "./jstree.php",
type: 'post',
async: false,
data: {
operation: "move_dir",
....
}
}).responseText);
// When everything's ok, the reponseText will be {success: true}
// In all other cases it won't exist at all.
if(move.success == undefined){
// Here I want to rollback the CURRENT failed node.
// $.jstree.rollback(data.rlbk); will rollback all
// of the directories that have been moved.
}
}
});
有没有办法做到这一点?
答案 0 :(得分:2)
我之前看过使用过jstree,但是在我的代码中没有使用它。因此,代码可能不正确,但概念应该是。
根据您的代码,您似乎正在服务器端执行移动操作,并且您希望更新树以反映结果。
基于jsTree文档,看起来好像你无法提交节点更新并回滚到最后一次提交。
您可以回滚树(所有更改)并在之后执行移动,而不是仅回滚您不想要的更改。
为了更好地理解下面的代码,您可能希望阅读它(或创建一个副本),而不需要在“if”语句的条件中设置或引用“wasTriggeredByCode”的行。
$("#tree").jstree({...}).bind("move_node.jstree", function (e, data) {
var jsTree = $(this);
var successes = [];
// Becomes true when function was triggered by code that updates jsTree to
// reflect nodes that were successfully moved on the server
var wasTriggeredByCode = false;
// process all selected nodes directory
data.rslt.o.each(function (i) {
// I'm not certain that this is how the node is referenced
var node = $(this);
wasTriggeredByCode = (wasTriggeredByCode || node.data('redoing'));
// Don't perform server changes when event was triggered from code
if (wasTriggeredByCode) {
return;
}
// Send request.
var move = $.parseJSON($.ajax({
url: "./jstree.php",
type: 'post',
async: false,
data: {
operation: "move_dir",
....
}
}).responseText);
if(move.success){
successes.push(node);
}
});
// Don't continue when event was triggered from code
if (wasTriggeredByCode) {
return;
}
// Roll back the tree here
jsTree.rollback(data.rlbk);
// Move the nodes
for (var i=0; i < successes.length; i++) {
var node = successes[i];
// According to the documentation this will trigger the move event,
// which will result in infinite recursion. To avoid this you'll need
// to set a flag or indicate that you're redoing the move.
node.data('redoing', true);
jsTree.move_node(node, ...);
// Remove the flag so that additional moves aren't ignored
node.removeData('redoing');
}
});
答案 1 :(得分:1)
我考虑过在jstree中发生类似“ onbeforenodemove”事件的事情,
$("#tree").jstree({...}).bind("before_move_node.jstree", function (e, data) {...}
因此,我查看了jstree.js文件(版本jsTree 3.1.1),并搜索了原始“ move_node.jstree”处理程序的声明。发现它声明了起始行3689:
move_node: function (obj, par, pos, callback, is_loaded, skip_redraw, origin) {...}
此函数的主体末尾包含以下行:
this.trigger('move_node', { "node" : obj, "parent" : new_par.id, "position" : pos, "old_parent" : old_par, "old_position" : old_pos, 'is_multi' : (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign' : (!old_ins || !old_ins._id), 'old_instance' : old_ins, 'new_instance' : this });
上面的行实际上调用了使用.bind(“ move_node.jstree”)声明的回调。 因此,在此函数主体的开头,我添加了以下内容:
var before_data = { "node": obj, "parent": new_par.id, "position": pos, "old_parent": old_par, "old_position": old_pos, 'is_multi': (old_ins && old_ins._id && old_ins._id !== this._id), 'is_foreign': (!old_ins || !old_ins._id), 'old_instance': old_ins, 'new_instance': this, cancelled: false };
this.trigger('before_move_node', before_data);
if (before_data.cancelled) {
return false;
}
注意“已取消”:在before_data分配值的末尾为false。
还请注意在分配new_par等值之后插入以上内容。
我页面上的代码(jsTree实例化)现在看起来像这样:
$('#tree')
.jstree({
core: {...},
plugins: [...]
})
.bind('before_move_node.jstree', function (e, data) {
if (...) {
data.cancelled = true;
}
})
传递给'before_move_node.jstree'的数据对象包含与在标准'move_node.jstree'数据参数中接收到的值相同的值,因此您可以决定要取消还是放弃移动。如果您决定取消,只需将其他“取消”属性设置为true。这样,整个动作就不会发生。