A really simple Javascript router

<!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>