11.8 Exemple XBL

Écrit par Neil Deakin , mise à jour par les contributeurs à MDC .
Traduit par Nadine Henry (17/09/2004), mise à jour par Laurent Jouanneau (20/09/2004) , Alain B. (04/04/2007) .
Page originale : http://developer.mozilla.org/en/docs/XUL_Tutorial/XBL_Example

Attention : Ce tutoriel est ancien et n'est pas mis à jour. Bien que beaucoup d'informations soient encore valables pour les dernières versions de gecko, beaucoup sont aussi obsolètes. Il est préférable d'aller consulter cette page sur la version française de ce tutoriel sur developer.mozilla.org.

Cette section va décrire un exemple d'élément XBL.

Un élément de diaporama

Construisons un exemple complet d'un élément XBL. Il s'agira de créer un élément graphique qui stocke un paquet d'objets, en les affichant un par un. Des boutons de navigation situés sur le bas permettront à l'utilisateur d'afficher les objets les uns aprés les autres (NdT : comme si c'était des pages) tandis qu'un élément graphique textuel entre les boutons affichera le numéro de la page courante. Vous pourriez mettre n'importe quoi dans les pages, cependant, cet élément graphique pourrait être utile pour afficher une série d'images. Nous l'appellerons élément de diaporama (NdT : 'slideshow').

Contenu du diaporama

Tout d'abord, déterminons quels sont les éléments qui ont besoin d'aller dans le contenu XBL. Puisque nous voulons un changement de page, un élément deck sera le plus approprié pour contenir les pages. Le contenu des pages sera spécifié dans le fichier XUL, et non dans XBL, mais nous aurons besoin de l'ajouter au sein du paquet (deck). La balise children devra être utilisée. En bas, nous aurons besoin d'un bouton pour aller à la page précédente, d'un élément graphique pour afficher la numéro de la page courante, et d'un bouton pour aller à la page suivante.

Exemple 11.8.1 : Source

<binding id="slideshow">
  <content>
    <xul:vbox flex="1">
      <xul:deck xbl:inherits="selectedIndex" selectedIndex="0" flex="1">
        <children/>
      </xul:deck>
      <xul:hbox>
        <xul:button xbl:inherits="label=previoustext"/>
        <xul:label flex="1"/>
        <xul:button xbl:inherits="label=nexttext"/>
      </xul:hbox>
    </xul:vbox>
  </content>
</binding>

Cette liaison crée la stucture de la présentation que nous souhaitons. L'attribut flex a été ajouté à plusieurs éléments pour qu'ils s'étendent de la bonne manière. Les attributs label sur les deux boutons héritent des valeurs de l'élément qui leur est attaché. Ici, ils héritent de deux attributs personnalisés, previoustext et nexttext. Ils rendent le changement des libellés des boutons simple. Les fils de l'élément auquel l'élément XBL est relié seront placés au sein de l'élément deck. L'attribut selectedIndex est hérité par le paquet, ainsi nous pouvons déclarer la page initiale dans XUL.

Le fichier XUL suivant produit le résultat affiché dans l'image.

<box class="slideshow" previoustext="Précédent" nexttext="Suivant"
flex="1">
  <button label="Bouton 1"/>
  <checkbox label="Case à cocher 2"/>
  <textbox/>
</box>

Le style CSS utilisé ici est :

.slideshow {
  -moz-binding: url("slideshow.xml#slideshow");
}

Le premier bouton, Bouton 1 a été utilisé comme première page du paquet. L'élément graphique label (NdT : celui du XBL) n'est pas apparu puisqu'aucun attribut value ne lui a été spécifié. Nous pourrions déclarer une valeur, mais elle sera plutôt calculée plus tard.

Propriété page

Ensuite, une propriété contenant le numéro de la page courante est ajoutée. Pour lire cette propriété personnalisée, il est nécessaire de rechercher la valeur de l'attribut selectedIndex du paquet qui contient le numéro de la page affichée. De même, lorsqu'on modifiera cette propriété, il sera nécessaire de changer l'attribut selectedIndex du paquet. De plus, l'élément graphique textuel devra être mis à jour pour afficher le numéro de la page courante.

