| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035 |
- var __extends = (this && this.__extends) || (function () {
- var extendStatics = Object.setPrototypeOf ||
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
- function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
- return function (d, b) {
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- };
- })();
- import { EventEmitter, Input, ReflectiveInjector } from '@angular/core';
- import { DIRECTION_BACK, DIRECTION_FORWARD, INIT_ZINDEX, STATE_ATTACHED, STATE_DESTROYED, STATE_INITIALIZED, STATE_NEW, convertToViews, } from './nav-util';
- import { setZIndex } from './nav-util';
- import { isBlank, isNumber, isPresent, isTrueProperty } from '../util/util';
- import { ViewController, isViewController } from './view-controller';
- import { Ion } from '../components/ion';
- import { NavController } from './nav-controller';
- import { NavParams } from './nav-params';
- import { SwipeBackGesture } from './swipe-back';
- /**
- * @hidden
- * This class is for internal use only. It is not exported publicly.
- */
- var NavControllerBase = (function (_super) {
- __extends(NavControllerBase, _super);
- function NavControllerBase(parent, _app, config, plt, elementRef, _zone, renderer, _cfr, _gestureCtrl, _trnsCtrl, _linker, _domCtrl, _errHandler) {
- var _this = _super.call(this, config, elementRef, renderer) || this;
- _this.parent = parent;
- _this._app = _app;
- _this.config = config;
- _this.plt = plt;
- _this._zone = _zone;
- _this._cfr = _cfr;
- _this._gestureCtrl = _gestureCtrl;
- _this._trnsCtrl = _trnsCtrl;
- _this._linker = _linker;
- _this._domCtrl = _domCtrl;
- _this._errHandler = _errHandler;
- _this._ids = -1;
- _this._init = false;
- _this._queue = [];
- _this._trnsId = null;
- _this._trnsTm = false;
- _this._views = [];
- _this._zIndexOffset = 0;
- _this.viewDidLoad = new EventEmitter();
- _this.viewWillEnter = new EventEmitter();
- _this.viewDidEnter = new EventEmitter();
- _this.viewWillLeave = new EventEmitter();
- _this.viewDidLeave = new EventEmitter();
- _this.viewWillUnload = new EventEmitter();
- _this._sbEnabled = config.getBoolean('swipeBackEnabled');
- _this._children = [];
- _this.id = 'n' + (++ctrlIds);
- _this._destroyed = false;
- return _this;
- }
- Object.defineProperty(NavControllerBase.prototype, "swipeBackEnabled", {
- get: function () {
- return this._sbEnabled;
- },
- set: function (val) {
- this._sbEnabled = isTrueProperty(val);
- this._swipeBackCheck();
- },
- enumerable: true,
- configurable: true
- });
- NavControllerBase.prototype.push = function (page, params, opts, done) {
- return this._queueTrns({
- insertStart: -1,
- insertViews: [{ page: page, params: params }],
- opts: opts,
- }, done);
- };
- NavControllerBase.prototype.insert = function (insertIndex, page, params, opts, done) {
- return this._queueTrns({
- insertStart: insertIndex,
- insertViews: [{ page: page, params: params }],
- opts: opts,
- }, done);
- };
- NavControllerBase.prototype.insertPages = function (insertIndex, insertPages, opts, done) {
- return this._queueTrns({
- insertStart: insertIndex,
- insertViews: insertPages,
- opts: opts,
- }, done);
- };
- NavControllerBase.prototype.pop = function (opts, done) {
- return this._queueTrns({
- removeStart: -1,
- removeCount: 1,
- opts: opts,
- }, done);
- };
- NavControllerBase.prototype.popTo = function (indexOrViewCtrl, opts, done) {
- var config = {
- removeStart: -1,
- removeCount: -1,
- opts: opts
- };
- if (isViewController(indexOrViewCtrl)) {
- config.removeView = indexOrViewCtrl;
- config.removeStart = 1;
- }
- else if (isNumber(indexOrViewCtrl)) {
- config.removeStart = indexOrViewCtrl + 1;
- }
- return this._queueTrns(config, done);
- };
- NavControllerBase.prototype.popToRoot = function (opts, done) {
- return this._queueTrns({
- removeStart: 1,
- removeCount: -1,
- opts: opts,
- }, done);
- };
- NavControllerBase.prototype.popAll = function () {
- var promises = [];
- for (var i = this._views.length - 1; i >= 0; i--) {
- promises.push(this.pop(null));
- }
- return Promise.all(promises);
- };
- NavControllerBase.prototype.remove = function (startIndex, removeCount, opts, done) {
- if (removeCount === void 0) { removeCount = 1; }
- return this._queueTrns({
- removeStart: startIndex,
- removeCount: removeCount,
- opts: opts,
- }, done);
- };
- NavControllerBase.prototype.removeView = function (viewController, opts, done) {
- return this._queueTrns({
- removeView: viewController,
- removeStart: 0,
- removeCount: 1,
- opts: opts,
- }, done);
- };
- NavControllerBase.prototype.setRoot = function (pageOrViewCtrl, params, opts, done) {
- return this.setPages([{ page: pageOrViewCtrl, params: params }], opts, done);
- };
- NavControllerBase.prototype.setPages = function (viewControllers, opts, done) {
- if (isBlank(opts)) {
- opts = {};
- }
- // if animation wasn't set to true then default it to NOT animate
- if (opts.animate !== true) {
- opts.animate = false;
- }
- return this._queueTrns({
- insertStart: 0,
- insertViews: viewControllers,
- removeStart: 0,
- removeCount: -1,
- opts: opts
- }, done);
- };
- // _queueTrns() adds a navigation stack change to the queue and schedules it to run:
- // 1. _nextTrns(): consumes the next transition in the queue
- // 2. _viewInit(): initializes enteringView if required
- // 3. _viewTest(): ensures canLeave/canEnter returns true, so the operation can continue
- // 4. _postViewInit(): add/remove the views from the navigation stack
- // 5. _transitionInit(): initializes the visual transition if required and schedules it to run
- // 6. _viewAttachToDOM(): attaches the enteringView to the DOM
- // 7. _transitionStart(): called once the transition actually starts, it initializes the Animation underneath.
- // 8. _transitionFinish(): called once the transition finishes
- // 9. _cleanup(): syncs the navigation internal state with the DOM. For example it removes the pages from the DOM or hides/show them.
- NavControllerBase.prototype._queueTrns = function (ti, done) {
- var promise = new Promise(function (resolve, reject) {
- ti.resolve = resolve;
- ti.reject = reject;
- });
- ti.done = done;
- // Normalize empty
- if (ti.insertViews && ti.insertViews.length === 0) {
- ti.insertViews = undefined;
- }
- // Enqueue transition instruction
- this._queue.push(ti);
- // if there isn't a transition already happening
- // then this will kick off this transition
- this._nextTrns();
- return promise;
- };
- NavControllerBase.prototype._success = function (result, ti) {
- if (this._queue === null) {
- this._fireError('nav controller was destroyed', ti);
- return;
- }
- this._init = true;
- this._trnsId = null;
- // ensure we're not transitioning here
- this.setTransitioning(false);
- this._swipeBackCheck();
- // let's see if there's another to kick off
- this._nextTrns();
- if (ti.done) {
- ti.done(result.hasCompleted, result.requiresTransition, result.enteringName, result.leavingName, result.direction);
- }
- ti.resolve(result.hasCompleted);
- };
- NavControllerBase.prototype._failed = function (rejectReason, ti) {
- if (this._queue === null) {
- this._fireError('nav controller was destroyed', ti);
- return;
- }
- this._trnsId = null;
- this._queue.length = 0;
- // let's see if there's another to kick off
- this.setTransitioning(false);
- this._swipeBackCheck();
- this._nextTrns();
- this._fireError(rejectReason, ti);
- };
- NavControllerBase.prototype._fireError = function (rejectReason, ti) {
- if (ti.done) {
- ti.done(false, false, rejectReason);
- }
- if (ti.reject && !this._destroyed) {
- ti.reject(rejectReason);
- }
- else {
- ti.resolve(false);
- }
- };
- NavControllerBase.prototype._nextTrns = function () {
- var _this = this;
- // this is the framework's bread 'n butta function
- // only one transition is allowed at any given time
- if (this.isTransitioning()) {
- return false;
- }
- // there is no transition happening right now
- // get the next instruction
- var ti = this._queue.shift();
- if (!ti) {
- return false;
- }
- // set that this nav is actively transitioning
- var enteringView;
- var leavingView;
- this._startTI(ti)
- .then(function () { return _this._loadLazyLoading(ti); })
- .then(function () {
- leavingView = _this.getActive();
- enteringView = _this._getEnteringView(ti, leavingView);
- if (!leavingView && !enteringView) {
- throw 'no views in the stack to be removed';
- }
- if (enteringView && enteringView._state === STATE_NEW) {
- _this._viewInit(enteringView);
- }
- // Needs transition?
- ti.requiresTransition = (ti.enteringRequiresTransition || ti.leavingRequiresTransition) && enteringView !== leavingView;
- })
- .then(function () { return _this._viewTest(enteringView, leavingView, ti); })
- .then(function () { return _this._postViewInit(enteringView, leavingView, ti); })
- .then(function () { return _this._transition(enteringView, leavingView, ti); })
- .then(function (result) { return _this._success(result, ti); })
- .catch(function (rejectReason) { return _this._failed(rejectReason, ti); });
- return true;
- };
- NavControllerBase.prototype._startTI = function (ti) {
- var viewsLength = this._views.length;
- if (isPresent(ti.removeView)) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- var index = this.indexOf(ti.removeView);
- if (index < 0) {
- return Promise.reject('removeView was not found');
- }
- ti.removeStart += index;
- }
- if (isPresent(ti.removeStart)) {
- if (ti.removeStart < 0) {
- ti.removeStart = (viewsLength - 1);
- }
- if (ti.removeCount < 0) {
- ti.removeCount = (viewsLength - ti.removeStart);
- }
- ti.leavingRequiresTransition = (ti.removeCount > 0) && ((ti.removeStart + ti.removeCount) === viewsLength);
- }
- if (ti.insertViews) {
- // allow -1 to be passed in to auto push it on the end
- // and clean up the index if it's larger then the size of the stack
- if (ti.insertStart < 0 || ti.insertStart > viewsLength) {
- ti.insertStart = viewsLength;
- }
- ti.enteringRequiresTransition = (ti.insertStart === viewsLength);
- }
- this.setTransitioning(true);
- return Promise.resolve();
- };
- NavControllerBase.prototype._loadLazyLoading = function (ti) {
- var _this = this;
- var insertViews = ti.insertViews;
- if (insertViews) {
- (void 0) /* assert */;
- return convertToViews(this._linker, insertViews).then(function (viewControllers) {
- (void 0) /* assert */;
- viewControllers = viewControllers.filter(function (v) { return v !== null; });
- if (viewControllers.length === 0) {
- throw 'invalid views to insert';
- }
- // Check all the inserted view are correct
- for (var i = 0; i < viewControllers.length; i++) {
- var view = viewControllers[i];
- var nav = view._nav;
- if (nav && nav !== _this) {
- throw 'inserted view was already inserted';
- }
- if (view._state === STATE_DESTROYED) {
- throw 'inserted view was already destroyed';
- }
- }
- ti.insertViews = viewControllers;
- });
- }
- return Promise.resolve();
- };
- NavControllerBase.prototype._getEnteringView = function (ti, leavingView) {
- var insertViews = ti.insertViews;
- if (insertViews) {
- // grab the very last view of the views to be inserted
- // and initialize it as the new entering view
- return insertViews[insertViews.length - 1];
- }
- var removeStart = ti.removeStart;
- if (isPresent(removeStart)) {
- var views = this._views;
- var removeEnd = removeStart + ti.removeCount;
- var i;
- var view;
- for (i = views.length - 1; i >= 0; i--) {
- view = views[i];
- if ((i < removeStart || i >= removeEnd) && view !== leavingView) {
- return view;
- }
- }
- }
- return null;
- };
- NavControllerBase.prototype._postViewInit = function (enteringView, leavingView, ti) {
- var _this = this;
- (void 0) /* assert */;
- (void 0) /* assert */;
- (void 0) /* assert */;
- var opts = ti.opts || {};
- var insertViews = ti.insertViews;
- var removeStart = ti.removeStart;
- var removeCount = ti.removeCount;
- var view;
- var i;
- var destroyQueue;
- // there are views to remove
- if (isPresent(removeStart)) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- destroyQueue = [];
- for (i = 0; i < removeCount; i++) {
- view = this._views[i + removeStart];
- if (view && view !== enteringView && view !== leavingView) {
- destroyQueue.push(view);
- }
- }
- // default the direction to "back"
- opts.direction = opts.direction || DIRECTION_BACK;
- }
- var finalBalance = this._views.length + (insertViews ? insertViews.length : 0) - (removeCount ? removeCount : 0);
- (void 0) /* assert */;
- if (finalBalance === 0 && !this._isPortal) {
- console.warn("You can't remove all the pages in the navigation stack. nav.pop() is probably called too many times.", this, this.getNativeElement());
- throw 'navigation stack needs at least one root page';
- }
- // At this point the transition can not be rejected, any throw should be an error
- // there are views to insert
- if (insertViews) {
- // manually set the new view's id if an id was passed in the options
- if (isPresent(opts.id)) {
- enteringView.id = opts.id;
- }
- // add the views to the
- for (i = 0; i < insertViews.length; i++) {
- view = insertViews[i];
- this._insertViewAt(view, ti.insertStart + i);
- }
- if (ti.enteringRequiresTransition) {
- // default to forward if not already set
- opts.direction = opts.direction || DIRECTION_FORWARD;
- }
- }
- // if the views to be removed are in the beginning or middle
- // and there is not a view that needs to visually transition out
- // then just destroy them and don't transition anything
- // batch all of lifecycles together
- // let's make sure, callbacks are zoned
- if (destroyQueue && destroyQueue.length > 0) {
- this._zone.run(function () {
- for (i = 0; i < destroyQueue.length; i++) {
- view = destroyQueue[i];
- _this._willLeave(view, true);
- _this._didLeave(view);
- _this._willUnload(view);
- }
- });
- // once all lifecycle events has been delivered, we can safely detroy the views
- for (i = 0; i < destroyQueue.length; i++) {
- this._destroyView(destroyQueue[i]);
- }
- }
- // set which animation it should use if it wasn't set yet
- if (ti.requiresTransition && !opts.animation) {
- if (isPresent(ti.removeStart)) {
- opts.animation = (leavingView || enteringView).getTransitionName(opts.direction);
- }
- else {
- opts.animation = (enteringView || leavingView).getTransitionName(opts.direction);
- }
- }
- ti.opts = opts;
- };
- /**
- * DOM WRITE
- */
- NavControllerBase.prototype._viewInit = function (enteringView) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- // render the entering view, and all child navs and views
- // entering view has not been initialized yet
- var componentProviders = ReflectiveInjector.resolve([
- { provide: NavController, useValue: this },
- { provide: ViewController, useValue: enteringView },
- { provide: NavParams, useValue: enteringView.getNavParams() }
- ]);
- var componentFactory = this._linker.resolveComponent(enteringView.component);
- var childInjector = ReflectiveInjector.fromResolvedProviders(componentProviders, this._viewport.parentInjector);
- // create ComponentRef and set it to the entering view
- enteringView.init(componentFactory.create(childInjector, []));
- enteringView._state = STATE_INITIALIZED;
- this._preLoad(enteringView);
- };
- NavControllerBase.prototype._viewAttachToDOM = function (view, componentRef, viewport) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- // fire willLoad before change detection runs
- this._willLoad(view);
- // render the component ref instance to the DOM
- // ******** DOM WRITE ****************
- viewport.insert(componentRef.hostView, viewport.length);
- view._state = STATE_ATTACHED;
- if (view._cssClass) {
- // the ElementRef of the actual ion-page created
- var pageElement = componentRef.location.nativeElement;
- // ******** DOM WRITE ****************
- this._renderer.setElementClass(pageElement, view._cssClass, true);
- }
- componentRef.changeDetectorRef.detectChanges();
- // successfully finished loading the entering view
- // fire off the "didLoad" lifecycle events
- this._zone.run(this._didLoad.bind(this, view));
- };
- NavControllerBase.prototype._viewTest = function (enteringView, leavingView, ti) {
- // Only test canLeave/canEnter if there is transition
- if (!ti.requiresTransition) {
- return Promise.resolve();
- }
- var promises = [];
- if (leavingView) {
- promises.push(leavingView._lifecycleTest('Leave'));
- }
- if (enteringView) {
- promises.push(enteringView._lifecycleTest('Enter'));
- }
- if (promises.length === 0) {
- return Promise.resolve();
- }
- // darn, async promises, gotta wait for them to resolve
- return Promise.all(promises).then(function (values) {
- if (values.some(function (result) { return result === false; })) {
- throw 'canEnter/Leave returned false';
- }
- }).catch(function (reason) {
- // Do not
- ti.reject = null;
- throw reason;
- });
- };
- NavControllerBase.prototype._transition = function (enteringView, leavingView, ti) {
- var _this = this;
- if (!ti.requiresTransition) {
- // transition is not required, so we are already done!
- // they're inserting/removing the views somewhere in the middle or
- // beginning, so visually nothing needs to animate/transition
- // resolve immediately because there's no animation that's happening
- return Promise.resolve({
- hasCompleted: true,
- requiresTransition: false
- });
- }
- var opts = ti.opts;
- // figure out if this transition is the root one or a
- // child of a parent nav that has the root transition
- this._trnsId = this._trnsCtrl.getRootTrnsId(this);
- if (this._trnsId === null) {
- // this is the root transition, meaning all child navs and their views
- // should be added as a child transition to this one
- this._trnsId = this._trnsCtrl.nextId();
- }
- // create the transition options
- var animationOpts = {
- animation: opts.animation,
- direction: opts.direction,
- duration: (opts.animate === false ? 0 : opts.duration),
- easing: opts.easing,
- isRTL: this._config.plt.isRTL,
- ev: opts.ev,
- };
- // create the transition animation from the TransitionController
- // this will either create the root transition, or add it as a child transition
- var transition = this._trnsCtrl.get(this._trnsId, enteringView, leavingView, animationOpts);
- // ensure any swipeback transitions are cleared out
- this._sbTrns && this._sbTrns.destroy();
- this._sbTrns = null;
- // swipe to go back root transition
- if (transition.isRoot() && opts.progressAnimation) {
- this._sbTrns = transition;
- }
- // transition start has to be registered before attaching the view to the DOM!
- var promise = new Promise(function (resolve) { return transition.registerStart(resolve); }).then(function () {
- return _this._transitionStart(transition, enteringView, leavingView, opts);
- });
- if (enteringView && (enteringView._state === STATE_INITIALIZED)) {
- // render the entering component in the DOM
- // this would also render new child navs/views
- // which may have their very own async canEnter/Leave tests
- // ******** DOM WRITE ****************
- this._viewAttachToDOM(enteringView, enteringView._cmp, this._viewport);
- }
- if (!transition.hasChildren) {
- // lowest level transition, so kick it off and let it bubble up to start all of them
- transition.start();
- }
- return promise;
- };
- NavControllerBase.prototype._transitionStart = function (transition, enteringView, leavingView, opts) {
- var _this = this;
- (void 0) /* assert */;
- this._trnsId = null;
- // set the correct zIndex for the entering and leaving views
- // ******** DOM WRITE ****************
- setZIndex(this, enteringView, leavingView, opts.direction, this._renderer);
- // always ensure the entering view is viewable
- // ******** DOM WRITE ****************
- enteringView && enteringView._domShow(true, this._renderer);
- // always ensure the leaving view is viewable
- // ******** DOM WRITE ****************
- leavingView && leavingView._domShow(true, this._renderer);
- // initialize the transition
- transition.init();
- // we should animate (duration > 0) if the pushed page is not the first one (startup)
- // or if it is a portal (modal, actionsheet, etc.)
- var isFirstPage = !this._init && this._views.length === 1;
- var shouldNotAnimate = isFirstPage && !this._isPortal;
- var canNotAnimate = this._config.get('animate') === false;
- if (shouldNotAnimate || canNotAnimate) {
- opts.animate = false;
- }
- if (opts.animate === false) {
- // if it was somehow set to not animation, then make the duration zero
- transition.duration(0);
- }
- // create a callback that needs to run within zone
- // that will fire off the willEnter/Leave lifecycle events at the right time
- transition.beforeAddRead(this._viewsWillLifecycles.bind(this, enteringView, leavingView));
- // get the set duration of this transition
- var duration = transition.getDuration();
- // create a callback for when the animation is done
- var promise = new Promise(function (resolve) {
- transition.onFinish(resolve);
- });
- if (transition.isRoot()) {
- // this is the top most, or only active transition, so disable the app
- // add XXms to the duration the app is disabled when the keyboard is open
- if (duration > DISABLE_APP_MINIMUM_DURATION && opts.disableApp !== false) {
- // if this transition has a duration and this is the root transition
- // then set that the app is actively disabled
- this._app.setEnabled(false, duration + ACTIVE_TRANSITION_OFFSET, opts.minClickBlockDuration);
- }
- else {
- (void 0) /* console.debug */;
- }
- // cool, let's do this, start the transition
- if (opts.progressAnimation) {
- // this is a swipe to go back, just get the transition progress ready
- // kick off the swipe animation start
- transition.progressStart();
- }
- else {
- // only the top level transition should actually start "play"
- // kick it off and let it play through
- // ******** DOM WRITE ****************
- transition.play();
- }
- }
- return promise.then(function () { return _this._zone.run(function () {
- return _this._transitionFinish(transition, opts);
- }); });
- };
- NavControllerBase.prototype._transitionFinish = function (transition, opts) {
- var hasCompleted = transition.hasCompleted;
- var enteringView = transition.enteringView;
- var leavingView = transition.leavingView;
- // mainly for testing
- var enteringName;
- var leavingName;
- if (hasCompleted) {
- // transition has completed (went from 0 to 1)
- if (enteringView) {
- enteringName = enteringView.name;
- this._didEnter(enteringView);
- }
- if (leavingView) {
- leavingName = leavingView.name;
- this._didLeave(leavingView);
- }
- this._cleanup(enteringView);
- }
- else {
- // If transition does not complete, we have to cleanup anyway, because
- // previous pages in the stack are not hidden probably.
- this._cleanup(leavingView);
- }
- if (transition.isRoot()) {
- // this is the root transition
- // it's safe to destroy this transition
- this._trnsCtrl.destroy(transition.trnsId);
- // it's safe to enable the app again
- this._app.setEnabled(true);
- // mark ourselves as not transitioning - `deepLinker navchange` requires this
- // TODO - probably could be resolved in a better way
- this.setTransitioning(false);
- if (!this.hasChildren() && opts.updateUrl !== false) {
- // notify deep linker of the nav change
- // if a direction was provided and should update url
- this._linker.navChange(opts.direction);
- }
- if (opts.keyboardClose !== false) {
- // the keyboard is still open!
- // no problem, let's just close for them
- this.plt.focusOutActiveElement();
- }
- }
- return {
- hasCompleted: hasCompleted,
- requiresTransition: true,
- enteringName: enteringName,
- leavingName: leavingName,
- direction: opts.direction
- };
- };
- NavControllerBase.prototype._viewsWillLifecycles = function (enteringView, leavingView) {
- var _this = this;
- if (enteringView || leavingView) {
- this._zone.run(function () {
- // Here, the order is important. WillLeave must be called before WillEnter.
- if (leavingView) {
- var willUnload = enteringView ? leavingView.index > enteringView.index : true;
- _this._willLeave(leavingView, willUnload);
- }
- enteringView && _this._willEnter(enteringView);
- });
- }
- };
- NavControllerBase.prototype._insertViewAt = function (view, index) {
- var existingIndex = this._views.indexOf(view);
- if (existingIndex > -1) {
- // this view is already in the stack!!
- // move it to its new location
- (void 0) /* assert */;
- this._views.splice(index, 0, this._views.splice(existingIndex, 1)[0]);
- }
- else {
- (void 0) /* assert */;
- // this is a new view to add to the stack
- // create the new entering view
- view._setNav(this);
- // give this inserted view an ID
- this._ids++;
- if (!view.id) {
- view.id = this.id + "-" + this._ids;
- }
- // insert the entering view into the correct index in the stack
- this._views.splice(index, 0, view);
- }
- };
- NavControllerBase.prototype._removeView = function (view) {
- (void 0) /* assert */;
- var views = this._views;
- var index = views.indexOf(view);
- (void 0) /* assert */;
- if (index >= 0) {
- views.splice(index, 1);
- }
- };
- NavControllerBase.prototype._destroyView = function (view) {
- view._destroy(this._renderer);
- this._removeView(view);
- };
- /**
- * DOM WRITE
- */
- NavControllerBase.prototype._cleanup = function (activeView) {
- // ok, cleanup time!! Destroy all of the views that are
- // INACTIVE and come after the active view
- // only do this if the views exist, though
- if (!this._destroyed) {
- var activeViewIndex = this._views.indexOf(activeView);
- var views = this._views;
- var reorderZIndexes = false;
- var view = void 0;
- var i = void 0;
- for (i = views.length - 1; i >= 0; i--) {
- view = views[i];
- if (i > activeViewIndex) {
- // this view comes after the active view
- // let's unload it
- this._willUnload(view);
- this._destroyView(view);
- }
- else if (i < activeViewIndex && !this._isPortal) {
- // this view comes before the active view
- // and it is not a portal then ensure it is hidden
- view._domShow(false, this._renderer);
- }
- if (view._zIndex <= 0) {
- reorderZIndexes = true;
- }
- }
- if (!this._isPortal && reorderZIndexes) {
- for (i = 0; i < views.length; i++) {
- view = views[i];
- // ******** DOM WRITE ****************
- view._setZIndex(view._zIndex + INIT_ZINDEX + 1, this._renderer);
- }
- }
- }
- };
- NavControllerBase.prototype._preLoad = function (view) {
- (void 0) /* assert */;
- view._preLoad();
- };
- NavControllerBase.prototype._willLoad = function (view) {
- (void 0) /* assert */;
- try {
- view._willLoad();
- }
- catch (e) {
- this._errHandler && this._errHandler.handleError(e);
- }
- };
- NavControllerBase.prototype._didLoad = function (view) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- try {
- view._didLoad();
- this.viewDidLoad.emit(view);
- this._app.viewDidLoad.emit(view);
- }
- catch (e) {
- this._errHandler && this._errHandler.handleError(e);
- }
- };
- NavControllerBase.prototype._willEnter = function (view) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- try {
- view._willEnter();
- this.viewWillEnter.emit(view);
- this._app.viewWillEnter.emit(view);
- }
- catch (e) {
- this._errHandler && this._errHandler.handleError(e);
- }
- };
- NavControllerBase.prototype._didEnter = function (view) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- try {
- view._didEnter();
- this.viewDidEnter.emit(view);
- this._app.viewDidEnter.emit(view);
- }
- catch (e) {
- this._errHandler && this._errHandler.handleError(e);
- }
- };
- NavControllerBase.prototype._willLeave = function (view, willUnload) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- try {
- view._willLeave(willUnload);
- this.viewWillLeave.emit(view);
- this._app.viewWillLeave.emit(view);
- }
- catch (e) {
- this._errHandler && this._errHandler.handleError(e);
- }
- };
- NavControllerBase.prototype._didLeave = function (view) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- try {
- view._didLeave();
- this.viewDidLeave.emit(view);
- this._app.viewDidLeave.emit(view);
- }
- catch (e) {
- this._errHandler && this._errHandler.handleError(e);
- }
- };
- NavControllerBase.prototype._willUnload = function (view) {
- (void 0) /* assert */;
- (void 0) /* assert */;
- try {
- view._willUnload();
- this.viewWillUnload.emit(view);
- this._app.viewWillUnload.emit(view);
- }
- catch (e) {
- this._errHandler && this._errHandler.handleError(e);
- }
- };
- NavControllerBase.prototype.hasChildren = function () {
- return this._children && this._children.length > 0;
- };
- NavControllerBase.prototype.getActiveChildNavs = function () {
- return this._children;
- };
- NavControllerBase.prototype.getAllChildNavs = function () {
- return this._children;
- };
- NavControllerBase.prototype.registerChildNav = function (container) {
- this._children.push(container);
- };
- NavControllerBase.prototype.unregisterChildNav = function (nav) {
- this._children = this._children.filter(function (child) { return child !== nav; });
- };
- NavControllerBase.prototype.destroy = function () {
- var views = this._views;
- var view;
- for (var i = 0; i < views.length; i++) {
- view = views[i];
- view._willUnload();
- view._destroy(this._renderer);
- }
- // release swipe back gesture and transition
- this._sbGesture && this._sbGesture.destroy();
- this._sbTrns && this._sbTrns.destroy();
- this._queue = this._views = this._sbGesture = this._sbTrns = null;
- // Unregister navcontroller
- if (this.parent && this.parent.unregisterChildNav) {
- this.parent.unregisterChildNav(this);
- }
- else if (this._app) {
- this._app.unregisterRootNav(this);
- }
- this._destroyed = true;
- };
- NavControllerBase.prototype.swipeBackStart = function () {
- if (this.isTransitioning() || this._queue.length > 0) {
- return;
- }
- // default the direction to "back";
- var opts = {
- direction: DIRECTION_BACK,
- progressAnimation: true
- };
- this._queueTrns({
- removeStart: -1,
- removeCount: 1,
- opts: opts,
- }, null);
- };
- NavControllerBase.prototype.swipeBackProgress = function (stepValue) {
- if (this._sbTrns && this._sbGesture) {
- // continue to disable the app while actively dragging
- this._app.setEnabled(false, ACTIVE_TRANSITION_DEFAULT);
- this.setTransitioning(true);
- // set the transition animation's progress
- this._sbTrns.progressStep(stepValue);
- }
- };
- NavControllerBase.prototype.swipeBackEnd = function (shouldComplete, currentStepValue, velocity) {
- if (this._sbTrns && this._sbGesture) {
- // the swipe back gesture has ended
- var dur = this._sbTrns.getDuration() / (Math.abs(velocity) + 1);
- this._sbTrns.progressEnd(shouldComplete, currentStepValue, dur);
- }
- };
- NavControllerBase.prototype._swipeBackCheck = function () {
- if (this.canSwipeBack()) {
- if (!this._sbGesture) {
- this._sbGesture = new SwipeBackGesture(this.plt, this, this._gestureCtrl, this._domCtrl);
- }
- this._sbGesture.listen();
- }
- else if (this._sbGesture) {
- this._sbGesture.unlisten();
- }
- };
- NavControllerBase.prototype.canSwipeBack = function () {
- return (this._sbEnabled &&
- !this._isPortal &&
- !this._children.length &&
- !this.isTransitioning() &&
- this._app.isEnabled() &&
- this.canGoBack());
- };
- NavControllerBase.prototype.canGoBack = function () {
- var activeView = this.getActive();
- return !!(activeView && activeView.enableBack());
- };
- NavControllerBase.prototype.isTransitioning = function () {
- return this._trnsTm;
- };
- NavControllerBase.prototype.setTransitioning = function (isTransitioning) {
- this._trnsTm = isTransitioning;
- };
- NavControllerBase.prototype.getActive = function () {
- return this._views[this._views.length - 1];
- };
- NavControllerBase.prototype.isActive = function (view) {
- return (view === this.getActive());
- };
- NavControllerBase.prototype.getByIndex = function (index) {
- return this._views[index];
- };
- NavControllerBase.prototype.getPrevious = function (view) {
- // returns the view controller which is before the given view controller.
- if (!view) {
- view = this.getActive();
- }
- var views = this._views;
- var index = views.indexOf(view);
- return (index > 0) ? views[index - 1] : null;
- };
- NavControllerBase.prototype.first = function () {
- // returns the first view controller in this nav controller's stack.
- return this._views[0];
- };
- NavControllerBase.prototype.last = function () {
- // returns the last page in this nav controller's stack.
- var views = this._views;
- return views[views.length - 1];
- };
- NavControllerBase.prototype.indexOf = function (view) {
- // returns the index number of the given view controller.
- return this._views.indexOf(view);
- };
- NavControllerBase.prototype.length = function () {
- return this._views.length;
- };
- NavControllerBase.prototype.getViews = function () {
- return this._views;
- };
- /**
- * Return a view controller
- */
- NavControllerBase.prototype.getViewById = function (id) {
- for (var _i = 0, _a = this._views; _i < _a.length; _i++) {
- var vc = _a[_i];
- if (vc && vc.id === id) {
- return vc;
- }
- }
- return null;
- };
- NavControllerBase.prototype.isSwipeBackEnabled = function () {
- return this._sbEnabled;
- };
- NavControllerBase.prototype.dismissPageChangeViews = function () {
- for (var _i = 0, _a = this._views; _i < _a.length; _i++) {
- var view = _a[_i];
- if (view.data && view.data.dismissOnPageChange) {
- view.dismiss().catch(function () { });
- }
- }
- };
- NavControllerBase.prototype.setViewport = function (val) {
- this._viewport = val;
- };
- NavControllerBase.prototype.resize = function () {
- var active = this.getActive();
- if (!active) {
- return;
- }
- var content = active.getIONContent();
- content && content.resize();
- };
- NavControllerBase.prototype.goToRoot = function (_opts) {
- return Promise.reject(new Error('goToRoot needs to be implemented by child class'));
- };
- /*
- * @private
- */
- NavControllerBase.prototype.getType = function () {
- return 'nav';
- };
- /*
- * @private
- */
- NavControllerBase.prototype.getSecondaryIdentifier = function () {
- return null;
- };
- /**
- * Returns the active child navigation.
- */
- NavControllerBase.prototype.getActiveChildNav = function () {
- console.warn('(getActiveChildNav) is deprecated and will be removed in the next major release. Use getActiveChildNavs instead.');
- return this._children[this._children.length - 1];
- };
- NavControllerBase.propDecorators = {
- 'swipeBackEnabled': [{ type: Input },],
- };
- return NavControllerBase;
- }(Ion));
- export { NavControllerBase };
- var ctrlIds = -1;
- var DISABLE_APP_MINIMUM_DURATION = 64;
- var ACTIVE_TRANSITION_DEFAULT = 5000;
- var ACTIVE_TRANSITION_OFFSET = 2000;
- //# sourceMappingURL=nav-controller-base.js.map
|