a zip code crypto-currency system good for red ONLY

deep-linker.js 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. (function (factory) {
  2. if (typeof module === "object" && typeof module.exports === "object") {
  3. var v = factory(require, exports);
  4. if (v !== undefined) module.exports = v;
  5. }
  6. else if (typeof define === "function" && define.amd) {
  7. define(["require", "exports", "./nav-util", "../util/util", "./url-serializer", "./view-controller"], factory);
  8. }
  9. })(function (require, exports) {
  10. "use strict";
  11. Object.defineProperty(exports, "__esModule", { value: true });
  12. var nav_util_1 = require("./nav-util");
  13. var util_1 = require("../util/util");
  14. var url_serializer_1 = require("./url-serializer");
  15. var view_controller_1 = require("./view-controller");
  16. /**
  17. * @hidden
  18. */
  19. var DeepLinker = (function () {
  20. function DeepLinker(_app, _serializer, _location, _moduleLoader, _baseCfr) {
  21. this._app = _app;
  22. this._serializer = _serializer;
  23. this._location = _location;
  24. this._moduleLoader = _moduleLoader;
  25. this._baseCfr = _baseCfr;
  26. /** @internal */
  27. this._history = [];
  28. }
  29. /**
  30. * @internal
  31. */
  32. DeepLinker.prototype.init = function () {
  33. var _this = this;
  34. // scenario 1: Initial load of all navs from the initial browser URL
  35. var browserUrl = normalizeUrl(this._location.path());
  36. (void 0) /* console.debug */;
  37. // remember this URL in our internal history stack
  38. this._historyPush(browserUrl);
  39. // listen for browser URL changes
  40. this._location.subscribe(function (locationChg) {
  41. _this._urlChange(normalizeUrl(locationChg.url));
  42. });
  43. };
  44. /**
  45. * The browser's location has been updated somehow.
  46. * @internal
  47. */
  48. DeepLinker.prototype._urlChange = function (browserUrl) {
  49. var _this = this;
  50. // do nothing if this url is the same as the current one
  51. if (!this._isCurrentUrl(browserUrl)) {
  52. var isGoingBack = true;
  53. if (this._isBackUrl(browserUrl)) {
  54. // scenario 2: user clicked the browser back button
  55. // scenario 4: user changed the browser URL to what was the back url was
  56. // scenario 5: user clicked a link href that was the back url
  57. (void 0) /* console.debug */;
  58. this._historyPop();
  59. }
  60. else {
  61. // scenario 3: user click forward button
  62. // scenario 4: user changed browser URL that wasn't the back url
  63. // scenario 5: user clicked a link href that wasn't the back url
  64. isGoingBack = false;
  65. (void 0) /* console.debug */;
  66. this._historyPush(browserUrl);
  67. }
  68. // get the app's root nav container
  69. var activeNavContainers_1 = this._app.getActiveNavContainers();
  70. if (activeNavContainers_1 && activeNavContainers_1.length) {
  71. if (browserUrl === '/') {
  72. // a url change to the index url
  73. if (util_1.isPresent(this._indexAliasUrl)) {
  74. // we already know the indexAliasUrl
  75. // update the url to use the know alias
  76. browserUrl = this._indexAliasUrl;
  77. }
  78. else {
  79. // the url change is to the root but we don't
  80. // already know the url used. So let's just
  81. // reset the root nav to its root page
  82. activeNavContainers_1.forEach(function (navContainer) {
  83. navContainer.goToRoot({
  84. updateUrl: false,
  85. isNavRoot: true
  86. });
  87. });
  88. return;
  89. }
  90. }
  91. // normal url
  92. var segments = this.getCurrentSegments(browserUrl);
  93. segments
  94. .map(function (segment) {
  95. // find the matching nav container
  96. for (var _i = 0, activeNavContainers_2 = activeNavContainers_1; _i < activeNavContainers_2.length; _i++) {
  97. var navContainer = activeNavContainers_2[_i];
  98. var nav = getNavFromTree(navContainer, segment.navId);
  99. if (nav) {
  100. return {
  101. segment: segment,
  102. navContainer: nav
  103. };
  104. }
  105. }
  106. })
  107. .filter(function (pair) { return !!pair; })
  108. .forEach(function (pair) {
  109. _this._loadViewForSegment(pair.navContainer, pair.segment, function () { });
  110. });
  111. }
  112. }
  113. };
  114. DeepLinker.prototype.getCurrentSegments = function (browserUrl) {
  115. if (!browserUrl) {
  116. browserUrl = normalizeUrl(this._location.path());
  117. }
  118. return this._serializer.parse(browserUrl);
  119. };
  120. /**
  121. * Update the deep linker using the NavController's current active view.
  122. * @internal
  123. */
  124. DeepLinker.prototype.navChange = function (direction) {
  125. if (direction) {
  126. var activeNavContainers = this._app.getActiveNavContainers();
  127. // the only time you'll ever get a TABS here is when loading directly from a URL
  128. // this method will be called again when the TAB is loaded
  129. // so just don't worry about the TABS for now
  130. // if you encounter a TABS, just return
  131. for (var _i = 0, activeNavContainers_3 = activeNavContainers; _i < activeNavContainers_3.length; _i++) {
  132. var activeNavContainer = activeNavContainers_3[_i];
  133. if (nav_util_1.isTabs(activeNavContainer) || activeNavContainer.isTransitioning()) {
  134. return;
  135. }
  136. }
  137. // okay, get the root navs and build the segments up
  138. var segments = [];
  139. var navContainers = this._app.getRootNavs();
  140. for (var _a = 0, navContainers_1 = navContainers; _a < navContainers_1.length; _a++) {
  141. var navContainer = navContainers_1[_a];
  142. var segmentsForNav = this.getSegmentsFromNav(navContainer);
  143. segments = segments.concat(segmentsForNav);
  144. }
  145. segments = segments.filter(function (segment) { return !!segment; });
  146. if (segments.length) {
  147. var browserUrl = this._serializer.serialize(segments);
  148. this._updateLocation(browserUrl, direction);
  149. }
  150. }
  151. };
  152. DeepLinker.prototype.getSegmentsFromNav = function (nav) {
  153. var _this = this;
  154. var segments = [];
  155. if (nav_util_1.isNav(nav)) {
  156. segments.push(this.getSegmentFromNav(nav));
  157. }
  158. else if (nav_util_1.isTab(nav)) {
  159. segments.push(this.getSegmentFromTab(nav));
  160. }
  161. nav.getActiveChildNavs().forEach(function (child) {
  162. segments = segments.concat(_this.getSegmentsFromNav(child));
  163. });
  164. return segments;
  165. };
  166. DeepLinker.prototype.getSegmentFromNav = function (nav, component, data) {
  167. if (!component) {
  168. var viewController = nav.getActive(true);
  169. if (viewController) {
  170. component = viewController.component;
  171. data = viewController.data;
  172. }
  173. }
  174. return this._serializer.serializeComponent(nav, component, data);
  175. };
  176. DeepLinker.prototype.getSegmentFromTab = function (navContainer, component, data) {
  177. if (navContainer && navContainer.parent) {
  178. var tabsNavContainer = navContainer.parent;
  179. var activeChildNavs = tabsNavContainer.getActiveChildNavs();
  180. if (activeChildNavs && activeChildNavs.length) {
  181. var activeChildNav = activeChildNavs[0];
  182. var viewController = activeChildNav.getActive(true);
  183. if (viewController) {
  184. component = viewController.component;
  185. data = viewController.data;
  186. }
  187. return this._serializer.serializeComponent(tabsNavContainer, component, data);
  188. }
  189. }
  190. };
  191. /**
  192. * @internal
  193. */
  194. DeepLinker.prototype._updateLocation = function (browserUrl, direction) {
  195. if (this._indexAliasUrl === browserUrl) {
  196. browserUrl = '/';
  197. }
  198. if (direction === nav_util_1.DIRECTION_BACK && this._isBackUrl(browserUrl)) {
  199. // this URL is exactly the same as the back URL
  200. // it's safe to use the browser's location.back()
  201. (void 0) /* console.debug */;
  202. this._historyPop();
  203. this._location.back();
  204. }
  205. else if (!this._isCurrentUrl(browserUrl)) {
  206. // probably navigating forward
  207. (void 0) /* console.debug */;
  208. this._historyPush(browserUrl);
  209. this._location.go(browserUrl);
  210. }
  211. };
  212. DeepLinker.prototype.getComponentFromName = function (componentName) {
  213. var link = this._serializer.getLinkFromName(componentName);
  214. if (link) {
  215. // cool, we found the right link for this component name
  216. return this.getNavLinkComponent(link);
  217. }
  218. // umm, idk
  219. return Promise.reject("invalid link: " + componentName);
  220. };
  221. DeepLinker.prototype.getNavLinkComponent = function (link) {
  222. if (link.component) {
  223. // sweet, we're already got a component loaded for this link
  224. return Promise.resolve(link.component);
  225. }
  226. if (link.loadChildren) {
  227. // awesome, looks like we'll lazy load this component
  228. // using loadChildren as the URL to request
  229. return this._moduleLoader.load(link.loadChildren).then(function (response) {
  230. link.component = response.component;
  231. return response.component;
  232. });
  233. }
  234. return Promise.reject("invalid link component: " + link.name);
  235. };
  236. /**
  237. * @internal
  238. */
  239. DeepLinker.prototype.resolveComponent = function (component) {
  240. var cfr = this._moduleLoader.getComponentFactoryResolver(component);
  241. if (!cfr) {
  242. cfr = this._baseCfr;
  243. }
  244. return cfr.resolveComponentFactory(component);
  245. };
  246. /**
  247. * @internal
  248. */
  249. DeepLinker.prototype.createUrl = function (navContainer, nameOrComponent, _data, prepareExternalUrl) {
  250. if (prepareExternalUrl === void 0) { prepareExternalUrl = true; }
  251. // create a segment out of just the passed in name
  252. var segment = this._serializer.createSegmentFromName(navContainer, nameOrComponent);
  253. var allSegments = this.getCurrentSegments();
  254. if (segment) {
  255. for (var i = 0; i < allSegments.length; i++) {
  256. if (allSegments[i].navId === navContainer.name || allSegments[i].navId === navContainer.id) {
  257. allSegments[i] = segment;
  258. var url = this._serializer.serialize(allSegments);
  259. return prepareExternalUrl ? this._location.prepareExternalUrl(url) : url;
  260. }
  261. }
  262. }
  263. return '';
  264. };
  265. /**
  266. * Each NavController will call this method when it initializes for
  267. * the first time. This allows each NavController to figure out
  268. * where it lives in the path and load up the correct component.
  269. * @internal
  270. */
  271. DeepLinker.prototype.getSegmentByNavIdOrName = function (navId, name) {
  272. var browserUrl = normalizeUrl(this._location.path());
  273. var segments = this._serializer.parse(browserUrl);
  274. for (var _i = 0, segments_1 = segments; _i < segments_1.length; _i++) {
  275. var segment = segments_1[_i];
  276. if (segment.navId === navId || segment.navId === name) {
  277. return segment;
  278. }
  279. }
  280. return null;
  281. };
  282. /**
  283. * @internal
  284. */
  285. DeepLinker.prototype.initViews = function (segment) {
  286. var _this = this;
  287. var link = this._serializer.getLinkFromName(segment.name);
  288. return this.getNavLinkComponent(link).then(function (component) {
  289. segment.component = component;
  290. var view = new view_controller_1.ViewController(component, segment.data);
  291. view.id = segment.id;
  292. if (util_1.isArray(segment.defaultHistory)) {
  293. return nav_util_1.convertToViews(_this, segment.defaultHistory).then(function (views) {
  294. views.push(view);
  295. return views;
  296. });
  297. }
  298. return [view];
  299. });
  300. };
  301. /**
  302. * @internal
  303. */
  304. DeepLinker.prototype._isBackUrl = function (browserUrl) {
  305. return (browserUrl === this._history[this._history.length - 2]);
  306. };
  307. /**
  308. * @internal
  309. */
  310. DeepLinker.prototype._isCurrentUrl = function (browserUrl) {
  311. return (browserUrl === this._history[this._history.length - 1]);
  312. };
  313. /**
  314. * @internal
  315. */
  316. DeepLinker.prototype._historyPush = function (browserUrl) {
  317. if (!this._isCurrentUrl(browserUrl)) {
  318. this._history.push(browserUrl);
  319. if (this._history.length > 30) {
  320. this._history.shift();
  321. }
  322. }
  323. };
  324. /**
  325. * @internal
  326. */
  327. DeepLinker.prototype._historyPop = function () {
  328. this._history.pop();
  329. if (!this._history.length) {
  330. this._historyPush(this._location.path());
  331. }
  332. };
  333. /**
  334. * @internal
  335. */
  336. DeepLinker.prototype._getTabSelector = function (tab) {
  337. if (util_1.isPresent(tab.tabUrlPath)) {
  338. return tab.tabUrlPath;
  339. }
  340. if (util_1.isPresent(tab.tabTitle)) {
  341. return url_serializer_1.formatUrlPart(tab.tabTitle);
  342. }
  343. return "tab-" + tab.index;
  344. };
  345. /**
  346. * Using the known Path of Segments, walk down all descendents
  347. * from the root NavController and load each NavController according
  348. * to each Segment. This is usually called after a browser URL and
  349. * Path changes and needs to update all NavControllers to match
  350. * the new browser URL. Because the URL is already known, it will
  351. * not update the browser's URL when transitions have completed.
  352. *
  353. * @internal
  354. */
  355. DeepLinker.prototype._loadViewForSegment = function (navContainer, segment, done) {
  356. if (!segment) {
  357. return done(false, false);
  358. }
  359. if (nav_util_1.isTabs(navContainer) || (nav_util_1.isTab(navContainer) && navContainer.parent)) {
  360. var tabs = (nav_util_1.isTabs(navContainer) ? navContainer : navContainer.parent);
  361. var selectedIndex = tabs._getSelectedTabIndex(segment.secondaryId);
  362. var tab = tabs.getByIndex(selectedIndex);
  363. tab._segment = segment;
  364. tabs.select(tab, {
  365. updateUrl: false,
  366. animate: false
  367. }, true);
  368. return done(false, false);
  369. }
  370. var navController = navContainer;
  371. var numViews = navController.length() - 1;
  372. // walk backwards to see if the exact view we want to show here
  373. // is already in the stack that we can just pop back to
  374. for (var i = numViews; i >= 0; i--) {
  375. var viewController = navController.getByIndex(i);
  376. if (viewController && (viewController.id === segment.id || viewController.id === segment.name)) {
  377. // hooray! we've already got a view loaded in the stack
  378. // matching the view they wanted to show
  379. if (i === numViews) {
  380. // this is the last view in the stack and it's the same
  381. // as the segment so there's no change needed
  382. return done(false, false);
  383. }
  384. else {
  385. // it's not the exact view as the end
  386. // let's have this nav go back to this exact view
  387. return navController.popTo(viewController, {
  388. animate: false,
  389. updateUrl: false,
  390. }, done);
  391. }
  392. }
  393. }
  394. // ok, so we don't know about a view that they're navigating to
  395. // so we might as well just call setRoot and make tthe view the first view
  396. // this seems like the least bad option
  397. return navController.setRoot(segment.component || segment.name, segment.data, {
  398. id: segment.id, animate: false, updateUrl: false
  399. }, done);
  400. };
  401. return DeepLinker;
  402. }());
  403. exports.DeepLinker = DeepLinker;
  404. function setupDeepLinker(app, serializer, location, moduleLoader, cfr) {
  405. var deepLinker = new DeepLinker(app, serializer, location, moduleLoader, cfr);
  406. deepLinker.init();
  407. return deepLinker;
  408. }
  409. exports.setupDeepLinker = setupDeepLinker;
  410. function normalizeUrl(browserUrl) {
  411. browserUrl = browserUrl.trim();
  412. if (browserUrl.charAt(0) !== '/') {
  413. // ensure first char is a /
  414. browserUrl = '/' + browserUrl;
  415. }
  416. if (browserUrl.length > 1 && browserUrl.charAt(browserUrl.length - 1) === '/') {
  417. // ensure last char is not a /
  418. browserUrl = browserUrl.substr(0, browserUrl.length - 1);
  419. }
  420. return browserUrl;
  421. }
  422. exports.normalizeUrl = normalizeUrl;
  423. function getNavFromTree(nav, id) {
  424. while (nav) {
  425. if (nav.id === id || nav.name === id) {
  426. return nav;
  427. }
  428. nav = nav.parent;
  429. }
  430. return null;
  431. }
  432. exports.getNavFromTree = getNavFromTree;
  433. });
  434. //# sourceMappingURL=deep-linker.js.map