Roo/Template.js
[roojs1] / Roo / XComponent.js
index 3440ca0..c4a1ec4 100644 (file)
@@ -6,6 +6,7 @@
 /**
  * @class Roo.XComponent
  * A delayed Element creator...
+ * Or a way to group chunks of interface together.
  * 
  * Mypart.xyx = new Roo.XComponent({
 
         }
      ]
  *})
+ *
+ *
+ * It can be used to build a big heiracy, with parent etc.
+ * or you can just use this to render a single compoent to a dom element
+ * MYPART.render(Roo.Element | String(id) | dom_element )
+ * 
  * @extends Roo.util.Observable
  * @constructor
  * @param cfg {Object} configuration of component
@@ -37,16 +44,10 @@ Roo.XComponent = function(cfg) {
             * Fires when this the componnt is built
             * @param {Roo.XComponent} c the component
             */
-        'built' : true,
-        /**
-            * @event buildcomplete
-            * Fires on the top level element when all elements have been built
-            * @param {Roo.XComponent} c the top level component.
-         */
-        'buildcomplete' : true
+        'built' : true
         
     });
-    
+    this.region = this.region || 'center'; // default..
     Roo.XComponent.register(this);
     this.modules = false;
     this.el = false; // where the layout goes..
@@ -98,14 +99,85 @@ Roo.extend(Roo.XComponent, Roo.util.Observable, {
      * String to display while loading.
      */
     name : false,
+    /**
+     * @cfg {String} region
+     * Region to render component to (defaults to center)
+     */
+    region : 'center',
+    
     /**
      * @cfg {Array} items
      * A single item array - the first element is the root of the tree..
      * It's done this way to stay compatible with the Xtype system...
      */
-    items : false
-     
-     
+    items : false,
+    
+    /**
+     * @property _tree
+     * The method that retuns the tree of parts that make up this compoennt 
+     * @type {function}
+     */
+    _tree  : false,
+    
+     /**
+     * render
+     * render element to dom or tree
+     * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
+     */
+    
+    render : function(el)
+    {
+        
+        el = el || false;
+        var hp = this.parent ? 1 : 0;
+        
+        if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
+            // if parent is a '#.....' string, then let's use that..
+            var ename = this.parent.substr(1)
+            this.parent = false;
+            el = Roo.get(ename);
+            if (!el) {
+                Roo.log("Warning - element can not be found :#" + ename );
+                return;
+            }
+        }
+        
+        
+        if (!this.parent) {
+            
+            el = el ? Roo.get(el) : false;     
+            
+            // it's a top level one..
+            this.parent =  {
+                el : new Roo.BorderLayout(el || document.body, {
+                
+                     center: {
+                         titlebar: false,
+                         autoScroll:false,
+                         closeOnTab: true,
+                         tabPosition: 'top',
+                          //resizeTabs: true,
+                         alwaysShowTabs: el && hp? false :  true,
+                         hideTabs: el || !hp ? true :  false,
+                         minTabWidth: 140
+                     }
+                 })
+            }
+        }
+        
+               
+               // The 'tree' method is  '_tree now' 
+            
+        var tree = this._tree ? this._tree() : this.tree();
+        tree.region = tree.region || this.region;
+        this.el = this.parent.el.addxtype(tree);
+        this.fireEvent('built', this);
+        
+        this.panel = this.el;
+        this.layout = this.panel.layout;
+               this.parentLayout = this.parent.layout  || false;  
+         
+    }
     
 });
 
