route.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. Route = function(router, pathDef, options, group) {
  2. options = options || {};
  3. this.options = options;
  4. this.pathDef = pathDef
  5. // Route.path is deprecated and will be removed in 3.0
  6. this.path = pathDef;
  7. if (options.name) {
  8. this.name = options.name;
  9. }
  10. this._action = options.action || Function.prototype;
  11. this._subscriptions = options.subscriptions || Function.prototype;
  12. this._triggersEnter = options.triggersEnter || [];
  13. this._triggersExit = options.triggersExit || [];
  14. this._subsMap = {};
  15. this._router = router;
  16. this._params = new ReactiveDict();
  17. this._queryParams = new ReactiveDict();
  18. this._routeCloseDep = new Tracker.Dependency();
  19. // tracks the changes in the URL
  20. this._pathChangeDep = new Tracker.Dependency();
  21. this.group = group;
  22. };
  23. Route.prototype.clearSubscriptions = function() {
  24. this._subsMap = {};
  25. };
  26. Route.prototype.register = function(name, sub, options) {
  27. this._subsMap[name] = sub;
  28. };
  29. Route.prototype.getSubscription = function(name) {
  30. return this._subsMap[name];
  31. };
  32. Route.prototype.getAllSubscriptions = function() {
  33. return this._subsMap;
  34. };
  35. Route.prototype.callAction = function(current) {
  36. var self = this;
  37. self._action(current.params, current.queryParams);
  38. };
  39. Route.prototype.callSubscriptions = function(current) {
  40. this.clearSubscriptions();
  41. if (this.group) {
  42. this.group.callSubscriptions(current);
  43. }
  44. this._subscriptions(current.params, current.queryParams);
  45. };
  46. Route.prototype.getRouteName = function() {
  47. this._routeCloseDep.depend();
  48. return this.name;
  49. };
  50. Route.prototype.getParam = function(key) {
  51. this._routeCloseDep.depend();
  52. return this._params.get(key);
  53. };
  54. Route.prototype.getQueryParam = function(key) {
  55. this._routeCloseDep.depend();
  56. return this._queryParams.get(key);
  57. };
  58. Route.prototype.watchPathChange = function() {
  59. this._pathChangeDep.depend();
  60. };
  61. Route.prototype.registerRouteClose = function() {
  62. this._params = new ReactiveDict();
  63. this._queryParams = new ReactiveDict();
  64. this._routeCloseDep.changed();
  65. this._pathChangeDep.changed();
  66. };
  67. Route.prototype.registerRouteChange = function(currentContext, routeChanging) {
  68. // register params
  69. var params = currentContext.params;
  70. this._updateReactiveDict(this._params, params);
  71. // register query params
  72. var queryParams = currentContext.queryParams;
  73. this._updateReactiveDict(this._queryParams, queryParams);
  74. // if the route is changing, we need to defer triggering path changing
  75. // if we did this, old route's path watchers will detect this
  76. // Real issue is, above watcher will get removed with the new route
  77. // So, we don't need to trigger it now
  78. // We are doing it on the route close event. So, if they exists they'll
  79. // get notify that
  80. if(!routeChanging) {
  81. this._pathChangeDep.changed();
  82. }
  83. };
  84. Route.prototype._updateReactiveDict = function(dict, newValues) {
  85. var currentKeys = _.keys(newValues);
  86. var oldKeys = _.keys(dict.keyDeps);
  87. // set new values
  88. // params is an array. So, _.each(params) does not works
  89. // to iterate params
  90. _.each(currentKeys, function(key) {
  91. dict.set(key, newValues[key]);
  92. });
  93. // remove keys which does not exisits here
  94. var removedKeys = _.difference(oldKeys, currentKeys);
  95. _.each(removedKeys, function(key) {
  96. dict.set(key, undefined);
  97. });
  98. };