- From: John Boyer <boyerj@ca.ibm.com>
- Date: Tue, 4 Mar 2008 22:03:48 -0800
- To: Forms WG (new) <public-forms@w3.org>
- Message-ID: <OFE62A4FF6.2E9F4814-ON88257403.00200A23-88257403.00214F79@ca.ibm.com>
In order to fuel the discussion of the simplified, on-the-glass syntax,
here is the "canonical" version of a purchase order form that we would
like to express with the simplified syntax.
It is a 1.0 form, so it still uses a methodology for insert that was
needed prior to having the origin attribute.
Mark, this is the form that needs to be able to use bind sites and $ XPath
variables. Will you be able to whip up a translation before the call?
<?xml version="1.0" encoding="UTF-8"?>
<!-- The purpose of this form is to demonstrate the XForms 1.0 methods
that are likely
to come into play when handling a simple repeat table, such as in
a purchase order.
Here are the important aspects of how row insertion and deletion
are done:
1) The last row of the data is regarded as containing
'prototypical'
data for use in row insertion.
2) The last row containing the prototypical data is made
non-relevant.
3) The last row is excluded from the repeat nodeset. Although
repeats
don't show non-relevant rows, the repeat index can become
equal
to the position of a non-relevant row, so it is easier to
manage
the repeat by excluding the non-relevant node from the
nodeset.
4) A new first row of data is generated on startup (if only one
row exists)
so that the user will have an initial table row with which
to interact.
5) The delete trigger uses a conditional insert to make sure that
the
repeat is never empty of relevant nodes.
6) The insert and delete triggers use a setfocus action because
the user
activation of a trigger transfers focus to that trigger,
so we want
the focus to go back to the repeat table when the
operations over the
repeat nodeset are completed.
-->
<html xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<head>
<xforms:model>
<xforms:instance id="po" xmlns="">
<po>
<order>
<row>
<product/>
<unitCost>0</unitCost>
<qty>0</qty>
<lineTotal>0</lineTotal>
</row>
</order>
<subtotal>0</subtotal>
<tax>0</tax>
<total>0</total>
</po>
</xforms:instance>
<!-- Make the last row of the table non-relevant so it can be
used as prototypical data for insertion -->
<xforms:bind nodeset="order/row[last()]" relevant="false()"/>
<!-- If there is only one row, it is non-relevant so add another
row -->
<xforms:insert ev:event="xforms-model-construct-done"
nodeset="order/row[last()=1]" at="1"
position="before"/>
<!-- This instance contains a temporary variable that allows the
form
author to configure what the sales tax rate is. This
could be
obtained from external data instead using the src
attribute. -->
<xforms:instance id='taxrate' xmlns="">
<rate>0.07</rate>
</xforms:instance>
<!-- This instance contains the product list, which also could be
obtained externally using src. -->
<xforms:instance id='products' xmlns="">
<products>
<product name="Widget" code="W1"/>
<product name="Gadget" code="G1"/>
<product name="Trinket" code="T1"/>
<product name="Gromet" code="G2"/>
</products>
</xforms:instance>
<!-- The total is just the sum of the subtotal and the tax; any
time
those change, the total is automatically updated -->
<xforms:bind nodeset="total" calculate="../subtotal + ../tax"/>
<!-- The tax is just the subtotal times the tax rate -->
<xforms:bind nodeset="tax" calculate="../subtotal *
instance('taxrate')"/>
<!-- The subtotal is the sum of all the line totals. Any time a
row is
inserted, deleted or changed, the subtotal is
automatically updated.
The calculate uses the 'node set' feature of XPath to get
however
many line total elements exist for the summation. -->
<xforms:bind nodeset="subtotal"
calculate="sum(../order/row/lineTotal)"/>
<!-- The node set feature of XPath is used to get all the line
total
elements and set a calculation for each one. A line total
is
just the unit cost times the quantity. Any time a new row
is
inserted, this declaration automatically creates a new
line total
calculation for it. An update of unit cost or quantity on
any row
automatically updates the line total of that row, which
then causes
the subtotal, tax and total to be updated automatically.
Even though
those calculations are declared before this one, XForms
reorders the
calculations so that they run in the order that makes
sense. -->
<xforms:bind nodeset="order/row/lineTotal" calculate="../unitCost
* ../qty"/>
<!-- This submission simulates a simple server module that
bounces submitted
data back to the client. It does so by doing put then get
on a file
(the location of which is based on retrieval domain of the
form) -->
<xforms:submission id="S" method="put"
includenamespaceprefixes=""
replace="none" action="file:poBounce.xml">
<xforms:send ev:event="xforms-submit-done" submission="T"/>
<xforms:message ev:event="xforms-submit-error"
level="modal">Could not upload file</xforms:message>
</xforms:submission>
<xforms:submission id="T" method="get" action="file:poBounce.xml"
replace="all"/>
</xforms:model>
</head>
<body>
<xforms:trigger>
<xforms:label>Add to Order</xforms:label>
<xforms:action ev:event="DOMActivate">
<!-- Insert a new row after the one that had the focus
before this trigger
was activated, then set the focus from this
trigger back to the repeat -->
<xforms:insert nodeset="order/row" at="index('orderTable')"
position="after"/>
<xforms:setfocus control="orderTable"/>
</xforms:action>
</xforms:trigger>
<xforms:trigger>
<xforms:label>Delete Row</xforms:label>
<xforms:action ev:event="DOMActivate">
<!-- Delete the row that had the focus before this trigger
was activated.
Then, if only the prototypical row remains, then
insert a new row for
the user. Otherwise, if the last row was deleted,
then set the table
index now points at the non-relevant row containing
the prototypical
data, so we bump it up one to point to the last
relevant row. Finally,
we set the focus from the delete trigger back to the
repeat. -->
<xforms:delete nodeset="order/row[last()>1]"
at="index('orderTable')"/>
<xforms:insert nodeset="order/row[last()=1]" at="1"
position="before"/>
<xforms:setfocus control="orderTable"/>
</xforms:action>
</xforms:trigger>
<xforms:submit submission="S">
<xforms:label>Submit Order</xforms:label>
</xforms:submit>
<xforms:repeat nodeset="order/row[position()!=last()]"
id="orderTable" startindex="1">
<xforms:select1 ref="product" appearance="minimal">
<xforms:label>Product Name</xforms:label>
<xforms:itemset nodeset="instance('products')/product">
<xforms:label ref="@name"/>
<xforms:value ref="@code"/>
</xforms:itemset>
</xforms:select1>
<xforms:input ref="unitCost">
<xforms:label>Unit Cost</xforms:label>
</xforms:input>
<xforms:input ref="qty">
<xforms:label>Quantity</xforms:label>
</xforms:input>
<xforms:output ref="lineTotal">
<xforms:label>Line Total</xforms:label>
</xforms:output>
</xforms:repeat>
<xforms:output ref="subtotal">
<xforms:label>Subtotal: </xforms:label>
</xforms:output>
<xforms:output ref="tax">
<xforms:label>Tax: </xforms:label>
</xforms:output>
<xforms:output ref="total">
<xforms:label>Total: </xforms:label>
</xforms:output>
</body>
</html>
Received on Wednesday, 5 March 2008 06:04:09 UTC