chromium/third_party/google-closure-library/closure/goog/ui/editor/tabpane.js

/**
 * @license
 * Copyright The Closure Library Authors.
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Tabbed pane with style and functionality specific to
 * Editor dialogs.
 */

goog.provide('goog.ui.editor.TabPane');

goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.InputType');
goog.require('goog.dom.TagName');
goog.require('goog.dom.classlist');
goog.require('goog.events.EventHandler');
goog.require('goog.events.EventType');
goog.require('goog.style');
goog.require('goog.ui.Component');
goog.require('goog.ui.Control');
goog.require('goog.ui.Tab');
goog.require('goog.ui.TabBar');
goog.requireType('goog.events.Event');



/**
 * Creates a new Editor-style tab pane.
 * @param {goog.dom.DomHelper} dom The dom helper for the window to create this
 *     tab pane in.
 * @param {string=} opt_caption Optional caption of the tab pane.
 * @constructor
 * @extends {goog.ui.Component}
 * @final
 */
goog.ui.editor.TabPane = function(dom, opt_caption) {
  'use strict';
  goog.ui.editor.TabPane.base(this, 'constructor', dom);

  /**
   * The event handler used to register events.
   * @type {goog.events.EventHandler<!goog.ui.editor.TabPane>}
   * @private
   */
  this.eventHandler_ = new goog.events.EventHandler(this);
  this.registerDisposable(this.eventHandler_);

  /**
   * The tab bar used to render the tabs.
   * @type {goog.ui.TabBar}
   * @private
   */
  this.tabBar_ =
      new goog.ui.TabBar(goog.ui.TabBar.Location.START, undefined, this.dom_);
  this.tabBar_.setFocusable(false);

  /**
   * The content element.
   * @private
   */
  this.tabContent_ = this.dom_.createDom(
      goog.dom.TagName.DIV, {className: goog.getCssName('goog-tab-content')});

  /**
   * The currently selected radio button.
   * @type {?Element}
   * @private
   */
  this.selectedRadio_ = null;

  /**
   * The currently visible tab content.
   * @type {?Element}
   * @private
   */
  this.visibleContent_ = null;


  // Add the caption as the first element in the tab bar.
  if (opt_caption) {
    const captionControl =
        new goog.ui.Control(opt_caption, undefined, this.dom_);
    captionControl.addClassName(goog.getCssName('tr-tabpane-caption'));
    captionControl.setEnabled(false);
    this.tabBar_.addChild(captionControl, true);
  }
};
goog.inherits(goog.ui.editor.TabPane, goog.ui.Component);


/**
 * @return {string} The ID of the content element for the current tab.
 */
goog.ui.editor.TabPane.prototype.getCurrentTabId = function() {
  'use strict';
  return this.tabBar_.getSelectedTab().getId();
};


/**
 * Selects the tab with the given id.
 * @param {string} id Id of the tab to select.
 */
goog.ui.editor.TabPane.prototype.setSelectedTabId = function(id) {
  'use strict';
  this.tabBar_.setSelectedTab(this.tabBar_.getChild(id));
};


/**
 * Adds a tab to the tab pane.
 * @param {string} id The id of the tab to add.
 * @param {string} caption The caption of the tab.
 * @param {string} tooltip The tooltip for the tab.
 * @param {string} groupName for the radio button group.
 * @param {Element} content The content element to show when this tab is
 *     selected.
 */
goog.ui.editor.TabPane.prototype.addTab = function(
    id, caption, tooltip, groupName, content) {
  'use strict';
  const radio = this.dom_.createDom(
      goog.dom.TagName.INPUT,
      {name: groupName, type: goog.dom.InputType.RADIO});

  const tab = new goog.ui.Tab(
      [radio, this.dom_.createTextNode(caption)], undefined, this.dom_);
  tab.setId(id);
  tab.setTooltip(tooltip);
  this.tabBar_.addChild(tab, true);

  // When you navigate the radio buttons with TAB and then the Arrow keys on
  // Chrome and FF, you get a CLICK event on them, and the radio button
  // is selected.  You don't get a SELECT at all.  We listen for SELECT
  // nonetheless because it's possible that some browser will issue only
  // SELECT.
  this.eventHandler_.listen(
      radio, [goog.events.EventType.SELECT, goog.events.EventType.CLICK],
      goog.bind(this.tabBar_.setSelectedTab, this.tabBar_, tab));

  content.id = id + '-tab';
  this.tabContent_.appendChild(content);
  goog.style.setElementShown(content, false);
};


/** @override */
goog.ui.editor.TabPane.prototype.enterDocument = function() {
  'use strict';
  goog.ui.editor.TabPane.base(this, 'enterDocument');

  // Get the root element and add a class name to it.
  const root = this.getElement();
  goog.asserts.assert(root);
  goog.dom.classlist.add(root, goog.getCssName('tr-tabpane'));

  // Add the tabs.
  this.addChild(this.tabBar_, true);
  this.eventHandler_.listen(
      this.tabBar_, goog.ui.Component.EventType.SELECT, this.handleTabSelect_);

  // Add the tab content.
  root.appendChild(this.tabContent_);

  // Add an element to clear the tab float.
  root.appendChild(this.dom_.createDom(goog.dom.TagName.DIV, {
    className: goog.getCssName('goog-tab-bar-clear')
  }));
};


/**
 * Handles a tab change.
 * @param {goog.events.Event} e The browser change event.
 * @private
 * @suppress {strictMissingProperties} Part of the go/strict_warnings_migration
 */
goog.ui.editor.TabPane.prototype.handleTabSelect_ = function(e) {
  'use strict';
  const tab = /** @type {goog.ui.Tab} */ (e.target);

  // Show the tab content.
  if (this.visibleContent_) {
    goog.style.setElementShown(this.visibleContent_, false);
  }
  this.visibleContent_ = this.dom_.getElement(tab.getId() + '-tab');
  goog.style.setElementShown(this.visibleContent_, true);

  // Select the appropriate radio button (and deselect the current one).
  if (this.selectedRadio_) {
    this.selectedRadio_.checked = false;
  }
  this.selectedRadio_ = goog.dom.getElementsByTagName(
      goog.dom.TagName.INPUT, tab.getElementStrict())[0];
  this.selectedRadio_.checked = true;
};