3.4 - Tests spéciaux

Attention : Ce tutoriel est ancien, incomplet, et n'est pas mis à jour. Il ne contient pas toutes les nouveautés du système de template de Gecko 1.9 / Firefox 3.0 qui est largement simplifié et permet d'utiliser sqlite ou xml comme source de données. Aussi est-il préférable d'aller consulter la version anglaise sur developer.mozilla.org.

Tests de conteneurs

La syntaxe de règle simplifiée supporte deux tests conditionnels spéciaux habituellement utilisés avec des règles multiples. Le premier de ces tests sert à tester si un élément est un conteneur ou non. Pour l'utiliser, placez un attribut iscontainer sur un élément rule. L'attribut iscontainer doit être défini à true si vous ne voulez trouver que des conteneurs, et à false si vous ne voulez trouver que des non-conteneurs. Un conteneur est un conteneur RDF tel qu'un Seq.

L'attribut iscontainer facilite la gestion des contenus récursifs puisque vous pouvez avoir une règle pour tous les conteneurs et une autre règle pour tous les non-conteneurs. Vous n'avez plus besoin de filtrer selon un type ou selon quelques prédicats. Il vous permet une récursivité plus profonde vers des niveaux plus importants sans avoir recours à des règles supplémentaires. Il est communément utilisé avec des menus, et nous pouvons réécrire l'exemple précédent en utilisant l'attribut iscontainer à la place.

<button label="Les maisons de mon quartier" 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>

La seule différence dans le code de cet exemple est que l'ordre des règles a été inversé, que la condition testant les maisons a été supprimée et que l'attribut iscontainer a été ajouté. Comme l'attribut iscontainer est défini à true, la règle sera vérifiée pour la valeur membre ou le fils d'un noeud de départ qui sont des conteneurs RDF. Nous pourrions également laisser les règles dans l'ordre originel et définir sur la première règle l'attribut iscontainer à false. La seule chose dont nous devons être certain, est que les règles soient dans l'ordre approprié afin que les données attendues correspondent à la bonne règle. Souvenez vous que les règles les plus spécifiques doivent être placées avant les règles moins spécifiques.

Notez que l'omission de l'attribut iscontainer ne signifie pas la même chose que de le définir à true ou à false. Si vous n'utilisez pas l'attribut iscontainer, tous les noeuds correspondront à la règle, qu'ils soient un conteneur ou non.

L'attribut iscontainer trouvera également les conteneurs convenablement si vous avez placé un attribut containment dans le gabarit pour définir les prédicats modifiés en conteneur. Si le noeud a un de ces prédicats listés dans l'attribut containment et pointant vers celui-ci, il sera aussi considéré comme étant un conteneur. Par exemple, nous pourrions ajouter le code suivant à l'exemple précédent :

<button label="Les maisons de mon quartier" type="menu"
        datasources="template-guide-streets.rdf"
        containment="http://www.xulplanet.com/rdf/address"
        ref="http://www.xulplanet.com/rdf/myneighbourhood">

Les maisons ont une valeur pour le prédicat http://www.xulplanet.com/rdf/address, donc elles seront également considérées comme des conteneurs, ce qui entraînera la création d'un autre niveau de menus. Bien entendu, vous devrons mettre à jour les prédicats et les libellés pour obtenir un rendu correct. Mais cet exemple illustre ce qui s'est réellement produit.

Tests de conteneurs vides

Le second attribut conditionnel spécial teste les conteneurs vides. Il nécessite de placer l'attribut isempty sur une règle avec la valeur true ou false. Avec la valeur true, tous les conteneurs vides correspondront, c'est-à-dire les conteneurs n'ayant aucun enfant. Avec la valeur false, tous les conteneurs ayant au moins un enfants correspondront. Sans cet attribut isempty, tout pourra correspondre. Ce test conditionnel est communément utilisé pour afficher du contenu généré de façon différente selon qu'il s'agit de conteneurs vides ou non vides.

