src/backbone_modules/router.js   A
last analyzed

Complexity

Total Complexity 23
Complexity/F 1.92

Size

Lines of Code 131
Function Count 12

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 0
c 2
b 0
f 0
nc 8
dl 0
loc 131
rs 10
wmc 23
mnd 1
bc 21
fnc 12
bpm 1.75
cpm 1.9166
noi 3

9 Functions

Rating   Name   Duplication   Size   Complexity  
A _.extend.navigate 0 4 1
A _.extend.preinitialize 0 1 1
A router.js ➔ Router 0 9 2
A _.extend.initialize 0 1 1
A _.extend.execute 0 5 2
B _.extend.route 0 23 4
A _.extend._routeToRegExp 0 9 1
A _.extend._bindRoutes 0 10 3
A _.extend._extractParameters 0 10 1
1
import $ from 'jquery';
0 ignored issues
show
introduced by
Definition for rule 'keyword-spacing' was not found
Loading history...
2
import _ from 'underscore';
3
import {
4
  Backbone
5
} from './core.js';
6
import {
7
  Events
8
} from './events.js';
9
10
// Backbone.Router
11
// ---------------
12
13
// Routers map faux-URLs to actions, and fire events when routes are
14
// matched. Creating a new one sets its `routes` hash, if not set statically.
15
var Router = function (options) {
16
  options = options || {};
17
  this.preinitialize.apply(this, arguments);
18
  if (options.routes) {
19
    this.routes = options.routes;
20
  }
21
  this._bindRoutes();
22
  this.initialize.apply(this, arguments);
23
};
24
25
// Cached regular expressions for matching named param parts and splatted
26
// parts of route strings.
27
var optionalParam = /\((.*?)\)/g;
28
var namedParam = /(\(\?)?:\w+/g;
29
var splatParam = /\*\w+/g;
30
var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
31
32
// Set up all inheritable **Backbone.Router** properties and methods.
33
_.extend(Router.prototype, Events, {
34
35
  // preinitialize is an empty function by default. You can override it with a function
36
  // or object.  preinitialize will run before any instantiation logic is run in the Router.
37
  preinitialize: function () {},
38
39
  // Initialize is an empty function by default. Override it with your own
40
  // initialization logic.
41
  initialize: function () {},
42
43
  // Manually bind a single named route to a callback. For example:
44
  //
45
  //     this.route('search/:query/p:num', 'search', function(query, num) {
46
  //       ...
47
  //     });
48
  //
49
  route: function (route, name, callback) {
50
    if (!_.isRegExp(route)) {
51
      route = this._routeToRegExp(route);
52
    }
53
    if (_.isFunction(name)) {
54
      callback = name;
55
      name = '';
56
    }
57
    if (!callback) {
58
      callback = this[name];
59
    }
60
    var router = this;
0 ignored issues
show
introduced by
Unexpected alias 'router' for 'this'.
Loading history...
61
    Backbone.history.route(route, function (fragment) {
62
      var args = router._extractParameters(route, fragment);
63
      if (router.execute(callback, args, name) !== false) {
64
        router.trigger.apply(router, ['route:' + name].concat(
65
          args));
66
        router.trigger('route', name, args);
67
        Backbone.history.trigger('route', router, name, args);
68
      }
69
    });
70
    return this;
71
  },
72
73
  // Execute a route handler with the provided parameters.  This is an
74
  // excellent place to do pre-route setup or post-route cleanup.
75
  execute: function (callback, args, name) {
0 ignored issues
show
Unused Code introduced by
The parameter name is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
76
    if (callback) {
77
      callback.apply(this, args);
78
    }
79
  },
80
81
  // Simple proxy to `Backbone.history` to save a fragment into the history.
82
  navigate: function (fragment, options) {
83
    Backbone.history.navigate(fragment, options);
84
    return this;
85
  },
86
87
  // Bind all defined routes to `Backbone.history`. We have to reverse the
88
  // order of the routes here to support behavior where the most general
89
  // routes can be defined at the bottom of the route map.
90
  _bindRoutes: function () {
91
    if (!this.routes) {
92
      return;
93
    }
94
    this.routes = _.result(this, 'routes');
95
    var route, routes = _.keys(this.routes);
96
    while ((route = routes.pop()) != null) {
97
      this.route(route, this.routes[route]);
98
    }
99
  },
100
101
  // Convert a route string into a regular expression, suitable for matching
102
  // against the current location hash.
103
  _routeToRegExp: function (route) {
104
    route = route.replace(escapeRegExp, '\\$&')
105
      .replace(optionalParam, '(?:$1)?')
106
      .replace(namedParam, function (match, optional) {
107
        return optional ? match : '([^/?]+)';
108
      })
109
      .replace(splatParam, '([^?]*?)');
110
    return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
111
  },
112
113
  // Given a route, and a URL fragment that it matches, return the array of
114
  // extracted decoded parameters. Empty or unmatched parameters will be
115
  // treated as `null` to normalize cross-browser behavior.
116
  _extractParameters: function (route, fragment) {
117
    var params = route.exec(fragment).slice(1);
118
    return _.map(params, function (param, i) {
119
      // Don't decode the search params.
120
      if (i === params.length - 1) {
121
        return param || null;
122
      }
123
      return param ? decodeURIComponent(param) : null;
124
    });
125
  }
126
127
});
128
129
export {
130
  Router
131
};
132