The following sections describe all of the XForms Actions defined in XForms. Any of the following can be invoked in such a way that the processing described for the element happens in response to a given event.
This action directs a message to the user, with various possible levels of intrusiveness, based on the required attribute level. In scripting, this effect is commonly implemented with the alert( ) function, which is the most intrusive technique, since it is modal, and prevents any further action until the user dismisses the message. XForms enables friendlier (and less visual-centric) messages: modeless, which doesn't interfere with the rest of the form, but sticks around until dismissed; and ephemeral, a fleeting, goes-away-by-itself message, such as a tool tip or brief status bar message. Figure 7-2 shows visual representations of various messages. Figure 7-2. XForms Action: messageThe general concept of various levels of intrusiveness applies well to non-visual designs, too; for example, the difference between an insistent voice prompt that requires acknowledgement versus a one-time message. Typically, the content of the message element is the message to be rendered. Like other XForms elements, the content can also come from the instance data (from binding attributes) or from an external file (from linking attributes). Only a single source is ever used; the order of preference is: binding attributes, linking attributes, inline text, as shown next. <message level="ephemeral" ev:event="DOMFocusIn">Produced by PBP</message> <message level="modeless" model="messages" ref="instructions/part3" ev:event="xforms-help"/> <message level="modal" src="/books/2/308/1/html/2/important.html" ev:event="DOMActivate">
Binding attributes on this element select the location in the instance data to receive the value, which is always simpleContent. Note that XForms doesn't include a way to arbitrarily alter complexContent through XForms Actions, though the insert and delete actions can to a limited extent. Another job commonly reserved for scripting is to set values in the form, as shown in the earlier example in this chapter. This action can set the value of an attribute node or an element's text node, to either a fixed value or the result of evaluating XPath. The value to place in the instance is either an XPath expression, contained in the value attribute, or literal text as the content of the element. If both should happen to be present, the evaluated XPath is used. Clearing a value is the same as setting a zero-length string in other words, neither a value attribute nor element content. setvalue can be useful in several contexts, as shown here: <!-- on initialize, set a value of "0" --> <setvalue bind="frequency" ev:event="xforms-ready">0</setvalue> ... <!-- on initialize, copy the billing address to the shipping address --> <setvalue ref="Shipping/Addr" value="../Billing/Addr" ev:event="xforms-ready"/> ... <!-- clear a value when an Insert happens --> <setvalue bind="phone_num" ev:event="xforms-insert"/>
This action redirects the focus to a different form control. An attribute named control holds an IDREF of the form control that will get focus. In effect, this action does nothing more than dispatch an xforms-focus event to the form control indicated. It can be used like this: <setfocus control="Address_1" ev:event="xforms-ready"/>
This action invokes submission of a form. A required attribute submission holds an IDREF to a submission element that contains the details of what and how to submit. The effect is the same as dispatching an xforms-submit event to the submission element indicated. Details of submit options are discussed in Chapter 8. <send submission="submis3" ev:event="DOMActivate"/>
A reset control is probably the most overused form control on the web. (This is why XForms doesn't define a reset control) Still, in the right circumstances, it's necessary to reset a form, which is what this action does. It takes an attribute model, which contains the IDREF of the model element that will be reset. The reset condition is defined as the state the instance data was in immediately after the xforms-ready event was dispatched. reset can be used like this: <reset model="weather" ev:event="DOMActivate"/>
This action traverses a link, possibly in a new window (or browsing context for non-visual devices), possibly replacing the active form. The optional attribute show, which can have a value of either "new" or "replace", determines the behavior. The URL that the link goes to can either be specified in the resource attribute, or it can be in the instance data, pointed to by binding attributes (bind, or ref optionally with model).
Two ways to use the load action are like this: <load resource="http://www.example.com" ev:event="DOMActivate" show="replace"/> <load ref="linktable/nextpage" ev:event="DOMFocusOut" show="new"/>
This action works with a switch element, selecting by IDREF a particular case within. The selected case is rendered, while all other cases are not. The ability to show and hide sections is a handy way to implement a "multiple page" form, which guides the user through one section at a time. It's also useful within a page, to set up wizard-like sequences, or just to hide entire sections of the form that aren't needed at the moment. Each case contains a selected attribute, which stays in sync, so that at any given time one and only one of the cases in a switch will have selected="true". In fact, in systems that support CSS2 selectors, one possible implementation is with the rule case[selected="false"] { display: none }. The toggle action is used like this: <toggle case="summary" ev:event="DOMActivate"/>
This action works within a node-set, by constructing new nodes based on a template. The immediate problem with this approach is that if there are no nodes present in the repeating set (as can happen after invoking the delete action), what template can be used to copy from? The answer depends on the way instance data is constructed in XForms: as a separate in-memory representation. The initial instance data, as it appears inside the instance element in the containing document (or in an external linked file) doesn't change as the instance data changes through all the various interactions defined by XForms. Thus, the initial instance data is defined as the source of the template to be copied, even though it makes for some awkward terminology to explain how it works. The main attributes that control the operation of this element are:
The at attribute is evaluated as an XPath number, which creates a few edge cases that need to be addressed:
Once the location for the new node is determined, a new element node is manufactured by parsing the corresponding portion of the initial instance data, taking the final node present, which is deep copied into the instance data. This example demonstrates: <model> <instance> <order xmlns=""> <items> <item price="1.00"/> <item price="2.00"/> <item price="3.00"/> </items> </order> </instance> </model> ... <repeat nodeset="order/items/item"> <input ref="@price"> <label>Price</label> </input> </repeat> ... <trigger> <label>Insert a new item after the current one</label> <action ev:event="DOMActivate"> <insert nodeset="/order/items/item" at="index('repeat_id')" position="after"/> <setvalue ref="/order/items/item[index('lineset')]/@price"/> </action> </trigger> In this example, every time an insert action happens, the element node that gets copied is the one that reads <item price="3.00"/>, being the final member of the repeat set in the initial instance data. This is true no matter what insertions or deletions happen to the instance data. This example also shows following an insert with a setvalue, to give the newly-inserted node a desired value (in this case, empty). Another question that comes up is what model item properties apply to the newly-inserted nodes. All bind expressions that point into the repeat set are reevaluated, so the model item properties can be applied equally to the new nodes. As a typical result of insert, a new repeating item will be rendered in the user interface. The newly-inserted repeat item also becomes the repeat index, effectively giving focus to the new content.
This action is the counterpart of insert it removes nodes from the instance data. Without the issues of copying nodes from a template, the overall operation of this element is much simpler. This element also has an attribute named at, which operates the same way as insert. It identifies an element node that is removed, along with any associated nodes (content text nodes, child element nodes, attribute nodes, and so on). The corresponding user interface for the repeat will also adjust to the now smaller repeat set. This example continues the example in the previous section: <trigger> <label>Remove current item</label> <delete ev:event="activate" nodeset="/order/items/item" at="index('repeat_id')"/> </trigger>
Every repeat set keeps track of a current item, similar to a database cursor. The official term for this is the index. The index item behaves for multiple form controls much as a focus behaves for single form controls. In fact, setting the focus to a form control in a repeat set also adjusts the index to that spot. This action explicitly changes the index. Two attributes control the behavior of this element: repeat, which takes an IDREF of a repeat set, and index, which takes an XPath expression that evaluates to a number, just as the as attribute on insert and delete. setindex is used like this: <setindex repeat="repeat_id" index="1" ev:event="xforms-ready"/>
XForms keeps track of computational dependencies, like a spreadsheet, so that any chained calculations properly resolve themselves in the face of changes. This action explicitly invokes a rebuilding of the dependencies, and is almost never needed. These four actions trigger the processing involved with revalidation, recalculation, refresh, and rebuilding dependencies, respectively. Under normal conditions, all of these activities take place automatically, and form authors don't even need to consider these events or actions. The primary exception, however, is on limited platforms where any of these activities might be expensive, in terms of processing or perceived user delay. When that's the case, it's not desirable for these events to happen automatically. Instead, users will want to have greater control over exactly when such things happen. This is similar to the concept of spreadsheets that have an option to turn off automatic recalculation. To do this in XForms is a two-step process. First, an observer needs to be set up to cancel all automatically generated events for the expensive process (recalculation in this example). That step, by itself, will result in the recalculation never happening, which doesn't work so well. So the second step is to provide an option for the user to manually fire off a recalculate. This example shows both aspects: <model ev:event="xforms-recalculate" ev:defaultAction="cancel"> ... <trigger> <label>Recalculate now</label> <recalculate ev:event="DOMActivate"/> </trigger> Note that this works because the recalculate action directly invokes the processing, without the intervening event flow (which would get cancelled by the observer on model anyway).
This action dispatches any event to any element. In a sense, this is the most powerful XForms Action since, through events, nearly anything can be done. This element contains four special attributes. The two required attributes are name, which names the event, and target, which holds the IDREF of the element that will be the target of the event. Two other optional attributes (bubbles and cancelable) specify whether the event can bubble or be cancelled, though all the predefined events have their own specification and can't be overridden. An advanced technique is to create custom events, which can be dispatched and observed to accomplish specific behaviors, like this: <dispatch name="xforms-refresh" target="model3" ev:event="DOMActivate"/> <dispatch name="show-easter-egg" target="listener9" cancelable="false" ev:event="my-custom-evt"/>
This element is a wrapper for other XForms Actions. It contains child elements that are executed in sequence. action can be used like this: <action ev:event="DOMActivate"> <setvalue ref="email/contact" value="email/admin"/> <message level="ephemeral">Synchronized email addresses</message> </action>
|