开发者

Dojo DnD Move Node Programmatically

I would like to know if there is a way to move the node programmatically in dojo Dnd? The reason is I would like to revert the changes to the drag and drop when the web service call triggered a failed save on the database. Here is what I have so far.

In my code, the node Id seems to be unrecognized by the dojo.dnd.Container.DelItem. I cannot just use the selected item on the target because this is a asynchronous webservice function callback. So the user may be selecting another node on the container when this is called.

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;
        }
    }
}

EDIT: Solution (Thanks Eugene Lazutkin) [2009/11/30]:

/**
* Move one node from one container to the other
*/
f开发者_Go百科unction 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;
}


It looks like you assume that delItem removes physical nodes. Take a look at the documentation — probably you want to move nodes between containers instead of deleting them from the map. One simple way to do that just to move DOM nodes between containers, and call sync() on both containers.

Addition: Here is a super-simple pseudocode-like example:

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();
}

Or something along these lines should work. The important pieces:

  • Move node from one parent to another using any DOM operations you deem appropriate. I used appendChild(), but you can use insertBefore(), or anything else.
  • Synchronize both sources involved after the move.

Obviously it works if both sources use nodes of the same type and structure. If not, you should do something more complex, e.g., move everything you need emulating a real DnD move by publishing topics described in the documentation.


I have this function which moves selected nodes by button click:

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() is an overridable method, which is called upon item drop, and by default calls to method onDropExternal(source, nodes, copy).


I am doing the same thing right now. I was able to solve by doing the following.

  • Set the dnd/Source autoSync property to true

<div data-dojo-type="dojo.dnd.Source" accept="widget" class="source" data-dojo-props="autoSync: true">

After dragging it looses the dndtype so I had to re-add it using client side code. Also I remove the dojoDndItemAnchor class after drop.

$(node).removeClass('dojoDndItemAnchor').attr('dndtype', 'widget');

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