<property name="page"
    onget="return
parseInt(document.getAnonymousNodes(this)[0].childNodes[0].getAttribute('selectedIndex'));"
    onset="return this.setPage(val);"/>

La propriété page obtient sa valeur en observant le premier élément du tableau anonyme. Elle renvoie la boîte verticale, donc, pour obtenir le paquet, nous devons obtenir le premier n½ud fils de la boîte. Le tableau anonyme n'est pas utilisé puisque le paquet n'est pas anonyme à partir de la boîte. Finalement, la valeur de l'attribut selectedIndex est récupérée. Pour spécifier la page, une méthode setPage qui sera définie plus tard est appelée.

Un gestionnaire oncommand devra être ajouté aux boutons Précédent et Suivant pour que la page soit changée lorsque les boutons sont pressés. Nous pouvons changer facilement la page en utilisant la propriété personnalisée page qui vient d'être ajoutée :

<xul:button xbl:inherits="label=previoustext"
               oncommand="parentNode.parentNode.parentNode.page--;"/>
<xul:description flex="1"/>
<xul:button xbl:inherits="label=nexttext"
               oncommand="parentNode.parentNode.parentNode.page++;"/>

Etant donné que la propriété page est dans l'élément XUL externe, nous devons utiliser la propriété parentNode pour l'obtenir. La première propriété parentNode retourne l'élément parent du bouton qui est la boîte horizontale, la seconde son parent, la boîte verticale, et la dernière son parent qui est la boîte externe. La propriété page est incrémentée ou décrémentée. Elle va appeler le script onget pour obtenir la valeur, incrémentera ou décrémentera la valeur, et enfin appelera le gestionnaire onset pour enregistrer la valeur.

Méthode setPage

Définissons à présent la méthode setPage. Elle prendra un paramètre, le numéro de page qui sert à spécifier la page. Il sera nécessaire de vérifier que le numéro de page n'est pas en dehors des limites et ensuite modifier les attributs selectedIndex du paquet et l'attribut label de l'élément graphique textuel.

<method name="setPage">
  <parameter name="newidx"/>
  <body>
    <![CDATA[
      var thedeck=document.getAnonymousNodes(this)[0].childNodes[0];
      var totalpages=this.childNodes.length;

      if (newidx<0) return 0;
      if (newidx>=totalpages) return totalpages;
      thedeck.setAttribute("selectedIndex",newidx);
      document.getAnonymousNodes(this)[0].childNodes[1].childNodes[1]
              .setAttribute("value",(newidx+1)+" sur "+totalpages);
      return newidx;
    ]]>
  </body>
</method>

Cette fonction est appelée setPage et prend un paramètre newidx. Le corps de la méthode a été encapsulé entre <![CDATA[ et ]]>. C'est le mécanisme général dans tous les fichiers XML qui peut être utilisé pour échapper tout le texte à l'intérieur. De cette manière, vous n'avez pas besoin d'échapper tous les signes "inférieur" et "supérieur" à l'intérieur.

Décomposons le code morceau par morceau.

