import { IComponentController } from 'angular' import _ from 'lodash' import { Component, Input } from '../decorators' import { ActiveTabColor } from '../style-typings/styles' import TabController from './tab' @Component({ selector: 'mflyTabGroup', template: require('./tab-group.html'), transclude: true, }) export default class TabGroupController implements IComponentController { @Input('=') activeTab: string @Input() activeTabColor: string protected activeTabStyle: ActiveTabColor protected allTabsHidden: boolean protected tabs: TabController[] = [] private bypassWatch: boolean = false $onChanges(changes: { activeTab: ng.IChangesObject, activeTabColor: ng.IChangesObject }) { // setup style object if (changes.activeTabColor.previousValue !== changes.activeTabColor.currentValue) { this.activeTabStyle = { 'color': this.activeTabColor, 'border-bottom-color': this.activeTabColor } } // if the watch is called with a bypass we flip the boolean and // perform no further execution if (this.bypassWatch) { this.bypassWatch = false return } if (changes.activeTab) { // find the desired tab const newActiveTab = _.find(this.tabs, {tabId: changes.activeTab.currentValue}) // if it is found, activate it and disabled all others if (newActiveTab) { this.activateTab(newActiveTab, { updateSetActive: false, processCallbacks: false}) } } } // Individual tabs call this controller function so that the tab set // knows how many tabs to create and what their labels should be. registerTab(tab: TabController): void { if (this.tabs.length === 0 && !this.activeTab) { this.activeTab = tab.tabId } this.tabs.push(tab) } // when the active tab is hidden we need to activate the first (non-hidden) tab onTabHideChange(tab: TabController) { // if we are setting a tab to visible, but all tabs where previously hidded we need to display and activate if (!tab.isHidden && this.allTabsHidden) { this.activateFirstVisibleTab() this.allTabsHidden = false return } // if we set a tab to visible, but another visible tab exists we can exit if (!tab.isHidden) { return } // since we are hiding a tab we may need to update all tabs hidden this.allTabsHidden = !this.hasVisibleTab() // since we are hiding the currently active tab we should try to activate another visible tab if (this.activeTab === tab.tabId) { this.activateFirstVisibleTab() } } protected startTabChange = (selectedTab) => { // don't do anything for disabled tag if (selectedTab.isDisabled) { return } const currentTab = _.find(this.tabs, {tabId: this.activeTab}) if (currentTab && !_.isUndefined(currentTab.tabChangeStart)) { const response = currentTab.tabChangeStart(selectedTab) if (!_.isUndefined(response) && !_.isUndefined(response.then)) { response.then(() => { // resolved successfully this.activateTab(selectedTab, { updateSetActive: true, processCallbacks: true}) }) } else { // not a good promise default to accepting the tab switch this.activateTab(selectedTab, { updateSetActive: true, processCallbacks: true}) } } else { // no onChange function, default to accept the tab switch this.activateTab(selectedTab, { updateSetActive: true, processCallbacks: true}) } } private activateTab(tabToActivate: TabController, options) { _.each(this.tabs, (tab) => { if (tab.tabId === tabToActivate.tabId) { this.activeTab = tabToActivate.tabId if (options.updateSetActive) { this.bypassWatch = true this.activeTab = tabToActivate.tabId // reset bypass for watch this.bypassWatch = false } if (options.processCallbacks) { if (!_.isUndefined(tab.tabWhenClicked)) { tab.tabWhenClicked() } } } }) } private hasVisibleTab(): boolean { let tabFound: boolean = false _.each(this.tabs, (t) => { if (t && !t.isHidden) { tabFound = true return false } return }) return tabFound } // returns true if there is a non-hidden tab to activage, otherwise false private activateFirstVisibleTab() { _.each(this.tabs, (t) => { if (t && !t.isHidden) { this.activateTab(t, {updateSetActive: false, processCallbacks: false}) return false } return }) } }