4.4 Complete Example of an XForms User Interface


4.4 Complete Example of an XForms User Interface

We conclude this chapter with a complete XForms example that uses nested repeating structures to create a dynamic task list. The resulting visual interface is shown in Figure 4.18.

Figure 4.18. Task list interface rendered by X-Smiles.

graphics/04fig18.gif

The task list tracks a set of open tasks. Tasks are organized into sections such as work or personal ; a user can add or remove sections as desired. A section consists of one or more tasks, and a task in turn holds information about a particular task, such as the date the task is due, a description of the task, and its current status. The task list interface we create allows the user to edit, maintain, and view the task list within a Web browser or other conforming XForms user agents .

In creating this example, we cover many of the concepts introduced so far in this book including:

  • Declaring the data model by defining the structure of the task list via an XML Schema: Section 4.4.1

  • Declaring the initial instance: Section 4.4.2

  • Combining the schema and instance declarations into the XForms model and including this data model within an element head in an XHTML page: Section 4.4.3

  • Creating the user interface via repeat and embedding the repeating structure within an XHTML table: Section 4.4.4

  • Binding XForms user interface controls to the underlying data model: Section 4.4.5

  • Creating the needed navigation controls: Section 4.4.6

  • Encapsulating these into an XHTML document: Section 4.4.7

The example will be introduced in stages to cover each of these items.

4.4.1 Defining the Structure of the Task List

The structure of the task list is defined by an XML Schema as shown in Figure 4.19. A task list has element todo as its root element which consists of one or more section elements. The schema declares that element todo must have at least one section child by specifying a value of 1 for facet minOccurs .

Figure 4.19 XML Schema that defines the data model for the task list.
 <  x:schema   targetNamespace  ="http://example.com/todo"  xmlns:t  ="http://example.com/todo"  xmlns:x  ="http://www.w3.org/2001/XMLSchema"  elementFormDefault  ="qualified"  id  ="todo-schema"> <  x:element   name  ="task"> <  x:complexType  > <  x:sequence  > <  x:element   name  ="date"  type  ="x:date"/> <  x:element   name  ="description"  type  ="x:string"/> <  x:element   name  ="status"  type  ="x:string"/> <  x:element   name  ="done"  type  ="x:boolean"/> </  x:sequence  > </  x:complexType  > </  x:element  > <  x:element   name  ="section"> <  x:complexType  > <  x:sequence   maxOccurs  ="unbounded"> <  x:element   ref  ="t:task"/> </  x:sequence  > <  x:attribute   name  ="name"  type  ="x:string"/> </  x:complexType  > </  x:element  > <  x:element   name  ="todo"> <  x:complexType  > <  x:sequence   maxOccurs  ="unbounded"> <  x:element   ref  ="t:section"/> </  x:sequence  > </  x:complexType  > </  x:element  > </  x:schema  > 

Element section holds the name of the section in attribute name . A section can hold one or more task elements. A task element consists of four required child elements as follow:

date

Holds the due date for this task. The value is of type xsd:date .

description

Holds a human-readable description of the task. The value is of type xsd:string .

status

Holds a human-readable status of the task. The value is of type xsd:string .

done

An xsd:boolean that holds a true or false value indicating if the task has been completed. The schema declares a default value of false for this field.

We declare attribute id with value todo-schema for the schema definition, and this identifier will be used when connecting the instance declaration with the schema definition in the XForms model. The schema for the task list declares the target namespace for this schema in the statement

 
 targetNamespace="http://example.com/todo" 

to specify that elements defined by this schema are in the namespace identified by http://example.com/todo .

The local namespace prefix t is used within the schema in referring to types defined in this schema, for example, t:task .

Note that defining the instance data in an application-specific namespace is a powerful but fairly advanced feature. For the various elements being defined by this schema to be placed in the application-specific namespace, we add the attribute declaration

 
  elementFormDefault  ="qualified" 

