refactor(structure): allow content to scroll under headers/footers

This commit is contained in:
Adam Bradley
2016-06-16 11:28:02 -05:00
parent 64af0c8ba0
commit d13fa4e2cf
57 changed files with 1390 additions and 956 deletions

View File

@@ -377,7 +377,7 @@ export interface ActionSheetOptions {
class ActionSheetSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
@@ -394,7 +394,7 @@ Transition.register('action-sheet-slide-in', ActionSheetSlideIn);
class ActionSheetSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
@@ -411,7 +411,7 @@ Transition.register('action-sheet-slide-out', ActionSheetSlideOut);
class ActionSheetMdSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
@@ -428,7 +428,7 @@ Transition.register('action-sheet-md-slide-in', ActionSheetMdSlideIn);
class ActionSheetMdSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
@@ -444,7 +444,7 @@ Transition.register('action-sheet-md-slide-out', ActionSheetMdSlideOut);
class ActionSheetWpSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
@@ -461,7 +461,7 @@ Transition.register('action-sheet-wp-slide-in', ActionSheetWpSlideIn);
class ActionSheetWpSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));

View File

@@ -571,7 +571,7 @@ class AlertCmp {
// this is an alert with text inputs
// return an object of all the values with the input name as the key
let values = {};
let values: {[k: string]: string} = {};
this.d.inputs.forEach(i => {
values[i.name] = i.value;
});
@@ -605,14 +605,14 @@ export interface AlertInputOptions {
*/
class AlertPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
backdrop.fromTo('opacity', '0.01', '0.3');
wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
backdrop.fromTo('opacity', 0.01, 0.3);
this
.easing('ease-in-out')
@@ -626,14 +626,14 @@ Transition.register('alert-pop-in', AlertPopIn);
class AlertPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
backdrop.fromTo('opacity', '0.3', '0');
wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
backdrop.fromTo('opacity', 0.3, 0);
this
.easing('ease-in-out')
@@ -647,14 +647,14 @@ Transition.register('alert-pop-out', AlertPopOut);
class AlertMdPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
backdrop.fromTo('opacity', '0.01', '0.5');
wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
backdrop.fromTo('opacity', 0.01, 0.5);
this
.easing('ease-in-out')
@@ -668,14 +668,14 @@ Transition.register('alert-md-pop-in', AlertMdPopIn);
class AlertMdPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
backdrop.fromTo('opacity', '0.5', '0');
wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
backdrop.fromTo('opacity', 0.5, 0);
this
.easing('ease-in-out')
@@ -690,14 +690,14 @@ Transition.register('alert-md-pop-out', AlertMdPopOut);
class AlertWpPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.3', '1');
backdrop.fromTo('opacity', '0.01', '0.5');
wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.3, 1);
backdrop.fromTo('opacity', 0.01, 0.5);
this
.easing('cubic-bezier(0,0 0.05,1)')
@@ -711,14 +711,14 @@ Transition.register('alert-wp-pop-in', AlertWpPopIn);
class AlertWpPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.alert-wrapper'));
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '1.3');
backdrop.fromTo('opacity', '0.5', '0');
wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 1.3);
backdrop.fromTo('opacity', 0.5, 0);
this
.easing('ease-out')

View File

