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