2009-11-28 50 views
2

我想知道是否有方法在dojo Dnd中以编程方式移动节点?原因是我想恢复对Web服务调用触发数据库失败保存时拖放的更改。这是我到目前为止。Dojo DnD以编程方式移动节点

在我的代码中,节点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; 
     } 
    } 
} 

编辑:解决方案(感谢尤金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; 
} 
+0

你怎么祈求的OnMoveWSComplete免打扰完成后?我创建了一个适用于/ dnd/drop的函数,但是当它被调用时,DnD还没有创建,所以更改的反向失败。你能给我一个调用的例子吗? 谢谢。 何塞 – 2010-05-19 13:36:14

+0

何塞,当我承认我刚刚使用连接的Dnd drop事件。它适用于我。 dojo.connect(containerId,'onDrop',onDropSave); – Nap 2010-05-20 06:39:26

回答

3

看起来你认为delItem删除物理节点。看看documentation —可能你想在容器之间移动节点,而不是从地图上删除它们。一个简单的方法就是在容器之间移动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动作。

+0

我其实也已经做过同步(),但它不起作用。顺便说一句,如果删除然后添加不建议,你可以指向我的移动功能?我在文档中找不到任何功能。 – Nap 2009-11-30 00:40:32

+1

没有特殊的API在源之间移动节点。你在我的回答(最后一句)中试过了我为你勾画的那个吗?好的,我会添加一个例子。 – 2009-11-30 01:45:51

+0

我刚刚读了sync的源代码。看起来delItem()和sync()调用不起作用的原因是因为delItem()从map中删除,而sync()将实际的DOM节点复制回实际上否定delItem()的映射结构。 – Nap 2009-11-30 03:02:11

2

我有这个功能,通过点击按钮移动选定的节点:

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)

0

我现在正在做同样的事情。我能够通过以下方式解决问题。

  • 设置免打扰/来源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');