Roo/Template.js
[roojs1] / Roo / XComponent.js
1 /*
2  * Original code for Roojs - LGPL
3  * <script type="text/javascript">
4  */
5  
6 /**
7  * @class Roo.XComponent
8  * A delayed Element creator...
9  * 
10  * Mypart.xyx = new Roo.XComponent({
11
12     parent : 'Mypart.xyz', // empty == document.element.!!
13     order : '001',
14     name : 'xxxx'
15     region : 'xxxx'
16     disabled : function() {} 
17      
18     tree : function() { // return an tree of xtype declared components
19         var MODULE = this;
20         return 
21         {
22             xtype : 'NestedLayoutPanel',
23             // technicall
24         }
25      ]
26  *})
27  * @extends Roo.util.Observable
28  * @constructor
29  * @param cfg {Object} configuration of component
30  * 
31  */
32 Roo.XComponent = function(cfg) {
33     Roo.apply(this, cfg);
34     this.addEvents({ 
35         /**
36              * @event built
37              * Fires when this the componnt is built
38              * @param {Roo.XComponent} c the component
39              */
40         'built' : true,
41         /**
42              * @event buildcomplete
43              * Fires on the top level element when all elements have been built
44              * @param {Roo.XComponent} c the top level component.
45          */
46         'buildcomplete' : true,
47         
48     });
49     
50     Roo.XComponent.register(this);
51     this.modules = false;
52     this.el = false; // where the layout goes..
53     
54     
55 }
56 Roo.extend(Roo.XComponent, Roo.util.Observable, {
57     /**
58      * @property el
59      * The created element (with Roo.factory())
60      * @type {Roo.Layout}
61      */
62     el  : false,
63     
64     /**
65      * @property el
66      * for BC  - use el in new code
67      * @type {Roo.Layout}
68      */
69     panel : false,
70     
71     /**
72      * @property layout
73      * for BC  - use el in new code
74      * @type {Roo.Layout}
75      */
76     layout : false,
77     
78      /**
79      * @cfg {Function|boolean} disabled
80      * If this module is disabled by some rule, return true from the funtion
81      */
82     disabled : false,
83     
84     /**
85      * @cfg {String} parent 
86      * Name of parent element which it get xtype added to..
87      */
88     parent: false,
89     
90     /**
91      * @cfg {String} order
92      * Used to set the order in which elements are created (usefull for multiple tabs)
93      */
94     
95     order : false,
96     /**
97      * @cfg {String} name
98      * String to display while loading.
99      */
100     name : false,
101     /**
102      * @cfg {Array} items
103      * A single item array - the first element is the root of the tree..
104      * It's done this way to stay compatible with the Xtype system...
105      */
106     items : false,
107      
108      
109     
110 });
111
112 Roo.apply(Roo.XComponent, {
113     
114     /**
115      * @property  buildCompleted
116      * True when the builder has completed building the interface.
117      * @type Boolean
118      */
119     buildCompleted : false,
120      
121     /**
122      * @property  topModule
123      * the upper most module - uses document.element as it's constructor.
124      * @type Object
125      */
126      
127     topModule  : false,
128       
129     /**
130      * @property  modules
131      * array of modules to be created by registration system.
132      * @type Roo.XComponent
133      */
134     
135     modules : [],
136       
137     
138     /**
139      * Register components to be built later.
140      *
141      * This solves the following issues
142      * - Building is not done on page load, but after an authentication process has occured.
143      * - Interface elements are registered on page load
144      * - Parent Interface elements may not be loaded before child, so this handles that..
145      * 
146      *
147      * example:
148      * 
149      * MyApp.register({
150           order : '000001',
151           module : 'Pman.Tab.projectMgr',
152           region : 'center',
153           parent : 'Pman.layout',
154           disabled : false,  // or use a function..
155         })
156      
157      * * @param {Object} details about module
158      */
159     register : function(obj) {
160         this.modules.push(obj);
161          
162     },
163     /**
164      * convert a string to an object..
165      * 
166      */
167     
168     toObject : function(str)
169     {
170         if (!str || typeof(str) == 'object') {
171             return str;
172         }
173         var ar = str.split('.');
174         var rt, o;
175         rt = ar.shift();
176             /** eval:var:o */
177         eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
178         if (o === false) {
179             throw "Module not found : " + str;
180         }
181         Roo.each(ar, function(e) {
182             if (typeof(o[e]) == 'undefined') {
183                 throw "Module not found : " + str;
184             }
185             o = o[e];
186         });
187         return o;
188         
189     },
190     
191     
192     /**
193      * move modules into their correct place in the tree..
194      * 
195      */
196     preBuild : function ()
197     {
198         
199         Roo.each(this.modules , function (obj)
200         {
201             obj.parent = this.toObject(obj.parent);
202             
203             if (!obj.parent) {
204                 this.topModule = obj;
205                 return;
206             }
207             
208             if (!obj.parent.modules) {
209                 obj.parent.modules = new Roo.util.MixedCollection(false, 
210                     function(o) { return o.order + '' }
211                 );
212             }
213             
214             obj.parent.modules.add(obj);
215         }, this);
216     },
217     
218      /**
219      * make a list of modules to build.
220      * @return {Array} list of modules. 
221      */ 
222     
223     buildOrder : function()
224     {
225         var _this = this;
226         var cmp = function(a,b) {   
227             return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
228         };
229         
230         if (!this.topModule || !this.topModule.modules) {
231             throw "No top level modules to build";
232         }
233        
234         // make a flat list in order of modules to build.
235         var mods = [ this.topModule ];
236         
237         
238         // add modules to their parents..
239         var addMod = function(m) {
240            // console.log(m.modKey);
241             
242             mods.push(m);
243             if (m.modules) {
244                 m.modules.keySort('ASC',  cmp );
245                 m.modules.each(addMod);
246             }
247             // not sure if this is used any more..
248             if (m.finalize) {
249                 m.finalize.name = m.name + " (clean up) ";
250                 mods.push(m.finalize);
251             }
252             
253         }
254         this.topModule.modules.keySort('ASC',  cmp );
255         this.topModule.modules.each(addMod);
256         return mods;
257     },
258     
259      /**
260      * Build the registered modules.
261      * @param {Object} parent element.
262      * @param {Function} optional method to call after module has been added.
263      * 
264      */ 
265    
266     build : function() 
267     {
268         
269         this.preBuild();
270         var mods = this.buildOrder();
271       
272         //this.allmods = mods;
273         //console.log(mods);
274         //return;
275         if (!mods.length) { // should not happen
276             throw "NO modules!!!";
277         }
278         
279         
280         
281         // flash it up as modal - so we store the mask!?
282         Roo.MessageBox.show({ title: 'loading' });
283         Roo.MessageBox.show({
284            title: "Please wait...",
285            msg: "Building Interface...",
286            width:450,
287            progress:true,
288            closable:false,
289            modal: false
290           
291         });
292         var total = mods.length;
293         
294         var _this = this;
295         var progressRun = function() {
296             if (!mods.length) {
297                 console.log('hide?');
298                 Roo.MessageBox.hide();
299                 _this.topModule.fireEvent('buildcomplete', _this.topModule);
300                 return;    
301             }
302             
303             var m = mods.shift();
304             console.log(m);
305             if (typeof(m) == 'function') { // not sure if this is supported any more..
306                 m.call(this);
307                 return progressRun.defer(10, _this);
308             } 
309             
310             Roo.MessageBox.updateProgress(
311                 (total  - mods.length)/total,  "Building Interface " + (total  - mods.length) + 
312                     " of " + total + 
313                     (m.name ? (' - ' + m.name) : '')
314                     );
315             
316          
317             
318             var disabled = (typeof(m.disabled) == 'function') ?
319                 m.disabled.call(m.module.disabled) : m.disabled;    
320             
321             
322             if (disabled) {
323                 return progressRun(); // we do not update the display!
324             }
325             
326             if (!m.parent) {
327                 // it's a top level one..
328                 var layoutbase = new Ext.BorderLayout(document.body, {
329                
330                     center: {
331                          titlebar: false,
332                          autoScroll:false,
333                          closeOnTab: true,
334                          tabPosition: 'top',
335                          //resizeTabs: true,
336                          alwaysShowTabs: true,
337                          minTabWidth: 140
338                     }
339                 });
340                 var tree = m.tree();
341                 tree.region = 'center';
342                 m.el = layoutbase.addxtype(tree);
343                 m.panel = m.el;
344                 m.layout = m.panel.layout;    
345                 return progressRun.defer(10, _this);
346             }
347             
348             var tree = m.tree();
349             tree.region = tree.region || m.region;
350             m.el = m.parent.el.addxtype(tree);
351             m.fireEvent('built', m);
352             m.panel = m.el;
353             m.layout = m.panel.layout;    
354             progressRun.defer(10, _this); 
355             
356         }
357         progressRun.defer(1, _this);
358      
359         
360         
361     }
362      
363    
364     
365     
366 });
367