My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
Spaces  
Detailed Introduction to Application Spaces
Updated Dec 20, 2010 by sw.cote

Introduction

Application Spaces are managed domains in which content drives implementation. The Application Space Service orchestrates Hemi Framework services and compartmentalizes implementation details.

Overview

Application Spaces may or may not be bound to an HTML node, and the contents of each space server as a driver via Application Space Definitions. Nodes that match definitions may be referenced using unique object identifiers or friendly reference identifiers that are unique only to the space. Form fields are augmented by the Form Service to create Virtual Forms. Spaces can load automatically or use the Task Service to bootstrap dependencies.

By default, common HTML nodes match space definitions for XHTML Components. XHTML Components automatically load Application Components, Modules, and Templates (which in turn may spawn their own Application Spaces). Refer to the Application Space Definitions section for more details.

API

Application Space API

Starting the Space Service

When using the composite Hemi JavaScript Framework file, or if the hemi.app.space library is included, the Application Space service will start. If the auto_load property is not set to false, the service will attempt to discover declared spaces, or use the BODY element as a default.

Creating Spaces

Application Spaces can be created in one of three ways:

  1. Don't make any changes, and the BODY element will be designated as a space.
  2. Declare the is-space attribute with a value of 1 on a DIV, SPAN, or FORM element.
  3. Use the createSpace method to create a new space for a given element. The createSpace method includes token and XHTML processor options to override default behavior. For example, the Application Component uses custom processors when creating spaces for templates.

The following example shows how a space is defined for a DIV element.

<div is-space = "1"> ... </div>

Note: Except in special or complex circumstances, using the default (which is do nothing) or only the is-space attribute are the fastest ways of getting started with an application space.

Primary Application Space

The first Application Space that loads is designated as the Primary. By default, if the service is loaded and the auto_load is not set to false, the service attempts to discover elements marked with the is-space attribute and load Application Spaces for those elements. If one or more elements are discovered, the first element becomes the primary. Otherwise, the BODY element is treated as the Primary space.

This behavior may be configured by setting the auto_load property to false before the browser's window.onload event fires.

Space Configuration

Application Spaces are loaded against pre-defined configurations which are applied through Application Space Definitions. By default, Application Spaces are loaded against the self configuration, which means the XHTML contents of the space are the configuration.

External Space Configuration

Note: Only use External Space Configuration for special or complex circumstances. Using the default configuration (which is do nothing at all) and/or templates requires less setup than External Space Configuration.

The first and second versions of the Engine for Web Applications Engine Service was driven by external configuration with support in the second version for self configuration. In the Hemi version, the default was made self to reduce the otherwise required external configuration.

External Space Configurations are very powerful, but also require more configuration. Refer to the section on External Space Configurations vs. Templates.

For cases where the primary Application Space requires bootstrapping (via the Task Service), the default self configuration can be overridden with declarative configuration.

To use an external configuration, the following attributes may be specified

  • is-space : Needed to identify the element as an Application Space.
  • space-id : The identifier of the Space, used to retrieve a specific space by a known value.
  • space-action : The task action. Typically this would be to load an external task list.
  • space-action-type : The type of the action. For an external task list, this would xml.
  • space-handler : The task handler. If the action is a task list, the handler is the id of a task from that task list.
  • space-handler-type : The type of the handler. If the handler is a task, then the handler-type is import-task.
  • space-config : The id of the configuration element to use for the space.
  • space-config-task : The id of the task that loaded the space configuration.

For example, to load an Application Space that is dependent on an external Space Configuration and Application Configuration, the following structure would be used:

Example Space Configuration:

<space-configurations>
   <configuration id = "space-9">
      <p>EXTERNAL SPACE</p>
   </configuration>
</space-configurations>

Example Application Configuration:

<application-config>
   <config>
      <param name="log_level" value="DEBUG" />
      <param name="config_version" value="devcfg_3.1.7" />
   </config>
</application-config>

Example Task List:

<tasks>

   <task id="space_driver"
      action-type="default"
      action="[nothing]"
      handler-type="event"
      handler="space_service_initialized"
   >
      <task rid = "load_application_config" auto-execute="1" />
      <task rid = "load_space_config" auto-execute="1" />

      <depends rid="dom_event_window_load" />

   </task>

   <task id="load_space_config"
      action-type="xml"
      action="/path/spaceConfig.xml"
      handler-type="default"
      handler="[nothing]"
   />

   <task id="load_application_config"
      action-type="xml"
      action="/path/applicationConfig.xml"
      handler-type="script"
      handler="#cdata"
   >
      <![CDATA[
         function RunTaskScript(oTask){

            Hemi.include("hemi.driver");
            Hemi.include("hemi.util.config");
            var _a = Hemi.driver.service.getObjects();
            // create a new config utility instance
            _a.application_config = Hemi.util.config.newInstance();
            // set the parent config element name
            _a.application_config.setElementParentName("driver-config");

            // parse the config from the dom for the xml file loaded by the task
            _a.application_config.parseConfig(oTask.data);

            // set a bit indicating the config was loaded
            Hemi.driver.service.getProperties().config_loaded = 1;
            Hemi.message.service.setReportThreshold(_a.application_config.getParam('log_level'));

            return true;
         }
      ]]>
   </task>
