Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / examples / dd / dragdropzones.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 Ext.require(['*']);
16
17 Ext.onReady(function() {
18
19     var patients = [{
20         insuranceCode: '11111',
21         name: 'Fred Bloggs',
22         address: 'Main Street',
23         telephone: '555 1234 123'
24     }, {
25         insuranceCode: '22222',
26         name: 'Fred Bansod',
27         address: 'Van Ness',
28         telephone: '666 666 666'
29     }, {
30         insuranceCode: '33333',
31         name: 'Fred Mercury',
32         address: 'Over The Rainbow',
33         telephone: '555 321 0987'
34     }, {
35         insuranceCode: '44444',
36         name: 'Fred Forsyth',
37         address: 'Blimp Street',
38         telephone: '555 111 2222'
39     }, {
40         insuranceCode: '55555',
41         name: 'Fred Douglass',
42         address: 'Talbot County, Maryland',
43         telephone: 'N/A'
44     }];
45
46     Ext.define('Patient', {
47         extend: 'Ext.data.Model',
48         idProperty: 'insuranceCode',
49         fields: [{
50                 name: 'name'
51             }, {
52                 name: 'address'
53             }, {
54                 name: 'telephone'
55             }]
56     });
57
58     var patientStore = Ext.create('Ext.data.Store', {
59         model: 'Patient',
60         data: patients
61     });
62
63     var hospitals = [{
64         code: 'AAAAA',
65         name: 'Saint Thomas',
66         address: 'Westminster Bridge Road, SE1 7EH',
67         telephone: '020 7188 7188'
68     }, {
69         code: 'BBBBB',
70         name: 'Queen\'s Medical Centre',
71         address: 'Derby Road, NG7 2UH',
72         telephone: '0115 924 9924'
73     }, {
74         code: 'CCCCC',
75         name: 'Saint Bartholomew',
76         address: 'West Smithfield, EC1A 7BE',
77         telephone: '020 7377 7000'
78     }, {
79         code: 'DDDDD',
80         name: 'Royal London',
81         address: 'Whitechapel, E1 1BB',
82         telephone: '020 7377 7000'
83     }];
84
85     Ext.define('Hospital', {
86         extend: 'Ext.data.Model',
87         idProperty: 'code',
88         fields: [{
89             name: 'name'
90         }, {
91             name: 'address'
92         }, {
93             name: 'telephone'
94         }]
95     });
96
97     var hospitalStore = Ext.create('Ext.data.Store', {
98         model: 'Hospital',
99         data: hospitals
100     });
101
102     var patientView = Ext.create('Ext.view.View', {
103         cls: 'patient-view',
104         tpl: '<tpl for=".">' +
105                 '<div class="patient-source"><table><tbody>' +
106                     '<tr><td class="patient-label">Name</td><td class="patient-name">{name}</td></tr>' +
107                     '<tr><td class="patient-label">Address</td><td class="patient-name">{address}</td></tr>' +
108                     '<tr><td class="patient-label">Telephone</td><td class="patient-name">{telephone}</td></tr>' +
109                 '</tbody></table></div>' +
110              '</tpl>',
111         itemSelector: 'div.patient-source',
112         overItemCls: 'patient-over',
113         selectedItemClass: 'patient-selected',
114         singleSelect: true,
115         store: patientStore,
116         listeners: {
117             render: initializePatientDragZone
118         }
119     });
120
121     var helpWindow = Ext.create('Ext.Window', {
122         title: 'Source code',
123         width: 920,
124         height: 500,
125         closeAction: 'hide',
126         layout: 'fit',
127         items: [
128             {
129                 xtype: 'textarea',
130                 itemId: 'srcTextArea'
131             }
132         ],
133         listeners: {
134             render: function(w) {
135                 Ext.Ajax.request({
136                     url: 'dragdropzones.js',
137                     success: function(r) {
138                         w.down('#srcTextArea').setValue(r.responseText);
139                     }
140                 });
141             }
142         }
143     });
144
145     var hospitalGrid = Ext.create('Ext.grid.Panel', {
146         title: 'Hospitals',
147         region: 'center',
148         margins: '0 5 5 0',
149         bbar: [{
150             text: 'View Source',
151             handler: function() {
152                 helpWindow.show();
153             }
154         }],
155         sortableColumns: false,
156         columns: [{
157             dataIndex: 'name',
158             header: 'Name',
159             width: 200
160         }, {
161             dataIndex: 'address',
162             header: 'Address',
163             width: 300
164         }, {
165             dataIndex: 'telephone',
166             header: 'Telephone',
167             width: 100
168         }],
169         features: [{
170             ftype:'rowbody',
171             rowBodyDivCls: 'hospital-target',
172             getAdditionalData: function() {
173                 return Ext.apply(Ext.grid.feature.RowBody.prototype.getAdditionalData.apply(this, arguments), {
174                     rowBody: 'Drop Patient Here'
175                 });
176             }
177         }],
178         viewConfig: {
179             listeners: {
180                 render: initializeHospitalDropZone
181             }
182         },
183         store: hospitalStore
184     });
185
186     Ext.create('Ext.Viewport', {
187         layout: 'border',
188         items: [{
189             cls: 'app-header',
190             region: 'north',
191             height: 30,
192             html: '<h1>Patient Hospital Assignment</h1>',
193             margins: '5 5 5 5'
194         }, {
195             title: 'Patients',
196             region: 'west',
197             width: 300,
198             margins: '0 5 5 5',
199             items: patientView
200         }, hospitalGrid ]
201     });
202 });
203
204 /*
205  * Here is where we "activate" the DataView.
206  * We have decided that each node with the class "patient-source" encapsulates a single draggable
207  * object.
208  *
209  * So we inject code into the DragZone which, when passed a mousedown event, interrogates
210  * the event to see if it was within an element with the class "patient-source". If so, we
211  * return non-null drag data.
212  *
213  * Returning non-null drag data indicates that the mousedown event has begun a dragging process.
214  * The data must contain a property called "ddel" which is a DOM element which provides an image
215  * of the data being dragged. The actual node clicked on is not dragged, a proxy element is dragged.
216  * We can insert any other data into the data object, and this will be used by a cooperating DropZone
217  * to perform the drop operation.
218  */
219 function initializePatientDragZone(v) {
220     v.dragZone = Ext.create('Ext.dd.DragZone', v.getEl(), {
221
222 //      On receipt of a mousedown event, see if it is within a draggable element.
223 //      Return a drag data object if so. The data object can contain arbitrary application
224 //      data, but it should also contain a DOM element in the ddel property to provide
225 //      a proxy to drag.
226         getDragData: function(e) {
227             var sourceEl = e.getTarget(v.itemSelector, 10), d;
228             if (sourceEl) {
229                 d = sourceEl.cloneNode(true);
230                 d.id = Ext.id();
231                 return v.dragData = {
232                     sourceEl: sourceEl,
233                     repairXY: Ext.fly(sourceEl).getXY(),
234                     ddel: d,
235                     patientData: v.getRecord(sourceEl).data
236                 };
237             }
238         },
239
240 //      Provide coordinates for the proxy to slide back to on failed drag.
241 //      This is the original XY coordinates of the draggable element.
242         getRepairXY: function() {
243             return this.dragData.repairXY;
244         }
245     });
246 }
247
248 /*
249  * Here is where we "activate" the GridPanel.
250  * We have decided that the element with class "hospital-target" is the element which can receieve
251  * drop gestures. So we inject a method "getTargetFromEvent" into the DropZone. This is constantly called
252  * while the mouse is moving over the DropZone, and it returns the target DOM element if it detects that
253  * the mouse if over an element which can receieve drop gestures.
254  *
255  * Once the DropZone has been informed by getTargetFromEvent that it is over a target, it will then
256  * call several "onNodeXXXX" methods at various points. These include:
257  *
258  * onNodeEnter
259  * onNodeOut
260  * onNodeOver
261  * onNodeDrop
262  *
263  * We provide implementations of each of these to provide behaviour for these events.
264  */
265 function initializeHospitalDropZone(v) {
266     var gridView = v,
267         grid = gridView.up('gridpanel');
268
269     grid.dropZone = Ext.create('Ext.dd.DropZone', v.el, {
270
271 //      If the mouse is over a target node, return that node. This is
272 //      provided as the "target" parameter in all "onNodeXXXX" node event handling functions
273         getTargetFromEvent: function(e) {
274             return e.getTarget('.hospital-target');
275         },
276
277 //      On entry into a target node, highlight that node.
278         onNodeEnter : function(target, dd, e, data){
279             Ext.fly(target).addCls('hospital-target-hover');
280         },
281
282 //      On exit from a target node, unhighlight that node.
283         onNodeOut : function(target, dd, e, data){
284             Ext.fly(target).removeCls('hospital-target-hover');
285         },
286
287 //      While over a target node, return the default drop allowed class which
288 //      places a "tick" icon into the drag proxy.
289         onNodeOver : function(target, dd, e, data){
290             return Ext.dd.DropZone.prototype.dropAllowed;
291         },
292
293 //      On node drop, we can interrogate the target node to find the underlying
294 //      application object that is the real target of the dragged data.
295 //      In this case, it is a Record in the GridPanel's Store.
296 //      We can use the data set up by the DragZone's getDragData method to read
297 //      any data we decided to attach.
298         onNodeDrop : function(target, dd, e, data){
299             var rowBody = Ext.fly(target).findParent('.x-grid-rowbody-tr', null, false),
300                 mainRow = rowBody.previousSibling,
301                 h = gridView.getRecord(mainRow),
302                 targetEl = Ext.get(target);
303
304             targetEl.update(data.patientData.name + ', ' + targetEl.dom.innerHTML);
305             Ext.Msg.alert('Drop gesture', 'Dropped patient ' + data.patientData.name +
306                 ' on hospital ' + h.data.name);
307             return true;
308         }
309     });
310 }
311