Skip to content

Instantly share code, notes, and snippets.

@fantactuka
Created March 5, 2014 15:27
Show Gist options
  • Save fantactuka/9369430 to your computer and use it in GitHub Desktop.
Save fantactuka/9369430 to your computer and use it in GitHub Desktop.
var Config = {
'legal-entities/:id': 'entities#show',
'external-contact/current/legal-entities': 'ecEntities#index',
'internal-contact/current/legal-entities': 'icEntities#index',
'outreach-campaigns': 'oc#index',
'outreach-campaigns/new': 'oc#create',
'outreach-campaigns/:id': 'oc#show',
'outreach-campaigns/:id/edit': 'oc#edit',
'outreach-campaigns/:id/legal-entities': 'ocEntities#index'
};
Router.setConfig(Config);
var EcEntitiesRouter = Router.extend({
name: 'ecEntities',
before: {
index: '_checkPermission'
},
index: function() {
// ...
},
_checkPermission: function() {
// ...
}
});
// Overriding constructor to add newly created instance into
// overall registry, that is accessible for direct and reversed routing
var Router = Backbone.Router.extend({
constructor: function() {
var name = this.name || fail('Router requires "name" property to be defined');
if (!routesRegistry[name]) {
routesRegistry[name] = [];
}
routesRegistry[name].push(this);
this.initialize.apply(this, arguments);
}
});
// Router registry that hold all routes instances by its names
var routesRegistry = Router.registry = {},
routeToRegExp = Router.prototype._routeToRegExp;
// Creates url using routes registry for reverse routing
Router.createUrl = function(options) {
var pattern = _.invert(routesRegistry)[options.name] || fail('Unable to find route "%s"', options.name),
params = options.params.slice(),
url = pattern.replace(/:(\w+)/g, function() {
return encodeURIComponent(params.shift()) || '';
});
if (!_.isEmpty(options.query)) {
url += (url.indexOf('?') > -1 ? '&' : '?') + $.param(options.query);
}
return '#' + url;
};
// Parsing static config into route handlers that calls
// routes by its names
Router.setConfig = function(config) {
var patterns = _.keys(config).reverse();
_.each(patterns, function(pattern) {
var routeRegExp = _.isRegExp(pattern) ? pattern : routeToRegExp(pattern),
partials = config[pattern].match(/^(\w*)#(\w*)$/) || fail('Expected handler like "router#action", but received %s', pattern),
name = partials[1],
action = partials[2];
Backbone.history.route(routeRegExp, function(fragment) {
Router.execute(fragment, routeRegExp, name, action);
});
});
};
// Executing route handler if any - looking though instances with passed name
// and executing handler if before filter passed
Router.execute = function(fragment, routeRegExp, name, action) {
var routers = routesRegistry[name];
_.any(routers, function(router) {
var handler = router[action];
if (handler) {
var args = router._extractParameters(routeRegExp, fragment);
if (pass(router, action, fragment, args)) {
handler.apply(router, args);
router.trigger.apply(router, ['route:' + action].concat(args));
router.trigger('route', action, args);
Backbone.history.trigger('route', router, action, args);
}
}
return !!handler;
});
};
function pass(router, action, fragment, args) {
if (!router.before || !router.before[action]) {
return true;
}
var callback = router.before[action];
if (typeof callback === 'string') {
callback = router[callback];
}
return callback.call(router, fragment, args) !== false;
}
function fail(message) {
var args = _.tail(arguments);
throw new Error(message.replace(/%s/g, _.bind(args.shift, args)));
}
Router.createUrl('oc#edit', 100); // => #outreach-campaigns/100/edit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment