diff --git a/demos/navigation/index.ts b/demos/navigation/index.ts index fa304341b3..3a2075a7c7 100644 --- a/demos/navigation/index.ts +++ b/demos/navigation/index.ts @@ -12,7 +12,7 @@ import {NavParams, NavController} from 'ionic/ionic'; '

{{title}}

' + '

' + '

' + - '

' + + '

' + '' }) class FirstPage { @@ -29,11 +29,11 @@ class FirstPage { } } - setViews() { + setPages() { let items = [ ThirdPage ]; - this.nav.setViews(items); + this.nav.setPages(items); } push() { @@ -52,7 +52,7 @@ class FirstPage {

-

+

` }) @@ -66,12 +66,12 @@ class SecondPage { console.log('Second page params:', params); } - setViews() { + setPages() { let items = [ FirstPage, ThirdPage ]; - this.nav.setViews(items); + this.nav.setPages(items); } pop() { diff --git a/ionic/components/action-sheet/action-sheet.ts b/ionic/components/action-sheet/action-sheet.ts index 0e0844d5c1..9151ce7c61 100644 --- a/ionic/components/action-sheet/action-sheet.ts +++ b/ionic/components/action-sheet/action-sheet.ts @@ -77,7 +77,6 @@ import {extend} from '../../util/util'; '' + '', host: { - '[style.zIndex]': '_zIndex', 'role': 'dialog' }, directives: [NgFor, NgIf, Icon] diff --git a/ionic/components/nav/nav-controller.ts b/ionic/components/nav/nav-controller.ts index e0b0363dd2..f408d0ddb4 100644 --- a/ionic/components/nav/nav-controller.ts +++ b/ionic/components/nav/nav-controller.ts @@ -125,7 +125,7 @@ export class NavController extends Ion { this._loader = loader; this._viewManager = viewManager; this._zone = zone; - this.renderer = renderer; + this._renderer = renderer; this._views = []; this._trnsTime = 0; @@ -165,8 +165,7 @@ export class NavController extends Ion { */ push(componentType, params = {}, opts = {}, callback) { if (!componentType) { - console.debug('invalid componentType to push'); - return Promise.reject(); + return Promise.reject('invalid componentType to push'); } if (typeof componentType !== 'function') { @@ -211,10 +210,6 @@ export class NavController extends Ion { // add the view to the stack this._add(enteringView); - if (opts.preCleanup !== false) { - this._cleanup(enteringView); - } - if (this.router) { // notify router of the state change this.router.stateChange('push', enteringView, params); @@ -292,23 +287,31 @@ export class NavController extends Ion { return Promise.resolve(); } - let resolve; + // ensure the entering view is shown + this._renderView(viewCtrl, true); + + let resolve = null; let promise = new Promise(res => { resolve = res; }); opts.direction = opts.direction || 'back'; + let leavingView = this.getActive() || new ViewController(); + // get the views to auto remove without having to do a transiton for each // the last view (the currently active one) will do a normal transition out if (this._views.length > 1) { let autoRemoveItems = this._views.slice(targetIndex, this._views.length); + let popView; for (let i = 0; i < autoRemoveItems.length; i++) { - autoRemoveItems[i].shouldDestroy = true; - autoRemoveItems[i].shouldCache = false; - autoRemoveItems[i].willUnload(); + popView = autoRemoveItems[i]; + popView.shouldDestroy = true; + popView.shouldCache = false; + popView.willUnload(); + + // only the leaving view should be shown, all others hide + this._renderView(popView, (popView === leavingView)); } } - let leavingView = this.getPrevious(viewCtrl); - if (this.router) { this.router.stateChange('pop', viewCtrl); } @@ -328,11 +331,11 @@ export class NavController extends Ion { /** * Inserts a view into the nav stack at the specified index. - * @param {Component} The name of the component you want to insert into the nav stack * @param {Index} The index where you want to insert the view + * @param {Component} The name of the component you want to insert into the nav stack * @returns {Promise} Returns a promise when the view has been inserted into the navigation stack */ - insert(componentType, index, params = {}, opts = {}) { + insert(index, componentType, params = {}, opts = {}) { if (!componentType || index < 0) { return Promise.reject(); } @@ -373,20 +376,29 @@ export class NavController extends Ion { return Promise.resolve(); } + /** + * @private + */ + setViews(components, opts = {}) { + console.warn('setViews() deprecated, use setPages() instead'); + this.setPages(components, opts); + } + /** * Set the view stack to reflect the given component classes. * @param {TODO} components TODO * @param {TODO} [opts={}] TODO * @returns {Promise} TODO */ - setViews(components, opts = {}) { + setPages(components, opts = {}) { if (!components || !components.length) { return Promise.resolve(); } + let leavingView = this.getActive() || new ViewController(); + // if animate has not been set then default to false opts.animate = opts.animate || false; - opts.preCleanup = false; // ensure leaving views are not cached, and should be destroyed opts.cacheLeavingView = false; @@ -395,10 +407,17 @@ export class NavController extends Ion { // the last view (the currently active one) will do a normal transition out if (this._views.length > 1) { let autoRemoveItems = this._views.slice(0, this._views.length - 1); + let popView; for (let i = 0; i < autoRemoveItems.length; i++) { - autoRemoveItems[i].shouldDestroy = true; - autoRemoveItems[i].shouldCache = false; - autoRemoveItems[i].willUnload(); + popView = autoRemoveItems[i]; + popView.shouldDestroy = true; + popView.shouldCache = false; + popView.willUnload(); + + if (opts.animate) { + // only the leaving view should be shown, all others hide + this._renderView(popView, (popView === leavingView)); + } } } @@ -406,15 +425,14 @@ export class NavController extends Ion { let componentType = null; let viewCtrl = null; - // create the ViewControllers that go before the new active ViewController in the stack - // but the previous views won't should render yet + // create the ViewControllers that go before the new active ViewController + // in the stack, but the previous views shouldn't render yet if (components.length > 1) { let newBeforeItems = components.slice(0, components.length - 1); for (let j = 0; j < newBeforeItems.length; j++) { componentObj = newBeforeItems[j]; if (componentObj) { - // could be an object with a componentType property, or it is a componentType componentType = componentObj.componentType || componentObj; @@ -446,7 +464,7 @@ export class NavController extends Ion { * @returns {Promise} Returns a promise when done */ setRoot(componentType, params = {}, opts = {}) { - return this.setViews([{ + return this.setPages([{ componentType, params }], opts); @@ -462,6 +480,7 @@ export class NavController extends Ion { * @returns {any} TODO */ _transition(enteringView, leavingView, opts, done) { + console.debug('_transition', enteringView, leavingView, opts); let self = this; if (enteringView === leavingView) { @@ -487,9 +506,8 @@ export class NavController extends Ion { return done(enteringView); } - self._setZIndex(enteringView.instance, leavingView.instance, opts.direction); - self._zone.runOutsideAngular(() => { + self._setZIndex(enteringView, leavingView, opts.direction); enteringView.shouldDestroy = false; enteringView.shouldCache = false; @@ -638,7 +656,7 @@ export class NavController extends Ion { if (this._views.length === 1) { this._zone.runOutsideAngular(() => { rafFrames(38, () => { - this.renderer.setElementClass(this.elementRef, 'has-views', true); + this._renderer.setElementClass(this.elementRef, 'has-views', true); }); }); } @@ -647,17 +665,42 @@ export class NavController extends Ion { }); } - _setZIndex(enteringInstance, leavingInstance, direction) { - if (!leavingInstance) { - enteringInstance._zIndex = 10; + _setZIndex(enteringView, leavingView, direction) { + let enteringPageRef = enteringView && enteringView.pageRef(); + if (enteringPageRef) { + if (!leavingView || !leavingView.isLoaded()) { + enteringView.zIndex = 10; - } else if (direction === 'back') { - // moving back - enteringInstance._zIndex = leavingInstance._zIndex - 1; + } else if (direction === 'back') { + // moving back + enteringView.zIndex = leavingView.zIndex - 1; - } else { - // moving forward - enteringInstance._zIndex = leavingInstance._zIndex + 1; + } else { + // moving forward + enteringView.zIndex = leavingView.zIndex + 1; + } + + if (enteringView.zIndex !== enteringView._zIndex) { + this._renderer.setElementStyle(enteringPageRef, 'z-index', enteringView.zIndex); + enteringView._zIndex = enteringView.zIndex; + } + } + } + + _renderView(viewCtrl, shouldShow) { + // using hidden element attribute to display:none and not render views + // renderAttr of '' means the hidden attribute will be added + // renderAttr of null means the hidden attribute will be removed + // doing checks to make sure we only make an update to the element when needed + if (shouldShow && viewCtrl._hdnAttr === '' || + !shouldShow && viewCtrl._hdnAttr !== '') { + viewCtrl._hdnAttr = (shouldShow ? null : ''); + this._renderer.setElementAttribute(viewCtrl.pageRef(), 'hidden', viewCtrl._hdnAttr); + + let navbarRef = viewCtrl.navbarRef(); + if (navbarRef) { + this._renderer.setElementAttribute(navbarRef, 'hidden', viewCtrl._hdnAttr); + } } } @@ -899,9 +942,8 @@ export class NavController extends Ion { destroys.push(view); } else { - let isActiveView = (view === activeView); - let isPreviousView = (view === previousView); - view.domCache && view.domCache(isActiveView, isPreviousView); + let shouldShow = (view === activeView) || (view === previousView); + this._renderView(view, shouldShow); } } }); diff --git a/ionic/components/nav/test/basic/index.ts b/ionic/components/nav/test/basic/index.ts index 61c3a58042..6aaee5524e 100644 --- a/ionic/components/nav/test/basic/index.ts +++ b/ionic/components/nav/test/basic/index.ts @@ -36,7 +36,7 @@ class MyCmpTest{} - + @@ -63,12 +63,12 @@ class FirstPage { } } - setViews() { + setPages() { let items = [ PrimaryHeaderPage ]; - this.nav.setViews(items); + this.nav.setPages(items); } setRoot(PrimaryHeaderPage) { @@ -99,7 +99,7 @@ class FirstPage {

-

+

` }) @@ -112,13 +112,13 @@ class FullPage { this.params = params; } - setViews() { + setPages() { let items = [ FirstPage, PrimaryHeaderPage ]; - this.nav.setViews(items); + this.nav.setPages(items); } pushPrimaryHeaderPage() { @@ -168,7 +168,7 @@ class PrimaryHeaderPage { } insert() { - this.nav.insert(FirstPage, 2); + this.nav.insert(2, FirstPage); } removeSecond() { diff --git a/ionic/components/nav/test/insert-views/index.ts b/ionic/components/nav/test/insert-views/index.ts index 4b057a84b8..eabc724299 100644 --- a/ionic/components/nav/test/insert-views/index.ts +++ b/ionic/components/nav/test/insert-views/index.ts @@ -39,7 +39,7 @@ class SecondPage { this.nav = nav; } insertPage(){ - this.nav.insert(InsertPage, 1) + this.nav.insert(1, InsertPage) } } diff --git a/ionic/components/nav/test/nav-controller.spec.ts b/ionic/components/nav/test/nav-controller.spec.ts index 9e69fad948..7a7b99a327 100644 --- a/ionic/components/nav/test/nav-controller.spec.ts +++ b/ionic/components/nav/test/nav-controller.spec.ts @@ -36,12 +36,16 @@ export function run() { } function mockCanGoBackFn() { - return true; + return true; } // beforeEach(inject([Compiler], compiler => { beforeEach(() => { nav = new NavController(null, null, new Config(), null, null, null, null, null); + nav._renderer = { + setElementAttribute: function(){}, + setElementStyle: function(){} + }; }); it('should exist', () => { @@ -125,12 +129,12 @@ export function run() { }); }); - describe("setViews", () => { + describe("setPages", () => { it('should return a resolved Promise if components is falsy', done => { let s = jasmine.createSpy('success'); let f = jasmine.createSpy('fail'); - let promise = nav.setViews(); + let promise = nav.setPages(); promise.then(s, f).then(() => { expect(s).toHaveBeenCalled(); @@ -147,7 +151,7 @@ export function run() { let arr = [FirstPage, SecondPage, ThirdPage]; nav._transition = mockTransitionFn; - nav.setViews(arr); + nav.setPages(arr); //_views[0] will be transitioned out of expect(nav._views[1].componentType).toBe(FirstPage); @@ -161,22 +165,24 @@ export function run() { it('insert page at the specified index', () => { nav._views = [{}, {}, {}]; expect(nav._views[2].componentType).toBeUndefined(); - nav.insert(FirstPage, 2); + nav.insert(2, FirstPage); expect(nav._views[2].componentType).toBe(FirstPage); }); it('push page if index >= _views.length', () => { nav._views = [{}, {}, {}]; spyOn(nav, 'push').and.callThrough(); - nav.insert(FirstPage, 2); + nav.insert(2, FirstPage); expect(nav.push).not.toHaveBeenCalled(); nav._transition = mockTransitionFn; - nav.insert(FirstPage, 4); + nav.insert(4, FirstPage); expect(nav._views[4].componentType).toBe(FirstPage); expect(nav.push).toHaveBeenCalled(); - nav.insert(FirstPage, 10); + nav.setTransitioning(false); + + nav.insert(10, FirstPage); expect(nav._views[5].componentType).toBe(FirstPage); expect(nav.push.calls.count()).toBe(2); }); @@ -270,23 +276,30 @@ export function run() { describe("_setZIndex", () => { it('should set zIndex 10 on first entering view', () => { - let enteringInstance = {}; - nav._setZIndex(enteringInstance, null, 'forward'); - expect(enteringInstance._zIndex).toEqual(10); + let enteringView = new ViewController(); + enteringView.setPageRef({}); + nav._setZIndex(enteringView, null, 'forward'); + expect(enteringView.zIndex).toEqual(10); }); it('should set zIndex 1 on second entering view', () => { - let leavingInstance = { _zIndex: 0 }; - let enteringInstance = {}; - nav._setZIndex(enteringInstance, leavingInstance, 'forward'); - expect(enteringInstance._zIndex).toEqual(1); + let leavingView = new ViewController(); + leavingView.zIndex = 0; + leavingView._loaded = true; + let enteringView = new ViewController(); + enteringView.setPageRef({}); + nav._setZIndex(enteringView, leavingView, 'forward'); + expect(enteringView.zIndex).toEqual(1); }); it('should set zIndex 0 on entering view going back', () => { - let leavingInstance = { _zIndex: 1 }; - let enteringInstance = {}; - nav._setZIndex(enteringInstance, leavingInstance, 'back'); - expect(enteringInstance._zIndex).toEqual(0); + let leavingView = new ViewController(); + leavingView.zIndex = 1; + leavingView._loaded = true; + let enteringView = new ViewController(); + enteringView.setPageRef({}); + nav._setZIndex(enteringView, leavingView, 'back'); + expect(enteringView.zIndex).toEqual(0); }); }); diff --git a/ionic/components/nav/view-controller.ts b/ionic/components/nav/view-controller.ts index 5af1089176..008d1579eb 100644 --- a/ionic/components/nav/view-controller.ts +++ b/ionic/components/nav/view-controller.ts @@ -209,8 +209,4 @@ export class ViewController { this.instance.onPageDidUnload && this.instance.onPageDidUnload(); } - domCache(isActiveView, isPreviousView) { - this.instance._hidden = (!isActiveView && !isPreviousView); - } - } diff --git a/ionic/components/popup/popup.ts b/ionic/components/popup/popup.ts index 767fe652fa..b4bf69bc0e 100644 --- a/ionic/components/popup/popup.ts +++ b/ionic/components/popup/popup.ts @@ -287,7 +287,6 @@ const OVERLAY_TYPE = 'popup'; '' + '', host: { - '[style.zIndex]': '_zIndex', 'role': 'dialog' }, directives: [FORM_DIRECTIVES, NgClass, NgIf, NgFor, Button] diff --git a/ionic/config/decorators.ts b/ionic/config/decorators.ts index c72011c99a..c8752c7c4a 100644 --- a/ionic/config/decorators.ts +++ b/ionic/config/decorators.ts @@ -70,7 +70,6 @@ export function Page(config={}) { config.host = config.host || {}; config.host['[hidden]'] = '_hidden'; config.host['[class.tab-subpage]'] = '_tabSubPage'; - config.host['[style.zIndex]'] = '_zIndex'; var annotations = Reflect.getMetadata('annotations', cls) || []; annotations.push(new Component(config)); Reflect.defineMetadata('annotations', annotations, cls);