XForms/Folding Menus
From Wikibooks, the open-content textbooks collection
< XForms
Contents |
[edit] Motivation
You want to display a complex list of choices in a tree structure where each branch could be opened and closed.
[edit] Sample Program
<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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ev="http://www.w3.org/2001/xml-events"> <head> <title>Folding Menus</title> <xf:model id="modelID" ev:event="" functions="" schema=""> <xf:instance id="instanceData" xmlns=""> <group id="mainGroup"> <group id="group1" fold="0" category="Category One"> <item id="item1">Enter Data</item> <item id="item2">Enter Data</item> <item id="item3">Enter Data</item> <group id="group2" fold="0" category="Category Two"> <item id="item4">Enter Data</item> <item id="item5">Enter Data</item> <group id="group3" fold="0" category="Category Three"> <item id="item6">Enter Data</item> <item id="item7">Enter Data</item> <item id="item8">Enter Data</item> </group> <item id="item9">Enter Data</item> </group> </group> </group> </xf:instance> <xf:instance id="foldedNodes" xmlns=""> <foldednodes> <nodelist /> </foldednodes> </xf:instance> <xf:bind nodeset="descendant::*" relevant="not(contains(instance('foldedNodes')/nodelist, current()/parent::*/@id))" /> </xf:model> <style type="text/css"> @namespace xhtml url("http://www.w3.org/1999/xhtml"); @namespace xf url("http://www.w3.org/2002/xforms"); xf|*:disabled { display: none; } </style> </head> <body> <div class="header">Folding Test</div> <xf:group id="mainGroup"> <xf:output ref="instance('foldedNodes')/nodelist"> <xf:label>ID List</xf:label> </xf:output> <xf:repeat nodeset="instance('instanceData')/descendant::group" id="repeatGroup"> <xf:output class="outputInline" value="concat(substring('                                                          ',1,3 * count(current()/ancestor::*)), '     ')" /> <xf:trigger> <xf:label> <xf:output value="if(contains(instance('foldedNodes')/nodelist, ./@id), '+', '-')" /> </xf:label> <xf:action ev:event="DOMActivate"> <xf:setvalue ref="instance('foldedNodes')/nodelist" value="if(contains(instance('foldedNodes')/nodelist, instance('instanceData')/descendant::group[position()=index('repeatGroup')]/@id), concat(substring-before(instance('foldedNodes')/nodelist, instance('instanceData')/descendant::group[position()=index('repeatGroup')]/@id), substring-after(instance('foldedNodes')/nodelist, instance('instanceData')/descendant::group[position()=index('repeatGroup')]/@id)), concat(instance('foldedNodes')/nodelist, instance('instanceData')/descendant::group[position()=index('repeatGroup')]/@id))" /> </xf:action> </xf:trigger> <xf:output class="outputInline" ref="./@category" /> <xf:repeat nodeset="./item" id="repeatItem"> <xf:output class="outputInline" value="concat(substring('                                                          ',1,3 * count(current()/ancestor::*)), '     ')" /> <xf:output class="outputInline" ref="./@id"> <xf:label>id: </xf:label> </xf:output> <xf:input class="inputInline" ref=".[name() = 'item' or name() = 'file']"> <xf:label>data: </xf:label> </xf:input> </xf:repeat> </xf:repeat> </xf:group> </body> </html>
[edit] Discussion
There are some interesteing XPath expressions in this example. For example the following counts the number of ancestor nodes of the current node:
count(current()/ancestor::*)
The following gets all of the decendant groups within the instance data:
instance('instanceData')/descendant::group
The following returns a "+" if the nodelist contains the value in the id attribute and a "-" if it does not.
if(contains(instance('foldedNodes')/nodelist, ./@id), '+', '-')
[edit] Credits
Thanks to Fraser for posting this on the Mozilla XForms developer newsgroup in Oct. of 2007