This particular series has been ongoing since late last year - not quite a book, though a very healthy chapter towards one, fortunately. When I started it, I was hoping to learn a little bit myself about XForms, as teaching a new technology is, at least for me, one of the best ways I can think of to learn one. However, along the way, I have learned quite a bit, both good and bad, about this technology, and have to admit that I see far more potential in it now than I did when first I addressed the issue in Revisiting XForms.
XForms is not perfect - there were times when I was working on things that I found XForms to be very limiting indeed, sometimes over the most trivial issues. Working on an in-progress implementation certainly didn’t help with this, of course, though I will readily admit that, even unfinished, the Mozilla Firefox XForms implementation is very, very effective, something I’ll say more about at the end of this article.
XBL Redux
I’ve already dealt with XBL previously in this series, but at the time specifically avoided getting into the use of such bindings much beyond creating simple replacements for certain elements (such as displaying images rather than URIs in output elements). However, as part of the advantage of the Mozilla XForms implementation comes in its integration with XBL, I felt it was worthwhile to readdress the XForms/XBL connection in a little more depth.
The first facet about XForms that I wanted to explore is its dirty little secret - a small amount of the XForms implementation exists as a set of binary services, largely for performance sake. However, probably 95% of the actual XForms implementation is written in … XBL. In other words, at least on the Mozilla platform, what you are in fact doing when you create an extension to a given XForms element is simply subclassing the existing XBL implementation. Once you understand this, you can do an incredible amount of magic without ever having to bother with powering up a compiler.
This implementation exposes a number of system defined interfaces that you can access
through JavaScript. For most components, the base object that’s exposed is the
nsIXFormsUIWidget object, which provides a number of virtual
methods and properties that can be subclassed. This interface is, for the most part
expressed as part of a specialized object called the accessors object
(nsIXFormsAccessors), which has the following properties:
| getValue() | This returns the rectified value of the binding for the given object, in its pre-defined schema type. |
| QueryInterface() | This provides the interfaces necessary to do discovery on the object. Seldom used from JavaScript. |
| setValue(val) | This sets the value of the data element bound to the component. |
| isReadonly() | This (read-only) property determines whether the object in question can be written to or not. |
| isRelevant() | This (read-only) property determines whether the object is relevant (has a
bound node with relevant = "true|false"). |
| isRequired() | This (read-only) property determines whether the object is required (has a
bound node with required = "true|false"). |
| isValid() | This (read-only) property determines whether the object is valid based upon the constraints set upon it |
| hasBoundNode() | This returns true if the object currently has a bound node in the data model that it is associated with. This is false if the node was calculated from multiple bindings. |
| getBoundNode() | This returns the bound node from the data model that’s associated with the component, if such a binding exists. |
| setContent(containerNode,forceUpdate) | In certain cases the content of a given element in the data model consists of more than just a text string, but may be an entire set of nodes. In that particular case, you would use setContent method to take the contents of a given container node, copy them, and place the results into the model. If forceUpdate is true, this will automatically update the model and force a refresh of the XFOrms elements on the page. |
The accessors object provides a low level interface that is inherited by
all XForms UI Widgets, although each individual element may also extend this with
additional properties on the object itself. For most of the core input and output
type elements, the interfaces share a great deal in common, with most of
these interface methods described as follows:
| _control | Internal variable for control, which should be used
instead. |
| _delegate | Internal variable for delegate, which should be used
instead. |
| _accessors | Internal variable for accessors, which should be used
instead. |
| widgetAttached | Method used by the internal delegate handlers for the components. Should generally not be used from JavaScript. |
| getXFormsAccessors | This retrieves the accessors object. |
| reportError | This returns the error object populated when an error occurs |
| getControlElement() | This returns the underlying XHTML object that generates the primary control, such as a span for an output or an input text box for an input control. |
| refresh() | This method is invoked whenever the underlying XForms model is refreshed, and can be overridden to provide custom update to the component in question. |
| focus() | This method is invoked whenever the control receives the focus, and can be overridden in order to update the component upon receiving the onfocus() event. |
| updateInstanceData | This invokes a rebuild() and recalculate on the underlying data model’s instance associated with the bound object. |
| disable(disableState) | This disables the control, and sets the requisite hooks so that any CSS disable rendering is provided. The object will not update itself until this is restored. |
| accessors | This is an object containing the various accessors methods. |
| stringValue | This is a read-write property for either reading or setting the value of the component, given as a string. |
| delegate | This is an internal representation of the object itself. |
| XFORMS_NS | This is the XForms Namespace - “http://www.w3.org/2002/xforms” |
| dispatchDOMUIEvent(eventname) | This is used to notify the XForms system that the DOM UI has been refreshed. |
| dispatchXFormsNotificationEvent(eventname) | This is used to notify the XForms system that the model has been modified. |
| control | control description |
The control object is fairly important within the general API - it is
essentially the XHTML component that either receives or displays the information
bound from the model, and as such exists as a somewhat privileged entity. When you
set the .xf-value class in CSS, what you are actually doing is setting the styling
for this particular control. Since subclassing an XForms object usually entails
modifying or replacing this particular control, knowing what the control is in the
first place is crucial.
An example at this stage could prove useful to understanding in a little more detail what exactly is going on with these commands. The output element is one of the more intriguing in the XForms panoply, in great part because it is so easy to subclass and its uses are fairly obvious. For instance, suppose that a particular element in the model (call it description) contained XHTML comment to display. This would be very difficult for “stock” XForms to handle, but its not hard to imagine an output element of the form:
<xf:output ref="description" appearance="xhtml"/>
Fortunately, with XBL, you can create a binding on any attribute using a CSS statement that points to the binding:
@namespace xf url('http://www.w3.org/2002/xforms');
xf|output[appearance='xhtml'] {
url('xformsExtensions.xml#output-xhtml');
This is displayed in the Listing 1, xformsXBL1.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events">
<head>
<title/>
<xf:model>
<xf:instance>
<data xmlns="">
<description xmlns:h="http://www.w3.org/1999/xhtml">
<h:div>
<h:h3>Message</h:h3>
<h:p>This is a message describing meaningful, signficant and important
content ... really!</h:p>
<h:p>
<h:i>Along with a completely unimportant and irrelevant
message.</h:i>
</h:p>
</h:div>
</description>
<description xmlns:h="http://www.w3.org/1999/xhtml">
<h:div>
<h:h3>A second message</h:h3>
<h:p>Here's an even more basic message that the previous one, perhaps
not quite as insightful, but nonetheless still relevant.</h:p>
<h:p>
<h:i>Along with another completely unimportant and irrelevant
message.</h:i>
</h:p>
</h:div>
</description>
<description xmlns:h="http://www.w3.org/1999/xhtml">
<h:div xmlns="http://www.w3.org/1999/xhtml">
<h:h3>The final message</h:h3>
<h:p>This is the end-all and be-all (or at least end-all) of the
messages. This is it, there ain't no more.</h:p>
<h:p>
<h:i>Except this message, of course.</h:i>
</h:p>
</h:div>
</description>
</data>
</xf:instance>
</xf:model>
<style type="text/css">
@namespace xf url('http://www.w3.org/2002/xforms');
xf|output[appearance='xhtml'] {-moz-binding:url('xformsExtensions.xml#output-xhtml');}
</style>
</head>
<body>
<xf:trigger>
<xf:label>Message 1</xf:label>
<xf:toggle case="btn1" ev:event="DOMActivate"/>
</xf:trigger>
<xf:trigger>
<xf:label>Message 2</xf:label>
<xf:toggle case="btn2" ev:event="DOMActivate"/>
</xf:trigger>
<xf:trigger>
<xf:label>Message 3</xf:label>
<xf:toggle case="btn3" ev:event="DOMActivate"/>
</xf:trigger>
<xf:switch>
<xf:case id="btn1">
<xf:output ref="description[1]" appearance="xhtml"/>
</xf:case>
<xf:case id="btn2">
<xf:output ref="description[2]" appearance="xhtml"/>
</xf:case>
<xf:case id="btn3">
<xf:output ref="description[3]" appearance="xhtml"/>
</xf:case>
</xf:switch>
</body>
</html>
It’s worth noting such things as the use of the XHTML namespace for the content
within the <description> blocks.. This code creates a
switch view (akin to a set of three tapped pages) with each page holding a single
XHTML block of content. Clicking on the buttons above the content bring up the
appropriate page. Also, while this has the content inline, a more realistic
application would likely have this data referenced via the
<xf:instance>’s src attribute.
The specific binding file itself is pretty typical for such XForms bindings, and is shown on Listing 2, XFormsExtensions.xml:
<xbl:bindings xmlns:xbl="http://www.mozilla.org/xbl"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms">
<xbl:binding id="output-xhtml"
extends="chrome://xforms/content/xforms.xml#xformswidget-base">
<xbl:content>
<span style="display:none;">
<xbl:children/>
</span>
<div anonid="content">
</div>
</xbl:content>
<xbl:implementation implements="nsIXFormsUIWidget">
<xbl:method name="refresh">
<xbl:body><![CDATA[
var content = document.getAnonymousElementByAttribute(this,"anonid","content");
while (content.firstChild != null){
content.removeChild(content.firstChild);
}
var boundNode = this.accessors.getBoundNode();
for (var index=0; index != boundNode.childNodes.length;index++){
var newNode = boundNode.childNodes.item(index).cloneNode(true);
content.appendChild(newNode);
}
return true;
]]></xbl:body>
</xbl:method>
</xbl:implementation>
</xbl:binding>
</xbl:bindings>
The first point to note within the binding is that the screen is redrawn via the
refresh() method, which is automatically invoked by the XForms
engine whenever the control needs to be redrawn (including the first time it’s
rendered). For this reason, unless you are initializing state variables within the
binding, it is far more likely that the code you write will likely end up in
refresh() rather than putting such code in the constructor block.
The getBoundNode() method is the key to doing most of the work here. The bound node
is the node that the <xf:input> or
<xf:output> watches (or modifies) via the
ref node, though if the component uses a bind attribute
instead, then getBoundNode() will return the node referenced by the binding.
Finally, if any XForms component that supports it uses the value
attribute, then the bound node is the one that’s implicitly referenced by the
current context.
The <xbl:content> node exists to do a couple of things.
First, it overrides the existing control, so that the output isn’t directed into the
existing objects. Additionally, all of the children of the control (labels and so
forth) are also redirected into a hidden <div> element -
they are still accessible, but they aren’t explicitly displayed. You can retrieve
the children by using the getElementsByTagNameNS() function. For instance, the
following retrieves the <xf:label> node, if it exists,
for the control:
var label = this.getElementsByTagNameNS(this.XFORMS_NS,"label")[0];
Finally, once the bound node is retrieved, the component should empty out the existing content within the display portion of the control, a process that is accomplished by removing the first element of the control’s children until there are no such elements left:
while (content.firstChild != null){
content.removeChild(content.firstChild);
}
If this step is left out, then the new content will appear after the existing content, rather than replacing it. While generally this isn’t desireable, it can come in handy if you are wishing to create a log or similar archive of your actions (you’d use insertBefore() rather than append() of course to put the most recent items of the log on top, rather than on the bottom.
Note that you can similarly pull in external resources using XMLHttpRequest from within a binding. In this case, the bound object is a URL that can be loaded in and displayed in a similar manner to the above. Additionally, sub-document references (via hash marks (#) in the URL) make it possible to retrieve subordinate content from an external document - something that can be accomplished easily enough with JavaScript.
The one change in approach here comes in the use of a slightly different attribute -
mediatype, rather than appearance, within the input or
output element. The mediatype attribute is part of the XForms 1.1
specification, which will likely be supported by Mozilla Firefox in the near future
but which currently is outside the scope of development, and is intended to provide
some indicator to how the referenced resource will be displayed. Listing 3,
xformxXBL2.xhtml, shows how this slightly changed attribute would be declared:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events">
<head>
<title/>
<xf:model>
<xf:instance>
<data xmlns="">
<description>messages.xhtml#msg1</description>
<description>messages.xhtml#msg2</description>
<description>messages.xhtml#msg3</description>
</data>
</xf:instance>
</xf:model>
<style type="text/css"><![CDATA[
@namespace xf url('http://www.w3.org/2002/xforms');
xf|output[mediatype='xhtml'] {
-moz-binding:url('xformsExtensions.xml#output-type-xhtml');}
]]></style>
</head>
<body>
<xf:trigger>
<xf:label>Message 1</xf:label>
<xf:toggle case="btn1" ev:event="DOMActivate"/>
</xf:trigger>
<xf:trigger>
<xf:label>Message 2</xf:label>
<xf:toggle case="btn2" ev:event="DOMActivate"/>
</xf:trigger>
<xf:trigger>
<xf:label>Message 3</xf:label>
<xf:toggle case="btn3" ev:event="DOMActivate"/>
</xf:trigger>
<xf:switch>
<xf:case id="btn1">
<xf:output ref="description[1]" mediatype="xhtml"/>
</xf:case>
<xf:case id="btn2">
<xf:output ref="description[2]" mediatype="xhtml"/>
</xf:case>
<xf:case id="btn3">
<xf:output ref="description[3]" mediatype="xhtml"/>
</xf:case>
</xf:switch>
</body>
</html>
This assumes that the messages in the previous example were consolidated into a single XHTML document and assigned reference ids, as shown in messages.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div id="msg1">
<h3>Message</h3>
<p>This is a message describing meaningful, signficant and important
content ... really!</p>
<p>
<i>Along with a completely unimportant and irrelevant
message.</i>
</p>
</div>
<div id="msg2">
<h3>A second message</h3>
<p>Here's an even more basic message that the previous one, perhaps
not quite as insightful, but nonetheless still relevant.</p>
<p>
<i>Along with another completely unimportant and irrelevant
message.</i>
</p>
</div>
<div id="msg3">
<h3>The final message</h3>
<p>This is the end-all and be-all (or at least end-all) of the
messages. This is it, there ain't no more.</p>
<p>
<i>Except this message, of course.</i>
</p>
</div>
</body>
</html>
The code in the binding has also changed, in this case, making an AJAX call to
retrieve the content, then parsing the URL to determine whether it includes a hashed
id indicator. If it does, then the document retrieves a copy of the node
corresponding to that particular entity, otherwise it just clones the entire
document. Either way this new node is then appended to the content node, just as in
the previous example. This is shown in the new binding
output-type-xhtml:
<xbl:binding id="output-type-xhtml"
extends="chrome://xforms/content/xforms.xml#xformswidget-base">
<xbl:content>
<span style="display:none;">
<xbl:children/>
</span>
<div anonid="content">
</div>
</xbl:content>
<xbl:implementation implements="nsIXFormsUIWidget">
<xbl:constructor><![CDATA[
]]>
</xbl:constructor>
<xbl:method name="refresh">
<xbl:body><![CDATA[
var component = this;
var url = this.accessors.getValue();
urlArr = url.split('#');
path = urlArr[0];
hashId = urlArr[1];
var http = new XMLHttpRequest();
http.open("GET",path,true);
http.onreadystatechange = function(){
if(http.readyState == 4){
var xmlDoc = http.responseXML;
if (hashId != null){
var elt = xmlDoc.getElementById(hashId).cloneNode(true);
}
else {
var elt = xmlDoc.documentElement.cloneNode(true);
}
var content = document.getAnonymousElementByAttribute(
component,"anonid","content");
while (content.firstChild != null){
content.removeChild(content.firstChild);
}
content.appendChild(elt);
}
}
http.send(null);
return true;
]]></xbl:body>
</xbl:method>
</xbl:implementation>
</xbl:binding>
which is also contained in the XFormsExtensions.xml file.
The last example I give with a certain degree of trepidation, because while it opens
up whole avenues of development it also has the potential to break the spirit of
XForms, because it provides a way to introduce scripted content into the XForms
model that may produce potentially disastrous side-effects. It is, again, an
extension of the <xf:output> object, but in this
particular case nothing is actually visually displayed. Instead, it provides
functionality similar to the <xf:setvalue> command, but
in this case takes the referenced node (or its value), passes this to a JavaScript
call, then if a target XPath expression relative to the bound node is given, places
the result into the node given by the expression.
An example of how this can be called is shown in Listing 4, xformsXBL3.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events">
<head>
<title/>
<style type="text/css"><![CDATA[
@namespace xf url('http://www.w3.org/2002/xforms');
xf|output[javascript] {-moz-binding:url(
'xformsExtensions.xml#output-javascript');}
]]></style>
<script type="text/javascript">
var sigDigits = Math.pow(10,6);
function dsin(angle){
return Math.floor(Math.sin(Math.PI * angle/180) * sigDigits)/sigDigits;
}
function dcos(angle){
return Math.floor(Math.cos(Math.PI * angle/180) * sigDigits)/sigDigits;
}
function dtan(angle){
return Math.floor(Math.tan(Math.PI * angle/180) * sigDigits)/sigDigits;
}
</script>
<xf:model>
<xf:instance>
<data xmlns="">
<angle>45</angle>
<sine>0</sine>
<cosine>1</cosine>
<tangent>1</tangent>
</data>
</xf:instance>
</xf:model>
</head>
<body>
<xf:output ref="angle" javascript="dsin(current())"
target="../sine"/>
<xf:output ref="angle" javascript="dcos(current());"
target="../cosine"/>
<xf:output ref="angle" javascript="dtan(current());"
target="../tangent"/>
<xf:input ref="angle" incremental="true">
<xf:label>Angle: </xf:label><br/>
</xf:input>
<xf:output ref="sine">
<xf:label>Sine: </xf:label><br/>
</xf:output>
<xf:output ref="cosine">
<xf:label>Cosine: </xf:label><br/>
</xf:output>
<xf:output ref="tangent">
<xf:label>Tangent: </xf:label><br/>
</xf:output>
</body>
</html>
The particular nodes that support the JavaScript transactions are defined (in CSS) by
having the javascript attribute. This can invoke any JavaScript
function (or evaluate any expression) including functions that are defined within
the global context of the page. This is demonstrated here with the use of the dsin
(Degree Sine), dcos and dtan functions, which are defined in the script block at the
beginning of the XHTML file.
The behavior defines three functions which can be used to access important properties:
- current(). This returns the value of the currently bound node as a string,
- currentNode(). This returns the bound node itself, and can be used to perform navigation relative to the node within the larger model,
- instance(id). When passed the id of an instance element, this returns the current instance node, which may differ from the original instance node downloaded from the web.
These are JavaScript functions that exist within the scope of the binding, so you don’t need to worry about global functions of the same name overriding them.
The <target> attribute creates a new binding - once the
javascript expression evaluates, if a target is defined (using XPath notation), then
the result of that evaluation is placed into the target node. Note that if no target
node is specificied, the JavaScript expression will still be evaluated (and any side
effects run) but no direct assignment into the model takes place.
The behavior for making this work is relatively simple, and is shown in Listing 6, output-javascript.
<xbl:binding id="output-javascript"
extends="chrome://xforms/content/xforms.xml#xformswidget-base">
<xbl:content>
<span>
<xbl:children/>
</span>
<span anonid="content"> </span>
</xbl:content>
<xbl:implementation implements="nsIXFormsUIWidget">
<xbl:constructor>
this._escapeUpdate = false;
</xbl:constructor>
<xbl:method name="refresh">
<xbl:body><![CDATA[
if (!this._escapeUpdate){
var boundNode= this.accessors.getBoundNode();
var js = this.getAttribute("javascript");
var target = this.getAttribute("target");
var xpe = new XPathEvaluator();
var xpr = xpe.createNSResolver(boundNode);
var xpResult = xpe.evaluate(target,boundNode,xpr,0,null);
var targetNode = xpResult.iterateNext();
function current(){
return boundNode.textContent;
}
function currentNode(){
return boundNode;
}
function instance(id){
var instanceNode = document.getElementById(id);
var modelNode = instanceNode.parentNode;
return modelNode.getModelInstance(id);
}
var str = new String(eval(js));
if (targetNode != null){
targetNode.textContent = str;
}
this._escapeUpdate = true;
var models = document.getElementsByTagNameNS(
this.XFORMS_NS,"model");
for (var index=0;index != models.length;index++){
var model = models[index];
model.rebuild();
model.recalculate();
model.revalidate();
model.refresh();
}
this._escapeUpdate = false;
}
return true;
]]></xbl:body>
</xbl:method>
</xbl:implementation>
</xbl:binding>
The refresh() method here can be broken into roughly three parts. The
first part retrieves the values from the attributes, and converts them into objects.
This section includes the use of the XPathEvaluator to perform the XPath on the
initial bound context node in order to retrieve the target nodes. Notice that this
makes the assumption that the desired target node is within the same XML tree as the
initial node - I leave it as an exercise for the reader to integrate an XPath
instance method in order to extend the search outside of the initial tree.
The second part of the method defines the JavaScript current(),
currentNode(), and instance() methods to be evaluated
within the JavaScript expression, then evaluates this expression and (if a target
has been defined) assigns it. Please note that the use of the eval() here has the
potential to be a security hole, so some thought should be given to sanitizing any
expressions before evaluating them.
The final block starts with the setting of the this._escapeUpdate
property. This property solves a rather thorny problem. In order to recalculate and
update the form, each model must run the four methods rebuild(),
recalculate(), revalidate() and
refresh(). However, normally, in doing so, this would also cause the
<xf:output> objects itself to refresh, which would
launch this object’s refresh method again, and eventually cause a stack overflow.
The solution here is straightforward - the object defines the
_escapeUpdate property and initially sets it to false. During the
course of the first refresh(), this property is set to true prior to invoking the
refresh method for the model, which means that if the model is currently updating,
then the refresh call will encounter the initial if test and fail
through. Once the model has been updated (here a synchronous operation) then the
property is set back to false.
The approach taken care solves a number of the more vexing issues when dealing with XForms - the lack of a formal extensible mechanism that can be accessed from within XPath, the inability to invoke external function calls when a critical property changes, and ways of making the UI components even more interactive, but this comes at something of a price in terms of debugging and code development. In general, if you do use this approach, avoid side-effects that may transparently change the data model or otherwise affect the operation of XForm components.
The State of the XForms Industry
I’ve worked fairly extensively with AJAX, and the current deep interest in AJAX programming has made a lot of people more cognizant about a number of deep seated design issues that seem to define the current state of software development.
- Distributed programming, in any guise, is hard, and only by keeping programming at the endpoints relatively simple can you manage to keep all but the most basic web applications from unravelling. This usually translates into a need to keep frameworks small, lightweight and manageable, always a challenge when the underlying trend in most frameworks is to increase complexity or rigidity in the environment.
- Declarative systems, whether embodied by XML, JSON, YAML and so on, provide a way of letting people manipulate complex objects without needing to impute semantics to those objects. The more you can avoid resolving semantics until absolutely necessary, the easier it is to deal with the transport and transformation of such code, and the more clearly decoupled such applications tend to become.
- Declarative systems are inherently secure, until such point as you resolve the semantics of the system (in that respect they are a lot like quantum entities that maintain a multiplicity of states until such time as you open the lid on the box to determine whether you have a very dead or a very pissed cat). Of course, such declarations are fundamentally useless until you do resolve semantics, so it behooves systems developers to insure that your XML objects (or other declarative entities) are clean and safe before you impute semantics onto them.
- Imputing semantics generally requires the use of some binding language. The more that you can minimize the need for these bindings to be public, the more stable and secure your code will be, and the less likelihood you will run into namespace collisions or unanticipated component interactions, something that tends to be a major problem with many JavaScript implementations.
- This implies that, in order to reach a level of abstraction beyond simple “scripts”, regardless of the language, the imperative language (JavaScript, for instance) should in general support the bindings “beneath the covers” by creating a one-to-one relationship between the bound entity (the XML object) and its associated behaviors.
- By that light, XForms, given that it both provides a mechanism for working with information in a model-view-controller manner, also has the advantage of being bindable - in other words, the language provides a set of pre-defined (and standardized) behaviors on abstract objects while at the same time opening up those objects to new ways of being rendered in the final presentations … in essence, letting users establish new behaviors on top of the old ones.
In other words, I see XForms as being an integral part of the future of such technologies as AJAX, as it provides a standard means of defining common behaviors while at the same time being extensible to allow for new behaviors. There is a tendency among programmers to look upon “competing” technologies as being all or nothing propositions - you either adopt XForms or you adopt AJAX, for instance - but I’m far more inclined to see XForms as being one of potentially many integral pieces that AJAX can use to establish more formal frameworks, especially given that AJAX by its very nature is largely the use of existing open standards (XHTML, JavaScript, CSS, XML, XMLHttpRequest, etc.).
Let me state that again in a slightly simpler fashion - XForms is part of the future of AJAX - providing a cohesive and time-tested framework at a time when the AJAX community is desperately trying to come up with one.
By itself, XForms is an interesting technology but one that might potentially always be a “specialist tool”. AJAX, while powerful, has security problems, lacks the mechanisms to abstract (or scale) well, and runs into implementation problems that will likely always be an intrinsic brake to the language’s adoption. Together I think the two technologies complement one another well, providing a powerful combination that can be readily adopted on any browser or stand-alone platform.
I see the Mozilla implementation as being a proof of concept that, once demonstrated, will likely prove attractive to other browser vendors and developers as well, for quite a number of reasons. The ability to make better forms is of course a part of this, a part that is likely to prove far more attractive to enterprise managers than it will the MySpace crowd, but realistically so much of what we currently use browsers for ultimately comes down to the expressive display of complex information, which is what forms are all about.
For instance, a few days ago I was at my local library and using the online catalog to find some science fiction books written by L.E. Modessit (one of my favorite authors, and well worth the reader). The interface was written for output on a Mozilla browser running on a Linux system. However, it was painfully slow, required navigation in ways that were neither intuitive nor always predictable, and I suspect that the Greater Victoria Library System likely paid a pretty penny to have it developed.
An XForms solution would have made it possible to separate the GUI presentation logic from the data-binding, minimizing the laboriously long waits as the server spent time generating complex markup. Indeed, at least a significant proportion of the application could have been downloaded just once, then repopulated with new content simply by changing the source of the data instance — without the need of rebuilding each page from scratch. It would likely, at least in the hands of a decent XForms developer, have taken a third or less of the time it took to create the server-centric one, and by moving most of the presentation logic to the client using a declarative structure, the application would have at least seemed faster and more responsive.
Admittedly, today, those XForms developers are few and far between. I don’t see this staying the case, however. Ever more data is being moved into XML - whether as data objects, documents, configuration resources or transport protocols - and as this process continues, “holistic” solutions that are XML aware at the pre-semantic level will tend to trump imperative solutions which attempt to impose semantics too early, even up to DOM manipulating code.
The presence of XForms in Mozilla natively, and through AJAX frameworks such as Orbeon non-natively, mean that people can create fairly sophisticated application GUIs without the need to ship large binaries or have Java or ActiveX support enabled … and can do it without having to worry about distribution costs or licensing restrictions. Coupled with binding languages, the expressiveness of XForms improves dramatically as well, letting you do with one well placed tag and a behavioral declaration what might take hours and lots of debugging headaches with other platforms - and because you can create such libraries of behaviors this becomes a solution which is scalable from both a development and a deployment standpoint.
In the end any web solution lives or dies based upon the degree to which it reduces development costs while improving performance. Given the benefits, I see XForms becoming very big within the next few years, perhaps in many ways as important as XHTML itself will likely end up being.
Tomorrow and tomorrow and tomorrow … I’ve begun developing commercial applications around XForms, something which I will discuss in a few months when it might less jeopardize the endeavors, but I keep coming back to this interesting paradox. The applications which I build exist almost exclusively within the constraints of the XML space. The server side code I need is lightweight to the point of absurdity, coming as it did from a decision to avoid getting wrapped up in frameworks. I transform code with XSLT and EXSLT, perform validation of business logic with schematron and more transformations, generate forms from schemas balanced by a separation of presentation layers via CSS, use XForms and XBL on the client to build the interfaces and marshal the results, again coupled with the occasional transform or query, and I use an XQuery interface and some limited Sparql processing to provide some semantic business rules constraints.
The curious thing is that the applications, ones that in other frameworks end up taking man-years and are notoriously brittle, seem to naturally flow out of the movement of the XML through the system. I’ve written in the past about the kudzu nature of XML - that once you introduce XML into a system it tends to induce a phase shift within that system, replacing complex semantics with neutral abstractions and just-in-time semantic resolution.
XForms is a key to this process - once you introduce it into your systems you’ll wonder why you spent so much time wrapped up in imperative frameworks. Especially in conjunction with both XHTML and some kind of a binding language such as XBL, XForms brings a means of building and distributing applications cleanly, reducing your dependency upon server side parsing of text strings and the expensive process of maintaining complex session state on servers.
The XForms solution out of Mozilla has been the focus of this series, but there are other implementations out there. Orbeon is an AJAX based XForms implementation that can be run effectively on Internet Explorer (and I believe they either have or have in the works a Mozilla implementation). I’d heartily recommend it in those cases where you need cross-platform AJAX support.
IBM recently acquired PureEdge, a forms based solution that includes an XForms implementation, and is now marketing the product as the IBM Forms ??. A number of key people (and colleagues that I have a lot of respect for) are involved with this particular product, including John Boyer, the current editor of the XForms 1.1 specification for the W3C.
X-Port’s FormsPlayer engine was one of the first XForms engines that I played with, nearly five years ago now, and it is still one of the best such engines for use within Internet Explorer. Mark Birbeck, the architect of the original application, has been heavily involved with the W3C’s XForms efforts.
Open Office 2.0 also has a remarkably robust XForms engine, one which is remarkably capable of generating sophisticated forms using a WYWSIWYG forms editor, and I will be writing additional articles about utilizing the XForms engine shortly.
There are a number of others. I am planning, in the near future, to cowrite a benchmark suite comparing performance, compliance and utility of various XForms engines, as the field is now getting robust enough that such studies are dealing with mature products and projects rather than betas and one-offs.
Launching XForms.org
Given all of this, I was fortunate in getting the chance to acquire the domain xforms.org. There are a few domains which I see as being both primal and that have the potential to become major nexus points on the web, and I believe strongly that this is one of them. To that end, as I’ve been working on this series I have also, in the background, been working on creating a portal at www.xforms.org that will be a focal point for covering news of the XForms industry, benchmark studies, code implementations , business articles and viewpoints and similar works.
It’s purpose is simple - I want to see XForms succeed. I want to encourage the adoption of the open standard, I want to see people who work hard building implementations or mastering the intricacies of developing applications with XForms get recognized for their work, I want to see companies that have bet the farm on bringing XForms to the masses prosper, and I want people to have a place where they can learn how to use the technology.
The site is still in its infancy - I am attempting to balance getting it launched with other outstanding obligations, but I plan to have discussion groups (with mail-list support), newsfeeds, and sample code repositories up shortly. I want this to be the nucleus for a new XForms development community, one that’s open to all people and that, while I hope to address issues pertinent to specific implementations, will nonetheless be open to people working with all implementations.
What I am seeking now are people who would be interested in writing blogs or articles, companies that would be interested in setting up sections within the site to promote their own products, and people willing to pass on news about their XForms related applications. If you are interested in any of these, (or if you are interested in getting an xforms.org email address) please contact me at kurt.cagle@xforms.org..
For those of you who have stuck with me through this series, I wish to express my appreciation, and a request that you contact me as well to express your thoughts on what you’d like to see in subsequent series and columns. I think the time for XForms is nearly at hand, and it should be an interesting ride …
Kurt Cagle is an author, technology evangelist, and software developer specializing in XML, AJAX and web technologies. He lives in Victoria, BC, where he is helping to coordinate the SVG Open 2006 conference (more information about which will be in the next column).


Give me a print stylesheet or something equivalent please! I need to print this! :-)
Kurt you type faster than I can read.
Great article and excellent news you've set up xforms.org. Even though I don't have the time for it now you can be sure I'll try to pop in soon enough.
- Sylvain
FormFaces is a pure JavaScript solution that utilizes AJAX techniques and can be seamlessly integrated with AJAX applications. This means that XForms+HTML can be sent directly to the browser where JavaScript transcodes the XForms controls to HTML form controls and processes the binding directly within the browser - requiring zero server-side processing and zero plug-ins. FormFaces is extremely simple to use, just insert the following tag into your XForms+HTML document:
<script type="text/javascript" src="formfaces.js"></script>
The FormFaces JavaScript is compatible with browsers that implement XHTML 1.0, ECMA-262 3rd Edition, and DOM Level 2 which includes Internet Explorer, Netscape, Mozilla, FireFox, Opera, Konquerer, Safari, and NetFront. To this end, the FormFaces framework enables:
1. Cross-browser support - existing client-side browser can be used.
2. Server-side technology agnostic - the same forms can be used across disparate frameworks such as Java and .Net.
3. Offline mode - user interaction does not require server round-trips.
FormFaces also enables Web 2.0 APIs, such as Google Maps, Yahoo Traffic Alerts, Kiko Calendar, and Skype Voice Service, to be easily integrated with XForms. This Web 2.0 and XForms integration is not yet well known.
We garner your efforts to benchmark performance, compliance and utility across various XForms engines. I suspect that not only deployment configurations are significantly different across implementations, but so are server CPU load, network bandwidth, user agent load and user interaction latencies. We will participate as needed to aid in this effort.
We are certainly interested in participating in your www.xforms.org portal site and truly appreciate your collaborative efforts in bringing us all together. I believe this will not only help the XForms initiative as a whole, but will help the implementation variants to better understand deployment and performance requirements and constraints, subsequently, maturing into numerous web form use cases. We will send you an email as requested. We will put a link and description of this initiative on our www.FormFaces.com website.
> Give me a print stylesheet or something equivalent please! I need to print this! :-)
I'm pulling these together at the XForms.org site and should have printable versions of them there as well - check back there in a few days.
How about your "The Power of Free" article? I'd like to print that one as well. :-)
Tips for Being a Successful Landlord
In today's apartment rental market there are several things that are "must do's" for becoming a successful landlord. The reason you're playing the real estate rental game is to have the check in your mailbox on the first of the month, right? Here are a few tips that can help you to achieve this with as little aggravation and frustration possible.
First and foremost is finding the right tenant to rent your apartment, house or other rental. This is the most important ingredient in the recipe. Checking the prospective tenant's credit history to make sure they are paying their bills is one of the best ways you can screen. A tenant that pays their bills on time most likely will send you their rent on time. Establish a clear system on collecting rent, handling complaints from the tenant and how you will contact them if you need to gain access to the apartment.
Secondly, get all the important terms of the tenancy in writing. You have the option to have a basic rental agreement or draw up a formal lease. Whichever you decide, the important thing is to document the terms that you and the tenant agreed to. Clarify who is paying the utilities, the rental price and any other agreements made between you and your tenant.
It's a good idea to stay on top of the repair and maintenance needs of your property. When you are notified of something that is broken or not working, repair it as soon as possible to prevent further damages. You may also lawfully enable the tenant to withhold rent, sue for injuries caused by defective conditions or move out without notice.
On a similar topic make sure you are carrying enough property and liability insurance to cover yourself in any situation. A well designed insurance program can protect your rental property from losses caused by everything from fire and storms to burglary, vandalism, and personal injury lawsuits.
I hope that this has been helpful to you. Just remember, as long as you follow these simple tips you will be on your way to a happy and fulfilling landlord future. Best of luck!
ABOUT THE AUTHOR: Eric Goldstein, associated with www.AllSpacses.com which Conveniently Connects All People with All Spaces in All Places, has been dedicated to the real estate rental market for over 8 years. He has assisted over 25,000 landlords with their renting needs. Any questions about renting apartments, houses or other rentals feel free to visit www.AllSpaces.com or email him at Eric@AllSpaces.com.
I am running this in Firefox 2.0 with the newest XForms plugin. To make the example that used javascript to calculate angles work, I had to surround the xbl file with:
<xbl:bindings xmlns:xbl="http://www.mozilla.org/xbl">
...Kurt's stuff goes here...
</xbl:bindings>
Hello Kurt,
what about xforms in relation to the openLaszlo approach? This isn't an explicit implementation, but it seems to me that it offers all the benefits of xforms.
Relating to Asbjørns question, where can I find print stylesheet as well as other articles about ajax? Ther are very informative and easy to follow...
Kirsten
I enjoyed reading this article, thanks
welker
Can I use AJAX on my blog. It would be such a improvement from a monotone and uniform templates that blogger uses.
Hello, I often read your blog, it's great.
lokey
bamba
technique usable on many different operating systems, computer architectures, and web browsers as it is based on open standards such as JavaScript and the DOM. There are free and open source implementations of suitable frameworks and libraries.