Table of Contents | Prev | Next | Bottom |
Quick Table of Contents |
---|
8 XForms User Interface 8.1 Conditional Constructs For Dynamic User Interfaces 8.1.1 switch 8.2 Repeating Structures 8.2.1 Design Rationale 8.2.2 Special Event Handlers For Element repeat 8.2.3 repeat 8.2.4 Design Consequences 8.3 Reusable Form Controls 8.3.1 Creating User Interface Templates 8.3.2 DTD For uiTemplate And useUITemplate 8.4 Layout in XForms 8.4.1 Orientation and Direction 8.4.2 Alignment 8.4.3 Controlling Automatic Sizing 8.4.4 Preferred, Minimum, and Maximum Sizes 8.4.5 Packing Controls 8.4.6 Overflow 8.4.7 Inlines and Blocks 8.5 Multiple Sub-forms Or Sub-pages 8.5.1 Subpages |
The XForms User Interface allows the authoring of dynamic user interfaces, i.e., user interfaces that vary based on the current state of the instance data being populated. As an example, portions of a questionnaire pertaining to the user's automobile may become relevant only if the user has answered in the affirmative to the question 'Do you own a car?'. Another use case for such dynamic user interfaces is when the underlying XForms Model contains conditional structures.
Editorial note: Raman | |
Please do not attach semantics to the element name to prejudge the design. |
This element contains one or more
case
elements. Each
case
has an id
attribute
that is used within event handlers appearing
within the form controls to activate or deactivate
that portion of the user interface created by the markup
contained within that case
element.
<switch id="01" default="initial"> <case id="us"> <group> <caption>Please Specify a US Shipping Address.</caption> </group> </case> <case id="uk"> <group > <caption>Please specify a UK shipping address.</caption> </group> </case> <case id="initial"> <group > ... </group> </case> </switch> |
The above will result in the portion of the user interface
contained within the default case being
initially displayed.
Next, we define an XForms event handler toggle
below for
activating and deactivating different portions of this
conditional construct.
toggle
>
<toggle switch="switchID" case="caseID" /> |
Attribute
switch
identifies the switch constructor to be affected.
Attributecase
identifies the portion of theswitch
construct to activate.
In addition to event handler toggle
, event handler
scroll
might be used within construct switch
to cycle through
the various contained case
clauses.
The XForms Model allows the definition of repeating structures such as multiple items being purchased within a purchase order. When defining the XForms Model, such higher-level aggregations are constructed out of basic building blocks; similarly, here we define higher-level user interface constructs that build on the form controls defined previously, that can bind to data structures such as lists and collections.
The basic XForms form controls defined so far
permit populating data instances conforming to
Schema simpleTypes.
These form controls can be aggregated using
group
(see 8.4 Layout in XForms) to form higher-level user
interface form controls. As an extension to this, the user interface markup for
repeating structures only adds encapsulation metadata
about the collection being populated, as well as the
necessary controls needed for adding, deleting and
navigating the items in the repeating structure.
Finally, this section also defines relevant portions of the
processing model that track the item that is
current in a repeat structure..
Element repeat
encapsulates the following
pieces of metadata:
Binding expression specifying the collection to be
populated by the contained XForms form
controls.
This binding expression returns a node-set that
represents the collection of items over which
this repeat
will iterate.
Starting index of the first element from the collection to be displayed to the user.
Number of elements from the collection to be displayed to the user.
repeat
We define XForms-specific event handlers for
use within element repeat
.
These event handlers will appear within element
onevent
to specify the event handler to
trigger when an event is received by the containing
event listener.
In the examples below, we will assume event
dom-click
;
however, note that this specification does not normatively
define the mapping between physical events
and specific behaviors.
Construct repeat
introduces the notion of a
cursor that is maintained by
the XForms processing model for each repeating structure.
Thus, each repeat
has its own
a conceptual cursor.
Event handlers are provided for querying and updating the
position of this cursor;
this cursor position in turn is used for determining the
behavior of insert
and delete
.
Thus, these event handlers can be thought of as the markup
equivalent of the additions to the XForms DOM
introduced by construct repeat
.
setRepeatCursor
for marking an item as
being current.
setRepeatCursor
>
<setRepeatCursor repeat="repeatId" cursor="itemID"/> |
Attribute
repeat
identifies the repeat constructor whose cursor is to be updated.
Attributecursor
identifies the cursor position. It should be a binding expression that evaluates to an element of the node set being iterated over by this repeat construct.
getRepeatCursor
for accessing
position of the repeat cursor.
getRepeatCursor
>
<getRepeatCursor repeat="repeatId" /> |
Attribute
repeat
identifies the repeat constructor whose cursor position is to be obtained.
scroll
for changing item that is current.
scroll
>
<scroll repeat="repeatId" step="n" /> |
Attribute
repeat
identifies the repeat constructor whose cursor position is to be updated.
Attributestep
is an integer value that specifies the amount by which the list is scrolled. Negative values may be used to scroll the list in the reverse direction.
insert
for inserting an item at the current
cursor position into the
repeating structure. This causes the instantiation of
the necessary user interface
for populating a new entry in the underlying collection. It also
updates the instance data by instantiating the necessary
nodes.
insert
>
<insert repeat="repeatId" /> |
Attribute
repeat
identifies the repeat constructor being affected, and defaults to therepeat
construct within which this event handler appears.
delete
for deleting an item from the
repeating structure. This causes the destruction of
the necessary user interface for populating the entry
at the current cursor position in the underlying
collection. It also updates the instance data by
destroying the necessary nodes.
delete
>
<delete repeat="repeatId" /> |
Attribute
repeat
identifies the repeat constructor being affected, and defaults to therepeat
construct within which this event handler appears.
The event handlers enumerated above may be used within event
listeners attached to button
elements
placed inside the body of construct repeat
.
In combination with the facilities provided by
element group
and CSS layout, this allows
document authors to customize the positioning of
controls for standard actions such as insert or
delete.
Element repeat
represents a repeating homogenous
collection, in other words, a collection consisting
entirely of like form controls.
<repeat ref="bindingExpr" startIndex="si" number="n"> <caption>Shopping Cart</caption> <!-- XForms UI for one element of the collection --> <!-- controls for adding, deleting and navigating entries --> </repeat> |
Notice that the underlying schema for the
collection being populated would typically have defined
attributes minOccurs
and
maxOccurs
; these values will in
turn determine if the user agent displays
appropriate UI controls for the user to add or
delete entries in the collection. Event listeners
within element repeat
control UI
aspects such as scrolling and insertion. This
specification will not specify normative means for
displaying such add and delete controls; as with the
rest of the XForms User Interface design, we leave
these to be flexible while showing a default
presentation.
repeat
>
<repeat (common attributes) startIndex = xsd:positiveInteger : 1 number = xsd:nonNegativeInteger > <!-- caption, help?, hint?, onevent?, ( any form control )* --> </repeat> |
common attributes defined in 7.13.1 Common Attributes
startIndex = xsd:positiveInteger : 1 - 1-based hint to the XForms Processor as to which starting element from the collection to display.
number = xsd:nonNegativeInteger - hint to the XForms Processor as to how many elements from the collection to display.
any form control - any form control defined in 7 Form Controls
This subsection enumerates the design consequences and is for members of the Working Group to evaluate the above design.
Binding expression is placed on element
repeat
and should refer to the
collection being populated, not to an
individual item of the collection. Thus, it
would be items/item
in a
purchase order, where element items
contains one or more item
children.
The form controls appearing inside
element repeat
needs to be suitable for
populating individual items of the collection.
Thus, to continue the purchase order example,
the contained XForms form controls
would need to be suitable for populating a data
instance conforming to item
.
A simple but powerful consequence of the above
is that if the XForms Model specifies nested
collections, then we can create a corresponding
user interface by nesting
repeat
elements. As an example,
consider the XForms Model for a hypothetical
purchase order that contains element
items
for holding collection of
item
elements. Further, assume that
element item
comprises of two atomic
fields catalogNumber
,
partNumber
and a collection
colors
which in turn holds one or more
color
elements. The user interface for
populating this data instance would use nested
repeat
elements.
Notice that the
contained XForms form controls inside
element repeat
do not explicitly
specify the index of the collection entry being
populated. This is intentional; it keeps both
authoring as well as the processing model
simple. But as a consequence, the user
interface cannot bind to an element from the
underlying collection out of
sequence. Notice that this is not a
serious drawback because the use interface layer
can always populate a specific member of a
collection without using element
repeat
.
User Interface templates allow the creation of reusable user interface components. Just as we can define data types and structures that can be reused within the XForms Model, reusable user interface components allow us to design complex user interfaces using the basic building blocks described in the previous section, and then reuse these components in multiple situations. As with any component framework, this has two basic requirements:
Components need to declare what aspects of the component are parameterizable by the caller.
The caller needs to be able to override the default values of the parameters declared in the component.
Here, we describe such a component framework along with sample markup. For
this example, assume that USShippingAddress
is a reusable data
type that is used in multiple places in the XForms Model, e.g. the user will
be asked for a billingAddress
and shippingAddress
--both
of type USShippingAddress
.
First, we show a simple example that is designed to bind an XForms form
control to a model item of
type address
with no attention to making the component
reusable.
<group> <textbox ref="address/street"> <caption>Please enter your street address</caption> </textbox> <textbox ref="address/zip"> <caption>Zip Code</caption> </textbox> </group> |
Next, we prepare the above fragment to become a reusable component that could be used for obtaining both the shipping and billing address. To do this, we need to parameterize those portions of the component that the caller will wish to modify.
<uiTemplate id="AddressWidget"> <param name="streetPrompt"/> <param name="zipPrompt"/> <param name="border" value="line"/> <group border="$border"> <textbox ref="address/street"> <caption><value-of name="streetPrompt"/></caption> </textbox> <textbox ref="address/zip"> <caption><value-of name="zipPrompt"/></caption> </textbox> </group> </uiTemplate> |
Note that the markup shown above does not create a
user interface; user interface is created by explicitly
instantiating the component via element
useUITemplate
described next.
Next, we use this component to instantiate the user interface for obtaining the shipping and billing address.
<useUITemplate ref="myAddress" component="AddressWidget"> <withParam name="streetPrompt">Shipping Street Address</withParam> <withParam name="zipPrompt">Zip Code for shipping state</withParam> <withParam name="border">dotted</withParam> </useUITemplate> |
The reusable component is instantiated by element useUITemplate
;
parameter values are specified by the contained
withParam
elements.
Attribute xform
sets the binding context relative to which binding expressions within the instantiated template get evaluated.
TODO: convert to 'XML Representation' consistent with rest of spec.
<!-- param element for use in uiTemplate --> <!ELEMENT param EMPTY> <!-- name Name of parameter being declared --> <!ATTLIST param name CDATA #REQUIRED> <!-- Defines a reusable user interface template --> <!ELEMENT uiTemplate (param*, %FormControls;+)> <!-- id Unique ID for use when instantiating this template --> <!ATTLIST uiTemplate id ID #REQUIRED> <!-- Used to pass parameter values when instantiating uiTemplate --> <!ELEMENT withParam #MIXED> <!-- name Name of parameter whose value is being specified --> <!ATTLIST withParam name CDATA #REQUIRED> |
The group
element is used as a container
for defining a hierarchy of form controls. Groups lay
out their children using a constraint-based system
that supports both relative flexible sizing and
intrinsic sizing. Groups can be nested to create
complex hierarchies. Using CSS, an inline box can be
specified using the display
property with
a value of inline
. A block-level group can
be specified with a value of block
, which
is the default.
group
>
<group> <!-- all form controls & mixed content --> </group> |
All form
controls defined so far are treated as
inline text for purposes of XHTML processing.
XForms visual clients are expected to use a a box layout model as defined by CSS for
determining the overall layout of the XForms visual
interface. Grouping of form controls using
element group
also provides semantics about the relationship amongst user
interface controls; such knowledge can be useful in
delivering a coherent UI to small devices--e.g.,
if the user interface needs to be split up amongst several
screens, controls appearing inside the
same
group would typically be rendered on the same screen.
Finally, the hierarchy defined by nested group elements is used to determine the
traversal order specified by attribute navindex
on form controls.
Setting the input focus on a group results in the focus being set to the
lowest form control in the tabbing order within that
group.
t is an open issue whether the binding attribute xform
is allowed on element group
.
It might make authoring easier but makes
implementations significantly harder.
Note that this note is here because at one point in our
design we said that controls inside a
group
could use relative XPath expressions with the context being
set by the containing group.
Containers typically have an orientation and a direction.
The box-orient
CSS property specifies
the orientation of the group. It has values of
horizontal
, vertical
, or
inherit
. A horizontal group lays out its
children in a horizontal line, and a vertical group
stacks its children vertically.
The box-direction
CSS property specifies the direction of the group. It has values of
normal
, reverse
, and inherit
.
A normal horizontal group lays out its children from left to right, and a normal
vertical group lays out its children from top to bottom.
Direction within nested groups is inherited by default. If direction is omitted on the outermost group, it is assumed to have a horizontal orientation and normal direction.
<group> <textbox ref="/person/name"> <caption>Please enter your name</caption> </textbox> <textbox ref="/person/ssid"> <caption>Enter your SSID</caption> </textbox> </group> |
When items are placed in a group without specifying any additional information about their size, then the sizes the children intrinsically. In other words, the group makes each child only as big as it needs to be. Notice that in the above example, the two form controls are only as big as they need to be, and that this in turn determines the size of the group (since we assume for simplicity that this group is not nested).
Widths can be specified for items inside a horizontal group. When an object specifies its width in CSS, it is telling the group that it would like to be that width. Similarly, heights can be specified in CSS for items in a vertical group. A non-nested group placed inside an enclosing CSS block will obey all the usual sizing rules of the block. For example, setting the width of a non-nested group to 100% ensures that the group is the maximum width permitted by the enclosing CSS block.
The box-align
property specifies how controls are aligned along the orientation
of the group. Its possible values are left
, center
, right
,
top
, bottom
, baseline
, stretch
and inherit
.
The default value is stretch
.
By default a horizontal group ensures that all children are the same height. Once a height is computed for a horizontal group, all of the children are stretched vertically to the height of the group (minus the CSS border and padding on the group). Similarly, a vertical group ensures that all its children are the same width. The stretch policy overrides any specified width or height values.
<group style="box-orient: vertical"> <output ref="/person/name"/> <output ref="/person/age"/> <output ref="/person/country"/> </group> |
In addition to stretch
, a horizontal group can also align its children using the
values top
, center
, baseline
and bottom
. A vertical
group can align its children using the values left
, center
, and right
.
When these values are used, the items are no longer stretched. They are sized intrinsically
and then aligned on the group axis according to the specified property value on the containing
group.
The layout algorithm can be controlled by specifying the
degree to which items may flex i.e.,
the degree to which an item allows itself to be
auto-sized.
Items in groupes fall into two categories: flexible
and
inflexible
. Inflexible objects will not grow, even when there is
extra space left over in the group.
When several objects in a group are flexible, the extra space is divided
among the objects based on how flexible they are. The group determines how
much space to give an object by adding up the flex values on all of its
children. An object gets an amount of extra space equal to the percentage
of flex that it is responsible for.
For example, if two objects have a flex of 1, then after both objects are given their preferred sizes, the first object gets 1/(1+1) = 1/2 of the extra space, and the second object also gets 1/2 of the extra space.
<group style="box-orient: horizontal; width: 200px"> <textbox style="box-flex: 1" ref="/person/name> <caption>Please enter your full name: </caption> </textbox> <textbox style="box-flex: 1.5" ref="/person/age> <caption>How young?</caption> </textbox> </group> |
For inflexible objects, the specification of the width
and height
CSS properties can be used to
specify a preferred size. If these properties are omitted,
an inflexible object will be sized intrinsically, i.e., it will be given
the minimum amount of space required to lay out the item.
With flexible objects, there are more options. Just as with inflexible
objects, the width
and height
properties can be used to specify a preferred
size. Unlike inflexible objects, however, this size is only a guideline.
A flexible object will stretch as necessary. It will also
shrink if required until it can shrink no more (e.g.,
when the object hits its minimum required intrinsic size).
<group style="box-orient: vertical"> <textbox style="box-flex: 1; height:1000px" ref="/person/name"> <caption>Please enter your name:</caption> </textbox> </group> |
In the above example if the group were to shrink, the
textbox being flexible would shrink--despite its
preferred height of 1000px
. The group
continues to shrink minimum required height for the
textbox is reached. After that, the textbox can
shrink no further. If the group were to continue to
shrink, the form control's contents would be
clipped, and a portion of the control would no
longer be visible.
For a more fine-grained control of
minimum and maximum sizes, the
min-width
, min-height
,
max-width
, and max-height
CSS properties can be used. When specified, these
properties provide extra information to the group as
it shrinks and grows the object in question.
In a horizontal group, for example, if a minimum width is specified, then the flexible object will not be allowed to shrink below that width. If a maximum width is specified, then the flexible object will not be allowed to grow beyond that width.
The above example demonstrates the use of min-height
and max-height
within a vertical group. In the first
image the group has been shrunk until it is smaller than 100 pixels in
height. Because the iframe
has a specified minimum height of 100 pixels,
it is not allowed to shrink any further, and so as the group falls below 100
pixels, the iframe
gets clipped, and portions of it become invisible.
In the second image, the group has been expanded past 300 pixels in
height. Even though the group is getting bigger, the extra space is not
being consumed by the iframe
, because its maximum height of 300 pixels has
been reached. It will grow no further.
Below is another example illustrating min and max width.
Example unavailable at publication time |
In the above example, the group has been stretched so that it is very wide. The first child has a maximum width of 50 pixels, and it divides the excess space equally with the second child until its maximum width has been reached. After that, since it is not allowed to grow any further, the remaining space all goes to the second child.
When all of the items within a group
element are inflexible or when all objects have
grown to their maximum sizes and can stretch no
further, extra space may be left over in the group.
An additional property can be used to dictate how
any additional space should be distributed between
objects. The CSS property box-pack
has
the possible values of left
,
right
, top
,
bottom
, center
,
justify
and inherit
. The
default is justify
.
In the above example, the button is centered within the group using the box-align
and box-pack
properties together. The former centers the button vertically, and
the latter centers the button horizontally.
Items within a group may use the CSS overflow
property to obtain horizontal and
vertical scrollbars as needed. Flexible objects that shrink below their minimum intrinsic
size (but that still have a size greater than a specified CSS minimum) can display
scrollbars using the overflow
property. If overflow is not specified,
the object will be clipped instead.
Whether an element is inline or block when placed directly inside a group is irrelevant. Objects
will be flowed horizontally or vertically based off the
box-orient
property.
When any raw text nodes are encountered directly inside a group, an anonymous block is constructed to wrap the text. This anonymous block then participates in the layout as a single item.
Editorial note: Raman | March 12, 2001 |
Notice that we originally started by creating
an equivalent of fieldset --but given
the present design of the XForms UI layer, and given
that conditional construct case can take
either group or html:div elements,
there is little left in this construct that is
additional to what is in XHTML html:div . I
therefore suggest simply reusing html:div --perhaps
bind XForms specific behaviors through CSS
e.g., a stack of cards for example? The way I am
thinking of this is that whether it is a stack of
cards shown one at a time, or a sequence of tab
dialogs is a presentation issue and might therefore be
best left to CSS as we have done with the rest of the
presentational issues in XForms.
|
Subpages provide a means to present XForms one bit at a time, breaking a complex
task into smaller, simpler parts. Presentation of a subpage can occupy the entire
"page" or just part of a page. Different presentations are possible, e.g. a
stack of pages with visible name tags, or as a set of buttons for flipping
through the stack or navigating directly to a particular subpage. One possible
representation is a formset
element enclosing one or more subpage
elements, each of which starts with a
caption
element.
As the name implies subpage
is not specific to XForms--our intent
is to design subpage
so that it can be used within XForms--and
more generally within XHTML to create presentations where document views are
presented to progressively reveal the document
structure and content.
Table of Contents | Top |