S R T B H P N

StoryTeller Design


Concept:

Figure 1. StoryTeller_LocalStorage UI
A story is an ordered collection of content from a website, relevant to a specific theme, e.g., C++. Its purpose is to provide: StoryTeller is a mechanism for choosing one of several stories and manually stepping through its content.

Design:

We will discuss four views of the design: UI, activities, call graph, and a JavaScript code fragment.

StoryTeller User Interface (UI)

The UI consists of a static web page with an embedded iframe. The iframe, shown in the top left quadrant of Fig 1., displays story content. Buttons on the right are used for navigation through the story timeline, and header and footer provide information that helps user navigation.
Figure 2. StoryTeller_LocalStorage Activities

StoryTeller Activities:

When the StoryTeller loads the initialization process is triggered by the end of browser document parsing. That results in a list of available stories being loaded into the iframe. We will see how that is done in the next section. Nothing happens until the user selects a story. When its storyTOC loads, JavaScript analyzes its own content and writes relevant information into local storage, e.g., the url, name, and page note text for each link on the page - one link per story page. When storyTOC loading completes, the information has been saved in localStorage and the iframe's onLoad event fires, calling StoryTeller's srcChange() function. StoryTeller reads story information out of localStorage and builds an array of JavaScript page objects. Each page object has attributes for page url, used to load the page, page name, used to build a Table Of Contents (TOC), and page notes text, used to supply additional information should the user click the [?] button. When a user clicks next, prev, ... buttons the button listeners process the information, usually by calling render to display a new page. For example, next() adds 1 to curr, the page index, and calls render to display the next page. That continues until the user clicks the [Exit] button.
Figure 3. StoryTeller_LocalStorage Call Graph

StoryTeller Call Graph:

The call graph, shown in Fig 3., demonstrates how that works. Processing starts with:
  • initialize() adds event listeners for key presses, then calls render(0), which loads the StoryList.
  • When the user selects a story link, that changes the iframe document which loads a storyTOC page. Its JavaScript evaluates its own content with getContent() and save()s it to localStorage. When the storyTOC page loading is complete, that invokes the srcChange() function when the iframe onLoad event is fired.
  • srcChange(), if key "saveStory" is in local storage, calls retrieve to read story information from localStorage. Otherwise it does nothing except return.
  • retrieve() reads localStorage, builds the pages array, and calls loadTOC() to build the table of contents. It then calls render(1) to show the first story page. finally, it clears localStorage so that key "saveStory" is no longer there.
  • render(index), if index = 0, it is rendering the StoryList, so it clears pages array and localStorage and loads the StoryList into the iframe. If index > 0, retrieve has already been called, so it loads the page url into the iframe, which displays pages[index-1].url.
Figure 4. Javascript Fragment

JavaScript Code Fragment:

Finally, a note about the structure of StoryTeller's JavaScript. This github site has been accumulating a lot of JavaScript libraries, so variable and function name collisions started to happen. To handle that, all of the more recent libraries define a JavaScript object for that specific library. For StoryTeller, the object shown in Fig 4. was defined. All of the data needed by many of the functions and all of the functions are defined as properties of the storyTeller object. Now, the code uses things like storyTeller.render(index). For variables and functions that are used many times in a single function, we can define an alias variable, e.g., let rend = storyTeller.render, and then simply invoke rend(index);