willf1976
9 Aug 2009, 10:43 PM
Hi All
I have made a simple treePanel plugin which allows for a copy of a node to be created when it is dropped into the tree (as opposed to the default functionality where the node is just moved).
The plugin includes some properties which can be used to set up simple logic for when a node is copied instead of moved (such as defining an array of components whose nodes will be copied when they are dropped into the treePanel).
The class also adds some events to the treePanel class which you can attach listeners to in order to define your own logical for when a node is copied instead of moved. Please see the documentation with in the class for more details.
Note: This plugin needs to be applied to the treePanel which the nodes will be dropped to and does not need to be on the treePanel where the nodes are dragged from.
Please let me know if you find any bugs or having suggestions.
Best regards
Will Ferrer
Update (09/03/09): This code now uses Ext.ux.tree.TreePanel.toObject to copy childNodes that have been dynamically added to branches. This code is available in thread: http://www.extjs.com/forum/showthread.php?t=20793.
Here is Ext.ux.tree.TreePanel.toObject:
/*
original author: dpasichnik
modified by: Will Ferrer
date: 09/03/09
history:
09/03/09 -- posted to ExtJS forums
*/
/**
This code is based on dpasichnik's treeSerializer found at:
http://www.extjs.com/forum/showthread.php?t=20793
*/
/**
* Returns a object that represents the tree
* @param {Function} nodeFilter (optional) A function, which when passed the node, returns true or false to include
* or exclude the node.
* @param {Function} attributeFilter (optional) A function, which when passed an attribute name, and an attribute value,
* returns true or false to include or exclude the attribute.
* @param {Object} attributeMapping (optional) An associative array which can you use to remap attribute names on the nodes as they are converted to an object. Keys in the array represent attributes to be remapped, and their associated values represent the new keys that those attributes will be remapped onto in the returned object.
* @return {String}
*/
Ext.tree.TreePanel.prototype.toObject = function(nodeFilter, attributeFilter, attributeMapping){
return this.getRootNode().toObject(nodeFilter, attributeFilter, attributeMapping);
};
/**
* Returns an object that represents the node
* @param {Function} nodeFilter (optional) A function, which when passed the node, returns true or false to include
* or exclude the node.
* @param {Function} attributeFilter (optional) A function, which when passed an attribute name, and an attribute value,
* returns true or false to include or exclude the attribute.
* @param {Object} attributeMapping (optional) An associative array which can you use to remap attribute names on the nodes as they are converted to an object. Keys in the array represent attributes to be remapped, and their associated values represent the new keys that those attributes will be remapped onto in the returned object.
* @return {String}
*/
Ext.tree.TreeNode.prototype.toObject = function(nodeFilter, attributeFilter, attributeMapping){
// Exclude nodes based on caller-supplied filtering function
if (nodeFilter && (nodeFilter(this) == false)) {
return {};
}
var c = false, returnObj = {};
// Add the id attribute unless the attribute filter rejects it.
if (!attributeFilter || attributeFilter("id", this.id)) {
returnObj.id = this.id;
c = true;
}
// Add all user-added attributes unless rejected by the attributeFilter.
for(var key in this.attributes) {
if ((key != 'id') && (!attributeFilter || attributeFilter(key, this.attributes[key]))) {
if (attributeMapping && attributeMapping[key]) {
thisKey = attributeMapping[key];
} else {
thisKey = key;
}
returnObj[thisKey] = this.attributes[key];
c = true;
}
}
// Add child nodes if any
var children = this.childNodes;
var clen = children.length;
if(clen != 0){
returnObj['children'] = [];
for(var i = 0; i < clen; i++){
returnObj['children'][i] = children[i].toObject(nodeFilter, attributeFilter, attributeMapping);
}
}
return returnObj;
}
Ext.ux.tree.TreePanel.CopyDropNode:
/*
author: Will Ferrer
date: 09/02/09
history:
08/09/09 -- posted to ExtJS forums
08/09/09 -- minor structural changes and changed class name
08/13/09 -- fixed a problem where copying nodes inside the same tree could result in duplicate node its.
08/21/09 -- added superclass.constructor.call for posterities sake
08/24/09 -- acceptFromComponents property added
09/02/09 -- added acceptFromSelf property
*/
/**
* @class Ext.ux.tree.TreePanel.CopyDropNode
* @extends Ext.util.Observable
* A simple plug in for TreePanel that allows you to make nodes dropped into the tree panel be copied instead of moved to the panel.
* Plugin includes properties that can be configured to discern what nodes should be copied and what nodes shouldn't.
* This plugin also adds some events to the treePanel on which the plugin was applied -- these events provide additional control over when a node is copied.
* In order to override the logic used in this plug in to determine whether a node should be copied or not, a boolean value of doCopy may be set on the node which is being dropped.
* You may also control this functionality by modifying the drop event itself -- please see the beforecopydropnode event definition for more details.
* @constructor
* @param {Object} config The config object
* @ptype ux-tree-treepanel-copydropnode
*/
Ext.ns('Ext.ux.tree.TreePanel');
Ext.ux.tree.TreePanel.CopyDropNode = function(config){
Ext.apply(this, config);
Ext.ux.tree.TreePanel.CopyDropNode.superclass.constructor.call(this);
};/*
author: Will Ferrer
date: 09/03/09
history:
08/09/09 -- posted to ExtJS forums
08/09/09 -- minor structural changes and changed class name
08/13/09 -- fixed a problem where copying nodes inside the same tree could result in duplicate node its.
08/21/09 -- added superclass.constructor.call for posterities sake
08/24/09 -- acceptFromComponents property added
09/02/09 -- added acceptFromSelf property
09/03/09 -- added fullBranchCopy, nodeFilter, attributeFilter, attributeMapping
09/04/09 -- added parent.copyDropNode = this;
*/
/**
* @class Ext.ux.tree.TreePanel.CopyDropNode
* @extends Ext.util.Observable
* A simple plug in for TreePanel that allows you to make nodes dropped into the tree panel be copied instead of moved to the panel.
* Plugin includes properties that can be configured to discern what nodes should be copied and what nodes shouldn't.
* This plugin also adds some events to the treePanel on which the plugin was applied -- these events provide additional control over when a node is copied.
* In order to override the logic used in this plug in to determine whether a node should be copied or not, a boolean value of doCopy may be set on the node which is being dropped.
* You may also control this functionality by modifying the drop event itself -- please see the beforecopydropnode event definition for more details.
* @constructor
* @param {Object} config The config object
* @ptype ux-tree-treepanel-copydropnode
*/
Ext.ns('Ext.ux.tree.TreePanel');
Ext.ux.tree.TreePanel.CopyDropNode = function(config){
Ext.apply(this, config);
Ext.ux.tree.TreePanel.CopyDropNode.superclass.constructor.call(this);
};
Ext.extend(Ext.ux.tree.TreePanel.CopyDropNode, Ext.util.Observable, {
//Public Properties:
/**
* @cfg {Boolean} enabled
* Whether or not copying is enabled -- if set to false this plug in will stop copying nodes. Defaults to true.
*/
enabled : true,
/**
* @cfg {Mixed} copyFromComponents
* An array of component ids or null to disable the feature. When a node is dropped on the tree we will check to see if the id of the tree the node was dragged from is present in this array, if it is we will copy the node rather than moving it. If set to null then which tree the node was dragged from won't be a factor in whether it is coppied or not. Defaults to null.
*/
copyFromComponents : null,
/**
* @cfg {Boolean} rejectFromComponents
* An array of component ids or null to disable the feature. When a node is dropped on the tree we will check to see if the id of the tree the node was dragged from is present in this array, if it is we will accept the drag opperation. Defaults to null.
*/
acceptFromComponents : null,
/**
* @cfg {Boolean} acceptFromSelf
* Whether or not to accept drags from with in the same tree. Defaults to true.
*/
acceptFromSelf : true,
/**
* @cfg {Boolean} copyLeafs
* Allow copying of leaf nodes. Defaults to true.
*/
copyLeafs : true,
/**
* @cfg {Boolean} copyLeafs
* Allow copying of branch nodes. Defaults to true.
*/
copyBranches : true,
/**
* @cfg {Boolean} preventCopyFromSelf
* Prevent a copy from occuring when droping nodes that originated in this tree panel
*/
preventCopyFromSelf : true,
/**
* @cfg {Boolean} copyInSameTreeChangeId
* When a copy takes place with in the same tree that the nodes orgenated from should we generated a new id for that node () in order to prevent duplicate nodes. Defaults to true.
*/
copyInSameTreeChangeId : true,
/**
* @cfg {Boolean} copyToDifferentTreeChangeId
* When a copy takes place between 2 trees should we generated a new id for that node () in order to prevent duplicate nodes. Defaults to false.
*/
copyToDifferentTreeChangeId : true,
//!!NOTE: The following features requires Ext.ux.tree.TreePanel.toObject which can be found at: http://www.extjs.com/forum/showthread.php?t=20793.
/**
* @cfg {Boolean} fullBranchCopy
* If set to true child nodes that have been added to branches of the tree will be properly coppied when you copy a branch node -- other wise these child nodes may not be coppied properly. Defaults to false.
*/
fullBranchCopy : false,
/**
* @cfg {Function|null} nodeFilter
* A function that will be used when a fullBranchCopyOccures -- which when passed the node, returns true or false to include or exclude the node. Defaults to null;
*/
nodeFilter : null,
/**
* @cfg {Function|null} attributeFilter
* A function that will be used when a fullBranchCopyOccures -- which when passed an attribute name, and an attribute value, returns true or false to include or exclude the attribute.. Defaults to null;
*/
attributeFilter : null,
/**
* @cfg {Array|null} attributeMapping
* A associative array that will be used when a fullBranchCopyOccures -- which can you use to remap attribute names on the nodes as they are converted to an object. Keys in the array represent attributes to be remapped, and their associated values represent the new keys that those attributes will be remapped onto in the returned object. Defaults to null;
*/
attributeMapping : null,
//Private Functions:
//@private
init: function(parent){
this.parent = parent;
this.parent.copyDropNode = this;
this.parent.on('beforenodedrop', this.onBeforeNodeDrop, this);
this.parent.addEvents(
/**
* @event beforecopydropnode
* Fires right before the copyDropNode function is run. This happens every time the treePanels beforenodedrop event fires. If you would like to override the standard logic used to define if a copy occures or not you may set a boolean value on the event object passed to the listener -- set a value of doCopy true or false to manually dictate whether or not a copy should occure. You may also return false from this event in order to stop the drop action from completeing enterly.
* @param {Ext.ux.tree.TreePanel.CopyDropNode} this
* @param {Object} e The dropNode event contains: (tree: The TreePanel, target: The node being targeted for the drop, data: The drag data from the drag source, point: The point of the drop - append, above or below, source: The drag source, rawEvent: Raw mouse event, dropNode: Drop node(s) provided by the source OR you can supply node(s) to be inserted by setting them on this object., cancel: Set this to true to cancel the drop, dropStatus: If the default drop action is cancelled but the drop is valid, setting this to true will prevent the animated "repair" from appearing.
*/
'beforecopydropnode',
/**
* @event aftercopydropnode
* Fires right after the copyDropNode function is run.
* @param {Ext.ux.tree.TreePanel.CopyDropNode} this
* @param {Boolean} copied true if a copy occured, false if one did not occure
* @param {Object} newNode the new node that was created when the copy occured
* @param {Object} e The dropNode event contains: (tree: The TreePanel, target: The node being targeted for the drop, data: The drag data from the drag source, point: The point of the drop - append, above or below, source: The drag source, rawEvent: Raw mouse event, dropNode: Drop node(s) provided by the source OR you can supply node(s) to be inserted by setting them on this object., cancel: Set this to true to cancel the drop, dropStatus: If the default drop action is cancelled but the drop is valid, setting this to true will prevent the animated "repair" from appearing.
*/
'aftercopydropnode'
);
},
//@private
onBeforeNodeDrop: function(e){
var finishDrop = this.parent.fireEvent("beforecopydropnode", this, e);
var enabled = this.enabled;
var copyFromComponents = (typeof(this.copyFromComponents)=='string')?[this.copyFromComponents]:this.copyFromComponents;
var acceptFromComponents = (typeof(this.acceptFromComponents)=='string')?[this.acceptFromComponents]:this.acceptFromComponents;
var copyLeafs = this.copyLeafs;
var copyBranches = this.copyBranches;
var preventCopyFromSelf = this.preventCopyFromSelf;
var acceptFromSelf = this.acceptFromSelf;
var node = e.dropNode;
var isLeaf = (typeof(node.attributes.leaf)!='undefined' && node.attributes.leaf);
var fromTreeId = e.source.tree.id;
var toTreeId = e.tree.id;
var fromSelf = (fromTreeId == toTreeId);
var doCopy = e.doCopy;
doCopy = (typeof(doCopy)=='undefined')?node.doCopy:doCopy;
var newNode;
finishDrop = ((Ext.isArray(acceptFromComponents) && this.inArray(acceptFromComponents, fromTreeId)) || !acceptFromComponents || (fromSelf && acceptFromSelf))?finishDrop:false;
if (finishDrop) {
if (enabled) {
if (typeof(doCopy)=='undefined') {
doCopy = ((Ext.isArray(copyFromComponents) && this.inArray(copyFromComponents, fromTreeId)) || !copyFromComponents);
doCopy = ((isLeaf && copyLeafs) || (!isLeaf && copyBranches))?doCopy:false;
doCopy = (!preventCopyFromSelf || !fromSelf)?doCopy:false;
}
newNode = (doCopy)?this.copyDropNode(e, node):null;
this.parent.fireEvent("aftercopydropnode", this, doCopy, newNode, e);
}
return true;
} else {
return false;
}
},
//@private
copyDropNode : function (e, node) {
//We make a new node based on the attributes of the node that was going to be dropped and then we swap it over the old node that was on the event in order to cause the new node to be added rather than the old node to be moved. Then the rest of the standard drag and drop functionality will proceed as normal.
var fromSelf = (node.ownerTree.id == e.tree.id), attributes;
if (this.fullBranchCopy) {
attributes = node.toObject(this.nodeFilter, this.attributeFilter, this.attributeMapping);
} else {
attributes = node.attributes
}
var newNode = new Ext.tree.AsyncTreeNode(attributes);
if ((fromSelf && this.copyInSameTreeChangeId) || (!fromSelf && this.copyToDifferentTreeChangeId)) {
var dummyNode = new Ext.tree.AsyncTreeNode({});
newNode.setId(dummyNode.id);
}
e.dropStatus = true;
e.dropNode = newNode;
return newNode;
},
//@private
inArray : function (array, value, caseSensitive) {
var i;
for (i=0; i < array.length; i++) {
// use === to check for Matches. ie., identical (===),
if(caseSensitive){ //performs match even the string is case sensitive
if (array[i].toLowerCase() == value.toLowerCase()) {
return true;
}
}else{
if (array[i] == value) {
return true;
}
}
}
return false;
}
});
Ext.preg('ux-tree-treepanel-copydropnode', Ext.ux.tree.TreePanel.CopyDropNode);
I have made a simple treePanel plugin which allows for a copy of a node to be created when it is dropped into the tree (as opposed to the default functionality where the node is just moved).
The plugin includes some properties which can be used to set up simple logic for when a node is copied instead of moved (such as defining an array of components whose nodes will be copied when they are dropped into the treePanel).
The class also adds some events to the treePanel class which you can attach listeners to in order to define your own logical for when a node is copied instead of moved. Please see the documentation with in the class for more details.
Note: This plugin needs to be applied to the treePanel which the nodes will be dropped to and does not need to be on the treePanel where the nodes are dragged from.
Please let me know if you find any bugs or having suggestions.
Best regards
Will Ferrer
Update (09/03/09): This code now uses Ext.ux.tree.TreePanel.toObject to copy childNodes that have been dynamically added to branches. This code is available in thread: http://www.extjs.com/forum/showthread.php?t=20793.
Here is Ext.ux.tree.TreePanel.toObject:
/*
original author: dpasichnik
modified by: Will Ferrer
date: 09/03/09
history:
09/03/09 -- posted to ExtJS forums
*/
/**
This code is based on dpasichnik's treeSerializer found at:
http://www.extjs.com/forum/showthread.php?t=20793
*/
/**
* Returns a object that represents the tree
* @param {Function} nodeFilter (optional) A function, which when passed the node, returns true or false to include
* or exclude the node.
* @param {Function} attributeFilter (optional) A function, which when passed an attribute name, and an attribute value,
* returns true or false to include or exclude the attribute.
* @param {Object} attributeMapping (optional) An associative array which can you use to remap attribute names on the nodes as they are converted to an object. Keys in the array represent attributes to be remapped, and their associated values represent the new keys that those attributes will be remapped onto in the returned object.
* @return {String}
*/
Ext.tree.TreePanel.prototype.toObject = function(nodeFilter, attributeFilter, attributeMapping){
return this.getRootNode().toObject(nodeFilter, attributeFilter, attributeMapping);
};
/**
* Returns an object that represents the node
* @param {Function} nodeFilter (optional) A function, which when passed the node, returns true or false to include
* or exclude the node.
* @param {Function} attributeFilter (optional) A function, which when passed an attribute name, and an attribute value,
* returns true or false to include or exclude the attribute.
* @param {Object} attributeMapping (optional) An associative array which can you use to remap attribute names on the nodes as they are converted to an object. Keys in the array represent attributes to be remapped, and their associated values represent the new keys that those attributes will be remapped onto in the returned object.
* @return {String}
*/
Ext.tree.TreeNode.prototype.toObject = function(nodeFilter, attributeFilter, attributeMapping){
// Exclude nodes based on caller-supplied filtering function
if (nodeFilter && (nodeFilter(this) == false)) {
return {};
}
var c = false, returnObj = {};
// Add the id attribute unless the attribute filter rejects it.
if (!attributeFilter || attributeFilter("id", this.id)) {
returnObj.id = this.id;
c = true;
}
// Add all user-added attributes unless rejected by the attributeFilter.
for(var key in this.attributes) {
if ((key != 'id') && (!attributeFilter || attributeFilter(key, this.attributes[key]))) {
if (attributeMapping && attributeMapping[key]) {
thisKey = attributeMapping[key];
} else {
thisKey = key;
}
returnObj[thisKey] = this.attributes[key];
c = true;
}
}
// Add child nodes if any
var children = this.childNodes;
var clen = children.length;
if(clen != 0){
returnObj['children'] = [];
for(var i = 0; i < clen; i++){
returnObj['children'][i] = children[i].toObject(nodeFilter, attributeFilter, attributeMapping);
}
}
return returnObj;
}
Ext.ux.tree.TreePanel.CopyDropNode:
/*
author: Will Ferrer
date: 09/02/09
history:
08/09/09 -- posted to ExtJS forums
08/09/09 -- minor structural changes and changed class name
08/13/09 -- fixed a problem where copying nodes inside the same tree could result in duplicate node its.
08/21/09 -- added superclass.constructor.call for posterities sake
08/24/09 -- acceptFromComponents property added
09/02/09 -- added acceptFromSelf property
*/
/**
* @class Ext.ux.tree.TreePanel.CopyDropNode
* @extends Ext.util.Observable
* A simple plug in for TreePanel that allows you to make nodes dropped into the tree panel be copied instead of moved to the panel.
* Plugin includes properties that can be configured to discern what nodes should be copied and what nodes shouldn't.
* This plugin also adds some events to the treePanel on which the plugin was applied -- these events provide additional control over when a node is copied.
* In order to override the logic used in this plug in to determine whether a node should be copied or not, a boolean value of doCopy may be set on the node which is being dropped.
* You may also control this functionality by modifying the drop event itself -- please see the beforecopydropnode event definition for more details.
* @constructor
* @param {Object} config The config object
* @ptype ux-tree-treepanel-copydropnode
*/
Ext.ns('Ext.ux.tree.TreePanel');
Ext.ux.tree.TreePanel.CopyDropNode = function(config){
Ext.apply(this, config);
Ext.ux.tree.TreePanel.CopyDropNode.superclass.constructor.call(this);
};/*
author: Will Ferrer
date: 09/03/09
history:
08/09/09 -- posted to ExtJS forums
08/09/09 -- minor structural changes and changed class name
08/13/09 -- fixed a problem where copying nodes inside the same tree could result in duplicate node its.
08/21/09 -- added superclass.constructor.call for posterities sake
08/24/09 -- acceptFromComponents property added
09/02/09 -- added acceptFromSelf property
09/03/09 -- added fullBranchCopy, nodeFilter, attributeFilter, attributeMapping
09/04/09 -- added parent.copyDropNode = this;
*/
/**
* @class Ext.ux.tree.TreePanel.CopyDropNode
* @extends Ext.util.Observable
* A simple plug in for TreePanel that allows you to make nodes dropped into the tree panel be copied instead of moved to the panel.
* Plugin includes properties that can be configured to discern what nodes should be copied and what nodes shouldn't.
* This plugin also adds some events to the treePanel on which the plugin was applied -- these events provide additional control over when a node is copied.
* In order to override the logic used in this plug in to determine whether a node should be copied or not, a boolean value of doCopy may be set on the node which is being dropped.
* You may also control this functionality by modifying the drop event itself -- please see the beforecopydropnode event definition for more details.
* @constructor
* @param {Object} config The config object
* @ptype ux-tree-treepanel-copydropnode
*/
Ext.ns('Ext.ux.tree.TreePanel');
Ext.ux.tree.TreePanel.CopyDropNode = function(config){
Ext.apply(this, config);
Ext.ux.tree.TreePanel.CopyDropNode.superclass.constructor.call(this);
};
Ext.extend(Ext.ux.tree.TreePanel.CopyDropNode, Ext.util.Observable, {
//Public Properties:
/**
* @cfg {Boolean} enabled
* Whether or not copying is enabled -- if set to false this plug in will stop copying nodes. Defaults to true.
*/
enabled : true,
/**
* @cfg {Mixed} copyFromComponents
* An array of component ids or null to disable the feature. When a node is dropped on the tree we will check to see if the id of the tree the node was dragged from is present in this array, if it is we will copy the node rather than moving it. If set to null then which tree the node was dragged from won't be a factor in whether it is coppied or not. Defaults to null.
*/
copyFromComponents : null,
/**
* @cfg {Boolean} rejectFromComponents
* An array of component ids or null to disable the feature. When a node is dropped on the tree we will check to see if the id of the tree the node was dragged from is present in this array, if it is we will accept the drag opperation. Defaults to null.
*/
acceptFromComponents : null,
/**
* @cfg {Boolean} acceptFromSelf
* Whether or not to accept drags from with in the same tree. Defaults to true.
*/
acceptFromSelf : true,
/**
* @cfg {Boolean} copyLeafs
* Allow copying of leaf nodes. Defaults to true.
*/
copyLeafs : true,
/**
* @cfg {Boolean} copyLeafs
* Allow copying of branch nodes. Defaults to true.
*/
copyBranches : true,
/**
* @cfg {Boolean} preventCopyFromSelf
* Prevent a copy from occuring when droping nodes that originated in this tree panel
*/
preventCopyFromSelf : true,
/**
* @cfg {Boolean} copyInSameTreeChangeId
* When a copy takes place with in the same tree that the nodes orgenated from should we generated a new id for that node () in order to prevent duplicate nodes. Defaults to true.
*/
copyInSameTreeChangeId : true,
/**
* @cfg {Boolean} copyToDifferentTreeChangeId
* When a copy takes place between 2 trees should we generated a new id for that node () in order to prevent duplicate nodes. Defaults to false.
*/
copyToDifferentTreeChangeId : true,
//!!NOTE: The following features requires Ext.ux.tree.TreePanel.toObject which can be found at: http://www.extjs.com/forum/showthread.php?t=20793.
/**
* @cfg {Boolean} fullBranchCopy
* If set to true child nodes that have been added to branches of the tree will be properly coppied when you copy a branch node -- other wise these child nodes may not be coppied properly. Defaults to false.
*/
fullBranchCopy : false,
/**
* @cfg {Function|null} nodeFilter
* A function that will be used when a fullBranchCopyOccures -- which when passed the node, returns true or false to include or exclude the node. Defaults to null;
*/
nodeFilter : null,
/**
* @cfg {Function|null} attributeFilter
* A function that will be used when a fullBranchCopyOccures -- which when passed an attribute name, and an attribute value, returns true or false to include or exclude the attribute.. Defaults to null;
*/
attributeFilter : null,
/**
* @cfg {Array|null} attributeMapping
* A associative array that will be used when a fullBranchCopyOccures -- which can you use to remap attribute names on the nodes as they are converted to an object. Keys in the array represent attributes to be remapped, and their associated values represent the new keys that those attributes will be remapped onto in the returned object. Defaults to null;
*/
attributeMapping : null,
//Private Functions:
//@private
init: function(parent){
this.parent = parent;
this.parent.copyDropNode = this;
this.parent.on('beforenodedrop', this.onBeforeNodeDrop, this);
this.parent.addEvents(
/**
* @event beforecopydropnode
* Fires right before the copyDropNode function is run. This happens every time the treePanels beforenodedrop event fires. If you would like to override the standard logic used to define if a copy occures or not you may set a boolean value on the event object passed to the listener -- set a value of doCopy true or false to manually dictate whether or not a copy should occure. You may also return false from this event in order to stop the drop action from completeing enterly.
* @param {Ext.ux.tree.TreePanel.CopyDropNode} this
* @param {Object} e The dropNode event contains: (tree: The TreePanel, target: The node being targeted for the drop, data: The drag data from the drag source, point: The point of the drop - append, above or below, source: The drag source, rawEvent: Raw mouse event, dropNode: Drop node(s) provided by the source OR you can supply node(s) to be inserted by setting them on this object., cancel: Set this to true to cancel the drop, dropStatus: If the default drop action is cancelled but the drop is valid, setting this to true will prevent the animated "repair" from appearing.
*/
'beforecopydropnode',
/**
* @event aftercopydropnode
* Fires right after the copyDropNode function is run.
* @param {Ext.ux.tree.TreePanel.CopyDropNode} this
* @param {Boolean} copied true if a copy occured, false if one did not occure
* @param {Object} newNode the new node that was created when the copy occured
* @param {Object} e The dropNode event contains: (tree: The TreePanel, target: The node being targeted for the drop, data: The drag data from the drag source, point: The point of the drop - append, above or below, source: The drag source, rawEvent: Raw mouse event, dropNode: Drop node(s) provided by the source OR you can supply node(s) to be inserted by setting them on this object., cancel: Set this to true to cancel the drop, dropStatus: If the default drop action is cancelled but the drop is valid, setting this to true will prevent the animated "repair" from appearing.
*/
'aftercopydropnode'
);
},
//@private
onBeforeNodeDrop: function(e){
var finishDrop = this.parent.fireEvent("beforecopydropnode", this, e);
var enabled = this.enabled;
var copyFromComponents = (typeof(this.copyFromComponents)=='string')?[this.copyFromComponents]:this.copyFromComponents;
var acceptFromComponents = (typeof(this.acceptFromComponents)=='string')?[this.acceptFromComponents]:this.acceptFromComponents;
var copyLeafs = this.copyLeafs;
var copyBranches = this.copyBranches;
var preventCopyFromSelf = this.preventCopyFromSelf;
var acceptFromSelf = this.acceptFromSelf;
var node = e.dropNode;
var isLeaf = (typeof(node.attributes.leaf)!='undefined' && node.attributes.leaf);
var fromTreeId = e.source.tree.id;
var toTreeId = e.tree.id;
var fromSelf = (fromTreeId == toTreeId);
var doCopy = e.doCopy;
doCopy = (typeof(doCopy)=='undefined')?node.doCopy:doCopy;
var newNode;
finishDrop = ((Ext.isArray(acceptFromComponents) && this.inArray(acceptFromComponents, fromTreeId)) || !acceptFromComponents || (fromSelf && acceptFromSelf))?finishDrop:false;
if (finishDrop) {
if (enabled) {
if (typeof(doCopy)=='undefined') {
doCopy = ((Ext.isArray(copyFromComponents) && this.inArray(copyFromComponents, fromTreeId)) || !copyFromComponents);
doCopy = ((isLeaf && copyLeafs) || (!isLeaf && copyBranches))?doCopy:false;
doCopy = (!preventCopyFromSelf || !fromSelf)?doCopy:false;
}
newNode = (doCopy)?this.copyDropNode(e, node):null;
this.parent.fireEvent("aftercopydropnode", this, doCopy, newNode, e);
}
return true;
} else {
return false;
}
},
//@private
copyDropNode : function (e, node) {
//We make a new node based on the attributes of the node that was going to be dropped and then we swap it over the old node that was on the event in order to cause the new node to be added rather than the old node to be moved. Then the rest of the standard drag and drop functionality will proceed as normal.
var fromSelf = (node.ownerTree.id == e.tree.id), attributes;
if (this.fullBranchCopy) {
attributes = node.toObject(this.nodeFilter, this.attributeFilter, this.attributeMapping);
} else {
attributes = node.attributes
}
var newNode = new Ext.tree.AsyncTreeNode(attributes);
if ((fromSelf && this.copyInSameTreeChangeId) || (!fromSelf && this.copyToDifferentTreeChangeId)) {
var dummyNode = new Ext.tree.AsyncTreeNode({});
newNode.setId(dummyNode.id);
}
e.dropStatus = true;
e.dropNode = newNode;
return newNode;
},
//@private
inArray : function (array, value, caseSensitive) {
var i;
for (i=0; i < array.length; i++) {
// use === to check for Matches. ie., identical (===),
if(caseSensitive){ //performs match even the string is case sensitive
if (array[i].toLowerCase() == value.toLowerCase()) {
return true;
}
}else{
if (array[i] == value) {
return true;
}
}
}
return false;
}
});
Ext.preg('ux-tree-treepanel-copydropnode', Ext.ux.tree.TreePanel.CopyDropNode);