<!DOCTYPE html> <!-- Joakim Beng's simple client-side routing example, with John Resig's simple router @see http://joakim.beng.se/blog/posts/a-javascript-router-in-20-lines.html @see http://ejohn.org/blog/javascript-micro-templating/ --> <html> <head> <meta charset="utf-8"> <title>Building a router</title> <script type="text/ecmascript"> // Simple JavaScript Templating // John Resig - http://ejohn.org/ - MIT Licensed (function () { var cache = {}; this.tmpl = function tmpl(str, data) { // Figure out if we're getting a template, or if we need to // load the template - and be sure to cache the result. var fn = !/\W/.test(str) ? cache[str] = cache[str] || tmpl(document.getElementById(str).innerHTML) : // Generate a reusable function that will serve as a template // generator (and which will be cached). new Function("obj", "var p=[],print=function(){p.push.apply(p,arguments);};" + // Introduce the data as local variables using with(){} "with(obj){p.push('" + // Convert the template into pure JavaScript str .replace(/[\r\t\n]/g, " ") .split("<%").join("\t") .replace(/((^|%>)[^\t]*)'/g, "$1\r") .replace(/\t=(.*?)%>/g, "',$1,'") .split("\t").join("');") .split("%>").join("p.push('") .split("\r").join("\\'") + "');}return p.join('');"); // Provide some basic currying to the user return data ? fn(data) : fn; }; })(); </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> <script type="text/ecmascript" id="routing"> // A hash to store our routes: var routes = {}; // The route registering function: function route(path, templateId, controller) { routes[path] = { templateId: templateId, controller: controller }; } // Now declare the routes. route('/', 'home', function () { }); route('/page1', 'template1', function () { this.greeting = 'Hello world!'; this.moreText = 'Bacon ipsum...'; }); route('/page2', 'template2', function () { this.heading = 'I\'m page two!'; }); // The router. var el = null; function router () { // Lazy load view element: el = el || document.getElementById('view'); // Current route url (getting rid of '#' in hash as well): var url = location.hash.slice(1) || '/'; // Get route by url: var route = routes[url]; // Do we have both a view and a route? if (el && route && route.controller) { // Render route template with John Resig's template engine: el.innerHTML = tmpl(route.templateId, new route.controller()); } } // Listen on hash change: window.addEventListener('hashchange', router); // Listen on page load: window.addEventListener('load', router); </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> </body> </html>