Login

Responsive Resume Project - User Interface

Note, this article is part of series (see here). In our last installment we looked at data structures. In this installment we will look at basic processes and architecture.

Our immediate goal is to get a working model up and running as quickly as possible. A working model is also know as a demonstration release (AKA alpha release). Typically a working model is partial implementation. We implement the crucial "must have" functions.

In the prior installment we created enough data to render a small grid (2 rows, 2 columns, 2 row_columns). However, we hard coded the content. Therefore, we need to implement a user interface. An interface that allows the user to create content. To create content, the user starts by adding the first row to the resume document.

Planning the user interface for simple functions such as "add a row" or "add a column" requires us to elaborate our definitions. Sometimes a definition has "implied" requirements. Sometimes a definition has ambiguities. The following statements demonstrate how we remove ambiguities and specify "implied rules". Note! The writing style for "requirement definitions" is a little unusual. We over state requirements on purpose.

  • Each row has 2 distinct values. An id (a unique identifier). A location (the vertical position of the row).
    • The user identifies a row by it's location.
    • The application identifies a row by it's id.
    • The row id is an internal identifier. The row id id not display in the user interface.
    • The row location is a public identified. The row location is displayed in the user interface.
  • A row location is always incremented by one. The first row location is a value of zero, The first row location positions the row at the top of the resume document.
  • When a user "adds" a row, the applications determines the maximum row location value and then increments the maximum row location by 1.
  • When a user "adds" a row, the application always adds the row to the bottom of the document.
  • A row can never have zero columns. Therefore, when a user adds a row, the application always populates the new row with at least one column.

Let's start with "add a new row". Per the rules above, the application must determine the last (maximum) row location. Two strategies come to mind: 1) We store the last row location as a property. 2) We iterate through the list of rows and compare row locations, deriving the "last" row location. I choose the second option. Here is a sample implementation:

    this.getLastRowLocation = function() {
        var len = this.list.length;
        var last =0;
        var elem = null;
        for (var nIndex =0; nIndex < len; nIndex++) {
            elem = this.list[nIndex];
            if (elem.getLocation()> last) {
                last = elem.getLocation();
            }
        }
        return last;
    };

Sequential Processing and JavaScript

The only thing to note in the above code segment is the declaration of our var "nIndex". JavaScript by default does not process statements sequentially. If "nIndex" was declared outside of the for loop, the JavaScript engine would not execute the statements in order. If there were 5 rows in our list, the Javascript engine would first increment nIndex till it's value is 4. After nIndex is assigned a value of 4, then the Javscript engine executes "elem = this.list[Index]". Thus, our list would not be iterated through as expected.

We have to declare "nIndex" inside the for loop. That forces the JavaScript engine to iterate through the list as expected.

The user interface for "add a row" is simply a menu item. In other words, the function is invoked by the user clicking on a menu item. Either a menu item the application always displays, or a "drop down" menu item the use must navigate too (before the application displays it).

Since we are now talking about html markup, lets discuss the basic user interface architecture.

Single Page Application
Our application is going include one single html web page.

This project is a learning tool. The single page architecture is not really necessary for our "responsive resume publisher" application. However, the single page architecture is an important optimization strategy for mobile web apps. When you transition to a second page, a second instance of the JavaScript engine must be loaded by the browser. That's a costly operation on many mobile devices.

To summarize, our menus, dialogues ,controls and resume work area will reside on one single web page (html document). We will either generate and remove elements as needed, or, we'll toggle elements between hidden and shown.

Menus, Dialogs and Event Listeners

One of the internal design decisions we have make regards Document Object Model (DOM) event listeners. Logically we want the user to be able to click on a row_column (cell) and invoke edit dialog. That means we need a JavaScript function listens for a "click" event. Two strategies come to mind:

1) Add a dedicated event listener to each row_column. Since the event listener is associated with a specific row_column, we are spared the tasking of determining which row_column the usee wants to edit. Folks who use JavaScript Model View Controller (MVC) frameworks like Backbone.js tend to associate event listeners with the "model". The model represents data, so if we adopted that pattern, our click listener would be a property of our row_column

2) Add one single click listener that filters click events that occur on certain elements (I.E. row_columns). In this pattern, we need to determine which row_column was clicked.

When to two patterns we have another issue to consider. Our user has the ability to delete row_columns. That means if use pattern 1, we have to makes sure were deleting listeners along with the data.

This would be great place to set up a performance test and see if either pattern/strategy has a performance benefit. I am going to pick strategy/pattern 2. Only because pattern 2 seems less work to implement, less testing, etc. Thus, my guess is, implementing a single click listener cost less in development time. Later in the project, we may revist this decision.

Updating the page display.
Out next decision concerns how render changes to our page display.

In our current grid.render() method, we dynamically create the html elements that house our data. In other words, the html markup (and css rules) are stored in the application html page document. The JavaScript application generates the html markup when a request is made to render the document.

The prime task of our application is to custom resume documents. Each document may vary in number of rows, columns and css style rules. The resume document (as it's worked on by the resume writer), is in essence dynamic.

Our current task to construct or menus and dialogues. The application's menus and dialogues is relatively static. As we build the application, we might add our change a menu item. However, each user is going to have access to the same number of menu items and same number of application dialogues.

Thus, the applications menus and dialogues will be stored statically in the application's single page html document. We'll add the html markup for the various dialogues in the body of our application document. The default display state for our dialogues will be "hidden". When a user chooses to invoke the dialog, we change the dialogues display state to "show" (I.E. technically we set the style rule from display:hidden to display:block;).

This decision is also consistent with our decision on event listeners. We just create the corresponding event listeners for our menus and dialogues with the single page application's creation. We will literally create and attach the listeners when the document emits the "ready" signal.

Note. Our projects code and wiki are located on Git Hub. Right now we are on branch dev-1.0 here:
https://github.com/lorinpa/resume-publisher/tree/dev-1.0.

Build or Obtain?
Do we write markup for user interface from scratch or do we leverage some existing tool (E.G. Twitter Bootstrap front-end framework). There is no right or wrong answer here.

A short explanation for an otherwise "arbitrary" decision :) I'm not a designer. Becoming a designer is not in this project's scope. I'll use a "custom download" of Twitter Bootstrap front-end framework. Everything except the JavaScript components. I'll add a few CSS rules to our application, that will enable the Twitter Bootstrap menu to "drop-down". Later, if necessary we'll add a JavaScript event listener to enable the menu "drop-down" via a click event.

This project's focus is to learn JavaScript programming, JavaScript programming optimization techniques that will be used on a mobile device. Thus, we will "obtain" the superior Twitter Bootstrap menu design/layout. We'll build the rest.

In other words, no critique if Twitter's JavaScript library or jQuery's. I simply want to explore how to build it manually.

First Cut
First cut will include the following:

  • Top Drop Down Menu
    • Document
    • Row
      • Add Row
    • Column
      • Add Column
  • Bottom Status Bar

Here is first cut implementation. We've moved our JavaScript file listings to a sub-directory (js/local/). We've added the fore-mentioned CSS rules to implement our "drop down" menu. All of the source code is listed here.

About the Author:
Lorin M Klugman - I'm an experienced developer. My main interest is in new technology. Please use our contact box here if you are interested in hiring me. Please no recruiters :)