Issue with using XML Events 2 with repeated content

We have had a lot of difficulty in XForms with using XML events due to 
repeated content .

We have the most problems at the join between the repeated content and the 
element doing the repeating.  A simple example should help:

...
  <icecream>
     <desired></desired>
     <flavor color="brown">chocolate</flavor>
     <flavor color="pink">strawberry</flavor>
     <flavor color="white">vanilla</flavor>
  </icecream>
...
<select1 ref="desired">
    <label>Pick one flavor:</label>
    <itemset nodeset="../flavor">
         <label ref="."/>
         <value ref="."/>
         <hint>The color will be <output ref="./@color"/></hint>
         <action ev:event="xforms-select">
           <!-- Do some stuff -->
         </action> 
    </itemset>
</select1>

Note that I could have written a "help" instead of the "message" above, 
but the help is the same as the above message, which more clearly shows 
the connection to XML events.

The itemset keyword in XForms generates, for each node of its nodeset,  a 
wrapper "item" element around a label, value and message given in the 
content of the itemset.  The XPaths within the wrapper item are evaluated 
relative to the generating node from the nodeset.  So the select1 will 
present a list of three items, chocolate, strawberry and vanilla.  When 
the user picks one, the "value" of it is placed into the node named 
desired.  If the user requests a hint on an item, they are told the color 
of the icecream represented by that item.

We cannot do this right now in XForms because elements like hint and help 
are not allowed in itemset.  We could do it with a message action instead, 
but the results across implementations are not likely to be interoperable. 
 The problem is that hint is very similar to having <message 
ev:event="xforms-hint">...</message>, which has some of the same problems 
as the action that listens for "xforms-select".

One problem is that it is unclear whether the action handler sets up a 
listener on each wrapper item generated by the itemset, or whether it sets 
up a listener on the itemset element itself, or both.

Based on having an XML events processor that is distinct from the XForms 
processor, I think we get both, which is unfortunate.  I think when the 
document is loaded, a listener for xforms-select on the itemset is 
created.  Then, when the XForms processor generates each wrapper item, 
that is a new XML document that contains an action handler, and so a new 
listener is created to listen for an xforms-select event on each wrapper 
item.

In this case, I did not intend to set the listener on the itemset but only 
on the generated items.  However, in this case, I think it doesn't hurt 
anything to have both ***unless*** events in the generated DOM are 
expected to bubble up to the generator items.  I believe the two DOMs are 
separate and that events don't bubble between them.  I also believe that 
XML Events talks about what happens within ***a*** DOM and does not define 
event bubbling between DOMs.  However, some have argued that just because 
the spec doesn't say the events bubble doesn't mean they don't bubble. 
Therefore, for the sake of clarity, please spell out the fact that the 
spec does not define any bubbling behavior between two DOMs and that 
events don't traverse more than one DOM unless a consumer of XML events 
defines a mechanism for dispatching events in one DOM based on the 
occurrence of events in another DOM.  And even then, there would be a 
problem because the join points between two DOMS would look like event 
targets when they should really be part of the capture and bubble phase of 
a multi-DOM event. 

Unfortunately, while my views above about events not bubbling between DOMs 
works out well for xforms-select, it does not work out so well in two 
other cases.

First, sometimes you do want the events to bubble out of generated content 
and into the generator.

Second, sometimes you only want the event handler to attach to the 
generator (repeater) element, not to the generated elements.

For the first case, we can amend the select1 above slightly to see the 
problem.  Suppose you have this:

<select1 ref="desired">
    <label>Pick one flavor:</label>
    <hint>The color will depend on what flavor you pick.</hint>
    <itemset nodeset="../flavor">
         <label ref="."/>
         <value ref="."/>
         <action ev:event="xforms-select">
           <!-- Do some stuff -->
         </action> 
    </itemset>
</select1>

Now, we would like to be able to say that the item element is the target 
of the xforms-hint event so that one can provide item-specific events. Yet 
clearly the second select1 above just wants to do a round-up of all 
xforms-hint events generated by all item elements and provide a more 
generic hint.  But for that to work, the xforms-hint targeted at the item 
would also need to bubble up to the select1.  We really need a fix for 
this.

For the second problem, I have to turn to the xforms repeat construct, and 
put a repeat within a repeat:

<repeat nodeset="some/nodes" id="X">
   <action ev:event="xforms-scroll-last">
         <!-- Do some stuff -->
   </action>
   <repeat nodeset="more/nodes" id="Y">
      ...
   </repeat>
</repeat>

In the above example, it is clear that I want to listen for 
xforms-scroll-last on repeat X.  However, I contend above that another 
copy of the event listener will be created to listen for 
xforms-scroll-last on each wrapper group element generated by the repeat 
to represent a "row" of the repeated content in a "table".  However, when 
an xforms-scroll-last is dispatched to an instance of repeat Y, it bubbles 
up from repeat Y to the wrapper group element, where we "Do some stuff" 
that was only intended to happen when repeat X received the event.

In this case I think it is a bit hacky but again an OK solution to 
conclude that a listener gets created both on the repeat in the original 
document and on each repeat row's wrapper group element as long as there 
is an easy way to restrict the handler to only run in the former case. And 
again, I realize there is *a* way, namely adding ev:targetid="X" but I 
only added the IDs for the purpose of discussion and I would prefer to not 
use IDs.  Fortunately, this is another case that would work out nicely if 
you added phase="target" AND made it the default.  Then, the above markup 
would look the way it acts, and it would act properly.

Cheers,
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 Friday, 10 August 2007 23:35:10 UTC