to the root of the schema element. Because of the way XML namespaces interact with XPath, XForms binding expressions need to namespace qualify individual components of the XPath locator.

As an example, note the namespace prefix t: in each step of the XPath locators used when binding user interface controls. If we omitted the namespace prefix in this case, the binding expression would fail. Writing

 
 /todo/section/task 

would use the default namespace when looking for these nodes; as a consequence, todo would use the default namespace, which in the case of the user interface markup is different from the namespace that contains the task list.

4.4.2 Declaring the Task List Instance

Next , we create a skeleton XML instance for holding the task list. This skeleton serves as the initial data for the task list; it also serves as a declaration that is used when creating new sections and tasks in the task list. The instance declaration is shown in Figure 4.20.

Figure 4.20 Instance declaration for the task list.
 <  todo   xmlns  ="http://example.com/todo"> <  section   name  ="business"> <  task  > <  date  >2003-01-07</  date  > <  description  >XForms Call</  description  > <  status  /><  done  /> </  task  ></  section  > <  section   name  ="personal"> <  task  > <  date  >2003-04-15</  date  > <  description  >Tax Deadline</  description  > <  status  /><  done  /> </  task  ></  section  > <  section   name  ="writing"> <  task  > <  date  >2003-04-01</  date  > <  description  >Complete book</  description  > <  status  /><  done  /> </  task  ></  section  > </  todo  > 

The namespace for the task list is declared as the default namespace using the statement

 
 xmlns="http://example.com/todo" 

to avoid having to namespace qualify the various elements in the task list. The task list starts with three sections named work , personal , and writing . Each section contains one partially filled-in task element.

4.4.3 Declaring the Data Model within XHTML head

Next, we create the XForms data model within element head of an XHTML document in Figure 4.21. We assume that the XHTML namespace has been declared as the default namespace. Element model contains the XForms model, and we temporarily make the XForms namespace the default namespace with an appropriate xmlns attribute. Element model carries two attributes in this example:

