Engine for Web Applications Overview

Current Version: 2.1

Overview

Current Version 2.1.1 : 2009/07/25

Engine is a framework for Web Applications, and may be used alongside most Web frameworks and libraries. Custom components can be loaded externally or easily built into the framework, deployed as separate script packages or as application components.

Engine is very easy to start using. Like every other framework, add a reference to the base script file to a Web page. For engine, that file is engcomp.js (Refer downloads for further details).

Every framework

For convenience, the diagrams are marked Yellow to indicate touchpoints where developers add their code.

Key features include managing application interdependencies and bootstrapping (tasking), messaging, transactions, configuration, dynamic runtime components, and monitoring. The engine service provides an abstraction layer for associating script with content and exposing declarative scripting with XML.

Communication

Engine was designed in the Summer of 2002, based in part on experiences learned with the Multi-Document Interface Script API project. As such, Engine was built to provide a set of core services, starting with communication.

In the following diagrams, the Yellow blocks indicate areas where developers write code.

DOM Events

DOM Events

Engine includes a light wrapper for managing events across browsers, and exposing a few helper methods.

One key feature is Event Buffering, which compensates for losing object context when passing function pointers. The event buffer makes use of the Object Registry and injects the createHandler method into specified objects. The createHandler method may then be used to create an event handler buffer to pre-process the object lookup.

API: org.cote.js.dom.event

DOM Monitor Service

Monitor Service

The monitor service is a corner stone for passive-analytics Web monitors. Monitoring is simple to setup and use, and very powerful for tapping into Web pages.

	var oMonitor = {
	   // Specify the handler.
	   // That's it.  The rest is taken care of.
	   //
	   handle_window_load:function(){
	   },
	   // Required by MonitorService
	   initializeMonitor:function(){
		  // must return true for monitoring to be enabled;
		  return 1;
	   }
	};
	// important to prepare object so 1) it can be registered, and 2) add it to the ObjectRegistry
	org.cote.js.prepareObject("MyMonitor","1.0",true,oMonitor);
	// add the monitor object
	org.cote.js.monitor.MonitorService.addMonitor(oMonitor);
	

API: org.cote.js.monitor

Communication

Messaging is an eventing system based on subscriptions and publications. In particular, the sendMessage method allows for blanket broadcasts to subscribers to the onsendmessage publication.

Messaging

API: org.cote.js.message

Primitive Wires

JavaScript functions can be connected with primitive wiring. One function becomes the action, and the other function becomes the handler.

Primitive Wires

API: org.cote.js.wires.primitive

Wires

Primitive wires can be chained together using a wire service. The wire service manages signalling between the primitive wire invocations by linking handlers to identical sibling actions.

Wires

API: org.cote.js.wires

Transactions

The Transaction Service is available to objects that conform to the Engine API (via prototyping, construction, newObject, or decorating prepareObject), are included in the Object Registry, and implement the Transaction Service interface methods. Qualifying objects then participate in one or more transactions, whose state and participations are maintained by a Transaction Packet.

The Transaction Service is the foundation for the Task Service, and is a great compliment to portlet wiring and JSR-286.

Transaction Service

API: org.cote.js.transaction

Framework

In tandem with communication, Engine was designed to address object management, XML handling, bootstrapping, and indirectly associating XML and HTML nodes with the framework.

In the following diagrams, the Yellow blocks indicate areas where developers write code.

Registry

The Object Registry is a central repository into which all Engine objects are stored.

Tasks may be created through script or imported from an XML file.

Object Registry

API: org.cote.js.registry

Bootstrapping

The Task Service, which makes direct use of the Transaction Service, provides the foundation for bootstrapping action and dependency sequences into a managable and portable schema.

Tasks may be created through script or imported from an XML file.

Task Service

API: org.cote.js.task

XML and AJAX

XML is managed through the org.cote.js.xml API. This API is also available separately as libXmlRequest.

XML Utility

The XML library includes in memory caching and is very easy to implement. Persistant caching through the storage library is around the corner.

API: org.cote.js.xml

Threading

Engine includes a threading library that is straight forward to implement. The threading functionality detects when registered engine objects are destroyed, and can self terminate.

Threading Library

API: org.cote.js.thread

Working with XML and HTML Nodes

HTML and XML nodes may be represented to the framework as XHTMLComponent objects. This is useful when working with dynamic displays where global identifiers may not be desirable and nodes are routinely created and thrown away.

XHTMLComponent

API: org.cote.js.xhtml

Offline Storage

Offline storage is provided through a library that wraps the DOMStorage API and includes some downlevel and cross-implementation providers to expose support to a wide audience.

DOMStorage

