mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 11:41:20 +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 {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;
|
||||||
}
|
}
|
||||||
|
@ -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?
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user