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 */ 14var TabSwitcherView = (function() { 15 'use strict'; 16 17 // We inherit from View. 18 var superClass = View; 19 20 /** 21 * @constructor 22 * 23 * @param {DOMSelectNode} dropdownMenu The menu for switching between tabs. 24 * The TabSwitcherView will attach an onchange event to 25 * the dropdown menu, and control the selected index. 26 * @param {?Function} opt_onTabSwitched Optional callback to run when the 27 * active tab changes. Called as 28 * opt_onTabSwitched(oldTabId, newTabId). 29 */ 30 function TabSwitcherView(dropdownMenu, opt_onTabSwitched) { 31 assertFirstConstructorCall(TabSwitcherView); 32 33 this.tabIdToView_ = {}; 34 this.activeTabId_ = null; 35 36 this.dropdownMenu_ = dropdownMenu; 37 this.dropdownMenu_.onchange = this.onMenuSelectionChanged_.bind(this); 38 39 this.onTabSwitched_ = opt_onTabSwitched; 40 41 superClass.call(this); 42 } 43 44 TabSwitcherView.prototype = { 45 // Inherit the superclass's methods. 46 __proto__: superClass.prototype, 47 48 // --------------------------------------------- 49 // Override methods in View 50 // --------------------------------------------- 51 52 setGeometry: function(left, top, width, height) { 53 superClass.prototype.setGeometry.call(this, left, top, width, height); 54 55 // Position each of the tabs content areas. 56 for (var tabId in this.tabIdToView_) { 57 var view = this.tabIdToView_[tabId]; 58 view.setGeometry(left, top, width, height); 59 } 60 }, 61 62 show: function(isVisible) { 63 superClass.prototype.show.call(this, isVisible); 64 var activeView = this.getActiveTabView(); 65 if (activeView) 66 activeView.show(isVisible); 67 }, 68 69 // --------------------------------------------- 70 71 /** 72 * Adds a new tab (initially hidden). 73 * 74 * @param {string} tabId The ID to refer to the tab by. 75 * @param {!View} view The tab's actual contents. 76 * @param {string} name The name for the menu item that selects the tab. 77 */ 78 addTab: function(tabId, view, name) { 79 if (!tabId) { 80 throw Error('Must specify a non-false tabId'); 81 } 82 83 this.tabIdToView_[tabId] = view; 84 85 // Tab content views start off hidden. 86 view.show(false); 87 88 // Add it to the dropdown menu. 89 var menuItem = addNode(this.dropdownMenu_, 'option'); 90 menuItem.value = tabId; 91 menuItem.textContent = name; 92 }, 93 94 showMenuItem: function(tabId, isVisible) { 95 var wasActive = this.activeTabId_ == tabId; 96 97 // Hide the menuitem from the list. Note it needs to be 'disabled' to 98 // prevent it being selectable from keyboard. 99 var menuitem = this.getMenuItemNode_(tabId); 100 setNodeDisplay(menuitem, isVisible); 101 menuitem.disabled = !isVisible; 102 103 if (wasActive && !isVisible) { 104 // If the active tab is being hidden in the dropdown menu, then 105 // switch to the first tab which is still visible. 106 for (var i = 0; i < this.dropdownMenu_.options.length; ++i) { 107 var option = this.dropdownMenu_.options[i]; 108 if (option.style.display != 'none') { 109 this.switchToTab(option.value); 110 break; 111 } 112 } 113 } 114 }, 115 116 getAllTabViews: function() { 117 return this.tabIdToView_; 118 }, 119 120 getTabView: function(tabId) { 121 return this.tabIdToView_[tabId]; 122 }, 123 124 getActiveTabView: function() { 125 return this.tabIdToView_[this.activeTabId_]; 126 }, 127 128 getActiveTabId: function() { 129 return this.activeTabId_; 130 }, 131 132 /** 133 * Changes the currently active tab to |tabId|. This has several effects: 134 * (1) Replace the tab contents view with that of the new tab. 135 * (2) Update the dropdown menu's current selection. 136 * (3) Invoke the optional onTabSwitched callback. 137 */ 138 switchToTab: function(tabId) { 139 var newView = this.getTabView(tabId); 140 141 if (!newView) { 142 throw Error('Invalid tabId'); 143 } 144 145 var oldTabId = this.activeTabId_; 146 this.activeTabId_ = tabId; 147 148 this.dropdownMenu_.value = tabId; 149 150 // Hide the previously visible tab contents. 151 if (oldTabId) 152 this.getTabView(oldTabId).show(false); 153 154 newView.show(this.isVisible()); 155 156 if (this.onTabSwitched_) 157 this.onTabSwitched_(oldTabId, tabId); 158 }, 159 160 getMenuItemNode_: function(tabId) { 161 for (var i = 0; i < this.dropdownMenu_.options.length; ++i) { 162 var option = this.dropdownMenu_.options[i]; 163 if (option.value == tabId) { 164 return option; 165 } 166 } 167 return null; 168 }, 169 170 onMenuSelectionChanged_: function(event) { 171 var tabId = this.dropdownMenu_.value; 172 this.switchToTab(tabId); 173 }, 174 }; 175 176 return TabSwitcherView; 177})(); 178