diff --git a/backbone.js b/backbone.js
index bbc63fdab..3484f8484 100644
--- a/backbone.js
+++ b/backbone.js
@@ -1455,6 +1455,16 @@
// Set up all inheritable **Backbone.Router** properties and methods.
_.extend(Router.prototype, Events, {
+ // If set to true, route handlers will be called with routeData object
+ //
+ // this.route('search/:query/p:num', 'search', function(params, routeData) {
+ // // for route 'search/backbone/p5?a=b'
+ // // params.query === 'backbone'
+ // // params.num === '5'
+ // // routeData.queryString === 'a=b'
+ // });
+ //
+ useParamsObject: false,
// Initialize is an empty function by default. Override it with your own
// initialization logic.
@@ -1467,12 +1477,26 @@
// });
//
route: function(route, name, callback) {
- if (!_.isRegExp(route)) route = this._routeToRegExp(route);
+ // Pass paramNames into _routeToRegExp and let that function populate it
+ var paramNames = [];
+ // Need to know this so we don't try to create params object when the route is matched
+ var isRegExpRoute = _.isRegExp(route);
+
+ if (!isRegExpRoute) route = this._routeToRegExp(route, paramNames);
+
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
+
+ this._routeInfos = this._routeInfos || {};
+ this._routeInfos[route] = {
+ name: name,
+ isRegExpRoute: isRegExpRoute,
+ paramNames: paramNames
+ };
+
var router = this;
Backbone.history.route(route, function(fragment) {
var args = router._extractParameters(route, fragment);
@@ -1511,13 +1535,18 @@
// Convert a route string into a regular expression, suitable for matching
// against the current location hash.
- _routeToRegExp: function(route) {
+ _routeToRegExp: function(route, paramNames) {
route = route.replace(escapeRegExp, '\\$&')
.replace(optionalParam, '(?:$1)?')
.replace(namedParam, function(match, optional) {
- return optional ? match : '([^/?]+)';
+ if (optional) return match;
+ paramNames.push(match.slice(1));
+ return '([^/?]+)';
})
- .replace(splatParam, '([^?]*?)');
+ .replace(splatParam, function(match) {
+ paramNames.push(match.slice(1));
+ return '([^?]*?)';
+ });
return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$');
},
@@ -1526,11 +1555,37 @@
// treated as `null` to normalize cross-browser behavior.
_extractParameters: function(route, fragment) {
var params = route.exec(fragment).slice(1);
- return _.map(params, function(param, i) {
+ var decodedParams = _.map(params, function(param, i) {
// Don't decode the search params.
if (i === params.length - 1) return param || null;
return param ? decodeURIComponent(param) : null;
});
+
+ if (this.useParamsObject) {
+ // get routeInfo, which has array of param names
+ var routeInfo = this._routeInfos[route];
+
+ var routeData = {
+ name: routeInfo.name
+ };
+ var routeParams;
+
+ if (routeInfo.isRegExpRoute) {
+ // if original route is RegExp, everything goes into .params
+ routeParams = decodedParams;
+ }
+ else {
+ routeParams = _.object(routeInfo.paramNames, decodedParams);
+ var queryString = decodedParams[decodedParams.length - 1];
+ if (queryString) {
+ routeData.queryString = queryString;
+ }
+ }
+
+ return [routeParams, routeData];
+ }
+
+ return decodedParams;
}
});
diff --git a/test/index.html b/test/index.html
index 3dad8c679..c632e4171 100644
--- a/test/index.html
+++ b/test/index.html
@@ -18,6 +18,7 @@
+