Panel.js

Ext.Panel = function(config){
    Ext.Panel.superclass.constructor.call(this, config);
};

Ext.extend(Ext.Panel, Ext.Container, {
    baseCls : 'x-panel',
    collapsedCls : 'x-panel-collapsed',
    elements : 'header,body,footer',
    maskDisabled: true,
    collapsed : false,
    animCollapse:Ext.enableFx,
    toolTarget : 'header',
    headerAsText:true,
    buttonAlign:'right',
    /**
     * @cfg {Number} minButtonWidth Minimum width of all buttons (defaults to 75)
     */
    minButtonWidth:75,

    initComponent : function(){
        Ext.Panel.superclass.initComponent.call(this);
        this.addEvents({
            bodyresize : true,
            titlechange: true,
            collapse : true,
            expand:true,
            beforecollapse : true,
            beforeexpand:true,

            // these 4 events are only fired if used within
            // a container that supports them
            beforeclose: true,
            close: true,
            activate: true,
            deactivate: true
        });

        // shortcuts
        if(this.tbar){
            this.elements += ',tbar';
            if(typeof this.tbar == 'object'){
                this.topToolbar = this.tbar;
            }
            delete this.tbar;
        }
        if(this.bbar){
            this.elements += ',bbar';
            if(typeof this.bbar == 'object'){
                this.bottomToolbar = this.bbar;
            }
            delete this.bbar;
        }

        if(this.buttons){
            var btns = this.buttons;
            delete this.buttons;
            for(var i = 0, len = btns.length; i < len; i++) {
                this.addButton(btns[i]);
            }
        }
    },

    // private, notify box this class will handle heights
    deferHeight:true,

    createElement : function(name, pnode){
        if(name !== 'bwrap' && this.elements.indexOf(name) == -1){
            return;
        }
        if(this[name]){
            pnode.appendChild(this[name].dom);
        }else{
            if(this[name+'Cfg']){
                this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
            }else{
                var el = document.createElement('div');
                el.className = this[name+'Cls'];
                this[name] = Ext.get(pnode.appendChild(el));
            }
        }
    },

    onRender : function(ct, position){
        Ext.Panel.superclass.onRender.call(this, ct, position);

        this.createClasses();

        if(this.el){ // existing markup
            this.header = this.el.down('.'+this.headerCls);
            this.bwrap = this.el.down('.'+this.bwrapCls);
            var cp = this.bwrap ? this.bwrap : this.el;
            this.tbar = cp.down('.'+this.tbarCls);
            this.body = cp.down('.'+this.bodyCls);
            this.bbar = cp.down('.'+this.bbarCls);
            this.footer = cp.down('.'+this.footerCls);
        }else{
            this.el = ct.createChild({
                id: this.id,
                cls: this.baseCls
            }, position);
        }
        var el = this.el, d = el.dom;
        if(this.cls){
            this.el.addClass(this.cls);
        }
        // This block allows for maximum flexibility and performance when using existing markup

        // framing requires special markup
        if(this.frame){
            el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));

            this.createElement('header', d.firstChild.firstChild.firstChild);
            this.createElement('bwrap', d);

            // append the mid and bottom frame to the bwrap
            var bw = this.bwrap.dom;
            var ml = d.childNodes[1], bl = d.childNodes[2];
            bw.appendChild(ml);
            bw.appendChild(bl);

            var mc = bw.firstChild.firstChild.firstChild;
            this.createElement('tbar', mc);
            this.createElement('body', mc);
            this.createElement('bbar', mc);
            this.createElement('footer', bw.lastChild.firstChild.firstChild);
        }else{
            this.createElement('header', d);
            this.createElement('bwrap', d);

            // append the mid and bottom frame to the bwrap
            var bw = this.bwrap.dom;
            this.createElement('tbar', bw);
            this.createElement('body', bw);
            this.createElement('bbar', bw);
            this.createElement('footer', bw);

            if(!this.header){
                this.body.addClass(this.bodyCls + '-noheader');
            }
        }

        this.bwrap.enableDisplayMode('block');

        if(this.header){
            this.header.unselectable();
        }

        if(this.iconCls){
            this.header.addClass('x-panel-icon '+this.iconCls);
        }

        if(this.ownerCt){
            this.el.addClass(this.baseCls + '-nested');
        }

        // for tools, we need to wrap any existing header markup
        if(this.header && this.headerAsText){
            this.header.dom.innerHTML =
                '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
        }
        if(this.floating){
            this.el = new Ext.Layer(
                typeof this.floating == 'object' ? this.floating : {
                    shadow:this.shadow||'sides', constrain:false, shim: this.shim === false ? false : undefined
                }, this.el
            );
        }
        if(this.collapsible){
            this.tools = this.tools || [];
            this.tools.unshift({
                id: 'toggle',
                on : {
                    'click' : this.toggleCollapse,
                    'scope': this
                }
            });
        }
        if(this.tools){
            var ts = this.tools;
            this.tools = {};
            this.addTool.apply(this, ts);
        }else{
            this.tools = {};
        }

        if(this.buttons && this.buttons.length > 0){
            // tables are required to maintain order and for correct IE layout
            var tb = this.footer.createChild({cls:'x-panel-btns-ct', cn: {
                cls:"x-panel-btns x-panel-btns-"+this.buttonAlign,
                html:'<table cellspacing="0"><tbody><tr></tr></tbody></table><div class="x-clear"></div>'
            }}, null, true);
            var tr = tb.getElementsByTagName('tr')[0];
            for(var i = 0, len = this.buttons.length; i < len; i++) {
                var b = this.buttons[i];
                var td = document.createElement('td');
                td.className = 'x-panel-btn-td';
                b.render(tr.appendChild(td));
            }
        }

        if(this.tbar && this.topToolbar){
            if(this.topToolbar instanceof Array){
                this.topToolbar = new Ext.Toolbar(this.topToolbar);
            }
            this.topToolbar.render(this.tbar);
        }
        if(this.bbar && this.bottomToolbar){
            if(this.bottomToolbar instanceof Array){
                this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
            }
            this.bottomToolbar.render(this.bbar);
        }
    },

    // must be called before rendering
    addButton : function(config, handler, scope){
        var bc = {
            handler: handler,
            scope: scope,
            minWidth: this.minButtonWidth,
            hideParent:true
        };
        if(typeof config == "string"){
            bc.text = config;
        }else{
            Ext.apply(bc, config);
        }
        var btn = new Ext.Button(null, bc);
        if(!this.buttons){
            this.buttons = [];
        }
        this.buttons.push(btn);
        return btn;
    },

    addTool : function(){
        if(!this.toolTemplate){
            // initialize the global tool template on first use
            var tt = new Ext.Template(
                 '<div class="x-tool x-tool-{id}">&#160</div>'
            );
            tt.disableFormats = true;
            tt.compile();
            Ext.Panel.prototype.toolTemplate = tt;
        }
        for(var i = 0, a = arguments, len = a.length; i < len; i++) {
            var tc = a[i];
            var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
            this.tools[tc.id] = t;
            t.enableDisplayMode('block');
            if(tc.on){
                t.on(tc.on);
            }
            if(tc.hidden){
                t.hide();
            }
            t.addClassOnOver('x-tool-'+tc.id+'-over');
        }
    },

    afterRender : function(){
        if(this.floating && !this.hidden && !this.initHidden){
            this.el.show();
        }
        if(this.title){
            this.setTitle(this.title);
        }
        if(this.autoScroll){
            this.body.dom.style.overflow = 'auto';
        }
        if(this.html){
            this.body.update(this.html);
            delete this.html;
        }
        if(this.contentEl){
            this.body.dom.appendChild(Ext.getDom(this.contentEl));
        }
        if(this.loadContent){
            this.load.defer(10, this, [this.loadContent]);
            delete this.loadContent;
        }
        if(this.collapsed){
            this.collapsed = false;
            this.collapse(false);
        }
        Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
        this.initEvents();
    },

    initEvents : function(){

    },

    beforeEffect : function(){
        if(this.floating){
            this.el.beforeAction();
        }
        if(Ext.isGecko){
            this.body.clip();
        }
    },

    afterEffect : function(){
        this.syncShadow();
        if(Ext.isGecko){
            this.body.unclip();
        }
    },

    // private - wraps up an animation param with internal callbacks
    createEffect : function(a, cb, scope){
        var o = {
            scope:scope,
            block:true
        };
        if(a === true){
            o.callback = cb;
            return o;
        }else if(!a.callback){
            o.callback = cb;
        }else { // wrap it up
            o.callback = function(){
                cb.call(scope);
                Ext.callback(a.callback, a.scope);
            };
        }
        return Ext.applyIf(o, a);
    },

    collapse : function(animate){
        if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
            return;
        }
        var a = animate === true || (animate !== false && this.animCollapse);
        this.beforeEffect();
        if(a){
            this.bwrap.slideOut('t', this.createEffect(a, this.afterCollapse, this));
        }else{
            this.bwrap.hide();
            this.afterCollapse();
        }
        return this;
    },

    afterCollapse : function(){
        this.collapsed = true;
        this.el.addClass(this.collapsedCls);
        this.afterEffect();
        this.fireEvent('collapse', this);
    },

    expand : function(animate){
        if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
            return;
        }
        var a = animate === true || (animate !== false && this.animCollapse);
        this.el.removeClass(this.collapsedCls);
        this.beforeEffect();
        if(a){
            this.bwrap.slideIn('t', this.createEffect(a, this.afterExpand, this));
        }else{
            this.bwrap.show();
            this.afterExpand();
        }
        return this;
    },

    afterExpand : function(){
        this.collapsed = false;
        this.afterEffect();
        this.fireEvent('expand', this);
    },

    toggleCollapse : function(animate){
        this[this.collapsed ? 'expand' : 'collapse'](animate);
        return this;
    },

    onDisable : function(){
        if(this.rendered && this.maskDisabled){
            this.el.mask();
        }
        Ext.Panel.superclass.onDisable.call(this);
    },

    onEnable : function(){
        if(this.rendered && this.maskDisabled){
            this.el.unmask();
        }
        Ext.Panel.superclass.onEnable.call(this);
    },

    onResize : function(w, h){
        if(w !== undefined || h !== undefined){
            if(typeof w == 'number'){
                this.body.setWidth(w - this.getFrameWidth());
            }else if(w == 'auto'){
                this.body.setWidth(w);
            }

            if(typeof h == 'number'){
                this.body.setHeight(h - this.getFrameHeight());
            }else if(h == 'auto'){
                this.body.setHeight(h);
            }
            this.syncShadow();
            this.fireEvent('bodyresize', this, w, h);
        }
    },

    onPosition : function(){
        this.syncShadow();
    },

    getFrameWidth : function(){
        var w = this.el.getFrameWidth('lr');

        if(this.frame){
            var l = this.bwrap.dom.firstChild;
            w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
            var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
            w += Ext.fly(mc).getFrameWidth('lr');
        }
        return w;
    },

    getFrameHeight : function(){
        var h  = this.el.getFrameWidth('tb');
        h += (this.tbar ? this.tbar.getHeight() : 0) +
             (this.bbar ? this.bbar.getHeight() : 0);

        if(this.frame){
            var hd = this.el.dom.firstChild;
            var ft = this.bwrap.dom.lastChild;
            h += (hd.offsetHeight + ft.offsetHeight);
            var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
            h += Ext.fly(mc).getFrameWidth('tb');
        }else{
            h += (this.header ? this.header.getHeight() : 0) +
                (this.footer ? this.footer.getHeight() : 0);
        }
        return h;
    },

    getInnerWidth : function(){
        return this.getSize().width - this.getFrameWidth();
    },

    getInnerHeight : function(){
        return this.getSize().height - this.getFrameHeight();
    },

    syncShadow : function(){
        if(this.floating){
            this.el.sync(true);
        }
    },

    getLayoutTarget : function(){
        return this.body;
    },

    setTitle : function(title){
        this.title = title;
        if(this.header && this.headerAsText){
            this.header.child('span').update(title);
            this.fireEvent('titlechange', this, title);
        }
        return this;
    },

    /**
     * Get the {@link Ext.UpdateManager} for this panel. Enables you to perform Ajax updates.
     * @return {Ext.UpdateManager} The UpdateManager
     */
    getUpdateManager : function(){
        return this.body.getUpdateManager();
    },

     /**
     * Loads this content panel immediately with content from XHR.
     * @param {Object/String/Function} config A config object containing any of the following options:
<pre><code>
panel.load({<br/>
    url: "your-url.php",<br/>
    params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
    callback: yourFunction,<br/>
    scope: yourObject, //(optional scope)  <br/>
    discardUrl: false, <br/>
    nocache: false,<br/>
    text: "Loading...",<br/>
    timeout: 30,<br/>
    scripts: false<br/>
});
</code></pre>
     * The only required property is url. The optional properties nocache, text and scripts
     * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
     * associated property on this panel UpdateManager instance.
     * @return {Ext.Panel} this
     */
    load : function(){
        var um = this.body.getUpdateManager();
        um.update.apply(um, arguments);
        return this;
    },

    beforeDestroy : function(){
        Ext.Element.uncache(
            this.header,
            this.tbar,
            this.bbar,
            this.footer,
            this.body
        );
    },

    createClasses : function(){
        this.headerCls = this.baseCls + '-header';
        this.headerTextCls = this.baseCls + '-header-text';
        this.bwrapCls = this.baseCls + '-bwrap';
        this.tbarCls = this.baseCls + '-tbar';
        this.bodyCls = this.baseCls + '-body';
        this.bbarCls = this.baseCls + '-bbar';
        this.footerCls = this.baseCls + '-footer';
    },

    createGhost : function(cls, useShim, preventAppend){
        var el = document.createElement('div');
        el.className = 'x-panel-ghost ' + (cls ? cls : '');
        if(this.header){
            el.appendChild(this.el.dom.firstChild.cloneNode(true));
        }
        Ext.fly(el.appendChild(document.createElement('ul'))).setSize(this.bwrap.getSize());
        if(!preventAppend){
            this.container.dom.appendChild(el);
        }
        if(useShim !== false && this.el.useShim !== false){
            var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
            layer.show();
            return layer;
        }else{
            return new Ext.Element(el);
        }
    }
});

Ext - Copyright © 2006-2007 Ext JS, LLC
All rights reserved.