4 Commits 6433b35cf5 ... db7c6e76ea

Author SHA1 Message Date
  Mathieu Lirzin db7c6e76ea main: Remove 'Main_component' class 6 years ago
  Mathieu Lirzin 35b2928774 main: Always display hash when handling "load-page" messages 6 years ago
  Mathieu Lirzin 51c3bcf1f0 utils: Add more information in 'navigation_links' docstring 6 years ago
  Mathieu Lirzin e45bc77c06 utils: Avoid conversion from NodeList to Array in 'navigation_links' 6 years ago
3 changed files with 52 additions and 56 deletions
  1. 33 35
      js/src/main.js
  2. 4 10
      js/src/sidebar.js
  3. 15 11
      js/src/utils.js

+ 33 - 35
js/src/main.js

@@ -27,8 +27,28 @@ import { navigation_links } from "./utils";
 
 /* Global state manager.  */
 let store;
-/* Main stateful view.   */
-let components;
+
+/* Aggregation of all the components.   */
+let components = {
+  element: null,
+  components: [],
+
+  register (id, component)
+  {
+    if (this.element === null)
+      throw new Error ("element property must be set first");
+
+    this[id] = component;
+    this.components.push (component);
+    if (component.element)
+      this.element.appendChild (component.element);
+  },
+
+  render (state)
+  {
+    this.components.forEach (cmpt => cmpt.render (state));
+  }
+};
 
 export class
 Selected_div
@@ -39,46 +59,21 @@ Selected_div
     this.element = null;
   }
 
-  render (id)
+  render (state)
   {
-    if (id === this.id)
+    if (state.current === this.id)
       return;
 
     if (this.element)
       this.element.setAttribute ("hidden", "true");
-    let div = document.getElementById (id);
+    let div = document.getElementById (state.current);
     div.removeAttribute ("hidden");
 
-    this.id = id;
+    this.id = state.current;
     this.element = div;
   }
 }
 
-export class
-Main_component
-{
-  constructor (root, index_div)
-  {
-    let sidebar = new Sidebar ();
-    root.appendChild (sidebar.element);
-    let pages = new Pages (index_div);
-    root.appendChild (pages.element);
-
-    /* Root DOM element.  */
-    this.root = root;
-    /* Instance of a Sidebar object.  */
-    this.sidebar = sidebar;
-    /* Currently visible page.  */
-    this.selected_div = new Selected_div ();
-  }
-
-  render (state)
-  {
-    this.sidebar.render ({ current: config.INDEX_ID, visible: true });
-    this.selected_div.render (state.current);
-  }
-}
-
 /*------------------------------------------------
 | Auxilary functions for the top-level context.  |
 `-----------------------------------------------*/
@@ -98,7 +93,8 @@ split_id_anchor (node_name)
     }
 }
 
-/* Load URL in the corresponding iframe.  */
+/* Load URL in its corresponding iframe and make this iframe visible.  Display
+   HASH in the url bar.  */
 function
 load_page (url, hash)
 {
@@ -130,7 +126,6 @@ load_page (url, hash)
       iframe.contentWindow.postMessage (msg, "*");
     }
 
-  components.sidebar.selected_node = node_name;
   window.history.pushState ("", document.title, path);
   store.dispatch (actions.set_current_url (node_name));
 }
@@ -150,7 +145,10 @@ on_load ()
     index_div.appendChild (ch);
 
   /* Instanciate the components.  */
-  components = new Main_component (document.body, index_div);
+  components.element = document.body;
+  components.register ("sidebar", new Sidebar ());
+  components.register ("selected_div", new Selected_div ());
+  components.register ("pages", new Pages (index_div));
 
   let initial_state = {
     /* Dictionary associating page ids to next, prev, up, forward,
@@ -218,7 +216,7 @@ on_message (event)
           let ids = store.state.loaded_nodes[store.state.current];
           let link_id = ids[data.nav];
           if (link_id)
-            load_page (link_id + ".xhtml", "");
+            load_page (link_id + ".xhtml", "#" + link_id);
         }
         break;
       }

+ 4 - 10
js/src/sidebar.js

@@ -63,19 +63,13 @@ Sidebar
   {
     if (state.current !== this.state.current)
       {
+        /* Update sidebar to highlight the title corresponding to
+           'state.current'.  */
+        let iframe = this.element.querySelector ("iframe");
         let msg = { message_kind: "update-sidebar", selected: state.current };
-        this.element.contentWindow.postMessage (msg, "*");
+        iframe.contentWindow.postMessage (msg, "*");
       }
   }
-
-  /* Update sidebar to highligh NODE_NAME which must be a string
-     identifying */
-  set selected_node (node_name)
-  {
-    let iframe = this.element.querySelector ("iframe");
-    let msg = { message_kind: "update-sidebar", selected: node_name };
-    iframe.contentWindow.postMessage (msg, "*");
-  }
 }
 
 /*----------------------------------------------

+ 15 - 11
js/src/utils.js

@@ -66,21 +66,25 @@ href_hash (href)
   return href.replace (/.*#/, "");
 }
 
-/** Retrieve PREV, NEXT, and UP links and Return a object containing
-    references to those links.  */
+/** Retrieve PREV, NEXT, and UP links from CONTENT and Return an object
+    containing references to those links.  CONTENT must be an object
+    implementing the ParentNode interface (Element, Document...).  */
 export function
 navigation_links (content)
 {
-  let links = Array.from (content.querySelectorAll ("footer a"));
-
+  let links = content.querySelectorAll ("footer a");
+  let res = {};
   /* links have the form MAIN_FILE.html#FRAME-ID.  For convenience
-     we only store FRAME-ID.  */
-  return links.reduce ((acc, link) => {
-    let nav_id = navigation_links.dict[link.getAttribute ("accesskey")];
-    if (nav_id)
-      acc[nav_id] = href_hash (link.getAttribute ("href"));
-    return acc;
-  }, {});
+     only store FRAME-ID.  */
+  for (let i = 0; i < links.length; i += 1)
+    {
+      let link = links[i];
+      let nav_id = navigation_links.dict[link.getAttribute ("accesskey")];
+      if (nav_id)
+        res[nav_id] = href_hash (link.getAttribute ("href"));
+    }
+
+  return res;
 }
 
 /* Dictionary associating an 'accesskey' property to its navigation id.  */