This commit is contained in:
Adam Bradley
2015-06-04 16:42:24 -05:00
parent c097a32fbd
commit 02e789649a
4 changed files with 108 additions and 70 deletions

View File

@ -15,6 +15,7 @@ import {NavPane, NavBarSection} from './nav-pane';
import {Transition, ClickBlock} from 'ionic/ionic'; import {Transition, ClickBlock} from 'ionic/ionic';
import * as util from 'ionic/util'; import * as util from 'ionic/util';
let itemsIds = -1;
export class NavBase { export class NavBase {
@ -39,6 +40,9 @@ export class NavBase {
this.sbTransition = null; this.sbTransition = null;
this.sbActive = false; this.sbActive = false;
this.panes = {}; this.panes = {};
this.id = ++itemsIds;
this.childIds = -1;
} }
initial(initial) { initial(initial) {
@ -109,8 +113,8 @@ export class NavBase {
} }
} }
push(Component, params = {}, opts = {}) { push(ComponentClass, params = {}, opts = {}) {
if (!Component || this.isTransitioning()) { if (!ComponentClass || this.isTransitioning()) {
return Promise.reject(); return Promise.reject();
} }
@ -136,13 +140,13 @@ export class NavBase {
leavingItem.willCache(); leavingItem.willCache();
// create a new NavStackItem // create a new NavStackItem
let enteringItem = new NavItem(this, Component, params); let enteringItem = new NavItem(this, ComponentClass, params);
// set that this item is staged (it's not ready to be animated in yet) // set that this item is staged (it's not ready to be animated in yet)
enteringItem.state = STAGED_STATE; enteringItem.state = STAGED_STATE;
// add the item to the stack // add the item to the stack
this.items.push(enteringItem); this.add(enteringItem);
// start the transition // start the transition
this.transition(enteringItem, leavingItem, opts, () => { this.transition(enteringItem, leavingItem, opts, () => {
@ -193,7 +197,25 @@ export class NavBase {
return promise; return promise;
} }
switchActive(enteringItem, opts = {}) {
opts.animation = 'none';
let leavingItem = this.getActive() || new NavItem();
leavingItem.shouldDestroy = false;
leavingItem.shouldCache = true;
leavingItem.willCache();
this.transition(enteringItem, leavingItem, opts, () => {
// transition completed, destroy the leaving item
console.log('switchActive comlete')
});
}
transition(enteringItem, leavingItem, opts, callback) { transition(enteringItem, leavingItem, opts, callback) {
if (!enteringItem || enteringItem === leavingItem) {
return callback();
}
opts.isAnimated = (opts.animation !== 'none'); opts.isAnimated = (opts.animation !== 'none');
this.transitionStart(opts); this.transitionStart(opts);
@ -409,16 +431,6 @@ export class NavBase {
return false; return false;
} }
clear() {
let pops = [];
for(let item of this.items) {
pops.push(this.pop({
animate: false
}));
}
return Promise.all(pops);
}
getActive() { getActive() {
for (let i = 0, ii = this.items.length; i < ii; i++) { for (let i = 0, ii = this.items.length; i < ii; i++) {
if (this.items[i].state === ACTIVE_STATE) { if (this.items[i].state === ACTIVE_STATE) {
@ -428,6 +440,15 @@ export class NavBase {
return null; return null;
} }
findByInstance(instance) {
for (let i = 0, ii = this.items.length; i < ii; i++) {
if (this.items[i].instance === instance) {
return this.items[i];
}
}
return null;
}
getPrevious(item) { getPrevious(item) {
if (item) { if (item) {
return this.items[ this.items.indexOf(item) - 1 ]; return this.items[ this.items.indexOf(item) - 1 ];
@ -457,10 +478,43 @@ export class NavBase {
return this.domElement; return this.domElement;
} }
add(item) {
item.id = this.id + '' + (++this.childIds);
this.items.push(item);
}
remove(itemOrIndex) { remove(itemOrIndex) {
util.array.remove(this.items, itemOrIndex); util.array.remove(this.items, itemOrIndex);
} }
length() {
return this.items.length;
}
isActive(item) {
return (item && item.stage === ACTIVE_STATE);
}
clear() {
let pops = [];
for (let item of this.items) {
pops.push(this.pop({
animate: false
}));
}
return Promise.all(pops);
}
instances() {
let instances = [];
for (let item of this.items) {
if (item.instance) {
instances.push(item.instance);
}
}
return instances
}
width() { width() {
return this.domElement.offsetWidth; return this.domElement.offsetWidth;
} }

View File

@ -11,11 +11,12 @@ import {TabPane, NavPane, NavPaneSection} from './nav';
export class NavItem { export class NavItem {
constructor(navBase, Component, params = {}) { constructor(navBase, ComponentClass, params = {}) {
this.navBase = navBase; this.navBase = navBase;
this.Component = Component; this.ComponentClass = ComponentClass;
this.params = params; this.params = params;
this.id = util.nextUid(); this.instance = null;
this._titleEle = undefined; this._titleEle = undefined;
this._backBtn = undefined; this._backBtn = undefined;
this.disposals = []; this.disposals = [];
@ -40,7 +41,7 @@ export class NavItem {
} }
// compile the Component // compile the Component
this.navBase.compiler.compileInHost(this.Component).then(componentProtoViewRef => { this.navBase.compiler.compileInHost(this.ComponentClass).then(componentProtoViewRef => {
// figure out the sturcture of this Component // figure out the sturcture of this Component
// does it have a navbar? Is it tabs? Should it not have a navbar or any toolbars? // does it have a navbar? Is it tabs? Should it not have a navbar or any toolbars?

View File

@ -50,18 +50,24 @@ export class Tab {
injector: Injector, injector: Injector,
viewContainerRef: ViewContainerRef viewContainerRef: ViewContainerRef
) { ) {
this.navBase = new NavBase(parentNavBase, compiler, elementRef, loader, injector); this.navBase = new NavBase(parentNavBase, compiler, elementRef, loader, injector);
this.parentNavBase = parentNavBase;
this.tabItem = new NavItem(parentNavBase);
this.tabItem.instance = this
tabs.addTab(this.tabItem);
this.panelId = 'tab-panel-' + this.tabItem.id;
this.labeledBy = 'tab-button-' + this.tabItem.id;
this.elementRef = elementRef;
this.viewContainerRef = viewContainerRef; this.viewContainerRef = viewContainerRef;
this.sections = parentNavBase.panes['_n'].sections; this.sections = parentNavBase.panes['_n'].sections;
this.navBase.panes['_n'] = this; this.navBase.panes['_n'] = this;
this.isSelected = false;
tabs.addTab(this);
this.panelId = 'tab-panel-' + this.id;
this.labeledBy = 'tab-button-' + this.id;
this.domElement = elementRef.domElement; this.domElement = elementRef.domElement;
this.config = Nav.config.invoke(this); this.config = Nav.config.invoke(this);
@ -69,19 +75,8 @@ export class Tab {
console.log('Tab constructor', this.id, ' parentNavBase:', parentNavBase); console.log('Tab constructor', this.id, ' parentNavBase:', parentNavBase);
} }
onInit() { get isSelected() {
this.navBase.initial(this.initial); return this.parentNavBase.isActive(this);
}
select(shouldSelect) {
if (shouldSelect && !this.isSelected) {
console.log('Select tab', this.id);
} else if (!shouldSelect && this.isSelected) {
console.log('Deselect tab', this.id);
}
this.isSelected = shouldSelect;
} }
} }

View File

@ -1,8 +1,9 @@
import {Ancestor, Parent} from 'angular2/src/core/annotations_impl/visibility'; import {Ancestor, Parent} from 'angular2/src/core/annotations_impl/visibility';
import {Optional} from 'angular2/src/di/annotations_impl' import {Optional} from 'angular2/src/di/annotations_impl'
import {Directive, Component, onInit} from 'angular2/src/core/annotations_impl/annotations'; import {Directive, Component} from 'angular2/src/core/annotations_impl/annotations';
import {View} from 'angular2/src/core/annotations_impl/view'; import {View} from 'angular2/src/core/annotations_impl/view';
import {ElementRef} from 'angular2/src/core/compiler/element_ref'; import {ElementRef} from 'angular2/src/core/compiler/element_ref';
import {Compiler} from 'angular2/angular2';
import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader'; import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
import {Injector} from 'angular2/di'; import {Injector} from 'angular2/di';
import {NgFor} from 'angular2/angular2'; import {NgFor} from 'angular2/angular2';
@ -14,17 +15,15 @@ import {TabButton} from './tab-button';
import {Icon} from '../icon/icon'; import {Icon} from '../icon/icon';
import {Nav, NavPane} from '../nav/nav'; import {Nav, NavPane} from '../nav/nav';
import {NavItem} from '../nav/nav-item'; import {NavItem} from '../nav/nav-item';
import {NavBase} from '../nav/nav-base';
let tabsId = -1;
@Component({ @Component({
selector: 'ion-tabs', selector: 'ion-tabs',
properties: [ properties: [
'tabBarPlacement', 'tabBarPlacement',
'tabBarIcons' 'tabBarIcons'
], ]
lifecycle: [onInit]
}) })
@View({ @View({
template: ` template: `
@ -43,46 +42,35 @@ let tabsId = -1;
directives: [NgFor, TabButton, Icon] directives: [NgFor, TabButton, Icon]
}) })
export class Tabs { export class Tabs {
constructor(elementRef: ElementRef) { constructor(
this.id = ++tabsId; @Optional() parentNavBase: NavBase,
this.tabIds = 0; compiler: Compiler,
this.tabs = []; elementRef: ElementRef,
this._selected = null; loader: DynamicComponentLoader,
injector: Injector
) {
this.navBase = new NavBase(parentNavBase, compiler, elementRef, loader, injector);
this.domElement = elementRef.domElement; this.domElement = elementRef.domElement;
this.config = Tabs.config.invoke(this); this.config = Tabs.config.invoke(this);
console.log('Tabs constructor', this.id);
} }
onInit() { addTab(tabItem) {
if (this.tabs.length > 0) { this.navBase.add(tabItem);
this.selectTab(this.tabs[0]);
if (this.navBase.length() === 1) {
this.selectTab(tabItem.instance);
} }
} }
addTab(tab) { get tabs() {
tab.id = this.id + '' + (++this.tabIds); return this.navBase.instances();
this.tabs.push(tab);
} }
selectTab(tabToSelect) { selectTab(tabInstance) {
if (typeof tabToSelect === 'number') { let enteringItem = this.navBase.findByInstance(tabInstance);
let index = tabToSelect;
tabToSelect = null;
if (index < this.tabs.length) {
tabToSelect = this.tabs[index];
}
}
if (!tabToSelect || this._selected === tabToSelect) return;
let tabToDeselect = this._selected; this.navBase.switchActive(enteringItem);
this.tabs.forEach(tab => {
tab.select( (tab === tabToSelect) );
});
this._selected = tabToSelect;
} }
} }