]> git.proxmox.com Git - extjs.git/blob - extjs/packages/ux/classic/src/DataView/Draggable.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / ux / classic / src / DataView / Draggable.js
1 /**
2 * ## Basic DataView with Draggable mixin.
3 *
4 * Ext.Loader.setPath('Ext.ux', '../../../SDK/extjs/examples/ux');
5 *
6 * Ext.define('My.cool.View', {
7 * extend: 'Ext.view.View',
8 *
9 * mixins: {
10 * draggable: 'Ext.ux.DataView.Draggable'
11 * },
12 *
13 * initComponent: function() {
14 * this.mixins.draggable.init(this, {
15 * ddConfig: {
16 * ddGroup: 'someGroup'
17 * }
18 * });
19 *
20 * this.callParent(arguments);
21 * }
22 * });
23 *
24 * Ext.onReady(function () {
25 * Ext.create('Ext.data.Store', {
26 * storeId: 'baseball',
27 * fields: ['team', 'established'],
28 * data: [
29 * { team: 'Atlanta Braves', established: '1871' },
30 * { team: 'Miami Marlins', established: '1993' },
31 * { team: 'New York Mets', established: '1962' },
32 * { team: 'Philadelphia Phillies', established: '1883' },
33 * { team: 'Washington Nationals', established: '1969' }
34 * ]
35 * });
36 *
37 * Ext.create('My.cool.View', {
38 * store: Ext.StoreMgr.get('baseball'),
39 * tpl: [
40 * '<tpl for=".">',
41 * '<p class="team">',
42 * 'The {team} were founded in {established}.',
43 * '</p>',
44 * '</tpl>'
45 * ],
46 * itemSelector: 'p.team',
47 * renderTo: Ext.getBody()
48 * });
49 * });
50 */
51 Ext.define('Ext.ux.DataView.Draggable', {
52 requires: 'Ext.dd.DragZone',
53
54 /**
55 * @cfg {String} ghostCls The CSS class added to the outermost element of the created ghost proxy
56 * (defaults to 'x-dataview-draggable-ghost')
57 */
58 ghostCls: 'x-dataview-draggable-ghost',
59
60 /**
61 * @cfg {Ext.XTemplate/Array} ghostTpl The template used in the ghost DataView
62 */
63 ghostTpl: [
64 '<tpl for=".">',
65 '{title}',
66 '</tpl>'
67 ],
68
69 /**
70 * @cfg {Object} ddConfig Config object that is applied to the internally created DragZone
71 */
72
73 /**
74 * @cfg {String} ghostConfig Config object that is used to configure the internally created DataView
75 */
76
77 init: function(dataview, config) {
78 /**
79 * @property dataview
80 * @type Ext.view.View
81 * The Ext.view.View instance that this DragZone is attached to
82 */
83 this.dataview = dataview;
84
85 dataview.on('render', this.onRender, this);
86
87 Ext.apply(this, {
88 itemSelector: dataview.itemSelector,
89 ghostConfig : {}
90 }, config || {});
91
92 Ext.applyIf(this.ghostConfig, {
93 itemSelector: 'img',
94 cls: this.ghostCls,
95 tpl: this.ghostTpl
96 });
97 },
98
99 /**
100 * @private
101 * Called when the attached DataView is rendered. Sets up the internal DragZone
102 */
103 onRender: function() {
104 var config = Ext.apply({}, this.ddConfig || {}, {
105 dvDraggable: this,
106 dataview : this.dataview,
107 getDragData: this.getDragData,
108 getTreeNode: this.getTreeNode,
109 afterRepair: this.afterRepair,
110 getRepairXY: this.getRepairXY
111 });
112
113 /**
114 * @property dragZone
115 * @type Ext.dd.DragZone
116 * The attached DragZone instane
117 */
118 this.dragZone = Ext.create('Ext.dd.DragZone', this.dataview.getEl(), config);
119 },
120
121 getDragData: function(e) {
122 var draggable = this.dvDraggable,
123 dataview = this.dataview,
124 selModel = dataview.getSelectionModel(),
125 target = e.getTarget(draggable.itemSelector),
126 selected, dragData;
127
128 if (target) {
129 if (!dataview.isSelected(target)) {
130 selModel.select(dataview.getRecord(target));
131 }
132
133 selected = dataview.getSelectedNodes();
134 dragData = {
135 copy: true,
136 nodes: selected,
137 records: selModel.getSelection(),
138 item: true
139 };
140
141 if (selected.length === 1) {
142 dragData.single = true;
143 dragData.ddel = target;
144 } else {
145 dragData.multi = true;
146 dragData.ddel = draggable.prepareGhost(selModel.getSelection());
147 }
148
149 return dragData;
150 }
151
152 return false;
153 },
154
155 getTreeNode: function() {
156 // console.log('test');
157 },
158
159 afterRepair: function() {
160 this.dragging = false;
161
162 var nodes = this.dragData.nodes,
163 length = nodes.length,
164 i;
165
166 //FIXME: Ext.fly does not work here for some reason, only frames the last node
167 for (i = 0; i < length; i++) {
168 Ext.get(nodes[i]).frame('#8db2e3', 1);
169 }
170 },
171
172 /**
173 * @private
174 * Returns the x and y co-ordinates that the dragged item should be animated back to if it was dropped on an
175 * invalid drop target. If we're dragging more than one item we don't animate back and just allow afterRepair
176 * to frame each dropped item.
177 */
178 getRepairXY: function(e) {
179 if (this.dragData.multi) {
180 return false;
181 } else {
182 var repairEl = Ext.get(this.dragData.ddel),
183 repairXY = repairEl.getXY();
184
185 //take the item's margins and padding into account to make the repair animation line up perfectly
186 repairXY[0] += repairEl.getPadding('t') + repairEl.getMargin('t');
187 repairXY[1] += repairEl.getPadding('l') + repairEl.getMargin('l');
188
189 return repairXY;
190 }
191 },
192
193 /**
194 * Updates the internal ghost DataView by ensuring it is rendered and contains the correct records
195 * @param {Array} records The set of records that is currently selected in the parent DataView
196 * @return {HTMLElement} The Ghost DataView's encapsulating HTMLElement.
197 */
198 prepareGhost: function(records) {
199 return this.createGhost(records).getEl().dom;
200 },
201
202 /**
203 * @private
204 * Creates the 'ghost' DataView that follows the mouse cursor during the drag operation. This div is usually a
205 * lighter-weight representation of just the nodes that are selected in the parent DataView.
206 */
207 createGhost: function(records) {
208 var me = this,
209 store;
210
211 if (me.ghost) {
212 (store = me.ghost.store).loadRecords(records);
213 } else {
214 store = Ext.create('Ext.data.Store', {
215 model: records[0].self
216 });
217
218 store.loadRecords(records);
219 me.ghost = Ext.create('Ext.view.View', Ext.apply({
220 renderTo: document.createElement('div'),
221 store: store
222 }, me.ghostConfig));
223 me.ghost.container.skipGarbageCollection = me.ghost.el.skipGarbageCollection = true;
224 }
225 store.clearData();
226
227 return me.ghost;
228 },
229
230 destroy: function() {
231 var ghost = this.ghost;
232
233 if (ghost) {
234 ghost.container.destroy();
235 ghost.destroy();
236 }
237 this.callParent();
238 }
239 });