You are reading O'Reilly XForms Essentials by Micah Dubinko. (What is this?) - Buy XForms Essentials Online

Chapter 6. The XForms User Interface

"A human being should be able to change a diaper, plan an invasion, butcher a hog, conn a ship, design a building, write a sonnet, balance accounts, build a wall, set a bone, comfort the dying, take orders, give orders, cooperate, act alone, solve equations, analyze a new problem, pitch manure, program a computer, cook a tasty meal, fight efficiently, and die gallantly. Specialization is for insects."

Robert A. Heinlein

Form controls are windows onto the form data kept in the XForms Model. In principle, this was true also for HTML forms, although the design of XForms makes a much sharper separation.

The following sections describe every form control included in XForms. The examples show a variety of different binding techniques through the attributes ref, model, and bind, which are explained in Chapter 5, The XForms Model.

This form control is quite similar to its HTML forms counterpart, as it permits the entry of any character data. There are some significant improvements, however, such as the ability to use an XML Schema datatype to optimize the user experience of entering the data. Example 6.1, “Sample markup for an input control ” shows sample code for an entry control, and Figure 6.1, “Input form controls rendered with X-Smiles” shows several different renderings, selected by datatype, of an input control in the open source X-Smiles browser, available at http://www.x-smiles.org.

Almost any simpleType can bind to input, except the binary datatypes, like base64Binary, which don't make sense for manual entry and aren't allowed.

This is the only form control that doesn't accept user input, though once developers start using it, they can't imagine life without it. Output renders data from an XForms Model as inline text, normally indistinguishable from other text on the page. The same transformations that apply to text rendered in an input form control apply equally to output so that, for instance, numeric values will be correctly formatted to user expectations. Example 6.4, “Sample markup for an output control ” shows sample markup for an output control. Since the result of an output control is ordinary inline text, screen shots tend to be rather unimpressive.

Figure 6.4, “Output form control rendered with DENG” shows an output control alongside an input control, to demonstrate how it operates, running in the Mozquito DENG "Desktop Engine," available at http://mozquito.markuplanguage.net.

A couple of other design aspects of output stand out. For one, a label element is not required, for situations where only the dynamic content is required. The actual content taken from the instance data is rendered, usually in an inline manner that isn't stylistically distinguishable from surrounding text.

In some cases, the value to be displayed doesn't relate directly to an instance data node, but rather needs to be computed. To handle this common case, the attribute value, containing any XPath expression, can be used instead of the ref attribute, which can contain only an XPath path selection expression.

This control can bind to any simpleType, although it's not clear how binary items would be supported. Presumably, binary items, such as images, could be rendered as the content of this element.

HTML forms had a limited file upload control, but the XForms version surpasses it in many ways. Example 6.5, “Sample markup for the upload control ” shows sample code for an upload control, and Figure 6.5, “Upload form control rendered with FormsPlayer” shows the result rendered in X-Port's FormsPlayer, available at http://www.formsplayer.com.

The XForms specification names a number of possible input sources:

Control over what kinds of choices are presented falls to the mediatype attribute, which is a media (or MIME)-type string such as image/png or application/zip. If the specific subtype doesn't matter, it can be specified as the * character, as in audio/*. If this leads to a situation where no input is possible (for instance a request for video/* where there simply aren't any possible ways to generate a video file) the user has to be made aware of this problem rather than silently pretending it doesn't exist.

One unique aspect of this form control is that it can bind to the instance data in multiple places; for example, through the child elements mediatype and filename, each of which takes separate binding attributes. The actual media type and filename of the chosen data source, if known, are placed in the instance data. This is a one-way trip—these values are placed in the instance and not looked at again, and so are only for the benefit of the server application that processes the form data.

Only a binary-based type, such as base64Binary and hexBinary, or a derived datatype, can be used as the target of the uploaded data. Storing large amounts of binary data in XML poses some challenges, which are addressed in Chapter 8, Submit.

