1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {$} from 'chrome://resources/js/util.js';
import {addNode, addNodeWithText, setNodeDisplay, setNodePosition} from './util.js';
import {View} from './view.js';
const TAB_LIST_ID = 'tab-list';
/** @type {?TabSwitcherView} */
let instance = null;
/**
* 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.
*/
export class TabSwitcherView extends View {
constructor() {
super();
this.tabIdToView_ = {};
this.tabIdToLink_ = {};
// Map from tab id to the views link visiblity.
this.tabIdsLinkVisibility_ = new Map();
this.activeTabId_ = null;
this.onTabSwitched_ = null;
// 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;
}
/**
* @param {!Function} onTabSwitched Callback to run when the
* active tab changes. Called as
* onTabSwitched(oldTabId, newTabId).
*/
setOnTabSwitched(onTabSwitched) {
this.onTabSwitched_ = onTabSwitched;
}
// ---------------------------------------------
// Override methods in View
// ---------------------------------------------
setGeometry(left, top, width, height) {
super.setGeometry(this, left, top, width, height);
const 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.
let 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 (const tabId in this.tabIdToView_) {
const view = this.tabIdToView_[tabId];
view.setGeometry(left + tabListWidth, top, width - tabListWidth, height);
}
}
show(isVisible) {
super.show(isVisible);
const 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(tabId, view, name, hash) {
if (!tabId) {
throw Error('Must specify a non-false tabId');
}
this.tabIdToView_[tabId] = view;
this.tabIdsLinkVisibility_.set(tabId, true);
const 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;
}
getAllTabViews() {
return this.tabIdToView_;
}
getTabView(tabId) {
return this.tabIdToView_[tabId];
}
getActiveTabView() {
return this.tabIdToView_[this.activeTabId_];
}
getActiveTabId() {
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(tabId) {
const newView = this.getTabView(tabId);
if (!newView) {
throw Error('Invalid tabId');
}
const 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);
}
}
static getInstance() {
return instance || (instance = new TabSwitcherView());
}
}
|