您的位置:首页 > Web前端 > JavaScript

ExtJs_Ext.TabPanel解释

2011-09-28 13:59 309 查看
/*!

* Ext JS Library 3.3.1

*/

/**

* @class Ext.TabPanel

* <p>A basic tab container. TabPanels can be used exactly(确切地) like a standard {Ext.Panel}

* for layout purposes(效果), but also have special(特别的) support for containing child Components;

*

* 注意:<tt> 标签呈现类似打字机或者等宽的文本效果;

* (<tt>{Ext.Container#items items}</tt>) that are managed using a

* {Ext.layout.CardLayout CardLayout layout manager}, and displayed as separate(分开) tabs.</p>

*

* <b>Note:</b> By default, a tab's close tool <i>destroys</i> the child tab Component
//<i>斜体;

* and all its descendants(后代). This makes the child tab Component, and all its descendants <b>unusable</b>. To enable

* re-use of a tab, configure the TabPanel with <b><code>{#autoDestroy autoDestroy: false}</code></b>.

*

* <p><b><u>TabPanel header/footer elements</u></b></p>
//<u>下划线;

* <p>TabPanels use their {Ext.Panel#header header} or {Ext.Panel#footer footer} element

* (depending on the {#tabPosition} configuration) to accommodate(使适应) the tab selector buttons.

* This means that a TabPanel will not display any configured title, and will not display any

* configured header {Ext.Panel#tools tools}.</p>

* <p>To display a header, embed(插入) the TabPanel in a {Ext.Panel Panel} which uses

* <b><tt>{Ext.Container#layout layout:'fit'}</tt></b>.</p>

*

* <p><b><u>Tab Events</u></b></p>

* <p>There is no actual(实在的) tab class —(为分割线"—"符号) each tab is simply(只不过) a {Ext.BoxComponent Component}

* such as a {Ext.Panel Panel}. However, when rendered in a TabPanel, each child Component

* can fire additional(额外的) events that only exist for tabs and are not available(可用的) from other Components.

* These events are:</p>

* <div><ul class="mdetail-params">

* <li><tt><b>{Ext.Panel#activate activate}</b></tt> : Fires when this Component becomes the active tab.</li>

* <li><tt><b>{Ext.Panel#deactivate deactivate}</b></tt> : Fires when the Component that was the active tab becomes

* deactivated.</li>

* <li><tt><b>{Ext.Panel#beforeclose beforeclose}</b></tt> : Fires when the user clicks on the close tool of a closeable

* tab.

* May be vetoed(否决) by returning <code>false</code> from a handler.</li>

* <li><tt><b>{Ext.Panel#close close}</b></tt> : Fires a closeable tab has been closed by the user.</li>

* </ul></div>

* <p><b><u>Creating TabPanels from Code</u></b></p>

* <p>TabPanels can be created and rendered completely in code, as in this example:</p>

* <pre><code>

var tabs = new Ext.TabPanel({

renderTo: Ext.getBody(),

activeTab: 0,

items: [{

title: 'Tab 1',

html: 'A simple tab'

},{

title: 'Tab 2',

html: 'Another one'

}]

});

</code></pre>

* <p><b><u>Creating TabPanels from Existing Markup(标记)</u></b></p>

* <p>TabPanels can also be rendered from pre-existing markup in a couple(一些) of ways.</p>

* <div><ul class="mdetail-params">

*

* <li>Pre-Structured Markup</li>

* <div class="sub-desc">

* <p>A container div with one or more nested tab divs with class <tt>'x-tab'</tt> can be rendered entirely(全部地)

* from existing markup (See the {#autoTabs} example).</p>

* </div>

*

* <li>Un-Structured Markup</li>

* <div class="sub-desc">

* <p>A TabPanel can also be rendered from markup that is not strictly(严格地) structured by simply specifying by id

* which elements should be the container and the tabs. Using this method tab content can be pulled from different

* elements within the page by id regardless(不管) of page structure. For example:</p>

* <pre><code>

var tabs = new Ext.TabPanel({

renderTo: 'my-tabs',

activeTab: 0,

items:[

{contentEl:'tab1', title:'Tab 1'},

{contentEl:'tab2', title:'Tab 2'}

]

});

// Note that the tabs do not have to be nested within the container (although they can be(虽然他们可能))

<div id="my-tabs"></div>

<div id="tab1" class="x-hide-display">A simple tab</div>

<div id="tab2" class="x-hide-display">Another one</div>

</code></pre>

* Note that the tab divs in this example contain the class <tt>'x-hide-display'</tt> so that they can be rendered

* deferred(延期的) without displaying outside the tabs. You could alternately(轮流地) set <tt>{#deferredRender} = false </tt>

* to render all content tabs on page load.

* </div>

* </ul></div>

*

* @extends Ext.Panel

* @constructor

* @param {Object} config_The configuration options

* @xtype tabpanel

*/