</tasks>

And, the declarative attribute combination to execute this bootstrap:

<div
   is-space = "1"
   space-action = "/path/spaceTasks.xml"
   space-action-type = "xml"
   space-handler = "space_driver"
   space-handler-type = "import-task"
   space-config = "space-9"
   space-config-task = "load_space_config" 
>
[ volatile ]
</div>

External Space Configuration vs. Templates

External Space Configurations are the pre-cursor to Templates loaded into Spaces. Both use the same processor to create a relationship between external functionality and content, and both are applied to spaces using the configureSpace method. Using Templates with Spaces requires a less external configuration and setup than using External Space Configurations.

One feature of External Space Configurations was deprecated with version three (Hemi): Application Space Definitions were defined within the configuration. In version three, the definitions were moved into their own service.

Except where designated, discussion of Templates in this section supposes that the Application Component is set to load the Template into an Application Space.

The differences between External Space Configurations and a Template loaded into an Application Space are subtle albeit fundamental:

  • Templates are managed by the Application Component.
    • If the component designates that the template is a space, the template thereby is loaded into its own Application Space using the self configuration.
    • If the component does not designate the template be loaded into a space, the template is copied into the existing space and without processing the contents.
  • External Space Configurations are integrated into the Application Space task. By virtue of the feature, External Space Configurations are not self. Therefore, the default contents of an Application Space using an External Space Configuration is volatile: The contents will be removed in favor of the external contents.
  • Templates are pre-processed External Space Configurations. The Application Component pre-processors handle token and XML transformation, principally for the ${this}, ${this.id}, and ${hemi.hemi_base} tokens, and the embedded-script elements.
  • External Space Configurations do not require an XHTML binding node; Templates do require an XHTML binding node.

It is generally easier to get started with Templates and only use the External Space Configuration when multi-dependency bootstrapping is required.

Working with Spaces

Application Spaces create an environment to disconnect content from functionality. To define post-load actions for spaces without using a task list, the onspaceconfigload publication may be used.

Application Space Publications

The following example demonstrates how a subscription is created for the onspaceconfigload publication to listen for a space loading.

Hemi.message.service.subscribe("onspaceconfigload", function (sName, oSpace) {
   if (!oSpace.is_primary) return;
   /// Work with the primary space
});

Application Space Objects

When an Application Space is created and configured, XHTML Nodes that are not designated as abstract are indexed into the Application Space intstance. Nodes are discoverable by reference identifier, CSS class, or framework identifier.

Space Objects include three properties:

  • object : The object that was used to create the index.
  • rid : The reference identifier for the object
  • config : The configuration in effect when the object was indexed (typically will be self).

For example, given the following space:

<div is-space = "1" space-id = "demoSpace">
   <p rid = "lblSpace">[ label ]</p>
</div>

The lblSpace node is discoverable in the context of demoSpace.

/// Get the space
var oSpace = Hemi.app.space.service.getSpace("demoSpace");

/// Get the space object
var oSpaceObject = oSpace.getSpaceObjectByName("lblSpace");

Default Object Model and Topology

With the default configuration in effect, the following example shows the relationship between a DIV element and an application space. Refer to Application Space Definitions for a list of matching HTML nodes.

  • The Application Space Definition for DIV is to represent that node to the framework as an XHTMLComponent.
  • The XHTMLComponent is registered to the Space as a SpaceObject with the reference identifier.
  • If the node specified a component or template (the XHTMLComponent Quick Fix), an ApplicationComponent would be created for the component or template, bound to the XHTMLComponent's backing node and a reference stored by the XHTMLComponent. The XHTMLComponent would still be the binding to the Space Object.

Example Node and XHTML Component Topology

In the following example, the DIV element is given a reference identifier, and a message subscription is used to receive notification for the onspaceconfigload publication. The publication takes place after the window loads and on completion of the space configuration task.

