Index: netlog_viewer/tab_switcher_view.js |
diff --git a/netlog_viewer/tab_switcher_view.js b/netlog_viewer/tab_switcher_view.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..01b3c7d176b936d38f5a5f3102591fb03cfce02b |
--- /dev/null |
+++ b/netlog_viewer/tab_switcher_view.js |
@@ -0,0 +1,178 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+/** |
+ * Controller and View for switching between tabs. |
+ * |
+ * The View part of TabSwitcherView displays the contents of the currently |
+ * selected tab (only one tab can be active at a time). |
+ * |
+ * The controller part of TabSwitcherView hooks up a dropdown menu (i.e. HTML |
+ * SELECT) to control switching between tabs. |
+ */ |
+var TabSwitcherView = (function() { |
+ 'use strict'; |
+ |
+ // We inherit from View. |
+ var superClass = View; |
+ |
+ var TAB_LIST_ID = 'tab-list'; |
+ |
+ /** |
+ * @constructor |
+ * |
+ * @param {?Function} opt_onTabSwitched Optional callback to run when the |
+ * active tab changes. Called as |
+ * opt_onTabSwitched(oldTabId, newTabId). |
+ */ |
+ function TabSwitcherView(opt_onTabSwitched) { |
+ assertFirstConstructorCall(TabSwitcherView); |
+ |
+ this.tabIdToView_ = {}; |
+ this.tabIdToLink_ = {}; |
+ // Ordered list of views. |
+ this.viewList_ = []; |
+ this.activeTabId_ = null; |
+ |
+ this.onTabSwitched_ = opt_onTabSwitched; |
+ |
+ // The ideal width of the tab list. If width is reduced below this, the |
+ // tab list will be shrunk, but it will be returned to this width once it |
+ // can be. |
+ this.tabListWidth_ = $(TAB_LIST_ID).offsetWidth; |
+ |
+ superClass.call(this); |
+ } |
+ |
+ TabSwitcherView.prototype = { |
+ // Inherit the superclass's methods. |
+ __proto__: superClass.prototype, |
+ |
+ // --------------------------------------------- |
+ // Override methods in View |
+ // --------------------------------------------- |
+ |
+ setGeometry: function(left, top, width, height) { |
+ superClass.prototype.setGeometry.call(this, left, top, width, height); |
+ |
+ var tabListNode = $(TAB_LIST_ID); |
+ |
+ // Set position of the tab list. Can't use DivView because DivView sets |
+ // a fixed width at creation time, and need to set the width of the tab |
+ // list only after its been populated. |
+ var tabListWidth = this.tabListWidth_; |
+ if (tabListWidth > width) |
+ tabListWidth = width; |
+ tabListNode.style.position = 'absolute'; |
+ setNodePosition(tabListNode, left, top, tabListWidth, height); |
+ |
+ // Position each of the tab's content areas. |
+ for (var tabId in this.tabIdToView_) { |
+ var view = this.tabIdToView_[tabId]; |
+ view.setGeometry(left + tabListWidth, top, width - tabListWidth, |
+ height); |
+ } |
+ }, |
+ |
+ show: function(isVisible) { |
+ superClass.prototype.show.call(this, isVisible); |
+ var activeView = this.getActiveTabView(); |
+ if (activeView) |
+ activeView.show(isVisible); |
+ }, |
+ |
+ // --------------------------------------------- |
+ |
+ /** |
+ * Adds a new tab (initially hidden). To ensure correct tab list sizing, |
+ * may only be called before first layout. |
+ * |
+ * @param {string} tabId The ID to refer to the tab by. |
+ * @param {!View} view The tab's actual contents. |
+ * @param {string} name The name for the menu item that selects the tab. |
+ */ |
+ addTab: function(tabId, view, name, hash) { |
+ if (!tabId) { |
+ throw Error('Must specify a non-false tabId'); |
+ } |
+ |
+ this.tabIdToView_[tabId] = view; |
+ this.viewList_.push(view); |
+ |
+ var node = addNodeWithText($(TAB_LIST_ID), 'a', name); |
+ node.href = hash; |
+ this.tabIdToLink_[tabId] = node; |
+ addNode($(TAB_LIST_ID), 'br'); |
+ |
+ // Tab content views start off hidden. |
+ view.show(false); |
+ |
+ this.tabListWidth_ = $(TAB_LIST_ID).offsetWidth; |
+ }, |
+ |
+ showTabLink: function(tabId, isVisible) { |
+ var wasActive = this.activeTabId_ == tabId; |
+ |
+ setNodeDisplay(this.tabIdToLink_[tabId], isVisible); |
+ |
+ if (wasActive && !isVisible) { |
+ // If the link for active tab is being hidden, then switch to the first |
+ // tab which is still visible. |
+ for (var view in this.viewList_) { |
+ if (view.isVisible()) |
+ this.switchToTab(option.value); |
+ } |
+ } |
+ }, |
+ |
+ getAllTabViews: function() { |
+ return this.tabIdToView_; |
+ }, |
+ |
+ getTabView: function(tabId) { |
+ return this.tabIdToView_[tabId]; |
+ }, |
+ |
+ getActiveTabView: function() { |
+ return this.tabIdToView_[this.activeTabId_]; |
+ }, |
+ |
+ getActiveTabId: function() { |
+ return this.activeTabId_; |
+ }, |
+ |
+ /** |
+ * Changes the currently active tab to |tabId|. This has several effects: |
+ * (1) Replace the tab contents view with that of the new tab. |
+ * (2) Update the dropdown menu's current selection. |
+ * (3) Invoke the optional onTabSwitched callback. |
+ */ |
+ switchToTab: function(tabId) { |
+ var newView = this.getTabView(tabId); |
+ |
+ if (!newView) { |
+ throw Error('Invalid tabId'); |
+ } |
+ |
+ var oldTabId = this.activeTabId_; |
+ this.activeTabId_ = tabId; |
+ |
+ if (oldTabId) { |
+ this.tabIdToLink_[oldTabId].classList.remove('selected'); |
+ // Hide the previously visible tab contents. |
+ this.getTabView(oldTabId).show(false); |
+ } |
+ |
+ this.tabIdToLink_[tabId].classList.add('selected'); |
+ |
+ newView.show(this.isVisible()); |
+ |
+ if (this.onTabSwitched_) |
+ this.onTabSwitched_(oldTabId, tabId); |
+ }, |
+ }; |
+ |
+ return TabSwitcherView; |
+})(); |
+ |