chore(): fix Tabs types

This commit is contained in:
Adam Bradley
2016-01-13 22:40:30 -06:00
parent c4d59002c0
commit 100b1e79ae
8 changed files with 191 additions and 156 deletions

View File

@ -305,7 +305,7 @@ export class Content {
*/ */
add_padding(newPadding) { add_padding(newPadding) {
if (newPadding > this._padding) { if (newPadding > this._padding) {
console.debug('add_padding', newPadding); console.debug('content add padding', newPadding);
this._padding = newPadding; this._padding = newPadding;
this._scrollEle.style.paddingBottom = newPadding + 'px'; this._scrollEle.style.paddingBottom = newPadding + 'px';

View File

@ -100,30 +100,31 @@ import {raf, rafFrames} from '../../util/dom';
* @see {@link /docs/v2/components#navigation Navigation Component Docs} * @see {@link /docs/v2/components#navigation Navigation Component Docs}
*/ */
export class NavController extends Ion { export class NavController extends Ion {
private _views: Array<ViewController> = []; protected _ids: number = -1;
private _trnsTime: number = 0; protected _sbEnabled: any;
private _trnsDelay: any; protected _sbThreshold: any;
private _sbTrans: any = null; protected _sbTrans: any = null;
private _sbEnabled: any; protected _trnsDelay: any;
private _sbThreshold: any; protected _trnsTime: number = 0;
public sbGesture: any; protected _views: Array<ViewController> = [];
private initZIndex: number = 10; protected _zIndex: number = 10;
public id: number; public id: number;
private _ids: number = -1;
public providers: ResolvedProvider[]; public providers: ResolvedProvider[];
public router: any; public router: any;
public sbGesture: any;
constructor( constructor(
public parent: NavController, public parent: any,
public app: IonicApp, public app: IonicApp,
public config: Config, public config: Config,
public keyboard: Keyboard, public keyboard: Keyboard,
elementRef: ElementRef, elementRef: ElementRef,
private _anchorName: string, protected _anchorName: string,
private _compiler: Compiler, protected _compiler: Compiler,
private _viewManager: AppViewManager, protected _viewManager: AppViewManager,
private _zone: NgZone, protected _zone: NgZone,
private _renderer: Renderer protected _renderer: Renderer
) { ) {
super(elementRef); super(elementRef);
@ -555,7 +556,7 @@ export class NavController extends Ion {
* @param {Object} [opts={}] Any options you want to use pass to transtion * @param {Object} [opts={}] Any options you want to use pass to transtion
* @returns {Promise} Returns a promise when the view has been removed * @returns {Promise} Returns a promise when the view has been removed
*/ */
remove(index: number, opts = {}): Promise<any> { remove(index: number, opts: any = {}): Promise<any> {
if (index < 0 || index >= this._views.length) { if (index < 0 || index >= this._views.length) {
return Promise.reject("index out of range"); return Promise.reject("index out of range");
} }
@ -1067,7 +1068,7 @@ export class NavController extends Ion {
let enteringPageRef = enteringView && enteringView.pageRef(); let enteringPageRef = enteringView && enteringView.pageRef();
if (enteringPageRef) { if (enteringPageRef) {
if (!leavingView || !leavingView.isLoaded()) { if (!leavingView || !leavingView.isLoaded()) {
enteringView.zIndex = this.initZIndex; enteringView.zIndex = this._zIndex;
} else if (direction === 'back') { } else if (direction === 'back') {
// moving back // moving back
@ -1391,7 +1392,7 @@ export class NavController extends Ion {
* @param {Index} The index of the page you want to get * @param {Index} The index of the page you want to get
* @returns {Component} Returns the component that matches the index given * @returns {Component} Returns the component that matches the index given
*/ */
getByIndex(index: number): ViewController { getByIndex(index: number): any {
if (index < this._views.length && index > -1) { if (index < this._views.length && index > -1) {
return this._views[index]; return this._views[index];
} }

View File

@ -18,23 +18,26 @@ import {Navbar} from '../navbar/navbar';
* ``` * ```
*/ */
export class ViewController { export class ViewController {
public instance: any = {}; private _cntDir: any;
public state: number = 0; private _cntRef: ElementRef;
private _destroys: Array<Function> = []; private _destroys: Array<Function> = [];
private _loaded: boolean = false; private _loaded: boolean = false;
public shouldDestroy: boolean = false;
public shouldCache: boolean = false;
public viewType: string = '';
public id: string;
private _leavingOpts: any = null; private _leavingOpts: any = null;
private _onDismiss: Function = null; private _nbDir: Navbar;
protected _nav: NavController;
private _nbTmpRef: TemplateRef; private _nbTmpRef: TemplateRef;
private _nbVwRef: ViewContainerRef; private _nbVwRef: ViewContainerRef;
private _onDismiss: Function = null;
private _pgRef: ElementRef; private _pgRef: ElementRef;
private _cntRef: ElementRef; protected _nav: NavController;
private _nbDir: Navbar;
private _cntDir: any; id: string;
instance: any = {};
state: number = 0;
shouldDestroy: boolean = false;
shouldCache: boolean = false;
viewType: string = '';
onReady: any;
@Output() private _emitter: EventEmitter<any> = new EventEmitter(); @Output() private _emitter: EventEmitter<any> = new EventEmitter();
constructor(public componentType?: Type, public data: any = {}) {} constructor(public componentType?: Type, public data: any = {}) {}

View File

@ -0,0 +1,49 @@
import {Component, Directive, ElementRef, Optional, Host, forwardRef, ViewContainerRef, HostListener, EventEmitter, Output, Input, Renderer} from 'angular2/core';
import {Tab} from './tab';
import {Config} from '../../config/config';
/**
* @private
*/
@Directive({
selector: '.tab-button',
host: {
'[attr.id]': 'tab._btnId',
'[attr.aria-controls]': 'tab._panelId',
'[attr.aria-selected]': 'tab.isSelected',
'[class.has-title]': 'hasTitle',
'[class.has-icon]': 'hasIcon',
'[class.has-title-only]': 'hasTitleOnly',
'[class.icon-only]': 'hasIconOnly',
'[class.disable-hover]': 'disHover'
}
})
export class TabButton {
private disHover: boolean;
private hasTitle: boolean;
private hasIcon: boolean;
private hasTitleOnly: boolean;
private hasIconOnly: boolean;
@Input() tab: Tab;
@Output() select: EventEmitter<Tab> = new EventEmitter();
constructor(config: Config) {
this.disHover = (config.get('hoverCSS') === false);
}
ngOnInit() {
this.tab.btn = this;
this.hasTitle = !!this.tab.tabTitle;
this.hasIcon = !!this.tab.tabIcon;
this.hasTitleOnly = (this.hasTitle && !this.hasIcon);
this.hasIconOnly = (this.hasIcon && !this.hasTitle);
}
@HostListener('click')
private onClick() {
this.select.emit(this.tab);
}
}

View File

@ -0,0 +1,31 @@
import {Directive, ElementRef} from 'angular2/core';
import {rafFrames} from '../../util/dom';
/**
* @private
*/
@Directive({
selector: 'tab-highlight'
})
export class TabHighlight {
private _init: boolean;
constructor(private _elementRef: ElementRef) {}
select(tab) {
rafFrames(3, () => {
let d = tab.btn.getDimensions();
let ele = this._elementRef.nativeElement;
ele.style.transform = 'translate3d(' + d.left + 'px,0,0) scaleX(' + d.width + ')';
if (!this._init) {
this._init = true;
rafFrames(6, () => {
ele.classList.add('animate');
});
}
});
}
}

View File

@ -1,5 +1,5 @@
import {ChangeDetectorRef, Component, Directive, Host, ElementRef, Compiler, AppViewManager, NgZone, Renderer} from 'angular2/core'; import {Component, Directive, Host, Inject, forwardRef, ElementRef, Compiler, AppViewManager, NgZone, Renderer, Type} from 'angular2/core';
import {EventEmitter, Output} from 'angular2/core'; import {EventEmitter, Input, Output} from 'angular2/core';
import {IonicApp} from '../app/app'; import {IonicApp} from '../app/app';
import {Config} from '../../config/config'; import {Config} from '../../config/config';
@ -7,6 +7,7 @@ import {Keyboard} from '../../util/keyboard';
import {NavController} from '../nav/nav-controller'; import {NavController} from '../nav/nav-controller';
import {ViewController} from '../nav/view-controller'; import {ViewController} from '../nav/view-controller';
import {Tabs} from './tabs'; import {Tabs} from './tabs';
import {TabButton} from './tab-button';
/** /**
@ -83,11 +84,6 @@ import {Tabs} from './tabs';
*/ */
@Component({ @Component({
selector: 'ion-tab', selector: 'ion-tab',
inputs: [
'root',
'tabTitle',
'tabIcon'
],
host: { host: {
'[class.show-tab]': 'isSelected', '[class.show-tab]': 'isSelected',
'[attr.id]': '_panelId', '[attr.id]': '_panelId',
@ -97,10 +93,20 @@ import {Tabs} from './tabs';
template: '<template #contents></template>' template: '<template #contents></template>'
}) })
export class Tab extends NavController { export class Tab extends NavController {
public isSelected: boolean;
private _isInitial: boolean;
private _panelId: string;
private _btnId: string;
private _loaded: boolean;
private _loadTimer: any;
btn: TabButton;
@Input() root: Type;
@Input() tabTitle: string;
@Input() tabIcon: string;
@Output() select: EventEmitter<any> = new EventEmitter(); @Output() select: EventEmitter<any> = new EventEmitter();
constructor( constructor(
@Host() parentTabs: Tabs, @Inject(forwardRef(() => Tabs)) parentTabs: Tabs,
app: IonicApp, app: IonicApp,
config: Config, config: Config,
keyboard: Keyboard, keyboard: Keyboard,
@ -108,11 +114,10 @@ export class Tab extends NavController {
compiler: Compiler, compiler: Compiler,
viewManager: AppViewManager, viewManager: AppViewManager,
zone: NgZone, zone: NgZone,
renderer: Renderer, renderer: Renderer
cd: ChangeDetectorRef
) { ) {
// A Tab is a NavController for its child pages // A Tab is a NavController for its child pages
super(parentTabs, app, config, keyboard, elementRef, 'contents', compiler, viewManager, zone, renderer, cd); super(parentTabs, app, config, keyboard, elementRef, 'contents', compiler, viewManager, zone, renderer);
this._isInitial = parentTabs.add(this); this._isInitial = parentTabs.add(this);
@ -146,7 +151,7 @@ export class Tab extends NavController {
/** /**
* @private * @private
*/ */
load(opts, done) { load(opts, done?: Function) {
if (!this._loaded && this.root) { if (!this._loaded && this.root) {
this.push(this.root, null, opts, done); this.push(this.root, null, opts, done);
this._loaded = true; this._loaded = true;
@ -186,13 +191,6 @@ export class Tab extends NavController {
this.hideNavbars(!isSelected); this.hideNavbars(!isSelected);
} }
/**
* @private
*/
emitSelect() {
this.select.emit();
}
/** /**
* @private * @private
*/ */
@ -214,7 +212,7 @@ export class Tab extends NavController {
* } * }
* ``` * ```
* *
* @returns {Number} Returns the index of this page within its NavController. * @returns {number} Returns the index of this page within its NavController.
* *
*/ */
get index() { get index() {

View File

@ -1,9 +1,12 @@
import {Component, Directive, ElementRef, Optional, Host, forwardRef, ViewContainerRef, HostListener, EventEmitter, Output, Input, Renderer} from 'angular2/core'; import {Component, Directive, ElementRef, Optional, Host, forwardRef, ViewContainerRef, ViewChild, ViewChildren, EventEmitter, Output, Input, Renderer} from 'angular2/core';
import {NgFor, NgIf} from 'angular2/common'; import {NgFor, NgIf} from 'angular2/common';
import {Ion} from '../ion'; import {IonicApp} from '../app/app';
import {Attr} from '../app/id';
import {Config} from '../../config/config'; import {Config} from '../../config/config';
import {Tab} from './tab';
import {TabButton} from './tab-button';
import {TabHighlight} from './tab-highlight';
import {Ion} from '../ion';
import {Platform} from '../../platform/platform'; import {Platform} from '../../platform/platform';
import {NavController} from '../nav/nav-controller'; import {NavController} from '../nav/nav-controller';
import {ViewController} from '../nav/view-controller'; import {ViewController} from '../nav/view-controller';
@ -56,42 +59,50 @@ import {isUndefined} from '../../util/util';
Icon, Icon,
NgFor, NgFor,
NgIf, NgIf,
Attr, TabButton,
forwardRef(() => TabButton), TabHighlight,
forwardRef(() => TabHighlight),
forwardRef(() => TabNavBarAnchor) forwardRef(() => TabNavBarAnchor)
] ]
}) })
export class Tabs extends Ion { export class Tabs extends Ion {
private tabs: Array<any>; private _ids: number = -1;
@Input() tabbarPlacement: string; private _tabs: Array<Tab> = [];
private _onReady = null;
private _useHighlight: boolean;
id: number;
navbarContainerRef: ViewContainerRef;
subPages: boolean;
@Input() preloadTabs: any;
@Input() tabbarIcons: string; @Input() tabbarIcons: string;
@Input() preloadTabs: boolean; @Input() tabbarPlacement: string;
@Output() change: EventEmitter<any> = new EventEmitter(); @Output() change: EventEmitter<Tab> = new EventEmitter();
@ViewChild(TabHighlight) private _highlight: TabHighlight;
@ViewChildren(TabButton) private _btns;
constructor( constructor(
elementRef: ElementRef,
@Optional() viewCtrl: ViewController, @Optional() viewCtrl: ViewController,
@Optional() navCtrl: NavController, @Optional() public parent: NavController,
private _app: IonicApp,
private _config: Config, private _config: Config,
private _elementRef: ElementRef,
private _platform: Platform, private _platform: Platform,
private _renderer: Renderer private _renderer: Renderer
) { ) {
super(elementRef); super(_elementRef);
this.parent = navCtrl;
this.subPages = _config.get('tabSubPages');
this._tabs = []; this.id = ++tabIds;
this._id = ++tabIds; this.subPages = _config.getBoolean('tabSubPages');
this._ids = -1; this._useHighlight = _config.getBoolean('tabbarHighlight');
this._onReady = null;
// Tabs may also be an actual ViewController which was navigated to // Tabs may also be an actual ViewController which was navigated to
// if Tabs is static and not navigated to within a NavController // if Tabs is static and not navigated to within a NavController
// then skip this and don't treat it as it's own ViewController // then skip this and don't treat it as it's own ViewController
if (viewCtrl) { if (viewCtrl) {
viewCtrl.setContent(this); viewCtrl.setContent(this);
viewCtrl.setContentRef(elementRef); viewCtrl.setContentRef(_elementRef);
viewCtrl.onReady = (done) => { viewCtrl.onReady = (done) => {
this._onReady = done; this._onReady = done;
@ -102,18 +113,24 @@ export class Tabs extends Ion {
/** /**
* @private * @private
*/ */
ngOnInit() { ngAfterViewInit() {
this.preloadTabs = (this.preloadTabs !== "false" && this.preloadTabs !== false); this.preloadTabs = (this.preloadTabs !== "false" && this.preloadTabs !== false);
this._setConfig('tabbarPlacement', 'bottom'); this._setConfig('tabbarPlacement', 'bottom');
this._setConfig('tabbarIcons', 'top'); this._setConfig('tabbarIcons', 'top');
this._setConfig('preloadTabs', false); this._setConfig('preloadTabs', false);
if (this._highlight) { if (this._useHighlight) {
this._platform.onResize(() => { this._platform.onResize(() => {
this._highlight.select(this.getSelected()); this._highlight.select(this.getSelected());
}); });
} }
this._btns.toArray().forEach((tabButton: TabButton) => {
tabButton.select.subscribe((tab: Tab) => {
this.select(tab);
});
});
} }
_setConfig(attrKey, fallback) { _setConfig(attrKey, fallback) {
@ -121,26 +138,26 @@ export class Tabs extends Ion {
if (isUndefined(val)) { if (isUndefined(val)) {
val = this._config.get(attrKey); val = this._config.get(attrKey);
} }
this._renderer.setElementAttribute(this.elementRef, attrKey, val); this._renderer.setElementAttribute(this._elementRef, attrKey, val);
} }
/** /**
* @private * @private
*/ */
add(tab) { add(tab) {
tab.id = this._id + '-' + (++this._ids); tab.id = this.id + '-' + (++this._ids);
this._tabs.push(tab); this._tabs.push(tab);
return (this._tabs.length === 1); return (this._tabs.length === 1);
} }
/** /**
* @param {Number} index Index of the tab you want to select * @param {number} index Index of the tab you want to select
*/ */
select(tabOrIndex) { select(tabOrIndex) {
let selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex); let selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
if (!selectedTab) { if (!selectedTab) {
return Promise.reject(); return;
} }
let deselectedTab = this.getSelected(); let deselectedTab = this.getSelected();
@ -167,7 +184,7 @@ export class Tabs extends Ion {
selectedTab.load(opts, () => { selectedTab.load(opts, () => {
selectedTab.emitSelect(); selectedTab.select.emit(selectedTab);
this.change.emit(selectedTab); this.change.emit(selectedTab);
if (selectedTab.root) { if (selectedTab.root) {
@ -180,7 +197,9 @@ export class Tabs extends Ion {
}); });
} }
this._highlight && this._highlight.select(selectedTab); if (this._useHighlight) {
this._highlight.select(selectedTab);
}
selectedPage && selectedPage.didEnter(); selectedPage && selectedPage.didEnter();
deselectedPage && deselectedPage.didLeave(); deselectedPage && deselectedPage.didLeave();
@ -195,10 +214,10 @@ export class Tabs extends Ion {
} }
/** /**
* @param {Number} index Index of the tab you want to get * @param {number} index Index of the tab you want to get
* @returns {Any} Tab Returs the tab who's index matches the one passed * @returns {Any} Tab Returs the tab who's index matches the one passed
*/ */
getByIndex(index) { getByIndex(index: number): any {
if (index < this._tabs.length && index > -1) { if (index < this._tabs.length && index > -1) {
return this._tabs[index]; return this._tabs[index];
} }
@ -208,7 +227,7 @@ export class Tabs extends Ion {
/** /**
* @return {Any} Tab Returns the currently selected tab * @return {Any} Tab Returns the currently selected tab
*/ */
getSelected() { getSelected(): Tab {
for (let i = 0; i < this._tabs.length; i++) { for (let i = 0; i < this._tabs.length; i++) {
if (this._tabs[i].isSelected) { if (this._tabs[i].isSelected) {
return this._tabs[i]; return this._tabs[i];
@ -220,7 +239,7 @@ export class Tabs extends Ion {
/** /**
* @private * @private
*/ */
getIndex(tab) { getIndex(tab: Tab): number {
return this._tabs.indexOf(tab); return this._tabs.indexOf(tab);
} }
@ -277,77 +296,6 @@ export class Tabs extends Ion {
let tabIds = -1; let tabIds = -1;
/**
* @private
*/
@Directive({
selector: '.tab-button',
inputs: ['tab'],
host: {
'[attr.id]': 'tab._btnId',
'[attr.aria-controls]': 'tab._panelId',
'[attr.aria-selected]': 'tab.isSelected',
'[class.has-title]': 'hasTitle',
'[class.has-icon]': 'hasIcon',
'[class.has-title-only]': 'hasTitleOnly',
'[class.icon-only]': 'hasIconOnly',
'[class.disable-hover]': 'disHover'
}
})
class TabButton extends Ion {
constructor(@Host() tabs: Tabs, config: Config, elementRef: ElementRef) {
super(elementRef);
this.tabs = tabs;
this.disHover = (config.get('hoverCSS') === false);
}
ngOnInit() {
this.tab.btn = this;
this.hasTitle = !!this.tab.tabTitle;
this.hasIcon = !!this.tab.tabIcon;
this.hasTitleOnly = (this.hasTitle && !this.hasIcon);
this.hasIconOnly = (this.hasIcon && !this.hasTitle);
}
@HostListener('click')
private onClick() {
this.tabs.select(this.tab);
}
}
/**
* @private
*/
@Directive({
selector: 'tab-highlight'
})
class TabHighlight {
constructor(@Host() tabs: Tabs, config: Config, elementRef: ElementRef) {
if (config.get('tabbarHighlight')) {
tabs._highlight = this;
this.elementRef = elementRef;
}
}
select(tab) {
rafFrames(3, () => {
let d = tab.btn.getDimensions();
let ele = this.elementRef.nativeElement;
ele.style.transform = 'translate3d(' + d.left + 'px,0,0) scaleX(' + d.width + ')';
if (!this.init) {
this.init = true;
rafFrames(6, () => {
ele.classList.add('animate');
});
}
});
}
}
/** /**
* @private * @private
*/ */

View File

@ -183,7 +183,7 @@ export class Config {
* *
* @param {String} [key] - the key for the config value * @param {String} [key] - the key for the config value
*/ */
get(key) { get(key: string): any {
if (!isDefined(this._c[key])) { if (!isDefined(this._c[key])) {
if (!isDefined(key)) { if (!isDefined(key)) {
@ -281,6 +281,11 @@ export class Config {
return this._c[key]; return this._c[key];
} }
getBoolean(key: string): boolean {
let val = this.get(key);
return (val || val === 'true') ? true : false;
}
/** /**
* @private * @private
*/ */