rad_nq
12 Mar 2007, 12:26 PM
While multi-node selection worked since 0.4 with the MultiSelectionModel you cannot (since last looked in 1.0 code) actually select multiple nodes and perform a Drag and Drop operation with them. Selection falls back to a single node and that is DnD'ed.
The following is a TreeDragZone subclass to allow for multiple node selection Drag and Drop operations.
Note: the render() in Tree has to be completely copied as I have not been able to create a standalone TreeDragZone instance and then set it to the tree. Exceptions all over the place so if anyone knows a better way of making and setting the "this.dropZone" on a TreePanel post a reply.
This was coded against 0.4 so adjust for 1.0 code as needed. (We are waiting for the alpha run to complete before migrating).
::override your TreePanel's render function with something like:
treePanel.render = function(){
}
The code body of the function is identical to the original except change:
if((this.enableDD || this.enableDrag) && !this.dragZone){
this.dragZone = new YAHOO.ext.tree.TreeDragZone(this, this.dragConfig || {
ddGroup: this.ddGroup || 'TreeDD',
scroll: this.ddScroll
});
}
with:
if((this.enableDD || this.enableDrag) && !this.dragZone){
this.dragZone = new RAD.tree.MultiDragZone(this, this.dragConfig || {
ddGroup: this.ddGroup || 'TreeDD',
scroll: this.ddScroll
});
}
And now the implementation of MultiDragZone:
YAHOO.extendX(RAD.tree.MultiDragZone, YAHOO.ext.tree.TreeDragZone, {
/**
* TreeDragZone does not support multiple selection very well. So if we are using
* a multi select model, then handle it appropriately.
*/
onInitDrag: function(e){
if(this.tree.getSelectionModel().getSelectedNodes){
return YAHOO.ext.tree.TreeDragZone.superclass.onInitDrag.call(this, e);
} else {
return RAD.tree.MultiDragZone.superclass.onInitDrag.call(this,e);
}
},
/**
* This returns the XY coordinates to send the animating repair ghost from failed DnD.
* We just grab the last selected item and focus the drop there. Should perhaps be something else?
*/
getRepairXY: function(e, data){
var result;
if(data.node){//invocation
result = RAD.tree.MultiDragZone.superclass.getRepairXY.call(this,e, data);
}else if(data.treeNodes){
result = data.treeNodes[data.treeNodes.length - 1].getUI().getDDRepairXY();
}else {
result = false;
}
return result;
},
/**
* TreeDragZone does not support multiple selection very well.
*/
beforeInvalidDrop: function(e, id){
return YAHOO.ext.tree.TreeDragZone.superclass.beforeInvalidDrop.call(this, e, id);
},
/**
* Gets the TreeNodes contained in data that are to be copied.
* @param data : The DnD object generated by getDragData
* @param targetNode : The node drop will be applied to.
* @param point : ??
* @param e : ??
*/
getTreeNode: function(data, targetNode, point, e){
return data.treeNodes;//move or copy will be handling this.
},
getDragData: function(e){
var dragData = YAHOO.ext.dd.Registry.getHandleFromEvent(e);
var selModel = this.tree.getSelectionModel();
if(dragData != null && selModel.getSelectedNodes){//Only do non-standard logic IF we have multiple selections.
//Ensure the node is selected.
if(!selModel.isSelected(dragData.node)){
//selModel.select(dragData.node, null, true);
}
var selNodes = selModel.getSelectedNodes();
if(selNodes.length > 1){
//We need to build up array of selected Tree elements.
var htmlNodes = new Array();
for(var i=0, len = selNodes.length; i< len; i++){
htmlNodes[i] = selNodes[i].getUI().getEl().firstChild;
}
dragData = {
nodes: htmlNodes,
multi: true,
treeNodes: selNodes
};
var div = document.createElement('div');//Create the multi element "ghost"
div.className = 'multi-proxy';//ydd-drag-proxy and ydd-drag-ghost
for(var i=0, len = htmlNodes.length; i< len; i++){
div.appendChild(htmlNodes[i].cloneNode(true));
//does automagic nextline stuff.
}
dragData.ddel = div;
}
}
return dragData;
}
});
The following is a TreeDragZone subclass to allow for multiple node selection Drag and Drop operations.
Note: the render() in Tree has to be completely copied as I have not been able to create a standalone TreeDragZone instance and then set it to the tree. Exceptions all over the place so if anyone knows a better way of making and setting the "this.dropZone" on a TreePanel post a reply.
This was coded against 0.4 so adjust for 1.0 code as needed. (We are waiting for the alpha run to complete before migrating).
::override your TreePanel's render function with something like:
treePanel.render = function(){
}
The code body of the function is identical to the original except change:
if((this.enableDD || this.enableDrag) && !this.dragZone){
this.dragZone = new YAHOO.ext.tree.TreeDragZone(this, this.dragConfig || {
ddGroup: this.ddGroup || 'TreeDD',
scroll: this.ddScroll
});
}
with:
if((this.enableDD || this.enableDrag) && !this.dragZone){
this.dragZone = new RAD.tree.MultiDragZone(this, this.dragConfig || {
ddGroup: this.ddGroup || 'TreeDD',
scroll: this.ddScroll
});
}
And now the implementation of MultiDragZone:
YAHOO.extendX(RAD.tree.MultiDragZone, YAHOO.ext.tree.TreeDragZone, {
/**
* TreeDragZone does not support multiple selection very well. So if we are using
* a multi select model, then handle it appropriately.
*/
onInitDrag: function(e){
if(this.tree.getSelectionModel().getSelectedNodes){
return YAHOO.ext.tree.TreeDragZone.superclass.onInitDrag.call(this, e);
} else {
return RAD.tree.MultiDragZone.superclass.onInitDrag.call(this,e);
}
},
/**
* This returns the XY coordinates to send the animating repair ghost from failed DnD.
* We just grab the last selected item and focus the drop there. Should perhaps be something else?
*/
getRepairXY: function(e, data){
var result;
if(data.node){//invocation
result = RAD.tree.MultiDragZone.superclass.getRepairXY.call(this,e, data);
}else if(data.treeNodes){
result = data.treeNodes[data.treeNodes.length - 1].getUI().getDDRepairXY();
}else {
result = false;
}
return result;
},
/**
* TreeDragZone does not support multiple selection very well.
*/
beforeInvalidDrop: function(e, id){
return YAHOO.ext.tree.TreeDragZone.superclass.beforeInvalidDrop.call(this, e, id);
},
/**
* Gets the TreeNodes contained in data that are to be copied.
* @param data : The DnD object generated by getDragData
* @param targetNode : The node drop will be applied to.
* @param point : ??
* @param e : ??
*/
getTreeNode: function(data, targetNode, point, e){
return data.treeNodes;//move or copy will be handling this.
},
getDragData: function(e){
var dragData = YAHOO.ext.dd.Registry.getHandleFromEvent(e);
var selModel = this.tree.getSelectionModel();
if(dragData != null && selModel.getSelectedNodes){//Only do non-standard logic IF we have multiple selections.
//Ensure the node is selected.
if(!selModel.isSelected(dragData.node)){
//selModel.select(dragData.node, null, true);
}
var selNodes = selModel.getSelectedNodes();
if(selNodes.length > 1){
//We need to build up array of selected Tree elements.
var htmlNodes = new Array();
for(var i=0, len = selNodes.length; i< len; i++){
htmlNodes[i] = selNodes[i].getUI().getEl().firstChild;
}
dragData = {
nodes: htmlNodes,
multi: true,
treeNodes: selNodes
};
var div = document.createElement('div');//Create the multi element "ghost"
div.className = 'multi-proxy';//ydd-drag-proxy and ydd-drag-ghost
for(var i=0, len = htmlNodes.length; i< len; i++){
div.appendChild(htmlNodes[i].cloneNode(true));
//does automagic nextline stuff.
}
dragData.ddel = div;
}
}
return dragData;
}
});