• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * A TabView provides the ability to create tabs and switch between tabs. It's
7 * responsible for creating the DOM and managing the visibility of each tab.
8 * The first added tab is active by default and the others hidden.
9 */
10var TabView = (function() {
11  'use strict';
12
13  /**
14   * @constructor
15   * @param {Element} root The root DOM element containing the tabs.
16   */
17  function TabView(root) {
18    this.root_ = root;
19    this.ACTIVE_TAB_HEAD_CLASS_ = 'active-tab-head';
20    this.ACTIVE_TAB_BODY_CLASS_ = 'active-tab-body';
21    this.TAB_HEAD_CLASS_ = 'tab-head';
22    this.TAB_BODY_CLASS_ = 'tab-body';
23
24    /**
25     * A mapping for an id to the tab elements.
26     * @type {!Object<string, !TabDom>}
27     * @private
28     */
29    this.tabElements_ = {};
30
31    this.headBar_ = null;
32    this.activeTabId_ = null;
33    this.initializeHeadBar_();
34  }
35
36  // Creates a simple object containing the tab head and body elements.
37  function TabDom(h, b) {
38    this.head = h;
39    this.body = b;
40  }
41
42  TabView.prototype = {
43    /**
44     * Adds a tab with the specified id and title.
45     * @param {string} id
46     * @param {string} title
47     * @return {!Element} The tab body element.
48     */
49    addTab: function(id, title) {
50      if (this.tabElements_[id])
51        throw 'Tab already exists: ' + id;
52
53      var head = document.createElement('div');
54      head.className = this.TAB_HEAD_CLASS_;
55      head.textContent = id;
56      head.title = title;
57      this.headBar_.appendChild(head);
58      head.addEventListener('click', this.switchTab_.bind(this, id));
59
60      var body = document.createElement('div');
61      body.className = this.TAB_BODY_CLASS_;
62      body.id = id;
63      this.root_.appendChild(body);
64
65      this.tabElements_[id] = new TabDom(head, body);
66
67      if (!this.activeTabId_) {
68        this.switchTab_(id);
69      }
70      return this.tabElements_[id].body;
71    },
72
73    /** Removes the tab. @param {string} id */
74    removeTab: function(id) {
75      if (!this.tabElements_[id])
76        return;
77      this.tabElements_[id].head.parentNode.removeChild(
78          this.tabElements_[id].head);
79      this.tabElements_[id].body.parentNode.removeChild(
80          this.tabElements_[id].body);
81
82      delete this.tabElements_[id];
83      if (this.activeTabId_ == id) {
84        this.switchTab_(Object.keys(this.tabElements_)[0]);
85      }
86    },
87
88    /**
89     * Switches the specified tab into view.
90     *
91     * @param {string} activeId The id the of the tab that should be switched to
92     *     active state.
93     * @private
94     */
95    switchTab_: function(activeId) {
96      if (this.activeTabId_ && this.tabElements_[this.activeTabId_]) {
97        this.tabElements_[this.activeTabId_].body.classList.remove(
98            this.ACTIVE_TAB_BODY_CLASS_);
99        this.tabElements_[this.activeTabId_].head.classList.remove(
100            this.ACTIVE_TAB_HEAD_CLASS_);
101      }
102      this.activeTabId_ = activeId;
103      if (this.tabElements_[activeId]) {
104        this.tabElements_[activeId].body.classList.add(
105            this.ACTIVE_TAB_BODY_CLASS_);
106        this.tabElements_[activeId].head.classList.add(
107            this.ACTIVE_TAB_HEAD_CLASS_);
108      }
109    },
110
111    /** Initializes the bar containing the tab heads. */
112    initializeHeadBar_: function() {
113      this.headBar_ = document.createElement('div');
114      this.root_.appendChild(this.headBar_);
115      this.headBar_.style.textAlign = 'center';
116    },
117  };
118  return TabView;
119})();
120