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