ExtJs_ExtComponent基类解说

来源:互联网 发布:淘宝客服怎么返现 编辑:程序博客网 时间:2024/05/16 00:56

/**

 * Ext JS Library 3.3.0

 * @class Ext.Component

 * @extends Ext.util.Observable

 *

 *  Ext.Component是其他组件的基类,可以说是Ext.js框架里边最为基础的一个类。所有的子类组件都自动的参与Ext component的生命周期(lifecycle)中来,

包括其创建(creation),渲染(rendering)以及销毁(destruction),当然,这些是由Ext.Container类提供。

 *  在Ext.Comtainer创建的同时,可以通过的其items配置项来添加组件,除了这个方法,还可以通过Ext.Container的add方法动态地添加进容器里边。

 *  Component基类支持hide/show、enable/disable基本事件操作。所有的组件在构建的时候都被注册进Ext.ComponentMgr里边,所有可以随时随地的通过

Ext.getCmp("id")来访问里边的组件。

 *  每个组件都有唯一的xtype名称,可以通过getXType以及isXType来查看相关信息。

 */

 

 

 /**

 * @constructor

 * @param {Ext.Element/String/Object}

 *element: 内部元素,其id被作为组件id使用。

 *  

 *string: 字符串ID。

 * 

 *  Object: it is applied to the component

 */

Ext.Component = function(config){

    config = config || {};

    if(config.initialConfig){

        if(config.isAction){           // actions

            this.baseAction = config;

        }

        config = config.initialConfig; // component cloning / action set up

    }else if(config.tagName || config.dom || Ext.isString(config)){ // element object

        config = {applyTo: config, id: config.id || config};

    }

 

 

/**

     * 组件初始化配置说明 Read-only.

     * @type Object

     * @property initialConfig

     */

    this.initialConfig = config;

 

    Ext.apply(this, config);//LifeCycle_初始化Initialization_1、配置项对象生效 The config object is applied

 

    //注册事件

    this.addEvents(//LifeCycle_初始化Initialization_2、底层事件创建

 

/**

         * @event added

         * 当组件被添加到容器时触发。

         * Fires when a component is added to an Ext.Container

         * @param {Ext.Component} this 自身

         * @param {Ext.Container} ownerCt 组件拥有者,既容器 Container which holds the component

         * @param {number} index 索引(组件被添加到的位置) Position at which the component was added

         */

        'added',

 

/**

         * @event disable禁用

         * Fires after the component is disabled.

         * @param {Ext.Component} this

         */

        'disable',

 

/**

         * @event enable 激活

         * Fires after the component is enabled.

         * @param {Ext.Component} this

         */

        'enable',

 

/**

         * @event beforeshow

         * Fires before the component is shown by calling the show method.

         * Return false from an event handler to stop the show.

         * @param {Ext.Component} this

         */

        'beforeshow',

 

/**

         * @event show

         * Fires after the component is shown when calling the show method.

         * @param {Ext.Component} this

         */

        'show',

 

/**

         * @event beforehide

         * Fires before the component is hidden by calling the hide method.

         * Return false from an event handler to stop the hide.

         * @param {Ext.Component} this

         */

        'beforehide',

 

/**

         * @event hide

         * Fires after the component is hidden.

         * Fires after the component is hidden when calling the hide method.

         * @param {Ext.Component} this

         */

        'hide',

 

/**

         * @event removed移除组件

         * Fires when a component is removed from an Ext.Container

         * @param {Ext.Component} this

         * @param {Ext.Container} ownerCt Container which holds the component

         */

        'removed',

 

/**

         * @event beforerender

         * Fires before the component is rendered. Return false from an

         * event handler to stop the render.

         * @param {Ext.Component} this

         */

        'beforerender',

 

/**

         * @event render

         * Fires after the component markup is rendered.

         * @param {Ext.Component} this

         */

        'render',

 

/**

         * @event afterrender

* Fires after the component rendering is finished.

         * @param {Ext.Component} this

         */

        'afterrender',

 

/**

         * @event beforedestroy

         * Fires before the component is destroyed. Return false from an event handler to stop the destroy.

         * @param {Ext.Component} this

         */

        'beforedestroy',

 

/**

         * @event destroy

         * Fires after the component is destroyed.

         * @param {Ext.Component} this

         */

        'destroy',

 

/**

         * @event beforestaterestore 恢复状态之前

         * Fires before the state of the component is restored. Return false from an event handler to stop the restore.

         * @param {Ext.Component} this

         * @param {Object} state 

         */

        'beforestaterestore',

 

/**

         * @event staterestore 恢复状态

         * Fires after the state of the component is restored.

         * @param {Ext.Component} this

         * @param {Object} state

         */

        'staterestore',

 

/**

         * @event beforestatesave

         * Fires before the state of the component is saved to the configured state provider. Return false to stop the save.

         * @param {Ext.Component} this

         * @param {Object} state The hash of state values(状态哈希值).

         * 可以通过getState()得到组件的状态

         */

        'beforestatesave',

 

/**

         * @event statesave

         * Fires after the state of the component is saved to the configured state provider.

         * @param {Ext.Component} this

         * @param {Object} state 

         */

        'statesave'

    );

    this.getId();

    Ext.ComponentMgr.register(this);//LifeCycle_初始化Initialization_3、在组件管理器里登记组件

    Ext.Component.superclass.constructor.call(this);

 

    if(this.baseAction){

        this.baseAction.addComponent(this);

    }

 

    this.initComponent();

 

    if(this.plugins){//LifeCycle_初始化Initialization_4、加载插件

        if(Ext.isArray(this.plugins)){

            for(var i = 0, len = this.plugins.length; i < len; i++){//遍历所有插件

                this.plugins[i] = this.initPlugin(this.plugins[i]);

            }

        }else{

            this.plugins = this.initPlugin(this.plugins);

        }

    }

 

    if(this.stateful !== false){ //LifeCycle_初始化Initialization_5、状态感知进行初始化

        this.initState();

    }

 

    if(this.applyTo){//LifeCycle_初始化Initialization_6、渲染插件

        this.applyToMarkup(this.applyTo);

        delete this.applyTo;

    }else if(this.renderTo){

        this.render(this.renderTo);

        delete this.renderTo;

    }

};//end of Ext.Component

 

