Routers and App Events
This example demonstrates how Giraffe.Router ties into the appEvents
described in the App Events example.
var App, ChildView;
The App
Giraffe.App is a Giraffe.View that encapsulates an app and its routes. In this example, clicking some links will change the window location hash. The Giraffe.Router responds to this hash change and triggers an event on the app which shows a child view with a specific name.
App = Giraffe.App.extend({
template: '#app-template',
The Giraffe.App#routes
property maps URL routes to appEvents
, and as a result of
defining routes
on the app, it will automatically create an instance of
Giraffe.Router at app.router
. Giraffe.Router is dependent on
Giraffe.App because it uses appEvents
to communicate with your objects.
routes: {
'childView/:name': 'route:childView'
// 'someHashLocation/:andItsParams': 'some:appEvent'
},
routes
hash, but
you can create any number of routers. They do require that a Giraffe.App
exists on the page, and instead of defining routes
on an Giraffe.Router,
you define triggers
, which avoids conflict with Backbone.Router#routes
.
When a route is triggered, its corresponding appEvent
is called. Any
Giraffe object, including the app, can listen for appEvents
. In this
example the app listens to itself for the app event 'route:childView'
, which
is defined in the routes
above, and the 'all'
event, so we can log
everything that happens to appEvents
.
appEvents: {
'route:childView': 'showChildView',
'all': function() { console.log('app event', arguments); }
// 'some:otherRoute': 'someMethodName'
// 'some:otherAppEvent': 'someOtherMethodName'
},
route:
prefix is just a naming convention and is not required.
The handler for 'route:childView'
creates a child view named with the route
parameter, and inserts it into the DOM using the attachTo
method 'html'
,
which replaces anything inside '#child-view-container'
.
showChildView: function(name) {
var childView = new ChildView({name: name});
this.attach(childView, {el: '#child-view-container', method: 'html'});
}
});
Here's the app's template. It has three links to the three child views and a container for the active child view.
<script id="app-template" type="text/template">
<p><a href="#childView/1">show child view 1</a></p>
<p><a href="#childView/2">show child view 2</a></p>
<p><a href="#childView/3">show child view 3</a></p>
<div id="child-view-container"></div>
</script>
The Child View
In this example, we're going to create a child view that simply displays its name and a color.
ChildView = Giraffe.View.extend({
className: 'child-view',
template: '#child-template',
initialize: function(options) {
var color;
if (options.name === '1')
color = '#e99';
else if (options.name === '2')
color = '#9e9';
else
color = '#99e';
this.$el.css('background-color', color);
}
});
<script id="child-template" type="text/template">
<h2>child view <%= name %></h2>
</script>
Loading the App
It's time to create and attach the app.
var app = new App();
app.attachTo('body');
routes
hash could have been passed as an option to the Giraffe.App
constructor.
Almost finished! Let's start Backbone.history to get things rolling.
Backbone.history.start();
The Giraffe.Router has one more trick up its sleeve: it gives you
programmatic control over your routes. The function Giraffe.Router#cause
takes
an appEvent
and optional parameters, navigates to the corresponding route
defined in the router, and then triggers the appEvent
with the parameters.
Here we show child view 1 as the default view by causing its appEvent
.
app.router.cause('route:childView', 1);
Giraffe.Router also provides two utility functions to help you manage
routes, isCaused
and getRoute
. We could have used getRoute
to build our
anchor links in the app template above, but didn't for the sake of familiarity.
No longer must you build route links manually!
console.log(app.router.isCaused('route:childView', 1)); // => true
console.log(app.router.isCaused('route:childView', 2)); // => false
console.log(app.router.isCaused('route:childView')); // => false
console.log(app.router.getRoute('route:childView', 1)); // => '#childView/1'
Try It
var App, ChildView;
App = Giraffe.App.extend({
template: '#app-template',
routes: {
'childView/:name': 'route:childView'
// 'someHashLocation/:andItsParams': 'some:appEvent'
},
appEvents: {
'route:childView': 'showChildView',
'all': function() {
console.log('app event', arguments);
}
// 'some:otherRoute': 'someMethodName'
// 'some:otherAppEvent': 'someOtherMethodName'
},
showChildView: function(name) {
var childView = new ChildView({
name: name
});
this.attach(childView, {
el: '#child-view-container',
method: 'html'
});
}
});
ChildView = Giraffe.View.extend({
className: 'child-view',
template: '#child-template',
initialize: function(options) {
var color;
if (options.name === '1')
color = '#e99';
else if (options.name === '2')
color = '#9e9';
else
color = '#99e';
this.$el.css('background-color', color);
}
});
var app = new App();
app.attachTo('body');
Backbone.history.start();
app.router.cause('route:childView', 1);
console.log(app.router.isCaused('route:childView', 1)); // => true
console.log(app.router.isCaused('route:childView', 2)); // => false
console.log(app.router.isCaused('route:childView')); // => false
console.log(app.router.getRoute('route:childView', 1)); // => '#childView/1'
<!DOCTYPE html>
<html>
<head>
<link rel='stylesheet' type='text/css' href='../css/reset.css' />
<link rel='stylesheet' type='text/css' href='routersandappevents0-style.css' />
</head>
<body>
<script id="app-template" type="text/template">
<p><a href="#childView/1">show child view 1</a></p>
<p><a href="#childView/2">show child view 2</a></p>
<p><a href="#childView/3">show child view 3</a></p>
<div id="child-view-container"></div>
</script>
<script id="child-template" type="text/template">
<h2>child view <%= name %></h2>
</script>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="../backbone.giraffe.js" type="text/javascript"></script>
<script type='text/javascript' src='routersandappevents0-script.js'></script>
</body>
</html>
h2 {
font-size: 24px;
}
.child-view {
position: relative;
padding: 20px;
margin: 20px;
border: 1px dashed #999;
}