Nathan M. Andelin   November 2016

IBM i Modernization - The User Interface

(Part 8)

In the year 2005, a Web designer named Jesse James Garrett wrote an essay that delineated an emerging web-page/application methodology. It was based on a set of browser technologies that he collectively assigned an acronym to - AJAX - short for Asynchronous JavaScript and XML.

Mr. Garrett suggested that these technologies represented a fundamental shift in the way that web applications would be designed. That was an understatement. The paradigm shift became known as Web 2.0.

Asynchronous request processing paired with partial updates to page elements is the subject of this piece.

XMLHttpRequest Object

Browsers implement a software component named XMLHttpRequest that provides an interface for making requests asynchronously. This means that requests may execute in background threads that allow users to continue viewing or using the page without disruption.

The typical API for making asynchronous requests also entails defining and coding JavaScript functions that are invoked at the completion of the request-response cycle. Call-back functions typically update the browser's document object model (DOM) based on data objects (XML or JSON) received in responses.

Updating a browser's DOM is a way of dynamically adding or changing page content. It provides a streamlined and fluid user interface.

A Slight Derivative

I'd like to introduce an API that uses the browsers XMLHttpRequest object under the covers. With it, requests run asynchronously in browser threads.

However requests are queued. So developers can count on requests completing in the sequence that they were requested. The next request in the queue is automatically released when the response to the previous one completes.

This enables developers to accurately predict the results of firing off many requests at the same time. Without going into details at this time, this has proven to be very useful for developers.

Another feature of the API is that it doesn't entail specifying call-back routines. Instead, IBM i applications get to decide which (if any) JavaScript functions may be called in response to requests. For example, an IBM i application may choose to evoke a JavaScript error handling routine instead of one used to modify page content.

Rather than returning XML or JSON data objects via this API, IBM i applications return JavaScript expressions that are run in response. This has proven to be an effective means of reducing the size of data streams returned to browsers and improving UI performance. It's snappy!

This is not to suggest that other XMLHttpRequest wrappers are inferior. It is only to suggest an additional tool in the toolkit, based on a lot of application experience.

OO JavaScript

The other idea I'd like to briefly touch on is object-oriented JavaScript. This is NOT to suggest that application developers need to become proficient in OO JavaScript. In fact, frameworks that rely on developers mastering OO JavaScript skills have taken a wrong turn, in my opinion.

OO JavaScript makes more sense for framework developers than application developers. But application developers should at least be familiar with creating instances of objects by using the new operator. Maybe we can pick up the philosophical discussion about coding styles in a different piece.

We use the new operator in many applications to instantiate UI widgets, as I will explain with the following embedded application.

Simple Sample

This application is intended to illustrate:

  • Asynchronous request processing (ARP).
  • A handy ARP API.
  • The JavaScript new operator.
  • UI widgets.
  • Dynamic updates to page (DOM) elements.

Names

Click Here
Click Here
Click Here
Click Here

Key Points

Clicking on a table heading sends an asynchronous request to an IBM i server that downloads 500 names and appends them as table rows; Or alternatively clears all rows in the table.

Some web designers suggest that dynamic DOM (page) updates may perform poorly. This example shows that fluid and well-performing updates are possible, even when the changes are substantial in size and number of elements.

Clicking on table rows and pressing navigational keys (i.e. Arrow-Down, Arrow-Up, End, Home) shows that each table (UI widget) encapsulates its own event listeners and event handlers. That's rather object oriented.

Occasionally I hear of green-screen developers asking how to make sub-files appear side by side on a screen. The answers are never satisfactory. This example shows side by side tables when screen sizes permit. However the tables flow from top to bottom on cell phone screens. This is an example of "responsive design"; The layout automatically adjusts to screen width.

How Does It Work?

The HTML which encapsulates each table consists of an element hierarchy. Each element is styled via CSS class names.

An onClick() event listener is attached to table headings. Each table has a unique ID (i.e. "tb1", "tb2", "tb3", "tb4").

<div class="oc">
<center class="head" onclick="names('tb1')">Click Here</center>
<div class="ic">
<table id="tb1" width="100%" height="100%" cellpadding="6" cellspacing="0"></table>
</div>
</div>

A Table() object is created for each HTML table element and object references are stored in document variables.


var tb1 = new Table('tb1');
var tb2 = new Table('tb2');
var tb3 = new Table('tb3');
var tb4 = new Table('tb4');
var o = null;

The names() function is invoked when users click on a table heading.


function names(s) {
	$('hname').innerHTML = 'Names';
	o = eval(s);
	if (o.rows.length == 0)	reqGet('ibmiui8.txt');
	else o.clearRows();
}

The reqGet() function is invoked if the table is empty. This sends an asynchronous request to an IBM i server for a URL (ibmiui8.txt).

All rows in the table are alternatively removed if the table has rows. The application heading is updated (shows "Names").

The ar() function is automatically invoked for each "name" when the "response" is received from the IBM i server.


function ar(name) {
	o.insertRowBottom('<tr key=1><td>' + name + '</td></tr>');
}

The ar() function simply appends the person's "name" as a row in the table.

That delineates how the tables may be updated dynamically in response to "Click Me" events.

The _selectRow() function is invoked when new rows are selected via mouse click or key-press events. This changes the application heading to show the currently selected "name".


function _selectRow(row) {
	$('hname').innerHTML = row.innerHTML;
	$('hname').scrollIntoView();
}

This application draws from a small JavaScript framework that is referenced from this page as follows:

<script src="../../rdweb/apps/common/scripts/binders.js"></script>
<script src="../../rdweb/apps/common/scripts/keyhandler.js"></script>
<script src="../../rdweb/apps/common/scripts/tables.js"></script>
<script src="../../rdweb/apps/common/scripts/xmlhttp.js"></script>

The custom JavaScript for this application can be found in file ibmiui8.js.

Summary

An application's user interface can be improved by moving away from page-at-a-time and green-screen paradigms; Moving toward a paradigm that is facilitated by asynchronous request processing. This includes the use of UI widgets and dynamic page updates that provide fluid screen transformations. It also includes responsive layouts that automatically adapt to various screen sizes.

These techniques can be supported by small JavaScript frameworks combined with modest amounts of custom JavaScript.