Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added optional groups to route syntax, with tests #1509

Merged
merged 2 commits into from Oct 3, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion backbone.js
Expand Up @@ -894,9 +894,10 @@

// Cached regular expressions for matching named param parts and splatted
// parts of route strings.
var optionalParam = /\((.*?)\)/g;
var namedParam = /:\w+/g;
var splatParam = /\*\w+/g;
var escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g;
var escapeRegExp = /[-{}[\]+?.,\\^$|#\s]/g;

// Set up all inheritable **Backbone.Router** properties and methods.
_.extend(Router.prototype, Events, {
Expand Down Expand Up @@ -947,6 +948,7 @@
// against the current location hash.
_routeToRegExp: function(route) {
route = route.replace(escapeRegExp, '\\$&')
.replace(optionalParam, '(?:$1)?')
.replace(namedParam, '([^\/]+)')
.replace(splatParam, '(.*?)');
return new RegExp('^' + route + '$');
Expand Down
20 changes: 16 additions & 4 deletions index.html
Expand Up @@ -1931,15 +1931,27 @@ <h2 id="Router">Backbone.Router</h2>
similar to the <a href="#View">View</a>'s <a href="#View-delegateEvents">events hash</a>.
Routes can contain parameter parts, <tt>:param</tt>, which match a single URL
component between slashes; and splat parts <tt>*splat</tt>, which can match
any number of URL components.
any number of URL components. Part of a route can be made optional by
surrounding it in parentheses <tt>(/:optional)</tt>.
</p>

<p>
For example, a route of <tt>"search/:query/p:page"</tt> will match
a fragment of <tt>#search/obama/p2</tt>, passing <tt>"obama"</tt>
and <tt>"2"</tt> to the action. A route of <tt>"file/*path"</tt> will
match <tt>#file/nested/folder/file.txt</tt>,
passing <tt>"nested/folder/file.txt"</tt> to the action.
and <tt>"2"</tt> to the action.
</p>

<p>
A route of <tt>"file/*path"</tt> will match
<tt>#file/nested/folder/file.txt</tt>, passing
<tt>"nested/folder/file.txt"</tt> to the action.
</p>

<p>
A route of <tt>"docs/:section(/:subsection)"</tt> will match
<tt>#docs/faq</tt> and <tt>#docs/faq/installing</tt>, passing
<tt>"faq"</tt> to the action in the first case, and passing <tt>"faq"</tt>
and <tt>"installing"</tt> to the action in the second.
</p>

<p>
Expand Down
14 changes: 14 additions & 0 deletions test/router.js
Expand Up @@ -69,6 +69,7 @@ $(document).ready(function() {
"contacts": "contacts",
"contacts/new": "newContact",
"contacts/:id": "loadContact",
"optional(/:item)": "optionalItem",
"splat/*args/end": "splat",
"*first/complex-:part/*rest": "complex",
":entity?*args": "query",
Expand Down Expand Up @@ -105,6 +106,10 @@ $(document).ready(function() {
this.contact = 'load';
},

optionalItem: function(arg){
this.arg = arg !== undefined ? arg : null;
},

splat : function(args) {
this.args = args;
},
Expand Down Expand Up @@ -199,6 +204,15 @@ $(document).ready(function() {
equal(router.args, 'long-list/of/splatted_99args');
});

test("routes (optional)", 2, function() {
location.replace('http://example.com#optional');
Backbone.history.checkUrl();
equal(router.arg, null);
location.replace('http://example.com#optional/thing');
Backbone.history.checkUrl();
equal(router.arg, 'thing');
});

test("routes (complex)", 3, function() {
location.replace('http://example.com#one/two/three/complex-part/four/five/six/seven');
Backbone.history.checkUrl();
Expand Down