// private 

Ext.Component.AUTO_ID = 1000;

 

Ext.extend(Ext.Component, Ext.util.Observable, {//Ext.Component继承于Ext.util.Observable

//当FormLayout渲染时,下面的这些配置可以被用作所有组件。

    // Configs below are used for all Components when rendered by FormLayout.

 

/**

     * @cfg {String} fieldLabel 标签名称

* The label text to display next to this Component (defaults to ''_默认为空).

     * 特别说明:只用使用form布局时,标签名称才会显示。

* Note: this config is only used when this Component is rendered by a Container which

     * has been configured to use the Ext.layout.FormLayout layout manager (e.g.

     * Ext.form.FormPanel or specifying layout:'form').

     * 

* @cfg {Boolean} hideLabel 

* 如果为true,则不显示fieldLabel,如果为false则反之。

     * Example use:

new Ext.FormPanel({

   height: 100,

   renderTo: Ext.getBody(),

   items: [{

       xtype: 'textfield',

       fieldLabel: 'Name'

   }]

});

new Ext.FormPanel({

   height: 100,

   renderTo: Ext.getBody(),

   items: [{

       xtype: 'textfield'

       hideLabel: true

   }]

});

     */

 

/**

     * @cfg {String} labelStyle 标签样式

* Note: see the note for clearCls.

     * Example use:

new Ext.FormPanel({

   height: 100,

   renderTo: Ext.getBody(),

   items: [{

       xtype: 'textfield',

       fieldLabel: 'Name',

       labelStyle: 'font-weight:bold;'

   }]

});

     */

 

/**

     * @cfg {String} labelSeparator 标签分隔符

     * labelSeparator defaults to colon ':'

* Note: see the note for {@link #clearCls}.

     * Example use:

new Ext.FormPanel({

   height: 100,

   renderTo: Ext.getBody(),

   layoutConfig: {

       labelSeparator: '~' 

   },

   labelSeparator: '>>',     // 直接给容器配置的级别比布局配置(layout config)级别高,故Field2 显示的是'>>'

   items: [{

       xtype: 'textfield',

       fieldLabel: 'Field 1',

       labelSeparator: '...'

   },{

       xtype: 'textfield',

       fieldLabel: 'Field 2'

   }]

});

* @cfg {Ext.Template} fieldTpl 

     * Example use:

     new Ext.Template(

   '<div class="x-form-item {itemCls}" tabIndex="-1">',

       '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',

       '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',

       '</div><div class="{clearCls}"></div>',

   '</div>'

);

     */

 

/**

     * @cfg {Boolean} hideLabel 

* Note: see the note for clearCls.

     * Example use:

new Ext.FormPanel({

   height: 100,

   renderTo: Ext.getBody(),

   items: [{

       xtype: 'textfield'

       hideLabel: true

   }]

});

     */

 

/**

     * @cfg {String} clearCls 

* Note: 只有使用form布局的才能起作用。

     */

 

/**

     * @cfg {String} itemCls

* Note: 只有使用form布局的才能起作用。

     * Example use:

// Apply a style to the field's label:

<style>

   .required .x-form-item-label {font-weight:bold;color:red;}

</style>

new Ext.FormPanel({

   height: 100,

   renderTo: Ext.getBody(),

   items: [{

       xtype: 'textfield',

       fieldLabel: 'Name',

       itemCls: 'required' //this label will be styled

   },{

       xtype: 'textfield',

       fieldLabel: 'Favorite Color'

   }]

});

     */

 

 

/**

     * @cfg {String} id

     */

 

/**

     * @cfg {String} itemId

     * Example use:

var c = new Ext.Panel({

   height: 300,

   renderTo: document.body,

   layout: 'auto',

   items: [

       {

           itemId: 'p1',

           title: 'Panel 1',

           height: 150

       },

       {

           itemId: 'p2',

           title: 'Panel 2',

           height: 150

       }

   ]

})

p1 = c.getComponent('p1'); // not the same as Ext.getCmp()

p2 = p1.ownerCt.getComponent('p2'); 

     * 

     */

 

/**

     * @cfg {String} xtype

     */

 

/**

     * @cfg {String} ptype

     */

 

/**

     * @cfg {String} cls

     * An optional extra CSS class that will be added to this component's Element (defaults to '').

     */

 

/**

     * @cfg {String} overCls

     * An optional extra CSS class that will be added to this component's Element when the mouse moves

     * over the Element, and removed when the mouse moves out. (defaults to '').  

 

/**

     * @cfg {String} style

     * Example use:

new Ext.Panel({

   title: 'Some Title',

   renderTo: Ext.getBody(),

   width: 400, height: 300,

   layout: 'form',

   items: [{

       xtype: 'textarea',

       style: {

           width: '95%',

           marginBottom: '10px'

       }

   },

       new Ext.Button({

           text: 'Send',

           minWidth: '100',

           style: {

               marginBottom: '10px'

           }

       })

   ]

});

     */

 

/**

     * @cfg {String} ctCls

* An optional extra CSS class that will be added to this component's container. 

* Note: ctCls defaults to '' except for(除了...之外) the following class

     */

 

/**

     * @cfg {Boolean} disabled 是否禁用

     * Render this component disabled (default is false).

     */

    disabled : false,

 

/**

     * @cfg {Boolean} hidden 是否隐藏

     * Render this component hidden (default is false). If true, the

     * hide method will be called internally(内部地).

     */

    hidden : false,

 

/**

     * @cfg {Object/Array} plugins 插件

     * An object or array of objects that will provide custom functionality for this component.

     */

 

/**

     * @cfg {Mixed} applyTo 渲染之地

     */

 

/**

     * @cfg {Mixed} renderTo

     */

 

/**

     * @cfg {Boolean} stateful

Ext.state.Manager.setProvider(new Ext.state.CookieProvider({

   expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now

}));

     */

 

/**

     * @cfg {String} stateId

     */

 

/**

     * @cfg {Array} stateEvents

     */

 

/**

     * @cfg {Mixed} autoEl

     * Example usage:

{

   xtype: 'box',

   autoEl: {

       tag: 'img',

       src: 'http://www.example.com/example.jpg'

   }

}, {

   xtype: 'box',

   autoEl: {

       tag: 'blockquote',

       html: 'autoEl is cool!'

   }

}, {

   xtype: 'container',

   autoEl: 'ul',

   cls: 'ux-unordered-list',

   items: {

       xtype: 'box',

       autoEl: 'li',

       html: 'First list item'

   }

}

     */

    autoEl : 'div',

 

 

/**

     * @cfg {String} disabledClass

     * CSS class added to the component when it is disabled (defaults to 'x-item-disabled').

     */

    disabledClass : 'x-item-disabled',

 

/**

     * @cfg {Boolean} allowDomMove

     * Whether the component can move the Dom node when rendering (defaults to true).

     */

    allowDomMove : true,

 

/**

     * @cfg {Boolean} autoShow

     */

    autoShow : false,

 

/**

     * @cfg {String} hideMode

* 'visibility' 'offsets' and 'display'

     */

    hideMode : 'display',

 

/**

     * @cfg {Boolean} hideParent

     */

    hideParent : false,

 

/**

new Ext.Panel({

   title: 'The Clickable Panel',

   listeners: {

       render: function(p) {

           p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));

       },

       single: true  // Remove the listener after first invocation

   }

});

     * @type Ext.Element

     * @property el

     */

 

/**

     * True if this component has been rendered. Read-only.

     * @type Boolean

     * @property rendered

     */

    rendered : false,

 

 

/**

     * @cfg {String} contentEl

     */

 

/**

     * @cfg {String/Object} html

     */

 

 

/**

     * @cfg {Mixed} tpl

     */

 

 

/**

     * @cfg {String} tplWriteMode The Ext.(X)Template method to use when

     * updating the content area of the Component. Defaults to 'overwrite'

     */

    tplWriteMode : 'overwrite',

 

 

/**

     * @cfg {Mixed} data

     */

 

 

/**

     * @cfg {Array} bubbleEvents

     */

    bubbleEvents: [],

 

 

    // private

    ctype : 'Ext.Component',

 

    // private

    actionMode : 'el',

 

    // private

    getActionEl : function(){

        return this[this.actionMode];

    },

 

    initPlugin : function(p){

        if(p.ptype && !Ext.isFunction(p.init)){

            p = Ext.ComponentMgr.createPlugin(p);

        }else if(Ext.isString(p)){

            p = Ext.ComponentMgr.createPlugin({

                ptype: p

            });

        }

        p.init(this);

        return p;

    },

 

    /* // protected

     * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).

     * 

 

 

// Traditional constructor:

Ext.Foo = function(config){

    // call superclass constructor:

    Ext.Foo.superclass.constructor.call(this, config);

 

    this.addEvents({

        // add events

    });

};

Ext.extend(Ext.Foo, Ext.Bar, {

   // class body

}

 

// initComponent replaces the constructor:

Ext.Foo = Ext.extend(Ext.Bar, {

    initComponent : function(){

        // call superclass initComponent

        Ext.Foo.superclass.initComponent.call(this);

 

        this.addEvents({

            // add events

        });

    }

}

     */

 

    initComponent : function(){

        /*

         * this is double processing, however it allows people to be able to do

         * Ext.apply(this, {

         *     listeners: {

         *         //here

         *     }

         * });

         * MyClass.superclass.initComponent.call(this);

         */

        if(this.listeners){

            this.on(this.listeners);

            delete this.listeners;

        }

        this.enableBubble(this.bubbleEvents);

    },

 

 

/**

     * 渲染

* Render this Component into the passed HTML element.

     * 

* If you are using a Container object to house this Component, then

     * do not use the render method.

     * 

* A Container's child Components are rendered by that Container's

     * layout manager when the Container is first rendered.

     * 

* Certain(肯定的) layout managers allow dynamic addition of child components. Those that do

     * include CardLayout, AnchorLayout, FormLayout, TableLayout.

     * 

* If the Container is already rendered when a new child Component is added, you may need to call

     * the Container's doLayout to refresh the view which causes any

     * unrendered child Components to be rendered. This is required so that you can add multiple

     * child components if needed while only refreshing the layout once.

     * 

* When creating complex(复合的) UIs, it is important to remember that sizing and positioning

     * of child items is the responsibility(责任) of the Container's layout manager.

     * If you expect child items to be sized in response to user interactions, you must

     * configure the Container with a layout manager which creates and manages the type of layout you

     * have in mind.

     * 

* Omitting(省略) the Container's layout config means that a basic

     * layout manager is used which does nothing but render child components sequentially into the

     * Container. No sizing or positioning will be performed in this situation.

*

     * @param {Element/HTMLElement/String} container (optional) The element this Component should be

     * rendered into. If it is being created from existing markup, this should be omitted.

     * @param {String/Number} position (optional) The element ID or DOM node index within the container before

     * which this component will be inserted (defaults to appending to the end of the container)

     */

    render : function(container, position){ //LifeCycle_渲染过程 Rendering

    //LifeCycle_渲染过程 Rendering_1、触发beforerender事件

        if(!this.rendered && this.fireEvent('beforerender', this) !== false){ 

        //LifeCycle_渲染过程 Rendering_2、设置容器

            if(!container && this.el){

                this.el = Ext.get(this.el);

                container = this.el.dom.parentNode;

                this.allowDomMove = false;

            }

            this.container = Ext.get(container);

            if(this.ctCls){

                this.container.addClass(this.ctCls);//给容器添加样式。

            }

            this.rendered = true; //标志已经渲染。

            if(position !== undefined){

                if(Ext.isNumber(position)){

                    position = this.container.dom.childNodes[position];

                }else{

                    position = Ext.getDom(position);

                }

            }

            //LifeCycle_渲染过程 Rendering_3、调用onRender方法

            this.onRender(this.container, position || null);

            //LifeCycle_渲染过程 Rendering_4、组件是“隐藏”状态的

            if(this.autoShow){

                this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);

            }

            //LifeCycle_渲染过程 Rendering_5、自定义的类、样式生效了

            if(this.cls){

                this.el.addClass(this.cls);

                delete this.cls;

            }

            if(this.style){

                this.el.applyStyles(this.style);

                delete this.style;

            }

            if(this.overCls){//鼠标动作样式

                this.el.addClassOnOver(this.overCls);

            }

            //LifeCycle_渲染过程 Rendering_6、触发render事件

            this.fireEvent('render', this);

 

 

            // Populate content of the component with html, contentEl or a tpl.

            var contentTarget = this.getContentTarget();

            if (this.html){

                contentTarget.update(Ext.DomHelper.markup(this.html));

                delete this.html;

            }

            if (this.contentEl){

                var ce = Ext.getDom(this.contentEl);

                Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);

                contentTarget.appendChild(ce);

            }

            if (this.tpl) {

                if (!this.tpl.compile) {

                    this.tpl = new Ext.XTemplate(this.tpl);

                }

                if (this.data) {

                    this.tpl[this.tplWriteMode](contentTarget, this.data);

                    delete this.data;

                }

            }

            //LifeCycle_渲染过程 Rendering_7、调用了afterRender方法

            this.afterRender(this.container);

 

            //LifeCycle_渲染过程 Rendering_8、组件被隐藏或禁用

            if(this.hidden){

                // call this so we don't fire initial hide events.

                this.doHide();

            }

            if(this.disabled){

                // pass silent so the event doesn't fire the first time.

                this.disable(true);

            }

 

            //LifeCycle_渲染过程 Rendering_9、所有状态感知的事件初始化

            if(this.stateful !== false){

                this.initStateEvents();

            }

            this.fireEvent('afterrender', this);

        }

        return this;

    },

 

 

 

