/** * @private */Ext.define('Ext.grid.plugin.grouping.DropZone', { extend: 'Ext.drag.Target', groups: 'gridgrouping', upIndicatorCls: Ext.baseCSSPrefix + 'grid-drag-up-indicator', downIndicatorCls: Ext.baseCSSPrefix + 'grid-drag-down-indicator', columnCls: Ext.baseCSSPrefix + 'grid-group-column', // panelCls: Ext.baseCSSPrefix + 'grid-group-panel-body', panelCls: Ext.baseCSSPrefix + 'panel-body-wrap-el', constructor: function(panel) { var me = this; me.columnSelector = '.' + me.columnCls; me.panelSelector = '.' + me.panelCls; me.panel = panel; me.callParent([{ element: panel.element }]); }, destroy: function() { var me = this; Ext.destroy(me.upIndicator, me.downIndicator); me.callParent(); }, getUpIndicator: function() { var me = this; if (!me.upIndicator) { me.upIndicator = Ext.getBody().createChild({ cls: me.upIndicatorCls, html: " " }); // eslint-disable-next-line max-len me.self.prototype.indicatorOffset = Math.floor((me.upIndicator.dom.offsetWidth + 1) / 2); } return me.upIndicator; }, getDownIndicator: function() { var me = this; if (!me.downIndicator) { me.downIndicator = Ext.getBody().createChild({ cls: me.downIndicatorCls, html: " " }); } return me.downIndicator; }, accepts: function(info) { var column = info.data.column; if (!column) { return true; } return column.isGroupingPanelColumn || (column.isGridColumn && column.getGroupable()); }, onDragMove: function(info) { if (info.valid) { this.positionIndicator(info); } else { this.hideIndicators(); } }, onDragLeave: function(info) { this.hideIndicators(); }, onDrop: function(info) { var data = info.data, column = data.column, source = data.sourcePanel, index = data.index, panel = this.panel; this.hideIndicators(); if (!panel) { return; } panel.dragDropColumn(source, column, index); }, getLocationPosition: function(x, target) { var pos = 'after', region = target && target.element.getRegion(); if (region) { if ((region.right - x) <= (region.right - region.left) / 2) { pos = 'after'; } else { pos = 'before'; } } return pos; }, positionIndicator: function(info) { var me = this, items = me.panel.getItems(), upIndicator = me.getUpIndicator(), downIndicator = me.getDownIndicator(), indOffset = me.indicatorOffset, index = -1, el, item, topXY, downXY, minX, maxX, topAnchor, downAnchor, pos; el = me.getCursorElement(info, me.columnCls, me.columnSelector); if (el) { item = el.component; } else { item = items.last(); if (item) { el = item.element; } else { el = me.getCursorElement(info, me.panelCls, me.panelSelector); index = 0; } } if (!el) { el = me.panel.bodyWrapElement; } if (items.length === 0) { pos = 'before'; } else { pos = me.getLocationPosition(info.cursor.current.x, item); } if (pos === 'before') { topAnchor = 'bc-tl'; downAnchor = 'tc-bl'; } else { topAnchor = 'bc-tr'; downAnchor = 'tc-br'; } topXY = upIndicator.getAlignToXY(el, topAnchor); downXY = downIndicator.getAlignToXY(el, downAnchor); minX = el.getX() - indOffset; maxX = el.getX() + el.getWidth(); topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX); downXY[0] = Ext.Number.constrain(downXY[0], minX, maxX); upIndicator.show(); downIndicator.show(); upIndicator.setXY(topXY); downIndicator.setXY(downXY); if (index < 0) { index = me.findNewIndex(item, pos, info); } info.setData('position', pos); info.setData('index', Ext.Number.constrain(index, 0, items.length)); }, findNewIndex: function(overItem, pos, info) { var items = this.panel.getItems(), index = items.indexOf(overItem); if (overItem !== info.data.column) { if (pos === 'after') { index++; } else if (index !== items.length - 1) { index--; } } return index; }, hideIndicators: function() { this.getUpIndicator().hide(); this.getDownIndicator().hide(); }, /** * Find the element that matches the cursor position and selector. * * @param info * @param {String} cls The class used in the selector * @param {String} selector The simple selector to test. See {@link Ext.dom.Query} * for information about simple selectors. * @param {Number/String/HTMLElement/Ext.dom.Element} [limit] * The max depth to search as a number or an element that causes the upward * traversal to stop and is **not** considered for inclusion as the result. * (defaults to 50 || document.documentElement) * @param {Boolean} [returnDom=false] True to return the DOM node instead of Ext.dom.Element * @return {Ext.dom.Element/HTMLElement} The matching DOM node (or HTMLElement if * _returnDom_ is _true_). Or null if no match was found. */ getCursorElement: function(info, cls, selector, limit, returnDom) { var pos = info.cursor.current, elPoint = Ext.drag.Manager.elementFromPoint(pos.x, pos.y), el = Ext.fly(elPoint); return el && el.hasCls(cls) ? el : (el && el.up(selector, limit, returnDom)); }});