Dojo DnD以编程方式移动节点

时间:2009-11-28 10:02:05

标签: dojo drag-and-drop

我想知道是否有办法在dojo Dnd中以编程方式移动节点?原因是我希望在Web服务调用触发数据库上的失败保存时将更改还原为拖放。这是我到目前为止所拥有的。

在我的代码中,dojo.dnd.Container.DelItem似乎无法识别节点Id。我不能只使用目标上的选定项目,因为这是一个异步的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;
}

3 个答案:

答案 0 :(得分: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移动的所有内容。

答案 1 :(得分: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)

答案 2 :(得分:0)

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

  • 将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');