Browse Source

Working router with onhashchange handling.

Frederic G. MARAND 8 years ago
parent
commit
8aefae76f8
2 changed files with 62 additions and 22 deletions
  1. 2 1
      assignment.js
  2. 60 21
      routing.js

+ 2 - 1
assignment.js

@@ -14,14 +14,15 @@ const loadCount = templateNames.length + partialNames.length;
 
 var templates = {};
 var contentElement = document.getElementById("content");
+var ready = false;
 
 function checkLoad(target) {
   if (Object.keys(templates).length === loadCount) {
+    ready = true;
     target.dispatchEvent(new Event(EVENT_TEMPLATES_LOADED));
   }
 }
 
-
 templateNames.forEach(function (name) {
   const path = "templates/" + name + ".hbs";
 

+ 60 - 21
routing.js

@@ -2,7 +2,7 @@
  * @file
  *   Contains the router code and route definitions
  *
- * Inspired by Joakim Beng's example.
+ * Inspired by Joakim Beng"s example.
  *
  * @see http://joakim.beng.se/blog/posts/a-javascript-router-in-20-lines.html
  */
@@ -11,59 +11,98 @@
 // The routes object.
 var routes = {};
 
-// The route registering function:
+// The route registering function.
 function route(path, controller) {
   routes[path] = controller;
 }
 
-// The router.
+/**
+ * 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 CurrentRoute = routes[url];
 
   var context = null;
+  var listener = null;
   var templateName = null;
 
-  // Do we have both a view and a route ?
-  if (contentElement) {
-    if (currentRoute) {
-      // Render route template with Handlebars:
-      context = new currentRoute();
-      templateName = (url === "/") ? "home" : url;
-
-      contentElement.addEventListener(EVENT_TEMPLATES_LOADED, function () {
-        console.log('templates', templates, 'name', url, templateName);
-        contentElement.innerHTML = templates[templateName](context);
-      });
+  // 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.warn("Content found but no route matching", url);
+      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 not found.");
+    console.warn("Content found but no route matching", url);
   }
 }
 
 // Bind router to browser events.
-// window.addEventListener("hashchange", router);
+window.addEventListener("hashchange", router);
 window.addEventListener("load", router);
 
 // Route declarations.
 route("/", function () {
-  console.log('Home controller');
+  console.log("Home controller");
 });
 
 route("class", function () {
-  console.log('Class controller');
+  console.log("Class controller");
   this.greeting = "Hello world!";
   this.moreText = "Bacon ipsum...";
 });
 
 route("species", function () {
-  console.log('Species controller');
+  console.log("Species controller");
   this.heading = "I\"m page two!";
 });