API: org.cote.js.storage

Developing Components

Engine is straight forward to extend. And, it's very easy to develop encapsulated components.

In the following diagrams, the Yellow blocks indicate areas where developers write code.

Custom Engine Objects

Custom objects can be coded for Engine with a single method invocation.

function MyObjectClass(){
   org.cote.js.prepareObject("My Object","1.0",true,this);
}

API: org.cote.js

Application Components

Application Components are externalized modules, ideal for encapsulating reusable code and creating dynamic user interface widgets. Components can be created with no binding, or be bound to HTML nodes or XHTML Components.

Components are automatically registered with the Transaction Service, allowing components to communicate with each other through Packets. Components also can serve other transaction channels. The Application Component API includes built-in helper methods.

Another key feature is assertive programming. When the TransactionService is used, or when DOM event handling is desired, you only need to specify the name of the event or transaction and include the _handle_ preface. For example, declaring a function named _handle_click will result in the component automatically instrumenting an onclick handler on any binding node.

Application Component

API: org.cote.js.appcomp

Templates

Templates can be applied to Application Component objects. Templates are a combination of HTML, and a special script element, <embedded-script />. Script defined in the embedded-script element is applied when the template is loaded, and removed when the template is unloaded.

HTML in the template is run through a pre-processor, allowing for a few special tokens to be included. This allows the HTML nodes to include event handler declarations, such as onclick = ${this}.handle_click, where the handler is defined in the embedded script. ${this} evaluates to an object reference to the hosting application component. ${this.id} evaluates to the application component guid.

Application Component Templates

Example:

<Template>
   <p onclick = "${this}.DoClick()">Click<p>
   <embedded-init><[CDATA[
    template_init : function(){
    
    },
    embedded_init : function(){
	
    },
    DoClick : function(){
	
    }
   ]]></embedded-init>
</Template>

API: org.cote.js.appcomp

Distributed Components

Distributed Components single-source deployments into a single file that includes Application Components, Templates, Tasks, and Fragments. This DWAC Loader is an Application Component, the DWACControl. Account Manager and Core Web include request handlers for persisting DWAC data on the server and hosting the DWAC builder UIs for authenticated users.

Distributed Components

Abstraction

Engine abstraction is a powerful feature, and it is accomplished with declarative programming. The Separation of Functionality from Content article describes the ideology of this feature.

In the following diagrams, the Yellow blocks indicate areas where developers write code.

Engine Service

The Engine service is a declarative language parser. It optionally uses the Task Service to bootstrap dependencies, such as the engine.config.xml, config.xml, and ValidationPatterns.xml files.

After all task dependencies are complete, each Engine applies an Engine Configuration. An Engine Configuration may be itself, declared as self, or a named configuration group. scans its child nodes. If a node is defined, the scan continues through the node's children. A node is defined when it has a corresponding object-definition. The definition describes the implementation, constructor, and any required parameters. Dynamic parameter values are supported for passing attribute or node references, or XPath expressions.

The XHTMLComponent definition branches the node to the XHTMLFormComponent library if it is a form field, and to the Application Component library if an application component id is specified.

Engine Service

API: org.cote.js.engine

Engine Abstraction

Engine configurations can be used to switch blocks of content and to describe declarative implementations of third party widgets.

For example, a custom element such as <MyElement /> can be defined as programattic connector or even a placeholder to a widget provided by another framework. Once the definition is specified, no code need be written. Just use your custom element.

Engine Service Abstraction

API: org.cote.js.engine

Virtual Forms

The XHTMLFormComponent library creates virtual forms for aggregating user input for the lifecyle of a Web 2.0 application. In doing so, it creates a Virtual Form.

The forms are virtual in that the data exists and belongs to a collection of form values, but the HTML representing the form and form fields do not need to exist.

As XML and HTML nodes are processed by an Engine, the corresponding XHTMLComponent object-definition will implement and initialize any corresponding XHTMLFormComponent or Application Component objects. When a new input field processed through the XHTMLComponent, it is synchronized against a Virtual Form that is automatically created for the Engine. At that time, any existing values for the field are applied.

The special rid attribute is used to specify a context-sensitivie friendly name.

In this manner, a single template containing several form fields can co-exist on a single page, but in differert Virtual Forms. If a Virtual Form fields exists within an HTML form, the fields are submitted to the server as normal. Or, the virtual form can easily be serialized into XML for an AJAX call to the server.

Virtual Forms

INPUT, SELECT, and TEXTAREA fields are automatically added to virtual forms when included inside an Engine.

API: org.cote.js.xhtml.form

Engine Configuration and Component Templates

Documentation: Engine Configuration