Creating a menuitem in the filter list to show all items is fairly easy. This item doesn't need to be generated from the datasource. Instead it will be what is called static content in a template. The static content is any content that is a sibling of the
template element. This content is displayed as is without affecting the generated content from the template.
<menulist datasources="template-guide-photos4.rdf" ref="http://www.daml.org/2001/09/countries/country-ont#Country" oncommand="applyFilter(event.target.value);"> <menupopup> <menuitem label="All"/> </menupopup> <template> <query> <content uri="?start"/> <triple subject="?country" predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#type" object="?start"/> <triple subject="?country" predicate="http://purl.org/dc/elements/1.1/title" object="?countrytitle"/> </query> <action> <menupopup> <menuitem uri="?country" label="?countrytitle" value="?country"/> </menupopup> </action> </template> </menulist>
The only difference between the previous example and this one is that the
menulist element has some additional content added before the template. The content will be displayed just like it would be as if the template wasn't present. That is, before the template is examined, the menulist would have one item in it, with the label 'All'. The template generates two results as before, one for each country, and appends a
menuitem for each one.
One interesting thing about this example is that only one
menupopup will be created, even though there are two in the code, one outside the template and another one inside the action body. This demonstrates how the template builder generates content, and the specifics of how this is done become important when dealing with recursive content and multiple rules.
What's going on here is that the XUL parser first creates the outer
menulist element. The static content outside the template will also be created. The result will be a XUL display that looks just like the code above, except that the template and its content is hidden. At this point, the menulist will have a menupopup as a child, and the menupopup will in turn have one menuitem child. Next, the template is examined and two results are generated. Remember that only the content at the uri attribute or below inside the action are copied for each result.
When processing the action body, the builder looks at the first element inside the
action, in this case, the
menupopup. This element doesn't have a uri attribute, so the builder knows that this element should only be created once. You might think that the builder would then just create a
menupopup, but it doesn't. Instead, it looks to see if a
menupopup already exists in the location where it would be generated. In this case, there is one, the static menupopup defined outside the template. Instead of creating another menupopup, the builder uses the existing one. This is convenient since it makes it easy to combine static results and template generated results into one list.
The builder then switches where generated content would be generated to inside to existing menupopup and moves onto the next part of the action, the
menuitem. This element has the uri attribute so this content will be duplicated for each result.
The technique of looking for an existing element applies to any type of content. The builder will treat the element as already present as long as some element with the same tag name exists. If you were to change the static content to be some other element besides a
menupopup, it won't match, so the builder will create a new one when handling the action.
This becomes useful when using multiple rules and we'll see some examples of this later.
Here is the example to try. Note that the workaround of loading the datasource beforehand as mentioned for the last example isn't necessary, as the existence of the static content is another effective workaround. So, if you're using menulists with templates and the data isn't displaying properly when the data hasn't loaded, try using a static
menupopup. It doesn't even need to have any items in it.
The static content may be placed before or after the template, although usually you would place it first. Note that the static content is always placed before the generated content, so the 'All' item will always be the first item in the menu.
Static Content Example
Let's look at another example, involving radio buttons. Actually, this example is similar, it just uses a radiogroup instead of a menulist to display the list of countries.
<radiogroup datasources="template-guide-photos4.rdf" ref="http://www.daml.org/2001/09/countries/country-ont#Country" onselect="applyFilter(event.target.value);"> <radio label="All" selected="true"/> <template> <query> <content uri="?start"/> <triple subject="?country" predicate="http://www.w3.org/1999/02/22-rdf-syntax-ns#type" object="?start"/> <triple subject="?country" predicate="http://purl.org/dc/elements/1.1/title" object="?countrytitle"/> </query> <action> <radio uri="?country" label="?countrytitle" value="?country"/> </action> </template> </radiogroup>
This example doesn't have any other content to generate outside the radio element with the uri attribute, so it will just be copied as is. The static 'All' radio button will be left as the first radio item.