Roo/form/ComboNested.js
[roojs1] / Roo / form / ComboNested.js
1 /*
2  * RooJS Library 1.1.1
3  * Copyright(c) 2008-2011  Alan Knowles
4  *
5  * License - LGPL
6  */
7  
8
9 /**
10  * @class Roo.form.ComboNested
11  * @extends Roo.form.ComboBox
12  * A combobox for that allows selection of nested items in a list,
13  * eg.
14  *
15  *  Book
16  *    -> red
17  *    -> green
18  *  Table
19  *    -> square
20  *      ->red
21  *      ->green
22  *    -> rectangle
23  *      ->green
24  *      
25  * 
26  * @constructor
27  * Create a new ComboNested
28  * @param {Object} config Configuration options
29  */
30 Roo.form.ComboNested = function(config){
31     Roo.form.ComboCheck.superclass.constructor.call(this, config);
32     // should verify some data...
33     // like
34     // hiddenName = required..
35     // displayField = required
36     // valudField == required
37     var req= [ 'hiddenName', 'displayField', 'valueField' ];
38     var _t = this;
39     Roo.each(req, function(e) {
40         if ((typeof(_t[e]) == 'undefined' ) || !_t[e].length) {
41             throw "Roo.form.ComboNested : missing value for: " + e;
42         }
43     });
44      
45     
46 };
47
48 Roo.extend(Roo.form.ComboNested, Roo.form.ComboBox, {
49    
50    
51     list : null, // the outermost div..
52     innerLists : null, // the
53     views : null,
54     stores : null,
55     // private
56     onRender : function(ct, position)
57     {
58         Roo.form.ComboBox.superclass.onRender.call(this, ct, position); // skip parent call - got to above..
59         
60         if(this.hiddenName){
61             this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id:  (this.hiddenId||this.hiddenName)},
62                     'before', true);
63             this.hiddenField.value =
64                 this.hiddenValue !== undefined ? this.hiddenValue :
65                 this.value !== undefined ? this.value : '';
66
67             // prevent input submission
68             this.el.dom.removeAttribute('name');
69              
70              
71         }
72         
73         if(Roo.isGecko){
74             this.el.dom.setAttribute('autocomplete', 'off');
75         }
76
77         var cls = 'x-combo-list';
78
79         this.list = new Roo.Layer({
80             shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
81         });
82
83         var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
84         this.list.setWidth(lw);
85         this.list.swallowEvent('mousewheel');
86         this.assetHeight = 0;
87
88         if(this.title){
89             this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
90             this.assetHeight += this.header.getHeight();
91         }
92         this.innerLists = [];
93         this.views = [];
94         this.stores = [];
95         for (var i =0 ; i < 3; i++) {
96             this.onRenderList( cls, i);
97         }
98         
99         if(this.allowBlank && !this.disableClear){
100             this.footer = this.list.createChild({cls:cls+'-ft'});
101             this.pageTb = new Roo.Toolbar(this.footer);  
102         }
103        
104         
105         if (this.pageTb && this.allowBlank && !this.disableClear) {
106             var _this = this;
107             this.pageTb.add(new Roo.Toolbar.Fill(), {
108                 cls: 'x-btn-icon x-btn-clear',
109                 text: '&#160;',
110                 handler: function()
111                 {
112                     _this.collapse();
113                     _this.clearValue();
114                     _this.onSelect(false, -1);
115                 }
116             });
117         }
118         if (this.footer) {
119             this.assetHeight += this.footer.getHeight();
120         }
121         
122     },
123     onRenderList : function (  cls, i)
124     {
125         
126         var lw = Math.floor(
127                 ((this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth)) - this.list.getFrameWidth('lr')) / 3
128             );;
129
130         var il = this.innerLists[i] = this.list.createChild({cls:cls+'-inner'});
131         //il.on('mouseover', this.onViewOver, this, { list:  i });
132         //il.on('mousemove', this.onViewMove, this, { list:  i });
133         il.setWidth(lw);
134          
135
136         if(!this.tpl){
137             this.tpl = '<div class="'+cls+'-item">{' + this.displayField + '}</div>';
138         }
139         
140         var store  = this.store;
141         if (i > 0) {
142             store  = new Roo.data.SimpleStore({
143                 fields : [ 'key', 'value' ],
144                 data : [ ]
145             });
146         }
147         this.stores[i]  = store;
148                 
149         
150         
151         var view = this.views[i] = new Roo.View(il, this.tpl, {
152             singleSelect:true,
153             store: store,
154             selectedClass: this.selectedClass
155         });
156         view.getEl().setWidth(lw);
157         //view.on('click', this.onViewClick, this, { list : i });
158
159         store.on('beforeload', this.onBeforeLoad, this);
160         store.on('load', this.onLoad, this);
161         store.on('loadexception', this.onLoadException, this);
162
163           
164         
165         
166         
167     },
168     onResize : function()  {},
169     
170     restrictHeight : function()
171     {
172         var mh = 0;
173         Roo.each(this.innerLists, function(il,i) {
174             var el = this.views[i].getEl();
175             el.dom.style.height = '';
176             var inner = el.dom;
177             var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
178             el.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
179             il.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
180             mh = Math.max(el.getHeight(), mh);
181         }, this);
182         
183         this.list.beginUpdate();
184         this.list.setHeight(mh+this.list.getFrameWidth('tb')+this.assetHeight);
185         this.list.alignTo(this.el, this.listAlign);
186         this.list.endUpdate();
187         
188     },
189      
190     
191     // -- store handlers..
192     
193     // private
194     onLoad : function(a,b,c,d)
195     {
196          
197         if(!this.hasFocus){
198             return;
199         }
200         
201         if(this.store.getCount() > 0) {
202             this.expand();
203             this.restrictHeight();   
204         } else {
205             this.onEmptyResults();
206         }
207         //this.el.focus();
208     },
209     // private
210     onLoadException : function()
211     {
212         this.collapse();
213         Roo.log(this.store.reader.jsonData);
214         if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
215             Roo.MessageBox.alert("Error loading",this.store.reader.jsonData.errorMsg);
216         }
217         
218         
219     } ,
220      
221     onViewOver : function(e, t, opts)
222     {
223         return;
224         var item = this.views[opts.list].findItemFromChild(t);
225         if(item){
226             var index = this.views[opts.list].indexOf(item);
227             this.select(index, false);
228         }
229     },
230     
231     onViewClick : function(doFocus, opts)
232     {
233         Roo.log(arguments);
234         var index = this.views[opts.list].getSelectedIndexes()[0];
235         var r = this.stores[opts.list].getAt(index);
236         if(r){
237             this.onSelect(r, index);
238         }
239         if(doFocus !== false && !this.blockFocus){
240             this.el.focus();
241         }
242     },
243
244 });