- From: John Boyer <boyerj@ca.ibm.com>
- Date: Thu, 12 Apr 2007 15:05:54 -0700
- To: www-forms-editor@w3.org
- Cc: public-forms@w3.org
- Message-ID: <OF64304FB0.2BF3AB64-ON882572BB.00610C94-882572BB.007964FD@ca.ibm.com>
It needs to be specified what happens to XPath-based actions whose context
node has been deleted during execution of an action sequence.
1) A common use case would be a repeat construct in which the author is
attempting to enforce a one repeat item minimum (i.e. a one row table).
2) Frequently, form authors desire the ability to put the trigger that
deletes a repeat item within the repeat so that each repeat item receives
a trigger capable of deleting that repeat item.
In a repeat construct having both of the properties above, it is tempting
to write the trigger so that it first deletes the repeat item context node
then, if the set of nodes over which the repeat operates is empty, then
insert a new empty node. To the end user, it appears as if the one
remaining repeat item has been cleared rather than deleted.
While it is possible to achieve the effect just described by another
means, a further clarification of the XForms specification is needed to
indicate whether or not it can be done by the above means: delete followed
by insert if empty. The possible outcomes are
1) All further processing of an action sequence is terminated once the
context node is destroyed.
I point this out only as a possibility, but I do not think this is
desirable. It would mean that a context node deletion is essentially
illegal in XForms. For example, a delete may be followed by a setfocus.
Moreover, certainly the deferred update sequence must be executed after
the deletion.
2) Absence of a context node for XPath-based actions like insert results
in an xforms-binding-exception or a crash.
3) Absence of a context node for XPath-based actions like insert results
in a "no-operation", similar to getting an empty nodeset or a false result
on an 'if'.
This is what most implementers seem to be doing now.
4) The deletion of a context node removes it from the instance data, but
not from availability for evaluation until after the action sequence is
completed (immediately before deferred update behavior is executed).
This is the most desirable behavior. Note that in XForms 1.1, delete has
already been redefined so that the xforms-delete event has access to the
deleted node(s) in its event context after the node has been removed from
instance data. Moreover, it is possible to "parent up" from the deleted
node to its former parent.
As a result of these facts, the following markup should work:
<repeat nodeset="a/b/c" id="R">
...
<trigger>
<label>Delete</label>
<action ev:event="DOMActivate">
<delete nodeset="." at="1"/>
<insert if="count(../c)=0" context=".."
origin="instance('proto')/c"/>
<setfocus control="R"/>
</action>
</trigger>
</repeat>
The action sequence first deletes the repeat item containing the trigger
that is activated. Then, it attempts to use the context node to determine
whether the parent has any 'c' children remaining. If not, then the
parent of the deleted node receives a new empty prototypical 'c' node.
For the record, this alternate body of markup that should already work in
current implementations:
<repeat nodeset="a/b/c" id="R">
...
<trigger ref="..">
<label>Delete</label>
<action ev:event="DOMActivate">
<delete nodeset="c" at="index('R')"/>
<insert if="count(c)=0" context="."
origin="instance('proto')/c"/>
<setfocus control="R"/>
</action>
</trigger>
</repeat>
By "misusing" the trigger ref to go to the parent 'b' element, the delete
of a 'c' element does not delete the context node, so the subsequent
insert, appropriately tweaked for the change of context, should achieve
the desired effect.
The effect could also be achieved by first inserting a new prototypical
'c' node if there is only one left, then setting the repeat index back to
the one that should be deleted, then deleting afterward.
<repeat nodeset="a/b/c" id="R">
...
<trigger>
<label>Delete</label>
<action ev:event="DOMActivate">
<insert if="count(../c)=1" nodeset="../c" at="1"
origin="instance('proto')/c"/>
<setindex repeat="R" index="1"/>
<delete nodeset="." at="1"/>
<setfocus control="R"/>
</action>
</trigger>
</repeat>
Therefore, this isn't an issue of whether the desired user experience
effect can be achieved but rather whether a seemingly natural way of
expressing the solution should in fact work.
Best regards,
John M. Boyer, Ph.D.
STSM: Lotus Forms Architect and Researcher
Chair, W3C Forms Working Group
Workplace, Portal and Collaboration Software
IBM Victoria Software Lab
E-Mail: boyerj@ca.ibm.com
Blog: http://www.ibm.com/developerworks/blogs/page/JohnBoyer
Received on Thursday, 12 April 2007 22:06:08 UTC