Login

Mobile

Refers to applications and content used on a mobile phone (AKA smart phone) and/or tablet.

Leveraging Ruby on Rails and ClojureScript.

Our upcoming sample project focuses on application frameworks and compilers.

Ruby on Rails (ROR) is an application framework written in Ruby.

ClojureScript is a compiler which emits (generates) JavaScript. The ClojureScript compiler is written in Clojure.

Our project will focus on a couple of customizations.

  1. We'll define database integrity rules in the database server (versus the application code).
  2. We'll verify our JavaScript client code, marks nodes, removed from the document, as available for deletion. In other words, we will verify that after we remove an html element from the document, it's underlying object is empty. We will verify the web browser's garbage collector removes the nodes from memory.

As with projects other projects in this series, this project is primarily a learning device. We will build a useful application. However, the main benefit is, to learn technology.

Business Requirements

One of my hobbies is visiting libraries, used book stores, and reading. I want to carry a list of books, authors and categories (E.G. science fiction) with me on my mobile phone. I'd also like to refer to book reviews. Many folks who work in libraries or book stores are great sources for book and author recommendations. Communicating your prior reviews helps folks recommend new books and authors.

Application Architecture

Server will run on a Local Area Network (LAN). That means, access is provided by my LAN. We won't implement application layer authentication and authorization for the initial release.

Our application provides two user interfaces (UI and user experience (UX)).

  1. Full size web browser. Supports create, report, update, and delete (CRUD).
  2. Mobile web browser. Supports reports.

Responsive Resume Project - Initial Release

Note, this articles is part of a series (here). In the previous installment we implemented data persistence. In this installment we complete our "must have" functions and thus, our initial release.

Logical Functions
These are the "must have" functions added for this installment.

  • Publish HTML Document. The user can now publish their resume as an html document.
  • Set Title (Web Browser Tab). The user can customize the document title text. This is the text that is displayed in the web browser tab control.
  • Move Row. The user can move a document row to a new location. For example, move the top row to the bottom of the document.

Other Enhancements
These are changes which enhance current functionality.

  • Toggle Edit Controls. The user can now turn the display of edit icons, on or off. The use can also turn the display of *cell borders, on or off. The user can preview the html document by hiding both edit icons and cell borders.
  • Changed popup dialog position. The popup dialogues now display in top right hand corner of the web browser's view area. The pop up dialogues now overlay the top navigation bar. The only exception is the "cell edit dialog".

*Note. I added an option to display cell borders to help the resume author visualize the rows and columns. The cells borders are not displayed in the published document. The cell borders are only displayed during the edit process (when the user toggles cell border on).

Implementation
The issue I struggled with the most was "how to get the Twitter Bootstrap style sheets in to our published document".

Normally, the Twitter Bootstrap CSS rules are stored in an external file (or remote URL/a file located on a remote web server ). Your document then references the Bootstrap CSS rules via a <link> tag (placed in the document head section). Separating a large set of CSS rules in an external file/remote URL, is typical way to organize your document's data.

Our use case is a little different. Our goal is to produce a single html document the user can email to someone.

If the receiver of the email wants to view the resume while off-line, then a remote URL reference is not going to work. For example, someone gets on an elevator which blocks wireless signals (I.E. the person's phone is no longer connected to the internet). We want that person on the elevator to be able to view the resume with the intended layout. If our resume document references a remote URL located across the internet, our elevator rider's mobile phone won't be able to reference the CSS rules. The result is, our document is not rendered as intended (it's missing the CSS rules). Thus, a reference to an a remote URL is not going to work.