Ext.TabPanel = Ext.extend(Ext.Panel, {

/**

* @cfg {Boolean} layoutOnTabChange

* Set to true to force a layout of the active tab when the tab is changed. Defaults to false.

* See {Ext.layout.CardLayout}.<code>{Ext.layout.CardLayout#layoutOnCardChange layoutOnCardChange}</code>.

*/

/**

* @cfg {String} tabCls_<b>This config option is used on <u>child Components</u> of ths TabPanel.</b> A CSS

* class name applied to the tab strip(分离的) item representing(表现) the child Component, allowing special

* styling to be applied.

*/

/**

* @cfg {Boolean} deferredRender //延期渲染;

* <p><tt>true</tt> by default to defer the rendering of child <tt>{Ext.Container#items items}</tt>

* to the browsers DOM until a tab is activated. <tt>false</tt> will render all contained

* <tt>{Ext.Container#items items}</tt> as soon as the {Ext.layout.CardLayout layout}

* is rendered. If there is a significant(有效的) amount of content or a lot of heavy controls being

* rendered into panels that are not displayed by default, setting this to <tt>true</tt> might

* improve performance(执行).</p>

* <br><p>The <tt>deferredRender</tt> property is internally passed to the layout manager for

* TabPanels ({Ext.layout.CardLayout}) as its {Ext.layout.CardLayout#deferredRender}

* configuration value.</p>

* <br><p><b>Note</b>: leaving <tt>deferredRender</tt> as <tt>true</tt> means that the content

* within an unactivated tab will not be available. For example, this means that if the TabPanel

* is within a {Ext.form.FormPanel form}, then until a tab is activated, any Fields within

* unactivated tabs will not be rendered, and will therefore(因此) not be submitted and will not be

* available to either {Ext.form.BasicForm#getValues getValues} or

* {Ext.form.BasicForm#setValues setValues}.</p>

*/

deferredRender : true,

/**

* @cfg {Number} tabWidth_The initial width in pixels of each new tab (defaults to 120).

*/

tabWidth : 120,

/**

* @cfg {Number} minTabWidth_The minimum width in pixels for each tab when {#resizeTabs} = true (defaults to 30).

*/

minTabWidth : 30,

/**

* @cfg {Boolean} resizeTabs_True to automatically(自动的) resize each tab so that the tabs will completely fill the

* tab strip (defaults to false). Setting this to true may cause specific widths that might be set per tab to

* be overridden in order to fit them all into view (although {#minTabWidth} will always be honored).

*/

resizeTabs : false,

/**

* @cfg {Boolean} enableTabScroll_True to enable scrolling to tabs that may be invisible due(应有的东西)

* to overflowing the overall TabPanel width. Only available with tabPosition:'top' (defaults to false).

*/

enableTabScroll : false,

/**

* @cfg {Number} scrollIncrement_The number of pixels to scroll(滚动) each time a tab scroll button is pressed

* (defaults to <tt>100</tt>, or if <tt>{#resizeTabs} = true</tt>, the calculated(适当的) tab width). Only

* applies when <tt>{#enableTabScroll} = true</tt>.

*/

scrollIncrement : 0,

/**

* @cfg {Number} scrollRepeatInterval_Number of milliseconds between each scroll while a tab scroll button is

* continuously(连续不断地) pressed (defaults to <tt>400</tt>).

*/

scrollRepeatInterval : 400,

/**

* @cfg {Float} scrollDuration_The number of milliseconds that each scroll animation should last (defaults

* to <tt>.35</tt>). Only applies when <tt>{#animScroll} = true</tt>.

*/

scrollDuration : 0.35,

/**

* @cfg {Boolean} animScroll_True to animate tab scrolling so that hidden tabs slide smoothly(流畅地) into view (defaults

* to <tt>true</tt>). Only applies when <tt>{#enableTabScroll} = true</tt>.

*/

animScroll : true,

/**

* @cfg {String} tabPosition_The position where the tab strip should be rendered (defaults to <tt>'top'</tt>).

* The only other supported value is <tt>'bottom'</tt>. <b>Note</b>: tab scrolling is only supported for

* <tt>tabPosition: 'top'</tt>.

*/

tabPosition : 'top',

/**

* @cfg {String} baseCls The base CSS class applied to the panel (defaults to <tt>'x-tab-panel'</tt>).

*/

baseCls : 'x-tab-panel',

/**

* @cfg {Boolean} autoTabs

* <p><tt>true</tt> to query the DOM for any divs with a class of 'x-tab' to be automatically converted

* to tabs and added to this panel (defaults to <tt>false</tt>). Note that the query will be executed within

* the scope of the container element only (so that multiple tab panels from markup can be supported via this

* method).</p>

* <p>This method is only possible when the markup is structured correctly as a container with nested divs

* containing the class <tt>'x-tab'</tt>. To create TabPanels without these limitations, or to pull tab content

* from other elements on the page, see the example at the top of the class for generating(产声) tabs from markup.</p>

* <p>There are a couple of things to note when using this method:<ul>

* <li>When using the <tt>autoTabs</tt> config (as opposed to passing individual(特殊的) tab configs in the TabPanel's

* {#items} collection), you must use <tt>{#applyTo}</tt> to correctly use the specified <tt>id</tt>

* as the tab container. The <tt>autoTabs</tt> method <em>replaces</em> existing content with the TabPanel

* components.</li>

* <li>Make sure that you set <tt>{#deferredRender}: false</tt> so that the content elements for each

* tab will be rendered into the TabPanel immediately upon page load, otherwise they will not be transformed

* until each tab is activated and will be visible outside the TabPanel.</li>

* </ul>Example usage:</p>

* <pre><code>

var tabs = new Ext.TabPanel({

applyTo: 'my-tabs',

activeTab: 0,

deferredRender: false,

autoTabs: true

});

// This markup will be converted to a TabPanel from the code above

<div id="my-tabs">

<div class="x-tab" title="Tab 1">A simple tab</div>

<div class="x-tab" title="Tab 2">Another one</div>

</div>

</code></pre>

*/

autoTabs : false,

/**

* @cfg {String} autoTabSelector The CSS selector used to search for tabs in existing markup when

* <tt>{#autoTabs} = true</tt> (defaults to <tt>'div.x-tab'</tt>). This can be any valid selector

* supported by {Ext.DomQuery#select}. Note that the query will be executed within the scope of this

* tab panel only (so that multiple tab panels from markup can be supported on a page).

*/

autoTabSelector : 'div.x-tab',

/**

* @cfg {String/Number} activeTab A string id or the numeric index of the tab that should be initially(起初)

* activated on render (defaults to undefined).

*/

activeTab : undefined,

/**

* @cfg {Number} tabMargin The number of pixels of space to calculate(计算) into the sizing and scrolling of

* tabs. If you change the margin in CSS, you will need to update this value so calculations are correct

* with either <tt>{#resizeTabs}</tt> or scrolling tabs. (defaults to <tt>2</tt>)

*/

tabMargin : 2,

/**

* @cfg {Boolean} plain </tt>true</tt> to render the tab strip without a background container image

* (defaults to <tt>false</tt>).

*/

plain : false,

/**

* @cfg {Number} wheelIncrement For scrolling tabs, the number of pixels to increment on mouse wheel

* scrolling (defaults to <tt>20</tt>).

*/

wheelIncrement : 20, //滚轮;

/*

* This is a protected property used when concatenating(并置) tab ids to the TabPanel id for internal uniqueness.

* It does not generally need to be changed, but can be if external(外部的) code also uses an id scheme(计划) that can

* potentially(潜在地) clash(冲突) with this one.

*/

idDelimiter : '__', //Delimiter:分隔符;

// private

itemCls : 'x-tab-item',

// private config overrides

elements : 'body',

headerAsText : false,

frame : false,

hideBorders :true,

// private

initComponent : function(){

this.frame = false;

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

this.addEvents(

/**

* @event beforetabchange

* Fires before the active tab changes. Handlers can <tt>return false</tt> to cancel the tab change.

* @param {TabPanel} this

* @param {Panel} newTab The tab being activated

* @param {Panel} currentTab The current active tab

*/

'beforetabchange',

/**

* @event tabchange

* Fires after the active tab has changed.

* @param {TabPanel} this

* @param {Panel} tab The new active tab

*/

'tabchange',

/**

* @event contextmenu

* Relays(转达) the contextmenu event from a tab selector element in the tab strip.

* @param {TabPanel} this

* @param {Panel} tab The target tab

* @param {EventObject} e

*/

'contextmenu'

);

/**

* @cfg {Object} layoutConfig

* TabPanel implicitly(绝对地) uses {Ext.layout.CardLayout} as its layout manager.

* <code>layoutConfig</code> may be used to configure this layout manager.

* <code>{#deferredRender}</code> and <code>{#layoutOnTabChange}</code>

* configured on the TabPanel will be applied as configs to the layout manager.

*/

this.setLayout(new Ext.layout.CardLayout(Ext.apply({

layoutOnCardChange: this.layoutOnTabChange,

deferredRender: this.deferredRender

}, this.layoutConfig)));

if(this.tabPosition == 'top'){

this.elements += ',header';

this.stripTarget = 'header';

}else {

this.elements += ',footer';

this.stripTarget = 'footer';

}

if(!this.stack){

this.stack = Ext.TabPanel.AccessStack();

}

this.initItems();

},

// private

onRender : function(ct, position){

Ext.TabPanel.superclass.onRender.call(this, ct, position);

if(this.plain){

var pos = this.tabPosition == 'top' ? 'header' : 'footer';

this[pos].addClass('x-tab-panel-'+pos+'-plain');

}

var st = this[this.stripTarget];

this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{

tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});

var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);

st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);

