|
Spaces
Detailed Introduction to Application Spaces
IntroductionApplication Spaces are managed domains in which content drives implementation. The Application Space Service orchestrates Hemi Framework services and compartmentalizes implementation details. OverviewApplication 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. APIStarting the Space ServiceWhen 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 SpacesApplication Spaces can be created in one of three ways:
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 SpaceThe 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 ConfigurationApplication 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 ConfigurationNote: 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
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. TemplatesExternal 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:
It is generally easier to get started with Templates and only use the External Space Configuration when multi-dependency bootstrapping is required. Working with SpacesApplication 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 PublicationsThe 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 ObjectsWhen 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:
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 TopologyWith 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.
Example Node and XHTML Component TopologyIn 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 DefinitionsAn 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.
By default, the Hemi JavaScript Framework includes the following definitions:
Object Request AliasApplication 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
Suffix
Static Declarations
Object Request Alias ExampleThe following example demonstrates a few different ORA syntaxes:
Application Space Definition ExampleThe 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. |