2 * @class Ext.grid.header.DropZone
3 * @extends Ext.dd.DropZone
6 Ext.define('Ext.grid.header.DropZone', {
7 extend: 'Ext.dd.DropZone',
8 colHeaderCls: Ext.baseCSSPrefix + 'column-header',
9 proxyOffsets: [-4, -9],
11 constructor: function(headerCt){
12 this.headerCt = headerCt;
13 this.ddGroup = this.getDDGroup();
14 this.callParent([headerCt.el]);
17 getDDGroup: function() {
18 return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
21 getTargetFromEvent : function(e){
22 return e.getTarget('.' + this.colHeaderCls);
25 getTopIndicator: function() {
26 if (!this.topIndicator) {
27 this.topIndicator = Ext.core.DomHelper.append(Ext.getBody(), {
32 return this.topIndicator;
35 getBottomIndicator: function() {
36 if (!this.bottomIndicator) {
37 this.bottomIndicator = Ext.core.DomHelper.append(Ext.getBody(), {
38 cls: "col-move-bottom",
42 return this.bottomIndicator;
45 getLocation: function(e, t) {
47 region = Ext.fly(t).getRegion(),
50 if ((region.right - x) <= (region.right - region.left) / 2) {
57 header: Ext.getCmp(t.id),
62 positionIndicator: function(draggedHeader, node, e){
63 var location = this.getLocation(e, node),
64 header = location.header,
66 nextHd = draggedHeader.nextSibling('gridcolumn:not([hidden])'),
67 prevHd = draggedHeader.previousSibling('gridcolumn:not([hidden])'),
68 region, topIndicator, bottomIndicator, topAnchor, bottomAnchor,
69 topXY, bottomXY, headerCtEl, minX, maxX;
71 // Cannot drag beyond non-draggable start column
72 if (!header.draggable && header.getIndex() == 0) {
76 this.lastLocation = location;
78 if ((draggedHeader !== header) &&
79 ((pos === "before" && nextHd !== header) ||
80 (pos === "after" && prevHd !== header)) &&
81 !header.isDescendantOf(draggedHeader)) {
83 // As we move in between different DropZones that are in the same
84 // group (such as the case when in a locked grid), invalidateDrop
85 // on the other dropZones.
86 var allDropZones = Ext.dd.DragDropManager.getRelated(this),
87 ln = allDropZones.length,
92 dropZone = allDropZones[i];
93 if (dropZone !== this && dropZone.invalidateDrop) {
94 dropZone.invalidateDrop();
100 topIndicator = this.getTopIndicator();
101 bottomIndicator = this.getBottomIndicator();
102 if (pos === 'before') {
109 topXY = header.el.getAnchorXY(topAnchor);
110 bottomXY = header.el.getAnchorXY(bottomAnchor);
112 // constrain the indicators to the viewable section
113 headerCtEl = this.headerCt.el;
114 minX = headerCtEl.getLeft();
115 maxX = headerCtEl.getRight();
117 topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX);
118 bottomXY[0] = Ext.Number.constrain(bottomXY[0], minX, maxX);
120 // adjust by offsets, this is to center the arrows so that they point
121 // at the split point
126 // position and show indicators
127 topIndicator.setXY(topXY);
128 bottomIndicator.setXY(bottomXY);
130 bottomIndicator.show();
131 // invalidate drop operation and hide indicators
133 this.invalidateDrop();
137 invalidateDrop: function() {
139 this.hideIndicators();
142 onNodeOver: function(node, dragZone, e, data) {
143 if (data.header.el.dom !== node) {
144 this.positionIndicator(data.header, node, e);
146 return this.valid ? this.dropAllowed : this.dropNotAllowed;
149 hideIndicators: function() {
150 this.getTopIndicator().hide();
151 this.getBottomIndicator().hide();
154 onNodeOut: function() {
155 this.hideIndicators();
158 onNodeDrop: function(node, dragZone, e, data) {
160 this.invalidateDrop();
161 var hd = data.header,
162 lastLocation = this.lastLocation,
164 fromIdx = fromCt.items.indexOf(hd), // Container.items is a MixedCollection
165 toCt = lastLocation.header.ownerCt,
166 toIdx = toCt.items.indexOf(lastLocation.header),
167 headerCt = this.headerCt,
171 if (lastLocation.pos === 'after') {
175 // If we are dragging in between two HeaderContainers that have had the lockable
176 // mixin injected we will lock/unlock headers in between sections. Note that lockable
177 // does NOT currently support grouped headers.
178 if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && toCt.lockedCt) {
179 scrollerOwner = fromCt.up('[scrollerOwner]');
180 scrollerOwner.lock(hd, toIdx);
181 } else if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && fromCt.lockedCt) {
182 scrollerOwner = fromCt.up('[scrollerOwner]');
183 scrollerOwner.unlock(hd, toIdx);
185 // If dragging rightwards, then after removal, the insertion index will be one less when moving
186 // in between the same container.
187 if ((fromCt === toCt) && (toIdx > fromCt.items.indexOf(hd))) {
191 // Remove dragged header from where it was without destroying it or relaying its Container
192 if (fromCt !== toCt) {
193 fromCt.suspendLayout = true;
194 fromCt.remove(hd, false);
195 fromCt.suspendLayout = false;
198 // Dragged the last header out of the fromCt group... The fromCt group must die
199 if (fromCt.isGroupHeader) {
200 if (!fromCt.items.getCount()) {
201 groupCt = fromCt.ownerCt;
202 groupCt.suspendLayout = true;
203 groupCt.remove(fromCt, false);
204 fromCt.el.dom.parentNode.removeChild(fromCt.el.dom);
205 groupCt.suspendLayout = false;
207 fromCt.minWidth = fromCt.getWidth() - hd.getWidth();
208 fromCt.setWidth(fromCt.minWidth);
212 // Move dragged header into its drop position
213 toCt.suspendLayout = true;
214 if (fromCt === toCt) {
215 toCt.move(fromIdx, toIdx);
217 toCt.insert(toIdx, hd);
219 toCt.suspendLayout = false;
221 // Group headers acquire the aggregate width of their child headers
222 // Therefore a child header may not flex; it must contribute a fixed width.
223 // But we restore the flex value when moving back into the main header container
224 if (toCt.isGroupHeader) {
225 hd.savedFlex = hd.flex;
227 hd.width = hd.getWidth();
228 // When there was previously a flex, we need to ensure we don't count for the
230 toCt.minWidth = toCt.getWidth() + hd.getWidth() - (hd.savedFlex ? 1 : 0);
231 toCt.setWidth(toCt.minWidth);
234 hd.flex = hd.savedFlex;
240 // Refresh columns cache in case we remove an emptied group column
241 headerCt.purgeCache();
243 headerCt.onHeaderMoved(hd, fromIdx, toIdx);
244 // Emptied group header can only be destroyed after the header and grid have been refreshed
245 if (!fromCt.items.getCount()) {