RocketChat/Rocket.Chat

View on GitHub
apps/meteor/packages/flow-router/client/route.js

Summary

Maintainability
A
1 hr
Test Coverage
Route = function (router, pathDef, options, group) {
    options = options || {};

    this.options = options;
    this.pathDef = pathDef;

    // Route.path is deprecated and will be removed in 3.0
    this.path = pathDef;

    if (options.name) {
        this.name = options.name;
    }

    this._action = options.action || Function.prototype;
    this._subscriptions = options.subscriptions || Function.prototype;
    this._triggersEnter = options.triggersEnter || [];
    this._triggersExit = options.triggersExit || [];
    this._subsMap = {};
    this._router = router;

    this._params = new ReactiveDict();
    this._queryParams = new ReactiveDict();
    this._routeCloseDep = new Tracker.Dependency();

    // tracks the changes in the URL
    this._pathChangeDep = new Tracker.Dependency();

    this.group = group;
};

Route.prototype.clearSubscriptions = function () {
    this._subsMap = {};
};

Route.prototype.register = function (name, sub, options) {
    this._subsMap[name] = sub;
};

Route.prototype.getSubscription = function (name) {
    return this._subsMap[name];
};

Route.prototype.getAllSubscriptions = function () {
    return this._subsMap;
};

Route.prototype.callAction = function (current) {
    var self = this;
    self._action(current.params, current.queryParams);
};

Route.prototype.callSubscriptions = function (current) {
    this.clearSubscriptions();
    if (this.group) {
        this.group.callSubscriptions(current);
    }

    this._subscriptions(current.params, current.queryParams);
};

Route.prototype.getRouteName = function () {
    this._routeCloseDep.depend();
    return this.name;
};

Route.prototype.getParam = function (key) {
    this._routeCloseDep.depend();
    return this._params.get(key);
};

Route.prototype.getQueryParam = function (key) {
    this._routeCloseDep.depend();
    return this._queryParams.get(key);
};

Route.prototype.watchPathChange = function () {
    this._pathChangeDep.depend();
};

Route.prototype.registerRouteClose = function () {
    this._params = new ReactiveDict();
    this._queryParams = new ReactiveDict();
    this._routeCloseDep.changed();
    this._pathChangeDep.changed();
};

Route.prototype.registerRouteChange = function (currentContext, routeChanging) {
    // register params
    var params = currentContext.params;
    this._updateReactiveDict(this._params, params);

    // register query params
    var queryParams = currentContext.queryParams;
    this._updateReactiveDict(this._queryParams, queryParams);

    // if the route is changing, we need to defer triggering path changing
    // if we did this, old route's path watchers will detect this
    // Real issue is, above watcher will get removed with the new route
    // So, we don't need to trigger it now
    // We are doing it on the route close event. So, if they exists they'll
    // get notify that
    if (!routeChanging) {
        this._pathChangeDep.changed();
    }
};

Route.prototype._updateReactiveDict = function (dict, newValues) {
    var currentKeys = _.keys(newValues);
    var oldKeys = _.keys(dict.keyDeps);

    // set new values
    //  params is an array. So, _.each(params) does not works
    //  to iterate params
    _.each(currentKeys, function (key) {
        dict.set(key, newValues[key]);
    });

    // remove keys which does not exisits here
    var removedKeys = _.difference(oldKeys, currentKeys);
    _.each(removedKeys, function (key) {
        dict.set(key, undefined);
    });
};