mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 03:32:21 +08:00
tabs wip
This commit is contained in:
@ -15,6 +15,7 @@ import {NavPane, NavBarSection} from './nav-pane';
|
||||
import {Transition, ClickBlock} from 'ionic/ionic';
|
||||
import * as util from 'ionic/util';
|
||||
|
||||
let itemsIds = -1;
|
||||
|
||||
export class NavBase {
|
||||
|
||||
@ -39,6 +40,9 @@ export class NavBase {
|
||||
this.sbTransition = null;
|
||||
this.sbActive = false;
|
||||
this.panes = {};
|
||||
|
||||
this.id = ++itemsIds;
|
||||
this.childIds = -1;
|
||||
}
|
||||
|
||||
initial(initial) {
|
||||
@ -109,8 +113,8 @@ export class NavBase {
|
||||
}
|
||||
}
|
||||
|
||||
push(Component, params = {}, opts = {}) {
|
||||
if (!Component || this.isTransitioning()) {
|
||||
push(ComponentClass, params = {}, opts = {}) {
|
||||
if (!ComponentClass || this.isTransitioning()) {
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
@ -136,13 +140,13 @@ export class NavBase {
|
||||
leavingItem.willCache();
|
||||
|
||||
// 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)
|
||||
enteringItem.state = STAGED_STATE;
|
||||
|
||||
// add the item to the stack
|
||||
this.items.push(enteringItem);
|
||||
this.add(enteringItem);
|
||||
|
||||
// start the transition
|
||||
this.transition(enteringItem, leavingItem, opts, () => {
|
||||
@ -193,7 +197,25 @@ export class NavBase {
|
||||
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) {
|
||||
if (!enteringItem || enteringItem === leavingItem) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
opts.isAnimated = (opts.animation !== 'none');
|
||||
|
||||
this.transitionStart(opts);
|
||||
@ -409,16 +431,6 @@ export class NavBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
clear() {
|
||||
let pops = [];
|
||||
for(let item of this.items) {
|
||||
pops.push(this.pop({
|
||||
animate: false
|
||||
}));
|
||||
}
|
||||
return Promise.all(pops);
|
||||
}
|
||||
|
||||
getActive() {
|
||||
for (let i = 0, ii = this.items.length; i < ii; i++) {
|
||||
if (this.items[i].state === ACTIVE_STATE) {
|
||||
@ -428,6 +440,15 @@ export class NavBase {
|
||||
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) {
|
||||
if (item) {
|
||||
return this.items[ this.items.indexOf(item) - 1 ];
|
||||
@ -457,10 +478,43 @@ export class NavBase {
|
||||
return this.domElement;
|
||||
}
|
||||
|
||||
add(item) {
|
||||
item.id = this.id + '' + (++this.childIds);
|
||||
this.items.push(item);
|
||||
}
|
||||
|
||||
remove(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() {
|
||||
return this.domElement.offsetWidth;
|
||||
}
|
||||
|
@ -11,11 +11,12 @@ import {TabPane, NavPane, NavPaneSection} from './nav';
|
||||
|
||||
export class NavItem {
|
||||
|
||||
constructor(navBase, Component, params = {}) {
|
||||
constructor(navBase, ComponentClass, params = {}) {
|
||||
this.navBase = navBase;
|
||||
this.Component = Component;
|
||||
this.ComponentClass = ComponentClass;
|
||||
this.params = params;
|
||||
this.id = util.nextUid();
|
||||
this.instance = null;
|
||||
|
||||
this._titleEle = undefined;
|
||||
this._backBtn = undefined;
|
||||
this.disposals = [];
|
||||
@ -40,7 +41,7 @@ export class NavItem {
|
||||
}
|
||||
|
||||
// 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
|
||||
// does it have a navbar? Is it tabs? Should it not have a navbar or any toolbars?
|
||||
|
@ -50,18 +50,24 @@ export class Tab {
|
||||
injector: Injector,
|
||||
viewContainerRef: ViewContainerRef
|
||||
) {
|
||||
|
||||
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.sections = parentNavBase.panes['_n'].sections;
|
||||
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.config = Nav.config.invoke(this);
|
||||
@ -69,19 +75,8 @@ export class Tab {
|
||||
console.log('Tab constructor', this.id, ' parentNavBase:', parentNavBase);
|
||||
}
|
||||
|
||||
onInit() {
|
||||
this.navBase.initial(this.initial);
|
||||
}
|
||||
|
||||
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;
|
||||
get isSelected() {
|
||||
return this.parentNavBase.isActive(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import {Ancestor, Parent} from 'angular2/src/core/annotations_impl/visibility';
|
||||
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 {ElementRef} from 'angular2/src/core/compiler/element_ref';
|
||||
import {Compiler} from 'angular2/angular2';
|
||||
import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader';
|
||||
import {Injector} from 'angular2/di';
|
||||
import {NgFor} from 'angular2/angular2';
|
||||
@ -14,17 +15,15 @@ import {TabButton} from './tab-button';
|
||||
import {Icon} from '../icon/icon';
|
||||
import {Nav, NavPane} from '../nav/nav';
|
||||
import {NavItem} from '../nav/nav-item';
|
||||
import {NavBase} from '../nav/nav-base';
|
||||
|
||||
|
||||
let tabsId = -1;
|
||||
|
||||
@Component({
|
||||
selector: 'ion-tabs',
|
||||
properties: [
|
||||
'tabBarPlacement',
|
||||
'tabBarIcons'
|
||||
],
|
||||
lifecycle: [onInit]
|
||||
]
|
||||
})
|
||||
@View({
|
||||
template: `
|
||||
@ -43,46 +42,35 @@ let tabsId = -1;
|
||||
directives: [NgFor, TabButton, Icon]
|
||||
})
|
||||
export class Tabs {
|
||||
constructor(elementRef: ElementRef) {
|
||||
this.id = ++tabsId;
|
||||
this.tabIds = 0;
|
||||
this.tabs = [];
|
||||
this._selected = null;
|
||||
constructor(
|
||||
@Optional() parentNavBase: NavBase,
|
||||
compiler: Compiler,
|
||||
elementRef: ElementRef,
|
||||
loader: DynamicComponentLoader,
|
||||
injector: Injector
|
||||
) {
|
||||
this.navBase = new NavBase(parentNavBase, compiler, elementRef, loader, injector);
|
||||
|
||||
this.domElement = elementRef.domElement;
|
||||
this.config = Tabs.config.invoke(this);
|
||||
|
||||
console.log('Tabs constructor', this.id);
|
||||
}
|
||||
|
||||
onInit() {
|
||||
if (this.tabs.length > 0) {
|
||||
this.selectTab(this.tabs[0]);
|
||||
addTab(tabItem) {
|
||||
this.navBase.add(tabItem);
|
||||
|
||||
if (this.navBase.length() === 1) {
|
||||
this.selectTab(tabItem.instance);
|
||||
}
|
||||
}
|
||||
|
||||
addTab(tab) {
|
||||
tab.id = this.id + '' + (++this.tabIds);
|
||||
this.tabs.push(tab);
|
||||
get tabs() {
|
||||
return this.navBase.instances();
|
||||
}
|
||||
|
||||
selectTab(tabToSelect) {
|
||||
if (typeof tabToSelect === 'number') {
|
||||
let index = tabToSelect;
|
||||
tabToSelect = null;
|
||||
if (index < this.tabs.length) {
|
||||
tabToSelect = this.tabs[index];
|
||||
}
|
||||
}
|
||||
if (!tabToSelect || this._selected === tabToSelect) return;
|
||||
selectTab(tabInstance) {
|
||||
let enteringItem = this.navBase.findByInstance(tabInstance);
|
||||
|
||||
let tabToDeselect = this._selected;
|
||||
|
||||
this.tabs.forEach(tab => {
|
||||
tab.select( (tab === tabToSelect) );
|
||||
});
|
||||
|
||||
this._selected = tabToSelect;
|
||||
this.navBase.switchActive(enteringItem);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user