Skip to content

Instantly share code, notes, and snippets.

@JDziurlaj
Created December 13, 2022 18:00
Show Gist options
  • Save JDziurlaj/437ef86eaac38f4dc83c6bdef49d829e to your computer and use it in GitHub Desktop.
Save JDziurlaj/437ef86eaac38f4dc83c6bdef49d829e to your computer and use it in GitHub Desktop.
Reproduction for copy attribute issue Saxon-XForms
<xf:xform xmlns:rest="http://exquery.org/ns/restxq" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xf="http://www.w3.org/2002/xforms" xmlns:demo="urn:saxon-xforms:demo">
<!--
Have to use *: in XPaths. For some reason namespace declaration is not retained by betterForms
Have to use namespace. For some reason betterForms treats no namespace as XHTML namespace.
-->
<xf:model id="m-recipes">
<xf:instance id="all">
<demo:recipes>
<demo:recipe>
<demo:id>1</demo:id>
<demo:title>Orange and ginger chicken</demo:title>
<demo:ingredients>
<demo:ingredient>chicken</demo:ingredient>
<demo:ingredient>ginger</demo:ingredient>
<demo:ingredient>orange</demo:ingredient>
</demo:ingredients>
</demo:recipe>
<demo:recipe>
<demo:id>2</demo:id>
<demo:title>Sausage and mash</demo:title>
<demo:ingredients>
<demo:ingredient>sausages</demo:ingredient>
<demo:ingredient>potatoes</demo:ingredient>
<demo:ingredient>gravy</demo:ingredient>
</demo:ingredients>
</demo:recipe>
<demo:recipe>
<demo:id>3</demo:id>
<demo:title>Broccoli pasta</demo:title>
<demo:ingredients>
<demo:ingredient>broccoli</demo:ingredient>
<demo:ingredient>pasta</demo:ingredient>
<demo:ingredient>pesto</demo:ingredient>
<demo:ingredient>lemon</demo:ingredient>
</demo:ingredients>
</demo:recipe>
</demo:recipes>
</xf:instance>
<!-- empty <ingredient> to insert -->
<xf:instance id="i-new-ingredient">
<demo:ingredient/>
</xf:instance>
<xf:instance id="i-optional">
<demo:ingredient optional="true" />
</xf:instance>
</xf:model>
<div id="content">
<h2>Recipe list</h2>
<xf:repeat id="recipe-repeat" nodeset="instance('all')/demo:recipe" class="repeat" startindex="2">
<xf:output ref="demo:title"/>
<xf:repeat id="ingredient-repeat" nodeset="demo:ingredients/demo:ingredient" class="repeat">
<xf:output ref="text()"/>
</xf:repeat>
</xf:repeat>
<xf:trigger>
<xf:label>Rebuild</xf:label>
<xf:action ev:event="DOMActivate">
<xf:rebuild model="m-recipes"/>
</xf:action>
</xf:trigger>
<!--
EDIT RECIPE
-->
<h2>Edit recipe</h2>
<xf:group ref="instance('all')/demo:recipe[index('recipe-repeat')]" appearance="full" class="edit">
<xf:input ref="demo:title">
<xf:label>Recipe Name:</xf:label>
</xf:input>
<xf:repeat id="edit-ingredient-repeat" nodeset="demo:ingredients/demo:ingredient">
<xf:input ref="." id="edit-ingredient-repeat-input">
<xf:label>Ingredient:</xf:label>
</xf:input>
</xf:repeat>
<!-- http://wiki.orbeon.com/forms/how-to/logic/repeat-insert-position -->
<xf:trigger>
<xf:label>Add ingredient after selected item</xf:label>
<xf:action ev:event="DOMActivate">
<xf:insert context="." nodeset="demo:ingredients/demo:ingredient" at="index('edit-ingredient-repeat')" position="after" origin="instance('i-new-ingredient')"/>
<xf:setfocus control="edit-ingredient-repeat-input"/>
</xf:action>
</xf:trigger>
<xf:trigger>
<xf:label>Make ingredient optional</xf:label>
<xf:action ev:event="DOMActivate">
<xf:insert context="." nodeset="demo:ingredients/demo:ingredient" origin="instance('i-optional')/@optional"/>
<xf:setfocus control="edit-ingredient-repeat-input"/>
</xf:action>
</xf:trigger>
<xf:trigger>
<xf:label>Delete selected ingredient</xf:label>
<xf:action ev:event="DOMActivate">
<xf:delete context="." nodeset="demo:ingredients/demo:ingredient" at="index('edit-ingredient-repeat')"/>
<xf:setindex repeat="edit-ingredient-repeat" index="index('edit-ingredient-repeat') - 1" if="index('edit-ingredient-repeat') != 1"/>
<xf:insert context="./demo:ingredients" if="not(demo:ingredient)" nodeset="demo:ingredient" origin="instance('i-new-ingredient')"/>
<xf:setfocus control="edit-ingredient-repeat-input"/>
</xf:action>
</xf:trigger>
<xf:trigger>
<xf:label>Move selected ingredient Up</xf:label>
<!-- xf:action groups a sequence of actions -->
<xf:action ev:event="DOMActivate" if="index('edit-ingredient-repeat') != 1">
<!-- insert changes "focus" index to the newly inserted node -->
<xf:insert context="." nodeset="demo:ingredients/demo:ingredient" at="index('edit-ingredient-repeat') - 1" position="before" origin="demo:ingredients/demo:ingredient[index('edit-ingredient-repeat')]"/>
<!-- original node is now at index() + 2 -->
<xf:delete context="." nodeset="demo:ingredients/demo:ingredient" at="index('edit-ingredient-repeat') + 2"/>
<xf:setfocus control="edit-ingredient-repeat-input"/>
</xf:action>
</xf:trigger>
<xf:trigger>
<xf:label>Move selected ingredient Down</xf:label>
<!-- xf:action groups a sequence of actions
tried position() instead of index('edit-ingredient-repeat') but didn't work
possibly because focus was on a different row from where 'Down' was clicked
-->
<xf:action ev:event="DOMActivate" if="index('edit-ingredient-repeat') != count(demo:ingredients/demo:ingredient)">
<!-- insert changes "focus" index to the newly inserted node -->
<xf:insert context="." nodeset="demo:ingredients/demo:ingredient" at="index('edit-ingredient-repeat') + 1" position="after" origin="demo:ingredients/demo:ingredient[index('edit-ingredient-repeat')]"/>
<!-- original node is now at index() - 2 -->
<xf:delete context="." nodeset="demo:ingredients/demo:ingredient" at="index('edit-ingredient-repeat') - 2"/>
<!-- copy of original node is now at index() - 1 -->
<xf:setindex repeat="edit-ingredient-repeat" index="index('edit-ingredient-repeat') - 1"/>
<xf:setfocus control="edit-ingredient-repeat-input"/>
</xf:action>
</xf:trigger>
</xf:group>
</div>
</xf:xform>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment