Attention : Le contenu de ces pages n'a pas été mis à jour depuis longtemps. Il est probablement obsolète pour Firefox 4.0/Gecko 4.0 et supérieur. Pour du contenu plus récent, allez consulter developer.mozilla.org.

Exemple arbre hiérarchique code commenté

Ceci est l'exemple détaillé d'utilisation d'un nsITreeView pour un arbre hierarchique simple (on ne peut pas replier les branches), qui fonctionne avec gecko 1.8.

(page originale)

Intro

le but : afficher un arbre comme ceci :

 foo
	foo1
		foo4
		foo5
	foo2
		foo6
	foo3

Fichier xul

 <tree flags="dont-build-content" flex="1" id="thetree">
 <!--
    tree : pour dire que c'est un arbre
    flags="dont-build-content" : pour dire au générateur de rendu de ne pas
                                 afficher le contenu ?
    flex="1" : pour que l'arbre soit "flexible", donc s'adapte à la taille de
               la boîte qui le contient (peut être la fenêtre)
    id="thetree" : le "nom" de cet arbre, pour que javascript puisse l'appeler
 -->
    <treecols>
    <!--
       Définition des colonnes de l'arbre
    -->
      <treecol id="nom"  label="nom" primary="true" flex="1" />
      <!--
          Première colonne.
          id="nom"       : Elle s'appelle "nom" pour le DOM
          label="nom"    : Elle portera le titre "nom" quand elle sera affichée
          primary="true" : (?)
          flex="1"       : Elle sera "souple", flexible
      -->
      <treecol id="prenom" label="prenom" flex="1"/>
      <!--
          Idem pour la seconde colonne
      -->
    </treecols>
    <!--
        Fin de la définition des colonnes de l'arbre (il y a en donc 2)
    -->
    <treechildren/>
    <!--
        Pour placer les enfants de cet arbre, donc le contenu des
        colonnes et des lignes.
        C'est javascript qui se chargera de "peupler" l'arbre
        Noter le slash (/) à la fin. On aurait pu écrire aussi :
        <treechildren></treechildren>
    -->
 </tree>
 <!--
     Fin de la définition de l'arbre
 -->

La structure des données

Pour que cela soit simple au maximum, il faut une structure qui correspondent à ce qu'on veut afficher. On va donc avoir un tableau qui va comporter autant d'objet que de lignes.

  var gDataList = [];

Voici la structure des objets stockés dans gDataList :

 function dataInfo(){
    this.name="";
    this.firstname="";
    this.children=[]; // contient la liste du dataInfo
    this.parent=null; // pointe vers le dataInfo parent
    this.level = 0; // profondeur dans la hierarchie ( = nombre d'ancètre en fait)
    this.index = 0; // index de l'objet dans le tableau gDataList. utile pour getParentIndex
    this.nextSibling; // si le dataInfo est un fils, indique son frère suivant dans la liste des fils du parent
 }

Pour le remplissage du tableau, voir le fichier http://xulfr.org/sources/treeviewsimple/(..)