this.strip = new Ext.Element(this.stripWrap.dom.firstChild);

// create an empty span with class x-tab-strip-text to force the height of the header element when there's no tabs.

this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge', cn: [{tag: 'span', cls: 'x-tab-strip-text',

cn: ' '}]});

this.strip.createChild({cls:'x-clear'});

this.body.addClass('x-tab-panel-body-'+this.tabPosition);

/**

* @cfg {Template/XTemplate} itemTpl <p>(Optional) A {Ext.Template Template} or

* {Ext.XTemplate XTemplate} which may be provided to process(数据处理) the data object returned from

* <tt>{#getTemplateArgs}</tt> to produce a clickable selector element in the tab strip.</p>

* <p>The main element created should be a <tt><li></tt> element. In order for a click event on

* a selector element to be connected to its item, it must take its <i>id</i> from the TabPanel's

* native <tt>{#getTemplateArgs}</tt>.</p>

* <p>The child element which contains the title text must be marked by the CSS class

* <tt>x-tab-strip-inner</tt>.</p>

* <p>To enable closability, the created element should contain an element marked by the CSS class

* <tt>x-tab-strip-close</tt>.</p>

* <p>If a custom <tt>itemTpl</tt> is supplied, it is the developer's responsibility(责任) to create CSS

* style rules to create the desired(想得到的) appearance(效果).</p>

* Below is an example of how to create customized(自定义的) tab selector items:<pre><code>

new Ext.TabPanel({

renderTo: document.body,

minTabWidth: 115,

tabWidth: 135,

enableTabScroll: true,

width: 600,

height: 250,

defaults: {autoScroll:true},

itemTpl: new Ext.XTemplate(

'<li class="{cls}" id="{id}" style="overflow:hidden">',

'<tpl if="closable">',

'<a class="x-tab-strip-close"></a>',

'</tpl>',

'<a class="x-tab-right" href="#" style="padding-left:6px">',

'<em class="x-tab-left">',

'<span class="x-tab-strip-inner">',

'<img src="{src}" style="float:left;margin:3px 3px 0 0">',

'<span style="margin-left:20px" class="x-tab-strip-text {iconCls}">',

'{text} {extra}</span>',

'</span>',

'</em>',

'</a>',

'</li>'

),

getTemplateArgs: function(item) {

// Call the native method to collect the base data. Like the ID!

var result = Ext.TabPanel.prototype.getTemplateArgs.call(this, item);

// Add stuff(属性) used in our template

return Ext.apply(result, {

closable: item.closable,

src: item.iconSrc,

extra: item.extraText || ''

});

},

items: [{

title: 'New Tab 1',

iconSrc: '../shared/icons/fam/grid.png',

html: 'Tab Body 1',

closable: true

}, {

title: 'New Tab 2',

iconSrc: '../shared/icons/fam/grid.png',

html: 'Tab Body 2',

extraText: 'Extra stuff in the tab button'

}]

});

* </code></pre>

*/