This form control represents selection from a list with the intent of enforcing the selection of exactly one item. In XForms, the list controls have a broader interpretation than in HTML forms. Any control that expresses the goal of picking things from a list, including conventional radio buttons and checkboxes fall into this category. Example 6.9, “Sample markup for the select1 control ” shows sample markup for a select1 control, and Figure 6.8, “Select1 form control rendered with nForms” shows this control rendered with Ripcord Technology's nForms, available at http://www.ripcord.co.nz/.

When the initial instance data contains a value (possibly even an empty value) that doesn't match any of the provided values, there will be no visible indication of what the selection is. Unlike the case with select, however, any user selection will replace the value in the instance data.

One special option with this form control is when the selection attribute is specified as open. This indicates that "free entry" is allowed, so that the user can either pick from the list or use input-style data entry to enter a value not originally in the list of items. The entered value is still subject to all the validation rules in XForms, including XML Schema datatype validation.

Some graphic designers are unnerved about the generality of this form control, and would prefer to explicitly indicate that they want, say, checkboxes instead of a drop-down list. The correct answer is, of course, to use CSS to style the control, as discussed in Chapter 9, Styling XForms. In the general case, however, there's no guarantee that CSS (or any other style language) will be available at the point where the form is displayed. This is what the appearance attribute is all about. Because this request happens so often, the XForms specification gives some guidelines on how to indicate at a high level the desired rendering of the form control:

The configuration of select1, as shown previously in this section, binds to any XML Schema simpleContent; that is, to any kind of text whatsoever. Another configuration of the selection controls binds to an entire element plus content for the selection made.

This form control represents selection from a list with the intent of allowing nothing, one thing, or multiple things to be selected. It shares many common features with select1. Example 6.10, “Sample markup for the select control ” shows sample markup for a select control, and Figure 6.9, “Select form control rendered with Novell XForms Technology Preview” shows this form control rendered with Novell's XForms Technology Preview, available at http://www.novell.com/xforms/.

The select form control is the most general kind of list, as it holds no restrictions on how many items the user may select from the list. When used as in the previous example, the resulting selections will be placed in an XML Schema space-separated list, and if any of the values contain whitespace characters, the list won't work as expected, because in the resulting confusion each space-separated token will be treated as a separate selection.

In this configuration, any initial data provided to the list needs to be a space-separated list. It is possible for the instance data to not match the values provided (through the initial value, or through direct manipulation of the instance data), in which case the form control is required to somehow notify the user that the data value is "out of range" (described more in Chapter 9, Styling XForms). In fact, unless the form control has an "unselect all" affordance, such orphan selections will be more or less stuck in the instance data. Needless to say, this is bad practice in form design, and should be avoided.

Like select1, this form control allows authors a measure of control over the rendering through the appearance attribute.

The configuration of select, as shown previously in this section, binds to any XML Schema datatype that can hold a space-separated list. Ideally, this would be a list-derived datatype, but many built-in datatypes (such as string) work, too. The following section describes a configuration in which each selection binds to an individual element plus content.

Lists as described in the previous two sections always bind to what XML Schema calls simpleContent, or text that (for example) could be in an attribute value. It's also possible to configure a select or select1 so that each selected item corresponds to an element in the instance data, and thus changing the selection has the effect of changing the instance data at a structural level.

Before describing how this works, it's necessary to take a brief diversion to see how lists can get their set of possible selections from instance data rather than hard-coded values as shown previously. Instead of individual item elements, it is possible for list controls to obtain the list of things from which to select through an itemset element, which selects multiple instance data nodes and produces a potential selection out of each. This example uses multiple XForms Models:

<xforms:model id="list_items">
  <xforms:instance>
    <options>
      <email desc="work address">mdubinko@example.info</email>
      <email desc="home address">mdubinko@example.org</email>
      <email desc="alternate address">nospam@example.net</email>
    </options>
  </xforms:instance>
<xforms:model>
...
<xforms:model id="form_data">
  <xforms:instance>
    <user_selection/>
  </xforms:instance>
</xforms:model>
...
<xforms:select ref="." model="form_data">
  <xforms:label>Send a copy to the following email addresses</xforms:
          label<xforms:itemset nodeset="email" model="list_items">
    <xforms:label><xforms:output value="concat('Your ', @desc)"/></xforms:label>
    <xforms:value ref="."/>
  </xforms:itemset>