Ce code est repris en partie ci-dessous, pour commentaires :

 gDataList[0]= new dataInfo();
 /*
    On dit que le premier élément de gDataList (donc l'élément « 0 »), va
    être une instance de l'objet dataInfo défini plus haut (donc un clone
    totalement vierge
    Maintenant que ce premier élément est créé, on va le remplir, renseigner
    ses propriétés :
 */
 gDataList[0].name='foo';
 /* On met son 'name' à "foo" */
 gDataList[0].firstname='bar';
 /* On met son 'firstname' à "bar" */
 gDataList[0].parent=null;
 /* On dit qu'il n'a pas de parent (donc = null) */
 gDataList[0].level = 0;
 /* On dit qu'il est au premier niveau de l'arbre */
 gDataList[0].index = 0;
 /* On dit que c'est le premier élément (donc « 0 »)
 gDataList[0].nextSibling;
 /* On dit… rien du tout encore, on ne connaît pas son frère suivant, puisqu'il
    est pour le moment fils unique */
 gDataList[1]= new dataInfo();
 /* On crée le deuxième élément gDataList (donc son indice est « 1 »)
    Pour faire différent, on va créer une référence à ce deuxième élément,
    pour ne pas être obligé de toujours reprendre dDataList[1] (ce qui serait
    possible, comme dans le fichier original) :
 */
 var le2eElement = gDataList[1] ;
 /* On peut maintenant le renseigner comme l'autre : */
 le2eElement.name = 'foo1';
 le2eElement.firstname='bar1';
 le2eElement.parent=gDataList[0];
 le2eElement.level = 1; // C'est le deuxième niveau du tableau (qui commence à 0)
 le2eElement.index = 1; // C'est le deuxième élément du tableau (idem)
 /*
    On crée maintenant un troisième et quatrième élément, mais cela auront
    un indice 4 et 6 dans le tableau (car on en a besoin tout de suite pour
    préciser quelques parents qu'on verra plus bas)
    On crée donc l'élément d'indice 4
 */
 gDataList[4]= new dataInfo();
 /*
   ''(pour les plus forts que moi, peut-être faire ça sans perdre
     l'instance ?)''
   Attention : si ce code n'est pas confirmé par des plus forts que moi,
   utiliser le code ci-dessus, en reportant les valeurs.
 */
 gDataList[4] = {
                 'name':'foo2', 'firstname'='bar2',
                 'parent'=gDataList[0], /* Ici, on indique que le parent de cet
                                          élément d'indice 4 sera le premier élément*/
                 'level'=1, 'index'=4
                };
 /*
    On crée de la même façon un quatrième élément d'indice 6
    (cf. le code original)
 */
 …
 /*
    Maintenant que les éléments d'indice 4 et 6 ont été créés, on
    peut préciser que le deuxième élément (indice 1) aura l'élément
    d'indice 4 comme fils suivant…
 */
 gDataList[1].nextSibling = gDataList[4];
 /*
    Et que l'élément 4 aura pour frère suivant l'élément 6
 */
 gDataList[4].nextSibling = gDataList[6];
 /*
    On ajoute maintenant des enfants (children) au premier élément,
    grâce à la méthode "push" des tableaux (qui ajoute un élément
    à la fin de la liste (ici, la liste des enfants)
 */
 gDataList[0].children.push(gDataList[1]); // Le premier enfant de 0 sera l'élément 1
 gDataList[0].children.push(gDataList[4]); // Le deuxième enfant de 0 sera l'élément 4
 gDataList[0].children.push(gDataList[6]); // Le troisième enfant de 0 sera l'élément 6
 /*
   On crée tous les autres éléments de la même façon
   cf. le fichier original, il n'y a rien de plus
 */

L'objet d'interface nsITreeView

On crée maintenant l'objet qui va servir à afficher les données dans l'arbre. Les méthodes de cet objet seront appelées à divers stade du processus d'affichage de l'arbre. Par exemple, quand l'arbre voudra afficher le texte d'une cellule, il va appeler la méthode getCellText pour le récupérer.

 var theview =  {
	rowC[[ount:0]], // y mettre le nombre d'element gDataList.length
	[[selection:null]],
	[[treebox:null]],
	[[widget:null]],
	getCellText  : function (  row , col ) {
		if(col.id=='nom')
			return gDataList[row].name;
		else
			return gDataList[row].firstname;
	},
	getCellValue  : function (  row , col )  {return "";},
	getImageSrc  : function (  row , col )  {return "";},
	getLevel  : function (  row )  {
		return gDataList[row].level;
	},
	getParentIndex  : function (  row ){
		if(gDataList[row].parent)
			return gDataList[row].parent.index;
		else
			return 0;
	},
	hasNextSibling  : function (  row , afterIndex ){
		return (gDataList[row].nextSibling != null);
	},
	isContainer  : function (  row )    {
		return (gDataList[row].children.length > 0);
	},
	isContainerEmpty  : function (  row )  {
		return (gDataList[row].children.length == 0);
	},
	isContainerOpen  : function (  row )  { return true; },
	getProgressMode  : function (  row , col )   {},
	getCellProperties  : function (  row , col , properties ) { },
	getColumnProperties  : function ( col, properties ){},
	getRowProperties  : function (  row , properties ){ },
	isEditable  : function (  row , col )  {return false;},
	isSeparator  : function (  row )    {return false;},
	isSorted  : function ( )    {return false;},
	performAction  : function ( action )    {},
	performActionOnCell  : function ( action ,  row , col )   {},
	performActionOnRow  : function (  action ,  row )   {},
	selectionChanged  : function ( )    {},
	setCellText  : function (  row , col , value )    {},
	setTree  : function ( tree )    { this.treebox = tree;},
	toggleOpenState  : function (  row ) { },
	canDrop : function ( row , orientation ) { return false;},
	drop  : function (  row ,  orientation ) {},
	cycleCell  : function (  row , col ) {},
	cycleHeader  : function ( col ) {}
 }

Ensuite il suffit de l'affecter au tree pour que l'affichage se produise :

 theview.rowCount= gDataList.length;
 document.getElementById("thetree").view = theview;

Demo et autre lien

Voir la page originale


Copyright © 2003-2013 association xulfr, 2013-2016 Laurent Jouanneau - Informations légales.

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.