// backbone-subroute.js v0.4.0 // // Copyright (C) 2012 Dave Cadwallader, Model N, Inc. // Distributed under the MIT License // // Documentation and full license available at: // https://github.com/ModelN/backbone.subroute (function (factory) { if (typeof define === 'function' && define.amd) { // Register as an AMD module if available... define(['underscore', 'backbone'], factory); } else { // Browser globals for the unenlightened... factory(_, Backbone); } }(function(_, Backbone){ Backbone.SubRoute = Backbone.Router.extend( { constructor:function ( prefix, options ) { // Prefix is optional, set to empty string if not passed this.prefix = prefix = prefix || ""; // SubRoute instances may be instantiated using a prefix with or without a trailing slash. // If the prefix does *not* have a trailing slash, we need to insert a slash as a separator // between the prefix and the sub-route path for each route that we register with Backbone. this.separator = ( prefix.slice( -1 ) === "/" ) ? "" : "/"; // if you want to match "books" and "books/" without creating separate routes, set this // option to "true" and the sub-router will automatically create those routes for you. this.createTrailingSlashRoutes = options && options.createTrailingSlashRoutes; // Required to have Backbone set up routes Backbone.Router.prototype.constructor.call( this, options ); // grab the full URL var hash; if (Backbone.history.fragment) { hash = Backbone.history.getFragment(); } else { hash = Backbone.history.getHash(); } // Trigger the subroute immediately. this supports the case where // a user directly navigates to a URL with a subroute on the first page load. // Check every element, if one matches, break. Prevent multiple matches _.every(this.routes, function(key, route){ // Use the Backbone parser to turn route into regex for matching if(hash.match(Backbone.Router.prototype._routeToRegExp(route))) { Backbone.history.loadUrl(hash); return false; } return true; }, this); if (this.postInitialize) { this.postInitialize(options); } }, navigate:function ( route, options ) { if ( route.substr( 0, 1 ) != '/' && route.indexOf( this.prefix.substr( 0, this.prefix.length - 1 ) ) !== 0 ) { route = this.prefix + ( route ? this.separator : "") + route; } Backbone.Router.prototype.navigate.call( this, route, options ); }, route : function (route, name, callback) { // strip off any leading slashes in the sub-route path, // since we already handle inserting them when needed. if (route.substr(0) === "/") { route = route.substr(1, route.length); } var _route = this.prefix; if (route && route.length > 0) _route += (this.separator + route); if (this.createTrailingSlashRoutes) { this.routes[_route + '/'] = name; Backbone.Router.prototype.route.call(this, _route + '/', name, callback); } // Adding this mainly to support the specs, and for debug-ability. We're altering the way the router // handles routing, but not updating the actual routes hash. Might seem weird to anyone trying to // debug a routing issue. this.routes[_route] = name; return Backbone.Router.prototype.route.call(this, _route, name, callback); } } ); return Backbone.SubRoute; }));