if(!this.itemTpl){

var tt = new Ext.Template(

'<li class="{cls}" id="{id}">' +

'<a class="x-tab-strip-close"></a>',

'<a class="x-tab-right" href="#">' +

'<em class="x-tab-left">',

'<span class="x-tab-strip-inner">' +

'<span class="x-tab-strip-text {iconCls}">{text}</span>' +

'</span>',

'</em>' +

'</a>' +

'</li>'

);

tt.disableFormats = true;

tt.compile();

Ext.TabPanel.prototype.itemTpl = tt;

}

this.items.each(this.initTab, this);

},

// private

afterRender : function(){

Ext.TabPanel.superclass.afterRender.call(this);

if(this.autoTabs){

this.readTabs(false);

}

if(this.activeTab !== undefined){

var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);

delete this.activeTab;

this.setActiveTab(item);

}

},

// private

initEvents : function(){

Ext.TabPanel.superclass.initEvents.call(this);

this.mon(this.strip, {

scope: this,

mousedown: this.onStripMouseDown,

contextmenu: this.onStripContextMenu

});

if(this.enableTabScroll){

this.mon(this.strip, 'mousewheel', this.onWheel, this);

}

},

// private

findTargets : function(e){

var item = null,

itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);

if(itemEl){

item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);

if(item.disabled){

return {

close : null,

item : null,

el : null

};

}

}

