diff --git a/ionic/animations/animation.js b/ionic/animations/animation.js index fb52e09539..0649e81bc4 100644 --- a/ionic/animations/animation.js +++ b/ionic/animations/animation.js @@ -302,7 +302,7 @@ class Animate { this._duration = duration; - var easingName = easingConfig.name; + var easingName = easingConfig && easingConfig.name || 'linear'; var effects = [ convertProperties(fromEffect) ]; @@ -316,7 +316,7 @@ class Animate { effects.push( convertProperties(toEffect) ); this.player = ele.animate(effects, { - duration: duration, + duration: duration || 0, easing: easingName, playbackRate: playbackRate || 1 }); diff --git a/ionic/components/app/structure.scss b/ionic/components/app/structure.scss index fa236ab275..2c1bbd6abb 100644 --- a/ionic/components/app/structure.scss +++ b/ionic/components/app/structure.scss @@ -25,7 +25,6 @@ ion-app { } ion-nav { - // container of header.toolbar-container, footer.toolbar-container and .nav-item-container position: absolute; top: 0; right: 0; @@ -33,75 +32,49 @@ ion-nav { left: 0; width: 100%; height: 100%; - - display: flex; - flex-direction: column; overflow: hidden; } -.toolbar-container { - // container of many toolbars for each view in the ion-nav - position: relative; +ion-view { + position: absolute; + top: 0; + left: 0; width: 100%; + height: 100%; + + // by default this is display: none; + // and the transition animation will display it + display: none; + flex-direction: column; + + &.show-view { + display: flex; + } +} + +ion-toolbar { + display: flex; min-height: 4.4rem; order: $flex-order-toolbar-top; } -footer.toolbar-container { +.stage-off { + transform: translateX(9999px); +} + +ion-toolbar[footer] { order: $flex-order-toolbar-bottom; } -ion-toolbar { - // one view's toolbar, sibling to many view toolbars inside of .toolbar-container - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} - -.nav-item-container { - // container of many .nav-item's, each one containing one view - position: relative; - flex: 1; - order: $flex-order-view-content; -} - -.tab-item-container { - // container of each content for each tab component within a tabs component - position: relative; - flex: 1; - order: $flex-order-view-content; -} - -.nav-item { - // user created view, sibling to many .nav-item's, contained by .nav-item-container - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - - // by default .nav-item is hidden - // and the transition animation will display it - display: none; - - &.show-nav-item { - display: block; - } -} - ion-content { - // content within the user created view, contained by .nav-item - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; + position: relative; + display: block; + flex: 1; + order: $flex-order-view-content; } .scroll-content { - // extra div to allow overflow scrolling + // extra div added by ion-content directive to allow for overflow scrolling position: absolute; top: 0; right: 0; diff --git a/ionic/components/nav/nav-base.js b/ionic/components/nav/nav-base.js index 1cf6a155fb..cad8880ed1 100644 --- a/ionic/components/nav/nav-base.js +++ b/ionic/components/nav/nav-base.js @@ -265,15 +265,15 @@ export class NavBase { cleanup() { this.items.forEach((item) => { - - if (item && item.shouldDestroy) { - this.remove(item); - - util.dom.raf(() => { + if (item) { + if (item.shouldDestroy) { + this.remove(item); item.destroy(); - }); - } + } else if(item.state !== ACTIVE_STATE) { + item.cache(); + } + } }); } diff --git a/ionic/components/nav/nav-item.js b/ionic/components/nav/nav-item.js index 1a121de640..3a5d1dfaf5 100644 --- a/ionic/components/nav/nav-item.js +++ b/ionic/components/nav/nav-item.js @@ -3,6 +3,9 @@ import {bind} from 'angular2/di'; import * as util from 'ionic/util'; import {NavController} from './nav-controller'; +import {NavView} from './nav-view'; + +const SHOW_VIEW_CSS = 'show-view'; export class NavItem { @@ -15,7 +18,6 @@ export class NavItem { this.headerProtos = []; this.toolbarViews = []; this._titleEle = undefined; - this.disposals = []; // if it's possible to go back from this nav item this.enableBack = false; @@ -25,13 +27,19 @@ export class NavItem { // update if it's possible to go back from this nav item this.enableBack = !!this.nav.getPrevious(this); - if (!this.created) { - return this.create(); - } - return Promise.resolve(); + return this.create().then(() => { + return new Promise(resolve => { + this.viewEle && this.viewEle.classList.add(SHOW_VIEW_CSS); + resolve(); + }); + }); } create() { + if (this.created) { + return Promise.resolve(); + } + this.created = true; let resolve; @@ -43,30 +51,16 @@ export class NavItem { bind(NavItem).toValue(this) ]); - this.nav.loader.loadNextToExistingLocation(this.Component, this.nav.contentElementRef, injector).then((componentRef) => { + this.nav.loader.loadNextToExistingLocation(this.Component, this.nav.viewElementRef, injector).then((componentRef) => { // content this.component = componentRef; - this.contentEle = componentRef.location.domElement; - this.contentEle.classList.add('nav-item'); - this.contentEle.setAttribute('id', 'nav-item-' + this.id); + this.viewEle = componentRef.location.domElement; + this.viewEle.setAttribute('id', 'view-' + this.id); - if (componentRef && componentRef._dispose) { - this.disposals.push(componentRef._dispose); - } - - - // TODO: talk to misko about correct way to set context - let context = { - boundElementIndex: 0, - parentView: { - _view: componentRef.location.parentView._view.componentChildViews[0] - } - }; - - for (let i = 0; i < this.headerProtos.length; i++) { - this.createHeader(this.headerProtos[i], context, injector); + if (componentRef && componentRef.dispose) { + this._dispose = componentRef.dispose; } resolve(); @@ -75,44 +69,21 @@ export class NavItem { return promise; } - createHeader(toolbarProtoView, context, injector) { - let headerContainer = this.nav.headerContainerRef; - - if (!headerContainer) return; - - let atIndex = -1; - - let headerView = headerContainer.create(toolbarProtoView, atIndex, context, injector); - - if (headerView) { - this.toolbarViews.push(headerView); - - this.disposals.push(() => { - headerContainer.remove( headerContainer.indexOf(headerView) ); - }); - } + viewElement() { + return this.viewEle; } - addHeader(toolbarProtoView) { - this.headerProtos.push(toolbarProtoView); + contentElement() { + return this.viewEle.querySelector('ion-content'); } - getContent() { - return this.contentEle; + toolbarElements() { + return this.viewEle.querySelectorAll('ion-toolbar'); } - getToolbars() { - let elements = []; - for (let i = 0; i < this.toolbarViews.length; i++) { - var toolbarView = this.toolbarViews[i]; - elements.push(toolbarView._view.render._view.rootNodes[0]); - } - return elements; - } - - getTitle() { + titleElement() { if (this._titleEle === undefined) { - let toolbarElements = this.getToolbars(); + let toolbarElements = this.toolbarElements(); for (let i = 0; i < toolbarElements.length; i++) { var titleEle = toolbarElements[i].querySelector('ion-title'); if (titleEle) { @@ -125,9 +96,9 @@ export class NavItem { return this._titleEle; } - getBackButton() { + backButtonElement() { if (this._backBtn === undefined) { - let toolbarElements = this.getToolbars(); + let toolbarElements = this.toolbarElements(); for (let i = 0; i < toolbarElements.length; i++) { var backBtn = toolbarElements[i].querySelector('back-button'); if (backBtn) { @@ -140,10 +111,12 @@ export class NavItem { return this._backBtn; } + cache() { + this.viewEle.classList.remove(SHOW_VIEW_CSS); + } + destroy() { - for (let i = 0; i < this.disposals.length; i++) { - this.disposals[i](); - } + this._dispose && this._dispose(); // just to help prevent any possible memory leaks for (let name in this) { diff --git a/ionic/components/nav/nav.js b/ionic/components/nav/nav.js index 1d268736f8..2622d7deb8 100644 --- a/ionic/components/nav/nav.js +++ b/ionic/components/nav/nav.js @@ -17,15 +17,8 @@ import {ToolbarContainer} from '../toolbar/toolbar-container'; } }) @View({ - template: ` -
- -
- - `, - directives: [HeaderAnchor, ContentAnchor, ToolbarContainer] + template: ``, + directives: [ViewAnchor] }) export class Nav extends NavBase { constructor(elementRef: ElementRef, loader: DynamicComponentLoader, injector: Injector) { @@ -40,20 +33,10 @@ export class Nav extends NavBase { @Directive({ - selector: '[header-anchor]' + selector: '[view-anchor]' }) -class HeaderAnchor { - constructor(@Ancestor() nav: Nav, viewContainerRef: ViewContainerRef) { - nav.headerContainerRef = viewContainerRef; - } -} - - -@Directive({ - selector: '[content-anchor]' -}) -class ContentAnchor { +class ViewAnchor { constructor(@Ancestor() nav: Nav, elementRef: ElementRef) { - nav.contentElementRef = elementRef; + nav.viewElementRef = elementRef; } } diff --git a/ionic/components/nav/test/basic/pages/first-page.html b/ionic/components/nav/test/basic/pages/first-page.html index 157daf8873..2202e4452b 100644 --- a/ionic/components/nav/test/basic/pages/first-page.html +++ b/ionic/components/nav/test/basic/pages/first-page.html @@ -1,6 +1,5 @@ -First Page: {{ val }} - +First Page: {{ val }} diff --git a/ionic/components/nav/test/basic/pages/first-page.js b/ionic/components/nav/test/basic/pages/first-page.js index fa88288870..69079a6509 100644 --- a/ionic/components/nav/test/basic/pages/first-page.js +++ b/ionic/components/nav/test/basic/pages/first-page.js @@ -1,14 +1,14 @@ import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; import {View} from 'angular2/src/core/annotations_impl/view'; -import {NavController, HeaderTemplate, Toolbar, Content} from 'ionic/ionic'; +import {NavController, Toolbar, Content} from 'ionic/ionic'; import {SecondPage} from './second-page'; @Component({selector: 'ion-view'}) @View({ templateUrl: 'pages/first-page.html', - directives: [HeaderTemplate, Toolbar, Content] + directives: [Toolbar, Content] }) export class FirstPage { constructor( diff --git a/ionic/components/nav/test/basic/pages/second-page.html b/ionic/components/nav/test/basic/pages/second-page.html index d4c3780035..ba65c683aa 100644 --- a/ionic/components/nav/test/basic/pages/second-page.html +++ b/ionic/components/nav/test/basic/pages/second-page.html @@ -1,5 +1,5 @@ -Second Page +Second Page diff --git a/ionic/components/nav/test/basic/pages/second-page.js b/ionic/components/nav/test/basic/pages/second-page.js index 874ca69747..d7be2e1ef0 100644 --- a/ionic/components/nav/test/basic/pages/second-page.js +++ b/ionic/components/nav/test/basic/pages/second-page.js @@ -1,14 +1,14 @@ import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; import {View} from 'angular2/src/core/annotations_impl/view'; -import {NavController, NavParams, HeaderTemplate, Toolbar, Content} from 'ionic/ionic'; +import {NavController, NavParams, Toolbar, Content} from 'ionic/ionic'; import {ThirdPage} from './third-page'; -@Component() +@Component({selector: 'ion-view'}) @View({ templateUrl: 'pages/second-page.html', - directives: [HeaderTemplate, Toolbar, Content] + directives: [Toolbar, Content] }) export class SecondPage { constructor( diff --git a/ionic/components/nav/test/basic/pages/third-page.html b/ionic/components/nav/test/basic/pages/third-page.html index 68a9a7ff4b..c5e9badd5b 100644 --- a/ionic/components/nav/test/basic/pages/third-page.html +++ b/ionic/components/nav/test/basic/pages/third-page.html @@ -1,5 +1,5 @@ -Third Page +Third Page diff --git a/ionic/components/nav/test/basic/pages/third-page.js b/ionic/components/nav/test/basic/pages/third-page.js index 30f5c5e698..11b4db9900 100644 --- a/ionic/components/nav/test/basic/pages/third-page.js +++ b/ionic/components/nav/test/basic/pages/third-page.js @@ -1,13 +1,13 @@ import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; import {View} from 'angular2/src/core/annotations_impl/view'; -import {NavController, HeaderTemplate, Toolbar, Content} from 'ionic/ionic'; +import {NavController, Toolbar, Content} from 'ionic/ionic'; -@Component() +@Component({selector: 'ion-view'}) @View({ templateUrl: 'pages/third-page.html', - directives: [HeaderTemplate, Toolbar, Content] + directives: [Toolbar, Content] }) export class ThirdPage { constructor( diff --git a/ionic/components/toolbar/toolbar.js b/ionic/components/toolbar/toolbar.js index 7427ae4e25..d295f2c4a2 100644 --- a/ionic/components/toolbar/toolbar.js +++ b/ionic/components/toolbar/toolbar.js @@ -34,7 +34,6 @@ import {BackButton} from './back-button'; }) export class Toolbar { constructor(navItem: NavItem, elementRef: ElementRef) { - this.navItem = navItem; this.domElement = elementRef.domElement; this.config = Toolbar.config.invoke(this); @@ -95,18 +94,3 @@ export class Toolbar { } new IonicComponent(Toolbar, {}); - - -/* - Used to find and register headers in a view, and this directive's - content will be moved up to the common toolbar location, and created - using the same context as the view's content area. -*/ -@Directive({ - selector: 'template[header]' -}) -export class HeaderTemplate { - constructor(navItem: NavItem, protoViewRef: ProtoViewRef) { - navItem.addHeader(protoViewRef); - } -} diff --git a/ionic/components/toolbar/toolbar.scss b/ionic/components/toolbar/toolbar.scss index e586b69389..2892216bc1 100644 --- a/ionic/components/toolbar/toolbar.scss +++ b/ionic/components/toolbar/toolbar.scss @@ -2,7 +2,8 @@ // Toolbar // -------------------------------------------------- -$toolbar-background: #f7f7f8 !default; +$toolbar-background-color: #fff !default; + $toolbar-order: ( back-button: 10, title: 20, @@ -11,22 +12,11 @@ $toolbar-order: ( ); -.toolbar-container { - background: $toolbar-background; -} - ion-toolbar { + background: $toolbar-background-color; flex-direction: row; align-items: center; justify-content: space-between; - - // by default ion-toolbar is display:none and - // the transition animation will add the show class - display: none; - - &.show-toolbar { - display: flex; - } } .toolbar-inner { diff --git a/ionic/transitions/ios-transition.js b/ionic/transitions/ios-transition.js index 211517f313..453f1b57e4 100644 --- a/ionic/transitions/ios-transition.js +++ b/ionic/transitions/ios-transition.js @@ -1,6 +1,6 @@ import {Animation} from '../animations/animation'; -import {rafPromise} from '../util/dom' -import {Transition} from './transition' +import {rafPromise} from '../util/dom'; +import {Transition} from './transition'; const DURATION = 500; @@ -32,24 +32,24 @@ class IOSTransition extends Animation { let leavingItem = navCtrl.getStagedLeavingItem(); // create animation for the entering content - let enteringContent = new Animation(enteringItem.getContent()); + let enteringContent = new Animation(enteringItem.contentElement()); // create animation for the entering toolbars - let enteringToolbars = new Animation(enteringItem.getToolbars()); + let enteringToolbars = new Animation(enteringItem.toolbarElements()); // create animation for the entering title element - let enteringTitle = new Animation(enteringItem.getTitle()); + let enteringTitle = new Animation(enteringItem.titleElement()); // create animation for the leaving content // leavingItem could be null, but the animation instance knows to do nothing - let leavingContent = new Animation(leavingItem && leavingItem.getContent()); + let leavingContent = new Animation(leavingItem && leavingItem.contentElement()); // create animation for the leaving content // leavingItem could be null, but the animation instance knows to do nothing - let leavingToolbars = new Animation(leavingItem && leavingItem.getToolbars()); + let leavingToolbars = new Animation(leavingItem && leavingItem.toolbarElements()); // create animation for the entering title element - let leavingTitle = new Animation(leavingItem && leavingItem.getTitle()); + let leavingTitle = new Animation(leavingItem && leavingItem.titleElement()); // entering item moves to center // before starting, set enteringItem to display: block @@ -68,7 +68,7 @@ class IOSTransition extends Animation { // if the back button should show, then fade it in if (enteringItem.enableBack) { - let enteringBackButton = new Animation(enteringItem.getBackButton()) + let enteringBackButton = new Animation(enteringItem.backButtonElement()) enteringBackButton.from(OPACITY, 0).to(OPACITY, 1); this.addChild(enteringBackButton); } @@ -88,7 +88,7 @@ class IOSTransition extends Animation { .from(OPACITY, 1); if (leavingItem) { - let leavingBackButton = new Animation(leavingItem.getBackButton()); + let leavingBackButton = new Animation(leavingItem.backButtonElement()); leavingBackButton.from(OPACITY, 1).to(OPACITY, 0); this.addChild(leavingBackButton); } diff --git a/ionic/transitions/none-transition.js b/ionic/transitions/none-transition.js index 35a0a2df67..1e95f296a9 100644 --- a/ionic/transitions/none-transition.js +++ b/ionic/transitions/none-transition.js @@ -1,53 +1,19 @@ -import {Transition} from './transition' +import {Animation} from '../animations/animation'; +import {Transition} from './transition'; +import {rafPromise} from '../util/dom'; -const SHOW_TOOLBAR_CSS = 'show-toolbar'; -const SHOW_NAV_ITEM_CSS = 'show-nav-item'; - - -class NoneTransition { +class NoneTransition extends Animation { constructor(navCtrl) { - // get the entering and leaving items - let enteringItem = navCtrl.getStagedEnteringItem(); - let leavingItem = navCtrl.getStagedLeavingItem(); - - // show entering contet - let enteringContent = enteringItem.getContent(); - enteringContent.classList.add(SHOW_NAV_ITEM_CSS); - - // show entering headers - let enteringToolbars = enteringItem.getToolbars(); - for (let i = 0; i < enteringToolbars.length; i++) { - enteringToolbars[i].classList.add(SHOW_TOOLBAR_CSS); - } - - // hide the leaving item - if (leavingItem) { - let leavingContent = leavingItem.getContent(); - if (leavingContent) { - leavingContent.classList.remove(SHOW_NAV_ITEM_CSS); - } - - let leavingToolbars = leavingItem.getToolbars(); - for (let i = 0; i < leavingToolbars.length; i++) { - leavingToolbars[i].classList.remove(SHOW_TOOLBAR_CSS); - } - } + super(); } stage() { // immediately resolve - return Promise.resolve(); + return rafPromise(); } - play() { - // immediately resolve - return Promise.resolve(); - } - - dispose(){} - } Transition.register('none', NoneTransition);