<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Building a router</title>
<script>
// Put John's template engine code here...
(function () {
// A hash to store our routes:
var routes = {};
// The route registering function:
function route (path, templateId, controller) {
// Allow route(path, controller) for template less routes:
if (typeof templateId === 'function') {
controller = templateId;
templateId = null;
}
routes[path] = {templateId: templateId, controller: controller};
}
var el = null, current = null;
function router () {
// Current route url (getting rid of '#' in hash as well):
var url = location.hash.slice(1) || '/';
// Get route by url:
var route = routes[url];
// Is it a route without template?
if (route && !route.templateId) {
// Just initiate controller:
return route.controller ? new route.controller : null;
}
// Lazy load view element:
el = el || document.getElementById('view');
// Clear existing observer:
if (current) {
Object.unobserve(current.controller, current.render);
current = null;
}
// Do we have both a view and a route?
if (el && route && route.controller) {
// Set current route information:
current = {
controller: new route.controller,
template: tmpl(route.templateId),
render: function () {
// Render route template with John Resig's template engine:
el.innerHTML = this.template(this.controller);
}
};
// Render directly:
current.render();
// And observe for changes:
Object.observe(current.controller, current.render.bind(current));
}
}
// Listen on hash change:
this.addEventListener('hashchange', router);
// Listen on page load:
this.addEventListener('load', router);
// Expose the route register function:
this.route = route;
})();
</script>
<script type="text/html" id="home">
<h1>Router FTW!</h1>
</script>
<script type="text/html" id="template1">
<h1>Page 1: <%= greeting %></h1>
<p><%= moreText %></p>
</script>
<script type="text/html" id="template2">
<h1>Page 2: <%= heading %></h1>
<p>Lorem ipsum...</p>
</script>
</head>
<body>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#/page1">Page 1</a></li>
<li><a href="#/page2">Page 2</a></li>
</ul>
<div id="view"></div>
<script>
route('/', 'home', function () {});
route('/page1', 'template1', function () {
this.greeting = 'Hello world!';
this.moreText = 'Loading...';
// Simulating an Ajax call which take 0.5 s
setTimeout(function () {
this.moreText = 'Bacon ipsum...';
}.bind(this), 500);
});
route('/page2', 'template2', function () {
this.heading = 'I\'m page two!';
});
</script>
</body>
</html>