/** * @file * Contains the router code and route definitions * * Inspired by Joakim Beng"s example. * * @see http://joakim.beng.se/blog/posts/a-javascript-router-in-20-lines.html */ // The routes object. var routes = {}; // The route registering function. function route(path, controller) { routes[path] = controller; } /** * Set the target content to the template result. * * Use only if global "ready" is true, otherwise global "templates" may not be * entirely initialized. * * @param {DOMElement} target * The element in which to inject the template output. * @param {string} name * The name of the template to render. * @param {Object} context * The template context. * * @returns {void} * * @globals templates */ function render(target, name, context) { var output = null; var template = templates[name]; if (!template) { console.error("Template not found", name); return; } output = template(context); target.innerHTML = output; } /** * The router. * * @returns {void} * * @globals contentElement, ready, EVENT_TEMPLATES_LOADED */ function router() { // Current route url (getting rid of "#" in hash as well): var url = location.hash.slice(1) || "/"; // Get route by url: var CurrentRoute = routes[url]; var context = null; var listener = null; var templateName = null; // Do we have a route ? if (CurrentRoute) { // Render route template with Handlebars: context = new CurrentRoute(); templateName = (url === "/") ? "home" : url; if (ready) { console.log('Immediate render'); render(contentElement, templateName, context); } else { console.log('Deferred render'); listener = contentElement.addEventListener(EVENT_TEMPLATES_LOADED, function () { render(contentElement, templateName, context); contentElement.removeEventListener(EVENT_TEMPLATES_LOADED, listener); }); } } else { console.warn("Content found but no route matching", url); } } // Bind router to browser events. window.addEventListener("hashchange", router); window.addEventListener("load", router); // Route declarations. route("/", function () { console.log("Home controller"); }); route("class", function () { console.log("Class controller"); this.greeting = "Hello world!"; this.moreText = "Bacon ipsum..."; }); route("species", function () { console.log("Species controller"); this.heading = "I\"m page two!"; });