Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / dd / field-to-grid-dd.js
1 Ext.require(['*']);
2
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',
8
9     constructor: function(){},
10
11 //  Call the DropZone constructor using the View's scrolling element
12 //  only after the grid has been rendered.
13     init: function(grid) {
14         var me = this;
15
16         if (grid.rendered) {
17             me.grid = grid;
18             grid.getView().on({
19                 render: function(v) {
20                     me.view = v;
21                     Ext.ux.CellFieldDropZone.superclass.constructor.call(me, me.view.el);
22                 },
23                 single: true
24             });
25         } else {
26             grid.on('render', me.init, me, {single: true});
27         }
28     },
29
30 //  Scroll the main configured Element when we drag close to the edge
31     containerScroll: true,
32
33     getTargetFromEvent: function(e) {
34         var me = this,
35             v = me.view;
36
37 //      Ascertain whether the mousemove is within a grid cell
38         var cell = e.getTarget(v.cellSelector);
39         if (cell) {
40
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;
48
49             if (row && Ext.isDefined(columnIndex)) {
50                 return {
51                     node: cell,
52                     record: v.getRecord(row),
53                     fieldName: me.grid.columns[columnIndex].dataIndex
54                 };
55             }
56         }
57     },
58
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) {
61         delete this.dropOK;
62         if (!target) {
63             return;
64         }
65
66 //      Check that a field is being dragged.
67         var f = dragData.field;
68         if (!f) {
69             return;
70         }
71
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;
76         switch(type){
77             case types.FLOAT:
78             case types.INT:
79                 if (!f.isXType('numberfield')) {
80                     return;
81                 }
82                 break;
83             case types.DATE:
84                 if (!f.isXType('datefield')) {
85                     return;
86                 }
87                 break;
88             case types.BOOL:
89                 if (!f.isXType('checkbox')) {
90                     return;
91                 }
92         }
93         this.dropOK = true;
94         Ext.fly(target.node).addCls('x-drop-target-active');
95     },
96
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;
101     },
102
103 //  highlight the target node.
104     onNodeOut: function(target, dd, e, dragData) {
105         Ext.fly(target.node).removeCls('x-drop-target-active');
106     },
107
108 //  Process the drop event if we have previously ascertained that a drop is OK.
109     onNodeDrop: function(target, dd, e, dragData) {
110         if (this.dropOK) {
111             target.record.set(target.fieldName, dragData.field.getValue());
112             return true;
113         }
114     }
115 });
116
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', {
121
122     extend: 'Ext.dd.DragZone',
123
124     constructor: function(){},
125
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);
130         } else {
131             if (panel.rendered) {
132                 Ext.ux.PanelFieldDragZone.superclass.constructor.call(this, panel.getEl());
133                 var i = Ext.fly(panel.getEl()).select('input');
134                 i.unselectable();
135             } else {
136                 panel.on('afterlayout', this.init, this, {single: true});
137             }
138         }
139     },
140
141     scroll: false,
142
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');
149         if (t) {
150             e.stopEvent();
151
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.
155             if (Ext.isOpera) {
156                 Ext.fly(t).on('mousemove', function(e1){
157                     t.style.visibility = 'hidden';
158                     Ext.defer(function(){
159                         t.style.visibility = '';
160                     }, 1);
161                 }, null, {single:true});
162             }
163
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());
171             return {
172                 field: f,
173                 ddel: d
174             };
175         }
176     },
177
178 //  The coordinates to slide the drag proxy back to on failed drop.
179     getRepairXY: function() {
180         return this.dragData.field.getEl().getXY();
181     }
182 });
183
184 Ext.onReady(function(){
185
186     var myData = [
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']
216     ];
217
218     // example of custom renderer function
219     function change(val){
220         if(val > 0){
221             return '<span style="color:green;">' + val + '</span>';
222         }else if(val < 0){
223             return '<span style="color:red;">' + val + '</span>';
224         }
225         return val;
226     }
227
228     // example of custom renderer function
229     function pctChange(val){
230         if(val > 0){
231             return '<span style="color:green;">' + val + '%</span>';
232         }else if(val < 0){
233             return '<span style="color:red;">' + val + '%</span>';
234         }
235         return val;
236     }
237
238     // create the data store
239     var store = Ext.create('Ext.data.ArrayStore', {
240         fields: [
241            {name: 'company'},
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'}
246         ],
247         data: myData
248     });
249
250     var helpWindow = Ext.create('Ext.Window', {
251         title: 'Source code',
252         width: 920,
253         height: 500,
254         closeAction: 'hide',
255         layout: 'fit',
256         items: {
257             hideLabel: true,
258             xtype: 'textarea',
259             readOnly: true
260         },
261         listeners: {
262             render: function(w) {
263                 Ext.Ajax.request({
264                     url: 'field-to-grid-dd.js',
265                     success: function(r) {
266                         w.items.first().setValue(r.responseText);
267                     }
268                 });
269             }
270         }
271     });
272
273     // create the Grid
274     var grid = Ext.create('Ext.grid.Panel', {
275         store: store,
276         columns: [
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'}
282         ],
283         plugins: Ext.create('Ext.ux.CellFieldDropZone'),
284         stripeRows: true,
285         autoExpandColumn: 'company',
286         height:350,
287         width:600,
288         title:'Array Grid',
289         dockedItems: [{
290             dock: 'bottom',
291             xtype: 'toolbar',
292             items: {
293                 text: 'View Source',
294                 handler: function() {
295                     helpWindow.show();
296                 }
297             }
298         }]
299     });
300
301     grid.render('grid-example');
302
303     var f = Ext.create('Ext.Panel', {
304         frame: true,
305         width: 600,
306         plugins: Ext.create('Ext.ux.PanelFieldDragZone'),
307         labelWidth: 150,
308         items: [{
309             xtype: 'textfield',
310             fieldLabel: 'Drag this text',
311             value: 'test'
312         },{
313             xtype: 'numberfield',
314             fieldLabel: 'Drag this number',
315             value: '1.2'
316         },{
317             xtype: 'datefield',
318             fieldLabel: 'Drag this date',
319             value: new Date()
320         }],
321         renderTo: Ext.getBody()
322     });
323 });