holyApp!

holyApp is a pure javascript framework for building desktop-like applications in a browser.
It provides a rich environment of services, an ever-growing library of constructors for complex GUI elements, and some big ideas that tie them all together. It was released under the Clear BSD license by MetaCarta in November of 2007.

This framework - and the rich client applications built with it - follow a set of general principles:

  1. The UI works like a desktop app, not a Web site. There is one rich and dynamic workspace, not multiple pages.
  2. The code is object-oriented software, not dynamic HTML. Instead of generating HTML strings and injecting them into the document with document.write and innerHTML, holyApp uses the Document Object Model's ECMAScript bindings to directly create, destroy, and manipulate interface elements.
  3. Data, logic and UI are separate. There are distinct data and UI layers in the code. UI components known as Viewers are coupled with data structures to allow users to view and interact with data.
  4. The 2 Trees: Javascript and the DOM. We create a Javascript reference to every DOM element as it's created. That way, DOM elements will persist while added and removed from the DOM. These JS references are organized in a JS tree - with enough resemblance to the DOM tree that the connections between the 2 trees are intuitive.
  5. Because all elements are referenced through the JS tree, there is no need to reference by their HTML id property, as is the common practice. This is a big improvement because HTML ids are a one-dimensional namespace, and the multidimensional namespace of the JS tree is very well suited to the complex components being generated by constructors. Also, using getElementById() can slow down processing.
  6. All layout data (images, colors, dimensions and properties) is defined in CSS. Having it all in one place is organized. And we can change skins on the fly by swapping stylesheets
  7. The client runs the show, not the server. The server does not sent commands to the client. It sends only libraries and data. The server should know nothing about the client's internal workings. It should act only as a data store, network proxy, and occasionally a Web service for processes that cannot be done on the client.

Framework Components:

This framework has 3 major components: host environment, constructors, and the application.

HOST ENVIRONMENT:

The host environment is defined in the hostEnv.js file. It provides the following services to the application and constructors:

io
provides communication with the server via cookies, server push, and XMLHTTPRequests [ POST | GET | DELETE]
errors
provides global exception handling with a cookie-based talkback system that logs client errors to the server.
state
saves gui state on server and restores it from the server.
JSON
json de/serializer
browser detection
detects platform and user agent
drag and drop
handles all underlying drag-and-drop functions ( you can think if it like an X-Y shipyard crane over the whole canvas). To get specific behaviors, this system passes events through to the specific drag-drop handler of any grabbed object.
skins
system for changing appearance and even layout on the fly.
constructors
dynamically loads constructors as they?re needed, and plugs them into host for the next use. Many constructors (will) require CSS class definitions from constructors.css, which is located in each skin definition.
context
keeps tack of which panel, dialog, etc. is currently focused. This way, events like keystrokes and right mouse clicks can have context-specific results.
event routing
routes key events to the currently focused panel, dialog, etc.
panels
the larges structural element of an app, features a cascading resize system for handling changes in the gui.
global resize
(this is occluded in the app) a global resize function that calls the cascading resize functions of panel contents.
global closer
(this is occluded in the app) a global

The host environment also provides a diverse collection of small utilities. Check the Natural Docs documentation for more detail.

CONSTRUCTORS:

Constructors are used to create complex GUI elements and useful JS libraries. They are loaded, dynamically and automatically, from the server as they are needed. They only need to be loaded once per session, as they are stored in memory in host.constructors. Here is a list of current constructors:

control_button
A simple, momentary button with click and hover behaviors.
control_contextMenu
A 'right-click' menu that can be bound to any element.
control_menuBar
A container for a collection of horizontal menus. Menus can be used via mouse clicks, but are also fully navigable via keystrokes.
control_menuTable
A re-usable element leveraged by control_contextMenu and control_menuBar, this is an HTML table augmented with extra styles and behaviors.
control_modal_confirm
A modal dialog box.
html_div
A simple HTML DIV element with some useful extra behaviors.
html_formElement
A constructor for multiple types of form elements. This also adds some
lib_nerveDate
A library of useful date functions.
lib_nerveDateUTC
Same as lib_nerveDate, but for use with UTC dates.
structure_floater
A movable, resizable floating window that sutomatically remembers its position and dimensions between sessions.
structure_hSlider
A horizontal slider useful for resizing panels or other GUI elements. It automatically remembers its position between sessions.
structure_modalDialog
A modal dialog box that can be filled with any content or tools.
structure_panel
Panels are the main GUI building block for holyApps.
structure_panelSet
A container for a set of contiguous panels.
structure_tabSet
A set of tabs and corresponding containers for swappable content.
viewer_dataGrid
A feature-rich data grid.
viewer_folderTree
A feature-rich folder tree that can be combined with a data grid.
viewer_keyboard
An embeddable keyboard to assist with character set transposistion. This was created for MetaCarta's GeoData Processing suite.
viewer_keyboard_key
A small constructor used by viewer_keyboard
viewer_progressBar
A simple progress bar for showing the status of long processes.

APPLICATION:

While the host environment and the constructors are generic, re-usable libraries, each application is highly specific and unique. But there are some common elements we can expect. For this example, I'll assume we're placing our application code in a JS namespace called app.*.

3 layers: data, display, and logic.

One could say that there are 4 layers: data, display, data logic, and display logic. But those last 2 tend to get mashed together in practice, so we can just call them logic.

The data you see in the display layer is an echo of the data in the data layer. Any changes to the data are first applied to the data layer, then the display is updated. In this way, data never needs to be parsed. And you can do anything you want to the display layer without losing anything important.

data

All of this data is stored in app.data. But this data may be in several formats - which brings us to the Data Cascade. Data from the server and various other sources might not arrive in an optimal, integrated format. So it will have to be converted into a Master Data Format used by this application. But some of the constructors might require a format (or data set) different from the Master Data Format. So the data is transformed once again to populate these gui elements. And this is the cascade: server data formats --> Master Data Format --> constructor-specific data. Changes to downstream data should be applied to the Master Data Format and cascaded downstream, or even written back to the server, re-loaded, and cascaded from there. When dealing with a lot of data, it's best to formalize this cascade early. It can get hairy otherwise.

gui (display layer)

The gui is laid out using the concept of 'panels'. Panels are divs with extra properties and behaviors that connect them with the services host environment. These are a empty rectangular containers used for layout and to track context. They may have their own keystroke behaviors and context menus. GUI elements are placed within the panels and inherit their context (need to add detail later). Each gui has a global resize function that lays out the gui based on the browser window size, gui state information, and other factors. It may also call the resize functions of gui elements embedded with the panels. In future development, the skin system could contain different resize functions for each skin, allowing completely different layouts for each skin.

Each gui has a global closer function. This function closes menus, floaters, and other momentary gui elements in response to a mouse click anywhere in the gui. This is included to duplicate the expected behavior of desktop guis.