Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / docs / source / DropZone2.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-grid-header-DropZone'>/**
19 </span> * @class Ext.grid.header.DropZone
20  * @extends Ext.dd.DropZone
21  * @private
22  */
23 Ext.define('Ext.grid.header.DropZone', {
24     extend: 'Ext.dd.DropZone',
25     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
26     proxyOffsets: [-4, -9],
27
28     constructor: function(headerCt){
29         this.headerCt = headerCt;
30         this.ddGroup = this.getDDGroup();
31         this.callParent([headerCt.el]);
32     },
33
34     getDDGroup: function() {
35         return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
36     },
37
38     getTargetFromEvent : function(e){
39         return e.getTarget('.' + this.colHeaderCls);
40     },
41
42     getTopIndicator: function() {
43         if (!this.topIndicator) {
44             this.topIndicator = Ext.core.DomHelper.append(Ext.getBody(), {
45                 cls: &quot;col-move-top&quot;,
46                 html: &quot;&amp;#160;&quot;
47             }, true);
48         }
49         return this.topIndicator;
50     },
51
52     getBottomIndicator: function() {
53         if (!this.bottomIndicator) {
54             this.bottomIndicator = Ext.core.DomHelper.append(Ext.getBody(), {
55                 cls: &quot;col-move-bottom&quot;,
56                 html: &quot;&amp;#160;&quot;
57             }, true);
58         }
59         return this.bottomIndicator;
60     },
61
62     getLocation: function(e, t) {
63         var x      = e.getXY()[0],
64             region = Ext.fly(t).getRegion(),
65             pos, header;
66
67         if ((region.right - x) &lt;= (region.right - region.left) / 2) {
68             pos = &quot;after&quot;;
69         } else {
70             pos = &quot;before&quot;;
71         }
72         return {
73             pos: pos,
74             header: Ext.getCmp(t.id),
75             node: t
76         };
77     },
78
79     positionIndicator: function(draggedHeader, node, e){
80         var location = this.getLocation(e, node),
81             header = location.header,
82             pos    = location.pos,
83             nextHd = draggedHeader.nextSibling('gridcolumn:not([hidden])'),
84             prevHd = draggedHeader.previousSibling('gridcolumn:not([hidden])'),
85             region, topIndicator, bottomIndicator, topAnchor, bottomAnchor,
86             topXY, bottomXY, headerCtEl, minX, maxX;
87
88         // Cannot drag beyond non-draggable start column
89         if (!header.draggable &amp;&amp; header.getIndex() == 0) {
90             return false;
91         }
92
93         this.lastLocation = location;
94
95         if ((draggedHeader !== header) &amp;&amp;
96             ((pos === &quot;before&quot; &amp;&amp; nextHd !== header) ||
97             (pos === &quot;after&quot; &amp;&amp; prevHd !== header)) &amp;&amp;
98             !header.isDescendantOf(draggedHeader)) {
99
100             // As we move in between different DropZones that are in the same
101             // group (such as the case when in a locked grid), invalidateDrop
102             // on the other dropZones.
103             var allDropZones = Ext.dd.DragDropManager.getRelated(this),
104                 ln = allDropZones.length,
105                 i  = 0,
106                 dropZone;
107
108             for (; i &lt; ln; i++) {
109                 dropZone = allDropZones[i];
110                 if (dropZone !== this &amp;&amp; dropZone.invalidateDrop) {
111                     dropZone.invalidateDrop();
112                 }
113             }
114
115
116             this.valid = true;
117             topIndicator = this.getTopIndicator();
118             bottomIndicator = this.getBottomIndicator();
119             if (pos === 'before') {
120                 topAnchor = 'tl';
121                 bottomAnchor = 'bl';
122             } else {
123                 topAnchor = 'tr';
124                 bottomAnchor = 'br';
125             }
126             topXY = header.el.getAnchorXY(topAnchor);
127             bottomXY = header.el.getAnchorXY(bottomAnchor);
128
129             // constrain the indicators to the viewable section
130             headerCtEl = this.headerCt.el;
131             minX = headerCtEl.getLeft();
132             maxX = headerCtEl.getRight();
133
134             topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX);
135             bottomXY[0] = Ext.Number.constrain(bottomXY[0], minX, maxX);
136
137             // adjust by offsets, this is to center the arrows so that they point
138             // at the split point
139             topXY[0] -= 4;
140             topXY[1] -= 9;
141             bottomXY[0] -= 4;
142
143             // position and show indicators
144             topIndicator.setXY(topXY);
145             bottomIndicator.setXY(bottomXY);
146             topIndicator.show();
147             bottomIndicator.show();
148         // invalidate drop operation and hide indicators
149         } else {
150             this.invalidateDrop();
151         }
152     },
153
154     invalidateDrop: function() {
155         this.valid = false;
156         this.hideIndicators();
157     },
158
159     onNodeOver: function(node, dragZone, e, data) {
160         if (data.header.el.dom !== node) {
161             this.positionIndicator(data.header, node, e);
162         }
163         return this.valid ? this.dropAllowed : this.dropNotAllowed;
164     },
165
166     hideIndicators: function() {
167         this.getTopIndicator().hide();
168         this.getBottomIndicator().hide();
169     },
170
171     onNodeOut: function() {
172         this.hideIndicators();
173     },
174
175     onNodeDrop: function(node, dragZone, e, data) {
176         if (this.valid) {
177             this.invalidateDrop();
178             var hd = data.header,
179                 lastLocation = this.lastLocation,
180                 fromCt  = hd.ownerCt,
181                 fromIdx = fromCt.items.indexOf(hd), // Container.items is a MixedCollection
182                 toCt    = lastLocation.header.ownerCt,
183                 toIdx   = toCt.items.indexOf(lastLocation.header),
184                 headerCt = this.headerCt,
185                 groupCt,
186                 scrollerOwner;
187
188             if (lastLocation.pos === 'after') {
189                 toIdx++;
190             }
191
192             // If we are dragging in between two HeaderContainers that have had the lockable
193             // mixin injected we will lock/unlock headers in between sections. Note that lockable
194             // does NOT currently support grouped headers.
195             if (fromCt !== toCt &amp;&amp; fromCt.lockableInjected &amp;&amp; toCt.lockableInjected &amp;&amp; toCt.lockedCt) {
196                 scrollerOwner = fromCt.up('[scrollerOwner]');
197                 scrollerOwner.lock(hd, toIdx);
198             } else if (fromCt !== toCt &amp;&amp; fromCt.lockableInjected &amp;&amp; toCt.lockableInjected &amp;&amp; fromCt.lockedCt) {
199                 scrollerOwner = fromCt.up('[scrollerOwner]');
200                 scrollerOwner.unlock(hd, toIdx);
201             } else {
202                 // If dragging rightwards, then after removal, the insertion index will be one less when moving
203                 // in between the same container.
204                 if ((fromCt === toCt) &amp;&amp; (toIdx &gt; fromCt.items.indexOf(hd))) {
205                     toIdx--;
206                 }
207
208                 // Remove dragged header from where it was without destroying it or relaying its Container
209                 if (fromCt !== toCt) {
210                     fromCt.suspendLayout = true;
211                     fromCt.remove(hd, false);
212                     fromCt.suspendLayout = false;
213                 }
214
215                 // Dragged the last header out of the fromCt group... The fromCt group must die
216                 if (fromCt.isGroupHeader) {
217                     if (!fromCt.items.getCount()) {
218                         groupCt = fromCt.ownerCt;
219                         groupCt.suspendLayout = true;
220                         groupCt.remove(fromCt, false);
221                         fromCt.el.dom.parentNode.removeChild(fromCt.el.dom);
222                         groupCt.suspendLayout = false;
223                     } else {
224                         fromCt.minWidth = fromCt.getWidth() - hd.getWidth();
225                         fromCt.setWidth(fromCt.minWidth);
226                     }
227                 }
228
229                 // Move dragged header into its drop position
230                 toCt.suspendLayout = true;
231                 if (fromCt === toCt) {
232                     toCt.move(fromIdx, toIdx);
233                 } else {
234                     toCt.insert(toIdx, hd);
235                 }
236                 toCt.suspendLayout = false;
237
238                 // Group headers acquire the aggregate width of their child headers
239                 // Therefore a child header may not flex; it must contribute a fixed width.
240                 // But we restore the flex value when moving back into the main header container
241                 if (toCt.isGroupHeader) {
242                     hd.savedFlex = hd.flex;
243                     delete hd.flex;
244                     hd.width = hd.getWidth();
245                     // When there was previously a flex, we need to ensure we don't count for the
246                     // border twice.
247                     toCt.minWidth = toCt.getWidth() + hd.getWidth() - (hd.savedFlex ? 1 : 0);
248                     toCt.setWidth(toCt.minWidth);
249                 } else {
250                     if (hd.savedFlex) {
251                         hd.flex = hd.savedFlex;
252                         delete hd.width;
253                     }
254                 }
255
256
257                 // Refresh columns cache in case we remove an emptied group column
258                 headerCt.purgeCache();
259                 headerCt.doLayout();
260                 headerCt.onHeaderMoved(hd, fromIdx, toIdx);
261                 // Emptied group header can only be destroyed after the header and grid have been refreshed
262                 if (!fromCt.items.getCount()) {
263                     fromCt.destroy();
264                 }
265             }
266         }
267     }
268 });
269 </pre>
270 </body>
271 </html>