return {

close : e.getTarget('.x-tab-strip-close', this.strip),

item : item,

el : itemEl

};

},

// private

onStripMouseDown : function(e){

if(e.button !== 0){

return;

}

e.preventDefault();

var t = this.findTargets(e);

if(t.close){

if (t.item.fireEvent('beforeclose', t.item) !== false) {

t.item.fireEvent('close', t.item);

this.remove(t.item);

}

return;

}

if(t.item && t.item != this.activeTab){

this.setActiveTab(t.item);

}

},

// private

onStripContextMenu : function(e){

e.preventDefault();

var t = this.findTargets(e);

if(t.item){

this.fireEvent('contextmenu', this, t.item, e);

}

},

/**

* True to scan(扫描) the markup in this tab panel for <tt>{#autoTabs}</tt> using the

* <tt>{#autoTabSelector}</tt>

* @param {Boolean} removeExisting True to remove existing tabs

*/

readTabs : function(removeExisting){

if(removeExisting === true){

this.items.each(function(item){

this.remove(item);

}, this);

}

var tabs = this.el.query(this.autoTabSelector);

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

var tab = tabs[i],

title = tab.getAttribute('title');

tab.removeAttribute('title');

this.add({

title: title,

contentEl: tab

});

}

},

// private

initTab : function(item, index){

var before = this.strip.dom.childNodes[index],

p = this.getTemplateArgs(item),

el = before ?

this.itemTpl.insertBefore(before, p) :

this.itemTpl.append(this.strip, p),

cls = 'x-tab-strip-over',

tabEl = Ext.get(el);

tabEl.hover(function(){

if(!item.disabled){

tabEl.addClass(cls);

}

}, function(){

tabEl.removeClass(cls);

});

if(item.tabTip){

tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;

}

item.tabEl = el;

// Route *keyboard triggered(键盘触发)* click events to the tab strip mouse handler.

tabEl.select('a').on('click', function(e){

if(!e.getPageX()){

this.onStripMouseDown(e);

}

}, this, {preventDefault: true});

item.on({

scope: this,

disable: this.onItemDisabled,

enable: this.onItemEnabled,

titlechange: this.onItemTitleChanged,

iconchange: this.onItemIconChanged,

beforeshow: this.onBeforeShowItem

});

},

/**

* <p>Provides template arguments for rendering a tab selector item in the tab strip.</p>

* <p>This method returns an object hash containing properties used by the TabPanel's <tt>{#itemTpl}</tt>

* to create a formatted, clickable tab selector element. The properties which must be returned

* are:</p><div class="mdetail-params"><ul>

* <li><b>id</b> : String<div class="sub-desc">A unique identifier which links to the item</div></li>

* <li><b>text</b> : String<div class="sub-desc">The text to display</div></li>

* <li><b>cls</b> : String<div class="sub-desc">The CSS class name</div></li>

* <li><b>iconCls</b> : String<div class="sub-desc">A CSS class to provide appearance(外观) for an icon.</div></li>

* </ul></div>

* @param {Ext.BoxComponent} item The {Ext.BoxComponent BoxComponent} for which to create a selector element

* in the tab strip.

* @return {Object} An object hash containing the properties required to render the selector element.

*/

getTemplateArgs : function(item) {

var cls = item.closable ? 'x-tab-strip-closable' : '';

if(item.disabled){

cls += ' x-item-disabled';

}

if(item.iconCls){

cls += ' x-tab-with-icon';

}

if(item.tabCls){

cls += ' ' + item.tabCls;

}

return {

id: this.id + this.idDelimiter + item.getItemId(),

text: item.title,

cls: cls,

iconCls: item.iconCls || ''

};

},