De façon courante, vous utiliserez les deux attributs iscontainer et isempty ensemble selon différentes combinaisons pour créer l'effet désiré. Typiquement, cela signifie une règle pour un conteneur avec enfants, une seconde règle pour des conteneurs vides, et une troisième règle pour des non-conteneurs. Dans le cas des Marque-pages, les deux premières règles trouvent les dossiers, tandis que la troisième règle trouve les marque-pages. Naturellement, le test isempty ne s'applique pas aux noeuds qui ne sont pas des conteneurs.

Notez que les deux attributs iscontainer et isempty ne sont disponibles que pour des règles utilisant la syntaxe simplifiée.

Tests de balises parentes

Parfois, vous souhaitez simplement générer un bloc de contenu au niveau le plus haut et un contenu différent dans les niveaux récursifs. Par exemple, la barre d'outils des Marque-pages dans Firefox affiche un bouton au premier niveau, mais des menus et sous-menus ensuite. La totalité de la barre d'outils des Marque-pages est générée par un gabarit XUL.

Les gabarits peuvent permettre à une règle de tester si le contenu généré sera inséré à l'intérieur d'un élément ayant un nom précis de balise. Par exemple, si le conteneur était un vbox, une règle peut être créée pour ne correspondre qu'à cet élément vbox. Cette technique est très utile pour des gabarits récursifs, puisque les itérations internes peuvent utiliser du contenu différent. Il est plus utile de distinguer entre les niveaux externes et internes pendant le processus de génération du gabarit. Dans le cas de la barre d'outils des Marque-pages, le contenu externe est inséré à l'intérieur d'un hbox, mais au niveau inférieur, le contenu sera inséré à l'intérieur d'un menu.

Au cas où ce n'est pas clair, la balise devant correspondre à l'itération externe est l'élément racine, celui contenant l'attribut datasources. Pour les itérations internes, il s'agira de l'élément contenant l'attribut uri de l'itération précédente.

Pour réaliser ce type de correspondance dans une syntaxe simplifiée de gabarit, placez un attribut parent sur l'élément rule en lui affectant le nom de la balise à tester. Par exemple, nous pourrions utiliser le code suivant :

<vbox datasources="template-guide-streets.rdf"
            ref="http://www.xulplanet.com/rdf/myneighbourhood">
  <template>
    <rule parent="vbox">
      <groupbox uri="rdf:*">
        <caption label="rdf:http://purl.org/dc/elements/1.1/title"/>
      </groupbox>
    </rule>
    <rule>
      <label uri="rdf:*" value="rdf:http://www.xulplanet.com/rdf/address"/>
    </rule>
  </template>
</vbox>

Lors de la première passe, le conteneur dans lequel le contenu généré sera inséré est un vbox, donc la première règle va s'appliquer et un groupbox titré sera créé. Lors de la passe suivante, le conteneur parent sera l'élément avec l'attribut uri de la passe précédente, et dans ce cas, il s'agira du groupbox. Ce n'est donc plus la première règle qui ne va correspondre, mais la seconde règle en créant un libellé. Le résultat peut être observé si vous essayez cet exemple.

Tests de balises parents en utilisant la syntaxe étendue

Une balise de test peut également être utilisée avec la syntaxe étendue, bien que l'écriture soit différente. Plutôt que de mettre l'attribut parent sur la balise rule, vous placez un attribut tag sur la balise content dans les conditions. Par exemple, le test équivalent à l'exemple précédent utilisant l'attribut tag dans une syntaxe étendue est le suivant :

<content uri="?start" tag="vbox">

Cet exemple génère le même contenu en sortie que celui utilisant la syntaxe simplifiée. Comme nous l'avons vu dans les quelques exemples précédents, il existe plusieurs manières différentes de structurer les deux règles pour réagir différemment selon les niveaux. Des tests généraux sur des triplets, des tests sur un type RDF, des tests de conteneur et des tests sur les balises parentes, tous ces tests fournissent une grande variété de méthodes de filtrage spécifique. Bien entendu, dans les exemples simples que nous avons utilisé, les avantages d'une sorte de condition sur une autre ne sont pas évidents. Dans des exemples plus complexes toutefois, vous verrez le bénéfice d'un test sur les autres en fonction de la structure des données et de l'interface utilisateur que vous voulez créer. En combinant les différents types de conditions, des interfaces plus complexes peuvent être créées simplement avec des gabarits.


Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.