/**

     * Update the content area of a component.

     * @param {Mixed} htmlOrData

     * If this component has been configured with a template via the tpl config

     * then it will use this argument as data to populate the template.

     * If this component was not configured with a template, the components

     * content area will be updated via Ext.Element update

     * @param {Boolean} loadScripts

     * (optional) Only legitimate(合情合理的) when using the html configuration. Defaults to false

     * @param {Function} callback

     * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading

     */

    update: function(htmlOrData, loadScripts, cb) {

        var contentTarget = this.getContentTarget();

        if (this.tpl && typeof htmlOrData !== "string") {

            this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});

        } else {

            var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;

            contentTarget.update(html, loadScripts, cb);

        }

    },

 

 

    /**

     * @private

     * Method to manage awareness(能力) of when components are added to their

     * respective(涉及到的) Container, firing an added event.

     * References are established(被证实的) at add time rather than at render time.

     * @param {Ext.Container} container Container which holds the component

     * @param {number} pos Position at which the component was added

     */

    onAdded : function(container, pos) {

        this.ownerCt = container;

        this.initRef();

        this.fireEvent('added', this, container, pos);

    },

 

    /**

     * @private

     * Method to manage awareness of when components are removed from their

     * respective Container, firing an removed event. References are properly

     * cleaned up after removing a component from its owning container.

     */

    onRemoved : function() {

        this.removeRef();

        this.fireEvent('removed', this, this.ownerCt);

        delete this.ownerCt;

    },

 

    /**

     * @private

     * Method to establish(指定) a reference to a component.

     */

    initRef : function() {

/**

         * @cfg {String} ref

         * Example use:

var myGrid = new Ext.grid.EditorGridPanel({

   title: 'My EditorGridPanel',

   store: myStore,

   colModel: myColModel,

   tbar: [{

       text: 'Save',

       handler: saveChanges,

       disabled: true,

       ref: '../saveButton'

   }],

   listeners: {

       afteredit: function() {

// The button reference is in the GridPanel

           myGrid.saveButton.enable();

       }

   }

});

         * 

         */

        if(this.ref && !this.refOwner){

            var levels = this.ref.split('/'),

                last = levels.length,

                i = 0,

                t = this;

 

            while(t && i < last){

                t = t.ownerCt;

                ++i;

            }

            if(t){

                t[this.refName = levels[--i]] = this;

 

/**

                 * @type Ext.Container

                 * @property refOwner

                 */

                this.refOwner = t;

            }

        }

    },

 

    removeRef : function() {

        if (this.refOwner && this.refName) {

            delete this.refOwner[this.refName];

            delete this.refOwner;

        }

    },

 

    // private

    initState : function(){

        if(Ext.state.Manager){

            var id = this.getStateId();

            if(id){

                var state = Ext.state.Manager.get(id);

                if(state){

                    if(this.fireEvent('beforestaterestore', this, state) !== false){

                        this.applyState(Ext.apply({}, state));

                        this.fireEvent('staterestore', this, state);

                    }

                }

            }

        }

    },

 

    // private

    getStateId : function(){

        return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);

    },

 

    // private

    initStateEvents : function(){

        if(this.stateEvents){

            for(var i = 0, e; e = this.stateEvents[i]; i++){

                this.on(e, this.saveState, this, {delay:100});

            }

        }

    },

 

    // private

    applyState : function(state){

        if(state){

            Ext.apply(this, state);

        }

    },

 

    // private

    getState : function(){

        return null;

    },

 

    // private

    saveState : function(){

        if(Ext.state.Manager && this.stateful !== false){

            var id = this.getStateId();

            if(id){

                var state = this.getState();

                if(this.fireEvent('beforestatesave', this, state) !== false){

                    Ext.state.Manager.set(id, state);

                    this.fireEvent('statesave', this, state);

                }

            }

        }

    },

 

 

