题
我想知道是否有办法在 dojo Dnd 中以编程方式移动节点?原因是当 Web 服务调用触发数据库保存失败时,我想恢复对拖放的更改。这是我到目前为止所拥有的。
在我的代码中,节点 ID 似乎无法被 dojo.dnd.Container.DelItem 识别。我不能只使用目标上的所选项目,因为这是一个异步 Web 服务函数回调。因此,当调用此方法时,用户可能会选择容器上的另一个节点。
function OnMoveWSComplete(strResult) {
var resultObj = eval('(' + strResult + ')');
var sourceContainer = eval('(' + objResult.sourceContainerId + ')');
var targetContainer = eval('(' + objResult.targetContainerId + ')');
var targetNodes = targetContainer.getAllNodes();
for (var iNode = 0; iNode < targetNodes.length; iNode++) {
var currId = getLastIdFromStr(targetNodes[iNode].id);
if (currId == resultObj.Id) {
var targetN = targetNodes[iNode];
var Name = targetNodes[iNode].childNodes[0].nodeValue;
targetContainer.delItem(targetNodes[iNode].id);
var origData = { Id: resultObj.Id, Name: Name };
sourceContainer.insertNodes(true, origData);
break;
}
}
}
编辑: :解决方案(感谢Eugene Lazutkin)[2009/11/30]:
/**
* Move one node from one container to the other
*/
function moveNode(nodeId, sourceContainer, targetContainer) {
var node = dojo.byId(nodeId);
// Save the data
var saveData = sourceContainer.map[nodeId].data;
// Do the move
sourceContainer.parent.removeChild(node);
targetContainer.parent.appendChild(node);
// Sync the DOM object → map
sourceContainer.sync();
targetContainer.sync();
// Restore data for recreation of data
targetContainer.map[nodeId].data = saveData;
}
解决方案
看起来你假设 delItem
删除物理节点。看看 文档 - 可能您想在容器之间移动节点而不是从地图中删除它们。一种简单的方法就是在容器之间移动 DOM 节点,然后调用 sync()
在两个容器上。
添加: :这是一个超级简单的伪代码示例:
function move(node, source, target){
// normalize node and/or node id
node = dojo.byId(node);
// move it physically from one parent to another
// (from target to source) adding to the end
target.parent.appenChild(node);
// now it is moved from source to target
// let's synchronize both dojo.dnd.Source's
source.sync();
target.sync();
}
或者类似的东西应该有效。重要的部分:
- 使用您认为合适的任何 DOM 操作将节点从一个父节点移动到另一个父节点。我用了
appendChild()
, ,但你可以使用insertBefore()
, ,或其他任何东西。 - 移动后同步涉及的两个源。
显然,如果两个源都使用相同类型和结构的节点,则它可以工作。如果没有,您应该做一些更复杂的事情,例如,通过发布文档中描述的主题来移动您需要的所有内容,模拟真正的 DnD 移动。
其他提示
我有这个功能,通过按钮点击移动选定的节点:
source.forInItems(dojo.hitch(this, function(item, id, map) {
if (dojo.hasClass(id, "dojoDndItemAnchor")) {
target.onDrop(source, [ dojo.byId(id) ], false);
dojo.removeClass(id, "dojoDndItemAnchor");
}
}));
onDrop()
是一个可覆盖的方法,在项目删除时调用,默认情况下调用方法onDropExternal(source, nodes, copy)
。
我现在也在做同样的事情。我能够通过执行以下操作来解决。
- 将 dnd/Source autoSync 属性设置为 true
<div data-dojo-type="dojo.dnd.Source" accept="widget" class="source" data-dojo-props="autoSync: true">
拖动后它会丢失 dndtype,因此我必须使用客户端代码重新添加它。另外,我在放置后删除了 dojoDndItemAnchor 类。
$(node).removeClass('dojoDndItemAnchor').attr('dndtype', 'widget');