3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
\r
4 <title>The source code</title>
\r
5 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
\r
6 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
\r
8 <body onload="prettyPrint();">
\r
9 <pre class="prettyprint lang-js"><div id="cls-Ext.tree.TreeDropZone"></div>/**
\r
10 * @class Ext.tree.TreeDropZone
\r
11 * @extends Ext.dd.DropZone
\r
13 * @param {String/HTMLElement/Element} tree The {@link Ext.tree.TreePanel} for which to enable dropping
\r
14 * @param {Object} config
\r
16 if(Ext.dd.DropZone){
\r
18 Ext.tree.TreeDropZone = function(tree, config){
\r
19 <div id="cfg-Ext.tree.TreeDropZone-allowParentInsert"></div>/**
\r
20 * @cfg {Boolean} allowParentInsert
\r
21 * Allow inserting a dragged node between an expanded parent node and its first child that will become a
\r
22 * sibling of the parent when dropped (defaults to false)
\r
24 this.allowParentInsert = config.allowParentInsert || false;
\r
25 <div id="cfg-Ext.tree.TreeDropZone-allowContainerDrop"></div>/**
\r
26 * @cfg {String} allowContainerDrop
\r
27 * True if drops on the tree container (outside of a specific tree node) are allowed (defaults to false)
\r
29 this.allowContainerDrop = config.allowContainerDrop || false;
\r
30 <div id="cfg-Ext.tree.TreeDropZone-appendOnly"></div>/**
\r
31 * @cfg {String} appendOnly
\r
32 * True if the tree should only allow append drops (use for trees which are sorted, defaults to false)
\r
34 this.appendOnly = config.appendOnly || false;
\r
36 Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
\r
37 <div id="prop-Ext.tree.TreeDropZone-tree"></div>/**
\r
38 * The TreePanel for this drop zone
\r
39 * @type Ext.tree.TreePanel
\r
43 <div id="prop-Ext.tree.TreeDropZone-dragOverData"></div>/**
\r
44 * Arbitrary data that can be associated with this tree and will be included in the event object that gets
\r
45 * passed to any nodedragover event handler (defaults to {})
\r
46 * @type Ext.tree.TreePanel
\r
49 this.dragOverData = {};
\r
51 this.lastInsertClass = "x-tree-no-status";
\r
54 Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
\r
55 <div id="cfg-Ext.tree.TreeDropZone-ddGroup"></div>/**
\r
56 * @cfg {String} ddGroup
\r
57 * A named drag drop group to which this object belongs. If a group is specified, then this object will only
\r
58 * interact with other drag drop objects in the same group (defaults to 'TreeDD').
\r
62 <div id="cfg-Ext.tree.TreeDropZone-expandDelay"></div>/**
\r
63 * @cfg {String} expandDelay
\r
64 * The delay in milliseconds to wait before expanding a target tree node while dragging a droppable node
\r
65 * over the target (defaults to 1000)
\r
70 expandNode : function(node){
\r
71 if(node.hasChildNodes() && !node.isExpanded()){
\r
72 node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
\r
77 queueExpand : function(node){
\r
78 this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
\r
82 cancelExpand : function(){
\r
83 if(this.expandProcId){
\r
84 clearTimeout(this.expandProcId);
\r
85 this.expandProcId = false;
\r
90 isValidDropPoint : function(n, pt, dd, e, data){
\r
91 if(!n || !data){ return false; }
\r
92 var targetNode = n.node;
\r
93 var dropNode = data.node;
\r
94 // default drop rules
\r
95 if(!(targetNode && targetNode.isTarget && pt)){
\r
98 if(pt == "append" && targetNode.allowChildren === false){
\r
101 if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
\r
104 if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
\r
107 // reuse the object
\r
108 var overEvent = this.dragOverData;
\r
109 overEvent.tree = this.tree;
\r
110 overEvent.target = targetNode;
\r
111 overEvent.data = data;
\r
112 overEvent.point = pt;
\r
113 overEvent.source = dd;
\r
114 overEvent.rawEvent = e;
\r
115 overEvent.dropNode = dropNode;
\r
116 overEvent.cancel = false;
\r
117 var result = this.tree.fireEvent("nodedragover", overEvent);
\r
118 return overEvent.cancel === false && result !== false;
\r
122 getDropPoint : function(e, n, dd){
\r
125 return tn.allowChildren !== false ? "append" : false; // always append for root
\r
127 var dragEl = n.ddel;
\r
128 var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
\r
129 var y = Ext.lib.Event.getPageY(e);
\r
130 var noAppend = tn.allowChildren === false || tn.isLeaf();
\r
131 if(this.appendOnly || tn.parentNode.allowChildren === false){
\r
132 return noAppend ? false : "append";
\r
134 var noBelow = false;
\r
135 if(!this.allowParentInsert){
\r
136 noBelow = tn.hasChildNodes() && tn.isExpanded();
\r
138 var q = (b - t) / (noAppend ? 2 : 3);
\r
139 if(y >= t && y < (t + q)){
\r
141 }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
\r
149 onNodeEnter : function(n, dd, e, data){
\r
150 this.cancelExpand();
\r
153 onContainerOver : function(dd, e, data) {
\r
154 if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
\r
155 return this.dropAllowed;
\r
157 return this.dropNotAllowed;
\r
161 onNodeOver : function(n, dd, e, data){
\r
162 var pt = this.getDropPoint(e, n, dd);
\r
165 // auto node expand check
\r
166 if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
\r
167 this.queueExpand(node);
\r
168 }else if(pt != "append"){
\r
169 this.cancelExpand();
\r
172 // set the insert point style on the target node
\r
173 var returnCls = this.dropNotAllowed;
\r
174 if(this.isValidDropPoint(n, pt, dd, e, data)){
\r
179 returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
\r
180 cls = "x-tree-drag-insert-above";
\r
181 }else if(pt == "below"){
\r
182 returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
\r
183 cls = "x-tree-drag-insert-below";
\r
185 returnCls = "x-tree-drop-ok-append";
\r
186 cls = "x-tree-drag-append";
\r
188 if(this.lastInsertClass != cls){
\r
189 Ext.fly(el).replaceClass(this.lastInsertClass, cls);
\r
190 this.lastInsertClass = cls;
\r
198 onNodeOut : function(n, dd, e, data){
\r
199 this.cancelExpand();
\r
200 this.removeDropIndicators(n);
\r
204 onNodeDrop : function(n, dd, e, data){
\r
205 var point = this.getDropPoint(e, n, dd);
\r
206 var targetNode = n.node;
\r
207 targetNode.ui.startDrop();
\r
208 if(!this.isValidDropPoint(n, point, dd, e, data)){
\r
209 targetNode.ui.endDrop();
\r
212 // first try to find the drop node
\r
213 var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
\r
214 return this.processDrop(targetNode, data, point, dd, e, dropNode);
\r
217 onContainerDrop : function(dd, e, data){
\r
218 if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
\r
219 var targetNode = this.tree.getRootNode();
\r
220 targetNode.ui.startDrop();
\r
221 var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
\r
222 return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
\r
228 processDrop: function(target, data, point, dd, e, dropNode){
\r
236 dropNode: dropNode,
\r
240 var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
\r
241 if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
\r
242 target.ui.endDrop();
\r
243 return dropEvent.dropStatus;
\r
246 target = dropEvent.target;
\r
247 if(point == 'append' && !target.isExpanded()){
\r
248 target.expand(false, null, function(){
\r
249 this.completeDrop(dropEvent);
\r
250 }.createDelegate(this));
\r
252 this.completeDrop(dropEvent);
\r
258 completeDrop : function(de){
\r
259 var ns = de.dropNode, p = de.point, t = de.target;
\r
260 if(!Ext.isArray(ns)){
\r
264 for(var i = 0, len = ns.length; i < len; i++){
\r
267 t.parentNode.insertBefore(n, t);
\r
268 }else if(p == "below"){
\r
269 t.parentNode.insertBefore(n, t.nextSibling);
\r
275 if(Ext.enableFx && this.tree.hlDrop){
\r
279 this.tree.fireEvent("nodedrop", de);
\r
283 afterNodeMoved : function(dd, data, e, targetNode, dropNode){
\r
284 if(Ext.enableFx && this.tree.hlDrop){
\r
285 dropNode.ui.focus();
\r
286 dropNode.ui.highlight();
\r
288 this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
\r
292 getTree : function(){
\r
297 removeDropIndicators : function(n){
\r
300 Ext.fly(el).removeClass([
\r
301 "x-tree-drag-insert-above",
\r
302 "x-tree-drag-insert-below",
\r
303 "x-tree-drag-append"]);
\r
304 this.lastInsertClass = "_noclass";
\r
309 beforeDragDrop : function(target, e, id){
\r
310 this.cancelExpand();
\r
315 afterRepair : function(data){
\r
316 if(data && Ext.enableFx){
\r
317 data.node.ui.highlight();
\r