/**

     * Apply this component to existing markup that is valid. With this function, no call to render() is required.

     * @param {String/HTMLElement} el

     */

    applyToMarkup : function(el){

        this.allowDomMove = false;

        this.el = Ext.get(el);

        this.render(this.el.dom.parentNode);

    },

 

 

/**

     * Adds a CSS class to the component's underlying element.

     * @param {string} cls The CSS class name to add

     * @return {Ext.Component} this

     */

    addClass : function(cls){

        if(this.el){

            this.el.addClass(cls);

        }else{

            this.cls = this.cls ? this.cls + ' ' + cls : cls;

        }

        return this;

    },

 

 

/**

     * Removes a CSS class from the component's underlying element.

     * @param {string} cls The CSS class name to remove

     * @return {Ext.Component} this

     */

    removeClass : function(cls){

        if(this.el){

            this.el.removeClass(cls);

        }else if(this.cls){

            this.cls = this.cls.split(' ').remove(cls).join(' ');

        }

        return this;

    },

 

    // private

    // default function is not really useful

    onRender : function(ct, position){

        if(!this.el && this.autoEl){

            if(Ext.isString(this.autoEl)){

                this.el = document.createElement(this.autoEl);

            }else{

                var div = document.createElement('div');

                Ext.DomHelper.overwrite(div, this.autoEl);

                this.el = div.firstChild;

            }

            if (!this.el.id) {

                this.el.id = this.getId();

            }

        }

        if(this.el){

            this.el = Ext.get(this.el);

            if(this.allowDomMove !== false){

                ct.dom.insertBefore(this.el.dom, position);

                if (div) {

                    Ext.removeNode(div);

                    div = null;

                }

            }

        }

    },

 

    // private

    getAutoCreate : function(){

        var cfg = Ext.isObject(this.autoCreate) ?

                      this.autoCreate : Ext.apply({}, this.defaultAutoCreate);

        if(this.id && !cfg.id){

            cfg.id = this.id;

        }

        return cfg;

    },

 

    // private

    afterRender : Ext.emptyFn,

 

 

