4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-view-DropZone'>/**
19 </span> * @class Ext.view.DropZone
20 * @extends Ext.dd.DropZone
23 Ext.define('Ext.view.DropZone', {
24 extend: 'Ext.dd.DropZone',
26 indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
27 indicatorCls: 'x-grid-drop-indicator',
29 constructor: function(config) {
31 Ext.apply(me, config);
33 // Create a ddGroup unless one has been configured.
34 // User configuration of ddGroups allows users to specify which
35 // DD instances can interact with each other. Using one
36 // based on the id of the View would isolate it and mean it can only
37 // interact with a DragZone on the same View also using a generated ID.
39 me.ddGroup = 'view-dd-zone-' + me.view.id;
42 // The DropZone's encapsulating element is the View's main element. It must be this because drop gestures
43 // may require scrolling on hover near a scrolling boundary. In Ext 4.x two DD instances may not use the
44 // same element, so a DragZone on this same View must use the View's parent element as its element.
45 me.callParent([me.view.el]);
48 // Fire an event through the client DataView. Lock this DropZone during the event processing so that
49 // its data does not become corrupted by processing mouse events.
50 fireViewEvent: function() {
55 result = me.view.fireEvent.apply(me.view, arguments);
60 getTargetFromEvent : function(e) {
61 var node = e.getTarget(this.view.getItemSelector()),
62 mouseY, nodeList, testNode, i, len, box;
64 // Not over a row node: The content may be narrower than the View's encapsulating element, so return the closest.
65 // If we fall through because the mouse is below the nodes (or there are no nodes), we'll get an onContainerOver call.
67 mouseY = e.getPageY();
68 for (i = 0, nodeList = this.view.getNodes(), len = nodeList.length; i < len; i++) {
69 testNode = nodeList[i];
70 box = Ext.fly(testNode).getBox();
71 if (mouseY <= box.bottom) {
79 getIndicator: function() {
83 me.indicator = Ext.createWidget('component', {
84 html: me.indicatorHtml,
94 getPosition: function(e, node) {
96 region = Ext.fly(node).getRegion(),
99 if ((region.bottom - y) >= (region.bottom - region.top) / 2) {
100 pos = "before";
102 pos = "after";
107 <span id='Ext-view-DropZone-method-containsRecordAtOffset'> /**
108 </span> * @private Determines whether the record at the specified offset from the passed record
109 * is in the drag payload.
113 * @returns {Boolean} True if the targeted record is in the drag payload
115 containsRecordAtOffset: function(records, record, offset) {
119 var view = this.view,
120 recordIndex = view.indexOf(record),
121 nodeBefore = view.getNode(recordIndex + offset),
122 recordBefore = nodeBefore ? view.getRecord(nodeBefore) : null;
124 return recordBefore && Ext.Array.contains(records, recordBefore);
127 positionIndicator: function(node, data, e) {
130 pos = me.getPosition(e, node),
131 overRecord = view.getRecord(node),
132 draggingRecords = data.records,
133 indicator, indicatorY;
135 if (!Ext.Array.contains(draggingRecords, overRecord) && (
136 pos == 'before' && !me.containsRecordAtOffset(draggingRecords, overRecord, -1) ||
137 pos == 'after' && !me.containsRecordAtOffset(draggingRecords, overRecord, 1)
141 if (me.overRecord != overRecord || me.currentPosition != pos) {
143 indicatorY = Ext.fly(node).getY() - view.el.getY() - 1;
144 if (pos == 'after') {
145 indicatorY += Ext.fly(node).getHeight();
147 me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, indicatorY);
149 // Cache the overRecord and the 'before' or 'after' indicator.
150 me.overRecord = overRecord;
151 me.currentPosition = pos;
158 invalidateDrop: function() {
161 this.getIndicator().hide();
165 // The mouse is over a View node
166 onNodeOver: function(node, dragZone, e, data) {
169 if (!Ext.Array.contains(data.records, me.view.getRecord(node))) {
170 me.positionIndicator(node, data, e);
172 return me.valid ? me.dropAllowed : me.dropNotAllowed;
175 // Moved out of the DropZone without dropping.
176 // Remove drop position indicator
177 notifyOut: function(node, dragZone, e, data) {
180 me.callParent(arguments);
181 delete me.overRecord;
182 delete me.currentPosition;
188 // The mouse is past the end of all nodes (or there are no nodes)
189 onContainerOver : function(dd, e, data) {
192 count = view.store.getCount();
194 // There are records, so position after the last one
196 me.positionIndicator(view.getNode(count - 1), data, e);
199 // No records, position the indicator at the top
201 delete me.overRecord;
202 delete me.currentPosition;
203 me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, 0);
206 return me.dropAllowed;
209 onContainerDrop : function(dd, e, data) {
210 return this.onNodeDrop(dd, null, e, data);
213 onNodeDrop: function(node, dragZone, e, data) {
217 // Create a closure to perform the operation which the event handler may use.
218 // Users may now return <code>false</code> from the beforedrop handler, and perform any kind
219 // of asynchronous processing such as an Ext.Msg.confirm, or an Ajax request,
220 // and complete the drop gesture at some point in the future by calling this function.
221 processDrop = function () {
223 me.handleNodeDrop(data, me.overRecord, me.currentPosition);
225 me.fireViewEvent('drop', node, data, me.overRecord, me.currentPosition);
227 performOperation = false;
230 performOperation = me.fireViewEvent('beforedrop', node, data, me.overRecord, me.currentPosition, processDrop);
231 if (performOperation !== false) {
232 // If the processDrop function was called in the event handler, do not do it again.
238 return performOperation;
242 Ext.destroy(this.indicator);
243 delete this.indicator;