text: /**
   * A basic tab container. TabPanels can be used exactly like a standard {@link Ext.panel.Panel} for
   * layout purposes, but also have special support for containing child Components
   * (`{@link Ext.container.Container#cfg-items items}`) that are managed using a
   * {@link Ext.layout.container.Card CardLayout layout manager}, and displayed as separate tabs.
   *
   * **Note:** By default, a tab's close tool _destroys_ the child tab Component and all its descendants.
   * This makes the child tab Component, and all its descendants **unusable**.  To enable re-use of a tab,
   * configure the TabPanel with `{@link #autoDestroy autoDestroy: false}`.
   *
   * ## TabPanel's layout
   *
   * TabPanels use a Dock layout to position the {@link Ext.tab.Bar TabBar} at the top of the widget.
   * Panels added to the TabPanel will have their header hidden by default because the Tab will
   * automatically take the Panel's configured title and icon.
   *
   * TabPanels use their {@link Ext.panel.Header header} or {@link Ext.panel.Panel#fbar footer}
   * element (depending on the {@link #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 {@link Ext.panel.Panel#tools tools}.
   *
   * To display a header, embed the TabPanel in a {@link Ext.panel.Panel Panel} which uses
   * `{@link Ext.container.Container#layout layout: 'fit'}`.
   *
   * ## Controlling tabs
   *
   * Configuration options for the {@link Ext.tab.Tab} that represents the component can be passed in
   * by specifying the tabConfig option:
   *
   *     @example
   *     Ext.tip.QuickTipManager.init();
   *     Ext.create('Ext.tab.Panel', {
   *         width: 400,
   *         height: 400,
   *         renderTo: document.body,
   *         items: [{
   *             title: 'Foo'
   *         }, {
   *             title: 'Bar',
   *             tabConfig: {
   *                 title: 'Custom Title',
   *                 tooltip: 'A button tooltip'
   *             }
   *         }]
   *     });
   * 
   * ## Vetoing Changes
   * 
   * User interaction when changing the tabs can be vetoed by listening to the {@link #beforetabchange} event.
   * By returning `false`, the tab change will not occur.
   * 
   *     @example
   *     Ext.create('Ext.tab.Panel', {
   *         renderTo: Ext.getBody(),
   *         width: 200,
   *         height: 200,
   *         listeners: {
   *             beforetabchange: function(tabs, newTab, oldTab) {
   *                 return newTab.title != 'P2';
   *             }
   *         },
   *         items: [{
   *             title: 'P1'
   *         }, {
   *             title: 'P2'
   *         }, {
   *             title: 'P3'
   *         }]
   *     }); 
   *
   * # Examples
   *
   * Here is a basic TabPanel rendered to the body. This also shows the useful configuration {@link #activeTab},
   * which allows you to set the active tab on render.
   *
   *     @example
   *     Ext.create('Ext.tab.Panel', {
   *         width: 300,
   *         height: 200,
   *         activeTab: 0,
   *         items: [
   *             {
   *                 title: 'Tab 1',
   *                 bodyPadding: 10,
   *                 html : 'A simple tab'
   *             },
   *             {
   *                 title: 'Tab 2',
   *                 html : 'Another one'
   *             }
   *         ],
   *         renderTo : Ext.getBody()
   *     });
   *
   * It is easy to control the visibility of items in the tab bar. Specify hidden: true to have the
   * tab button hidden initially. Items can be subsequently hidden and show by accessing the
   * tab property on the child item.
   *
   *     @example
   *     var tabs = Ext.create('Ext.tab.Panel', {
   *         width: 400,
   *         height: 400,
   *         renderTo: document.body,
   *         items: [{
   *             title: 'Home',
   *             html: 'Home',
   *             itemId: 'home'
   *         }, {
   *             title: 'Users',
   *             html: 'Users',
   *             itemId: 'users',
   *             hidden: true
   *         }, {
   *             title: 'Tickets',
   *             html: 'Tickets',
   *             itemId: 'tickets'
   *         }]
   *     });
   *
   *     Ext.defer(function(){
   *         tabs.child('#home').tab.hide();
   *         var users = tabs.child('#users');
   *         users.tab.show();
   *         tabs.setActiveTab(users);
   *     }, 1000);
   *
   * You can remove the background of the TabBar by setting the {@link #plain} property to `true`.
   *
   *     @example
   *     Ext.create('Ext.tab.Panel', {
   *         width: 300,
   *         height: 200,
   *         activeTab: 0,
   *         plain: true,
   *         items: [
   *             {
   *                 title: 'Tab 1',
   *                 bodyPadding: 10,
   *                 html : 'A simple tab'
   *             },
   *             {
   *                 title: 'Tab 2',
   *                 html : 'Another one'
   *             }
   *         ],
   *         renderTo : Ext.getBody()
   *     });
   *
   * Another useful configuration of TabPanel is {@link #tabPosition}. This allows you to change the
   * position where the tabs are displayed. The available options for this are `'top'` (default) and
   * `'bottom'`.
   *
   *     @example
   *     Ext.create('Ext.tab.Panel', {
   *         width: 300,
   *         height: 200,
   *         activeTab: 0,
   *         bodyPadding: 10,
   *         tabPosition: 'bottom',
   *         items: [
   *             {
   *                 title: 'Tab 1',
   *                 html : 'A simple tab'
   *             },
   *             {
   *                 title: 'Tab 2',
   *                 html : 'Another one'
   *             }
   *         ],
   *         renderTo : Ext.getBody()
   *     });
   *
   * The {@link #setActiveTab} is a very useful method in TabPanel which will allow you to change the
   * current active tab. You can either give it an index or an instance of a tab. For example:
   *
   *     @example
   *     var tabs = Ext.create('Ext.tab.Panel', {
   *         items: [
   *             {
   *                 id   : 'my-tab',
   *                 title: 'Tab 1',
   *                 html : 'A simple tab'
   *             },
   *             {
   *                 title: 'Tab 2',
   *                 html : 'Another one'
   *             }
   *         ],
   *         renderTo : Ext.getBody()
   *     });
   *
   *     var tab = Ext.getCmp('my-tab');
   *
   *     Ext.create('Ext.button.Button', {
   *         renderTo: Ext.getBody(),
   *         text    : 'Select the first tab',
   *         scope   : this,
   *         handler : function() {
   *             tabs.setActiveTab(tab);
   *         }
   *     });
   *
   *     Ext.create('Ext.button.Button', {
   *         text    : 'Select the second tab',
   *         scope   : this,
   *         handler : function() {
   *             tabs.setActiveTab(1);
   *         },
   *         renderTo : Ext.getBody()
   *     });
   *
   * The {@link #getActiveTab} is a another useful method in TabPanel which will return the current active tab.
   *
   *     @example
   *     var tabs = Ext.create('Ext.tab.Panel', {
   *         items: [
   *             {
   *                 title: 'Tab 1',
   *                 html : 'A simple tab'
   *             },
   *             {
   *                 title: 'Tab 2',
   *                 html : 'Another one'
   *             }
   *         ],
   *         renderTo : Ext.getBody()
   *     });
   *
   *     Ext.create('Ext.button.Button', {
   *         text    : 'Get active tab',
   *         scope   : this,
   *         handler : function() {
   *             var tab = tabs.getActiveTab();
   *             alert('Current tab: ' + tab.title);
   *         },
   *         renderTo : Ext.getBody()
   *     });
   *
   * Adding a new tab is very simple with a TabPanel. You simple call the {@link #method-add} method with an config
   * object for a panel.
   *
   *     @example
   *     var tabs = Ext.create('Ext.tab.Panel', {
   *         items: [
   *             {
   *                 title: 'Tab 1',
   *                 html : 'A simple tab'
   *             },
   *             {
   *                 title: 'Tab 2',
   *                 html : 'Another one'
   *             }
   *         ],
   *         renderTo : Ext.getBody()
   *     });
   *
   *     Ext.create('Ext.button.Button', {
   *         text    : 'New tab',
   *         scope   : this,
   *         handler : function() {
   *             var tab = tabs.add({
   *                 // we use the tabs.items property to get the length of current items/tabs
   *                 title: 'Tab ' + (tabs.items.length + 1),
   *                 html : 'Another one'
   *             });
   *
   *             tabs.setActiveTab(tab);
   *         },
   *         renderTo : Ext.getBody()
   *     });
   *
   * Additionally, removing a tab is very also simple with a TabPanel. You simple call the {@link #method-remove} method
   * with an config object for a panel.
   *
   *     @example
   *     var tabs = Ext.create('Ext.tab.Panel', {
   *         items: [
   *             {
   *                 title: 'Tab 1',
   *                 html : 'A simple tab'
   *             },
   *             {
   *                 id   : 'remove-this-tab',
   *                 title: 'Tab 2',
   *                 html : 'Another one'
   *             }
   *         ],
   *         renderTo : Ext.getBody()
   *     });
   *
   *     Ext.create('Ext.button.Button', {
   *         text    : 'Remove tab',
   *         scope   : this,
   *         handler : function() {
   *             var tab = Ext.getCmp('remove-this-tab');
   *             tabs.remove(tab);
   *         },
   *         renderTo : Ext.getBody()
   *     });
   */
  Ext.define('Ext.tab.Panel', {
      extend: 'Ext.panel.Panel',
      alias: 'widget.tabpanel',
      alternateClassName: ['Ext.TabPanel'],
  
      requires: ['Ext.layout.container.Card', 'Ext.tab.Bar'],
  
      config: {
          // @cmd-auto-dependency { directRef: 'Ext.tab.Bar' }
          /**
           * @cfg {Object} tabBar
           * Optional configuration object for the internal {@link Ext.tab.Bar}.
           * If present, this is passed straight through to the TabBar's constructor
           */
          tabBar: undefined,
  
          /**
           * @cfg {"top"/"bottom"/"left"/"right"} tabPosition
           * The position where the tab strip should be rendered. Possible values are: 
           * 
           *  - top
           *  - bottom
           *  - left
           *  - right
           */
          tabPosition : 'top',
  
          /**
           * @cfg {'default'/0/1/2} tabRotation
           * The rotation of the tabs.  Can be one of the following values:
           *
           * - `'default'` use the default rotation, depending on {@link #tabPosition} (see below)
           * - `0` - no rotation
           * - `1` - rotate 90deg clockwise
           * - `2` - rotate 90deg counter-clockwise
           *
           * The default behavior of this config depends on the {@link #tabPosition}:
           *
           * - `'top'` or `'bottom'` - `0`
           * - `'right'` - `1`
           * - `'left'` - `2`
           */
          tabRotation: 'default',
  
          /**
           * @cfg {Boolean} tabStretchMax
           * `true` to stretch all tabs to the height of the tallest tab when the tabBar
           * is docked horizontally, or the width of the widest tab when the tabBar is
           * docked vertically.
           */
          tabStretchMax: true
      },
  
      /**
       * @cfg {Number} tabBarHeaderPosition
       * If specified, the {@link #tabBar} will be rendered as an item of the TabPanel's
       * Header and the specified `tabBarHeaderPosition` will be used as the Panel header's
       * {@link Ext.panel.Header#itemPosition}.  If not specified, the {@link #tabBar}
       * will be rendered as a docked item at {@link #tabPosition}.
       */
  
      /**
       * @cfg {String/Number} activeItem
       * Doesn't apply for {@link Ext.tab.Panel TabPanel}, use {@link #activeTab} instead.
       */
  
      /**
       * @cfg {String/Number/Ext.Component} activeTab
       * The tab to activate initially. Either an ID, index or the tab component itself. If null, no tab will be set as active.
       */
  
  
      /**
       * @cfg {Ext.enums.Layout/Object} layout
       * Optional configuration object for the internal {@link Ext.layout.container.Card card layout}.
       * If present, this is passed straight through to the layout's constructor
       */
  
      /**
       * @cfg {Boolean} removePanelHeader
       * True to instruct each Panel added to the TabContainer to not render its header element.
       * This is to ensure that the title of the panel does not appear twice.
       */
      removePanelHeader: true,
  
      /**
       * @cfg {Boolean} plain
       * True to not show the full background on the TabBar.
       */
      plain: false,
  
      /**
       * @cfg {String} [itemCls='x-tabpanel-child']
       * The class added to each child item of this TabPanel.
       */
      itemCls: Ext.baseCSSPrefix + 'tabpanel-child',
  
      /**
       * @cfg {Number} minTabWidth
       * The minimum width for a tab in the {@link #cfg-tabBar}.
       */
      minTabWidth: undefined,
  
      /**
       * @cfg {Number} maxTabWidth The maximum width for each tab.
       */
      maxTabWidth: undefined,
  
      /**
       * @cfg {Boolean} deferredRender
       *
       * True by default to defer the rendering of child {@link Ext.container.Container#cfg-items items} to the browsers DOM
       * until a tab is activated. False will render all contained {@link Ext.container.Container#cfg-items items} as soon as
       * the {@link Ext.layout.container.Card 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 true might improve
       * performance.
       *
       * The deferredRender property is internally passed to the layout manager for TabPanels ({@link
       * Ext.layout.container.Card}) as its {@link Ext.layout.container.Card#deferredRender} configuration value.
       *
       * **Note**: leaving deferredRender as true means that the content within an unactivated tab will not be available
       */
      deferredRender : true,
  
      _defaultTabRotation: {
          top: 0,
          right: 1,
          bottom: 0,
          left: 2
      },
  
      /**
       * @event beforetabchange
       * Fires before a tab change (activated by {@link #setActiveTab}). Return false in any listener to cancel
       * the tabchange
       * @param {Ext.tab.Panel} tabPanel The TabPanel
       * @param {Ext.Component} newCard The card that is about to be activated
       * @param {Ext.Component} oldCard The card that is currently active
       */
  
      /**
       * @event tabchange
       * Fires when a new tab has been activated (activated by {@link #setActiveTab}).
       * @param {Ext.tab.Panel} tabPanel The TabPanel
       * @param {Ext.Component} newCard The newly activated item
       * @param {Ext.Component} oldCard The previously active item
       */
  
      initComponent: function() {
          var me = this,
              // Default to 0 if undefined and not null!
              activeTab = me.activeTab !== null ? (me.activeTab || 0) : null,
              dockedItems = me.dockedItems,
              header = me.header,
              tabBarHeaderPosition = me.tabBarHeaderPosition,
              tabBar = me.getTabBar(),
              headerItems;
  
          // Configure the layout with our deferredRender, and with our activeTeb
          me.layout = new Ext.layout.container.Card(Ext.apply({
              owner: me,
              deferredRender: me.deferredRender,
              itemCls: me.itemCls,
              activeItem: activeTab
          }, me.layout));
  
          if (tabBarHeaderPosition != null) {
              header = me.header = Ext.apply({}, header);
  
              headerItems = header.items = (header.items ? header.items.slice() : []);
              header.itemPosition = tabBarHeaderPosition;
              headerItems.push(tabBar);
              header.hasTabBar = true;
          } else {
              dockedItems = [].concat(me.dockedItems || []);
              dockedItems.push(tabBar);
              me.dockedItems = dockedItems;
          }
  
          me.callParent(arguments);
  
          // We have to convert the numeric index/string ID config into its component reference
          activeTab = me.activeTab = me.getComponent(activeTab);
  
          // Ensure that the active child's tab is rendered in the active UI state
          if (activeTab) {
              tabBar.setActiveTab(activeTab.tab, true);
          }
      },
  
      /**
       * @method getTabBar
       * Returns the {@link Ext.tab.Bar} associated with this tabPanel.
       * @return {Ext.tab.Bar} The tabBar for this tabPanel
       */
  
      /**
       * @method setTabBar
       * @ignore
       */
  
      onRender: function() {
          var items = this.items.items,
              len = items.length,
              i;
  
          this.callParent(arguments);
  
          // We want to force any view model for the panel to be created.
          // This is because we capture various parts about the panel itself (title, icon, etc)
          // So we need to be able to use that to populate the tabs.
          // In the future, this could be optimized to be a bit smarter to prevent creation when
          // not required.
          for (i = 0; i < len; ++i) {
              items[i].getBind();
          }
      },
  
      /**
       * Makes the given card active. Makes it the visible card in the TabPanel's CardLayout and highlights the Tab.
       * @param {String/Number/Ext.Component} card The card to make active. Either an ID, index or the component itself.
       * @return {Ext.Component} The resulting active child Component. The call may have been vetoed, or otherwise
       * modified by an event listener.
       */
      setActiveTab: function(card) {
          var me = this,
              previous;
  
          // Check for a config object
          if (!Ext.isObject(card) || card.isComponent) {
              card = me.getComponent(card);
          }
          previous = me.getActiveTab();
          if (card) {
              Ext.suspendLayouts();
              // We may be passed a config object, so add it.
              // Without doing a layout!
              if (!card.isComponent) {
                  card = me.add(card);
              }
  
              if (previous === card || me.fireEvent('beforetabchange', me, card, previous) === false) {
                  Ext.resumeLayouts(true);
                  return previous;
              }
  
              // MUST set the activeTab first so that the machinery which listens for show doesn't
              // think that the show is "driving" the activation and attempt to recurse into here.
              me.activeTab = card;
  
              // Attempt to switch to the requested card. Suspend layouts because if that was successful
              // we have to also update the active tab in the tab bar which is another layout operation
              // and we must coalesce them.
              me.layout.setActiveItem(card);
  
              // Read the result of the card layout. Events dear boy, events!
              card = me.activeTab = me.layout.getActiveItem();
  
              // Card switch was not vetoed by an event listener
              if (card && card !== previous) {
  
                  // Update the active tab in the tab bar and resume layouts.
                  me.tabBar.setActiveTab(card.tab);
                  Ext.resumeLayouts(true);
  
                  // previous will be undefined or this.activeTab at instantiation
                  if (previous !== card) {
                      me.fireEvent('tabchange', me, card, previous);
                  }
              }
              // Card switch was vetoed by an event listener. Resume layouts (Nothing should have changed on a veto).
              else {
                  Ext.resumeLayouts(true);
              }
              return card;
          }
          return previous;
      },
  
      setActiveItem: function(item) {
          return this.setActiveTab(item);
      },
  
      /**
       * Returns the item that is currently active inside this TabPanel.
       * @return {Ext.Component} The currently active item.
       */
      getActiveTab: function() {
          var me = this,
              // Ensure the calculated result references a Component
              result = me.getComponent(me.activeTab);
  
          // Sanitize the result in case the active tab is no longer there.
          if (result && me.items.indexOf(result) !== -1) {
              me.activeTab = result;
          } else {
              me.activeTab = undefined;
          }
  
          return me.activeTab;
      },
  
      applyTabBar: function(tabBar) {
          var me = this,
              // if we are rendering the tabbar into the panel header, use same alignment
              // as header position, and ignore tabPosition.
              dock = (me.tabBarHeaderPosition != null) ? me.getHeaderPosition() : me.getTabPosition();
  
          return new Ext.tab.Bar(Ext.apply({
              ui: me.ui,
              dock: dock,
              tabRotation: me.getTabRotation(),
              vertical: (dock === 'left' || dock === 'right'),
              plain: me.plain,
              tabStretchMax: me.getTabStretchMax(),
              tabPanel: me
          }, tabBar));
      },
  
      updateHeaderPosition: function(headerPosition, oldHeaderPosition) {
          var tabBar = this.getTabBar();
  
          if (tabBar && (this.tabBarHeaderPosition != null)) {
              tabBar.setDock(headerPosition);
          }
  
          this.callParent([headerPosition, oldHeaderPosition]);
      },
  
      updateTabPosition: function(tabPosition) {
          var tabBar = this.getTabBar();
  
          if (tabBar && (this.tabBarHeaderPosition == null)) {
              tabBar.setDock(tabPosition);
          }
      },
  
      updateTabRotation: function(tabRotation) {
          var tabBar = this.getTabBar();
  
          if (tabBar) {
              tabBar.setTabRotation(tabRotation);
          }
      },
  
      /**
       * @protected
       * Makes sure we have a Tab for each item added to the TabPanel
       */
      onAdd: function(item, index) {
          var me = this,
              cfg = Ext.apply({}, item.tabConfig),
              tabBar = me.getTabBar(),
              ariaDom,
              defaultConfig = {
                  xtype: 'tab',
                  title: item.title,
                  icon: item.icon,
                  iconCls: item.iconCls,
                  glyph: item.glyph,
                  ui: tabBar.ui,
                  card: item,
                  disabled: item.disabled,
                  closable: item.closable,
                  hidden: item.hidden && !item.hiddenByLayout, // only hide if it wasn't hidden by the layout itself
                  tooltip: item.tooltip,
                  tabBar: tabBar,
                  tabPosition: tabBar.dock,
                  rotation: tabBar.getTabRotation()
              };
  
          if (item.closeText !== undefined) {
              defaultConfig.closeText = item.closeText;
          }
  
          cfg = Ext.applyIf(cfg, defaultConfig);
  
          // Create the correspondiong tab in the tab bar
          item.tab = me.tabBar.insert(index, cfg);
          
          // We want to force the relationship of the tabpanel to the tab
          item.ariaRole = 'tabpanel';
          
          // Item might be already rendered and then added to the TabPanel
          ariaDom = item.ariaEl.dom;
          
          if (ariaDom) {
              ariaDom.setAttribute('aria-labelledby', item.tab.id);
          }
          else {
              item.ariaRenderAttributes = item.ariaRenderAttributes || {};
              item.ariaRenderAttributes['aria-labelledby'] = item.tab.id;
          }
  
          item.on({
              scope : me,
              enable: me.onItemEnable,
              disable: me.onItemDisable,
              beforeshow: me.onItemBeforeShow,
              iconchange: me.onItemIconChange,
              iconclschange: me.onItemIconClsChange,
              glyphchange: me.onItemGlyphChange,
              titlechange: me.onItemTitleChange
          });
  
          if (item.isPanel) {
              if (me.removePanelHeader) {
                  if (item.rendered) {
                      if (item.header) {
                          item.header.hide();
                      }
                  } else {
                      item.header = false;
                  }
              }
              if (item.isPanel && me.border) {
                  item.setBorder(false);
              }
          }
  
          // Force the view model to be created, see onRender
          if (me.rendered) {
              item.getBind();
          }
  
          // Ensure that there is at least one active tab. This is only needed when adding tabs via a loader config, i.e., there
          // may be no pre-existing tabs. Note that we need to check if activeTab was explicitly set to `null` in the tabpanel
          // config (which tells the layout not to set an active item), as this is a valid value to mean 'do not set an active tab'.
          if (me.rendered && me.loader && me.activeTab === undefined && me.layout.activeItem !== null) {
              me.setActiveTab(0);
          }
      },
  
      onMove: function(item, fromIdx, toIdx) {
          var tabBar = this.getTabBar();
  
          this.callParent([item, fromIdx, toIdx]);
  
          // If the move of the item.tab triggered the movement of the child Panel,
          // then we're done.
          if (tabBar.items.indexOf(item.tab) !== toIdx) {
              tabBar.move(item.tab, toIdx);
          }
      },
  
      /**
       * @private
       * Enable corresponding tab when item is enabled.
       */
      onItemEnable: function(item){
          item.tab.enable();
      },
  
      /**
       * @private
       * Disable corresponding tab when item is enabled.
       */
      onItemDisable: function(item){
          item.tab.disable();
      },
  
      /**
       * @private
       * Sets activeTab before item is shown.
       */
      onItemBeforeShow: function(item) {
          if (item !== this.activeTab) {
              this.setActiveTab(item);
              return false;
          }
      },
  
      /**
       * @private
       * Update the tab icon when panel glyph has been set or changed.
       */
      onItemGlyphChange: function(item, newGlyph) {
          item.tab.setGlyph(newGlyph);
      },
  
      /**
       * @private
       * Update the tab icon when panel icon has been set or changed.
       */
      onItemIconChange: function(item, newIcon) {
          item.tab.setIcon(newIcon);
      },
      
      /**
       * @private
       * Update the tab iconCls when panel iconCls has been set or changed.
       */
      onItemIconClsChange: function(item, newIconCls) {
          item.tab.setIconCls(newIconCls);
      },
  
      /**
       * @private
       * Update the tab title when panel title has been set or changed.
       */
      onItemTitleChange: function(item, newTitle) {
          item.tab.setText(newTitle);
      },
  
      /**
       * @private
       * Makes sure we remove the corresponding Tab when an item is removed
       */
      onRemove: function(item, destroying) {
          var me = this;
  
          item.un({
              scope : me,
              enable: me.onItemEnable,
              disable: me.onItemDisable,
              beforeshow: me.onItemBeforeShow,
              iconchange: me.onItemIconChange,
              iconclschange: me.onItemIconClsChange,
              glyphchange: me.onItemGlyphChange,
              titlechange: me.onItemTitleChange
          });
  
          if (item.tab && !me.destroying && item.tab.ownerCt === me.tabBar) {
              me.tabBar.remove(item.tab);
          }
      },
  
      privates: {
          /**
           * @private
           * Unlink the removed child item from its (@link Ext.tab.Tab Tab}.
           *
           * If we're removing the currently active tab, activate the nearest one. The item is removed when we call super,
           * so we can do preprocessing before then to find the card's index
           */
          doRemove: function (item, autoDestroy) {
              var me = this,
                  toActivate;
  
              // Destroying, or removing the last item, nothing to activate
              if (me.removingAll || me.destroying || me.items.getCount() === 1) {
                  me.activeTab = null;
              }
  
              // Ask the TabBar which tab to activate next.
              // Set the active child panel using the index of that tab
              else if (item.tab && (toActivate = me.tabBar.items.indexOf(me.tabBar.findNextActivatable(item.tab))) !== -1) {
                  me.setActiveTab(toActivate);
              }
              this.callParent(arguments);
  
              if (item.tab) {
                  // Remove the two references
                  delete item.tab.card;
                  delete item.tab;
              }
          }
      }
  });
  