/**

     * Destroys this component by purging(清除) any event listeners, removing the component's element from the DOM,

     * removing the component from its Container (if applicable) and unregistering it from

     * ComponentMgr.  Destruction is generally handled automatically by the framework and this method

     * should usually not need to be called directly.

     *

     */

    destroy : function(){ //LifeCycle_销毁过程 Destruction

        if(!this.isDestroyed){

        //LifeCycle_销毁过程 Destruction_1、触发beforedestroy事件

            if(this.fireEvent('beforedestroy', this) !== false){

                this.destroying = true;

                //LifeCycle_销毁过程 Destruction_2、调用了beforeDestroy方法

                this.beforeDestroy();

                //LifeCycle_销毁过程 Destruction_3、元素及其侦听器被移除

                if(this.ownerCt && this.ownerCt.remove){

                    this.ownerCt.remove(this, false);

                }

                if(this.rendered){

                    this.el.remove();

                    if(this.actionMode == 'container' || this.removeMode == 'container'){

                        this.container.remove();

                    }

                }

                // Stop any buffered tasks

                if(this.focusTask && this.focusTask.cancel){

                    this.focusTask.cancel();

                }

                //LifeCycle_销毁过程 Destruction_4、调用了onDestroy方法

                this.onDestroy();

                //LifeCycle_销毁过程 Destruction_5、在组件管理器中撤销组件对象的登记

                Ext.ComponentMgr.unregister(this);

                //LifeCycle_销毁过程 Destruction_6、触发destroy事件

                this.fireEvent('destroy', this);

                //LifeCycle_销毁过程 Destruction_7、组件上的事件侦听器被移除

                this.purgeListeners();

                this.destroying = false;

                this.isDestroyed = true;

            }

        }

    },

 

    deleteMembers : function(){

        var args = arguments;

        for(var i = 0, len = args.length; i < len; ++i){

            delete this[args[i]];

        }

    },

 

    // private

    beforeDestroy : Ext.emptyFn,

 

    // private

    onDestroy  : Ext.emptyFn,

 

 

