Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / examples / ux / ItemSelector.js
1 /*!
2  * Ext JS Library 3.1.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /*\r
8  * Note that this control will most likely remain as an example, and not as a core Ext form\r
9  * control.  However, the API will be changing in a future release and so should not yet be\r
10  * treated as a final, stable API at this time.\r
11  */\r
12 \r
13 /**\r
14  * @class Ext.ux.form.ItemSelector\r
15  * @extends Ext.form.Field\r
16  * A control that allows selection of between two Ext.ux.form.MultiSelect controls.\r
17  *\r
18  *  @history\r
19  *    2008-06-19 bpm Original code contributed by Toby Stuart (with contributions from Robert Williams)\r
20  *\r
21  * @constructor\r
22  * Create a new ItemSelector\r
23  * @param {Object} config Configuration options\r
24  * @xtype itemselector \r
25  */\r
26 Ext.ux.form.ItemSelector = Ext.extend(Ext.form.Field,  {\r
27     hideNavIcons:false,\r
28     imagePath:"",\r
29     iconUp:"up2.gif",\r
30     iconDown:"down2.gif",\r
31     iconLeft:"left2.gif",\r
32     iconRight:"right2.gif",\r
33     iconTop:"top2.gif",\r
34     iconBottom:"bottom2.gif",\r
35     drawUpIcon:true,\r
36     drawDownIcon:true,\r
37     drawLeftIcon:true,\r
38     drawRightIcon:true,\r
39     drawTopIcon:true,\r
40     drawBotIcon:true,\r
41     delimiter:',',\r
42     bodyStyle:null,\r
43     border:false,\r
44     defaultAutoCreate:{tag: "div"},\r
45     /**\r
46      * @cfg {Array} multiselects An array of {@link Ext.ux.form.MultiSelect} config objects, with at least all required parameters (e.g., store)\r
47      */\r
48     multiselects:null,\r
49 \r
50     initComponent: function(){\r
51         Ext.ux.form.ItemSelector.superclass.initComponent.call(this);\r
52         this.addEvents({\r
53             'rowdblclick' : true,\r
54             'change' : true\r
55         });\r
56     },\r
57 \r
58     onRender: function(ct, position){\r
59         Ext.ux.form.ItemSelector.superclass.onRender.call(this, ct, position);\r
60 \r
61         // Internal default configuration for both multiselects\r
62         var msConfig = [{\r
63             legend: 'Available',\r
64             draggable: true,\r
65             droppable: true,\r
66             width: 100,\r
67             height: 100\r
68         },{\r
69             legend: 'Selected',\r
70             droppable: true,\r
71             draggable: true,\r
72             width: 100,\r
73             height: 100\r
74         }];\r
75 \r
76         this.fromMultiselect = new Ext.ux.form.MultiSelect(Ext.applyIf(this.multiselects[0], msConfig[0]));\r
77         this.fromMultiselect.on('dblclick', this.onRowDblClick, this);\r
78 \r
79         this.toMultiselect = new Ext.ux.form.MultiSelect(Ext.applyIf(this.multiselects[1], msConfig[1]));\r
80         this.toMultiselect.on('dblclick', this.onRowDblClick, this);\r
81 \r
82         var p = new Ext.Panel({\r
83             bodyStyle:this.bodyStyle,\r
84             border:this.border,\r
85             layout:"table",\r
86             layoutConfig:{columns:3}\r
87         });\r
88 \r
89         p.add(this.fromMultiselect);\r
90         var icons = new Ext.Panel({header:false});\r
91         p.add(icons);\r
92         p.add(this.toMultiselect);\r
93         p.render(this.el);\r
94         icons.el.down('.'+icons.bwrapCls).remove();\r
95 \r
96         // ICON HELL!!!\r
97         if (this.imagePath!="" && this.imagePath.charAt(this.imagePath.length-1)!="/")\r
98             this.imagePath+="/";\r
99         this.iconUp = this.imagePath + (this.iconUp || 'up2.gif');\r
100         this.iconDown = this.imagePath + (this.iconDown || 'down2.gif');\r
101         this.iconLeft = this.imagePath + (this.iconLeft || 'left2.gif');\r
102         this.iconRight = this.imagePath + (this.iconRight || 'right2.gif');\r
103         this.iconTop = this.imagePath + (this.iconTop || 'top2.gif');\r
104         this.iconBottom = this.imagePath + (this.iconBottom || 'bottom2.gif');\r
105         var el=icons.getEl();\r
106         this.toTopIcon = el.createChild({tag:'img', src:this.iconTop, style:{cursor:'pointer', margin:'2px'}});\r
107         el.createChild({tag: 'br'});\r
108         this.upIcon = el.createChild({tag:'img', src:this.iconUp, style:{cursor:'pointer', margin:'2px'}});\r
109         el.createChild({tag: 'br'});\r
110         this.addIcon = el.createChild({tag:'img', src:this.iconRight, style:{cursor:'pointer', margin:'2px'}});\r
111         el.createChild({tag: 'br'});\r
112         this.removeIcon = el.createChild({tag:'img', src:this.iconLeft, style:{cursor:'pointer', margin:'2px'}});\r
113         el.createChild({tag: 'br'});\r
114         this.downIcon = el.createChild({tag:'img', src:this.iconDown, style:{cursor:'pointer', margin:'2px'}});\r
115         el.createChild({tag: 'br'});\r
116         this.toBottomIcon = el.createChild({tag:'img', src:this.iconBottom, style:{cursor:'pointer', margin:'2px'}});\r
117         this.toTopIcon.on('click', this.toTop, this);\r
118         this.upIcon.on('click', this.up, this);\r
119         this.downIcon.on('click', this.down, this);\r
120         this.toBottomIcon.on('click', this.toBottom, this);\r
121         this.addIcon.on('click', this.fromTo, this);\r
122         this.removeIcon.on('click', this.toFrom, this);\r
123         if (!this.drawUpIcon || this.hideNavIcons) { this.upIcon.dom.style.display='none'; }\r
124         if (!this.drawDownIcon || this.hideNavIcons) { this.downIcon.dom.style.display='none'; }\r
125         if (!this.drawLeftIcon || this.hideNavIcons) { this.addIcon.dom.style.display='none'; }\r
126         if (!this.drawRightIcon || this.hideNavIcons) { this.removeIcon.dom.style.display='none'; }\r
127         if (!this.drawTopIcon || this.hideNavIcons) { this.toTopIcon.dom.style.display='none'; }\r
128         if (!this.drawBotIcon || this.hideNavIcons) { this.toBottomIcon.dom.style.display='none'; }\r
129 \r
130         var tb = p.body.first();\r
131         this.el.setWidth(p.body.first().getWidth());\r
132         p.body.removeClass();\r
133 \r
134         this.hiddenName = this.name;\r
135         var hiddenTag = {tag: "input", type: "hidden", value: "", name: this.name};\r
136         this.hiddenField = this.el.createChild(hiddenTag);\r
137     },\r
138     \r
139     doLayout: function(){\r
140         if(this.rendered){\r
141             this.fromMultiselect.fs.doLayout();\r
142             this.toMultiselect.fs.doLayout();\r
143         }\r
144     },\r
145 \r
146     afterRender: function(){\r
147         Ext.ux.form.ItemSelector.superclass.afterRender.call(this);\r
148 \r
149         this.toStore = this.toMultiselect.store;\r
150         this.toStore.on('add', this.valueChanged, this);\r
151         this.toStore.on('remove', this.valueChanged, this);\r
152         this.toStore.on('load', this.valueChanged, this);\r
153         this.valueChanged(this.toStore);\r
154     },\r
155 \r
156     toTop : function() {\r
157         var selectionsArray = this.toMultiselect.view.getSelectedIndexes();\r
158         var records = [];\r
159         if (selectionsArray.length > 0) {\r
160             selectionsArray.sort();\r
161             for (var i=0; i<selectionsArray.length; i++) {\r
162                 record = this.toMultiselect.view.store.getAt(selectionsArray[i]);\r
163                 records.push(record);\r
164             }\r
165             selectionsArray = [];\r
166             for (var i=records.length-1; i>-1; i--) {\r
167                 record = records[i];\r
168                 this.toMultiselect.view.store.remove(record);\r
169                 this.toMultiselect.view.store.insert(0, record);\r
170                 selectionsArray.push(((records.length - 1) - i));\r
171             }\r
172         }\r
173         this.toMultiselect.view.refresh();\r
174         this.toMultiselect.view.select(selectionsArray);\r
175     },\r
176 \r
177     toBottom : function() {\r
178         var selectionsArray = this.toMultiselect.view.getSelectedIndexes();\r
179         var records = [];\r
180         if (selectionsArray.length > 0) {\r
181             selectionsArray.sort();\r
182             for (var i=0; i<selectionsArray.length; i++) {\r
183                 record = this.toMultiselect.view.store.getAt(selectionsArray[i]);\r
184                 records.push(record);\r
185             }\r
186             selectionsArray = [];\r
187             for (var i=0; i<records.length; i++) {\r
188                 record = records[i];\r
189                 this.toMultiselect.view.store.remove(record);\r
190                 this.toMultiselect.view.store.add(record);\r
191                 selectionsArray.push((this.toMultiselect.view.store.getCount()) - (records.length - i));\r
192             }\r
193         }\r
194         this.toMultiselect.view.refresh();\r
195         this.toMultiselect.view.select(selectionsArray);\r
196     },\r
197 \r
198     up : function() {\r
199         var record = null;\r
200         var selectionsArray = this.toMultiselect.view.getSelectedIndexes();\r
201         selectionsArray.sort();\r
202         var newSelectionsArray = [];\r
203         if (selectionsArray.length > 0) {\r
204             for (var i=0; i<selectionsArray.length; i++) {\r
205                 record = this.toMultiselect.view.store.getAt(selectionsArray[i]);\r
206                 if ((selectionsArray[i] - 1) >= 0) {\r
207                     this.toMultiselect.view.store.remove(record);\r
208                     this.toMultiselect.view.store.insert(selectionsArray[i] - 1, record);\r
209                     newSelectionsArray.push(selectionsArray[i] - 1);\r
210                 }\r
211             }\r
212             this.toMultiselect.view.refresh();\r
213             this.toMultiselect.view.select(newSelectionsArray);\r
214         }\r
215     },\r
216 \r
217     down : function() {\r
218         var record = null;\r
219         var selectionsArray = this.toMultiselect.view.getSelectedIndexes();\r
220         selectionsArray.sort();\r
221         selectionsArray.reverse();\r
222         var newSelectionsArray = [];\r
223         if (selectionsArray.length > 0) {\r
224             for (var i=0; i<selectionsArray.length; i++) {\r
225                 record = this.toMultiselect.view.store.getAt(selectionsArray[i]);\r
226                 if ((selectionsArray[i] + 1) < this.toMultiselect.view.store.getCount()) {\r
227                     this.toMultiselect.view.store.remove(record);\r
228                     this.toMultiselect.view.store.insert(selectionsArray[i] + 1, record);\r
229                     newSelectionsArray.push(selectionsArray[i] + 1);\r
230                 }\r
231             }\r
232             this.toMultiselect.view.refresh();\r
233             this.toMultiselect.view.select(newSelectionsArray);\r
234         }\r
235     },\r
236 \r
237     fromTo : function() {\r
238         var selectionsArray = this.fromMultiselect.view.getSelectedIndexes();\r
239         var records = [];\r
240         if (selectionsArray.length > 0) {\r
241             for (var i=0; i<selectionsArray.length; i++) {\r
242                 record = this.fromMultiselect.view.store.getAt(selectionsArray[i]);\r
243                 records.push(record);\r
244             }\r
245             if(!this.allowDup)selectionsArray = [];\r
246             for (var i=0; i<records.length; i++) {\r
247                 record = records[i];\r
248                 if(this.allowDup){\r
249                     var x=new Ext.data.Record();\r
250                     record.id=x.id;\r
251                     delete x;\r
252                     this.toMultiselect.view.store.add(record);\r
253                 }else{\r
254                     this.fromMultiselect.view.store.remove(record);\r
255                     this.toMultiselect.view.store.add(record);\r
256                     selectionsArray.push((this.toMultiselect.view.store.getCount() - 1));\r
257                 }\r
258             }\r
259         }\r
260         this.toMultiselect.view.refresh();\r
261         this.fromMultiselect.view.refresh();\r
262         var si = this.toMultiselect.store.sortInfo;\r
263         if(si){\r
264             this.toMultiselect.store.sort(si.field, si.direction);\r
265         }\r
266         this.toMultiselect.view.select(selectionsArray);\r
267     },\r
268 \r
269     toFrom : function() {\r
270         var selectionsArray = this.toMultiselect.view.getSelectedIndexes();\r
271         var records = [];\r
272         if (selectionsArray.length > 0) {\r
273             for (var i=0; i<selectionsArray.length; i++) {\r
274                 record = this.toMultiselect.view.store.getAt(selectionsArray[i]);\r
275                 records.push(record);\r
276             }\r
277             selectionsArray = [];\r
278             for (var i=0; i<records.length; i++) {\r
279                 record = records[i];\r
280                 this.toMultiselect.view.store.remove(record);\r
281                 if(!this.allowDup){\r
282                     this.fromMultiselect.view.store.add(record);\r
283                     selectionsArray.push((this.fromMultiselect.view.store.getCount() - 1));\r
284                 }\r
285             }\r
286         }\r
287         this.fromMultiselect.view.refresh();\r
288         this.toMultiselect.view.refresh();\r
289         var si = this.fromMultiselect.store.sortInfo;\r
290         if (si){\r
291             this.fromMultiselect.store.sort(si.field, si.direction);\r
292         }\r
293         this.fromMultiselect.view.select(selectionsArray);\r
294     },\r
295 \r
296     valueChanged: function(store) {\r
297         var record = null;\r
298         var values = [];\r
299         for (var i=0; i<store.getCount(); i++) {\r
300             record = store.getAt(i);\r
301             values.push(record.get(this.toMultiselect.valueField));\r
302         }\r
303         this.hiddenField.dom.value = values.join(this.delimiter);\r
304         this.fireEvent('change', this, this.getValue(), this.hiddenField.dom.value);\r
305     },\r
306 \r
307     getValue : function() {\r
308         return this.hiddenField.dom.value;\r
309     },\r
310 \r
311     onRowDblClick : function(vw, index, node, e) {\r
312         if (vw == this.toMultiselect.view){\r
313             this.toFrom();\r
314         } else if (vw == this.fromMultiselect.view) {\r
315             this.fromTo();\r
316         }\r
317         return this.fireEvent('rowdblclick', vw, index, node, e);\r
318     },\r
319 \r
320     reset: function(){\r
321         range = this.toMultiselect.store.getRange();\r
322         this.toMultiselect.store.removeAll();\r
323         this.fromMultiselect.store.add(range);\r
324         var si = this.fromMultiselect.store.sortInfo;\r
325         if (si){\r
326             this.fromMultiselect.store.sort(si.field, si.direction);\r
327         }\r
328         this.valueChanged(this.toMultiselect.store);\r
329     }\r
330 });\r
331 \r
332 Ext.reg('itemselector', Ext.ux.form.ItemSelector);\r
333 \r
334 //backwards compat\r
335 Ext.ux.ItemSelector = Ext.ux.form.ItemSelector;\r