@@ -15,6 +15,8 @@ $z-index-refresher: 0;
$z-index-navbar-section: 10;
$z-index-page-container: 0;
$z-index-selected-tab: 1;
$z-index-toolbar: 10;
$z-index-toolbar-background: -1;
@@ -85,64 +87,138 @@ body {
text-size-adjust: none;
}
ion-app.app-init,
// Nav Container Structure
// --------------------------------------------------
ion-app,
ion-nav,
ion-tab,
ion-tabs {
position: absolute;
top: 0;
left: 0;
display: flex;
z-index: $z-index-page-container;
display: block;
overflow: hidden;
flex-direction: column;
width: 100%;
height: 100%;
}
ion-navbar-section {
display: block;
width: 100%;
min-height: 50px;
ion-tab scroll-cotent {
display: none;
}
ion-content-section {
position: relative;
display: block;
flex: 1;
width: 100%;
height: 100%;
ion-tab.show-tab {
z-index: $z-index-selected-tab;
}
ion-tab.show-tab scroll-cotent {
display: block;
}
// Page Container Structure
// --------------------------------------------------
ion-page {
position: absolute;
top: 0;
left: 0;
display: none;
flex-direction: column;
display: block;
width: 100%;
height: 100%;
&.show-page {
display: flex;
}
// do not show, but still render so we can get dimensions
visibility: hidden;
}
ion-content {
position: relative;
top: 0;
left: 0;
display: block;
flex: 1;
width: 100%;
height: 100%;
}
ion-page > ion-content {
position: absolute;
}
ion-page scroll-content {
// do not render the scroll-content at all until ready
display: none;
}
ion-page.show-page {
// show the page now that it's ready
visibility: visible;
}
ion-page.show-page scroll-content {
// render the content when ready
display: block;
}
ion-page.tab-subpage {
position: fixed;
z-index: 10;
}
// Toolbar Container Structure
// --------------------------------------------------
ion-header {
position: absolute;
top: 0;
left: 0;
z-index: $z-index-toolbar;
display: block;
width: 100%;
}
ion-footer {
position: absolute;
bottom: 0;
left: 0;
z-index: $z-index-toolbar;
display: block;
width: 100%;
}
ion-tabbar {
position: absolute;
bottom: 0;
left: 0;
z-index: $z-index-toolbar;
display: flex;
width: 100%;
// default to hidden until ready
visibility: hidden;
}
ion-tabbar.show-tabbar {
visibility: visible;
}
[tabbarPlacement=top] > ion-tabbar {
top: 0;
bottom: auto;
}
// Scrollable Content
// --------------------------------------------------
scroll-content {
position: absolute;
top: 0;
@@ -169,59 +245,9 @@ ion-content.js-scroll > scroll-content {
will-change: initial;
}
ion-tabbar {
position: absolute;
top: 0;
left: 0;
display: block;
width: 100%;
min-height: 50px;
}
ion-tab-section {
position: relative;
top: 0;
left: 0;
display: block;
overflow: hidden;
width: 100%;
height: 100%;
}
ion-page.tab-subpage {
position: fixed;
z-index: 10;
}
ion-navbar {
position: absolute;
top: 0;
left: 0;
z-index: $z-index-navbar-section;
display: block;
width: 100%;
min-height: 50px;
}
ion-navbar-section ion-navbar.toolbar {
position: absolute;
}
ion-toolbar {
display: block;
width: 100%;
}
ion-toolbar[position=bottom] {
bottom: 0;
z-index: $z-index-toolbar;
}
.sticky {
position: sticky;
top: 0;
}
[nav-viewport],
[nav-portal],
[tab-portal] {
display: none;
}

View File

@@ -57,7 +57,9 @@ import {ScrollView} from '../../util/scroll-view';
}
})
export class Content extends Ion {
private _padding: number = 0;
private _paddingTop: number = 0;
private _paddingBottom: number = 0;
private _scrollPadding: number = 0;
private _inputPolling: boolean = false;
private _scroll: ScrollView;
private _scLsn: Function;
@@ -370,14 +372,24 @@ export class Content extends Ion {
* so content below the keyboard can be scrolled into view.
*/
addScrollPadding(newPadding: number) {
if (newPadding > this._padding) {
if (newPadding > this._scrollPadding) {
console.debug('content addScrollPadding', newPadding);
this._padding = newPadding;
this._scrollPadding = newPadding;
this._scrollEle.style.paddingBottom = newPadding + 'px';
}
}
/**
* @private
*/
setContentPadding(paddingTop: number, paddingBottom: number) {
this._paddingTop = paddingTop;
this._paddingBottom = paddingBottom;
this._scrollEle.style.paddingTop = (paddingTop > 0 ? paddingTop + 'px' : '');
this._scrollEle.style.paddingBottom = (paddingBottom > 0 ? paddingBottom + 'px' : '');
}
/**
* @private
*/
@@ -386,8 +398,8 @@ export class Content extends Ion {
this._inputPolling = true;
this._keyboard.onClose(() => {
this._padding = 0;
this._scrollEle.style.paddingBottom = '';
this._scrollPadding = 0;
this._scrollEle.style.paddingBottom = (this._paddingBottom > 0 ? this._paddingBottom + 'px' : '');
this._inputPolling = false;
this.addScrollPadding(0);
}, 200, Infinity);

View File

@@ -230,14 +230,14 @@ export interface LoadingOptions {
*/
class LoadingPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
backdrop.fromTo('opacity', '0.01', '0.3');
wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
backdrop.fromTo('opacity', 0.01, 0.3);
this
.easing('ease-in-out')
@@ -251,14 +251,14 @@ export interface LoadingOptions {
class LoadingPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
backdrop.fromTo('opacity', '0.3', '0');
wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
backdrop.fromTo('opacity', 0.3, 0);
this
.easing('ease-in-out')
@@ -272,14 +272,14 @@ export interface LoadingOptions {
class LoadingMdPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.1', '1');
backdrop.fromTo('opacity', '0.01', '0.50');
wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.1, 1);
backdrop.fromTo('opacity', 0.01, 0.5);
this
.easing('ease-in-out')
@@ -293,14 +293,14 @@ export interface LoadingOptions {
class LoadingMdPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '0.9');
backdrop.fromTo('opacity', '0.50', '0');
wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 0.9);
backdrop.fromTo('opacity', 0.5, 0);
this
.easing('ease-in-out')
@@ -314,14 +314,14 @@ export interface LoadingOptions {
class LoadingWpPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
wrapper.fromTo('opacity', '0.01', '1').fromTo('scale', '1.3', '1');
backdrop.fromTo('opacity', '0.01', '0.16');
wrapper.fromTo('opacity', 0.01, 1).fromTo('scale', 1.3, 1);
backdrop.fromTo('opacity', 0.01, 0.16);
this
.easing('cubic-bezier(0,0 0.05,1)')
@@ -335,14 +335,14 @@ export interface LoadingOptions {
class LoadingWpPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.loading-wrapper'));
wrapper.fromTo('opacity', '1', '0').fromTo('scale', '1', '1.3');
backdrop.fromTo('opacity', '0.16', '0');
wrapper.fromTo('opacity', 0.99, 0).fromTo('scale', 1, 1.3);
backdrop.fromTo('opacity', 0.16, 0);
this
.easing('ease-out')

View File

@@ -1,15 +1,15 @@
import {Component, ComponentRef, ComponentResolver, ElementRef, HostListener, ViewChild, ViewContainerRef} from '@angular/core';
import {Component, ComponentResolver, HostListener, ViewChild, ViewContainerRef} from '@angular/core';
import {addSelector} from '../../config/bootstrap';
import {Animation} from '../../animations/animation';
import {NavParams} from '../nav/nav-params';
import {isPresent, pascalCaseToDashCase} from '../../util/util';
import {Key} from '../../util/key';
import {Transition, TransitionOptions} from '../../transitions/transition';
import {PageTransition} from '../../transitions/page-transition';
import {TransitionOptions} from '../../transitions/transition';
import {ViewController} from '../nav/view-controller';
import {windowDimensions} from '../../util/dom';
import {nativeRaf, CSS} from '../../util/dom';
/**
* @name Modal
@@ -191,7 +191,7 @@ export class ModalCmp {
}
loadComponent(done: Function) {
addSelector(this._navParams.data.componentType, 'ion-modal-inner');
addSelector(this._navParams.data.componentType, 'ion-page');
this._compiler.resolveComponent(this._navParams.data.componentType).then((componentFactory) => {
let componentRef = this.viewport.createComponent(componentFactory, this.viewport.length, this.viewport.parentInjector);
@@ -227,9 +227,9 @@ export class ModalCmp {
/**
* Animations for modals
*/
class ModalSlideIn extends Transition {
class ModalSlideIn extends PageTransition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdropEle = ele.querySelector('ion-backdrop');
@@ -263,12 +263,12 @@ export class ModalCmp {
}
}
}
Transition.register('modal-slide-in', ModalSlideIn);
PageTransition.register('modal-slide-in', ModalSlideIn);
class ModalSlideOut extends Transition {
class ModalSlideOut extends PageTransition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
@@ -290,12 +290,12 @@ class ModalSlideOut extends Transition {
.add(wrapper);
}
}
Transition.register('modal-slide-out', ModalSlideOut);
PageTransition.register('modal-slide-out', ModalSlideOut);
class ModalMDSlideIn extends Transition {
class ModalMDSlideIn extends PageTransition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
@@ -311,7 +311,7 @@ class ModalMDSlideIn extends Transition {
backdrop.fromTo('opacity', 0.01, 0.4);
wrapper.fromTo('translateY', '40px', '0px');
wrapper.fromTo('opacity', '0.01', '1.0');
wrapper.fromTo('opacity', 0.01, 1);
const DURATION = 280;
const EASING = 'cubic-bezier(0.36,0.66,0.04,1)';
@@ -328,12 +328,12 @@ class ModalMDSlideIn extends Transition {
}
}
}
Transition.register('modal-md-slide-in', ModalMDSlideIn);
PageTransition.register('modal-md-slide-in', ModalMDSlideIn);
class ModalMDSlideOut extends Transition {
class ModalMDSlideOut extends PageTransition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
@@ -341,7 +341,7 @@ class ModalMDSlideOut extends Transition {
backdrop.fromTo('opacity', 0.4, 0.0);
wrapper.fromTo('translateY', '0px', '40px');
wrapper.fromTo('opacity', '1.0', '0.00');
wrapper.fromTo('opacity', 0.99, 0);
this
.element(leavingView.pageRef())
@@ -351,4 +351,4 @@ class ModalMDSlideOut extends Transition {
.add(backdrop);
}
}
Transition.register('modal-md-slide-out', ModalMDSlideOut);
PageTransition.register('modal-md-slide-out', ModalMDSlideOut);

View File

@@ -1,4 +1,4 @@
import {ViewContainerRef, ComponentResolver, ComponentRef, provide, ReflectiveInjector, ResolvedReflectiveProvider, ElementRef, NgZone, Renderer, EventEmitter} from '@angular/core';
import {ViewContainerRef, ComponentResolver, ComponentFactory, ComponentRef, provide, ReflectiveInjector, ResolvedReflectiveProvider, ElementRef, NgZone, Renderer, EventEmitter} from '@angular/core';
import {addSelector} from '../../config/bootstrap';
import {App} from '../app/app';
@@ -1059,7 +1059,7 @@ export class NavController extends Ion {
// DOM WRITE
this.setTransitioning(true, 500);
this.loadPage(enteringView, null, opts, () => {
this.loadPage(enteringView, this._viewport, opts, () => {
enteringView.fireLoaded();
this.viewDidLoad.emit(enteringView);
this._postRender(transId, enteringView, leavingView, isAlreadyTransitioning, opts, done);
@@ -1467,8 +1467,8 @@ export class NavController extends Ion {
/**
* @private
*/
loadPage(view: ViewController, navbarContainerRef: ViewContainerRef, opts: NavOptions, done: Function) {
if (!this._viewport || !view.componentType) {
loadPage(view: ViewController, viewport: ViewContainerRef, opts: NavOptions, done: Function) {
if (!viewport || !view.componentType) {
return;
}
@@ -1489,7 +1489,7 @@ export class NavController extends Ion {
let componentRef = componentFactory.create(childInjector, null, null);
this._viewport.insert(componentRef.hostView, this._viewport.length);
viewport.insert(componentRef.hostView, viewport.length);
// a new ComponentRef has been created
// set the ComponentRef's instance to its ViewController
@@ -1518,30 +1518,6 @@ export class NavController extends Ion {
componentRef.destroy();
});
if (!navbarContainerRef) {
// there was not a navbar container ref already provided
// so use the location of the actual navbar template
navbarContainerRef = view.getNavbarViewRef();
}
// find a navbar template if one is in the page
let navbarTemplateRef = view.getNavbarTemplateRef();
// check if we have both a navbar ViewContainerRef and a template
if (navbarContainerRef && navbarTemplateRef) {
// let's now create the navbar view
let navbarViewRef = navbarContainerRef.createEmbeddedView(navbarTemplateRef);
view.onDestroy(() => {
// manually destroy the navbar when the page is destroyed
navbarViewRef.destroy();
});
}
// options may have had a postLoad method
// used mainly by tabs
opts.postLoad && opts.postLoad(view);
// our job is done here
done(view);
});
@@ -1852,7 +1828,6 @@ export interface NavOptions {
keyboardClose?: boolean;
preload?: boolean;
transitionDelay?: number;
postLoad?: Function;
progressAnimation?: boolean;
climbNav?: boolean;
ev?: any;

View File

@@ -109,7 +109,7 @@ import {ViewController} from './view-controller';
*/
@Component({
selector: 'ion-nav',
template: '<div #viewport></div><div nav-portal></div>',
template: '<div #viewport nav-viewport></div><div nav-portal></div>',
directives: [NavPortal],
encapsulation: ViewEncapsulation.None,
})

View File

@@ -13,15 +13,18 @@ class MyCmpTest{}
@Component({
template: `
<ion-navbar *navbar>
<ion-title>{{title}}</ion-title>
<ion-buttons start>
<button><ion-icon name="star"></ion-icon></button>
</ion-buttons>
<ion-buttons end>
<button>S1g</button>
</ion-buttons>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>{{title}}</ion-title>
<ion-buttons start>
<button><ion-icon name="star"></ion-icon></button>
</ion-buttons>
<ion-buttons end>
<button>S1g</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-list-header>
@@ -57,7 +60,7 @@ class MyCmpTest{}
directives: [MyCmpTest]
})
class FirstPage {
pushPage;
pushPage = FullPage;
title = 'First Page';
pages: Array<number> = [];
@ViewChild(Content) content: Content;
@@ -66,8 +69,6 @@ class FirstPage {
private nav: NavController,
private view: ViewController
) {
this.pushPage = FullPage;
for (var i = 1; i <= 50; i++) {
this.pages.push(i);
}
@@ -201,12 +202,15 @@ class FullPage {
@Component({
template: `
<ion-navbar *navbar primary>
<ion-title>Primary Color Page Header</ion-title>
<ion-buttons end>
<button>S1g</button>
</ion-buttons>
</ion-navbar>
<ion-header>
<ion-navbar primary>
<ion-title>Primary Color Page Header</ion-title>
<ion-buttons end>
<button>S1g</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content padding>
<p><button class="e2eFrom3To2" (click)="nav.pop()">Pop</button></p>
<p><button (click)="pushAnother()">Push to AnotherPage</button></p>
@@ -221,9 +225,12 @@ class FullPage {
</ion-fixed>
<ion-fixed style="pointer-events: none; top:0; bottom:0; right:0; width:50%; background: rgba(0,0,0,0.5);"></ion-fixed>
</ion-content>
<ion-toolbar position="bottom">
Footer
</ion-toolbar>
<ion-footer>
<ion-toolbar>
Footer
</ion-toolbar>
</ion-footer>
`
})
class PrimaryHeaderPage {
@@ -267,9 +274,12 @@ class PrimaryHeaderPage {
@Component({
template: `
<ion-navbar *navbar hideBackButton>
<ion-title>Another Page Header</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar hideBackButton>
<ion-title>Another Page Header</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
@@ -289,9 +299,11 @@ class PrimaryHeaderPage {
</ion-list>
</ion-content>
<ion-toolbar position="bottom">
Another Page Footer
</ion-toolbar>
<ion-footer>
<ion-toolbar>
Another Page Footer
</ion-toolbar>
</ion-footer>
`
})
class AnotherPage {

View File

@@ -1,9 +1,11 @@
import {Output, EventEmitter, Type, TemplateRef, ViewContainerRef, ElementRef, Renderer, ChangeDetectorRef} from '@angular/core';
import {Header, Footer} from '../toolbar/toolbar';
import {isPresent, merge} from '../../util/util';
import {Navbar} from '../navbar/navbar';
import {NavController, NavOptions} from './nav-controller';
import {NavParams} from './nav-params';
import {isPresent, merge} from '../../util/util';
import {Tabs} from '../tabs/tabs';
/**
@@ -27,13 +29,13 @@ export class ViewController {
private _cntDir: any;
private _cntRef: ElementRef;
private _tbRefs: ElementRef[] = [];
private _destroys: Function[] = [];
private _hdrDir: Header;
private _ftrDir: Footer;
private _destroyFn: Function;
private _hdAttr: string = null;
private _leavingOpts: NavOptions = null;
private _loaded: boolean = false;
private _nbDir: Navbar;
private _nbTmpRef: TemplateRef<Object>;
private _nbVwRef: ViewContainerRef;
private _onDismiss: Function = null;
private _pgRef: ElementRef;
private _cd: ChangeDetectorRef;
@@ -110,6 +112,9 @@ export class ViewController {
this.didUnload = new EventEmitter();
}
/**
* @private
*/
subscribe(generatorOrNext?: any): any {
return this._emitter.subscribe(generatorOrNext);
}
@@ -121,10 +126,16 @@ export class ViewController {
this._emitter.emit(data);
}
/**
* @private
*/
onDismiss(callback: Function) {
this._onDismiss = callback;
}
/**
* @private
*/
dismiss(data?: any, role?: any, navOptions: NavOptions = {}) {
let options = merge({}, this._leavingOpts, navOptions);
return this._nav.remove(this._nav.indexOf(this), 1, options).then(() => {
@@ -140,6 +151,13 @@ export class ViewController {
this._nav = navCtrl;
}
/**
* @private
*/
getNav() {
return this._nav;
}
/**
* @private
*/
@@ -201,31 +219,21 @@ export class ViewController {
/**
* You can find out the index of the current view is in the current navigation stack.
*
* ```typescript
* ```ts
* export class Page1 {
* constructor(view: ViewController){
* this.view = view;
* constructor(private view: ViewController){
* // Just log out the index
* console.log(this.view.index);
* }
* }
* ```
*
* @returns {number} Returns the index of this page within its NavController.
* @returns {number} Returns the index of this page within its `NavController`.
*/
get index(): number {
return (this._nav ? this._nav.indexOf(this) : -1);
}
/**
* @private
*/
private isRoot(): boolean {
// deprecated warning
console.warn('ViewController isRoot() has been renamed to isFirst()');
return this.isFirst();
}
/**
* @returns {boolean} Returns if this Page is the first in the stack of pages within its NavController.
*/
@@ -255,11 +263,6 @@ export class ViewController {
this._hdAttr = (shouldShow ? null : '');
renderer.setElementAttribute(this._pgRef.nativeElement, 'hidden', this._hdAttr);
let navbarRef = this.navbarRef();
if (navbarRef) {
renderer.setElementAttribute(navbarRef.nativeElement, 'hidden', this._hdAttr);
}
}
}
@@ -273,34 +276,6 @@ export class ViewController {
}
}
/**
* @private
*/
setNavbarTemplateRef(templateRef: TemplateRef<Object>) {
this._nbTmpRef = templateRef;
}
/**
* @private
*/
getNavbarTemplateRef(): TemplateRef<Object> {
return this._nbTmpRef;
}
/**
* @private
*/
getNavbarViewRef() {
return this._nbVwRef;
}
/**
* @private
*/
setNavbarViewRef(viewContainerRef: ViewContainerRef) {
this._nbVwRef = viewContainerRef;
}
/**
* @private
*/
@@ -331,6 +306,13 @@ export class ViewController {
return this._cntRef;
}
/**
* @private
*/
setContent(directive: any) {
this._cntDir = directive;
}
/**
* @private
*/
@@ -340,7 +322,6 @@ export class ViewController {
/**
* @private
* @returns {elementRef} Returns the Page's Content ElementRef
*/
toolbarRefs(): ElementRef[] {
return this._tbRefs;
@@ -349,8 +330,29 @@ export class ViewController {
/**
* @private
*/
setContent(directive: any) {
this._cntDir = directive;
setHeader(directive: Header) {
this._hdrDir = directive;
}
/**
* @private
*/
getHeader() {
return this._hdrDir;
}
/**
* @private
*/
setFooter(directive: Footer) {
this._ftrDir = directive;
}
/**
* @private
*/
getFooter() {
return this._ftrDir;
}
/**
@@ -376,15 +378,16 @@ export class ViewController {
}
/**
* You can find out of the current view has a Navbar or not. Be sure to wrap this in an `ionViewWillEnter` method in order to make sure the view has rendered fully.
* You can find out of the current view has a Navbar or not. Be sure
* to wrap this in an `ionViewWillEnter` method in order to make sure
* the view has rendered fully.
*
* ```typescript
* ```ts
* export class Page1 {
* constructor(view: ViewController) {
* this.view = view
* }
* constructor(private viewCtrl: ViewController) {}
*
* ionViewWillEnter(){
* console.log('Do we have a Navbar?', this.view.hasNavbar());
* console.log('Do we have a Navbar?', this.viewCtrl.hasNavbar());
* }
*}
* ```
@@ -448,9 +451,8 @@ export class ViewController {
*
* ```ts
* export class MyClass{
* constructor(viewCtrl: ViewController){
* this.viewCtrl = viewCtrl
* }
* constructor(private viewCtrl: ViewController) {}
*
* ionViewWillEnter() {
* this.viewCtrl.setBackButtonText('Previous');
* }
@@ -484,12 +486,14 @@ export class ViewController {
isLoaded(): boolean {
return this._loaded;
}
/**
* The loaded method is used to load any dynamic content/components
* into the dom before proceeding with the transition. If a component needs
* dynamic component loading, extending ViewController and overriding
* this method is a good option
* @param {function} done is a callback that must be called when async loading/actions are completed
* into the dom before proceeding with the transition. If a component
* needs dynamic component loading, extending ViewController and
* overriding this method is a good option
* @param {function} done is a callback that must be called when async
* loading/actions are completed
*/
loaded(done: (() => any)) {
done();
@@ -572,7 +576,7 @@ export class ViewController {
* @private
*/
onDestroy(destroyFn: Function) {
this._destroys.push(destroyFn);
this._destroyFn = destroyFn;
}
/**
@@ -582,11 +586,8 @@ export class ViewController {
this.didUnload.emit(null);
ctrlFn(this, 'DidUnload');
for (var i = 0; i < this._destroys.length; i++) {
this._destroys[i]();
}
this._destroys.length = 0;
this._tbRefs.length = 0;
this._destroyFn && this._destroyFn();
this._destroyFn = null;
}
}

View File

@@ -1,4 +1,4 @@
import {Component, Directive, Optional, ElementRef, Renderer, TemplateRef, forwardRef, Inject, ViewContainerRef, Input} from '@angular/core';
import {Component, Directive, Optional, ElementRef, Renderer, forwardRef, Inject, Input} from '@angular/core';
import {Ion} from '../ion';
import {Icon} from '../icon/icon';
@@ -137,8 +137,7 @@ export class Navbar extends ToolbarBase {
private _app: App,
@Optional() viewCtrl: ViewController,
elementRef: ElementRef,
config: Config,
private _renderer: Renderer
config: Config
) {
super(elementRef);
@@ -230,14 +229,13 @@ export class Navbar extends ToolbarBase {
selector: 'template[navbar]'
})
export class NavbarTemplate {
constructor(
viewContainerRef: ViewContainerRef,
templateRef: TemplateRef<Object>,
@Optional() viewCtrl: ViewController
) {
if (viewCtrl) {
viewCtrl.setNavbarTemplateRef(templateRef);
viewCtrl.setNavbarViewRef(viewContainerRef);
}
constructor() {
// deprecated warning: added 2016-06-14, beta.10
console.warn('ion-navbar no longer requires *navbar attribute. Please restructure header to:\n' +
'<ion-header>\n' +
' <ion-navbar>\n' +
' ...\n' +
' </ion-navbar>\n' +
'</ion-header>');
}
}

View File

@@ -613,7 +613,7 @@ class PickerDisplayCmp {
}
getSelected(): any {
let selected = {};
let selected: {[k: string]: any} = {};
this.d.columns.forEach((col, index) => {
let selectedColumn = col.options[col.selectedIndex];
selected[col.name] = {
@@ -658,7 +658,7 @@ export interface PickerColumnOption {
*/
class PickerSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
@@ -675,7 +675,7 @@ Transition.register('picker-slide-in', PickerSlideIn);
class PickerSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));

View File

@@ -2,7 +2,8 @@ import {Component, ComponentResolver, ElementRef, HostListener, Renderer, ViewCh
import {addSelector} from '../../config/bootstrap';
import {Animation} from '../../animations/animation';
import {Transition, TransitionOptions} from '../../transitions/transition';
import {PageTransition} from '../../transitions/page-transition';
import {TransitionOptions} from '../../transitions/transition';
import {Config} from '../../config/config';
import {NavParams} from '../nav/nav-params';
import {Platform} from '../../platform/platform';
@@ -244,9 +245,9 @@ export interface PopoverOptions {
/**
* Animations for popover
*/
class PopoverTransition extends Transition {
constructor(opts: TransitionOptions) {
super(opts);
class PopoverTransition extends PageTransition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(enteringView, leavingView, opts);
}
mdPositionView(nativeEle: HTMLElement, ev: any) {
@@ -392,16 +393,16 @@ class PopoverTransition extends Transition {
}
class PopoverPopIn extends PopoverTransition {
constructor(private enteringView: ViewController, private leavingView: ViewController, private opts: TransitionOptions) {
super(opts);
constructor(enteringView: ViewController, leavingView: ViewController, private opts: TransitionOptions) {
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.popover-wrapper'));
wrapper.fromTo('opacity', '0.01', '1');
backdrop.fromTo('opacity', '0.01', '0.08');
wrapper.fromTo('opacity', 0.01, 1);
backdrop.fromTo('opacity', 0.01, 0.08);
this
.easing('ease')
@@ -417,19 +418,19 @@ class PopoverPopIn extends PopoverTransition {
});
}
}
Transition.register('popover-pop-in', PopoverPopIn);
PageTransition.register('popover-pop-in', PopoverPopIn);
class PopoverPopOut extends PopoverTransition {
constructor(private enteringView: ViewController, private leavingView: ViewController, private opts: TransitionOptions) {
super(opts);
constructor(enteringView: ViewController, leavingView: ViewController, private opts: TransitionOptions) {
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let backdrop = new Animation(ele.querySelector('ion-backdrop'));
let wrapper = new Animation(ele.querySelector('.popover-wrapper'));
wrapper.fromTo('opacity', '1', '0');
backdrop.fromTo('opacity', '0.08', '0');
wrapper.fromTo('opacity', 0.99, 0);
backdrop.fromTo('opacity', 0.08, 0);
this
.easing('ease')
@@ -438,20 +439,20 @@ class PopoverPopOut extends PopoverTransition {
.add(wrapper);
}
}
Transition.register('popover-pop-out', PopoverPopOut);
PageTransition.register('popover-pop-out', PopoverPopOut);
class PopoverMdPopIn extends PopoverTransition {
constructor(private enteringView: ViewController, private leavingView: ViewController, private opts: TransitionOptions) {
super(opts);
constructor(enteringView: ViewController, leavingView: ViewController, private opts: TransitionOptions) {
super(enteringView, leavingView, opts);
let ele = enteringView.pageRef().nativeElement;
let content = new Animation(ele.querySelector('.popover-content'));
let viewport = new Animation(ele.querySelector('.popover-viewport'));
content.fromTo('scale', '0.001', '1');
viewport.fromTo('opacity', '0', '1');
content.fromTo('scale', 0.001, 1);
viewport.fromTo('opacity', 0.01, 1);
this
.easing('cubic-bezier(0.36,0.66,0.04,1)')
@@ -467,26 +468,26 @@ class PopoverMdPopIn extends PopoverTransition {
});
}
}
Transition.register('popover-md-pop-in', PopoverMdPopIn);
PageTransition.register('popover-md-pop-in', PopoverMdPopIn);
class PopoverMdPopOut extends PopoverTransition {
constructor(private enteringView: ViewController, private leavingView: ViewController, private opts: TransitionOptions) {
super(opts);
constructor(enteringView: ViewController, leavingView: ViewController, private opts: TransitionOptions) {
super(enteringView, leavingView, opts);
let ele = leavingView.pageRef().nativeElement;
let wrapper = new Animation(ele.querySelector('.popover-wrapper'));
wrapper.fromTo('opacity', '1', '0');
wrapper.fromTo('opacity', 0.99, 0);
this
.easing('ease')
.duration(500)
.fadeIn()
.fromTo('opacity', 0.01, 1)
.add(wrapper);
}
}
Transition.register('popover-md-pop-out', PopoverMdPopOut);
PageTransition.register('popover-md-pop-out', PopoverMdPopOut);
let popoverIds = -1;

View File

@@ -51,7 +51,6 @@ class IntroPage {
<ion-content padding>
<h1>Another Page</h1>
</ion-content>
`
})
class MainPage {}

View File

@@ -1,11 +1,13 @@
<ion-navbar *navbar>
<ion-buttons end>
<button (click)="skip()">
{{continueText}}
</button>
</ion-buttons>
<ion-title>Slides</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-buttons end>
<button (click)="skip()">
{{continueText}}
</button>
</ion-buttons>
<ion-title>Slides</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-slides pager [options]="mySlideOptions" (ionDidChange)="onSlideChanged($event)" (ionWillChange)="onSlideChangeStart($event)" (ionDrag)="onSlideMove($event)">

View File

@@ -207,7 +207,7 @@ export class Tab extends NavController {
@Output() ionSelect: EventEmitter<Tab> = new EventEmitter();
constructor(
@Inject(forwardRef(() => Tabs)) parentTabs: Tabs,
@Inject(forwardRef(() => Tabs)) public parent: Tabs,
app: App,
config: Config,
keyboard: Keyboard,
@@ -218,9 +218,9 @@ export class Tab extends NavController {
private _cd: ChangeDetectorRef
) {
// A Tab is a NavController for its child pages
super(parentTabs, app, config, keyboard, elementRef, zone, renderer, compiler);
super(parent, app, config, keyboard, elementRef, zone, renderer, compiler);
parentTabs.add(this);
parent.add(this);
this._panelId = 'tabpanel-' + this.id;
this._btnId = 'tab-' + this.id;
@@ -266,11 +266,7 @@ export class Tab extends NavController {
console.debug('Tabs, preload', this.id);
this.load({
animate: false,
preload: true,
postLoad: (viewCtrl: ViewController) => {
let navbar = viewCtrl.getNavbar();
navbar && navbar.setHidden(true);
}
preload: true
}, function(){});
}
}, wait);
@@ -279,18 +275,14 @@ export class Tab extends NavController {
/**
* @private
*/
loadPage(viewCtrl: ViewController, navbarContainerRef: any, opts: NavOptions, done: Function) {
// by default a page's navbar goes into the shared tab's navbar section
navbarContainerRef = this.parent.navbarContainerRef;
loadPage(viewCtrl: ViewController, viewport: ViewContainerRef, opts: NavOptions, done: Function) {
let isTabSubPage = (this.parent.subPages && viewCtrl.index > 0);
if (isTabSubPage) {
// a subpage, that's not the first index
// should not use the shared tabs navbar section, but use it's own
navbarContainerRef = null;
viewport = this.parent.portal;
}
super.loadPage(viewCtrl, navbarContainerRef, opts, () => {
super.loadPage(viewCtrl, viewport, opts, () => {
if (isTabSubPage) {
// add the .tab-subpage css class to tabs pages that should act like subpages
let pageEleRef = viewCtrl.pageRef();
@@ -316,18 +308,6 @@ export class Tab extends NavController {
// this tab is not selected, do not detect changes
this._cd.detach();
}
this.hideNavbars(!isSelected);
}
/**
* @private
*/
hideNavbars(shouldHideNavbars: boolean) {
this._views.forEach(viewCtrl => {
let navbar = viewCtrl.getNavbar();
navbar && navbar.setHidden(shouldHideNavbars);
});
}
/**

View File

@@ -15,12 +15,12 @@ $tab-button-ios-active-color: $toolbar-ios-active-color !default;
$tab-button-ios-inactive-color: $toolbar-ios-inactive-color !default;
tabbar {
ion-tabbar {
border-top: 1px solid $toolbar-ios-border-color;
background: $tabbar-ios-background;
}
ion-tabs[tabbarPlacement=top] tabbar {
ion-tabs[tabbarPlacement=top] ion-tabbar {
border-top: 0;
border-bottom: 1px solid $toolbar-ios-border-color;
}
@@ -98,11 +98,11 @@ ion-tabs[tabbarPlacement=top] tabbar {
&.hairlines ion-tabs {
tabbar {
ion-tabbar {
border-top-width: $hairlines-width;
}
&[tabbarPlacement="top"] tabbar {
&[tabbarPlacement="top"] ion-tabbar {
border-bottom-width: $hairlines-width;
}
@@ -114,7 +114,7 @@ ion-tabs[tabbarPlacement=top] tabbar {
@mixin tabbar-ios($color-name, $color-base, $color-contrast) {
ion-tabs[#{$color-name}] tabbar {
ion-tabs[#{$color-name}] ion-tabbar {
border-color: darken($color-base, 10%);
background-color: $color-base;

View File

@@ -15,7 +15,7 @@ $tab-button-md-active-color: $toolbar-md-active-color !default;
$tab-button-md-inactive-color: $toolbar-md-inactive-color !default;
tabbar {
ion-tabbar {
background: $tabbar-md-background;
}
@@ -101,7 +101,7 @@ tab-highlight {
@mixin tabbar-md($color-name, $color-base, $color-contrast) {
ion-tabs[#{$color-name}] tabbar {
ion-tabs[#{$color-name}] ion-tabbar {
background-color: $color-base;
.tab-button {

View File

@@ -4,62 +4,6 @@
// --------------------------------------------------
ion-tabs {
display: flex;
overflow: hidden;
flex-direction: column;
margin: 0;
padding: 0;
width: 100%;
max-width: 100%;
height: 100%;
max-height: 100%;
}
ion-tab {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: none;
overflow: hidden;
flex-direction: column;
width: 100%;
height: 100%;
&.show-tab {
display: flex;
}
}
ion-tabs > ion-navbar-section {
order: $flex-order-tabbar-navbar;
}
ion-tabbar-section {
position: relative;
order: $flex-order-tabbar-bottom;
}
[tabbarPlacement=top] ion-tabbar-section {
order: $flex-order-tabbar-top;
}
tabbar {
position: relative;
display: flex;
overflow: hidden;
justify-content: center;
}
.tab-button {
@include user-select-none();

View File

@@ -1,4 +1,4 @@
import {Component, Directive, ElementRef, Optional, Host, forwardRef, ViewContainerRef, ViewChild, ViewChildren, EventEmitter, Output, Input, Renderer, ViewEncapsulation} from '@angular/core';
import {Component, ElementRef, Optional, ViewChild, ViewContainerRef, EventEmitter, Output, Input, Renderer, ViewEncapsulation} from '@angular/core';
import {App} from '../app/app';
import {Config} from '../../config/config';
@@ -133,34 +133,26 @@ import {ViewController} from '../nav/view-controller';
@Component({
selector: 'ion-tabs',
template:
'<ion-navbar-section [class.statusbar-padding]="_sbPadding">' +
'<template navbar-anchor></template>' +
'</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="#" (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>' +
'<ion-button-effect></ion-button-effect>' +
'</a>' +
'<tab-highlight></tab-highlight>' +
'</tabbar>' +
'</ion-tabbar-section>' +
'<ion-content-section>' +
'<ng-content></ng-content>' +
'</ion-content-section>',
'<ion-tabbar role="tablist" #tabbar>' +
'<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>' +
'<ion-button-effect></ion-button-effect>' +
'</a>' +
'<tab-highlight></tab-highlight>' +
'</ion-tabbar>' +
'<ng-content></ng-content>' +
'<div #portal tab-portal></div>',
directives: [
TabButton,
TabHighlight,
forwardRef(() => TabNavBarAnchor)
TabHighlight
],
encapsulation: ViewEncapsulation.None,
})
export class Tabs extends Ion {
private _ids: number = -1;
private _preloadTabs: boolean = null;
private _tabs: Array<Tab> = [];
private _tabs: Tab[] = [];
private _onReady: any = null;
private _sbPadding: boolean;
private _useHighlight: boolean;
@@ -170,11 +162,6 @@ export class Tabs extends Ion {
*/
id: number;
/**
* @private
*/
navbarContainerRef: ViewContainerRef;
/**
* @private
*/
@@ -215,6 +202,16 @@ export class Tabs extends Ion {
*/
@ViewChild(TabHighlight) private _highlight: TabHighlight;
/**
* @private
*/
@ViewChild('tabbar') private _tabbar: ElementRef;
/**
* @private
*/
@ViewChild('portal', {read: ViewContainerRef}) portal: ViewContainerRef;
/**
* @private
*/
@@ -230,11 +227,12 @@ export class Tabs extends Ion {
private _renderer: Renderer
) {
super(_elementRef);
this.parent = parent;
this.id = ++tabIds;
this.subPages = _config.getBoolean('tabSubPages', false);
this._useHighlight = _config.getBoolean('tabbarHighlight', false);
this._sbPadding = _config.getBoolean('statusbarPadding', false);
this.subPages = _config.getBoolean('tabSubPages');
this._useHighlight = _config.getBoolean('tabbarHighlight');
this._sbPadding = _config.getBoolean('statusbarPadding');
if (parent) {
// this Tabs has a parent Nav
@@ -501,17 +499,17 @@ export class Tabs extends Ion {
return nav;
}
/**
* @private
*/
setTabbarPosition(top: number, bottom: number) {
let tabbarEle = <HTMLElement>this._tabbar.nativeElement;
tabbarEle.style.top = (top > -1 ? top + 'px' : '');
tabbarEle.style.bottom = (bottom > -1 ? bottom + 'px' : '');
tabbarEle.classList.add('show-tabbar');
}
}
let tabIds = -1;
/**
* @private
*/
@Directive({selector: 'template[navbar-anchor]'})
class TabNavBarAnchor {
constructor(@Host() tabs: Tabs, viewContainerRef: ViewContainerRef) {
tabs.navbarContainerRef = viewContainerRef;
}
}

View File

@@ -16,7 +16,7 @@ $tab-button-wp-inactive-color: $toolbar-wp-inactive-color !default;
$tab-button-wp-background-activated: rgba(0, 0, 0, .1) !default;
tabbar {
ion-tabbar {
background: $tabbar-wp-background;
}
@@ -94,7 +94,7 @@ tabbar {
@mixin tabbar-wp($color-name, $color-base, $color-contrast) {
ion-tabs[#{$color-name}] tabbar {
ion-tabs[#{$color-name}] ion-tabbar {
background-color: $color-base;
.tab-button {

View File

@@ -1,30 +1,10 @@
import {Component, ViewChild} from '@angular/core';
import {Location} from '@angular/common';
import {ionicBootstrap, NavController, NavParams, Modal, ViewController, Tabs, Tab} from '../../../../../src';
@Component({
template: `
<ion-navbar *navbar>
<ion-title>Sign In</ion-title>
</ion-navbar>
<ion-content padding>
<ion-card>
<ion-item>
<ion-label>Username:</ion-label>
<ion-input></ion-input>
</ion-item>
<ion-item>
<ion-label>Password:</ion-label>
<ion-input type="password"></ion-input>
</ion-item>
<ion-item>
<button block id="signIn" (click)="push()">Sign In</button>
</ion-item>
</ion-card>
</ion-content>
`
templateUrl: './signIn.html'
})
class SignIn {
constructor(private nav: NavController) {}
@@ -38,14 +18,7 @@ class SignIn {
@Component({
template: `
<ion-toolbar>
<ion-title>Chat Modal</ion-title>
</ion-toolbar>
<ion-content padding>
<p><button (click)="viewCtrl.dismiss()">Close Modal</button></p>
</ion-content>
`
templateUrl: './modalChat.html'
})
class ChatPage {
constructor(private viewCtrl: ViewController) {}
@@ -115,19 +88,7 @@ class TabsPage {
// tab 1
//
@Component({
template: '' +
'<ion-navbar *navbar>' +
'<ion-title>Tabs 1 Page 1</ion-title>' +
'</ion-navbar>' +
'<ion-content padding>' +
'<p><button id="goToTab1Page2" (click)="push()">Go to Tab 1, Page 2</button></p>' +
'<p><button (click)="logout()">Logout</button></p>' +
'<p><button (click)="favoritesTab()">Favorites Tab</button></p>' +
'<p><button (click)="goBack()">Go Back</button></p>' +
'<p>UserId: {{userId}}</p>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'</ion-content>'
templateUrl: './tab1page1.html'
})
class Tab1Page1 {
userId: string;
@@ -178,16 +139,7 @@ class Tab1Page1 {
@Component({
template: '' +
'<ion-navbar *navbar primary>' +
'<ion-title>Tabs 1 Page 2</ion-title>' +
'</ion-navbar>' +
'<ion-content padding>' +
'<p><button (click)="push()">Go to Tab 1, Page 3</button></p>' +
'<p><button id="backToTab1Page1" (click)="nav.pop()">Back to Tab 1, Page 1</button></p>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'</ion-content>'
templateUrl: './tab1page2.html'
})
class Tab1Page2 {
constructor(private nav: NavController) {}
@@ -219,15 +171,7 @@ class Tab1Page2 {
@Component({
template: '' +
'<ion-navbar *navbar>' +
'<ion-title>Tabs 1 Page 3</ion-title>' +
'</ion-navbar>' +
'<ion-content padding>' +
'<p><button (click)="nav.pop()">Back to Tab 1, Page 2</button></p>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'</ion-content>'
templateUrl: './tab1page3.html'
})
class Tab1Page3 {
constructor(private nav: NavController) {}
@@ -254,20 +198,11 @@ class Tab1Page3 {
}
//
// tab 2
//
@Component({
template: '' +
'<ion-navbar *navbar>' +
'<ion-title>Tabs 2 Page 1</ion-title>' +
'</ion-navbar>' +
'<ion-content padding>' +
'<p><button (click)="push()">Go to Tab 2, Page 2</button></p>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'</ion-content>'
templateUrl: './tab2page1.html'
})
class Tab2Page1 {
constructor(private nav: NavController) {}
@@ -299,16 +234,7 @@ class Tab2Page1 {
@Component({
template: '' +
'<ion-navbar *navbar>' +
'<ion-title>Tabs 2 Page 2</ion-title>' +
'</ion-navbar>' +
'<ion-content padding>' +
'<p><button (click)="push()">Go to Tab 2, Page 3</button></p>' +
'<p><button (click)="nav.pop()">Back to Tab 2, Page 1</button></p>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'</ion-content>'
templateUrl: './tab2page2.html'
})
class Tab2Page2 {
constructor(private nav: NavController) {}
@@ -340,15 +266,7 @@ class Tab2Page2 {
@Component({
template: '' +
'<ion-navbar *navbar>' +
'<ion-title>Tabs 2 Page 3</ion-title>' +
'</ion-navbar>' +
'<ion-content padding>' +
'<p><button (click)="nav.pop()">Back to Tab 2, Page 2</button></p>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>' +
'</ion-content>'
templateUrl: './tab2page3.html'
})
class Tab2Page3 {
constructor(private nav: NavController) {}
@@ -375,16 +293,11 @@ class Tab2Page3 {
}
//
// tab 3
//
@Component({
template: '' +
'<ion-navbar *navbar>' +
'<ion-title>Tabs 3</ion-title>' +
'</ion-navbar>' +
'<ion-content padding><h2>Tabs 3</h2></ion-content>'
templateUrl: './tab3page1.html'
})
class Tab3Page1 {
@@ -411,7 +324,7 @@ class Tab3Page1 {
@Component({
template: '<ion-nav [root]="root"></ion-nav>'
template: `<ion-nav [root]="root"></ion-nav>`
})
class E2EApp {
root = SignIn;

View File

@@ -0,0 +1,9 @@
<ion-header>
<ion-toolbar>
<ion-title>Chat Modal</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<p><button (click)="viewCtrl.dismiss()">Close Modal</button></p>
</ion-content>

View File

@@ -0,0 +1,21 @@
<ion-header>
<ion-navbar>
<ion-title>Sign In</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-card>
<ion-item>
<ion-label>Username:</ion-label>
<ion-input></ion-input>
</ion-item>
<ion-item>
<ion-label>Password:</ion-label>
<ion-input type="password"></ion-input>
</ion-item>
<ion-item>
<button block id="signIn" (click)="push()">Sign In</button>
</ion-item>
</ion-card>
</ion-content>

View File

@@ -0,0 +1,15 @@
<ion-header>
<ion-navbar>
<ion-title>Tabs 1, Page 1</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<p><button id="goToTab1Page2" (click)="push()">Go to Tab 1, Page 2</button></p>
<p><button (click)="logout()">Logout</button></p>
<p><button (click)="favoritesTab()">Favorites Tab</button></p>
<p><button (click)="goBack()">Go Back</button></p>
<p>UserId: {{userId}}</p>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
</ion-content>

View File

@@ -0,0 +1,12 @@
<ion-header>
<ion-navbar primary>
<ion-title>Tabs 1, Page 2</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<p><button (click)="push()">Go to Tab 1, Page 3</button></p>
<p><button id="backToTab1Page1" (click)="nav.pop()">Back to Tab 1, Page 1</button></p>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
</ion-content>

View File

@@ -0,0 +1,11 @@
<ion-header>
<ion-navbar>
<ion-title>Tabs 1, Page 3</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<p><button (click)="nav.pop()">Back to Tab 1, Page 2</button></p>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
</ion-content>

View File

@@ -0,0 +1,11 @@
<ion-header>
<ion-navbar>
<ion-title>Tabs 2, Page 1</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<p><button (click)="push()">Go to Tab 2, Page 2</button></p>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
</ion-content>

View File

@@ -0,0 +1,12 @@
<ion-header>
<ion-navbar>
<ion-title>Tabs 2, Page 2</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<p><button (click)="push()">Go to Tab 2, Page 3</button></p>
<p><button (click)="nav.pop()">Back to Tab 2, Page 1</button></p>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
</ion-content>

View File

@@ -0,0 +1,11 @@
<ion-header>
<ion-navbar>
<ion-title>Tabs 2, Page 3</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<p><button (click)="nav.pop()">Back to Tab 2, Page 2</button></p>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
<f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f><f></f>
</ion-content>

View File

@@ -0,0 +1,9 @@
<ion-header>
<ion-navbar>
<ion-title>Tabs 3, Page 1</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h2>Tabs 3, Page 1</h2>
</ion-content>

View File

@@ -6,19 +6,21 @@ import {ionicBootstrap, NavController, App, Alert, Modal, ViewController, Tab, T
//
@Component({
template: `
<ion-toolbar>
<ion-buttons start>
<button (click)="dismiss()">Cancel</button>
</ion-buttons>
<ion-header>
<ion-toolbar>
<ion-buttons start>
<button (click)="dismiss()">Cancel</button>
</ion-buttons>
<ion-title>
Filter Sessions
</ion-title>
<ion-title>
Filter Sessions
</ion-title>
<ion-buttons end>
<button (click)="dismiss()">Done</button>
</ion-buttons>
</ion-toolbar>
<ion-buttons end>
<button (click)="dismiss()">Done</button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="outer-content">
<ion-list>
@@ -66,9 +68,12 @@ class MyModal {
//
@Component({
template: `
<ion-navbar *navbar>
<ion-title>Heart</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>Heart</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-list-header>
@@ -108,9 +113,12 @@ export class Tab1 {
//
@Component({
template: `
<ion-navbar *navbar>
<ion-title>Schedule</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>Schedule</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item-sliding *ngFor="let session of sessions" #slidingItem>
@@ -159,12 +167,15 @@ export class Tab2 {
//
@Component({
template: `
<ion-navbar *navbar>
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Stopwatch</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Stopwatch</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h2>Tab 3</h2>
<p>

View File

@@ -7,18 +7,20 @@ import {ionicBootstrap, NavController, App, Alert, Modal, ViewController, Tab, T
//
@Component({
template: `
<ion-navbar *navbar>
<ion-title>
Tab 1
</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>
Tab 1
</ion-title>
</ion-navbar>
</ion-header>
<ion-content class="home">
<ion-nav [root]="root"></ion-nav>
</ion-content>
`
})
export class Tab1 {
class Tab1 {
root = SecondPage;
}
@@ -27,18 +29,20 @@ export class Tab1 {
//
@Component({
template: `
<ion-navbar *navbar>
<ion-title>
Tab 2
</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>
Tab 2
</ion-title>
</ion-navbar>
</ion-header>
<ion-content class="home">
<ion-nav [root]="root"></ion-nav>
</ion-content>
`
})
export class Tab2 {
class Tab2 {
root = SecondPage;
}
@@ -47,18 +51,20 @@ export class Tab2 {
//
@Component({
template: `
<ion-navbar *navbar>
<ion-title>
Tab 3
</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>
Tab 3
</ion-title>
</ion-navbar>
</ion-header>
<ion-content class="home">
<ion-nav [root]="root"></ion-nav>
</ion-content>
`
})
export class Tab3 {
class Tab3 {
root = SecondPage;
}
@@ -88,11 +94,13 @@ class ThirdPage{
@Component({
template: `
<ion-navbar *navbar>
<ion-title>
Fourth Page Comp
</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>
Fourth Page Comp
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngFor="let item of items">
@@ -124,7 +132,7 @@ class FourthPage{
</ion-tabs>
`
})
export class TabsPage {
class TabsPage {
root1 = Tab1;
root2 = Tab2;
root3 = Tab3;
@@ -133,7 +141,7 @@ export class TabsPage {
@Component({
template: `<ion-nav [root]="root"></ion-nav>`
})
export class E2EApp {
class E2EApp {
root = TabsPage;
}

View File

@@ -7,9 +7,11 @@ import {ionicBootstrap, NavController, Tab} from '../../../../../src';
//
@Component({
template: `
<ion-navbar *navbar>
<ion-title>Heart</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>Heart</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h2>Tab 1</h2>
</ion-content>
@@ -24,9 +26,11 @@ class Tab1 {
//
@Component({
template: `
<ion-navbar *navbar>
<ion-title>Star</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>Star</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h2>Tab 2</h2>
</ion-content>
@@ -41,12 +45,14 @@ class Tab2 {
//
@Component({
template: `
<ion-navbar *navbar>
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Stopwatch</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Stopwatch</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h2>Tab 3</h2>
</ion-content>
@@ -61,12 +67,14 @@ class Tab3 {
//
@Component({
template: `
<ion-navbar *navbar>
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Quesarito</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Quesarito</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h2>Quesarito</h2>
</ion-content>

View File

@@ -4,9 +4,11 @@ import {ionicBootstrap, Toast, NavController} from '../../../../../src';
@Component({
template: `
<ion-navbar *navbar>
<ion-title>Another Page</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>Another Page</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<p>This is another page to show that the toast stays.</p>
</ion-content>

View File

@@ -1,6 +1,8 @@
<ion-navbar *navbar>
<ion-title>Toasts</ion-title>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>Toasts</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button block (click)="showToast()">Show Toast and Navigate</button>

View File

@@ -70,7 +70,7 @@ export class Toast extends ViewController {
super(ToastCmp, opts);
// set the position to the bottom if not provided
if ( ! opts.position || ! this.isValidPosition(opts.position)) {
if (! opts.position || ! this.isValidPosition(opts.position)) {
opts.position = TOAST_POSITION_BOTTOM;
}
@@ -173,7 +173,7 @@ class ToastCmp implements AfterViewInit {
private _elementRef: ElementRef,
params: NavParams,
renderer: Renderer
) {
) {
this.d = params.data;
@@ -237,25 +237,27 @@ export interface ToastOptions {
class ToastSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
// DOM READS
let ele = enteringView.pageRef().nativeElement;
const wrapperEle = <HTMLElement> ele.querySelector('.toast-wrapper');
let wrapper = new Animation(wrapperEle);
if ( enteringView.data && enteringView.data.position === TOAST_POSITION_TOP ) {
if (enteringView.data && enteringView.data.position === TOAST_POSITION_TOP) {
// top
// by default, it is -100% hidden (above the screen)
// so move from that to 10px below top: 0px;
wrapper.fromTo('translateY', '-100%', `${10}px`);
} else if ( enteringView.data && enteringView.data.position === TOAST_POSITION_MIDDLE ) {
} else if (enteringView.data && enteringView.data.position === TOAST_POSITION_MIDDLE) {
// Middle
// just center it and fade it in
let topPosition = Math.floor(ele.clientHeight / 2 - wrapperEle.clientHeight / 2);
// DOM WRITE
wrapperEle.style.top = `${topPosition}px`;
wrapper.fromTo('opacity', '0.01', '1.0');
wrapper.fromTo('opacity', 0.01, 1);
} else {
// bottom
// by default, it is 100% hidden (below the screen),
@@ -263,168 +265,159 @@ class ToastSlideIn extends Transition {
wrapper.fromTo('translateY', '100%', `${0 - 10}px`);
}
const EASE: string = 'cubic-bezier(.36,.66,.04,1)';
const DURATION: number = 400;
// DOM WRITES
this.easing(EASE).duration(DURATION).add(wrapper);
this.easing('cubic-bezier(.36,.66,.04,1)').duration(400).add(wrapper);
}
}
class ToastSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
// DOM reads
let ele = leavingView.pageRef().nativeElement;
const wrapperEle = <HTMLElement> ele.querySelector('.toast-wrapper');
let wrapper = new Animation(wrapperEle);
if ( leavingView.data && leavingView.data.position === TOAST_POSITION_TOP ) {
if (leavingView.data && leavingView.data.position === TOAST_POSITION_TOP) {
// top
// reverse arguments from enter transition
wrapper.fromTo('translateY', `${10}px`, '-100%');
} else if ( leavingView.data && leavingView.data.position === TOAST_POSITION_MIDDLE ) {
} else if (leavingView.data && leavingView.data.position === TOAST_POSITION_MIDDLE) {
// Middle
// just fade it out
wrapper.fromTo('opacity', '1.0', '0.0');
wrapper.fromTo('opacity', 0.99, 0);
} else {
// bottom
// reverse arguments from enter transition
wrapper.fromTo('translateY', `${0 - 10}px`, '100%');
}
const EASE: string = 'cubic-bezier(.36,.66,.04,1)';
const DURATION: number = 300;
// DOM writes
this.easing(EASE).duration(DURATION).add(wrapper);
this.easing('cubic-bezier(.36,.66,.04,1)').duration(300).add(wrapper);
}
}
class ToastMdSlideIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
// DOM reads
let ele = enteringView.pageRef().nativeElement;
const wrapperEle = ele.querySelector('.toast-wrapper');
let wrapper = new Animation(wrapperEle);
if ( enteringView.data && enteringView.data.position === TOAST_POSITION_TOP ) {
if (enteringView.data && enteringView.data.position === TOAST_POSITION_TOP) {
// top
// by default, it is -100% hidden (above the screen)
// so move from that to top: 0px;
wrapper.fromTo('translateY', '-100%', `0px`);
} else if ( enteringView.data && enteringView.data.position === TOAST_POSITION_MIDDLE ) {
wrapper.fromTo('translateY', '-100%', `0%`);
} else if (enteringView.data && enteringView.data.position === TOAST_POSITION_MIDDLE) {
// Middle
// just center it and fade it in
let topPosition = Math.floor(ele.clientHeight / 2 - wrapperEle.clientHeight / 2);
// DOM WRITE
wrapperEle.style.top = `${topPosition}px`;
wrapper.fromTo('opacity', '0.01', '1.0');
wrapper.fromTo('opacity', 0.01, 1);
} else {
// bottom
// by default, it is 100% hidden (below the screen),
// so move from that to bottom: 0px
wrapper.fromTo('translateY', '100%', `0px`);
wrapper.fromTo('translateY', '100%', `0%`);
}
const EASE: string = 'cubic-bezier(.36,.66,.04,1)';
const DURATION: number = 400;
this.easing(EASE).duration(DURATION).add(wrapper);
this.easing('cubic-bezier(.36,.66,.04,1)').duration(400).add(wrapper);
}
}
class ToastMdSlideOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
// DOM reads
let ele = leavingView.pageRef().nativeElement;
const wrapperEle = ele.querySelector('.toast-wrapper');
let wrapper = new Animation(wrapperEle);
if ( leavingView.data && leavingView.data.position === TOAST_POSITION_TOP ) {
if (leavingView.data && leavingView.data.position === TOAST_POSITION_TOP) {
// top
// reverse arguments from enter transition
wrapper.fromTo('translateY', `${0}px`, '-100%');
} else if ( leavingView.data && leavingView.data.position === TOAST_POSITION_MIDDLE ) {
wrapper.fromTo('translateY', `${0}%`, '-100%');
} else if (leavingView.data && leavingView.data.position === TOAST_POSITION_MIDDLE) {
// Middle
// just fade it out
wrapper.fromTo('opacity', '1.0', '0.0');
wrapper.fromTo('opacity', 0.99, 0);
} else {
// bottom
// reverse arguments from enter transition
wrapper.fromTo('translateY', `${0}px`, '100%');
wrapper.fromTo('translateY', `${0}%`, '100%');
}
// DOM writes
const EASE: string = 'cubic-bezier(.36,.66,.04,1)';
const DURATION: number = 450;
this.easing(EASE).duration(DURATION).add(wrapper);
this.easing('cubic-bezier(.36,.66,.04,1)').duration(450).add(wrapper);
}
}
class ToastWpPopIn extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
// DOM reads
let ele = enteringView.pageRef().nativeElement;
const wrapperEle = ele.querySelector('.toast-wrapper');
let wrapper = new Animation(wrapperEle);
if ( enteringView.data && enteringView.data.position === TOAST_POSITION_TOP ) {
if (enteringView.data && enteringView.data.position === TOAST_POSITION_TOP) {
// top
wrapper.fromTo('opacity', '0.01', '1');
wrapper.fromTo('scale', '1.3', '1');
} else if ( enteringView.data && enteringView.data.position === TOAST_POSITION_MIDDLE ) {
wrapper.fromTo('opacity', 0.01, 1);
wrapper.fromTo('scale', 1.3, 1);
} else if (enteringView.data && enteringView.data.position === TOAST_POSITION_MIDDLE) {
// Middle
// just center it and fade it in
let topPosition = Math.floor(ele.clientHeight / 2 - wrapperEle.clientHeight / 2);
// DOM WRITE
wrapperEle.style.top = `${topPosition}px`;
wrapper.fromTo('opacity', '0.01', '1.0');
wrapper.fromTo('scale', '1.3', '1');
wrapper.fromTo('opacity', 0.01, 1);
wrapper.fromTo('scale', 1.3, 1);
} else {
// bottom
wrapper.fromTo('opacity', '0.01', '1');
wrapper.fromTo('scale', '1.3', '1');
wrapper.fromTo('opacity', 0.01, 1);
wrapper.fromTo('scale', 1.3, 1);
}
// DOM writes
const EASE: string = 'cubic-bezier(0,0 0.05,1)';
const DURATION: number = 200;
this.easing(EASE).duration(DURATION).add(wrapper);
this.easing('cubic-bezier(0,0 0.05,1)').duration(200).add(wrapper);
}
}
class ToastWpPopOut extends Transition {
constructor(enteringView: ViewController, leavingView: ViewController, opts: TransitionOptions) {
super(opts);
super(enteringView, leavingView, opts);
// DOM reads
let ele = leavingView.pageRef().nativeElement;
const wrapperEle = ele.querySelector('.toast-wrapper');
let wrapper = new Animation(wrapperEle);
if ( leavingView.data && leavingView.data.position === TOAST_POSITION_TOP ) {
if (leavingView.data && leavingView.data.position === TOAST_POSITION_TOP) {
// top
// reverse arguments from enter transition
wrapper.fromTo('opacity', '1', '0.00');
wrapper.fromTo('scale', '1', '1.3');
} else if ( leavingView.data && leavingView.data.position === TOAST_POSITION_MIDDLE ) {
wrapper.fromTo('opacity', 0.99, 0);
wrapper.fromTo('scale', 1, 1.3);
} else if (leavingView.data && leavingView.data.position === TOAST_POSITION_MIDDLE) {
// Middle
// just fade it out
wrapper.fromTo('opacity', '1.0', '0.00');
wrapper.fromTo('scale', '1', '1.3');
wrapper.fromTo('opacity', 0.99, 0);
wrapper.fromTo('scale', 1, 1.3);
} else {
// bottom
// reverse arguments from enter transition
wrapper.fromTo('opacity', '1', '0.00');
wrapper.fromTo('scale', '1', '1.3');
wrapper.fromTo('opacity', 0.99, 0);
wrapper.fromTo('scale', 1, 1.3);
}
// DOM writes

View File

@@ -0,0 +1,33 @@
import {Directive, ElementRef, Optional, forwardRef, Inject, ContentChildren} from '@angular/core';
import {Button} from '../button/button';
import {Navbar} from '../navbar/navbar';
import {Toolbar} from './toolbar';
/**
* @private
*/
@Directive({
selector: 'ion-buttons,[menuToggle]'
})
export class ToolbarItem {
inToolbar: boolean;
constructor(
elementRef: ElementRef,
@Optional() toolbar: Toolbar,
@Optional() @Inject(forwardRef(() => Navbar)) navbar: Navbar
) {
toolbar && toolbar.addItemRef(elementRef);
navbar && navbar.addItemRef(elementRef);
this.inToolbar = !!(toolbar || navbar);
}
@ContentChildren(Button)
set _buttons(buttons: any) {
if (this.inToolbar) {
Button.setRoles(buttons, 'bar-button');
}
}
}

View File

@@ -0,0 +1,65 @@
import {Component, ElementRef, Optional, forwardRef, Inject, ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
import {Ion} from '../ion';
import {Navbar} from '../navbar/navbar';
import {Toolbar} from './toolbar';
/**
* @name Title
* @description
* `ion-title` is a component that sets the title of the `Toolbar` or `Navbar`
*
* @usage
*
* ```html
* <ion-header>
* <ion-navbar>
* <ion-title>Tab 1</ion-title>
* </ion-navbar>
* </ion-header>
* ```
*
* Or to create a navbar with a toolbar as a subheader:
*
* ```html
* <ion-header>
* <ion-navbar>
* <ion-title>Tab 1</ion-title>
* </ion-navbar>
* </ion-header>
*
* <ion-toolbar>
* <ion-title>Subheader</ion-title>
* </ion-toolbar>
* ```
*
* @demo /docs/v2/demos/title/
*/
@Component({
selector: 'ion-title',
template:
'<div class="toolbar-title">' +
'<ng-content></ng-content>' +
'</div>',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class ToolbarTitle extends Ion {
constructor(
private _elementRef: ElementRef,
@Optional() toolbar: Toolbar,
@Optional() @Inject(forwardRef(() => Navbar)) navbar: Navbar
) {
super(_elementRef);
toolbar && toolbar.setTitleCmp(this);
navbar && navbar.setTitleCmp(this);
}
/**
* @private
*/
getTitleText() {
return this._elementRef.nativeElement.textContent;
}
}

View File

@@ -5,17 +5,12 @@
.toolbar {
position: relative;
z-index: $z-index-toolbar;
display: flex;
overflow: hidden;
flex: 0;
flex-direction: row;
align-items: center;
justify-content: space-between;
order: $flex-order-toolbar-top;
width: 100%;
}
@@ -35,10 +30,6 @@
pointer-events: none;
}
.toolbar[position=bottom] {
order: $flex-order-toolbar-bottom;
}
ion-title {
display: flex;

View File

@@ -8,6 +8,48 @@ import {Navbar} from '../navbar/navbar';
import {ViewController} from '../nav/view-controller';
@Directive({
selector: 'ion-header'
})
export class Header {
private _h: number = 0;
constructor(viewCtr: ViewController, private _elementRef: ElementRef) {
viewCtr.setHeader(this);
}
setHeight(heightPixels: number) {
this._h = heightPixels;
this._elementRef.nativeElement.style.height = (heightPixels > 0 ? heightPixels + 'px' : '');
}
getHeight(): number {
return this._h;
}
}
@Directive({
selector: 'ion-footer'
})
export class Footer {
private _h: number = 0;
constructor(viewCtr: ViewController, private _elementRef: ElementRef) {
viewCtr.setFooter(this);
}
setHeight(heightPixels: number) {
this._h = heightPixels;
this._elementRef.nativeElement.style.height = (heightPixels > 0 ? heightPixels + 'px' : '');
}
getHeight(): number {
return this._h;
}
}
/**
* @private
*/
@@ -160,90 +202,8 @@ export class Toolbar extends ToolbarBase {
config: Config
) {
super(elementRef);
this._sbPadding = config.getBoolean('statusbarPadding', false);
viewCtrl && viewCtrl.setToolbarRef(elementRef);
this._sbPadding = config.getBoolean('statusbarPadding');
}
}
/**
* @name Title
* @description
* `ion-title` is a component that sets the title of the `Toolbar` or `Navbar`
*
* @usage
*
* ```html
* <ion-navbar *navbar>
* <ion-title>Tab 1</ion-title>
* </ion-navbar>
* ```
*
* Or to create a navbar with a toolbar as a subheader:
*
* ```html
* <ion-navbar *navbar>
* <ion-title>Tab 1</ion-title>
* </ion-navbar>
*
* <ion-toolbar>
* <ion-title>Subheader</ion-title>
* </ion-toolbar>
* ```
*
* @demo /docs/v2/demos/title/
*/
@Component({
selector: 'ion-title',
template:
'<div class="toolbar-title">' +
'<ng-content></ng-content>' +
'</div>',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class ToolbarTitle extends Ion {
constructor(
elementRef: ElementRef,
@Optional() toolbar: Toolbar,
@Optional() @Inject(forwardRef(() => Navbar)) navbar: Navbar
) {
super(elementRef);
toolbar && toolbar.setTitleCmp(this);
navbar && navbar.setTitleCmp(this);
}
/**
* @private
*/
getTitleText() {
return this.getNativeElement().textContent;
}
}
/**
* @private
*/
@Directive({
selector: 'ion-buttons,[menuToggle],ion-nav-items'
})
export class ToolbarItem {
inToolbar: boolean;
constructor(
elementRef: ElementRef,
@Optional() toolbar: Toolbar,
@Optional() @Inject(forwardRef(() => Navbar)) navbar: Navbar
) {
toolbar && toolbar.addItemRef(elementRef);
navbar && navbar.addItemRef(elementRef);
this.inToolbar = !!(toolbar || navbar);
}
@ContentChildren(Button)
set _buttons(buttons: any) {
if (this.inToolbar) {
Button.setRoles(buttons, 'bar-button');
}
}
}

View File

@@ -1,11 +1,13 @@
<ion-navbar *navbar>
<ion-title>Virtual Scroll{{webview}}</ion-title>
<ion-buttons end>
<button (click)="reload()">
Reload
</button>
</ion-buttons>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>Virtual Scroll{{webview}}</ion-title>
<ion-buttons end>
<button (click)="reload()">
Reload
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>

View File

@@ -31,14 +31,16 @@
}
</style>
<ion-navbar *navbar>
<ion-title>Virtual Scroll: Image Gallery</ion-title>
<ion-buttons end>
<button (click)="reload()">
Reload
</button>
</ion-buttons>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>Virtual Scroll: Image Gallery</ion-title>
<ion-buttons end>
<button (click)="reload()">
Reload
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>

View File

@@ -1,11 +1,13 @@
<ion-navbar *navbar>
<ion-title>Virtual Scroll{{webview}}</ion-title>
<ion-buttons end>
<button (click)="reload()">
Reload
</button>
</ion-buttons>
</ion-navbar>
<ion-header>
<ion-navbar>
<ion-title>Virtual Scroll{{webview}}</ion-title>
<ion-buttons end>
<button (click)="reload()">
Reload
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>