3 // A DropZone which cooperates with DragZones whose dragData contains
4 // a "field" property representing a form Field. Fields may be dropped onto
5 // grid data cells containing a matching data type.
6 Ext.define('Ext.ux.CellFieldDropZone', {
7 extend: 'Ext.dd.DropZone',
9 constructor: function(){},
11 // Call the DropZone constructor using the View's scrolling element
12 // only after the grid has been rendered.
13 init: function(grid) {
21 Ext.ux.CellFieldDropZone.superclass.constructor.call(me, me.view.el);
26 grid.on('render', me.init, me, {single: true});
30 // Scroll the main configured Element when we drag close to the edge
31 containerScroll: true,
33 getTargetFromEvent: function(e) {
37 // Ascertain whether the mousemove is within a grid cell
38 var cell = e.getTarget(v.cellSelector);
41 // We *are* within a grid cell, so ask the View exactly which one,
42 // Extract data from the Model to create a target object for
43 // processing in subsequent onNodeXXXX methods. Note that the target does
44 // not have to be a DOM element. It can be whatever the noNodeXXX methods are
45 // programmed to expect.
46 var row = v.findItemByChild(cell),
47 columnIndex = cell.cellIndex;
49 if (row && Ext.isDefined(columnIndex)) {
52 record: v.getRecord(row),
53 fieldName: me.grid.columns[columnIndex].dataIndex
59 // On Node enter, see if it is valid for us to drop the field on that type of column.
60 onNodeEnter: function(target, dd, e, dragData) {
66 // Check that a field is being dragged.
67 var f = dragData.field;
72 // Check whether the data type of the column being dropped on accepts the
73 // dragged field type. If so, set dropOK flag, and highlight the target node.
74 var type = target.record.fields.get(target.fieldName).type,
75 types = Ext.data.Types;
79 if (!f.isXType('numberfield')) {
84 if (!f.isXType('datefield')) {
89 if (!f.isXType('checkbox')) {
94 Ext.fly(target.node).addCls('x-drop-target-active');
97 // Return the class name to add to the drag proxy. This provides a visual indication
98 // of drop allowed or not allowed.
99 onNodeOver: function(target, dd, e, dragData) {
100 return this.dropOK ? this.dropAllowed : this.dropNotAllowed;
103 // highlight the target node.
104 onNodeOut: function(target, dd, e, dragData) {
105 Ext.fly(target.node).removeCls('x-drop-target-active');
108 // Process the drop event if we have previously ascertained that a drop is OK.
109 onNodeDrop: function(target, dd, e, dragData) {
111 target.record.set(target.fieldName, dragData.field.getValue());
117 // A class which makes Fields within a Panel draggable.
118 // the dragData delivered to a cooperating DropZone's methods contains
119 // the dragged Field in the property "field".
120 Ext.define('Ext.ux.PanelFieldDragZone', {
122 extend: 'Ext.dd.DragZone',
124 constructor: function(){},
126 // Call the DRagZone's constructor. The Panel must have been rendered.
127 init: function(panel) {
128 if (panel.nodeType) {
129 Ext.ux.PanelFieldDragZone.superclass.init.apply(this, arguments);
131 if (panel.rendered) {
132 Ext.ux.PanelFieldDragZone.superclass.constructor.call(this, panel.getEl());
133 var i = Ext.fly(panel.getEl()).select('input');
136 panel.on('afterlayout', this.init, this, {single: true});
143 // On mousedown, we ascertain whether it is on one of our draggable Fields.
144 // If so, we collect data about the draggable object, and return a drag data
145 // object which contains our own data, plus a "ddel" property which is a DOM
146 // node which provides a "view" of the dragged data.
147 getDragData: function(e) {
148 var t = e.getTarget('input');
152 // Ugly code to "detach" the drag gesture from the input field.
153 // Without this, Opera never changes the mouseover target from the input field
154 // even when dragging outside of the field - it just keeps selecting.
156 Ext.fly(t).on('mousemove', function(e1){
157 t.style.visibility = 'hidden';
158 Ext.defer(function(){
159 t.style.visibility = '';
161 }, null, {single:true});
164 // Get the data we are dragging: the Field
165 // create a ddel for the drag proxy to display
166 var f = Ext.ComponentQuery.query('field[inputEl]{inputEl.id=="' + t.id + '"}')[0];
167 var d = document.createElement('div');
168 d.className = 'x-form-text';
169 d.appendChild(document.createTextNode(t.value));
170 Ext.fly(d).setWidth(f.getEl().getWidth());
178 // The coordinates to slide the drag proxy back to on failed drop.
179 getRepairXY: function() {
180 return this.dragData.field.getEl().getXY();
184 Ext.onReady(function(){
187 ['3m Co',71.72,0.02,0.03,'9/1 12:00am'],
188 ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'],
189 ['Altria Group Inc',83.81,0.28,0.34,'9/1 12:00am'],
190 ['American Express Company',52.55,0.01,0.02,'9/1 12:00am'],
191 ['American International Group, Inc.',64.13,0.31,0.49,'9/1 12:00am'],
192 ['AT&T Inc.',31.61,-0.48,-1.54,'9/1 12:00am'],
193 ['Boeing Co.',75.43,0.53,0.71,'9/1 12:00am'],
194 ['Caterpillar Inc.',67.27,0.92,1.39,'9/1 12:00am'],
195 ['Citigroup, Inc.',49.37,0.02,0.04,'9/1 12:00am'],
196 ['E.I. du Pont de Nemours and Company',40.48,0.51,1.28,'9/1 12:00am'],
197 ['Exxon Mobil Corp',68.1,-0.43,-0.64,'9/1 12:00am'],
198 ['General Electric Company',34.14,-0.08,-0.23,'9/1 12:00am'],
199 ['General Motors Corporation',30.27,1.09,3.74,'9/1 12:00am'],
200 ['Hewlett-Packard Co.',36.53,-0.03,-0.08,'9/1 12:00am'],
201 ['Honeywell Intl Inc',38.77,0.05,0.13,'9/1 12:00am'],
202 ['Intel Corporation',19.88,0.31,1.58,'9/1 12:00am'],
203 ['International Business Machines',81.41,0.44,0.54,'9/1 12:00am'],
204 ['Johnson & Johnson',64.72,0.06,0.09,'9/1 12:00am'],
205 ['JP Morgan & Chase & Co',45.73,0.07,0.15,'9/1 12:00am'],
206 ['McDonald\'s Corporation',36.76,0.86,2.40,'9/1 12:00am'],
207 ['Merck & Co., Inc.',40.96,0.41,1.01,'9/1 12:00am'],
208 ['Microsoft Corporation',25.84,0.14,0.54,'9/1 12:00am'],
209 ['Pfizer Inc',27.96,0.4,1.45,'9/1 12:00am'],
210 ['The Coca-Cola Company',45.07,0.26,0.58,'9/1 12:00am'],
211 ['The Home Depot, Inc.',34.64,0.35,1.02,'9/1 12:00am'],
212 ['The Procter & Gamble Company',61.91,0.01,0.02,'9/1 12:00am'],
213 ['United Technologies Corporation',63.26,0.55,0.88,'9/1 12:00am'],
214 ['Verizon Communications',35.57,0.39,1.11,'9/1 12:00am'],
215 ['Wal-Mart Stores, Inc.',45.45,0.73,1.63,'9/1 12:00am']
218 // example of custom renderer function
219 function change(val){
221 return '<span style="color:green;">' + val + '</span>';
223 return '<span style="color:red;">' + val + '</span>';
228 // example of custom renderer function
229 function pctChange(val){
231 return '<span style="color:green;">' + val + '%</span>';
233 return '<span style="color:red;">' + val + '%</span>';
238 // create the data store
239 var store = Ext.create('Ext.data.ArrayStore', {
242 {name: 'price', type: 'float'},
243 {name: 'change', type: 'float'},
244 {name: 'pctChange', type: 'float'},
245 {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
250 var helpWindow = Ext.create('Ext.Window', {
251 title: 'Source code',
262 render: function(w) {
264 url: 'field-to-grid-dd.js',
265 success: function(r) {
266 w.items.first().setValue(r.responseText);
274 var grid = Ext.create('Ext.grid.Panel', {
277 {id:'company',header: "Company", width: 160, sortable: true, dataIndex: 'company'},
278 {header: "Price", width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'},
279 {header: "Change", width: 75, sortable: true, renderer: change, dataIndex: 'change'},
280 {header: "% Change", width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'},
281 {header: "Last Updated", width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
283 plugins: Ext.create('Ext.ux.CellFieldDropZone'),
285 autoExpandColumn: 'company',
294 handler: function() {
301 grid.render('grid-example');
303 var f = Ext.create('Ext.Panel', {
306 plugins: Ext.create('Ext.ux.PanelFieldDragZone'),
310 fieldLabel: 'Drag this text',
313 xtype: 'numberfield',
314 fieldLabel: 'Drag this number',
318 fieldLabel: 'Drag this date',
321 renderTo: Ext.getBody()