OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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 * Controller and View for switching between tabs. |
| 7 * |
| 8 * The View part of TabSwitcherView displays the contents of the currently |
| 9 * selected tab (only one tab can be active at a time). |
| 10 * |
| 11 * The controller part of TabSwitcherView hooks up a dropdown menu (i.e. HTML |
| 12 * SELECT) to control switching between tabs. |
| 13 */ |
| 14 var TabSwitcherView = (function() { |
| 15 'use strict'; |
| 16 |
| 17 // We inherit from View. |
| 18 var superClass = View; |
| 19 |
| 20 var TAB_LIST_ID = 'tab-list'; |
| 21 |
| 22 /** |
| 23 * @constructor |
| 24 * |
| 25 * @param {?Function} opt_onTabSwitched Optional callback to run when the |
| 26 * active tab changes. Called as |
| 27 * opt_onTabSwitched(oldTabId, newTabId). |
| 28 */ |
| 29 function TabSwitcherView(opt_onTabSwitched) { |
| 30 assertFirstConstructorCall(TabSwitcherView); |
| 31 |
| 32 this.tabIdToView_ = {}; |
| 33 this.tabIdToLink_ = {}; |
| 34 // Ordered list of views. |
| 35 this.viewList_ = []; |
| 36 this.activeTabId_ = null; |
| 37 |
| 38 this.onTabSwitched_ = opt_onTabSwitched; |
| 39 |
| 40 // The ideal width of the tab list. If width is reduced below this, the |
| 41 // tab list will be shrunk, but it will be returned to this width once it |
| 42 // can be. |
| 43 this.tabListWidth_ = $(TAB_LIST_ID).offsetWidth; |
| 44 |
| 45 superClass.call(this); |
| 46 } |
| 47 |
| 48 TabSwitcherView.prototype = { |
| 49 // Inherit the superclass's methods. |
| 50 __proto__: superClass.prototype, |
| 51 |
| 52 // --------------------------------------------- |
| 53 // Override methods in View |
| 54 // --------------------------------------------- |
| 55 |
| 56 setGeometry: function(left, top, width, height) { |
| 57 superClass.prototype.setGeometry.call(this, left, top, width, height); |
| 58 |
| 59 var tabListNode = $(TAB_LIST_ID); |
| 60 |
| 61 // Set position of the tab list. Can't use DivView because DivView sets |
| 62 // a fixed width at creation time, and need to set the width of the tab |
| 63 // list only after its been populated. |
| 64 var tabListWidth = this.tabListWidth_; |
| 65 if (tabListWidth > width) |
| 66 tabListWidth = width; |
| 67 tabListNode.style.position = 'absolute'; |
| 68 setNodePosition(tabListNode, left, top, tabListWidth, height); |
| 69 |
| 70 // Position each of the tab's content areas. |
| 71 for (var tabId in this.tabIdToView_) { |
| 72 var view = this.tabIdToView_[tabId]; |
| 73 view.setGeometry(left + tabListWidth, top, width - tabListWidth, |
| 74 height); |
| 75 } |
| 76 }, |
| 77 |
| 78 show: function(isVisible) { |
| 79 superClass.prototype.show.call(this, isVisible); |
| 80 var activeView = this.getActiveTabView(); |
| 81 if (activeView) |
| 82 activeView.show(isVisible); |
| 83 }, |
| 84 |
| 85 // --------------------------------------------- |
| 86 |
| 87 /** |
| 88 * Adds a new tab (initially hidden). To ensure correct tab list sizing, |
| 89 * may only be called before first layout. |
| 90 * |
| 91 * @param {string} tabId The ID to refer to the tab by. |
| 92 * @param {!View} view The tab's actual contents. |
| 93 * @param {string} name The name for the menu item that selects the tab. |
| 94 */ |
| 95 addTab: function(tabId, view, name, hash) { |
| 96 if (!tabId) { |
| 97 throw Error('Must specify a non-false tabId'); |
| 98 } |
| 99 |
| 100 this.tabIdToView_[tabId] = view; |
| 101 this.viewList_.push(view); |
| 102 |
| 103 var node = addNodeWithText($(TAB_LIST_ID), 'a', name); |
| 104 node.href = hash; |
| 105 this.tabIdToLink_[tabId] = node; |
| 106 addNode($(TAB_LIST_ID), 'br'); |
| 107 |
| 108 // Tab content views start off hidden. |
| 109 view.show(false); |
| 110 |
| 111 this.tabListWidth_ = $(TAB_LIST_ID).offsetWidth; |
| 112 }, |
| 113 |
| 114 showTabLink: function(tabId, isVisible) { |
| 115 var wasActive = this.activeTabId_ == tabId; |
| 116 |
| 117 setNodeDisplay(this.tabIdToLink_[tabId], isVisible); |
| 118 |
| 119 if (wasActive && !isVisible) { |
| 120 // If the link for active tab is being hidden, then switch to the first |
| 121 // tab which is still visible. |
| 122 for (var view in this.viewList_) { |
| 123 if (view.isVisible()) |
| 124 this.switchToTab(option.value); |
| 125 } |
| 126 } |
| 127 }, |
| 128 |
| 129 getAllTabViews: function() { |
| 130 return this.tabIdToView_; |
| 131 }, |
| 132 |
| 133 getTabView: function(tabId) { |
| 134 return this.tabIdToView_[tabId]; |
| 135 }, |
| 136 |
| 137 getActiveTabView: function() { |
| 138 return this.tabIdToView_[this.activeTabId_]; |
| 139 }, |
| 140 |
| 141 getActiveTabId: function() { |
| 142 return this.activeTabId_; |
| 143 }, |
| 144 |
| 145 /** |
| 146 * Changes the currently active tab to |tabId|. This has several effects: |
| 147 * (1) Replace the tab contents view with that of the new tab. |
| 148 * (2) Update the dropdown menu's current selection. |
| 149 * (3) Invoke the optional onTabSwitched callback. |
| 150 */ |
| 151 switchToTab: function(tabId) { |
| 152 var newView = this.getTabView(tabId); |
| 153 |
| 154 if (!newView) { |
| 155 throw Error('Invalid tabId'); |
| 156 } |
| 157 |
| 158 var oldTabId = this.activeTabId_; |
| 159 this.activeTabId_ = tabId; |
| 160 |
| 161 if (oldTabId) { |
| 162 this.tabIdToLink_[oldTabId].classList.remove('selected'); |
| 163 // Hide the previously visible tab contents. |
| 164 this.getTabView(oldTabId).show(false); |
| 165 } |
| 166 |
| 167 this.tabIdToLink_[tabId].classList.add('selected'); |
| 168 |
| 169 newView.show(this.isVisible()); |
| 170 |
| 171 if (this.onTabSwitched_) |
| 172 this.onTabSwitched_(oldTabId, tabId); |
| 173 }, |
| 174 }; |
| 175 |
| 176 return TabSwitcherView; |
| 177 })(); |
| 178 |
OLD | NEW |