</xforms:select>

The single itemset element is responsible for all of the list choices. In this example, that's three items since the nodeset="email" attribute selects three nodes from the XForms Model list_items. For each node, the child elements of itemset are evaluated in turn, with the node in question as the context node. Thus, the expression concat('Your ', @desc) produces three different labels, which happen to match the labels on the earlier select example. Similarly, the value elements are evaluated and converted into text strings that also match the earlier example.

For this to work, the node-set returned by the expression on the nodeset attribute must be homogeneous, that is:

The copy element serves the same purpose as the value element, except that instead of producing a text value to insert into the instance data, it does a "deep copy," including attributes, text, and child elements. Thus, the arrangement of the instance data for the list depends on whether it uses value or copy elements. With the first two items selected, the respective instance data would look like:

Instance data with <value>:
<user_selection>mdubinko@example.info mdubinko@example.org</user_selection>

Instance data with <copy>:
<user_selection>
  <email desc="work address">mdubinko@example.info</email>
  <email desc="home address">mdubinko@example.org</email>
</user_selection>

Note that in the second case, even the desc attribute is copied.

Overall, the behavior of itemset is very similar to repeat, which is discussed in the section called “Repeating Line Items”," later in this chapter.

There are elements and attributes that appear on many form controls.

A critical, but too often overlooked, part of a form design is configuring the navigation order. A Tab or Next key is a standard part of nearly every device these days, and it's important that the default path through a form makes life easier for the form users. The actual mechanism for navigation depends on the host language, although XForms defines a suggested minimum level of performance, based on an attribute that would appear on every form control.

The default rules for determining the navigation order are essentially unchanged from HTML forms: each control can have an attribute named navindex, which holds a number between 0 and 32767. (For programming geeks, this upper limit is the largest number that a signed 16-bit integer can hold.) The navigation order starts with 1 and proceeds to progressively higher numbers, and finishes with form controls that don't specify navindex (or equivalently, specify it as 0). In the case of a tie, the navigation follows the order that the form controls appear in the document. Groups, switches, and repeats form local navigation units, which means that all the form controls in that group will be navigated, following the same rules here, before the focus proceeds to other controls outside the group.

Through relevant (see Chapter 5, The XForms Model), it's possible to have form controls that are no longer effectively part of the navigation sequence. The XForms specification states that even when this is the case, those form controls still have a relative order assigned, even though they are skipped. This means that should the form control become relevant, it will find itself at the right place in the navigation order.

XForms doesn't define what happens when either end of the navigation order is reached, though browsers typically cycle back to the other end of the form, with a few stops in between for the browser itself. The host language also might contain various object that can be part of the navigation order. By giving the host language ultimate control, the overall sequence can be one that makes sense in the full context of the document.

Before I was exposed to the worldly ways of global computing, I had often pondered idly about how keyboards work for languages with thousands of characters. Just how many keys are on those kinds of keyboards, anyway? The problem of entering a language or script on a different keyboard than one for the native language is accomplished by a piece of software called an Input Method Editor, or IME. Through the inputmode attribute, XForms allows form controls that accept direct keyboard input to give a hint for the appropriate IME to switch to when first entering the form control. The content of this attribute is a space separated list of tokens, which fall into three categories: script tokens (see Table 6.1, “Script tokens”), modifier tokens (see Table 6.2, “Modifier tokens”), and URIs. As a general catch-all, any token not already in the list can be assigned a URI and used like any other token in the inputmode attribute.

Upon seeing the lists in Tables Table 6.1, “Script tokens” and Table 6.2, “Modifier tokens”, most users wonder why so many choices were included. Since the values are only hints, there's no additional cost associated with a long list, and the additional values might help certain classes of users. The list of the modifiers in Table 6.2, “Modifier tokens” is more generally useful, as it includes options for automatically controlling the case of input text, and other options that are especially useful for phone keypads, such as predictive text or digit-only mode.