/**

     * Example use: 

new Ext.Panel({

   title: 'The Clickable Panel',

   listeners: {

       render: function(p) {

           p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));

       },

       single: true  // Remove the listener after first invocation

   }

});

     * @return {Ext.Element} The Element which encapsulates this Component.

     */

    getEl : function(){

        return this.el;

    },

 

    // private

    getContentTarget : function(){

        return this.el;

    },

 

 

/**

     * @return {String} id

     */

    getId : function(){

        return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));

    },

 

 

/**

     * Returns the itemId of this component.

     * @return {String}

     */

    getItemId : function(){

        return this.itemId || this.getId();

    },

 

 

/**

     * Try to focus this component.

     * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component

     * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)

     * @return {Ext.Component} this

     */

    focus : function(selectText, delay){

        if(delay){

            this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);

            this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);

            return this;

        }

        if(this.rendered && !this.isDestroyed){

            this.el.focus();

            if(selectText === true){

                this.el.dom.select();

            }

        }

        return this;

    },

 

    // private

    blur : function(){

        if(this.rendered){

            this.el.blur();

        }

        return this;

    },

 

 

/**

     * Disable this component and fire the 'disable' event.

     * @return {Ext.Component} this

     */

    disable : function(/* private */ silent){

        if(this.rendered){

            this.onDisable();

        }

        this.disabled = true;

        if(silent !== true){

            this.fireEvent('disable', this);

        }

        return this;

    },

 

    // private

    onDisable : function(){

        this.getActionEl().addClass(this.disabledClass);

        this.el.dom.disabled = true;

    },

 

 