var thedeck=document.getAnonymousNodes(this)[0].childNodes[0];
Récupère le premier élément du tableau de contenu anonyme qui sera la boîte verticale, puis obtient son premier fils qui sera le paquet deck.
var totalpages=this.childNodes.length;
Récupère le nombre de fils que détient la boîte qui est liée. Cela donnera le nombre total de pages qui s'y trouve.
if (newidx<0) return 0;
Si le nouvel index est avant la première page, ne pas changer la page et retourner 0. La page ne devrait pas donner une valeur plus petite que la première page.
if (newidx>=totalpages) return totalpages;
Si le nouvel index est après la dernière page, ne pas changer la page et retourner le dernier index de page. La page ne devrait pas devenir celle qui est après la dernière.
thedeck.setAttribute("selectedIndex",newidx);
Changer l'attribut selectedIndex du paquet. Cela entraîne l'affichage de la page demandée.
document.getAnonymousNodes(this)[0].childNodes[1].childNodes[1].setAttribute("value", (newidx+1)+" sur "+totalpages);
Cette ligne modifie l'élément label pour qu'il affiche l'index de la page courante. L'élément label peut être récupéré en obtenant le premier élément du contenu anonyme (la boîte verticale), le second fils de cet élément (la boîte horizontale), et enfin le second élément de cette boîte. L'attribut value est modifié pour indiquer 1 sur 3 ou quelque chose de similaire. Notez que l'index est incrémenté de un parce que les indices commence à 0.

Constructeur

Nous allons aussi avoir besoin d'un constructeur pour initialiser l'élément label afin qu'il s'affiche correctement la première fois que la présentation est affichée. Nous utilisons un code similaire à la méthode ci-dessus pour déclarer le numéro de page. La référence à 'this.page' va appeler le script onget de la propriété page qui à son tour va recupérer la page initiale à partir de l'attribut selectedIndex.

<constructor>
  var totalpages=this.childNodes.length;
  document.getAnonymousNodes(this)[0].childNodes[1].childNodes[1]
          .setAttribute("value",(this.page+1)+" sur "+totalpages);
</constructor>

Fonctionnalités supplémentaires

Nous pouvons aussi ajouter quelques caractéristiques supplémentaires. Certains raccourcis claviers peuvent être utilisés pour les boutons Précédent et Suivant, (disons l'effacement arrière et la touche Entrée). Des boutons Premier et Dernier peuvent être ajoutés pour aller à la première et à la dernière page. L'élément label pourrait être transformé en un champ de saisie où l'utilisateur pourrait entrer la page à afficher, ou une fenêtre surgissante pourrait être ajoutée pour permettre la sélection de la page à partir d'un menu. Nous pourrions aussi ajouter une bordure autour de la boîte avec un style CSS pour la rendre plus jolie.

Le code final

Le code final est le suivant :

Exemple 11.8.2 : Source

<binding id="slideshow">
  <content>
    <xul:vbox flex="1">
      <xul:deck xbl:inherits="selectedIndex" selectedIndex="0" flex="1">
        <children/>
      </xul:deck>
      <xul:hbox>
        <xul:button xbl:inherits="label=previoustext"
                    oncommand="parentNode.parentNode.parentNode.page--;"/>
        <xul:description flex="1"/>
        <xul:button xbl:inherits="label=nexttext"
                    oncommand="parentNode.parentNode.parentNode.page++;"/>
      </xul:hbox>
    </xul:vbox>
  </content>

  <implementation>

    <constructor>
      var totalpages=this.childNodes.length;
      document.getAnonymousNodes(this)[0].childNodes[1].childNodes[1]
              .setAttribute("value",(this.page+1)+" sur "+totalpages);
    </constructor>

    <property name="page"
          onget="return
parseInt(document.getAnonymousNodes(this)[0].childNodes[0].getAttribute('selectedIndex'));"
          onset="return this.setPage(val);"/>

    <method name="setPage">
      <parameter name="newidx"/>
      <body>
        <![CDATA[
          var thedeck=document.getAnonymousNodes(this)[0].childNodes[0];
          var totalpages=this.childNodes.length;

          if (newidx<0) return 0;
          if (newidx>=totalpages) return totalpages;
          thedeck.setAttribute("selectedIndex",newidx);
          document.getAnonymousNodes(this)[0].childNodes[1].childNodes[1]
                  .setAttribute("value",(newidx+1)+" sur "+totalpages);
          return newidx;
        ]]>
      </body>
    </method>
  </implementation>

</binding>

Tester dans une fenêtre : Voir.


Nous allons voir ensuite quelques propriétés additionnelles d'une fenêtre.


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.