Skip to content

Commit

Permalink
feat(tabs): track tab selecting history, create previousTab() method
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdbradley committed Jun 8, 2016
1 parent 6f8f2ab commit d98f3c9
Show file tree
Hide file tree
Showing 2 changed files with 251 additions and 17 deletions.
56 changes: 39 additions & 17 deletions src/components/tabs/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ import {ViewController} from '../nav/view-controller';
'</ion-navbar-section>' +
'<ion-tabbar-section>' +
'<tabbar role="tablist">' +
'<a *ngFor="let t of _tabs" [tab]="t" class="tab-button" [class.tab-disabled]="!t.enabled" [class.tab-hidden]="!t.show" role="tab" href="#">' +
'<a *ngFor="let t of _tabs" [tab]="t" class="tab-button" [class.tab-disabled]="!t.enabled" [class.tab-hidden]="!t.show" role="tab" href="#" (ionSelect)="select($event)">' +
'<ion-icon *ngIf="t.tabIcon" [name]="t.tabIcon" [isActive]="t.isSelected" class="tab-button-icon"></ion-icon>' +
'<span *ngIf="t.tabTitle" class="tab-button-text">{{t.tabTitle}}</span>' +
'<ion-badge *ngIf="t.tabBadge" class="tab-badge" [ngClass]="\'badge-\' + t.tabBadgeStyle">{{t.tabBadge}}</ion-badge>' +
Expand Down Expand Up @@ -175,6 +175,11 @@ export class Tabs extends Ion {
*/
navbarContainerRef: ViewContainerRef;

/**
* @private
*/
selectHistory: string[] = [];

/**
* @private
*/
Expand Down Expand Up @@ -213,12 +218,7 @@ export class Tabs extends Ion {
/**
* @private
*/
@ViewChildren(TabButton) private _btns: any;

/**
* @private
*/
parent: any;
parent: NavController;

constructor(
@Optional() parent: NavController,
Expand Down Expand Up @@ -271,12 +271,6 @@ export class Tabs extends Ion {
});
}

this._btns.toArray().forEach((tabButton: TabButton) => {
tabButton.ionSelect.subscribe((tab: Tab) => {
this.select(tab);
});
});

let preloadTabs = (isBlank(this.preloadTabs) ? this._config.getBoolean('preloadTabs') : isTrueProperty(this.preloadTabs));

// get the selected index
Expand Down Expand Up @@ -333,11 +327,11 @@ export class Tabs extends Ion {
}

/**
* @param {number} index Index of the tab you want to select
* @param {number|Tab} tabOrIndex Index, or the Tab instance, of the tab to select.
*/
select(tabOrIndex: any) {
let selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
if (!selectedTab) {
select(tabOrIndex: number | Tab) {
let selectedTab: Tab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
if (isBlank(selectedTab)) {
return;
}

Expand Down Expand Up @@ -390,9 +384,37 @@ export class Tabs extends Ion {
this._onReady = null;
}

// track the order of which tabs have been selected, by their index
// do not track if the tab index is the same as the previous
if (this.selectHistory[this.selectHistory.length - 1] !== selectedTab.id) {
this.selectHistory.push(selectedTab.id);
}

});
}

/**
* Get the previously selected Tab which is currently not disabled or hidden.
* @param {boolean} trimHistory If the selection history should be trimmed up to the previous tab selection or not.
* @returns {Tab}
*/
previousTab(trimHistory: boolean = true): Tab {
// walk backwards through the tab selection history
// and find the first previous tab that is enabled and shown
console.log('run previousTab', this.selectHistory)
for (var i = this.selectHistory.length - 2; i >= 0; i--) {
var tab = this._tabs.find(t => t.id === this.selectHistory[i]);
if (tab && tab.enabled && tab.show) {
if (trimHistory) {
this.selectHistory.splice(i + 1);
}
return tab;
}
}

return null;
}

/**
* @param {number} index Index of the tab you want to get
* @returns {Tab} Returns the tab who's index matches the one passed
Expand Down
212 changes: 212 additions & 0 deletions src/components/tabs/test/tabs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import {Component} from '@angular/core';
import {App, Nav, Tabs, Tab, NavOptions, Config, ViewController, Platform} from '../../../../src';

export function run() {

describe('Tabs', () => {

describe('previousTab', () => {

it('should find the previous tab when there has been 3 selections', () => {
var tabs = mockTabs();
var tab0 = mockTab(tabs);
var tab1 = mockTab(tabs);
var tab2 = mockTab(tabs);
tabs.add(tab0);
tabs.add(tab1);
tabs.add(tab2);
tab0.root = SomePage;
tab1.root = SomePage;
tab2.root = SomePage;

tabs.select(tab0);
tabs.select(tab1);
tabs.select(tab2);

expect(tabs.selectHistory).toEqual([tab0.id, tab1.id, tab2.id]);

expect(tabs.previousTab(true)).toEqual(tab1);
expect(tabs.selectHistory).toEqual([tab0.id, tab1.id]);

expect(tabs.previousTab(true)).toEqual(tab0);
expect(tabs.selectHistory).toEqual([tab0.id]);
});

it('should not find a previous tab when there has only been one selection', () => {
var tabs = mockTabs();
var tab0 = mockTab(tabs);
var tab1 = mockTab(tabs);
tabs.add(tab0);
tabs.add(tab1);
tab0.root = SomePage;
tab1.root = SomePage;

tabs.select(tab0);

expect(tabs.previousTab(true)).toEqual(null);
});

it('should not find a previous tab when theres no history', () => {
var tabs = mockTabs();
expect(tabs.selectHistory.length).toEqual(0);
expect(tabs.previousTab(true)).toEqual(null);
});

it('should track tab selections', () => {
var tabs = mockTabs();
var tab0 = mockTab(tabs);
var tab1 = mockTab(tabs);
tabs.add(tab0);
tabs.add(tab1);
tab0.root = SomePage;
tab1.root = SomePage;

expect(tabs.selectHistory.length).toEqual(0);

tabs.select(tab0);
expect(tabs.selectHistory[0]).toEqual(tab0.id);
expect(tabs.selectHistory.length).toEqual(1);

tabs.select(tab1);
expect(tabs.selectHistory[0]).toEqual(tab0.id);
expect(tabs.selectHistory[1]).toEqual(tab1.id);
expect(tabs.selectHistory.length).toEqual(2);

tabs.select(tab0);
expect(tabs.selectHistory[0]).toEqual(tab0.id);
expect(tabs.selectHistory[1]).toEqual(tab1.id);
expect(tabs.selectHistory[2]).toEqual(tab0.id);
expect(tabs.selectHistory.length).toEqual(3);
});

});

describe('select', () => {

it('should select tab by tab instance', () => {
var tabs = mockTabs();
var tab0 = mockTab(tabs);
var tab1 = mockTab(tabs);
tabs.add(tab0);
tabs.add(tab1);

tab0.root = SomePage;
tab1.root = SomePage;

tabs.select(tab1);

expect(tab0.isSelected).toEqual(false);
expect(tab1.isSelected).toEqual(true);
});

it('should select tab by index', () => {
var tabs = mockTabs();
var tab0 = mockTab(tabs);
var tab1 = mockTab(tabs);
tabs.add(tab0);
tabs.add(tab1);

tab0.root = SomePage;
tab1.root = SomePage;

expect(tab0.isSelected).toBeUndefined();
expect(tab1.isSelected).toBeUndefined();

tabs.select(0);

expect(tab0.isSelected).toEqual(true);
expect(tab1.isSelected).toEqual(false);
});

it('should not select an invalid tab index', () => {
var tabs = mockTabs();
var tab0 = mockTab(tabs);
var tab1 = mockTab(tabs);
tabs.add(tab0);
tabs.add(tab1);

expect(tabs.select(22)).toBeUndefined();
});

});

describe('getByIndex', () => {

it('should get the tab', () => {
var tabs = mockTabs();
var tab0 = mockTab(tabs);
tab0.setRoot()
var tab1 = mockTab(tabs);
tabs.add(tab0);
tabs.add(tab1);

expect(tabs.getIndex(tab0)).toEqual(0);
expect(tabs.getIndex(tab1)).toEqual(1);
});

});

describe('getSelected', () => {

it('should get the selected tab', () => {
var tabs = mockTabs();
var tab0 = mockTab(tabs);
var tab1 = mockTab(tabs);
tabs.add(tab0);
tabs.add(tab1);

tab1.setSelected(true);

expect(tabs.getSelected()).toEqual(tab1);
});

it('should get null if no selected tab', () => {
var tabs = mockTabs();
var tab0 = mockTab(tabs);
var tab1 = mockTab(tabs);
tabs.add(tab0);
tabs.add(tab1);

expect(tabs.getSelected()).toEqual(null);
});

});

var app: App;
var config: Config;
var platform: Platform;
var _cd: any;

function mockNav(): Nav {
return new Nav(null, null, null, config, null, null, null, null, null);
}

function mockTabs(): Tabs {
return new Tabs(null, null, null, config, null, null, null);
}

function mockTab(parentTabs: Tabs): Tab {
var tab = new Tab(parentTabs, app, config, null, null, null, null, null, _cd);
tab.load = function(opts: any, cb: Function) {
cb();
};
return tab;
}

@Component({})
class SomePage {}

beforeEach(() => {
config = new Config();
platform = new Platform();
app = new App(config, null, platform);
_cd = {
reattach: function(){},
detach: function(){}
};
});

});


}

0 comments on commit d98f3c9

Please sign in to comment.