Upgrade to ExtJS 4.0.2 - Released 06/09/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         renderTpl: [
127             '<textarea readonly class="{baseCls}-body<tpl if="bodyCls"> {bodyCls}</tpl><tpl if="frame"> {baseCls}-body-framed</tpl><tpl if="ui"> {baseCls}-body-{ui}</tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>'
128         ],
129         listeners: {
130             render: function(w) {
131                 Ext.Ajax.request({
132                     url: 'dragdropzones.js',
133                     success: function(r) {
134                         w.body.dom.value = r.responseText;
135                     }
136                 });
137             }
138         }
139     });
140
141     var hospitalGrid = Ext.create('Ext.grid.Panel', {
142         title: 'Hospitals',
143         region: 'center',
144         margins: '0 5 5 0',
145         bbar: [{
146             text: 'View Source',
147             handler: function() {
148                 helpWindow.show();
149             }
150         }],
151         sortableColumns: false,
152         columns: [{
153             dataIndex: 'name',
154             header: 'Name',
155             width: 200
156         }, {
157             dataIndex: 'address',
158             header: 'Address',
159             width: 300
160         }, {
161             dataIndex: 'telephone',
162             header: 'Telephone',
163             width: 100
164         }],
165         features: [{
166             ftype:'rowbody',
167             rowBodyDivCls: 'hospital-target',
168             getAdditionalData: function() {
169                 return Ext.apply(Ext.grid.feature.RowBody.prototype.getAdditionalData.apply(this, arguments), {
170                     rowBody: 'Drop Patient Here'
171                 });
172             }
173         }],
174         viewConfig: {
175             listeners: {
176                 render: initializeHospitalDropZone
177             }
178         },
179         store: hospitalStore
180     });
181
182     Ext.create('Ext.Viewport', {
183         layout: 'border',
184         items: [{
185             cls: 'app-header',
186             region: 'north',
187             height: 30,
188             html: '<h1>Patient Hospital Assignment</h1>',
189             margins: '5 5 5 5'
190         }, {
191             title: 'Patients',
192             region: 'west',
193             width: 300,
194             margins: '0 5 5 5',
195             items: patientView
196         }, hospitalGrid ]
197     });
198 });
199
200 /*
201  * Here is where we "activate" the DataView.
202  * We have decided that each node with the class "patient-source" encapsulates a single draggable
203  * object.
204  *
205  * So we inject code into the DragZone which, when passed a mousedown event, interrogates
206  * the event to see if it was within an element with the class "patient-source". If so, we
207  * return non-null drag data.
208  *
209  * Returning non-null drag data indicates that the mousedown event has begun a dragging process.
210  * The data must contain a property called "ddel" which is a DOM element which provides an image
211  * of the data being dragged. The actual node clicked on is not dragged, a proxy element is dragged.
212  * We can insert any other data into the data object, and this will be used by a cooperating DropZone
213  * to perform the drop operation.
214  */
215 function initializePatientDragZone(v) {
216     v.dragZone = Ext.create('Ext.dd.DragZone', v.getEl(), {
217
218 //      On receipt of a mousedown event, see if it is within a draggable element.
219 //      Return a drag data object if so. The data object can contain arbitrary application
220 //      data, but it should also contain a DOM element in the ddel property to provide
221 //      a proxy to drag.
222         getDragData: function(e) {
223             var sourceEl = e.getTarget(v.itemSelector, 10), d;
224             if (sourceEl) {
225                 d = sourceEl.cloneNode(true);
226                 d.id = Ext.id();
227                 return v.dragData = {
228                     sourceEl: sourceEl,
229                     repairXY: Ext.fly(sourceEl).getXY(),
230                     ddel: d,
231                     patientData: v.getRecord(sourceEl).data
232                 };
233             }
234         },
235
236 //      Provide coordinates for the proxy to slide back to on failed drag.
237 //      This is the original XY coordinates of the draggable element.
238         getRepairXY: function() {
239             return this.dragData.repairXY;
240         }
241     });
242 }
243
244 /*
245  * Here is where we "activate" the GridPanel.
246  * We have decided that the element with class "hospital-target" is the element which can receieve
247  * drop gestures. So we inject a method "getTargetFromEvent" into the DropZone. This is constantly called
248  * while the mouse is moving over the DropZone, and it returns the target DOM element if it detects that
249  * the mouse if over an element which can receieve drop gestures.
250  *
251  * Once the DropZone has been informed by getTargetFromEvent that it is over a target, it will then
252  * call several "onNodeXXXX" methods at various points. These include:
253  *
254  * onNodeEnter
255  * onNodeOut
256  * onNodeOver
257  * onNodeDrop
258  *
259  * We provide implementations of each of these to provide behaviour for these events.
260  */
261 function initializeHospitalDropZone(v) {
262     var gridView = v,
263         grid = gridView.up('gridpanel');
264
265     grid.dropZone = Ext.create('Ext.dd.DropZone', v.el, {
266
267 //      If the mouse is over a target node, return that node. This is
268 //      provided as the "target" parameter in all "onNodeXXXX" node event handling functions
269         getTargetFromEvent: function(e) {
270             return e.getTarget('.hospital-target');
271         },
272
273 //      On entry into a target node, highlight that node.
274         onNodeEnter : function(target, dd, e, data){
275             Ext.fly(target).addCls('hospital-target-hover');
276         },
277
278 //      On exit from a target node, unhighlight that node.
279         onNodeOut : function(target, dd, e, data){
280             Ext.fly(target).removeCls('hospital-target-hover');
281         },
282
283 //      While over a target node, return the default drop allowed class which
284 //      places a "tick" icon into the drag proxy.
285         onNodeOver : function(target, dd, e, data){
286             return Ext.dd.DropZone.prototype.dropAllowed;
287         },
288
289 //      On node drop, we can interrogate the target node to find the underlying
290 //      application object that is the real target of the dragged data.
291 //      In this case, it is a Record in the GridPanel's Store.
292 //      We can use the data set up by the DragZone's getDragData method to read
293 //      any data we decided to attach.
294         onNodeDrop : function(target, dd, e, data){
295             var rowBody = Ext.fly(target).findParent('.x-grid-rowbody-tr', null, false),
296                 mainRow = rowBody.previousSibling,
297                 h = gridView.getRecord(mainRow),
298                 targetEl = Ext.get(target);
299
300             targetEl.update(data.patientData.name + ', ' + targetEl.dom.innerHTML);
301             Ext.Msg.alert('Drop gesture', 'Dropped patient ' + data.patientData.name +
302                 ' on hospital ' + h.data.name);
303             return true;
304         }
305     });
306 }
307