Neil's Place

July 18, 2005

8:18 PM XUL Tutorial Now Part of the Mozilla Developer Documentation

In case you haven't noticed, the XUL tutorial is now available as part of the Mozilla Developer Documentation site. An advantage of this is that errors can be corrected quickly and by anyone who spots them. The user notes created by users haven't been transfered though. I'm not sure if that's a good thing or not.

The user notes include a number of useful tips that people have written relating to a particular page. Currently the user notes aren't posted until I actually read them. This is a good thing since half of the notes are either questions (which I usually just ignore), or are misleading or incorrect. On one hand, I don't want to discourage someone by not accepting a comment they've made, but on the other hand, I feel that if a comment is misleading or uses, for example, some code that is a bad way of doing something, I don't want to post it, since the point of the user notes is to improve the documentation.

Anyway, I think there are plans on posting some other XULPlanet stuff, and I also plan on posting the template guide I've been writing on here. The Aaron countdown timer seems to have disappeared recently perhaps indicating his return a few days early so maybe the App tutorial or Prefbar will get updated also.

In other news, I've been hacking a bit at templates using XML data. Here's the first ever image of a XUL template fed with only XML input. It doesn't look very exciting but that's because the excitment is in disguise. Vlad's just reviewed the main part of the code for this, so we could very well see this stuff early in the 1.9 timeframe.

Comments ( 3 )


7:52 PM How Templates Work XXVII - Container Tests

The simple rule syntax supports two special conditional tests that are commonly used with multiple rules. The first of these tests can be used to test if an element is a container or not. To use this test, place an iscontainer attribute on a <rule>. The iscontainer attribute should be set to true if you only want to match containers, and false if you only want to match non-containers. A container is an RDF container such as a Seq.

The iscontainer attribute makes it easier to handle recursive content since you can have one rule for all containers and another rule for all non-containers. You don't need to match by type or some other predicate. This allows you to recurse down to larger levels without needing additional rules. It is commonly used with menus, and we can rewrite the previous example using the iscontainer attribute instead.

<button label="Houses in my Neighbourhood" type="menu"
        datasources="template-guide-streets.rdf"
        ref="http://www.xulplanet.com/rdf/myneighbourhood">
  <template>
    <rule iscontainer="true">
      <menupopup>
        <menu uri="rdf:*" label="rdf:http://purl.org/dc/elements/1.1/title"/>
      </menupopup>
    </rule>
    <rule>
      <menupopup>
        <menuitem uri="rdf:*" label="rdf:http://www.xulplanet.com/rdf/address"/>
      </menupopup>
    </rule>
  </template>
</button>

The only difference in the code in this example is that the order of the rules has been switched around, the condition check for house has been removed and the iscontainer attribute has been added. Since the iscontainer attribute is set to true, the rule will match as long as the member value or child of the starting node is an RDF container. We could also have left the rules in the original order and set the iscontainer on the first rule to false. The only thing we need to make sure is that the rules are in the proper order, so that the right data will be matched by the right rule. Remember, the more specific rules should go before less specific rules.

Note that leaving out the iscontainer attribute is not the same as setting it to either true or false. If you don't use the iscontainer attribute, the rule will match regardless of whether the node is a container or not.

The iscontainer attribute will also match containers appropriately if you have used the containment attribute in the template to change the predicates that indicate containership. If the node has one of the predicates listed in the containment attribute pointing out of it, it will also be considered to be a container. For instance, we might add the following to the previous example:

<button label="Houses in my Neighbourhood" type="menu"
        datasources="template-guide-streets.rdf"
        containment="http://www.xulplanet.com/rdf/address"
        ref="http://www.xulplanet.com/rdf/myneighbourhood">

The houses do have a value for the "http://www.xulplanet.com/rdf/address" predicate, so they will also be considered to be containers as well, resulting in another level of menus. Of course, we will need to update the predicates and labels to retrieve the right data. But this example demonstrates that something different is indeed happening.

The second special condition attribute tests for empty containers. This invloves setting the isempty attribute on a rule to either true or false. Setting it to true will match all empty containers, that is, containers with no children. Setting it to false will match all containers that have at least one child. Leaving out the isempty attribute will match anything. This condition test is commonly used to display the generated content differently for empty and non-empty containers.

You will commonly use the two attributes iscontainer and isempty together in different combinations to create the effect you need. Typically, this will mean one rule for a container with children, a second rule for empty containers, and a third rule for non-containers. Considering the case of bookmarks, the first two rules would match folders, while the third rule would match bookmarks. Naturally, the emptiness test does not apply to nodes that are not containers.

Note that both the iscontainer and isempty attributes are only available for rules that use the simple syntax.

Comments ( 1 )