@@ -129,11 +201,18 @@ Roo.apply(Roo.XComponent, {
     /**
      * @property  modules
      * array of modules to be created by registration system.
-     * @type Roo.XComponent
+     * @type {Array} of Roo.XComponent
      */
     
     modules : [],
-      
+    /**
+     * @property  elmodules
+     * array of modules to be created by which use #ID 
+     * @type {Array} of Roo.XComponent
+     */
+     
+    elmodules : [],
+
     
     /**
      * Register components to be built later.
@@ -157,12 +236,32 @@ Roo.apply(Roo.XComponent, {
      * * @param {Object} details about module
      */
     register : function(obj) {
+               
+               Roo.XComponent.event.fireEvent('register', obj);
+               switch(typeof(obj.disabled) ) {
+                       
+                       case 'undefined':
+                               break;
+                       
+                       case 'function':
+                               if ( obj.disabled() ) {
+                                       return;
+                               }
+                               break;
+                       default:
+                               if (obj.disabled) {
+                                       return;
+                               }
+                               break;
+               }
+               
         this.modules.push(obj);
          
     },
     /**
      * convert a string to an object..
-     * 
+     * eg. 'AAA.BBB' -> finds AAA.BBB
+
      */
     
     toObject : function(str)
@@ -170,11 +269,20 @@ Roo.apply(Roo.XComponent, {
         if (!str || typeof(str) == 'object') {
             return str;
         }
+        if (str.substring(0,1) == '#') {
+            return str;
+        }
+
         var ar = str.split('.');
         var rt, o;
         rt = ar.shift();
             /** eval:var:o */
-        eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
+        try {
+            eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
+        } catch (e) {
+            throw "Module not found : " + str;
+        }
+        
         if (o === false) {
             throw "Module not found : " + str;
         }
@@ -184,6 +292,7 @@ Roo.apply(Roo.XComponent, {
             }
             o = o[e];
         });
+        
         return o;
         
     },
@@ -195,16 +304,34 @@ Roo.apply(Roo.XComponent, {
      */
     preBuild : function ()
     {
-        
+        var _t = this;
         Roo.each(this.modules , function (obj)
         {
-            obj.parent = this.toObject(obj.parent);
+            var opar = obj.parent;
+            try { 
+                obj.parent = this.toObject(opar);
+            } catch(e) {
+                Roo.log("parent:toObject failed: " + e.toString());
+                return;
+            }
             
             if (!obj.parent) {
+                               Roo.debug && Roo.log("GOT top level module");
+                               Roo.debug && Roo.log(obj);
+                               obj.modules = new Roo.util.MixedCollection(false, 
+                    function(o) { return o.order + '' }
+                );
                 this.topModule = obj;
                 return;
             }
-            
+                       // parent is a string (usually a dom element name..)
+            if (typeof(obj.parent) == 'string') {
+                this.elmodules.push(obj);
+                return;
+            }
+            if (obj.parent.constructor != Roo.XComponent) {
+                Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
+            }
             if (!obj.parent.modules) {
                 obj.parent.modules = new Roo.util.MixedCollection(false, 
                     function(o) { return o.order + '' }
@@ -226,24 +353,31 @@ Roo.apply(Roo.XComponent, {
         var cmp = function(a,b) {   
             return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
         };
-        
-        if (!this.topModule || !this.topModule.modules) {
+        if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
             throw "No top level modules to build";
         }
-       
-        // make a flat list in order of modules to build.
-        var mods = [ this.topModule ];
         
+        // make a flat list in order of modules to build.
+        var mods = this.topModule ? [ this.topModule ] : [];
+               
+               // elmodules (is a list of DOM based modules )
+        Roo.each(this.elmodules,function(e) { mods.push(e) });
+
         
         // add modules to their parents..
         var addMod = function(m) {
-           // Roo.debug && Roo.log(m.modKey);
+                       Roo.debug && Roo.log("build Order: add: " + m.name);
             
             mods.push(m);
             if (m.modules) {
+                               Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
                 m.modules.keySort('ASC',  cmp );
+                               Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
+
                 m.modules.each(addMod);
-            }
+            } else {
+                               Roo.debug && Roo.log("build Order: no child modules");
+                       }
             // not sure if this is used any more..
             if (m.finalize) {
                 m.finalize.name = m.name + " (clean up) ";
@@ -251,8 +385,10 @@ Roo.apply(Roo.XComponent, {
             }
             
         }
-        this.topModule.modules.keySort('ASC',  cmp );
-        this.topModule.modules.each(addMod);
+        if (this.topModule) { 
+            this.topModule.modules.keySort('ASC',  cmp );
+            this.topModule.modules.each(addMod);
+        }
         return mods;
     },
     
@@ -277,12 +413,12 @@ Roo.apply(Roo.XComponent, {
         }
         
         
-        
+        var msg = "Building Interface...";
         // flash it up as modal - so we store the mask!?
         Roo.MessageBox.show({ title: 'loading' });
         Roo.MessageBox.show({
            title: "Please wait...",
-           msg: "Building Interface...",
+           msg: msg,
            width:450,
            progress:true,
            closable:false,
@@ -296,25 +432,31 @@ Roo.apply(Roo.XComponent, {
             if (!mods.length) {
                 Roo.debug && Roo.log('hide?');
                 Roo.MessageBox.hide();
-                _this.topModule.fireEvent('buildcomplete', _this.topModule);
-                return;    
+                Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
+                
+                // THE END...
+                return false;   
             }
             
             var m = mods.shift();
+            
+            
             Roo.debug && Roo.log(m);
-            if (typeof(m) == 'function') { // not sure if this is supported any more..
+            // not sure if this is supported any more.. - modules that are are just function
+            if (typeof(m) == 'function') { 
                 m.call(this);
                 return progressRun.defer(10, _this);
             } 
             
-            Roo.MessageBox.updateProgress(
-                (total  - mods.length)/total,  "Building Interface " + (total  - mods.length) + 
+            
+            msg = "Building Interface " + (total  - mods.length) + 
                     " of " + total + 
-                    (m.name ? (' - ' + m.name) : '')
-                    );
+                    (m.name ? (' - ' + m.name) : '');
+                       Roo.debug && Roo.log(msg);
+            Roo.MessageBox.updateProgress(  (total  - mods.length)/total, msg  );
             
          
-            
+            // is the module disabled?
             var disabled = (typeof(m.disabled) == 'function') ?
                 m.disabled.call(m.module.disabled) : m.disabled;    
             
@@ -323,45 +465,60 @@ Roo.apply(Roo.XComponent, {
                 return progressRun(); // we do not update the display!
             }
             
-            if (!m.parent) {
-                // it's a top level one..
-                var layoutbase = new Ext.BorderLayout(document.body, {
-               
-                    center: {
-                         titlebar: false,
-                         autoScroll:false,
-                         closeOnTab: true,
-                         tabPosition: 'top',
-                         //resizeTabs: true,
-                         alwaysShowTabs: true,
-                         minTabWidth: 140
-                    }
-                });
-                var tree = m.tree();
-                tree.region = 'center';
-                m.el = layoutbase.addxtype(tree);
-                m.panel = m.el;
-                m.layout = m.panel.layout;    
-                return progressRun.defer(10, _this);
-            }
-            
-            var tree = m.tree();
-            tree.region = tree.region || m.region;
-            m.el = m.parent.el.addxtype(tree);
-            m.fireEvent('built', m);
-            m.panel = m.el;
-            m.layout = m.panel.layout;    
-            progressRun.defer(10, _this); 
+            // now build 
             
+                       
+                       
+            m.render();
+            // it's 10 on top level, and 1 on others??? why...
+            return progressRun.defer(10, _this);
+             
         }
         progressRun.defer(1, _this);
      
         
         
-    }
-     
+    },
+       
+       
+       /**
+        * Event Object.
+        *
+        *
+        */
+       event: false, 
+    /**
+        * wrapper for event.on - aliased later..  
+        * Typically use to register a event handler for register:
+        *
+        * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
+        *
+        */
+    on : false
    
     
     
 });
+
+Roo.XComponent.event = new Roo.util.Observable({
+               events : { 
+                       /**
+                        * @event register
+                        * Fires when an Component is registered,
+                        * set the disable property on the Component to stop registration.
+                        * @param {Roo.XComponent} c the component being registerd.
+                        * 
+                        */
+                       'register' : true,
+                       /**
+                        * @event buildcomplete
+                        * Fires on the top level element when all elements have been built
+                        * @param {Roo.XComponent} the top level component.
+                        */
+                       'buildcomplete' : true
+                       
+               }
+});
+
+Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event); 
  
\ No newline at end of file