Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / examples / dd / field-to-grid-dd.js
1 /*!
2  * Ext JS Library 3.0.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 // A DropZone which cooperates with DragZones whose dragData contains\r
8 // a "field" property representing a form Field. Fields may be dropped onto\r
9 // grid data cells containing a matching data type.\r
10 Ext.ux.CellFieldDropZone = Ext.extend(Ext.dd.DropZone, {\r
11     constructor: function(){},\r
12 \r
13 //  Call the DropZone constructor using the View's scrolling element\r
14 //  only after the grid has been rendered.\r
15     init: function(grid) {\r
16         if (grid.rendered) {\r
17             this.grid = grid;\r
18             this.view = grid.getView();\r
19             this.store = grid.getStore();\r
20             Ext.ux.CellFieldDropZone.superclass.constructor.call(this, this.view.scroller);\r
21         } else {\r
22             grid.on('render', this.init, this);\r
23         }\r
24     },\r
25 \r
26 //  Scroll the main configured Element when we drag close to the edge\r
27     containerScroll: true,\r
28 \r
29     getTargetFromEvent: function(e) {\r
30 //      Ascertain whether the mousemove is within a grid cell\r
31         var t = e.getTarget(this.view.cellSelector);\r
32         if (t) {\r
33 \r
34 //          We *are* within a grid cell, so ask the View exactly which one,\r
35 //          Extract data from the Model to create a target object for\r
36 //          processing in subsequent onNodeXXXX methods. Note that the target does\r
37 //          not have to be a DOM element. It can be whatever the noNodeXXX methods are\r
38 //          programmed to expect.\r
39             var rowIndex = this.view.findRowIndex(t);\r
40             var columnIndex = this.view.findCellIndex(t);\r
41             if ((rowIndex !== false) && (columnIndex !== false)) {\r
42                 return {\r
43                     node: t,\r
44                     record: this.store.getAt(rowIndex),\r
45                     fieldName: this.grid.getColumnModel().getDataIndex(columnIndex)\r
46                 }\r
47             }\r
48         }\r
49     },\r
50 \r
51 //  On Node enter, see if it is valid for us to drop the field on that type of column.\r
52     onNodeEnter: function(target, dd, e, dragData) {\r
53         delete this.dropOK;\r
54         if (!target) {\r
55             return;\r
56         }\r
57 \r
58 //      Check that a field is being dragged.\r
59         var f = dragData.field;\r
60         if (!f) {\r
61             return;\r
62         }\r
63 \r
64 //      Check whether the data type of the column being dropped on accepts the\r
65 //      dragged field type. If so, set dropOK flag, and highlight the target node.\r
66         var type = target.record.fields.get(target.fieldName).type;\r
67         switch (type) {\r
68             case 'float':\r
69             case 'int':\r
70                 if (!f.isXType('numberfield')) {\r
71                     return;\r
72                 }\r
73                 break;\r
74             case 'date':\r
75                 if (!f.isXType('datefield')) {\r
76                     return;\r
77                 }\r
78                 break;\r
79             case 'boolean':\r
80                 if (!f.isXType('checkbox')) {\r
81                     return;\r
82                 }\r
83         }\r
84         this.dropOK = true;\r
85         Ext.fly(target.node).addClass('x-drop-target-active');\r
86     },\r
87 \r
88 //  Return the class name to add to the drag proxy. This provides a visual indication\r
89 //  of drop allowed or not allowed.\r
90     onNodeOver: function(target, dd, e, dragData) {\r
91         return this.dropOK ? this.dropAllowed : this.dropNotAllowed;\r
92     },\r
93 \r
94 //   nhighlight the target node.\r
95     onNodeOut: function(target, dd, e, dragData) {\r
96         Ext.fly(target.node).removeClass('x-drop-target-active');\r
97     },\r
98 \r
99 //  Process the drop event if we have previously ascertained that a drop is OK.\r
100     onNodeDrop: function(target, dd, e, dragData) {\r
101         if (this.dropOK) {\r
102             target.record.set(target.fieldName, dragData.field.getValue());\r
103             return true;\r
104         }\r
105     }\r
106 });\r
107 \r
108 //  A class which makes Fields within a Panel draggable.\r
109 //  the dragData delivered to a coooperating DropZone's methods contains\r
110 //  the dragged Field in the property "field".\r
111 Ext.ux.PanelFieldDragZone = Ext.extend(Ext.dd.DragZone, {\r
112     constructor: function(){},\r
113 \r
114 //  Call the DRagZone's constructor. The Panel must have been rendered.\r
115     init: function(panel) {\r
116         if (panel.nodeType) {\r
117             Ext.ux.PanelFieldDragZone.superclass.init.apply(this, arguments);\r
118         } else {\r
119             if (panel.rendered) {\r
120                 Ext.ux.PanelFieldDragZone.superclass.constructor.call(this, panel.getEl());\r
121                 var i = Ext.fly(panel.getEl()).select('input');\r
122                 i.unselectable();\r
123             } else {\r
124                 panel.on('afterlayout', this.init, this, {single: true});\r
125             }\r
126         }\r
127     },\r
128 \r
129     scroll: false,\r
130 \r
131 //  On mousedown, we ascertain whether it is on one of our draggable Fields.\r
132 //  If so, we collect data about the draggable object, and return a drag data\r
133 //  object which contains our own data, plus a "ddel" property which is a DOM\r
134 //  node which provides a "view" of the dragged data.\r
135     getDragData: function(e) {\r
136         var t = e.getTarget('input');\r
137         if (t) {\r
138             e.stopEvent();\r
139 \r
140 //          Ugly code to "detach" the drag gesture from the input field.\r
141 //          Without this, Opera never changes the mouseover target from the input field\r
142 //          even when dragging outside of the field - it just keeps selecting.\r
143             if (Ext.isOpera) {\r
144                 Ext.fly(t).on('mousemove', function(e1){\r
145                     t.style.visibility = 'hidden';\r
146                     (function(){\r
147                         t.style.visibility = '';\r
148                     }).defer(1);\r
149                 }, null, {single:true});\r
150             }\r
151 \r
152 //          Get the data we are dragging: the Field\r
153 //          create a ddel for the drag proxy to display\r
154             var f = Ext.getCmp(t.id);\r
155             var d = document.createElement('div');\r
156             d.className = 'x-form-text';\r
157             d.appendChild(document.createTextNode(t.value));\r
158             Ext.fly(d).setWidth(f.getEl().getWidth());\r
159             return {\r
160                 field: f,\r
161                 ddel: d\r
162             };\r
163         }\r
164     },\r
165 \r
166 //  The coordinates to slide the drag proxy back to on failed drop.\r
167     getRepairXY: function() {\r
168         return this.dragData.field.getEl().getXY();\r
169     }\r
170 });\r
171 \r
172 Ext.onReady(function(){\r
173 \r
174     var myData = [\r
175         ['3m Co',71.72,0.02,0.03,'9/1 12:00am'],\r
176         ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'],\r
177         ['Altria Group Inc',83.81,0.28,0.34,'9/1 12:00am'],\r
178         ['American Express Company',52.55,0.01,0.02,'9/1 12:00am'],\r
179         ['American International Group, Inc.',64.13,0.31,0.49,'9/1 12:00am'],\r
180         ['AT&T Inc.',31.61,-0.48,-1.54,'9/1 12:00am'],\r
181         ['Boeing Co.',75.43,0.53,0.71,'9/1 12:00am'],\r
182         ['Caterpillar Inc.',67.27,0.92,1.39,'9/1 12:00am'],\r
183         ['Citigroup, Inc.',49.37,0.02,0.04,'9/1 12:00am'],\r
184         ['E.I. du Pont de Nemours and Company',40.48,0.51,1.28,'9/1 12:00am'],\r
185         ['Exxon Mobil Corp',68.1,-0.43,-0.64,'9/1 12:00am'],\r
186         ['General Electric Company',34.14,-0.08,-0.23,'9/1 12:00am'],\r
187         ['General Motors Corporation',30.27,1.09,3.74,'9/1 12:00am'],\r
188         ['Hewlett-Packard Co.',36.53,-0.03,-0.08,'9/1 12:00am'],\r
189         ['Honeywell Intl Inc',38.77,0.05,0.13,'9/1 12:00am'],\r
190         ['Intel Corporation',19.88,0.31,1.58,'9/1 12:00am'],\r
191         ['International Business Machines',81.41,0.44,0.54,'9/1 12:00am'],\r
192         ['Johnson & Johnson',64.72,0.06,0.09,'9/1 12:00am'],\r
193         ['JP Morgan & Chase & Co',45.73,0.07,0.15,'9/1 12:00am'],\r
194         ['McDonald\'s Corporation',36.76,0.86,2.40,'9/1 12:00am'],\r
195         ['Merck & Co., Inc.',40.96,0.41,1.01,'9/1 12:00am'],\r
196         ['Microsoft Corporation',25.84,0.14,0.54,'9/1 12:00am'],\r
197         ['Pfizer Inc',27.96,0.4,1.45,'9/1 12:00am'],\r
198         ['The Coca-Cola Company',45.07,0.26,0.58,'9/1 12:00am'],\r
199         ['The Home Depot, Inc.',34.64,0.35,1.02,'9/1 12:00am'],\r
200         ['The Procter & Gamble Company',61.91,0.01,0.02,'9/1 12:00am'],\r
201         ['United Technologies Corporation',63.26,0.55,0.88,'9/1 12:00am'],\r
202         ['Verizon Communications',35.57,0.39,1.11,'9/1 12:00am'],\r
203         ['Wal-Mart Stores, Inc.',45.45,0.73,1.63,'9/1 12:00am']\r
204     ];\r
205 \r
206     // example of custom renderer function\r
207     function change(val){\r
208         if(val > 0){\r
209             return '<span style="color:green;">' + val + '</span>';\r
210         }else if(val < 0){\r
211             return '<span style="color:red;">' + val + '</span>';\r
212         }\r
213         return val;\r
214     }\r
215 \r
216     // example of custom renderer function\r
217     function pctChange(val){\r
218         if(val > 0){\r
219             return '<span style="color:green;">' + val + '%</span>';\r
220         }else if(val < 0){\r
221             return '<span style="color:red;">' + val + '%</span>';\r
222         }\r
223         return val;\r
224     }\r
225 \r
226     // create the data store\r
227     var store = new Ext.data.ArrayStore({\r
228         fields: [\r
229            {name: 'company'},\r
230            {name: 'price', type: 'float'},\r
231            {name: 'change', type: 'float'},\r
232            {name: 'pctChange', type: 'float'},\r
233            {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}\r
234         ]\r
235     });\r
236     store.loadData(myData);\r
237     \r
238     var helpWindow = new Ext.Window({\r
239         title: 'Source code',\r
240         width: 920,\r
241         height: 500,\r
242         closeAction: 'hide',\r
243         bodyCfg: {tag: 'textarea', readonly: true},\r
244         bodyStyle: {\r
245             backgroundColor: 'white',\r
246             margin: '0px',\r
247             border: '0px none'\r
248         },\r
249         listeners: {\r
250             render: function(w) {\r
251                 Ext.Ajax.request({\r
252                     url: 'field-to-grid-dd.js',\r
253                     success: function(r) {\r
254                         w.body.dom.value = r.responseText;\r
255                     }\r
256                 });\r
257             }\r
258         }\r
259     });\r
260 \r
261     // create the Grid\r
262     var grid = new Ext.grid.GridPanel({\r
263         store: store,\r
264         columns: [\r
265             {id:'company',header: "Company", width: 160, sortable: true, dataIndex: 'company'},\r
266             {header: "Price", width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'},\r
267             {header: "Change", width: 75, sortable: true, renderer: change, dataIndex: 'change'},\r
268             {header: "% Change", width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'},\r
269             {header: "Last Updated", width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}\r
270         ],\r
271         plugins: new Ext.ux.CellFieldDropZone(),\r
272         stripeRows: true,\r
273         autoExpandColumn: 'company',\r
274         height:350,\r
275         width:600,\r
276         title:'Array Grid',\r
277         bbar: new Ext.PagingToolbar({\r
278             buttons: [{\r
279                 text: 'View Source',\r
280                 handler: function() {\r
281                     helpWindow.show();\r
282                 }\r
283             }],\r
284             store: store,\r
285             pageSize: 25\r
286         })\r
287     });\r
288 \r
289     grid.render('grid-example');\r
290     grid.getSelectionModel().selectFirstRow();\r
291 \r
292     var f = new Ext.Panel({\r
293         frame: true,\r
294         layout: 'form',\r
295         width: 600,\r
296         plugins: new Ext.ux.PanelFieldDragZone(),\r
297         style: {\r
298             'margin-top': '10px'\r
299         },\r
300         labelWidth: 150,\r
301         items: [{\r
302             xtype: 'textfield',\r
303             fieldLabel: 'Drag this text',\r
304             value: 'test'\r
305         },{\r
306             xtype: 'numberfield',\r
307             fieldLabel: 'Drag this number',\r
308             value: '1.2'\r
309         },{\r
310             xtype: 'datefield',\r
311             fieldLabel: 'Drag this date',\r
312             value: new Date()\r
313         }],\r
314         renderTo: Ext.getBody()\r
315     });\r
316 });