Figure 4.21 XHTML head for the task list.
 <  head  ><  title  >Editing Task List</  title  > <  model   xmlns  ="http://www.w3.org/2002/xforms"  id  ="todo"  schema  ="todo-schema.xsd">  <!-- instance declared by reference-->  <  instance   src  ="todo-instance.xml"/> <  submission   id  ="s01"  method  ="post"  action  ="http://examples.com/"/> </  model  > <  style   type  ="text/css"> @namespace xf url(http://www.w3.org/2002/xforms); xfinput.edit {font-weight:bold; ...} xflabel.sectionLabel {font-weight:bold; ...} xfsubmit {font-family: Arial;...} </  style  > </  head  > 

schema

Identifies the schema that defines the type and structure of instance data to be used in this model. Here, we use #todo-schema to identify the schema for the task list via its unique identifier shown in Figure 4.19.

The instance data is specified by reference in the line

 
 <  xf:instance  src="todo-instance.xml"/> 

where the location todo-instance.xml contains the skeleton instance shown in Figure 4.20. For brevity, we have replaced the schema definition for the task list shown in Figure 4.19 with a one-line comment.

In addition to the schema and instance declarations, the XForms model also declares a submission element that specifies the what , where , and how of submit processing. The result of submitting will be to update the user's saved task list.

Finally, element head contains a CSS style section in element style that contains CSS style rules for rendering specific aspects of the user interface. The CSS rules declared here will be used in Section 4.4.4 to style the various user interface controls.

4.4.4 Creating the User Interface Via Nested Repeats

The XForms user interface for editing and viewing the task list within an XHTML page can be thought of as a Web browser window onto the XML document shown in Figure 4.20. Thus, the actual document that the user is viewing and editing is the XML task list; the XForms user interface hosted in an XHTML page enables the user to maintain the task list without having to edit the raw XML source. In this section, we enable such browser-based editing by binding a user interface consisting of XForms constructs and controls to the task list data model; see Figure 4.22.

Figure 4.22 User interface for editing a hierarchical task list.
 <  xf:repeat   xmlns  ="http://www.w3.org/1999/xhtml"  xmlns:t  ="http://example.com/todo"  xmlns:ev  ="http://www.w3.org/2001/xml-events"  xmlns:xf  ="http://www.w3.org/2002/xforms"  id  ="rs"  nodeset  ="/t:todo/t:section"> <  h2  ><  xf:input   ref  ="@name">...</  xf:input  ></  h2  > <  table  > <  tr   xf:repeat-nodeset  ="t:task"  xf:repeat-id  ="rt"> <  td  ><  xf:input   ref  ="t:date"> <  xf:label  >Date</  xf:label  ></  xf:input  ></  td  > <  td  ><  xf:input   ref  ="t:description"> <  xf:label  >Task</  xf:label  ></  xf:input  ></  td  > <  td  ><  xf:input   ref  ="t:status"> <  xf:label  >...</  xf:label  ></  xf:input  ></  td  > <  td  ><  xf:input   ref  ="t:done"> <  xf:label  >Done</  xf:label  ></  xf:input  ></  td  ></  tr  > <  tr  ><  td  ><  xf:trigger   ev:event  ="DOMActivate"> <  xf:label  >New Task</  xf:label  > <  xf:insert   at  ="index('rt')"  position  ="after"  nodeset  ="/t:section[index('rs')]/t:task"/> </  xf:trigger  ></  td  > <  td  ><  xf:trigger   ev:event  ="DOMActivate"> <  xf:label  >Delete Task</  xf:label  > <  xf:delete   at  ="index('rt')"  nodeset  ="/t:section[index('rs')]/t:task"/> </  xf:trigger  ></  td  > <  td  ><  xf:trigger   ev:event  ="DOMActivate"> <  xf:label  >Scroll Forward</  xf:label  > <  xf:setindex   repeat  ="rt"  index  ="index('rt')+1"/></  xf:trigger  ></  td  > <  td  ><  xf:trigger   ev:event  ="DOMActivate"> <  xf:label  >Scroll Back</  xf:label  > <  xf:setindex   repeat  ="rt"  index  ="index('rt')-1"/> </  xf:trigger  ></  td  ></  tr  ></  table  ></  xf:repeat  > 

A key feature of the task list is its hierarchical nature and the ability to grow and shrink dynamically. The task list has been organized into a set of logical sections comprising the various tasks. On the user interface side, we mirror this structure by creating XHTML sections that correspond to the sections in the task list. In doing so, we can use the section name as encapsulated by attribute name of element section in constructing the section title that is displayed to the user. Since the number of sections can grow or shrink at run-time, XForms aggregation construct repeat is a natural choice for creating a scrolling view-port that allows the user to view a portion of the task list. We will create the necessary controls for adding, removing, and scrolling these sections and aggregate these controls to create navigation toolbars .

The tasks appearing in each section have additional substructure , and aligning the fields making up each task is an appropriate visual representation. We use XHTML tables to achieve this visual display. The user can add, remove, and scroll tasks appearing in a given section, and we use a repeating construct to achieve this end result. However, since we are using XHTML tables to render the list of tasks in a given section, we use repeat attributes rather than element repeat to create XHTML tables that grow or shrink dynamically during user interaction.

The consequence of this design is that we create nested repeat structures, with the outer repeat iterating the sections appearing in the task list and the inner repeat iterating tasks in a given section. Finally, notice that this form of nesting requires no special attention on the author's part; the design of the XForms repeat construct ensures that nested repeats work as the author would expect.

Note that for this example, we assume the XHTML namespace as the default; see relevant declaration in Figure 4.25. Hence, we prefix all elements from the XForms namespace via the local namespace prefix xf .

Outer repeat . The outer repeat iterates over the section children of the task list and is identified by setting attribute id to rs . This unique identifier will be used when manipulating the state of this repeating structure via XForms actions insert , delete , and setindex .

We identify the node-set to iterate via the binding expression

 
 nodeset="/todo/section" 

which selects all section children of element todo . Given the instance declared in Figure 4.20, this would select a set consisting of 3 section nodes. Notice that since there is only one model in this complete example, we do not need to specify attribute model in the binding expression; by default XForms uses the first model in the document. The binding expression appearing on element repeat also establishes the XPath evaluation context when evaluating relative XPath locators within the body of element repeat .

For brevity, we have not set optional attributes of element repeat such as startindex . In this case, the browser can display as many sections as appropriate for the connecting device.

The markup appearing within element repeat declares the template user interface to be applied to each member of the node-set being iterated. We first create a section header via XHTML element h2 that displays an editable field bound to attribute name of element section . Notice that XForms user interface control input is used as the contents of the XHTML section header created by element h2 . The result is to create a Web page where the section headings are editable by the user. Within this input control, we use a relative XPath locator @name to address attribute name of the current section . In the current example, the instance shown in Figure 4.20 results in the creation of 3 XHTML h2 elements, with each displaying attribute name from the corresponding section element. Editing the displayed value results in the underlying XML instance being updated, and the display is refreshed to show the new value.

The key thing to notice is that relative XPath locators appearing within the body of element repeat are evaluated in the evaluation context established by the binding expression on the containing repeat and with the current member of the node-set being iterated as the context node. Thus, the binding expression on control input

 
 ref="@name" 

is interpreted as ./@name , where . refers to the current node, that is, the current section . This is key to understanding the functioning of nested repeat structures as we will see when we examine the inner repeat next.

Inner repeat. The outer repeat creates an XHTML table for displaying the tasks in a given section. The context node for the outer repeat , that is, . refers to the current section from the task list, and this current section sets up the evaluation context as explained earlier. We want the XHTML table that displays the individual tasks to grow or shrink with the tasks in a section. We achieve this by turning XHTML element tr into a repeating structure via repeat attributes described in Section 4.3.6. In this case, the template user interface for this repeating construct is an XHTML table row that displays the fields making up an individual task.

The inner repeat is created via repeat attributes on XHTML element tr with the line

 
 <tr repeat-nodeset="task" repeat-id="rt"> 

which declares that the repeating structure being created will be identified via the unique identifier rt . The binding expression that locates the set of nodes to iterate uses the current evaluation context as set up by the outer repeat . Thus, the XPath locator in the statement

 
 repeat-nodeset="task" 

is interpreted as ./task and selects all task children of the current section . Thus, the outer repeat determines the specific section to operate on; the inner repeat structure selects the task of a specific section . The result is that, as the user changes the section that is current via add, delete, or scroll operations, the inner repeat structure is correctly updated to display the tasks from the right section .

The contents of the table row as given by the children of element tr declare the template user interface that is applied to each task appearing in the collection being iterated. We have created individual table cells via XHTML element td for each of these fields. Each table cell contains an XForms user interface control that binds to the corresponding field in element task .

Adding, removing, and scrolling tasks Before closing off element table created by the outer repeat , we create a table row that holds user interface controls for adding, removing, and scrolling tasks in the current section. These controls use XForms action handlers insert , delete , and setindex in a manner similar to that explained in Figure 4.13. Within these controls, we address the inner repeat via its unique identifier rt and the outer repeat via its unique identifier rs . Since the section on which the inner repeat operates is completely determined by the state of the outer repeat , the add, delete, and scroll controls in this example are identical in operation to what we saw when creating the shopping cart in Section 4.3.4.

Following, we examine one of these controls in detail to explain the functioning of the nested repeats. Consider the control that adds a new task. The new task is added by invoking XForms handler insert . This invocation needs to specify the node-set to which the new task node should be added and the position at which it should be inserted. The node-set in question is the set of all task children of the current section .

The position of the current section within the node-set of all section children of the task list can be accessed by invoking XPath extension function index , as in

 
 index(rs) 

which returns the value of the repeat index for the outer repeat . This expression can in turn be used to locate the desired set of task children of the current section as in

 
 nodeset="section[index('rs')]/task" 

which selects the set of all section nodes, filters it by the predicate index(rs) , and finally selects all task children of the result. Next, we specify where in this set of task elements the insertion should happen. This is expressed via the following:

 
 xf:insert at="index('rt)" position="after" 

where XPath extension function index is used to access the current value of the repeat index for the inner repeat identified by rt .

Finally, notice that the add, delete, and scroll controls described earlier appear within the outer repeat . The effect is to create a toolbar consisting of these controls for each section of the task list.

4.4.5 Binding User Interface Controls to the Task List

Next, we examine the binding expressions used in the user interface controls in Figure 4.22. As before, the evaluation context and context node for evaluating these XPath locators are determined by the containing repeat . The user interface in Figure 4.22 creates four input controls that each binds to one of the four child elements of task . The binding expressions in each of these controls are relative XPath expressions that are all evaluated with the current task as the context node. Thus, the binding expression on the first input control

 
 <input ref="date">...</input> 

binds that input control to the date of the task node that is current , that is, the node at the position given by index('rt') .

Notice also that we have bound XForms control input to each of the four child elements of task . Recall from the schema shown in Figure 4.19 that the children of task are typed . This type information can be used to create user interface controls appropriate to a given interaction modality and device. Thus, the input control bound to field date of type xsd:date might be rendered as a date picker control on a given device. The date picker on a desktop client might take the form of a simple calendar widget; the date picker on a cell phone with a small display might be rendered as a text field with smart completion. Child element done is of type xsd:boolean ; this information can be used to render the associated input control as a checkbox where appropriate.

4.4.6 Adding a Toolbar for Navigation

Controls for adding, removing, and scrolling tasks are described in Section 4.4.4. The controls for adding, removing, and scrolling the sections in the task list are similar in structure and functionality. Placing these controls in element group as shown in Figure 4.23 turns these controls into a conceptual toolbar that can be placed at the appropriate point in the containing user interface.

Figure 4.23 Toolbar for manipulating sections in the task list.
 <  group   xmlns  ="http://www.w3.org/2002/xforms"  xmlns:ev  ="http://www.w3.org/2001/xml-events"  xmlns:t  ="http://example.com/todo"> <  trigger   ev:event  ="DOMActivate"> <  label  >New section</  label  > <  insert   nodeset  ="t:section"  at  ="index('rs')"  position  ="after"/></  trigger  > <  trigger   ev:event  ="DOMActivate"> <  label  >Delete section</  label  > <  delete   nodeset  ="t:section"  at  ="index('rs')"/> </  trigger  > <  trigger   ev:event  ="DOMActivate"> <  label  >Scroll Forward</  label  > <  setindex   repeat  ="rs"  index  ="index('rs')+1"/> </  trigger  > <  trigger   ev:event  ="DOMActivate"> <  label  >Scroll Back</  label  > <  setindex   repeat  ="rs"  index  ="index('rs')-1"/> </  trigger  > </  group  > 

Notice that creating a new section in the task list effectively clones the prototypical section element declared in Figure 4.20. Binding the user interface shown in Figure 4.22 to the new collection results in an additional section appearing in the user interface.

This newly created section has an empty task node, and this task node in turns gets bound by the inner repeat structure that is part of the newly created table row. Notice also that depending on the available display real estate, a fixed number of sections will be shown to the user at any given time. Since the toolbar consisting of the controls for operating on sections is placed outside the outer repeat structure, that toolbar will never scroll off the display while the user is working with the task list.

The end result is to divide the displayed page effectively into a fixed toolbar and a scrolling region that displays the sections of the task list. Each displayed section is in turn subdivided into a toolbar for manipulating the tasks in that section and a scrolling view-port that displays the tasks in that section. We show a conceptual overview of this visual display in Figure 4.24.

Figure 4.24. Visual display for the task list editor.

graphics/04fig24.gif

4.4.7 Putting It Together inside an XHTML Page

In Figure 4.25, we bring together the various pieces of the task list example in an XHTML page that creates the complete task list application. Element html is the root of this document, and it declares the XHTML namespace to be the default namespace. We declare local namespace prefixes for the various namespaces used by the task list application as follows :

Figure 4.25 Dynamic XHTML user interface for editing a hierarchical task list.
 <  html   xmlns  ="http://www.w3.org/1999/xhtml"  xmlns:xf  ="http://www.w3.org/2002/xforms"  xmlns:xsd  ="http://www.w3.org/2001/XMLSchema"  xmlns:todo  ="http://example.com/todo"  xmlns:ev  ="http://www.w3.org/2001/xml-events">  <!-- insert head element here -->  <  body  > <  h1  >Task List</  h1  >  <!-- insert section toolbar here. -->   <!-- insert nested repeating here-->   <!-- Insert task list summarizer here. -->   <!--Insert submit control here-->  </  body  ></  html  > 

xf

The XForms 1.0 namespace.

xsd

The XML Schema namespace corresponding to XML Schema 1.0. XML Schema became a W3C Recommendation in 2002.

ev

The XML Events namespace. XML Events is currently a W3C Candidate Recommendation, but the namespace URI is not expected to change when XML Events becomes a W3C Recommendation.

t

The namespace containing elements in the task list instance. This namespace is private to the task list application.

Next, we insert XHTML element head as shown in Figure 4.21. This contains the XForms model and the CSS style rules used to style various aspects of the presentation.

The user interface described in Section 4.4.4 and Section 4.4.6 appears within XHTML element body . Notice that in the resulting interface, the level one heading produced by XHTML element h1 is fixed with respect to the scrolling view-port created by the repeat structure that binds to the hierarchical task list.

We follow the repeat that holds the task list user interface with other XForms controls that display a summary of the task list; see Figure 4.26. Like the title produced via element h1 , this summary section is also fixed with respect to the scrolling task list.

Figure 4.26 Displaying a summary of the task list.
 <  group   xmlns  ="http://www.w3.org/2002/xforms"  xmlns:t  ="http://example.com/todo"> You have <  output   value  ="count(/t:todo/t:section)"/> sections in your task list with a total of <  output   value  = "count(//t:task[ not(boolean-from-string(t:done))])"/> unfinished tasks.</  group  > 

The summary section displays the number of sections in the task list and a count of the tasks that remain to be completed. Since this computed information is not stored in a specific node in the task list instance, we cannot use a binding expression in control output to look up this information. We therefore use attribute value [2] on control output to specify the expression to compute. This information is computed dynamically at run-time and updates as the user interacts with the task list.

[2] This was an oft- requested feature that was added following public feedback during the Last Call period.

We conclude the example by adding a submit control that enables the user to save the task list.

4.4.8 Submitting the Task List

We began this section by introducing the XML document that holds the task list in Figure 4.20. The primary purpose of the user interface we have created so far is to edit, maintain; and view this XML document within a standard browser interface without having to worry about the details of the XML markup. The interface we have created provides the user the necessary interface controls to view and manipulate the task list XML document. The key advantage with the interface we have created is that the underlying task list remains valid XML at all times. We can complete the circle by submitting the task list in order to save the current state.

Creating such save task list functionality requires the addition of a submit control (see Figure 4.27) that binds to the submission element we created in the XForms model in Figure 4.21. Activating control submit results in the current state of the task list being serialized as an XML document and the result of this serialization being transmitted to the URI specified in the submission element.

Figure 4.27 Submitting the task list saves the current state.
 <  submit   xmlns  ="http://www.w3.org/2002/xforms"  submission  ="s01"> <  label  >Save Task List</  label  ><  help  >...</  help  > </  submit  > 


XForms. XML Powered Web Forms with CD
XForms. XML Powered Web Forms with CD
ISBN: N/A
EAN: N/A
Year: 2003
Pages: 94

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net