text: // Copyright 2011 Tart. All Rights Reserved.
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //      http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS-IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  /**
   * @fileoverview Tabs is a fully working and customizable tab panel creator class.
   *
   * Example Usage:
   *
   *
   * var tabPanel = new tart.Tabs({
   *      activeTab: 1
   *  });
   *
   * var panel1 = new tart.TabPanel({
   *    title: 'Tab 1',
   *    html: 'This is a basic text'
   * });
   * var panel2 = new tart.TabPanel({
   *     title: 'Tab 2',
   *    html: 'Lorem ipsum dolor sit amet'
   * });
   * var panel3 = new tart.TabPanel({
   *     title: 'Tab 3',
   *     html: 'Lorem ipsum dolor sit amet is a dummy text'
   * });
   *
   * tabPanel.addTabPanel(panel1);
   * tabPanel.addTabPanel(panel2);
   * tabPanel.addTabPanel(panel3);
   *
   * var dom = tabPanel.buildDOM();
   * $('body').append(dom);
   *
  */
  
  goog.provide('tart.Tabs');
  goog.require('goog.pubsub.PubSub');
  goog.require('tart.TabPanel');
  
  
  
  /**
   * Tabs is a fully working and customizable tab panel creator class
   * @constructor
   * @param {Object=} options Customized initial options for tabpanel.
   * @extends {goog.pubsub.PubSub}
   */
  tart.Tabs = function(options) {
      goog.base(this);
      options = options || {};
      this.initOptions(options);
  
      this.$tabContainer = $(this.templates_tabContainer());
      this.$panelContainer = $(this.templates_panelContainer());
  
      /**
       * Holds TabPanel objects associated with the tabpanel
       * @type {Array.<tart.TabPanel>}
       * @protected
       */
      this.tabPanels = [];
  
      /**
       * State of tab panel
       * @protected
       */
      this.rendered = false;
  
      this.initialize(this.props.renderConfig);
  };
  goog.inherits(tart.Tabs, goog.pubsub.PubSub);
  
  
  /**
   * Initialize the tabpanel with calling buildDOM method
   * @param {!string} renderCfg Where to container will be appended.
   */
  tart.Tabs.prototype.initialize = function(renderCfg) {
      var panelDOM = this.buildDOM();
      if (renderCfg.insertAfter) {
          panelDOM.insertAfter(renderCfg.insertAfter);
      }
      else if (renderCfg.insertBefore) {
          panelDOM.insertBefore(renderCfg.insertBefore);
      }
      else if (renderCfg.append) {
          renderCfg.append.append(panelDOM);
      }
  };
  
  
  /**
   * Adds new tab to existing tab panel
   * @param {!(Array|tart.TabPanel)} tabPanels An array that holds instance of TabPanel Class to add new tab.
   * Also tabPanels argument should be a tab panel instance instead of array.
   */
  tart.Tabs.prototype.addTabPanel = function(tabPanels) {
      var that = this;
      if (goog.isArray(tabPanels)) {
          for (var i = 0, len = tabPanels.length; i < len; i++) {
              that.addTab(tabPanels[i]);
          }
      } else {
          that.addTab(tabPanels);
      }
      this.setActiveTab(this.activeTab);
  };
  
  
  /**
   * Adds a new tab to a Tabs instance.
   * @param {tart.TabPanel} tabPanel instance that's going to be added to a Tabs instance.
   */
  tart.Tabs.prototype.addTab = function(tabPanel) {
      this.tabPanels.push(tabPanel);
      this.$tabContainer.append(tabPanel.$tab);
      this.$panelContainer.append(tabPanel.$panel);
      this.bindTabPanelEvents(tabPanel);
  };
  
  
  /**
   * Removes the tab with the given index.
   * @param {!number} index Index number of the tab that you want to remove.
   */
  tart.Tabs.prototype.removeTab = function(index) {
      var tabsLength = this.getTabsLength();
  
      if (index >= tabsLength || tabsLength === 0) {
          return;
      }
  
      this.tabPanels[index].$tab.remove();
      this.tabPanels[index].$panel.remove();
      this.tabPanels.splice(index, 1);
  
      try {
          if (index <= this.activeTab) {
              if (index === this.activeTab) {
                  this.setActiveTab(index - 1);
              } else {
                  this.setActiveTab(this.activeTab - 1);
              }
          }
      } catch (e) {}
  };
  
  
  /**
   * Sets the tab as active with the given index.
   * @param {!number} index Index number of the tab that you want to set as active.
   */
  tart.Tabs.prototype.setActiveTab = function(index) {
      if (index >= this.getTabsLength()) {
          return false;
      }
  
      var deActivatedTab = this.getActiveTab();
  
      for (var i = 0, len = this.tabPanels.length; i < len; i++) {
          if (index != i) {
              this.tabPanels[i].$tab.removeClass(this.props.activeTabCssClass);
              this.tabPanels[i].$panel.removeClass(this.props.activePanelCssClass);
          }
      }
      this.tabPanels[index].$tab.addClass(this.props.activeTabCssClass);
      this.tabPanels[index].$panel.addClass(this.props.activePanelCssClass);
      this.activeTab = index;
  
      var newlyActivatedTab = this.getActiveTab();
  
      if (deActivatedTab.onClose && deActivatedTab != newlyActivatedTab) /* prevent double fn call on initialize */
  	        deActivatedTab.onClose(this);
  
  	newlyActivatedTab.onShow && newlyActivatedTab.onShow(this); // call newly activated tab's onShow function
  	this.publish('tabChange', this.getActiveTab(), this);
  };
  
  
  /**
   * Returns the active tab object contains tab and panel elements and templates that used in tab and panel.
   * @return {tart.TabPanel} The active tab.
   */
  tart.Tabs.prototype.getActiveTab = function() {
      return this.tabPanels[this.activeTab];
  };
  
  
  /**
   * Binds required events of tabpanel.
   * @param {!tart.TabPanel} tabPanel Tabpanel instance for binding events to it.
   */
  tart.Tabs.prototype.bindTabPanelEvents = function(tabPanel) {
      var that = this;
  
      var setMeActive = function() {
          var myIndex = goog.array.indexOf(that.tabPanels, tabPanel);
          that.setActiveTab(myIndex);
      };
  
      tabPanel.$tab.click(setMeActive);
  };
  
  
  /**
   * Builds DOM elements for tabpanel and returns DOM as ready to append to a container
   * @return {jQueryObject} DOM element of the Tabs instance.
   */
  tart.Tabs.prototype.buildDOM = function() {
      this.$dom = $(this.templates_dom());
      this.$dom.append(this.$tabContainer);
      this.$dom.append(this.$panelContainer);
      this.rendered = true;
      return this.$dom;
  };
  
  
  /**
   * @return {boolean} The status of tabpanel, rendered or not.
   */
  tart.Tabs.prototype.isRendered = function() {
      return this.rendered;
  };
  
  
  /**
   * @return {number} number of tabs associated with the Tabs instance.
   */
  tart.Tabs.prototype.getTabsLength = function() {
      return this.tabPanels.length;
  };
  
  
  /**
   * Merges custom options object with defaults
   * @protected
   * @param {Object=} options Customized options for Tabs instance.
   */
  tart.Tabs.prototype.initOptions = function(options) {
      var props = this.props = {};
      props.axis = options.axis || 'x';
      this.activeTab = options.activeTab || 0;
  
      props.renderConfig = options.renderConfig || {};
  
      props.tabPanelCssClass = options.tabPanelCssClass || '';
      props.tabContainerCssClass = options.tabContainerCssClass || '';
      props.panelContainerCssClass = options.panelContainerCssClass || '';
      props.activeTabCssClass = options.activeTabCssClass || 'tartActiveTab';
      props.activePanelCssClass = options.activePanelCssClass || 'tartActivePanel';
      props.panelWrapperCssClass = options.panelWrapperCssClass || '';
  };
  
  
  /**
   * @return {string} Main container markup.
   */
  tart.Tabs.prototype.templates_dom = function() {
      return '<div class="tartTabPanelContainer ' + this.props.tabPanelCssClass + '"></div>';
  };
  
  
  /**
   * @return {string} Tab container markup.
   */
  tart.Tabs.prototype.templates_tabContainer = function() {
      return '<div class="tartTabContainer ' + this.props.tabContainerCssClass + '"></div>';
  };
  
  
  /**
   * @return {string} Panel container markup.
   */
  tart.Tabs.prototype.templates_panelContainer = function() {
      return '<div class="tartPanelContainer ' + this.props.panelContainerCssClass + '"></div>';
  };
  