Created
September 22, 2011 16:51
-
-
Save tbranyen/1235317 to your computer and use it in GitHub Desktop.
backbone.js sub routing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Pretend app setup stuff is here */ | |
/* Kick off app */ | |
jQuery(function($) { | |
var Gallery = app.module("gallery"); | |
app.Router = Backbone.Router.extend({ | |
initialize: function() { | |
this.gallery = new Gallery.Router("gallery/"); | |
} | |
}); | |
// Actually initialize | |
new app.Router(); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(Gallery) { | |
var Helper = app.module("helper"); | |
Gallery.Router = Helper.SubRoute.extend({ | |
routes: { | |
"": "list", | |
"add": "add", | |
"filter": "filter" | |
} | |
}); | |
})(app.module("gallery")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(Helper) { | |
Helper.SubRoute = Backbone.Router.extend({ | |
constructor: function(prefix) { | |
var routes = {}; | |
// Prefix is optional, set to empty string if not passed | |
prefix = prefix || ""; | |
// Allow for optionally omitting trailing /. Since base routes do not | |
// trigger with a trailing / this is actually kind of important =) | |
if (prefix[prefix.length-1] == "/") { | |
prefix = prefix.slice(0, prefix.length-1); | |
// If a prefix exists, add a trailing / | |
} else if (prefix) { | |
prefix += "/"; | |
} | |
// Every route needs to be prefixed | |
_.each(this.routes, function(callback, path) { | |
if (path) { | |
return routes[prefix + path] = callback; | |
} | |
// If the path is "" just set to prefix, this is to comply | |
// with how Backbone expects base paths to look gallery vs gallery/ | |
routes[prefix] = callback; | |
}); | |
// Must override with prefixed routes | |
this.routes = routes; | |
// Required to have Backbone set up routes | |
Backbone.Router.prototype.constructor.call(this); | |
} | |
}); | |
})(app.module("helper")); |
And how to dynamically remove the subroute?
@SamDecrock you can't without manipulating Backbone.history
and allowing your application to have knowledge of all the paths that were added. This can be quite a complex procedure if you haven't built your application with an ability to get paths from individual subroutes. I tend to create wrapping objects that have an activate and deactivate method that are managed by a facade to a Backbone router.
considering that you have a list of paths (allRoutes
in this example).
for (var path in allRoutes) {
var combinedPath = routerPrefix + '/' + path;
// This removes all trace of the routes from the history
Backbone.history.handlers = _.reject(
Backbone.history.handlers, function(value) {
return String.prototype.search.call(
value.route,
combinedPath
) !== -1;
}
);
}
// Unfortunately, we still have a route in the history for the routerPrefix
// (in fact we should have two, the one used by the primary router and
// one created by the sub router (the latter takes precedence as it has
// been unshifted onto the handlers array. The next step therefore is to
// get all the primary routes registered in the history.
var primaryHandlers = _.filter(Backbone.history.handlers, function(value) {
return String.prototype.search.call(value.route, routerPrefix) !== -1;
});
// If the result has a length greater than 1 (this will be the case most of
// the time) then we need to remove the first one that was registered by
// the subrouter, this leaves the primary route still available to start the
// sub router again when it is needed. Else we want to keep the route as
// it was set by the primary router.
if (primaryHandlers.length > 1) {
Backbone.history.handlers.splice(
Backbone.history.handlers.indexOf(primaryHandlers[0])
, 1);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I ended up logging an issue against @geekdave's repo at BackboneSubroute/backbone.subroute#4 - I'm not 100% sure everything is correct (it's a little handwavy, I'm under pressure to get something out the door blahblahblah so I had to move on), but I think that's the gist of things. Hopefully I'll have time to come back to it, if @geekdave isn't able to get to the bottom of it himself.