Écrit par Neil Deakin.
Traduit par Nadine Henry (17/09/2004), mise à jour par Laurent Jouanneau (20/09/2004) .
Page originale :
http://www.xulplanet.com/tutorials/xultu/xblex.html
Cette section va décrire un exemple d'élément XBL.
Construisons un exemple complet d'un élément XBL. Ce sera un élément graphique qui stocke un ensemble d'objets, un seul d'entre eux étant affiché à un moment donné. Les boutons de navigation le long du bas vont permettre à 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 boîte d'images. Nous appellerons cela un élément de présentation (NdT : un 'slideshow').
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
serait 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 10.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é à un nombre d'éléments pour qu'il s'étende de
la bonne manière. Les attributs label
sur les deux boutons héritent
leur valeur de l'élément qui leur est attaché. Ici, ils héritent de deux attributs personnalisés,
previoustext
et nexttext
. Cela rend
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="Boîte de dialogue 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.
Ensuite, une propriété contenant le numéro de la page courante est ajoutée.
Lorsqu'on obtient 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 façon similaire, 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, aussi, pour obtenir le paquet, nous devons obtenir le premier noeud
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.
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];
deck
(paquet).var totalpages=this.childNodes.length;
if (newidx<0) return 0;
if (newidx>=totalpages) return totalpages;
thedeck.setAttribute("selectedIndex",newidx);
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);
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
l'indice commence à 0.
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>
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 le retour chariot et la touche
Entrée). Les boutons "Premier" et "Dernier" peuvent être ajoutés pour aller à la première et à la
dernière page. L'élément label
pourrait être changé 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 CSS pour la rendre plus jolie.
Le code final est le suivant :
Exemple 10.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)+" of "+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)+" of "+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.