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