开发者

Dojo DnD: how to access newly copied node on onDndDrop event?

I am working on code like the following.

01: var c1 = new dojo.dnd.Source('container1', {copyOnly:true}); // container1 is a div
02: var c2 = new dojo.dnd.Source('container2');                  // container2 is a div
03: var list = [];
04: for (var i = 0; i < 3; i++) { list.push( dojo.create('div') ); }
05: c1.insertNodes(false, list);
06: 
07: function checkDndCopy(nodes, target){
08:  dojo.forEach(nodes, function(node){ alert(node.id); } );
09: }
10: dojo.subscribe("/dnd/drop", function(){
11:   var mgr = dojo.dnd.manager();
12:   checkDndCopy(mgr.nodes, mgr.target);开发者_JAVA技巧
13: });

The nodes inserted to the c1 at line 05 have id of "dojoUnique1, donoUnique2, dojoUnique3". On a event of drag and drop a node from c1 to c2, a onDndDrop event is fired and the subscribe method defined in line10-13 is invoked.

I expected that newly copied node appears in the nodes (for example) at line 08. But this is not true. When dojoUnique1 is target of drag and drop, nodes at line 08 contains only dojoUnique1.

I want to modify some attributes of newly copied nodes on the event of onDndDrop. Please let me know how such a thing is realized.


I'm not sure, if it is the only (and best) way, but you may write your own node creator to override dropped node and avatar creation. Example below extends your code and makes dropped nodes red:

    var c1 = new dojo.dnd.Source('container1', {copyOnly:true }); // container1 is a div
    var c2 = new dojo.dnd.Source('container2', { creator: nodeCreator }  );   // container2 is a div

    function nodeCreator(item, hint) {
      var node = dojo.create("div", { innerHTML: item }); 
      if (hint != "avatar") {
        dojo.style(node, 'color', 'red');
      }
      return { node: node, data: item };
    }

You can find more information about writing own creators here and in google


First, as a rule of thumb try to avoid using DnD topics especially for local things — they are cumbersome to use because by the time your function is called parameters can be modified or even destroyed by other processors (as you already discovered). Use local events and/or override methods. If you want to do something to newly inserted nodes just override onDrop (or onDropExternal, or onDropInternal, if you want to handle only specific drops).

Another useful hint: newly inserted nodes are selected.

Let's code it up:

var c1 = new dojo.dnd.Source('container1', {copyOnly:true});
var c2 = new dojo.dnd.Source('container2');

// ...

// the decorator technique
function paintRed(source){
  var old_onDrop = source.onDrop;
  source.onDrop = function(){
    // we don't care about actual parameters
    // (we will pass them in bulk)
    // let's do a drop:
    old_onDrop.apply(this, arguments);
    // now all dropped items are inserted and selected in c2
    // let's iterated over all selected items:
    this.forInSelectedItems(function(item, id){
      // print the id
      console.log(id);
      // paint it red
      dojo.style(id, "color", "red");
    });
  };
}

// now let's decorate c2
paintRed(c2);
// now c2 paints all dropped nodes red

If you allow to rearrange lists and want to do the modifications only for external drops (e.g., from c1 to c2), you should override onDropExternal. The code will be the same.

Because this example doesn't rely on original items, you can do it with topics but you may need some extra code if you want to do it conditionally (e.g., for c2, but not c1). If you don't care about any other things, it is actually pretty easy too:

dojo.subscribe("/dnd/drop", function(source, nodes, copy, target){
  // warning: by the time this function is called nodes
  // can be copied/modified/destroyed --- do not rely on them!
  // but we don't need them here
  target.forInSelectedItems(function(item, id){
    // print the id
    console.log(id);
    // paint it red
    dojo.style(id, "color", "red");
  });
});


Based on the way of using custom creator, I found following.

var d;
d = dojo.doc.createElement('div');
var c01 = new dojo.dnd.Source(d, { 'copyOnly': true, 'accept': [], 'creator': myCreator});

var arr = [];
for(i=0; i<3; i++){ 
  d = dojo.create('div'); // dnd items
  // define contents and properties of d
  arr.push( d );
}
c01.insertNodes(false, divArr);

d = dojo.doc.createElement('div');
var c02 = new dojo.dnd.Source(d, { 'creator': myCreator});

function myCreator(item, hint){
  var node = dojo.doc.createElement('div');
  node.id = dojo.dnd.getUniqueId();
  var mgr = dojo.dnd.manager();
  // from dojo.dnd.manager(), it is possible to find which one to create 
  // the follwoing condition is just a sample
  if(hint != 'avatar' && 
     mgr.source && mgr.target // these are null when creating newly inserted one
     mgr.source.node && mgr.target.node // by inspecting these nodes, one can know
                                        // whether the item is newly copied one
  ){
    dojo.style(node, 'color', 'red');
    // one can get mouse position from mgr and set the node position
  }
  var copyItem = createCopyItem( item );
  dojo.place(copyItem, node, 'last');

  return { node: node, data: copyItem, type:[ /* what you want */ ] };
}

Function createCopyItem() is out of scope. It is necessary to copy item and modify the new object because item cannot be placed both under its original parentNode and under node created in myCreator().

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