a zip code crypto-currency system good for red ONLY

nav-controller-base.js 41KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. var __extends = (this && this.__extends) || (function () {
  2. var extendStatics = Object.setPrototypeOf ||
  3. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  4. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  5. return function (d, b) {
  6. extendStatics(d, b);
  7. function __() { this.constructor = d; }
  8. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  9. };
  10. })();
  11. import { EventEmitter, Input, ReflectiveInjector } from '@angular/core';
  12. import { DIRECTION_BACK, DIRECTION_FORWARD, INIT_ZINDEX, STATE_ATTACHED, STATE_DESTROYED, STATE_INITIALIZED, STATE_NEW, convertToViews, } from './nav-util';
  13. import { setZIndex } from './nav-util';
  14. import { isBlank, isNumber, isPresent, isTrueProperty } from '../util/util';
  15. import { ViewController, isViewController } from './view-controller';
  16. import { Ion } from '../components/ion';
  17. import { NavController } from './nav-controller';
  18. import { NavParams } from './nav-params';
  19. import { SwipeBackGesture } from './swipe-back';
  20. /**
  21. * @hidden
  22. * This class is for internal use only. It is not exported publicly.
  23. */
  24. var NavControllerBase = (function (_super) {
  25. __extends(NavControllerBase, _super);
  26. function NavControllerBase(parent, _app, config, plt, elementRef, _zone, renderer, _cfr, _gestureCtrl, _trnsCtrl, _linker, _domCtrl, _errHandler) {
  27. var _this = _super.call(this, config, elementRef, renderer) || this;
  28. _this.parent = parent;
  29. _this._app = _app;
  30. _this.config = config;
  31. _this.plt = plt;
  32. _this._zone = _zone;
  33. _this._cfr = _cfr;
  34. _this._gestureCtrl = _gestureCtrl;
  35. _this._trnsCtrl = _trnsCtrl;
  36. _this._linker = _linker;
  37. _this._domCtrl = _domCtrl;
  38. _this._errHandler = _errHandler;
  39. _this._ids = -1;
  40. _this._init = false;
  41. _this._queue = [];
  42. _this._trnsId = null;
  43. _this._trnsTm = false;
  44. _this._views = [];
  45. _this._zIndexOffset = 0;
  46. _this.viewDidLoad = new EventEmitter();
  47. _this.viewWillEnter = new EventEmitter();
  48. _this.viewDidEnter = new EventEmitter();
  49. _this.viewWillLeave = new EventEmitter();
  50. _this.viewDidLeave = new EventEmitter();
  51. _this.viewWillUnload = new EventEmitter();
  52. _this._sbEnabled = config.getBoolean('swipeBackEnabled');
  53. _this._children = [];
  54. _this.id = 'n' + (++ctrlIds);
  55. _this._destroyed = false;
  56. return _this;
  57. }
  58. Object.defineProperty(NavControllerBase.prototype, "swipeBackEnabled", {
  59. get: function () {
  60. return this._sbEnabled;
  61. },
  62. set: function (val) {
  63. this._sbEnabled = isTrueProperty(val);
  64. this._swipeBackCheck();
  65. },
  66. enumerable: true,
  67. configurable: true
  68. });
  69. NavControllerBase.prototype.push = function (page, params, opts, done) {
  70. return this._queueTrns({
  71. insertStart: -1,
  72. insertViews: [{ page: page, params: params }],
  73. opts: opts,
  74. }, done);
  75. };
  76. NavControllerBase.prototype.insert = function (insertIndex, page, params, opts, done) {
  77. return this._queueTrns({
  78. insertStart: insertIndex,
  79. insertViews: [{ page: page, params: params }],
  80. opts: opts,
  81. }, done);
  82. };
  83. NavControllerBase.prototype.insertPages = function (insertIndex, insertPages, opts, done) {
  84. return this._queueTrns({
  85. insertStart: insertIndex,
  86. insertViews: insertPages,
  87. opts: opts,
  88. }, done);
  89. };
  90. NavControllerBase.prototype.pop = function (opts, done) {
  91. return this._queueTrns({
  92. removeStart: -1,
  93. removeCount: 1,
  94. opts: opts,
  95. }, done);
  96. };
  97. NavControllerBase.prototype.popTo = function (indexOrViewCtrl, opts, done) {
  98. var config = {
  99. removeStart: -1,
  100. removeCount: -1,
  101. opts: opts
  102. };
  103. if (isViewController(indexOrViewCtrl)) {
  104. config.removeView = indexOrViewCtrl;
  105. config.removeStart = 1;
  106. }
  107. else if (isNumber(indexOrViewCtrl)) {
  108. config.removeStart = indexOrViewCtrl + 1;
  109. }
  110. return this._queueTrns(config, done);
  111. };
  112. NavControllerBase.prototype.popToRoot = function (opts, done) {
  113. return this._queueTrns({
  114. removeStart: 1,
  115. removeCount: -1,
  116. opts: opts,
  117. }, done);
  118. };
  119. NavControllerBase.prototype.popAll = function () {
  120. var promises = [];
  121. for (var i = this._views.length - 1; i >= 0; i--) {
  122. promises.push(this.pop(null));
  123. }
  124. return Promise.all(promises);
  125. };
  126. NavControllerBase.prototype.remove = function (startIndex, removeCount, opts, done) {
  127. if (removeCount === void 0) { removeCount = 1; }
  128. return this._queueTrns({
  129. removeStart: startIndex,
  130. removeCount: removeCount,
  131. opts: opts,
  132. }, done);
  133. };
  134. NavControllerBase.prototype.removeView = function (viewController, opts, done) {
  135. return this._queueTrns({
  136. removeView: viewController,
  137. removeStart: 0,
  138. removeCount: 1,
  139. opts: opts,
  140. }, done);
  141. };
  142. NavControllerBase.prototype.setRoot = function (pageOrViewCtrl, params, opts, done) {
  143. return this.setPages([{ page: pageOrViewCtrl, params: params }], opts, done);
  144. };
  145. NavControllerBase.prototype.setPages = function (viewControllers, opts, done) {
  146. if (isBlank(opts)) {
  147. opts = {};
  148. }
  149. // if animation wasn't set to true then default it to NOT animate
  150. if (opts.animate !== true) {
  151. opts.animate = false;
  152. }
  153. return this._queueTrns({
  154. insertStart: 0,
  155. insertViews: viewControllers,
  156. removeStart: 0,
  157. removeCount: -1,
  158. opts: opts
  159. }, done);
  160. };
  161. // _queueTrns() adds a navigation stack change to the queue and schedules it to run:
  162. // 1. _nextTrns(): consumes the next transition in the queue
  163. // 2. _viewInit(): initializes enteringView if required
  164. // 3. _viewTest(): ensures canLeave/canEnter returns true, so the operation can continue
  165. // 4. _postViewInit(): add/remove the views from the navigation stack
  166. // 5. _transitionInit(): initializes the visual transition if required and schedules it to run
  167. // 6. _viewAttachToDOM(): attaches the enteringView to the DOM
  168. // 7. _transitionStart(): called once the transition actually starts, it initializes the Animation underneath.
  169. // 8. _transitionFinish(): called once the transition finishes
  170. // 9. _cleanup(): syncs the navigation internal state with the DOM. For example it removes the pages from the DOM or hides/show them.
  171. NavControllerBase.prototype._queueTrns = function (ti, done) {
  172. var promise = new Promise(function (resolve, reject) {
  173. ti.resolve = resolve;
  174. ti.reject = reject;
  175. });
  176. ti.done = done;
  177. // Normalize empty
  178. if (ti.insertViews && ti.insertViews.length === 0) {
  179. ti.insertViews = undefined;
  180. }
  181. // Enqueue transition instruction
  182. this._queue.push(ti);
  183. // if there isn't a transition already happening
  184. // then this will kick off this transition
  185. this._nextTrns();
  186. return promise;
  187. };
  188. NavControllerBase.prototype._success = function (result, ti) {
  189. if (this._queue === null) {
  190. this._fireError('nav controller was destroyed', ti);
  191. return;
  192. }
  193. this._init = true;
  194. this._trnsId = null;
  195. // ensure we're not transitioning here
  196. this.setTransitioning(false);
  197. this._swipeBackCheck();
  198. // let's see if there's another to kick off
  199. this._nextTrns();
  200. if (ti.done) {
  201. ti.done(result.hasCompleted, result.requiresTransition, result.enteringName, result.leavingName, result.direction);
  202. }
  203. ti.resolve(result.hasCompleted);
  204. };
  205. NavControllerBase.prototype._failed = function (rejectReason, ti) {
  206. if (this._queue === null) {
  207. this._fireError('nav controller was destroyed', ti);
  208. return;
  209. }
  210. this._trnsId = null;
  211. this._queue.length = 0;
  212. // let's see if there's another to kick off
  213. this.setTransitioning(false);
  214. this._swipeBackCheck();
  215. this._nextTrns();
  216. this._fireError(rejectReason, ti);
  217. };
  218. NavControllerBase.prototype._fireError = function (rejectReason, ti) {
  219. if (ti.done) {
  220. ti.done(false, false, rejectReason);
  221. }
  222. if (ti.reject && !this._destroyed) {
  223. ti.reject(rejectReason);
  224. }
  225. else {
  226. ti.resolve(false);
  227. }
  228. };
  229. NavControllerBase.prototype._nextTrns = function () {
  230. var _this = this;
  231. // this is the framework's bread 'n butta function
  232. // only one transition is allowed at any given time
  233. if (this.isTransitioning()) {
  234. return false;
  235. }
  236. // there is no transition happening right now
  237. // get the next instruction
  238. var ti = this._queue.shift();
  239. if (!ti) {
  240. return false;
  241. }
  242. // set that this nav is actively transitioning
  243. var enteringView;
  244. var leavingView;
  245. this._startTI(ti)
  246. .then(function () { return _this._loadLazyLoading(ti); })
  247. .then(function () {
  248. leavingView = _this.getActive();
  249. enteringView = _this._getEnteringView(ti, leavingView);
  250. if (!leavingView && !enteringView) {
  251. throw 'no views in the stack to be removed';
  252. }
  253. if (enteringView && enteringView._state === STATE_NEW) {
  254. _this._viewInit(enteringView);
  255. }
  256. // Needs transition?
  257. ti.requiresTransition = (ti.enteringRequiresTransition || ti.leavingRequiresTransition) && enteringView !== leavingView;
  258. })
  259. .then(function () { return _this._viewTest(enteringView, leavingView, ti); })
  260. .then(function () { return _this._postViewInit(enteringView, leavingView, ti); })
  261. .then(function () { return _this._transition(enteringView, leavingView, ti); })
  262. .then(function (result) { return _this._success(result, ti); })
  263. .catch(function (rejectReason) { return _this._failed(rejectReason, ti); });
  264. return true;
  265. };
  266. NavControllerBase.prototype._startTI = function (ti) {
  267. var viewsLength = this._views.length;
  268. if (isPresent(ti.removeView)) {
  269. (void 0) /* assert */;
  270. (void 0) /* assert */;
  271. var index = this.indexOf(ti.removeView);
  272. if (index < 0) {
  273. return Promise.reject('removeView was not found');
  274. }
  275. ti.removeStart += index;
  276. }
  277. if (isPresent(ti.removeStart)) {
  278. if (ti.removeStart < 0) {
  279. ti.removeStart = (viewsLength - 1);
  280. }
  281. if (ti.removeCount < 0) {
  282. ti.removeCount = (viewsLength - ti.removeStart);
  283. }
  284. ti.leavingRequiresTransition = (ti.removeCount > 0) && ((ti.removeStart + ti.removeCount) === viewsLength);
  285. }
  286. if (ti.insertViews) {
  287. // allow -1 to be passed in to auto push it on the end
  288. // and clean up the index if it's larger then the size of the stack
  289. if (ti.insertStart < 0 || ti.insertStart > viewsLength) {
  290. ti.insertStart = viewsLength;
  291. }
  292. ti.enteringRequiresTransition = (ti.insertStart === viewsLength);
  293. }
  294. this.setTransitioning(true);
  295. return Promise.resolve();
  296. };
  297. NavControllerBase.prototype._loadLazyLoading = function (ti) {
  298. var _this = this;
  299. var insertViews = ti.insertViews;
  300. if (insertViews) {
  301. (void 0) /* assert */;
  302. return convertToViews(this._linker, insertViews).then(function (viewControllers) {
  303. (void 0) /* assert */;
  304. viewControllers = viewControllers.filter(function (v) { return v !== null; });
  305. if (viewControllers.length === 0) {
  306. throw 'invalid views to insert';
  307. }
  308. // Check all the inserted view are correct
  309. for (var i = 0; i < viewControllers.length; i++) {
  310. var view = viewControllers[i];
  311. var nav = view._nav;
  312. if (nav && nav !== _this) {
  313. throw 'inserted view was already inserted';
  314. }
  315. if (view._state === STATE_DESTROYED) {
  316. throw 'inserted view was already destroyed';
  317. }
  318. }
  319. ti.insertViews = viewControllers;
  320. });
  321. }
  322. return Promise.resolve();
  323. };
  324. NavControllerBase.prototype._getEnteringView = function (ti, leavingView) {
  325. var insertViews = ti.insertViews;
  326. if (insertViews) {
  327. // grab the very last view of the views to be inserted
  328. // and initialize it as the new entering view
  329. return insertViews[insertViews.length - 1];
  330. }
  331. var removeStart = ti.removeStart;
  332. if (isPresent(removeStart)) {
  333. var views = this._views;
  334. var removeEnd = removeStart + ti.removeCount;
  335. var i;
  336. var view;
  337. for (i = views.length - 1; i >= 0; i--) {
  338. view = views[i];
  339. if ((i < removeStart || i >= removeEnd) && view !== leavingView) {
  340. return view;
  341. }
  342. }
  343. }
  344. return null;
  345. };
  346. NavControllerBase.prototype._postViewInit = function (enteringView, leavingView, ti) {
  347. var _this = this;
  348. (void 0) /* assert */;
  349. (void 0) /* assert */;
  350. (void 0) /* assert */;
  351. var opts = ti.opts || {};
  352. var insertViews = ti.insertViews;
  353. var removeStart = ti.removeStart;
  354. var removeCount = ti.removeCount;
  355. var view;
  356. var i;
  357. var destroyQueue;
  358. // there are views to remove
  359. if (isPresent(removeStart)) {
  360. (void 0) /* assert */;
  361. (void 0) /* assert */;
  362. destroyQueue = [];
  363. for (i = 0; i < removeCount; i++) {
  364. view = this._views[i + removeStart];
  365. if (view && view !== enteringView && view !== leavingView) {
  366. destroyQueue.push(view);
  367. }
  368. }
  369. // default the direction to "back"
  370. opts.direction = opts.direction || DIRECTION_BACK;
  371. }
  372. var finalBalance = this._views.length + (insertViews ? insertViews.length : 0) - (removeCount ? removeCount : 0);
  373. (void 0) /* assert */;
  374. if (finalBalance === 0 && !this._isPortal) {
  375. console.warn("You can't remove all the pages in the navigation stack. nav.pop() is probably called too many times.", this, this.getNativeElement());
  376. throw 'navigation stack needs at least one root page';
  377. }
  378. // At this point the transition can not be rejected, any throw should be an error
  379. // there are views to insert
  380. if (insertViews) {
  381. // manually set the new view's id if an id was passed in the options
  382. if (isPresent(opts.id)) {
  383. enteringView.id = opts.id;
  384. }
  385. // add the views to the
  386. for (i = 0; i < insertViews.length; i++) {
  387. view = insertViews[i];
  388. this._insertViewAt(view, ti.insertStart + i);
  389. }
  390. if (ti.enteringRequiresTransition) {
  391. // default to forward if not already set
  392. opts.direction = opts.direction || DIRECTION_FORWARD;
  393. }
  394. }
  395. // if the views to be removed are in the beginning or middle
  396. // and there is not a view that needs to visually transition out
  397. // then just destroy them and don't transition anything
  398. // batch all of lifecycles together
  399. // let's make sure, callbacks are zoned
  400. if (destroyQueue && destroyQueue.length > 0) {
  401. this._zone.run(function () {
  402. for (i = 0; i < destroyQueue.length; i++) {
  403. view = destroyQueue[i];
  404. _this._willLeave(view, true);
  405. _this._didLeave(view);
  406. _this._willUnload(view);
  407. }
  408. });
  409. // once all lifecycle events has been delivered, we can safely detroy the views
  410. for (i = 0; i < destroyQueue.length; i++) {
  411. this._destroyView(destroyQueue[i]);
  412. }
  413. }
  414. // set which animation it should use if it wasn't set yet
  415. if (ti.requiresTransition && !opts.animation) {
  416. if (isPresent(ti.removeStart)) {
  417. opts.animation = (leavingView || enteringView).getTransitionName(opts.direction);
  418. }
  419. else {
  420. opts.animation = (enteringView || leavingView).getTransitionName(opts.direction);
  421. }
  422. }
  423. ti.opts = opts;
  424. };
  425. /**
  426. * DOM WRITE
  427. */
  428. NavControllerBase.prototype._viewInit = function (enteringView) {
  429. (void 0) /* assert */;
  430. (void 0) /* assert */;
  431. // render the entering view, and all child navs and views
  432. // entering view has not been initialized yet
  433. var componentProviders = ReflectiveInjector.resolve([
  434. { provide: NavController, useValue: this },
  435. { provide: ViewController, useValue: enteringView },
  436. { provide: NavParams, useValue: enteringView.getNavParams() }
  437. ]);
  438. var componentFactory = this._linker.resolveComponent(enteringView.component);
  439. var childInjector = ReflectiveInjector.fromResolvedProviders(componentProviders, this._viewport.parentInjector);
  440. // create ComponentRef and set it to the entering view
  441. enteringView.init(componentFactory.create(childInjector, []));
  442. enteringView._state = STATE_INITIALIZED;
  443. this._preLoad(enteringView);
  444. };
  445. NavControllerBase.prototype._viewAttachToDOM = function (view, componentRef, viewport) {
  446. (void 0) /* assert */;
  447. (void 0) /* assert */;
  448. // fire willLoad before change detection runs
  449. this._willLoad(view);
  450. // render the component ref instance to the DOM
  451. // ******** DOM WRITE ****************
  452. viewport.insert(componentRef.hostView, viewport.length);
  453. view._state = STATE_ATTACHED;
  454. if (view._cssClass) {
  455. // the ElementRef of the actual ion-page created
  456. var pageElement = componentRef.location.nativeElement;
  457. // ******** DOM WRITE ****************
  458. this._renderer.setElementClass(pageElement, view._cssClass, true);
  459. }
  460. componentRef.changeDetectorRef.detectChanges();
  461. // successfully finished loading the entering view
  462. // fire off the "didLoad" lifecycle events
  463. this._zone.run(this._didLoad.bind(this, view));
  464. };
  465. NavControllerBase.prototype._viewTest = function (enteringView, leavingView, ti) {
  466. // Only test canLeave/canEnter if there is transition
  467. if (!ti.requiresTransition) {
  468. return Promise.resolve();
  469. }
  470. var promises = [];
  471. if (leavingView) {
  472. promises.push(leavingView._lifecycleTest('Leave'));
  473. }
  474. if (enteringView) {
  475. promises.push(enteringView._lifecycleTest('Enter'));
  476. }
  477. if (promises.length === 0) {
  478. return Promise.resolve();
  479. }
  480. // darn, async promises, gotta wait for them to resolve
  481. return Promise.all(promises).then(function (values) {
  482. if (values.some(function (result) { return result === false; })) {
  483. throw 'canEnter/Leave returned false';
  484. }
  485. }).catch(function (reason) {
  486. // Do not
  487. ti.reject = null;
  488. throw reason;
  489. });
  490. };
  491. NavControllerBase.prototype._transition = function (enteringView, leavingView, ti) {
  492. var _this = this;
  493. if (!ti.requiresTransition) {
  494. // transition is not required, so we are already done!
  495. // they're inserting/removing the views somewhere in the middle or
  496. // beginning, so visually nothing needs to animate/transition
  497. // resolve immediately because there's no animation that's happening
  498. return Promise.resolve({
  499. hasCompleted: true,
  500. requiresTransition: false
  501. });
  502. }
  503. var opts = ti.opts;
  504. // figure out if this transition is the root one or a
  505. // child of a parent nav that has the root transition
  506. this._trnsId = this._trnsCtrl.getRootTrnsId(this);
  507. if (this._trnsId === null) {
  508. // this is the root transition, meaning all child navs and their views
  509. // should be added as a child transition to this one
  510. this._trnsId = this._trnsCtrl.nextId();
  511. }
  512. // create the transition options
  513. var animationOpts = {
  514. animation: opts.animation,
  515. direction: opts.direction,
  516. duration: (opts.animate === false ? 0 : opts.duration),
  517. easing: opts.easing,
  518. isRTL: this._config.plt.isRTL,
  519. ev: opts.ev,
  520. };
  521. // create the transition animation from the TransitionController
  522. // this will either create the root transition, or add it as a child transition
  523. var transition = this._trnsCtrl.get(this._trnsId, enteringView, leavingView, animationOpts);
  524. // ensure any swipeback transitions are cleared out
  525. this._sbTrns && this._sbTrns.destroy();
  526. this._sbTrns = null;
  527. // swipe to go back root transition
  528. if (transition.isRoot() && opts.progressAnimation) {
  529. this._sbTrns = transition;
  530. }
  531. // transition start has to be registered before attaching the view to the DOM!
  532. var promise = new Promise(function (resolve) { return transition.registerStart(resolve); }).then(function () {
  533. return _this._transitionStart(transition, enteringView, leavingView, opts);
  534. });
  535. if (enteringView && (enteringView._state === STATE_INITIALIZED)) {
  536. // render the entering component in the DOM
  537. // this would also render new child navs/views
  538. // which may have their very own async canEnter/Leave tests
  539. // ******** DOM WRITE ****************
  540. this._viewAttachToDOM(enteringView, enteringView._cmp, this._viewport);
  541. }
  542. if (!transition.hasChildren) {
  543. // lowest level transition, so kick it off and let it bubble up to start all of them
  544. transition.start();
  545. }
  546. return promise;
  547. };
  548. NavControllerBase.prototype._transitionStart = function (transition, enteringView, leavingView, opts) {
  549. var _this = this;
  550. (void 0) /* assert */;
  551. this._trnsId = null;
  552. // set the correct zIndex for the entering and leaving views
  553. // ******** DOM WRITE ****************
  554. setZIndex(this, enteringView, leavingView, opts.direction, this._renderer);
  555. // always ensure the entering view is viewable
  556. // ******** DOM WRITE ****************
  557. enteringView && enteringView._domShow(true, this._renderer);
  558. // always ensure the leaving view is viewable
  559. // ******** DOM WRITE ****************
  560. leavingView && leavingView._domShow(true, this._renderer);
  561. // initialize the transition
  562. transition.init();
  563. // we should animate (duration > 0) if the pushed page is not the first one (startup)
  564. // or if it is a portal (modal, actionsheet, etc.)
  565. var isFirstPage = !this._init && this._views.length === 1;
  566. var shouldNotAnimate = isFirstPage && !this._isPortal;
  567. var canNotAnimate = this._config.get('animate') === false;
  568. if (shouldNotAnimate || canNotAnimate) {
  569. opts.animate = false;
  570. }
  571. if (opts.animate === false) {
  572. // if it was somehow set to not animation, then make the duration zero
  573. transition.duration(0);
  574. }
  575. // create a callback that needs to run within zone
  576. // that will fire off the willEnter/Leave lifecycle events at the right time
  577. transition.beforeAddRead(this._viewsWillLifecycles.bind(this, enteringView, leavingView));
  578. // get the set duration of this transition
  579. var duration = transition.getDuration();
  580. // create a callback for when the animation is done
  581. var promise = new Promise(function (resolve) {
  582. transition.onFinish(resolve);
  583. });
  584. if (transition.isRoot()) {
  585. // this is the top most, or only active transition, so disable the app
  586. // add XXms to the duration the app is disabled when the keyboard is open
  587. if (duration > DISABLE_APP_MINIMUM_DURATION && opts.disableApp !== false) {
  588. // if this transition has a duration and this is the root transition
  589. // then set that the app is actively disabled
  590. this._app.setEnabled(false, duration + ACTIVE_TRANSITION_OFFSET, opts.minClickBlockDuration);
  591. }
  592. else {
  593. (void 0) /* console.debug */;
  594. }
  595. // cool, let's do this, start the transition
  596. if (opts.progressAnimation) {
  597. // this is a swipe to go back, just get the transition progress ready
  598. // kick off the swipe animation start
  599. transition.progressStart();
  600. }
  601. else {
  602. // only the top level transition should actually start "play"
  603. // kick it off and let it play through
  604. // ******** DOM WRITE ****************
  605. transition.play();
  606. }
  607. }
  608. return promise.then(function () { return _this._zone.run(function () {
  609. return _this._transitionFinish(transition, opts);
  610. }); });
  611. };
  612. NavControllerBase.prototype._transitionFinish = function (transition, opts) {
  613. var hasCompleted = transition.hasCompleted;
  614. var enteringView = transition.enteringView;
  615. var leavingView = transition.leavingView;
  616. // mainly for testing
  617. var enteringName;
  618. var leavingName;
  619. if (hasCompleted) {
  620. // transition has completed (went from 0 to 1)
  621. if (enteringView) {
  622. enteringName = enteringView.name;
  623. this._didEnter(enteringView);
  624. }
  625. if (leavingView) {
  626. leavingName = leavingView.name;
  627. this._didLeave(leavingView);
  628. }
  629. this._cleanup(enteringView);
  630. }
  631. else {
  632. // If transition does not complete, we have to cleanup anyway, because
  633. // previous pages in the stack are not hidden probably.
  634. this._cleanup(leavingView);
  635. }
  636. if (transition.isRoot()) {
  637. // this is the root transition
  638. // it's safe to destroy this transition
  639. this._trnsCtrl.destroy(transition.trnsId);
  640. // it's safe to enable the app again
  641. this._app.setEnabled(true);
  642. // mark ourselves as not transitioning - `deepLinker navchange` requires this
  643. // TODO - probably could be resolved in a better way
  644. this.setTransitioning(false);
  645. if (!this.hasChildren() && opts.updateUrl !== false) {
  646. // notify deep linker of the nav change
  647. // if a direction was provided and should update url
  648. this._linker.navChange(opts.direction);
  649. }
  650. if (opts.keyboardClose !== false) {
  651. // the keyboard is still open!
  652. // no problem, let's just close for them
  653. this.plt.focusOutActiveElement();
  654. }
  655. }
  656. return {
  657. hasCompleted: hasCompleted,
  658. requiresTransition: true,
  659. enteringName: enteringName,
  660. leavingName: leavingName,
  661. direction: opts.direction
  662. };
  663. };
  664. NavControllerBase.prototype._viewsWillLifecycles = function (enteringView, leavingView) {
  665. var _this = this;
  666. if (enteringView || leavingView) {
  667. this._zone.run(function () {
  668. // Here, the order is important. WillLeave must be called before WillEnter.
  669. if (leavingView) {
  670. var willUnload = enteringView ? leavingView.index > enteringView.index : true;
  671. _this._willLeave(leavingView, willUnload);
  672. }
  673. enteringView && _this._willEnter(enteringView);
  674. });
  675. }
  676. };
  677. NavControllerBase.prototype._insertViewAt = function (view, index) {
  678. var existingIndex = this._views.indexOf(view);
  679. if (existingIndex > -1) {
  680. // this view is already in the stack!!
  681. // move it to its new location
  682. (void 0) /* assert */;
  683. this._views.splice(index, 0, this._views.splice(existingIndex, 1)[0]);
  684. }
  685. else {
  686. (void 0) /* assert */;
  687. // this is a new view to add to the stack
  688. // create the new entering view
  689. view._setNav(this);
  690. // give this inserted view an ID
  691. this._ids++;
  692. if (!view.id) {
  693. view.id = this.id + "-" + this._ids;
  694. }
  695. // insert the entering view into the correct index in the stack
  696. this._views.splice(index, 0, view);
  697. }
  698. };
  699. NavControllerBase.prototype._removeView = function (view) {
  700. (void 0) /* assert */;
  701. var views = this._views;
  702. var index = views.indexOf(view);
  703. (void 0) /* assert */;
  704. if (index >= 0) {
  705. views.splice(index, 1);
  706. }
  707. };
  708. NavControllerBase.prototype._destroyView = function (view) {
  709. view._destroy(this._renderer);
  710. this._removeView(view);
  711. };
  712. /**
  713. * DOM WRITE
  714. */
  715. NavControllerBase.prototype._cleanup = function (activeView) {
  716. // ok, cleanup time!! Destroy all of the views that are
  717. // INACTIVE and come after the active view
  718. // only do this if the views exist, though
  719. if (!this._destroyed) {
  720. var activeViewIndex = this._views.indexOf(activeView);
  721. var views = this._views;
  722. var reorderZIndexes = false;
  723. var view = void 0;
  724. var i = void 0;
  725. for (i = views.length - 1; i >= 0; i--) {
  726. view = views[i];
  727. if (i > activeViewIndex) {
  728. // this view comes after the active view
  729. // let's unload it
  730. this._willUnload(view);
  731. this._destroyView(view);
  732. }
  733. else if (i < activeViewIndex && !this._isPortal) {
  734. // this view comes before the active view
  735. // and it is not a portal then ensure it is hidden
  736. view._domShow(false, this._renderer);
  737. }
  738. if (view._zIndex <= 0) {
  739. reorderZIndexes = true;
  740. }
  741. }
  742. if (!this._isPortal && reorderZIndexes) {
  743. for (i = 0; i < views.length; i++) {
  744. view = views[i];
  745. // ******** DOM WRITE ****************
  746. view._setZIndex(view._zIndex + INIT_ZINDEX + 1, this._renderer);
  747. }
  748. }
  749. }
  750. };
  751. NavControllerBase.prototype._preLoad = function (view) {
  752. (void 0) /* assert */;
  753. view._preLoad();
  754. };
  755. NavControllerBase.prototype._willLoad = function (view) {
  756. (void 0) /* assert */;
  757. try {
  758. view._willLoad();
  759. }
  760. catch (e) {
  761. this._errHandler && this._errHandler.handleError(e);
  762. }
  763. };
  764. NavControllerBase.prototype._didLoad = function (view) {
  765. (void 0) /* assert */;
  766. (void 0) /* assert */;
  767. try {
  768. view._didLoad();
  769. this.viewDidLoad.emit(view);
  770. this._app.viewDidLoad.emit(view);
  771. }
  772. catch (e) {
  773. this._errHandler && this._errHandler.handleError(e);
  774. }
  775. };
  776. NavControllerBase.prototype._willEnter = function (view) {
  777. (void 0) /* assert */;
  778. (void 0) /* assert */;
  779. try {
  780. view._willEnter();
  781. this.viewWillEnter.emit(view);
  782. this._app.viewWillEnter.emit(view);
  783. }
  784. catch (e) {
  785. this._errHandler && this._errHandler.handleError(e);
  786. }
  787. };
  788. NavControllerBase.prototype._didEnter = function (view) {
  789. (void 0) /* assert */;
  790. (void 0) /* assert */;
  791. try {
  792. view._didEnter();
  793. this.viewDidEnter.emit(view);
  794. this._app.viewDidEnter.emit(view);
  795. }
  796. catch (e) {
  797. this._errHandler && this._errHandler.handleError(e);
  798. }
  799. };
  800. NavControllerBase.prototype._willLeave = function (view, willUnload) {
  801. (void 0) /* assert */;
  802. (void 0) /* assert */;
  803. try {
  804. view._willLeave(willUnload);
  805. this.viewWillLeave.emit(view);
  806. this._app.viewWillLeave.emit(view);
  807. }
  808. catch (e) {
  809. this._errHandler && this._errHandler.handleError(e);
  810. }
  811. };
  812. NavControllerBase.prototype._didLeave = function (view) {
  813. (void 0) /* assert */;
  814. (void 0) /* assert */;
  815. try {
  816. view._didLeave();
  817. this.viewDidLeave.emit(view);
  818. this._app.viewDidLeave.emit(view);
  819. }
  820. catch (e) {
  821. this._errHandler && this._errHandler.handleError(e);
  822. }
  823. };
  824. NavControllerBase.prototype._willUnload = function (view) {
  825. (void 0) /* assert */;
  826. (void 0) /* assert */;
  827. try {
  828. view._willUnload();
  829. this.viewWillUnload.emit(view);
  830. this._app.viewWillUnload.emit(view);
  831. }
  832. catch (e) {
  833. this._errHandler && this._errHandler.handleError(e);
  834. }
  835. };
  836. NavControllerBase.prototype.hasChildren = function () {
  837. return this._children && this._children.length > 0;
  838. };
  839. NavControllerBase.prototype.getActiveChildNavs = function () {
  840. return this._children;
  841. };
  842. NavControllerBase.prototype.getAllChildNavs = function () {
  843. return this._children;
  844. };
  845. NavControllerBase.prototype.registerChildNav = function (container) {
  846. this._children.push(container);
  847. };
  848. NavControllerBase.prototype.unregisterChildNav = function (nav) {
  849. this._children = this._children.filter(function (child) { return child !== nav; });
  850. };
  851. NavControllerBase.prototype.destroy = function () {
  852. var views = this._views;
  853. var view;
  854. for (var i = 0; i < views.length; i++) {
  855. view = views[i];
  856. view._willUnload();
  857. view._destroy(this._renderer);
  858. }
  859. // release swipe back gesture and transition
  860. this._sbGesture && this._sbGesture.destroy();
  861. this._sbTrns && this._sbTrns.destroy();
  862. this._queue = this._views = this._sbGesture = this._sbTrns = null;
  863. // Unregister navcontroller
  864. if (this.parent && this.parent.unregisterChildNav) {
  865. this.parent.unregisterChildNav(this);
  866. }
  867. else if (this._app) {
  868. this._app.unregisterRootNav(this);
  869. }
  870. this._destroyed = true;
  871. };
  872. NavControllerBase.prototype.swipeBackStart = function () {
  873. if (this.isTransitioning() || this._queue.length > 0) {
  874. return;
  875. }
  876. // default the direction to "back";
  877. var opts = {
  878. direction: DIRECTION_BACK,
  879. progressAnimation: true
  880. };
  881. this._queueTrns({
  882. removeStart: -1,
  883. removeCount: 1,
  884. opts: opts,
  885. }, null);
  886. };
  887. NavControllerBase.prototype.swipeBackProgress = function (stepValue) {
  888. if (this._sbTrns && this._sbGesture) {
  889. // continue to disable the app while actively dragging
  890. this._app.setEnabled(false, ACTIVE_TRANSITION_DEFAULT);
  891. this.setTransitioning(true);
  892. // set the transition animation's progress
  893. this._sbTrns.progressStep(stepValue);
  894. }
  895. };
  896. NavControllerBase.prototype.swipeBackEnd = function (shouldComplete, currentStepValue, velocity) {
  897. if (this._sbTrns && this._sbGesture) {
  898. // the swipe back gesture has ended
  899. var dur = this._sbTrns.getDuration() / (Math.abs(velocity) + 1);
  900. this._sbTrns.progressEnd(shouldComplete, currentStepValue, dur);
  901. }
  902. };
  903. NavControllerBase.prototype._swipeBackCheck = function () {
  904. if (this.canSwipeBack()) {
  905. if (!this._sbGesture) {
  906. this._sbGesture = new SwipeBackGesture(this.plt, this, this._gestureCtrl, this._domCtrl);
  907. }
  908. this._sbGesture.listen();
  909. }
  910. else if (this._sbGesture) {
  911. this._sbGesture.unlisten();
  912. }
  913. };
  914. NavControllerBase.prototype.canSwipeBack = function () {
  915. return (this._sbEnabled &&
  916. !this._isPortal &&
  917. !this._children.length &&
  918. !this.isTransitioning() &&
  919. this._app.isEnabled() &&
  920. this.canGoBack());
  921. };
  922. NavControllerBase.prototype.canGoBack = function () {
  923. var activeView = this.getActive();
  924. return !!(activeView && activeView.enableBack());
  925. };
  926. NavControllerBase.prototype.isTransitioning = function () {
  927. return this._trnsTm;
  928. };
  929. NavControllerBase.prototype.setTransitioning = function (isTransitioning) {
  930. this._trnsTm = isTransitioning;
  931. };
  932. NavControllerBase.prototype.getActive = function () {
  933. return this._views[this._views.length - 1];
  934. };
  935. NavControllerBase.prototype.isActive = function (view) {
  936. return (view === this.getActive());
  937. };
  938. NavControllerBase.prototype.getByIndex = function (index) {
  939. return this._views[index];
  940. };
  941. NavControllerBase.prototype.getPrevious = function (view) {
  942. // returns the view controller which is before the given view controller.
  943. if (!view) {
  944. view = this.getActive();
  945. }
  946. var views = this._views;
  947. var index = views.indexOf(view);
  948. return (index > 0) ? views[index - 1] : null;
  949. };
  950. NavControllerBase.prototype.first = function () {
  951. // returns the first view controller in this nav controller's stack.
  952. return this._views[0];
  953. };
  954. NavControllerBase.prototype.last = function () {
  955. // returns the last page in this nav controller's stack.
  956. var views = this._views;
  957. return views[views.length - 1];
  958. };
  959. NavControllerBase.prototype.indexOf = function (view) {
  960. // returns the index number of the given view controller.
  961. return this._views.indexOf(view);
  962. };
  963. NavControllerBase.prototype.length = function () {
  964. return this._views.length;
  965. };
  966. NavControllerBase.prototype.getViews = function () {
  967. return this._views;
  968. };
  969. /**
  970. * Return a view controller
  971. */
  972. NavControllerBase.prototype.getViewById = function (id) {
  973. for (var _i = 0, _a = this._views; _i < _a.length; _i++) {
  974. var vc = _a[_i];
  975. if (vc && vc.id === id) {
  976. return vc;
  977. }
  978. }
  979. return null;
  980. };
  981. NavControllerBase.prototype.isSwipeBackEnabled = function () {
  982. return this._sbEnabled;
  983. };
  984. NavControllerBase.prototype.dismissPageChangeViews = function () {
  985. for (var _i = 0, _a = this._views; _i < _a.length; _i++) {
  986. var view = _a[_i];
  987. if (view.data && view.data.dismissOnPageChange) {
  988. view.dismiss().catch(function () { });
  989. }
  990. }
  991. };
  992. NavControllerBase.prototype.setViewport = function (val) {
  993. this._viewport = val;
  994. };
  995. NavControllerBase.prototype.resize = function () {
  996. var active = this.getActive();
  997. if (!active) {
  998. return;
  999. }
  1000. var content = active.getIONContent();
  1001. content && content.resize();
  1002. };
  1003. NavControllerBase.prototype.goToRoot = function (_opts) {
  1004. return Promise.reject(new Error('goToRoot needs to be implemented by child class'));
  1005. };
  1006. /*
  1007. * @private
  1008. */
  1009. NavControllerBase.prototype.getType = function () {
  1010. return 'nav';
  1011. };
  1012. /*
  1013. * @private
  1014. */
  1015. NavControllerBase.prototype.getSecondaryIdentifier = function () {
  1016. return null;
  1017. };
  1018. /**
  1019. * Returns the active child navigation.
  1020. */
  1021. NavControllerBase.prototype.getActiveChildNav = function () {
  1022. console.warn('(getActiveChildNav) is deprecated and will be removed in the next major release. Use getActiveChildNavs instead.');
  1023. return this._children[this._children.length - 1];
  1024. };
  1025. NavControllerBase.propDecorators = {
  1026. 'swipeBackEnabled': [{ type: Input },],
  1027. };
  1028. return NavControllerBase;
  1029. }(Ion));
  1030. export { NavControllerBase };
  1031. var ctrlIds = -1;
  1032. var DISABLE_APP_MINIMUM_DURATION = 64;
  1033. var ACTIVE_TRANSITION_DEFAULT = 5000;
  1034. var ACTIVE_TRANSITION_OFFSET = 2000;
  1035. //# sourceMappingURL=nav-controller-base.js.map