// private

onAdd : function(c){

Ext.TabPanel.superclass.onAdd.call(this, c);

if(this.rendered){

var items = this.items;

this.initTab(c, items.indexOf(c));

this.delegateUpdates();

}

},

// private

onBeforeAdd : function(item){

var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);

if(existing){

this.setActiveTab(item);

return false;

}

Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);

var es = item.elements;

item.elements = es ? es.replace(',header', '') : es;

item.border = (item.border === true);

},

// private

onRemove : function(c){

var te = Ext.get(c.tabEl);

// check if the tabEl exists, it won't if the tab isn't rendered

if(te){

te.select('a').removeAllListeners();

Ext.destroy(te);

}

Ext.TabPanel.superclass.onRemove.call(this, c);

this.stack.remove(c);

delete c.tabEl;

c.un('disable', this.onItemDisabled, this);

c.un('enable', this.onItemEnabled, this);

c.un('titlechange', this.onItemTitleChanged, this);

c.un('iconchange', this.onItemIconChanged, this);

c.un('beforeshow', this.onBeforeShowItem, this);

if(c == this.activeTab){

var next = this.stack.next();

if(next){

this.setActiveTab(next);

}else if(this.items.getCount() > 0){

this.setActiveTab(0);

}else{

this.setActiveTab(null);

}

}

if(!this.destroying){

this.delegateUpdates();

}

},

// private

onBeforeShowItem : function(item){

if(item != this.activeTab){

this.setActiveTab(item);

return false;

}

},

// private

onItemDisabled : function(item){

var el = this.getTabEl(item);

if(el){

Ext.fly(el).addClass('x-item-disabled');

}

this.stack.remove(item);

},

// private

onItemEnabled : function(item){

var el = this.getTabEl(item);

if(el){

Ext.fly(el).removeClass('x-item-disabled');

}

},

// private

onItemTitleChanged : function(item){

var el = this.getTabEl(item);

if(el){

Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;

}

},

//private

onItemIconChanged : function(item, iconCls, oldCls){

var el = this.getTabEl(item);

if(el){

el = Ext.get(el);

el.child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);

el[Ext.isEmpty(iconCls) ? 'removeClass' : 'addClass']('x-tab-with-icon');

}

},

/**

* Gets the DOM element for the tab strip item which activates the child panel with the specified

* ID. Access this to change the visual treatment of the item, for example by changing the CSS class name.

* @param {Panel/Number/String} tab The tab component, or the tab's index, or the tabs id or itemId.

* @return {HTMLElement} The DOM node

*/

getTabEl : function(item){

var c = this.getComponent(item);

return c ? c.tabEl : null;

},

// private

onResize : function(){

Ext.TabPanel.superclass.onResize.apply(this, arguments);

this.delegateUpdates();

},

/**

* Suspends(暂停) any internal calculations(计算) or scrolling while doing a bulk(大量的) operation. See {#endUpdate}

*/

beginUpdate : function(){

this.suspendUpdates = true;

},

/**

* Resumes(重新开始) calculations(计算) and scrolling at the end of a bulk(大量的) operation. See {#beginUpdate}

*/

endUpdate : function(){

this.suspendUpdates = false;

this.delegateUpdates();

},

/**

* Hides the tab strip item for the passed tab

* @param {Number/String/Panel} item The tab index, id or item

*/

hideTabStripItem : function(item){

item = this.getComponent(item);

var el = this.getTabEl(item);

if(el){

el.style.display = 'none';

this.delegateUpdates();

}

this.stack.remove(item);

},

/**

* Unhides the tab strip item for the passed tab

* @param {Number/String/Panel} item The tab index, id or item

*/

unhideTabStripItem : function(item){

item = this.getComponent(item);

var el = this.getTabEl(item);

if(el){

el.style.display = '';

this.delegateUpdates();

}

},

// private

delegateUpdates : function(){

var rendered = this.rendered;

if(this.suspendUpdates){

return;

}

if(this.resizeTabs && rendered){

this.autoSizeTabs();

}

if(this.enableTabScroll && rendered){

this.autoScrollTabs();

}

},

// private

autoSizeTabs : function(){

var count = this.items.length,

ce = this.tabPosition != 'bottom' ? 'header' : 'footer',

ow = this[ce].dom.offsetWidth,

aw = this[ce].dom.clientWidth;

if(!this.resizeTabs || count < 1 || !aw){ // !aw for display:none

return;

}

var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth),