<div rid = "some_div">Some Div</div>
<script type = "text/javascript">
Hemi.message.service.subscribe("onspaceconfigload", function (sName, oSpace) {
   if (!oSpace.is_primary) return;

   // Get the SpaceObject which indexes "some_div" to the Framework object.
   var oObjectRef = oSpace.getSpaceObjectByName("some_div");
   
   // Get the Framework object representing the DIV
   var oXHTMLComponent = oObjectRef.object;
   
   // Retrieve the DIV node.
   var oDiv = oXHTMLComponent.getContainer();

</script>

Application Space Definitions

An Application Space Definition is a configuration that correlates HTML or XML nodes with a JavaScript statement. The JavaScript statement can be for any global function, or any toolkit or framework.

Each definition defines the following values, specified through the newDefinition method. While these values are represented internally as an object, they should not be changed once they are defined.

  • Matches : An array of strings representing node names for which the definition should apply.
  • Namespace : The namespace or package of the constructor.
    • abstract : A keyword indicating that the match is a pass-through.
    • window : Use when referring to a global JavaScript function.
  • Constructor : The name of the function or constructor.
  • Constructor Parameters : An array of string values. Refer to Object Request Alias parameters for specially encoded parameter values.
  • Context Switch : Bit indicating the constructor response is XML and the context processing should switch into the XML object model.
  • Context Path : When switching contexts, the XPATH expression where processing should begin in the target context.
  • Swap Name : When switching contexts, an alternate name used to replace the match element name.
  • Use Parent : Bit indicating to preserve the parent node reference when processing children.
  • No Recursion: Bit indicating not to process any children.

By default, the Hemi JavaScript Framework includes the following definitions:

  • html-fragment, template, and fragment as abstract implementations.
  • import-xml as a hemi.xml.getXml implementation.
  • import-style as a hemi.css.importStyle implementation.
  • p, span, div, body, form, input, textarea, select, table, tr, td, tbody, thead, th, img, ul, ol, li, a, iframe, h1, h2, h3, h4, h5, h6, dl, dd, and dt as hemi.object.xhtml implementations.

Object Request Alias

Application Space Definitions use a special Object Request Alias, or ORA, token that the Application Space Service translates to specific types of parameter values when invoking the constructor. The following ORA parameters and syntax are supported.

Prefix

  • ora: : All ORA values must have this prefix, or the value is treated as a static string value.
    • integer : The suffix is treated as an integer value.
    • xpath-node-value: : The suffix is evaluated as an XPath expression against the context node, and the return value treated as an individual node reference.
    • xpath-node-value-list: : The suffix is evaluated as an XPath expression against the context node, and the return value treated as a node list.

Suffix

  • parent : Shifts focus to the parent node for the following parameter aliases:
    • node_name : Parent node name
    • attr : Attribute taken from the parent node.
  • attr : read the prefix as an attribute value from the context node.

Static Declarations

  • parent_element : Node reference to the parent HTML container.
  • node_context : Node reference to the source context (XHTML or XML).
  • element_context : Node reference to the parent element in which the target context (XHTML or XML) is being applied. This may or may not be a newly created node or a parent node depending on the context of the invocation (eg: during translation between an external XML file and a local HTML file).
  • bool_true : Boolean true value.
  • data_source : Deprecated
  • parent_reference : The return value of the parent node reference implementation.
  • xml_document : XMLDocument reference to the source context (XML).
  • params_array : String array of child parameter values from the source context (XML) retrieved from elements named param with an attribute specified for value.
  • node_name : The name of the context node.
  • space_object : Reference to the Application Space for which this implementation was created.
  • space_element : Reference to any DOM Node bound to the Application Space.
  • space_config : The name of the space configuration being applied. Default is self.
  • space_id : The application space identifier.

Object Request Alias Example

The following example demonstrates a few different ORA syntaxes:

  • ora:integer_42 : The value would be 42.
  • ora:id_attr : The value would be that of the id attribute.
  • ora:node_context : Node reference to the matching element.

Application Space Definition Example

The following example demonstrates how to create an Application Space Definition for a custom element.

Given a custom element, such as:

<my-element my-attribute = "foo" />

The following definition matches the my-element node and stipulates a node context switch to a specified XPath expression and a global JavaScript function constructor named CustomElement. By defining a context switch, the Application Space processor expects the return value to be an XML document which will include the specified XPath.

Hemi.include("hemi.app.space");
Hemi.app.space.definitions.service.addDefinition(
   Hemi.app.space.definitions.service.newDefinition(
      ["my-element"],
      "window",
      "CustomElement",
      ["ora:node_context","ora:my-attribute_attr"],
      1,
      "/bar/",
      "span"
   )
);

Given the above definition, the following global JavaScript function would be invoked with the specified parameters. The function creates an xml document, populates it with some text based on the source element, and returns the document. The implementation definition then knows to treat the response as an XML reference from the switch-context bit, and will then process the child elements of the matching XPath.

function CustomElement(oSourceNode, sAttr) {
   var oXml = Hemi.xml.newXmlDocument("bar");
   var oNode = oXml.createTextNode(oSourceNode.nodeName + " attribute value is " + sAttr);
   oXml.documentElement.appendChild(oNode);
   return oXml.documentElement;
}

The result is that including the custom element in a Web page, an External Space Configuration, a Template, or a Fragment, would result in the following text being inserted:

MY-ELEMENT attribute value is foo

When using context switches, be forewarned that it is necessary to consider the different nodes that may be used for root or grouping nodes. It is necessary to also define those nodes as abstract in order for the nodes to be processed. Otherwise, the nodes will simply be copied. For non-HTML nodes, this can lead to validation or formatting problems.


Sign in to add a comment
Powered by Google Project Hosting