The most common element to use with a template is the tree.
You can use a template with a tree just like any other template. However, since templates are often used with trees—especially with large amounts of data—the template system supports a special builder just for creating trees. Rather than generate content for every row in the tree, the results are stored in a list inside the builder. This means that DOM nodes are not constructed for any of the items. This is much more efficient; creating large numbers of DOM nodes adds a lot of overhead. The performance advantage is possible since trees only display text. As a result, the builder only has a few pieces of information to keep track of.
To use the tree builder, you need to add a flags attribute to the root node:
<tree datasources="template-guide-streets.rdf" ref="https://www.xulplanet.com/rdf/myneighbourhood" flags="dont-build-content">
The dont-build-content
flag causes no content to be built for the template. But moreover, it uses a subtype of the main builder called the tree builder. Without this flag, the template will be handled by the content builder.
Apart from the flags
attribute, the template syntax for the tree builder and the content builder are identical. However, the tree builder requires a very specific form to the action body. Specifically, the action body should be a single treeitem
with its rows and cells.
Here is an example (using an RDF source):
<tree id="photosList" flex="1" datasources="template-guide-photos5.rdf" ref="https://www.xulplanet.com/rdf/myphotos" flags="dont-build-content"> <treecols> <treecol id="name" label="Name" flex="1"/> <treecol id="date" label="Date" flex="1"/> </treecols> <template> <treechildren> <treeitem uri="rdf:*"> <treerow> <treecell label="rdf:https://purl.org/dc/elements/1.1/title"/> <treecell label="rdf:https://purl.org/dc/elements/1.1/date"/> </treerow> </treeitem> </treechildren> </template> </tree>
treecols
) are declared outside the template as static content, since they only need to be declared once.This template uses the simple rule syntax. The extended syntax could also be used. When using the tree builder, the uri
attribute must be declared on the treeitem
element.
Here, the simple RDF query syntax is used, so the member variable is rdf:*
. The remaining tags have a similar syntax to a tree, but have only a single row. This row is used as the template data by the tree builder. Instead of generating content, the builder uses the cell attributes to determine what to display. The tree builder implements the nsITreeView interface, so it becomes the tree’s view—in other words, the tree’s view and the tree’s builder are the same object. When the tree is displayed, it asks the view for the contents of each cell. The builder looks at the label for the corresponding cell, translates any variables or predicates into values, and returns the value.
In the example above, the first cell should display the title. The builder doesn’t compute any labels until the view asks for them. When the view requests a label for the first cell, the builder looks up the ‘https://purl.org/dc/elements/1.1/title’ predicate for the row in question and returns it.
The content builder generates content in the template body and substitutes data from the datasource right away. However, it will generate the same result on screen to the user as with the tree builder. Compare the example with a tree builder and the same example using a content builder.
Here is an example of a tree using an SQLite datasource:
<tree datasources="profile:messages.sqlite" ref="*" querytype="storage" flags="dont-build-content"> <treecols> <treecol id="subject" label="Subject" flex="3"/> <treecol id="sender" label="Sender" flex="2"/> <treecol id="date" label="Date" flex="1"/> </treecols> <template> <query> select subject, sender, date from messages </query> <action> <treechildren> <treeitem uri="?"> <treerow> <treecell label="?subject"/> <treecell label="?sender"/> <treecell label="?date"/> </treerow> </treeitem> </treechildren> </action> </template> </tree>
Features of the Tree Builder
Besides the label of a cell, there are several other cell properties you can set when using the tree builder. The supported properties are: label
, mode
, properties
, src
and value
. The label
attribute is used to set the label for a cell. The mode
is used for progress meter columns. It may be set to either “normal” for a normal progress meter or “undetermined” for an undetermined progress meter. The value
attribute is used to set the current progress value for normal progress meters. The value
attribute may also be used for checkbox columns by setting it to either true
or false
. Whether a cell is a normal labeled value, a progress meter or a checkbox is determined by the type
attribute on the column the cell is in.
For cells in normal columns, you can use the value
attribute to store some other value and you can use the view’s getCellValue()
method to retrieve it. Naturally, this will retrieve the value after any variables have been substituted.
Besides the attributes mentioned above, any other attributes specified on the tree rows and cells are ignored. Since no elements are generated, you won’t be able to retrieve the values for them either. Thus, the value
attribute may be useful to associate an additional value with a row since it will be easier to retrieve.
The src
attribute may be used to set an image to appear in a cell. For example:
<tree id="photosList" flex="1" datasources="template-guide-photos5.rdf" ref="https://www.xulplanet.com/rdf/myphotos" flags="dont-build-content"> <treecols> <treecol id="photo" label="Photo" flex="1"/> </treecols> <template> <treechildren> <treeitem uri="rdf:*"> <treerow> <treecell src="rdf:*"/> </treerow> </treeitem> </treechildren> </template> </tree>
This tree displays each photo in the tree cells. In this case, the member resource is used since that holds the photo’s URL. However, it could be any other variable, a static value, or a combination of both.
Of course, we can’t really see the photos, since the tree’s rows are too small! It’s not normal to put photos in a tree like this—instead, the images would be used for icons. On the other hand, you could use a stylesheet to change the default height of the tree rows. You cannot make each row a different height, but you can change the height of all rows with some CSS:
treechildren::-moz-tree-row { height: 150px; }
Since no elements are constructed by the tree builder, you cannot use the style or class attributes to change the style of a cell (This is the case with all trees). You must use syntax like that above to change the appearance. In the example above, it changes the height of a row to 150 pixels. You may want to change the syntax to refer to a specific treechildren
element rather than all of them. Once the row height is changed, we can see the full photos.
Using Tree Properties
Since we need to use special CSS for trees, the properties
attribute on a cell becomes extremely useful. It can be used to define extra properties for reference later in a stylesheet.
For example, if the properties attribute was set to the value "?creator", you could style the photos created by different people differently. Alternatively, you could also use static values (in addition to variables) in the properties
attribute. For instance, consider the following CSS:
treechildren::-moz-tree-cell(Dave) { background-color: lightgreen; }
This would set the background color of a cell to green for any cell with the “Dave” property. You can also use the properties attribute on the treerow
to change the style for an entire row. This example sets the country associated with a photo as a property of a tree’s rows. We can use that property to change the appearance of each row.
<rule> <query> <content uri="?start"/> <member container="?start" child="?photo"/> <triple subject="?photo" predicate="https://www.xulplanet.com/rdf/country" object="?country"/> <triple subject="?country" predicate="https://purl.org/dc/elements/1.1/title" object="?countrytitle"/> </query> <action> <treechildren> <treeitem uri="?photo"> <treerow properties="?countrytitle"> <treecell src="?photo"/> </treerow> </treeitem> </treechildren> </action> </rule>
You might use the following CSS to change the border around rows listing a particular country:
treechildren::-moz-tree-row(Netherlands) { border: green 1px solid; }
The result of this example is a tree where one row has a green border around it.