this.minTabWidth); // -4 for float errors in IE

this.lastTabWidth = each;

var lis = this.strip.query('li:not(.x-tab-edge)');

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

var li = lis[i],

inner = Ext.fly(li).child('.x-tab-strip-inner', true),

tw = li.offsetWidth,

iw = inner.offsetWidth;

inner.style.width = (each - (tw-iw)) + 'px';

}

},

// private_adjust调整

adjustBodyWidth : function(w){

if(this.header){

this.header.setWidth(w);

}

if(this.footer){

this.footer.setWidth(w);

}

return w;

},

/**

* Sets the specified(规定的) tab as the active tab. This method fires the {#beforetabchange} event which

* can <tt>return false</tt> to cancel the tab change.

* @param {String/Number} item

* The id or tab Panel to activate. This parameter may be any of the following:

*String: representing(表示) the {Ext.Component#itemId itemId} or {Ext.Component#id id}of the child component;

*Number: representing the position of the child component within the {Ext.Container#items items} property;

* For additional(额外的) information(信息) see {Ext.util.MixedCollection#get}.

*/

setActiveTab : function(item){

item = this.getComponent(item);

if(this.fireEvent('beforetabchange', this, item, this.activeTab) === false){

return;

}

if(!this.rendered){

this.activeTab = item;

return;

}

if(this.activeTab != item){

if(this.activeTab){

var oldEl = this.getTabEl(this.activeTab);

if(oldEl){

Ext.fly(oldEl).removeClass('x-tab-strip-active');

}

}

this.activeTab = item;

if(item){

var el = this.getTabEl(item);

Ext.fly(el).addClass('x-tab-strip-active');

this.stack.add(item);

this.layout.setActiveItem(item);

// Need to do this here, since setting the active tab slightly(稍微地) changes the size

this.delegateUpdates();

if(this.scrolling){

this.scrollToTab(item, this.animScroll);

}

}

this.fireEvent('tabchange', this, item);

}

},

/**

* Returns the Component which is the currently active tab. <b>Note that before the TabPanel

* first activates a child Component, this method will return whatever was configured in the

* {#activeTab} config option.</b>

* @return {BoxComponent} The currently active child Component if one <i>is</i> active,

* or the {#activeTab} config value.

*/

getActiveTab : function(){

return this.activeTab || null;

},

/**

* Gets the specified tab by id.

* @param {String} id The tab id

* @return {Panel} The tab

*/

getItem : function(item){

return this.getComponent(item);

},

// private

autoScrollTabs : function(){

this.pos = this.tabPosition=='bottom' ? this.footer : this.header;

var count = this.items.length,

ow = this.pos.dom.offsetWidth,

tw = this.pos.dom.clientWidth,

wrap = this.stripWrap,

wd = wrap.dom,

cw = wd.offsetWidth,

pos = this.getScrollPos(),

l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;

if(!this.enableTabScroll || cw < 20){ // 20 to prevent display:none issues

return;

}

if(count == 0 || l <= tw){

// ensure the width is set if there's no tabs

wd.scrollLeft = 0;

wrap.setWidth(tw);

if(this.scrolling){

this.scrolling = false;

this.pos.removeClass('x-tab-scrolling');

this.scrollLeft.hide();

this.scrollRight.hide();

// See here: http://extjs.com/forum/showthread.php?t=49308&highlight=isSafari
if(Ext.isAir || Ext.isWebKit){

wd.style.marginLeft = '';

wd.style.marginRight = '';

}

}

}else{

if(!this.scrolling){

this.pos.addClass('x-tab-scrolling');

// See here: http://extjs.com/forum/showthread.php?t=49308&highlight=isSafari
if(Ext.isAir || Ext.isWebKit){

wd.style.marginLeft = '18px';

wd.style.marginRight = '18px';

}

}

tw -= wrap.getMargins('lr');

wrap.setWidth(tw > 20 ? tw : 20);

if(!this.scrolling){

if(!this.scrollLeft){

this.createScrollers();

}else{

this.scrollLeft.show();

this.scrollRight.show();

}

}

this.scrolling = true;

if(pos > (l-tw)){ // ensure it stays within bounds

wd.scrollLeft = l-tw;

}else{ // otherwise, make sure the active tab is still visible

this.scrollToTab(this.activeTab, false);

}

this.updateScrollButtons();

}

},

// private