/**

     * Enable this component and fire the 'enable' event.

     * @return {Ext.Component} this

     */

    enable : function(){

        if(this.rendered){

            this.onEnable();

        }

        this.disabled = false;

        this.fireEvent('enable', this);

        return this;

    },

 

    // private

    onEnable : function(){

        this.getActionEl().removeClass(this.disabledClass);

        this.el.dom.disabled = false;

    },

 

 

/**

     * Convenience(公共) function for setting disabled/enabled by boolean.

     * @param {Boolean} disabled

     * @return {Ext.Component} this

     */

    setDisabled : function(disabled){

        return this[disabled ? 'disable' : 'enable']();

    },

 

 

/**

     * Show this component.  Listen to the beforeshow event and return

     * false to cancel showing the component.  Fires the show 

     * event after showing the component.

     * @return {Ext.Component} this

     */

    show : function(){

        if(this.fireEvent('beforeshow', this) !== false){

            this.hidden = false;

            if(this.autoRender){

                this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);

            }

            if(this.rendered){

                this.onShow();

            }

            this.fireEvent('show', this);

        }

        return this;

    },

 

    // private

    onShow : function(){

        this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);

    },

 

 

/**

     * Hide this component.  Listen to the beforehide event and return

     * false to cancel hiding the component.  Fires the hide 

     * event after hiding the component. Note this method is called internally if

     * the component is configured to be hidden.

     * @return {Ext.Component} this

     */

    hide : function(){

        if(this.fireEvent('beforehide', this) !== false){

            this.doHide();

            this.fireEvent('hide', this);

        }

        return this;

    },

 

    // private

    doHide: function(){

        this.hidden = true;

        if(this.rendered){

            this.onHide();

        }

    },

 

    // private

    onHide : function(){

        this.getVisibilityEl().addClass('x-hide-' + this.hideMode);

    },

 

    // private

    getVisibilityEl : function(){

        return this.hideParent ? this.container : this.getActionEl();

    },

 

 

/**

     * Convenience function to hide or show this component by boolean.

     * @param {Boolean} visible True to show, false to hide

     * @return {Ext.Component} this

     */

    setVisible : function(visible){

        return this[visible ? 'show' : 'hide']();

    },

 

 

/**

     * Returns true if this component is visible.

     * @return {Boolean} True if this component is visible, false otherwise.

     */

    isVisible : function(){

        return this.rendered && this.getVisibilityEl().isVisible();

    },

 

 

/**

     * Clone the current component using the original(原始的) config values passed into this instance by default.

     * @param {Object} overrides A new config containing any properties to override in the cloned version.

     * An id property can be passed on this object, otherwise(否则) one will be generated to avoid duplicates.

     * @return {Ext.Component} clone(复制) The cloned copy of this component

     */

    cloneConfig : function(overrides){

        overrides = overrides || {};

        var id = overrides.id || Ext.id();

        var cfg = Ext.applyIf(overrides, this.initialConfig);

        cfg.id = id; // prevent dup id

        return new this.constructor(cfg);

    },

 

 

/**

     * Gets the xtype for this component as registered with Ext.ComponentMgr. For a list of all

     * available xtypes, see the Ext.Component header. 

     * Example usage:

var t = new Ext.form.TextField();

alert(t.getXType());  // alerts 'textfield'

     * @return {String} The xtype

     */

    getXType : function(){

        return this.constructor.xtype;

    },

 

 

/**

* Example usage:

var t = new Ext.form.TextField();

var isText = t.isXType('textfield');        // true

var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent

var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance

     * @param {String/Ext.Component/Class} xtype The xtype to check for this Component.

     * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is

     * the default), or true to check whether this Component is directly of the specified xtype.

     * @return {Boolean} True if this component descends from the specified xtype, false otherwise.

     */

    isXType : function(xtype, shallow){

        //assume(假设) a string by default

        if (Ext.isFunction(xtype)){

            xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component

        }else if (Ext.isObject(xtype)){

            xtype = xtype.constructor.xtype; //handle being passed an instance

        }

 

        return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;

    },

 

 

/**

* Example usage:

var t = new Ext.form.TextField();

alert(t.getXTypes());  // alerts 'component/box/field/textfield'

     * @return {String} The xtype hierarchy(等级) string

     */

    getXTypes : function(){

        var tc = this.constructor;

        if(!tc.xtypes){

            var c = [], sc = this;

            while(sc && sc.constructor.xtype){

                c.unshift(sc.constructor.xtype);

                sc = sc.constructor.superclass;

            }

            tc.xtypeChain = c;

            tc.xtypes = c.join('/');

        }

        return tc.xtypes;

    },

 

 

/**

     * @param {Function} fn   The custom function(自定义函数) to call with the arguments (container, this component).

     * @return {Ext.Container} The first Container for which the custom function returns true

     */

    findParentBy : function(fn) {

        for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);

        return p || null;

    },

 

 

/**

     * @param {String/Ext.Component/Class} xtype The xtype to check for this Component. 

     * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is

     * the default), or true to check whether this Component is directly of the specified xtype.

     * @return {Ext.Container} The first Container which matches the given xtype or class

     */

    findParentByType : function(xtype, shallow){

        return this.findParentBy(function(c){

            return c.isXType(xtype, shallow);

        });

    },

 

 

/**

     * @param {Function} fn The function to call

     * @param {Object} scope (optional) The scope of the function (defaults to current node)

     * @param {Array} args (optional) The args to call the function with (default to passing the current component)

     * @return {Ext.Component} this

     */

    bubble : function(fn, scope, args){ //bubble冒泡

        var p = this;

        while(p){

            if(fn.apply(scope || p, args || [p]) === false){

                break;

            }

            p = p.ownerCt;

        }

        return this;

    },

 

    // protected

    getPositionEl : function(){

        return this.positionEl || this.el;

    },

 

    // private

    purgeListeners : function(){

        Ext.Component.superclass.purgeListeners.call(this);

        if(this.mons){

            this.on('beforedestroy', this.clearMons, this, {single: true});

        }

    },

 

    // private

    clearMons : function(){

        Ext.each(this.mons, function(m){

            m.item.un(m.ename, m.fn, m.scope);

        }, this);

        this.mons = [];

    },

 

    // private

    createMons: function(){

        if(!this.mons){

            this.mons = [];

            this.on('beforedestroy', this.clearMons, this, {single: true});

        }

    },

 

 

/**

     * Usage:

myGridPanel.mon(myGridPanel.getSelectionModel(), 'selectionchange', handleSelectionChange, null, {buffer: 50});

or:

myGridPanel.mon(myGridPanel.getSelectionModel(), {

   selectionchange: handleSelectionChange,

   buffer: 50

});

 

     * @param {Observable|Element} item The item to which to add a listener/listeners.

     * @param {Object|String} ename The event name, or an object containing event name properties.

     * @param {Function} fn Optional. If the ename parameter was an event name, this

     * is the handler function.

     * @param {Object} scope Optional. If the ename parameter was an event name, this

     * is the scope (this reference) in which the handler function is executed.

     * @param {Object} opt Optional. If the ename parameter was an event name, this

     * is the addListener options.

     */

    mon : function(item, ename, fn, scope, opt){

        this.createMons();

        if(Ext.isObject(ename)){

            var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;

 

            var o = ename;

            for(var e in o){

                if(propRe.test(e)){

                    continue;

                }

                if(Ext.isFunction(o[e])){

                    // shared options

                    this.mons.push({

                        item: item, ename: e, fn: o[e], scope: o.scope

                    });

                    item.on(e, o[e], o.scope, o);

                }else{

                    // individual(独特的) options

                    this.mons.push({

                        item: item, ename: e, fn: o[e], scope: o.scope

                    });

                    item.on(e, o[e]);

                }

            }

            return;

        }

 

        this.mons.push({

            item: item, ename: ename, fn: fn, scope: scope

        });

        item.on(ename, fn, scope, opt);

    },

 

 

/**

     * Removes listeners that were added by the mon method.

     * @param {Observable|Element} item The item from which to remove a listener/listeners.

     * @param {Object|String} ename The event name, or an object containing event name properties.

     * @param {Function} fn Optional. If the ename parameter was an event name, this

     * is the handler function.

     * @param {Object} scope Optional. If the ename parameter was an event name, this

     * is the scope (this reference) in which the handler function is executed.

     */

    mun : function(item, ename, fn, scope){

        var found, mon;

        this.createMons();

        for(var i = 0, len = this.mons.length; i < len; ++i){

            mon = this.mons[i];

            if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){

                this.mons.splice(i, 1);

                item.un(ename, fn, scope);

                found = true;

                break;

            }

        }

        return found;

    },

 

 

/**

     * Returns the next component in the owning container

     * @return Ext.Component

     */

    nextSibling : function(){ //Sibling兄妹

        if(this.ownerCt){

            var index = this.ownerCt.items.indexOf(this);

            if(index != -1 && index+1 < this.ownerCt.items.getCount()){

                return this.ownerCt.items.itemAt(index+1);

            }

        }

        return null;

    },

 

 

/**

     * Returns the previous component in the owning container

     * @return Ext.Component

     */

    previousSibling : function(){

        if(this.ownerCt){

            var index = this.ownerCt.items.indexOf(this);

            if(index > 0){

                return this.ownerCt.items.itemAt(index-1);

            }

        }

        return null;

    },

 

 

/**

     * @return {Ext.Container} the Container which owns this Component.

     */

    getBubbleTarget : function(){

        return this.ownerCt;

    }

});

 

Ext.reg('component', Ext.Component);

 

原创粉丝点击