Referencing a local external file, also conflicts with our use case. Our resume author would have to email 2 files. The 2 files would need to always be in the same location (on the recipient's computer/mobile device). That scenario is way too unpredictable, it's just not practical. Therefore, referencing a second, local external file is not an option.

Thus, I decided to copy the Twitter Bootstrap CSS rules in to the published resume html document (I.E. in the html head section).

We still had one more issue. How do we get the Twitter Bootstrap CSS rules in to our published resume document. This is actually more of a user experience (UX) issue. We don't want the resume author, to have to locate, and then select, the proper CSS file. We want to limit the number of steps the resume author has to take.

The challenge requires a little explanation.

Our program can not simply open a file from the local file system. The user must locate and select a file, using the browser's file dialog. The program can not select the file. The user must select the file.

To complicate matters, our program can not set the default location of the file dialog. In other words, the file dialog could start anywhere on the file system.

Remember, our resume author at the end of the publishing process, is going to have to select a destination location and optionally a destination file name. If in addition, the resume author has to select the CSS files, that adds up to, way too many steps.

Thus, I applied the same solution to our main program listing. Instead of storing the Twitter Bootstrap CSS rules in an external file, I store them in the head section of our webapp.html file (our main program file listing). That eliminates any file dialog requirements to obtain the CSS rules. A document can access it's own contents.

Thus, our application's file organization is little unusual, but it works. Sometimes, just getting it to work is good enough :)

Responsive Resume Project - Persisting Data

Note, this articles is part of a series (here). In the previous installment we started implementing "must have" functions. Our focus is to release a working (demonstration) version of our application, as soon as possible. In this installment we will continue that process.

Currently, our application allows a user to create a basic "resume" document. The user can add, delete and update, rows and columns. The most pressing issue is, the application is not peristing the user's work. That is what we are going to focus on in this installment, "persisting data locally".

Persisting data locally means, we want the user to be able to save their work on their local machine. The user can save their work while offline. Our application's storage architecture is similar to a traditional "desktop" application.

When we started designing this project, we said up front the intended audience consists of web developers. Thus, our intended audience should be familiar with the following concepts. The user must know how to navigate the file system, understand file names, file types.

HTML5 specifies several mechanism for a local persistence. The mechanism referred to as "local storage" is implemented the most across web browsers. I'll summarize "local storage" as an embedded database. An embedded database that is dedicated to a particular web browser. What that means to a user is, data saved while using Firefox is not accessible while using Chromium (or any other browser, vice versa, etc). So local storage has some limitations.

HTML5 also introduces a file system api. That means we can engineer a dialog that allows the user to choose a file location to save their work. When the user saves their work to a local file, that information is accessible from any HTML5 web browser.

In addition to those 2 options (local storage and external file), we have a user experience (UX) issue to consider. When the user saves there work as an external file, they have to choose a location and a file name. If a user saves there work to the web browser's "local storage", the user does not have to choose a file location. Thus, the users performs far less steps when saving their work "local storage" (versus external file). So we are going to give the user both options. We'll suggest that they save minor changes to their work in the web browser's local storage. When the user completes a major revision of their work, we recommend they save to an external file.

As mentioned above, out application's storage is similar to a "desktop" application. The analogy would be working with a spreadsheet program like MS Excel or LibreOffice. The spreadsheet programs by default, saves the user's work in a internal format. If the user wants to share their work with other folks or other applications, they export the data as a comma delimited file (csv).

JavaScript's internal data format is JavaScript Object Notation (JSON). So our "row" entity is represented in JSON as such:

{"row_id":1, "location":6}

Our rowList entity is represented as (I.E. JSON array):

[{"row_id":1,"location":1}, {"row_id":5,"location":2}]

We can also represent our rowList as a JSON object as such:

{"rowList": [{"row_id":1,"location":1}, {"row_id":5,"location":2}]}

Responsive Resume Project - Implementing UI/UX Functions

Note, this article is part of series (see here). In our last installment we introduced our application's user interface (UI) and the subject of, user experience (UX). We identified "must have" functions and started our implementation.

In this installment we continue to focus on implementing our "must have" UI/UX functions. Thus we are adding the following:

  • Delete a row.
  • Edit a cell (row_column) content.
  • Edit the width and indentation of a cell.
  • Delete a cell (row_column).

The above are public functions, functions the user invokes. To implement the above functions, we also require additional internal infra structure functions. For example, in prior articles we defined the following business rules:

  • A row must always contain at least one column.
  • If a user deletes the last column of a row, the application must delete the row itself.

The following method

In our last commit, we added an internal entity that serves as a collection of row_columns. We call that collection of row_columns a "grid". Logically the grid represents our resume document. The grid provides the resume document's public properties and methods. That also means the "grid" is going to be composed of some of our other infra structure entities. Thus, I've added an instance of "columnList" and "rowList" to our grid.

Our grid now contains 3 collections, a columnList, a rowList and a list of row_columns (AKA cells).

Our grid can now count we the number of columns in each row. Here is our implementation:

    /** Check to see if we this row is empty **/
    this.getNumColumnsInRow=function(row_id) {
	var len = this.list.length;
	var elem = null;
	var count = 0;
	for (var nIndex=0; nIndex < len; nIndex++) {
            elem = this.list[nIndex];
            if (elem.getRowId() == row_id) {
                count++;
            }
        }
        return count;
    };

But wait, we are not done. If we delete a row at the top of the document, that effects all the rows below it. For example, we have 10 rows. The location property of the bottom row is 10. 10 is how the user identifies the bottom (AKA last) row. If we delete row 1 that means row 10 is now row 9. The last row now has a location value of 9. Thus, when we delete a row, we need to adjust the "location" properties of the remaining rows. The following method is our implementation:

Responsive Resume Project - User Interface - Source Code

Our markup

<!DOCTYPE html>
<html>
    <head>
    <title>Resume</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <link type="text/css" href="css/bootstrap/css/bootstrap.css" media="all" rel="stylesheet" id="bootstrap"/>
    <style>
        body {
            font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
            font-size: 14px;

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.

Responsive Resume - Internal Design - Data Structures

In our prior article we introduced the business and functional requirements for our Resume Publishing application. Business requirements detail "what" the does and "why" someone uses the the application. In this installment, we discuss the internal requirements. That is, "how" the application performs it's functions.

Data Structure Summary
Per our business and functional requirements the resume document is divided logically into row and columns.

The resume document contains one to many rows.

Each row contains one to twelve columns.

Each column contains a content property and a width property.

Each row contains a location property. (I.E. it's line number within the resume document).

The relationship between a row and a column is referred to as a row_column (or cell).

Each row_column contains a location property (I.E. horizontal position of the column inside the row). Note! This also allows for a future enhancement where a column is defined once but displayed many times within the document.

Responsive Resume -- Defining the Application

Note! This article is part of a series (see here). In prior installments of this series (see here), we demonstrated tools used to develop JavaScript applications. In this installment, we define our first mobile development project.

We start by describing business requirements. Business requirements describe "what" the application does and "why" someone would use the application.

Typically, "business requirements" are published in a formal document. I'm not going to publish a formal document here. However, we'll follow the basic document outline. We are also going to combine business and functional requirements in this article.

First a summary of our project.

JavaScript Tools -- Functional Testing and Debugging

Note! This article is part of a series (see here). In previous articles we explored syntax, string and performance testing. In this installation, we will explore functional testing and source code debuggers.

Our initial code really doesn't have much logic (see person.js detailed in previous articles). Right now, our person entity can only be identified by first and last name. In the real world we need additional properties to uniquely identify an individual person. In the U.S. we use a social security number. For our example code, lets just add a property called "id". Id is a unique number.

We are also adding a collection of persons (E.G personList). Our collection will allow to get an an individual by their "id" value.

Our functional test is "verify personList.getPerson(2) returns the person with an id value of 2". We'll add at 3 persons to our list. We'll make sure one of the persons has an id value of 2.

JavaScript Tools -- Documentation Generators

Note! This article is part of a series. In prior articles we wrote a small JavaScript application. We string tested the application, verified syntax and tested performance ( see here). In this installation, we will document our program.

We need to qualify what type of documentation we are referring to. In this case, it's "internal documentation". We are describing "how" the program works internally. The intended audience is other programmers. If we were working on a project where we expected other programmers to use and extend our program, we would refer to this as an Application Programming Interface (API). In fact, most projects, when successful are subject to change, enhancements and new team member. Thus, most "internal documentation" is referred to as API documentation.

Let's introduce another tool, jsdoc here: https://github.com/jsdoc3/jsdoc). JsDoc is a documentation processor.

Syndicate content