createScrollers : function(){

this.pos.addClass('x-tab-scrolling-' + this.tabPosition);

var h = this.stripWrap.dom.offsetHeight;

// left

var sl = this.pos.insertFirst({

cls:'x-tab-scroller-left'

});

sl.setHeight(h);

sl.addClassOnOver('x-tab-scroller-left-over');

this.leftRepeater = new Ext.util.ClickRepeater(sl, {

interval : this.scrollRepeatInterval,

handler: this.onScrollLeft,

scope: this

});

this.scrollLeft = sl;

// right

var sr = this.pos.insertFirst({

cls:'x-tab-scroller-right'

});

sr.setHeight(h);

sr.addClassOnOver('x-tab-scroller-right-over');

this.rightRepeater = new Ext.util.ClickRepeater(sr, {

interval : this.scrollRepeatInterval,

handler: this.onScrollRight,

scope: this

});

this.scrollRight = sr;

},

// private

getScrollWidth : function(){

return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();

},

// private

getScrollPos : function(){

return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;

},

// private

getScrollArea : function(){

return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;

},

// private

getScrollAnim : function(){

return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};

},

// private

getScrollIncrement : function(){

return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);

},

/**

* Scrolls to a particular(特定的) tab if tab scrolling is enabled

* @param {Panel} item The item to scroll to

* @param {Boolean} animate True to enable animations

*/

scrollToTab : function(item, animate){

if(!item){

return;

}

var el = this.getTabEl(item),

pos = this.getScrollPos(),

area = this.getScrollArea(),

left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,

right = left + el.offsetWidth;

if(left < pos){

this.scrollTo(left, animate);

}else if(right > (pos + area)){

this.scrollTo(right - area, animate);

}

},

// private

scrollTo : function(pos, animate){

this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);

if(!animate){

this.updateScrollButtons();

}

},

onWheel : function(e){

var d = e.getWheelDelta()*this.wheelIncrement*-1;

e.stopEvent();

var pos = this.getScrollPos(),

newpos = pos + d,

sw = this.getScrollWidth()-this.getScrollArea();

var s = Math.max(0, Math.min(sw, newpos));

if(s != pos){

this.scrollTo(s, false);

}

},

// private

onScrollRight : function(){

var sw = this.getScrollWidth()-this.getScrollArea(),

pos = this.getScrollPos(),

s = Math.min(sw, pos + this.getScrollIncrement());

if(s != pos){

this.scrollTo(s, this.animScroll);

}

},

// private

onScrollLeft : function(){

var pos = this.getScrollPos(),

s = Math.max(0, pos - this.getScrollIncrement());

if(s != pos){

this.scrollTo(s, this.animScroll);

}

},

// private

updateScrollButtons : function(){

var pos = this.getScrollPos();

this.scrollLeft[pos === 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');

this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']

('x-tab-scroller-right-disabled');

},

// private

beforeDestroy : function() {

Ext.destroy(this.leftRepeater, this.rightRepeater);

this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');

this.activeTab = null;

Ext.TabPanel.superclass.beforeDestroy.apply(this);

}

/**

* @cfg {Boolean} collapsible

* @hide

*/

/**

* @cfg {String} header

* @hide

*/

/**

* @cfg {Boolean} headerAsText

* @hide

*/

/**

* @property header

* @hide

*/

/**

* @cfg title

* @hide

*/

/**

* @cfg {Array} tools

* @hide

*/

/**

* @cfg {Array} toolTemplate

* @hide

*/

/**

* @cfg {Boolean} hideCollapseTool

* @hide

*/

/**

* @cfg {Boolean} titleCollapse

* @hide

*/

/**

* @cfg {Boolean} collapsed

* @hide

*/

/**

* @cfg {String} layout

* @hide

*/

/**

* @cfg {Boolean} preventBodyReset

* @hide

*/

});

Ext.reg('tabpanel', Ext.TabPanel);

/**

* See {#setActiveTab}. Sets the specified tab as the active tab. This method fires

* the {#beforetabchange} event which can return false to cancel the tab change.

* @param {String/Panel} tab The id or tab Panel to activate

* @method activate

*/

Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;

// private utility(使用的) class used by TabPanel

Ext.TabPanel.AccessStack = function(){

var items = [];

return {

add : function(item){

items.push(item);

if(items.length > 10){

items.shift(); //shift方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。;

}

},

remove : function(item){

var s = [];

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

if(items[i] != item){

s.push(items[i]);

}

}

items = s;

},

next : function(){

return items.pop();

}

};

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: