/**
* @private
*/
Ext.define('Ext.grid.plugin.grouping.DropZone', {
extend: 'Ext.dd.DropZone',
proxyOffsets: [-4, -9],
groupingPanelSelector: '.' + Ext.baseCSSPrefix + 'grid-group-panel-body',
groupColumnSelector: '.' + Ext.baseCSSPrefix + 'grid-group-column',
constructor: function(panel) {
var me = this;
me.panel = panel;
me.ddGroup = me.getDDGroup();
me.autoGroup = true;
me.callParent([panel.el]);
},
destroy: function() {
Ext.destroy(this.topIndicator, this.bottomIndicator);
this.callParent();
},
disable: function() {
this.disabled = true;
},
enable: function() {
this.disabled = false;
},
getDDGroup: function() {
// return the column header dd group so we can allow column
// dropping inside the grouping panel
return 'header-dd-zone-' + this.panel.up('[scrollerOwner]').id;
},
getTargetFromEvent: function(e) {
return e.getTarget(this.groupColumnSelector) || e.getTarget(this.groupingPanelSelector);
},
getTopIndicator: function() {
if (!this.topIndicator) {
this.topIndicator = Ext.getBody().createChild({
role: 'presentation',
cls: Ext.baseCSSPrefix + "col-move-top",
//<debug>
// tell the spec runner to ignore this element when checking if the dom is clean
"data-sticky": true,
//</debug>
html: " "
});
this.indicatorXOffset = Math.floor((this.topIndicator.dom.offsetWidth + 1) / 2);
}
return this.topIndicator;
},
getBottomIndicator: function() {
if (!this.bottomIndicator) {
this.bottomIndicator = Ext.getBody().createChild({
role: 'presentation',
cls: Ext.baseCSSPrefix + "col-move-bottom",
//<debug>
// tell the spec runner to ignore this element when checking if the dom is clean
"data-sticky": true,
//</debug>
html: " "
});
}
return this.bottomIndicator;
},
getLocation: function(e, t) {
var x = e.getXY()[0],
target = Ext.getCmp(t.id),
region, pos;
if (target.isGroupingPanel && target.items.length) {
region = Ext.fly(target.items.last().el).getRegion();
}
else {
region = Ext.fly(t).getRegion();
}
if ((region.right - x) <= (region.right - region.left) / 2) {
pos = "after";
}
else {
pos = "before";
}
return {
pos: pos,
header: target,
node: t
};
},
positionIndicator: function(data, node, e) {
var me = this,
dragHeader = data.header,
dropLocation = me.getLocation(e, node),
targetHeader = dropLocation.header,
pos = dropLocation.pos,
nextHd, prevHd, topIndicator, bottomIndicator, topAnchor, bottomAnchor,
topXY, bottomXY, headerCtEl, minX, maxX, allDropZones, ln, i, dropZone;
// Avoid expensive CQ lookups and DOM calculations if dropPosition has not changed
if (targetHeader === me.lastTargetHeader && pos === me.lastDropPos) {
return;
}
nextHd = dragHeader.nextSibling('groupingpanelcolumn:not([hidden])');
prevHd = dragHeader.previousSibling('groupingpanelcolumn:not([hidden])');
me.lastTargetHeader = targetHeader;
me.lastDropPos = pos;
data.dropLocation = dropLocation;
if ((dragHeader !== targetHeader) &&
((pos === "before" && nextHd !== targetHeader) ||
(pos === "after" && prevHd !== targetHeader)) &&
!targetHeader.isDescendantOf(dragHeader)) {
// As we move in between different DropZones that are in the same
// group (such as the case when in a locked grid), invalidateDrop
// on the other dropZones.
allDropZones = Ext.dd.DragDropManager.getRelated(me);
ln = allDropZones.length;
i = 0;
for (; i < ln; i++) {
dropZone = allDropZones[i];
if (dropZone !== me && dropZone.invalidateDrop) {
dropZone.invalidateDrop();
}
}
me.valid = true;
topIndicator = me.getTopIndicator();
bottomIndicator = me.getBottomIndicator();
if (pos === 'before') {
topAnchor = 'bc-tl';
bottomAnchor = 'tc-bl';
}
else {
topAnchor = 'bc-tr';
bottomAnchor = 'tc-br';
}
// Calculate arrow positions. Offset them to align exactly with column border line
if (targetHeader.isGroupingPanel && targetHeader.items.length > 0) {
// if dropping zone is the container then align the rows to the last column item
topXY = topIndicator.getAlignToXY(targetHeader.items.last().el, topAnchor);
bottomXY = bottomIndicator.getAlignToXY(targetHeader.items.last().el, bottomAnchor);
}
else {
topXY = topIndicator.getAlignToXY(targetHeader.el, topAnchor);
bottomXY = bottomIndicator.getAlignToXY(targetHeader.el, bottomAnchor);
}
// constrain the indicators to the viewable section
headerCtEl = me.panel.innerCt;
minX = headerCtEl.getX() - me.indicatorXOffset;
maxX = headerCtEl.getX() + headerCtEl.getWidth();
topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX);
bottomXY[0] = Ext.Number.constrain(bottomXY[0], minX, maxX);
// position and show indicators
topIndicator.setXY(topXY);
bottomIndicator.setXY(bottomXY);
topIndicator.show();
bottomIndicator.show();
// invalidate drop operation and hide indicators
}
else {
me.invalidateDrop();
}
},
invalidateDrop: function() {
this.valid = false;
this.hideIndicators();
},
onNodeOver: function(node, dragZone, e, data) {
var me = this,
from = data.groupcol || data.header,
doPosition = true;
if (data.header.el.dom === node) {
doPosition = false;
}
else if (from.isColumn) {
doPosition = from.groupable && me.panel.isNewColumn(from);
}
if (doPosition) {
me.positionIndicator(data, node, e);
}
else {
me.valid = false;
}
return me.valid ? me.dropAllowed : me.dropNotAllowed;
},
hideIndicators: function() {
var me = this;
me.getTopIndicator().hide();
me.getBottomIndicator().hide();
me.lastTargetHeader = me.lastDropPos = null;
},
onNodeOut: function() {
this.hideIndicators();
},
onNodeDrop: function(node, dragZone, e, data) {
var me = this,
dragColumn = data.groupcol || data.header,
dropLocation = data.dropLocation,
pos, grouper;
if (me.valid && dropLocation) {
/*
there are 2 possibilities here:
1. a new grid column should be added to the grouping panel
2. an existing group column changes its position
*/
me.invalidateDrop();
if (dragColumn.isColumn) {
Ext.suspendLayouts();
// don't hide this if it's the last column
if (dragColumn.up('gridpanel').headerCt.getVisibleGridColumns().length > 1) {
dragColumn.setVisible(false);
}
pos = me.panel.getColumnPosition(dropLocation.header, dropLocation.pos);
grouper = dragColumn.getGrouper();
if (!grouper) {
grouper = new Ext.util.Grouper({
property: dragColumn.displayField || dragColumn.dataIndex,
direction: dragColumn.sortState || 'ASC',
formatter: dragColumn.groupFormatter
});
}
me.panel.addColumn({
header: dragColumn.text,
idColumn: dragColumn.id,
grouper: grouper,
column: dragColumn
}, pos, true);
Ext.resumeLayouts(true);
}
else if (dragColumn.isGroupingPanelColumn) {
// 2nd possibility
me.panel.moveColumn(dragColumn, dropLocation.header.isGroupingPanel
? dropLocation.header.items.last()
: dropLocation.header, dropLocation.pos);
}
}
}
});