N'oubliez pas, vous pouvez reduire les fenetres pour organiser la page...
Telechargez ici Eclipse, logiciel tres puissant pour coder ; De nombreux plugs-in sont disponibles.
Plier le cadre - XML : Apprentissage niveau 1



Question 1: POURQUOI XML ?


img:coupe


Bonne question.
Pourquoi se lancer dans l'apprentissage ardu d'un truc qui a l'air horriblement compliqué (déjà rien qu'à voir le nombre de méthodes et de propriétés dans l'aide..) alors que les interpolations de forme ont l'air super bien et que le mélangeur de couleurs est ergonomique ???

Et bien voilà:

Supposons que dans une animation, un élément gagnerait à être dynamique (traduction: ça peut changer sans aucune intervention de votre part, selon les gens qui voient la page)

Par exemple il faut afficher le nom d'une personne, son age, la couleur de ses cheveux et s'il aime oui ou non le coca light décaféiné.
Jusque là, beaucoup me répondront:
on peut loader des variables d'un fichier texte, qui aurait la forme:

CODE
"nom=dupond&age=13&cheveux=violet&cocalight=non"


Soit.
Cette solution est acceptable.
...mais...
Supposons maintenant qu'il faut charger les infos sur 500 personnes...
Ca devient embrouillé...
Surtout si des attributs sont imbriqués...
(par exemple, pour les cheveux, la couleur et la longueur...)


C'est dans ce cas qu'XML intervient, en structurant efficacement les données.

Pour notre apprentissage, nous allons nous limiter à une seule personne et une seule information dessus.



Question 2: QU'EST-CE QUE C'EST le XML ?

img:coupe

Bonne question aussi (vous cumulez, là, c bien wink.gif )
Tout simplement c'est ça:

étape 1
:arrow: j'ouvre mon bloc-note

étape 2

:arrow: je tape :

CODE
<racine>

    <personne nom="dupond" age="13" />

</racine>


étape 3
:arrow: j'enregistre sous "essai.xml" (ouais bon ce qu'on veut quoi smile.gif)

PS : pour des mesures de sécurité pour la suite, et vu que flash mx n'accepte que du texte encodé en UTF8 je vous conseille d'enregistrer votre fichier en UTF8 (voir tutorial à ce sujet)



Question 3: COMMENT J'UTILISE le XML ?

img:coupe

Voila voila, fini de délirer, on passe aux choses sérieuses:

Dans flash, il y a une étape préliminaire:

CODE
xmlDoc= new XML(); /* créer un objet xml */

xmlDoc.ignoreWhite=true; /* ignorer les sauts de ligne */

xmlDoc.load("essai.xml"); /* loader le fichier */


Ceci vient de creer un objet xml et de loader le xml dedans.
Le chargement du xml peut prendre un certain temps, il y a des méthodes pour verifier qu'un fichier xml est bien chargé dans le tutorial "XML: préchargements".
On admet ici que le XML est à présent completement chargé:

Maintenant voyons comment recuperer le nom de la personne, et son age.
Voici déjà la réponse, c'est respectivement:

xmlDoc.firstChild.childNodes[0].attributes.nom
et
xmlDoc.firstChild.childNodes[0].attributes.age

Les attributs sont les paramêtres qui sont entre les crochets d'une même balise, sous la forme: nomParam='valeur'.

Maintenant voyons ce qu'on peut faire d'autre avec ce xml:
xmlDoc désigne l'objet xml en entier, celui qu'on a tapé dans l'éditeur.

Il possède à la base qu'on seul noeud, 'racine' (il ne doit pas y avoir plus d'un noeud au premier niveau ! impératif)
Pour désigner ce noeud, qui est 'le premier noeud enfant' du xml, on fait:
xmlDoc.firstChild .

Finalement, les informations dont on dispose par rapport à xmlDoc sont les mêmes, tout est là puisque'à la base il n'y a qu'un seul noeud.
Seulement, on a maintenant un noeud, et non un xml.

En particulier, ce noeud a un nom, 'racine' disponible par xmlDoc.firstChild.nodeName et ce noeud a un (ou plusieurs, mais pas ici) noeud enfants. Ceux-ci sont rangés dans le tableau 'childNodes' du noeud, donc ici le tableau est:

xmlDoc.firstChild.childNodes

Ce tableau, comme tous les tableaux a une longueur pour compter le nombre de noeuds enfants:

xmlDoc.firstChild.childNodes.length (=1 dans cet exemple)

Voyons maintenant le noeud '<personne nom="dupond" age="13" />'

Il s'agit d'un noeud enfant de 'racine' et le premier ( numéro 0 ) donc accessible par:

xmlDoc.firstChild.childNodes[0]

Ce noeud est (un noeud, donc:) du même type que 'racine', donc il pourrait avoir des noeuds enfants.
Au lieu de cela il a cette fois des attributes, rangés selon le même principe dans un tableau:

xmlDoc.firstChild.childNodes[0].attributes .

Toujours pareil, on a la propriété length sur ce tableau qui nous donne le nombre d'attibutes (ici 2, 'nom' et 'age')
Enfin pour acceder aux attributs on fait:

xmlDoc.firstChild.childNodes[0].attributes.nom
et:
xmlDoc.firstChild.childNodes[0].attributes.age

Dans un prochain tutorial, quelques petits exercices pour vous entrainer au maniement de données provenant de fichiers XML !!
Plier le cadre - XML : Apprentissage niveau 2

Alors voici quelques exemples de xml, puis une ou deux questions question et la réponse.


1.

CODE
<?xml version="1.0" encoding="iso-8859-1" ?>

<racine>

<personne nom="mat" age="17" />

<personne nom="kevin" age="19" />

<personne nom="lucas" age="27" />

</racine>


-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
>>Comment obtenir l'age de kevin ?
réponse:
xmlDoc.firstChild.childNodes[1].attributes.age
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
>>Comment savoir combien de personnes on recense?
réponse:
xmlDoc.firstChild.childNodes.length


2.

CODE
<?xml version="1.0" encoding="iso-8859-1" ?>

<racine>

  <personne nom="mat" age="17">

      <ami nom="georges" age="16" />

      <ami nom="sophie" age="18" />

  </personne>

  <personne nom="kevin" age="19">

      <ami nom="manu" age="18" />

  </personne>

  <personne nom="lucas" age="27">

      <ami nom="greg" age="30" />

      <ami nom="olivier" age="27" />

      <ami nom="marie" age="28" />

</personne>

</racine>


-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
>>Comment obtenir le nombre d'amis de lucas ?
réponse:
xmlDoc.firstChild.childNodes[2].childNodes.length
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
>>Comment obtenir le nom de l'ami de kevin ?
réponse:
xmlDoc.firstChild.childNodes[1].childNodes[0].attributes.nom
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
>>Comment obtenir l'age moyen des amis de lucas ?
réponse:

for(var i=0,var moyenne=0;i<xmlDoc.firstChild.childNodes[2].childNodes.length;i++)
moyenne+=xmlDoc.firstChild.childNodes[2].childNodes[i].attributes.age;

moyenne/=i+1;


Je rajouterai régulièrement des exemples assez différents, à bientôt.
Plier le cadre - XML : la transition de mySQL à Flash

Transformer une requete SQL en fichier XML img:coupe

Il est d'actualité de parler de flash dynamique et d'interactivité entre les technologies web.
Or précisement un des moyens de relier ces technologies, c'est le XML, sur lequel tout le monde insiste.
Beaucoup, quand on leur dit que le XML sert à structurer les données, le mettent instinctivement en 'concurrence' avec les bases de données telles MySql, et pensent les deux technologies incompatibles ou redondantes.
Pourtant, il existe une autre manière d'examiner le problème : le XML peut etre utilisé non comme solution d'archivage des données mais bien comme une formidable solution de TRANSFERT des données, en préservant la structure.

img:remarque Nous nous interessons ici à l'exploitation d'une base MySql par une application flash.
La jonction sera faite par un fichier php qui produira du code xml et non html, ce qui permet d'etre loadé dans un flash.
Le deuxième point interessant, c'est que la requete effectuée par le php lui sera transmise en parametre, dynamiquement par le flash.
Il s'agit donc d'un code polyvalent, utile en toutes situations, dès que vous voudrez remplacer une page web par une animation swf.

img:as Voici donc le code php:

CODE
<?xml version="1.0" encoding="UTF-8" ?>

<?



/*

** le script necessite que lui fournisse ou bien

** une requete  SQL précise,

** ou bien le nom d'une table qu'il retournera en entier.

**

** tout d'abord on se connecte à la base mysql

** remplacez host/login/pass/dbname par vos parametres

** ( par exemple, sur free, le login sert aussi de dbname

** et le host c'est 'sql.free.fr' )

*/

mysql_connect("host","login","pass") or die('<error>connexion impossible</error>');

mysql_select_db("dbname") or die('<error>Base down</error>');



/*

** ici on determine la requete

** selon que l'on a spécifié une requete précise

** ou seulement une table

*/

if(!$query)

$query="SELECT * FROM $table";



/*

** on effectue la requete:

** si elle échoue, un message d'erreur est renvoyé

*/

$result = mysql_query($query) or die('<error>'.$mysql_error().'</error>');



/*

** ici il sagit de structurer les données pour former la chaine xml

** la structure est LA MEME qu'un tableau html :

** <ligne><colonne></colonne><colonne></colonne></ligne>

** <ligne><colonne></colonne><colonne></colonne></ligne>

**

** dans notre cas:

** <row><field></field><field></field>><field></field></row>

** on utilise pour cela deux boucles for() , l'une pour les lignes

** et l'autre pour les colonnes.

*/

$xml = '<query numrows="'.mysql_num_rows($result).'">\n';

for($i = 0; $i < mysql_num_rows($result); $i++)

{

        $xml .= '<row>';

        $row= mysql_fetch_row($result);

        //pour tous les champs

        for($j = 0; $j < mysql_num_fields($result); $j++)

              $xml .= '<field name="'.mysql_field_name($result,$j).'">'.$row[$j].'</field>';

      $xml .= '</row>\n';

}

$xml .= '</query>\n';

mysql_free_result($result);



/*

** on donne le résultat:

*/

echo $xml;



?>



img:as Vu du flash, le code aura cette allure:

CODE
data=new XML(); // déclaration

data.ignoreWhite=true; // ignorer les sauts de ligne, indispensable

table='table_news'; //par exemple

data.load("URL/mysql_xml.php?table="+table);


Dans ce cas simple le fichier retournera tout la table, il est donc beaucoup plus puissant de transmettre une requête ciblée au fichier, de la meme façon que vous avez transmis le nom de la table.

Veuillez vous reporter aux autres tutoriaux pour manipuler les fichiers XML, ou mettre en place un préchargement. Merci.
Plier le cadre - Préchargement de données

Ce tutorial est une extension au tout premier, et a pour but d'expliquer le fonctionnement d'un système de préchargement pour le xml.

Supposons donc que l'on a écrit et enregistré ce fichier XML:

<?xml version="1.0" encoding="iso-8859-1"?>
<racine>
<perso nom="Wolf" />
<perso nom="Storm" />
</racine>


et que dans notre fichier flash on a codé:

document=new XML();
document.ignoreWhite=true;
document.load("monUrl.com/fichier.xml");
trace(document.firstChild.childNodes[1].attributes.nom);
/* doit afficher 'Storm' */


...
ça ne marche pas...

La raison est que lorsque flash execute la dernière ligne de commande, il n'a en général pas fini, ou pas même commencé de charger le fichier XML.
En conséquence, 'document.firstChild.childNodes[1].attributes.nom' lui paraît assez brumeux sinon imprécis smile.gif comme expression et il lui attribue, logique comme il est, la gentille valeur de 'undefined' ...

Il faut donc prévoir un certain temps entre le début du chargement et l'utilisation des donées.
Il y a la manière aveugle, c'est à dire laisser dix ou vingt images-clés entre les deux lignes de commande.
Ca marche dans la plupart des cas, mais s'il y a un gros lag ça ne marcher plus du tout...
La deuxième solution consiste à coder un loading, ce qui est beaucoup plus 'mieux' biggrin.gif

Alors voici plusieures façons de faire, en ordre croissant de subtilité biggrin.gif :

image 1:
document=new XML();
document.ignoreWhite=true;
document.load("monUrl.com/fichier.xml");

image 2:
if(!document.loaded)
gotoAndPlay("imagePrecedente");

image 3;
trace('document.firstChild.childNodes[1].attributes.nom');


-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

DEUXIEME METHODE:


image 1:
document=new XML();
_root.document.ignoreWhite=true;
_root.document.load("monUrl.com/fichier.xml");
_root.stop();
_root.document.onLoad=function(){
_root.play();
}

image 2:
trace(_root.document.firstChild.ChildNodes[1].attributes.nom);


EQUIVALENT A:

image 1:
_root.document=new XML();
_root.document.ignoreWhite=true;
_root.document.load("monUrl.com/fichier.xml");
_root.stop();
_root.document.onLoad=function(){
trace( this .firstChild.childNodes[1].attributes.nom);
_root.play();
}

Bon evidement cette dernière solution est un peu mieux mais peut-être beaucoup moins lisible dans quelques cas.

Remarquez aussi que lorsqu'on utilise le 'onLoad', les instructions entre crochets vont agir sur le document xml, désigné par 'this'.

Autre remarque:

On possède sur l'objet XML beaucoup de méthodes et propriétés, dont par exemple 'getBytesTotal()' et 'getBytesLoaded()' .
On peut les utiliser pour afficher le taux de chargement mais en aucun cas pour le code du préchargement lui-même.
En effet, les deux valeurs valent 0 immédiatement après avoir donné l'ordre de charger le XML. En conséquence, l'expression 'getBytesLoaded()==getBytesTotal()' vaudra 'true' bien que le fichier ne soit pas du tout chargé...
D'où l'utilisation de la propriété 'loaded' de l'objet XML, ou du gestionnaire d'evenements 'onLoad'.

Plier le cadre - Charger un fichier XML sur un autre serveur

[EDIT] Cette méthode n'est disponible que sur le Flash Player version 6

La methode load de l'objet XML n'autorise pas a accéder a un fichier qui ne soit pas dans un sous-répertoire sur le meme serveur que le swf ... :?
Devons nous donc renoncer a afficher (par exemple) des news fournies en XML par certains sites ( http://www.clubic.com/js/actu.xml par ex) ? :cry:

ET BIEN NON !!! :twisted: 8)

En effet, la methode sendAndload de l'objet LoadVars n'ayant pas cette restriction, et étant donné que vous pouvez indiquer un objet cible, il vous suffit de créer un objet LoadVars vide, et de faire un sendAndLoad vers votre objet XML, et le tour est joué !

CODE
// Objet XML que l'on veut charger

monXML = new XML();

monXML.onData = function {

  ...... // Les instructions a effectuer aprés chargement

}



// Objet LoadVars vide

monLoadVars = new LoadVars();



//On charge le fichier XML avec l'instruction sendAndLoad du LoadVars

monLoadVars.sendAndLoad("http://www.monsite.com/fichier.xml",monXML);

et le tour est joué !

En espérant que cela a pu vous servir, a+

Plier le cadre - Menu XML Elastique


Voici un menu XML pour Flash MX, avec des mouvements de menu élastiques.
Il est sous forme de Composant, pour etre ré-utilisable facilement.

Pour le détail du code, ouvrez la bibliothèque puis le composant 'XMLMenu'.

Pour l'utiliser, il suffit de faire glisser le menu sur la scene et de renseigner les paramètres dans l'onglet "Paramètres" du panneau [Propriétés] ...

Bonne lecture !!

xmlmenu.zip

Plier le cadre - XML : Menu dynamique avec arborescence

Dans ce tutorial, on va créer pas à pas une animation qui va chercher l'arborescence d'un menu dans un fichier xml et qui l'affiche, avec autant de niveau que l'on veut.
Bref, un script qui marche dans 100% des cas, facilement personnalisable.


Objectifs :
:arrow: charger les infos du fichier XML
(ça vous devriez commencer à avoir l'habitude, maintenant sinon, lire les autres tutos)
:arrow: construire le menu d'après l'arborescence du xml.
Plus dur, il faudra construire une fonction recursive, vu qu'on ne sait pas à priori combien de niveaux il y aura.

Voici la structure du menu qu'on veut avoir:
Racine
--Archives
----Par date
------ 10juillet *
------ 25juillet *
------ 25 aout *
---- Par sujet
------ location *
------ vente *
--Liens
---- Ciseaux
------ English
--------mysite *
------Francophone
--------mysite1 *
--------mysite2 *
--------mysite3 *
--------mysite4 *
--------mysite5 *
----Telescopique
------Labozone *
------Blitzds *

Les astérisques veulent dire que c'est le dernier niveau et que donc l'élement n'est plus une catégorie mais un lien cliquable (avec des infos comme l'url et le target)

voici le fichier xml:

CODE


<?xml version="1.0" encoding="iso-8859-1"?>

<items name="racine" >

<item name="Archives" >

  <item name="par date" >

  <item name="10 Juillet 02" adr="page1.htm" targ="_blank"/>

  <item name="25 Juillet 02" adr="page2.htm" targ="_blank"/>

  <item name="25 Aout 02" adr="page1.htm" targ="_blank"/>

  </item>

  <item name="par sujet" >

  <item name="Location" adr="page1.htm" targ="_blank"/>

  <item name="Vente" adr="page1.htm" targ="_blank"/>

  </item>

</item>

<item name="Liens" >

  <item name="Ciseaux" >

  <item name="English" >

    <item name="mysite" adr="mysite.htm" targ="_blank"/>

  </item>

  <item name="Francophone" >

    <item name="mysite1" adr="mysite1.htm" targ="_blank"/>

    <item name="mysite2" adr="mysite2.htm" targ="_blank"/>

    <item name="mysite3" adr="mysite3.htm" targ="_blank"/>

    <item name="mysite4" adr="mysite4.htm" targ="_blank"/>

    <item name="mysite5" adr="mysite5.htm" targ="_blank"/>

  </item>

  </item>

  <item name="telescopique" >

  <item name="Labozone" adr="http://www.lab.danceallstar.com/" targ="_blank"/>

  <item name="Blitz DS" adr="http://www.blitzds.com/" targ="_blank"/>

  </item>

</item>

</items>


Vous voyez que les possibilités sont infinies


Il est essentiel pour ce tutorial de bien comprendre comment on 'navigue' dans un XML à l'aide des 'childNodes' et autres 'firstChild' et 'attributes'.

Il est aussi recommandé d'avoir été en contact au moins une fois dans sa vie avec les fonctions récursives, auxquelles on met parfois un peu de temps à s'habituer.


On commence par le plus simple, bien sûr, le chargement du XML:

img:as image 1:
CODE
XMLmenu = new XML();

XMLmenu.ignoreWhite = true;

XMLmenu.load("menuMOD.xml");


img:as image 2:
création du clip, par programmation dans cet exemple, on peut bien sûr prendre un clip dessiné, pour des raisons esthétiques
Dans ce cas, il faut le placer sur la scene et lui donner le nom "modele"

CODE
_root.createEmptyMovieClip("modele",0);

_root.modele.lineStyle(1,0x000000,100);

_root.modele.beginFill(0xcccccc,100);

_root.modele.moveTo(0,0);

_root.modele.lineTo(0,20);

_root.modele.lineTo(150,20);

_root.modele.lineTo(150,0);

_root.modele.lineTo(0,0);

_root.modele.endFill();


img:as image 3: vide

img:as image 4:
le test de chargement du XML:
CODE
if(!XMLmenu.loaded)

gotoAndPlay(3);


img:as image 5:
les choses sérieuses commencent !!

CODE


_root.count=0;

// compteur pour le nombre de clips



/* ci-dessous la fonction recursive

** elle prend en paramêtres le niveau

** de l'arborescence à laquelle se trouve l'élément

** et bien sur le noeud XML d'où est

** tiré l'élément */



function constructLevel(XMLnode,parentLevel){

_root.count++;//incrémentation du compteur

if(XMLnode.attributes.adr==undefined){

  // si ce n'est pas le dernier niveau:

  _root.modele.duplicateMovieClip("item"+_root.count,_root.count);

  // on duplique le modele

  // on le place en le décalant vers la droite

  // selon son niveau dans l'arborescence:

  _root["item"+_root.count]._x=parentLevel*20;

  // on le place verticalement d'après le nombre

  // de clips déjà présents avant lui:

  _root["item"+_root.count]._y=count*25;

  // on crée un champ de texte dedans:

  _root["item"+_root.count].createTextField("name",1,20,0,130,20);

  // et on écrit son nom dedans:

  _root["item"+_root.count].name.text=XMLnode.attributes.name;

  // on a vu que ce n'était pas le dernier élément

  // donc  on réapplique la même fonction sur

  // chacun de ses 'fils'

  for(var i=0;i<XMLnode.childNodes.length;i++){



  constructLevel(XMLnode.childNodes[i],parentLevel+1);

  }

}else{

  // il s'agit du dernier élément dans

  // l'arborescence, c'est-à-dire

  //  d'un lien cliquable :

  _root.modele.duplicateMovieClip("item"+_root.count,_root.count);

  _root["item"+_root.count]._x=parentLevel*20;

  _root["item"+_root.count]._y=count*25;

  _root["item"+_root.count].createTextField("name",1,20,0,130,20);

  _root["item"+_root.count].name.text=XMLnode.attributes.name;

  // jusqu'ici, rien n'a changé, mais

  // maintenant on transforme le clip en bouton:

  Object.registerClass(_root["item"+_root.count], Button);

    _root["item"+_root.count].enabled = true;    

    _root["item"+_root.count].useHandcursor = true;

  // puis on lui dit où il doit nous mener

  // lorsqu'on clique:

    _root["item"+_root.count].onRelease = function () {

      getURL(XMLnode.attributes.adr,XMLnode.attributes.targ);

    }

}

}

// la fonction est prête, il ne reste plus qu'à la lancer,

// avec en noeud XML le XML tout entier, et en niveau: '0'



constructLevel(XMLmenu.firstChild,0);

stop();


Fini !
Comme toujours, une anim 100% code, "nette et propre" mais vous pouvez evidemment remplacer l'affreux rectangle gris par un élément graphique en accord avec votre charte graphique, il suffit de le placer sur la scène et de lui donner le nom "modele".

(Pour ceux qui aiment un peu bidouiller (tout le monde ici, j'espère! ) dans ce cas il est peut-être préférable d'utiliser des 'attachMovie', vous n'aurez pas à mettre votre clip sur la scène dans ce cas.)

En préparation, un menu du même genre mais animé, mais pas pour tout de suite

Fichier(s) joint(s)
menuxml.zip
menuxml.zip

Plier le cadre - Chargement d'une liste d'images (1)

A l'origine de ce tutorial, une question de Spontex, qui nous a finalement résumé la marche à suivre pour monter une galerie dynamique d'images par xml, que voici ( avec un préchargement du xml ):


Objectif :
:arrow: Charger des jpeg depuis un fichier XML
:arrow: Placer ces images en ligne de 3 colonnes.

img:remarque Impératif : les jpeg NE doivent PAS être enregistrées en "progressif"

img:as Fichier XML :

CODE
<gallerie>

  <desc nom="1.jpg" />

  <desc nom="2.jpg" />

  <desc nom="3.jpg" />

  <desc nom="4.jpg" />

  <desc nom="5.jpg" />

  <desc nom="6.jpg" />

</gallerie>


img:as Image 1
CODE
gallerieXml = new XML();

gallerieXml.ignoreWhite = true;


img:as Image 2
On charge le xml:
CODE
gallerieXml.load("gallerie.xml");


img:as Image 3 vide

img:as Image 4:
On fait un test pour voir si le xml est chargé:
CODE
if(!gallerieXml.loaded)

gotoAndPlay(3);


img:as Image 5
CODE
//Recupération des donnees du fichier xml

var galleriev = gallerieXml.firstChild.childNodes;

var lon = galleriev.length; //nombre d'image à placer

for (var i = 0; i<lon; i++) {

var nom = galleriev[i].attributes.nom; //recupére le nom du fichier

// Création d'un clip vide:

_root.createEmptyMovieClip("bitmap_mc"+i, i+10);

_root["bitmap_mc"+i].loadMovie(nom); //charge le jpeg

_root["bitmap_mc"+i]._xscale = _root["bitmap_mc"+i]._yscale /= 50; /*réduit l'image 50 fois, dépend de vos images*/

}

// Déplacement et redimensionnement du clip conteneur:

var colonne = 0; //j'initialise le nombre de colonne

var ligne = 0; //j'initialise le nombre de ligne

for (i=0; i<lon; i++) {

if (colonne == 3) { //si colonne =3 alors on change de ligne et on reprend à la colonne 0

  colonne = 0;

  ligne++;

}



//maintenant on dispose les images à partir de x=0 et y=0

_root["bitmap_mc"+i]._x = colonne*40;

_root["bitmap_mc"+i]._y = ligne*40;

colonne++;

}

stop();

Plier le cadre - Chargement d'une liste d'images (2)

Ce tutorial qui dérive du précédent est beaucoup plus complet, on trouve entre autres une fonction pour vérifier le chargement des images, correction de bugs, choix entre affichage par lignes ou colonnes, nombre de ligne/colonnes personnalisable, espacement entre les images et resize de celles-ci pour qu'elles occupent une zone précise...


Objectif :
:arrow: Charger des jpeg depuis un fichier XML
:arrow: Placer ces images en ligne de n colonnes.

img:remarque Impératif : les jpeg NE doivent PAS être enregistrées en "progressif"

img:as Fichier XML :

CODE
<gallerie>

  <desc nom="1.jpg" />

  <desc nom="2.jpg" />

  <desc nom="3.jpg" />

  <desc nom="4.jpg" />

  <desc nom="5.jpg" />

  <desc nom="6.jpg" />

</gallerie>


img:as Image 1
CODE
gallerieXml = new XML();

gallerieXml.ignoreWhite = true;


img:as Image 2
On charge le xml:
CODE
gallerieXml.load("gallerie.xml");


img:as Image 3 vide

img:as Image 4:
On fait un test pour voir si le xml est chargé:
CODE
if(!gallerieXml.loaded)

gotoAndPlay(3);



jusque là, pas de changements...


img:as Image 5
CODE


/* tous les paramêtres suivants gagneraient à être transmis par le xml également, de la même façon que pour les urls des images ou les champs de texte de l'autre tutorial */





// les images vont s'inscrire dans un carre de coté:

_root.zoneTaille = 80;

// espacement entre les images:

_root.zoneEspace = 10;

_root.affichage = "Colonnes";

// ou "Lignes" , avec la majuscule

_root.nbColonnes = 3;

// la variable ci-dessous de sera donc pas prise en compte, dans cet exemple

_root.nbLignes = 3;



//Recupération des donnees du fichier xml

_root.galleriev = gallerieXml.firstChild.childNodes;

_root.lon = galleriev.length; //nombre d'image à placer

for (i = 0; i<_root.lon; i++) {

  var nom = galleriev[i].attributes.nom; //recupére le nom du fichier

  // Création d'un clip vide:    

  _root.createEmptyMovieClip("bitmap_mc"+i, i+10);

  _root["bitmap_mc"+i].loadMovie(nom); //charge le jpeg

}

_root.picsLoaded = true;



img:as Image 6 vide


img:as Image 7
pour voir si toutes les images sont chargées:
CODE


_root.picsLoaded=true;

for(i=0;i<_root.lon;i++){

if(_root["bitmap_mc"+i].getBytesLoaded() !=_root["bitmap_mc"+i].getBytesTotal())

_root.picsLoaded=false;

}

if(_root.picsLoaded == true)

_root.gotoAndPlay(8);

else

_root.gotoAndPlay(6);



img:as Image 8
Ici on construit la gallerie, c'est à dire qu'on redimensionne les images et ensuite on les déplace.

CODE
for(i=0;i<_root.lon;i++){

_root.facteur=Math.max(_root["bitmap_mc"+i]._width,_root["bitmap_mc"+i]._height)/_root.zoneTaille;

  _root["bitmap_mc"+i]._xscale = _root["bitmap_mc"+i]._yscale /=_root.facteur;

//réduit l'image originale pour  qu'elle rentre dans la zone

}



// Déplacement et redimensionnement du clip conteneur:

_root.a = 0; //colonnes ou lignes (colonnes dans l'exemple)

_root.b = 0; //lignes ou colonnes

for (i=0; i<_root.lon; i++) {

  if (_root.a == _root["nb"+_root.affichage]) {

      _root.a = 0;

      _root.b++;

  }



//maintenant on dispose les images à partir de x=0 et y=0

  _root["bitmap_mc"+i]._x =(_root.affichage=="Colonnes"? _root.a : _root.b)*(_root.zoneTaille+_root.zoneEspace);

  _root["bitmap_mc"+i]._y =(_root.affichage=="Colonnes"? _root.b : _root.a)*(_root.zoneTaille+_root.zoneEspace);





  a++;

}



stop();


C'est fini, tout marche bien, j'espère que ce script aidera ceux qui veulent monter une petite galerie d'images, vous pouvez très facilement adapter celle-ci à vos besoins.
Dès que possible, je posterai la version prototypée du script, afin de convertir très simplement un movieClip Quelconque en galerie dynamique !

Ca sera un truc du genre:

movieClip.createGalerie(fichierXml,largeurPhotos,espacement,affichage,nb);
donc par exemple:
CODE
movieClip.createGalerie("file.xml",80,10,"Colonnes",3);

Le rêve, quoi


img:coupe


Et voici le prototype promis !!
(fichier source dispo en bas, anim en 100% code toujours)

Voici la syntaxe:

clip.loadGalerieFromXml(file,zoneTaille,zoneEspace,affichage,nombre);



Signification des paramêtres:

file : le nom du fichier xml, par exemple : "fichier.xml"
zoneTaille : les images vont s'adapter à un carré dont il faut spécifier le coté, par exemple : 80
zoneEspace :l'espacement entre ces carrés, par exemple: 10
affichage : "Colonnes" ou "Lignes" suivant ce que vous voulez.
nombre : le nombre d'items dont vous avez choisi la nature ci-dessus.


Finalement, le fichier flash ressemblera à quelque chose comme ça:

img:as image 1:
CODE
#include "galerieXmlPROTO.as"

_root.createEmptyMovieClip("galerie",1);

_root.galerie.loadGalerieFromXml("galerie.xml",80,10,"Colonnes",3);

stop();




AUSSI SIMPLE QUE CELA !!!

Bon, il faudrait peut-être que je vous donne le proto, maintenant

Tout ce code est à copier-coller dans le bloc-notes dans un fichier:
"galerieXmlPROTO.as" (ou sous un autre nom, mais veiller à changer le nom dans le flash aussi, au moment de l'inclusion du fichier )


CODE
movieClip.prototype.loadGalerieFromXml = function(file,zoneTaille,zoneEspace,affichage,nombre){

  this.galerieXml = new XML();

  this.galerieXml.parent=this;

  this.galerieXml.ignoreWhite = true;

  this.galerieXml.onLoad = function(){

      this.parent.zoneTaille = zoneTaille;

      this.parent.zoneEspace = zoneEspace;

      this.parent.picsLoaded = true;

      this.parent.affichage = affichage;

      this.parent["nb"+affichage] = nombre;

      this.parent.galeriev = this.firstChild.childNodes;

      this.parent.lon = this.parent.galeriev.length;

      for (var i = 0; i<this.parent.lon; i++) {

        var nom = this.parent.galeriev[i].attributes.nom;    

        this.parent.createEmptyMovieClip("bitmap_mc"+i, i+10);

        this.parent["bitmap_mc"+i].loadMovie(nom);

      }



      this.parent.onEnterFrame=function(){

        this.picsLoaded=true;

        for (var i = 0; i<this.lon; i++)

            if(this["bitmap_mc"+i].getBytesLoaded() !=this["bitmap_mc"+i].getBytesTotal()||this["bitmap_mc"+i].getBytesLoaded()==0)

            {this.picsLoaded=false;break;}

        if(this.picsLoaded==true){

            trace("ok");

            this.onEnterFrame=null;

            this.a = 0;  

            this.b = 0;  

            for (var i=0; i<this.lon; i++) {

              if (this.a == this["nb"+this.affichage]) {

                  this.a = 0;

                  this.b++;

              }

              this["bitmap_mc"+i]._x =(this.affichage=="Colonnes"? this.a : this.b)*(this.zoneTaille+this.zoneEspace);

              this["bitmap_mc"+i]._y =(this.affichage=="Colonnes"? this.b : this.a)*(this.zoneTaille+this.zoneEspace);

              this.a++;

            }

            for (var i = 0; i<this.lon; i++) {



              this.facteur=Math.max(this["bitmap_mc"+i]._width,this["bitmap_mc"+i]._height)/this.zoneTaille;  

              this["bitmap_mc"+i]._xscale = this["bitmap_mc"+i]._yscale /=this.facteur;  

            }

        }

      }

  }

  this.galerieXml.load(file);

}


Fichier(s) joint(s)
galeriexml.zip
galeriexmlproto.zip

Plier le cadre - Chargement d'une liste d'images (3)

:!: Avertissement:
Avant de lire ce tutorial, il est conseillé de lire les précédents (ceux portant sur la gestion d'une galerie d'images);
En particulier, les images ne doivent PAS etre enregistrées en mode progressif, flash n'accpte pas cela.
Ceci dit, attaquons les choses sérieuses:

Ce tutorial fournit 4 méthodes pour l'objet MovieClip, ce qu'on appelle 'prototype' par abus de langage, qui constituent du code polyvalent et réutilisable.
Il convient de placer ces scripts dans 4 fichiers texte séparés que vous appelerez depuis flash au moyen de la commande #include , de cette façon:

CODE
#include "monFichierTexte.txt"

Il ne faut pas mettre de point-virgule à la fin de la ligne !

Voici donc le code que vous aurez à taper dans les actions de votre animation, sous flash:



(ceci constitue tout le code à taper dans flash, sur les actions de la première image.)
img:coupe

C'est tout ce que vous aurez à savoir , et pour l'instant vous ne savez pas encore ce qu'est ce fameux 'loadGalerieFromXml'... il s'agit de l'une des méthodes fournies dans les fichiers texte; Cette méthode va lire un fichier xml où seront stockées les données, puis va construire une galerie de miniatures disposées en autant de lignes ou de colonnes que vous voudrez, puis va rendre cliquables ces miniatures, de façon à charger l'image en grand, ceci avec une barre de chargement....Ouf !!

img:coupe
img:remarque A signaler:
La construction de la galerie de miniatures ne change pas , il s'agit du meme prototype que précédemment, à part la ligne pour rendre cliquable les vignettes; Si vous n'avez pas saisi quelque chose, reportez-vous aux tutoriaux précédents, où le problème est plus développé.
img:coupe

img:as Une fois que la galerie d'images a été construite, on se retrouve avec plusieurs clips (les miniatures) que l'on veut rendre clicables.
On fait alors:
CODE
clip.onRelease=function(){ /* les actions */}


Comme on manque de place, on aimerait bien regrouper toutes les actions en une seule, donc on utilise une nouvelle fonction:
CODE
MovieClip.loadFile(image_ou_swf);

Cette fonction devra charger l'image ou l'animation, et aussi construire une barre de loading pour visualiser la progression du chargement de l'image.

img:coupe
img:as Il s'agit donc d'un problème de préchargement .
Maintenant, pour éviter de trop compliquer, prenons le problème à l'envers:
:arrow: Qui dit miniatures cliquables, dit ensuite images à charger.
:arrow: Qui dit images à charger dit barre de chargement.
:arrow: Qui dit barre de chargement dit... barre .

Il nous faut donc tout d'abord un script pour dessiner un rectangle:

fonction traceRectangle :
CODE
MovieClip.prototype.traceRectangle=function(xPos,yPos,width,height,fillColor,lineColor,alpha){

  this.beginFill(fillColor,alpha); /* debut du remplissage */

  this.lineStyle(1,lineColor,alpha); /* début du contour */

  this.moveTo(xPos,yPos);

  this.lineTo(xPos+width,yPos);

  this.lineTo(xPos+width,yPos+height);

  this.lineTo(xPos,yPos+height);

  this.lineTo(xPos,yPos); /* fin du contour */

  this.endFill(); /* fin du remplissage */

}

Ca va jusqu'ici ?
Vous retrouverez ce code dans le zip fourni, c'est dans 'traceRectangle.txt'.

img:as Maintenant que l'on sait tracer un rectangle dynamiquement, voyons le loading proprement dit:
Vous devriez à avoir l'habitude tellement il y a de posts et de tutoriaux dessus Vous avez quand meme ici une n-ième version d'un préchargement, qui utilise notre script précédent, pour dessiner la barre de chargement:

fonction setPreloader :
CODE
MovieClip.prototype.setPreloader=function(clip){

  /* options à modifier */

  infos={x:0,y:-15,width:100,height:10,fillColor:0xeeeeee,lineColor:0x000000,alpha:100,message:" loading..."};

  /* on décale le preloader */

  this._x=clip._x+infos.x;

  this._y=clip._y+infos.y

  /* on crée un clip pour la barre de loading */

  this.createEmptyMovieClip("barre",1);

  this.createTextField("message",2,infos.width,-5,100,20);

  this.message.text=infos.message; /* on écrit le message d'attente */

  this.onEnterFrame = function() {

      /* la boucle pour la progression du loading */

      this.barre.clear();

      /* on trace le rectangle dans la barre: */

      this.barre.traceRectangle(0,0,infos.width*this.barre.percent,infos.height,infos.fillColor,infos.lineColor,infos.alpha);

      /*  on calcule l'avancement du loading: */

      this.barre.percent=clip.getBytesLoaded()/clip.getBytesTotal();

      if (this.barre.percent>=0.99) { /* si c'est (presque) fini: */

        clip.onRelease=function(){ clip.removeMovieClip();}

        this.removeMovieClip(); /* on enleve la barre de chargement */

      }

  }

}


img:as Voyons comment fonctionne ce code, c'est un peu inhabituel.
Ce code transforme un clip quelquonque en un module de préchargement d'un clip cible, un 'preloader'.
Il y aura donc deux clips: celui où on charge l'image, et celui qui s'occupe de surveiller le chargement, le preloader.

Pour charger une image, il faudra donc quatre étapes:
:arrow: creer un clip vide pour l'image.
:arrow: creer un deuxième clip vide (pour le preloader).
:arrow: lancer le chargement de l'image dans le clip 1.
:arrow: dire au clip 2 de s'occuper du préchargement, ce qui se fera par:
CODE
clip2.setPreloader(clip1);


img:as On a décidé de regrouper ces quatres étapes dans une nouvelle fonction:


fonction loadFile :


img:as Quand on cliquera sur une vignette, l'action à executer est:
CODE
clipCible.loadFile(url_image);

C'est pratiquement la seule ligne qui change par rapport à l'ancien script, je remets la fonction ici pour ne pas vous forcer à faire de pénibles va-et-vient entre posts dans le forum:

:!: Finalement :
CODE
movieClip.prototype.loadGalerieFromXml = function(file,zoneTaille,zoneEspace,affichage,nombre,clipCible){

  this.galerieXml = new XML();

  racine=this;

  this.galerieXml.ignoreWhite = true;

  this.galerieXml.onLoad = function(){

      racine.zoneTaille = zoneTaille;

      racine.zoneEspace = zoneEspace;

      racine.picsLoaded = true;

      racine.affichage = affichage;

      racine["nb"+affichage] = nombre;

      racine.galeriev = this.firstChild.childNodes;

      racine.lon = racine.galeriev.length;

      for (var i = 0; i<racine.lon; i++) {

        var nom = racine.galeriev[i].attributes.small;    

        racine.createEmptyMovieClip("bitmap_mc"+i, i+10);

        racine["bitmap_mc"+i].loadMovie(nom);

      }

      racine.onEnterFrame=function(){

        this.picsLoaded=true;

        for (var i = 0; i<this.lon; i++){

            racine["bitmap_mc"+i]._visible=false;

            if(this["bitmap_mc"+i].getBytesLoaded() !=this["bitmap_mc"+i].getBytesTotal()||this["bitmap_mc"+i].getBytesLoaded()==0)

            {this.picsLoaded=false;break;}}

        if(this.picsLoaded==true){

            delete  this.onEnterFrame;

            this.a = 0;  

            this.b = 0;  

            for (var i=0; i<this.lon; i++) {

              racine["bitmap_mc"+i]._visible=true;

              if (this.a == this["nb"+this.affichage]) {

                  this.a = 0;

                  this.b++;

              }

              this["bitmap_mc"+i]._x =(this.affichage=="Colonnes"? this.a : this.b)*(this.zoneTaille+this.zoneEspace);

              this["bitmap_mc"+i]._y =(this.affichage=="Colonnes"? this.b : this.a)*(this.zoneTaille+this.zoneEspace);

              this.a++;

              this["bitmap_mc"+i].big=this.galeriev[i].attributes.big;

            }

            for (var i = 0; i<this.lon; i++) {



              this.facteur=Math.max(this["bitmap_mc"+i]._width,this["bitmap_mc"+i]._height)/this.zoneTaille;  

              this["bitmap_mc"+i]._xscale = this["bitmap_mc"+i]._yscale /=this.facteur;

              this["bitmap_mc"+i].onRelease= function(){ clipCible.loadFile(this.big); }

            }

        }

      }

  }

  this.galerieXml.load(file);

}




P.S : vous devez bien sur placer vos images dans le repertoire, et modifier le fichier XML en conséquence, et il faudra prévoir des miniatures de vos imges, la taille importe peu, pareil pour les proportions, ce qui compte, c'est que le poids de ces images soit vraiment faible, bien sur.



Fichier(s) joint(s)
galerie.zip
Plier le cadre - Tutorial Text Dynamique XML + Scroller Dynamique (FLASH MX)

img:coupe
Ce tutorial traite un exemple de gestion dynamique d'un champ de texte basé sur une analyse d'un fichier XML et permettant le changement immédiat du contenu en 2 langues différentes (français-anglais).
Le tester c'est l'adopter
De plus ce tutorial intègre un système de scroll dynamique du texte qui change des scrollbarres habituelles et permet de palier facilement à l'utilisation des composants MX encore pleins d'erreurs.

Vous trouverez dans le fichier zip : "scrolling text xml.zip" le fla, le swf et le fichier xml : "content.xml". Prenez le temps d'analyser le fichier xml pour voir comment il est réalisé.
img:remarque Je souligne le fait que pour gérer le codage Unicode UTF8 j'ai simplement "enregistrer sous" le fichier dans le bloc note de Win XP en n'oubliant pas de mettre le format du texte en UTF8... normalement il est possible de faire de même dans les versions antérieures de windows dans le wordpad... voir tutorial suivant :
http://www.flash-forum.net/viewtopic.php?p=15204#15204

Pour ce qui est du code vous le trouverez pour l'essentiel dans le clip principal situé à la racine de l'animation. Il se dispose sur 2 calques. Voir les informations et commentaires dans le .fla.

img:remarque Pour toutes questions ou commentaires veuillez utiliser la salle FLASH MX pour les questions traitant du scroll sur le champ dynamique et la salle FLASH DYNAMIQUE du forum pour les question traitant les problèmes liés au XML. Merci

Fichier(s) joint(s)
scrolling text xml.zip
scrolling final.swf
Plier le cadre - Chargement de texte et de propriétés + prototype

Le but de ce tutorial est d'apprendre à manipuler des fichiers xml (simples) avec flash, et plus précisement dans cet exemple de se servir du xml pour transmettre des textes et des informations sur leur mise en page.

Ainsi, le fichier xml servira à charger dans flash plusieurs blocs de texte, avec pour chaque bloc son identifiant, sa position et sa taille.
On peut imaginer plus de paramêtres, par exemple la couleur de fond, le style de bord, le wordwrapping, le redimmensionnement automatique, etc...

Voila donc notre fichier xml, il sert ici à charger deux champs de texte


CODE


<fields>

  <textField nom="monChamp1" contenu="he salut toi" x="50" y="50" largeur="80" hauteur="20"/>

  <textField nom="monChamp2" contenu="encore ?" x="100" y="100" largeur="80" hauteur="20"/>

</fields>



Un peu de vocabulaire:
:arrow: pour creer un nouvel objet xml avec pour identifiant 'objetXml', la syntaxe est:
objetXml = new XML
:arrow: le premier noeud ([b]firstChild
) est: <fields>
:arrow: les noeuds enfants ( childNodes ) sont:
<textField nom="monChamp1" ...> et
<textField nom="monChamp2" ...>
:arrow: Ici comme il n'y a qu'un niveau ce sont les enfants du tout premier noeud, ils sont donc accessibles de cette façon (stockés dans un tableau 'childNodes'):
objetXml.firstChild.childNodes[x] avec x qui vaut 0 ou 1, vu qu'il n'y a que deux éléments.
:arrow: on peut compter le nombre de noeuds enfants d'un objet xml en calculant la taille (nombre d'éléments) du tableau qui les contient:
ici il y a objetXml.firstChild.childNodes.length noeuds enfants (=2).


:arrow: pour préciser ce qu'il faut faire une fois le xml chargé, la syntaxe est:
objetXml. onLoad }

:arrow: pour charger un document xml dans un objet XML préalablement créé, la syntaxe est:
objetXml. load );



Code:

/* cet objet va contenir les informations
** que l'on va charger dynamiquement : */
myTextFields = new XML();
myTextFields.ignoreWhite = true;

/* ici on definit ce qu'on va faire une
** fois que le xml sera completement chargé */ myTextFields.onLoad = function(){
/* on fait une boucle sur tous les sous-noeuds
** (champs de texte) du document xml,
** le nombre de sous-noeuds correspond à la taille
** (nombre d'éléments) du tableau 'childNodes'
** contenant les sous-noeuds */
for(var i = 0; i<this.firstChild.childNodes.length ; i++)
{
/*on range les valeurs du xml dans des variables plus faciles d'utilisation*/
nom=this.firstChild.childNodes[i].attributes.nom;
contenu=this.firstChild.childNodes[i].attributes.contenu;
x=this.firstChild.childNodes[i].attributes.x;
y=this.firstChild.childNodes[i].attributes.y;
largeur=this.firstChild.childNodes[i].attributes.largeur;
hauteur=this.firstChild.childNodes[i].attributes.hauteur;

profondeur=10+i;

/* on créé le champ de texte, avec les caractéristiques prises dans le xml */

_root.createTextField(nom,profondeur,x,y,largeur,hauteur);

/* on lui attribue le texte venant également du xml */

_root[nom].text = contenu;

} /* fin du 'for' */

} /* fin du 'onLoad' */


/* maintenant que l'on a précisé les actions a accomplir
** après le chargement, on peut le charger : */

myTextFields.load("xmlFile.xml");


Voilà, c'est tout, vous pouvez tester, en mettant bien sûr dans le même repertoire un fichier "xmlFile.xml" qui contienne:

CODE
<fields><textField nom="monChamp1" contenu="he salut toi" x="50" y="50" largeur="80" hauteur="20"/><textField nom="monChamp2" contenu="encore ?" x="100" y="100" largeur="80" hauteur="20"/></fields>


-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
---------------- PROTOTYPE --------------------
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

Il est ensuite possible de transformer ces quelques lignes en une fonction que l'on peut rajouter au prototype de l'objet movieClip, de cette façon on aura une nouvelle méthode très facilement utilisable par tout le monde, sans avoir à taper le code.

On peut par exemple appeler cette fonction:
loadTextFieldsFromXml()

et voici le code (peu de changements, mais il faut bien connaitre la programmation orientée objet pour ne pas se perdre dans les multiples 'this' ):


CODE
movieClip.prototype.loadTextFieldsFromXml = function(url){



this.myTextFields = new XML();

this.myTextFields.ignoreWhite = true;

this.myTextFields.parent = this;

this.myTextFields.onLoad = function(){

for(var i = 0; i<this.firstChild.childNodes.length; i++)

{

nom=this.firstChild.childNodes[i].attributes.nom;

contenu=this.firstChild.childNodes[i].attributes.contenu;

x=this.firstChild.childNodes[i].attributes.x;

y=this.firstChild.childNodes[i].attributes.y;

largeur=this.firstChild.childNodes[i].attributes.largeur;

hauteur=this.firstChild.childNodes[i].attributes.hauteur;

profondeur=10+i;

this.parent.createTextField(nom,profondeur,x,y,largeur,hauteur);

this.parent[nom].text = contenu;

}

}

this.myTextFields.load(url);

}


Il suffit donc de mettre ce code n'importe où, par exemple de l'enregistrer dans un fichier texte ' loadTextFieldsFromXml.as '
puis pour tester:

CODE
#include "loadTextFieldsFromXml.as"



_root.createEmptyMovieClip("clip",1);

_root.clip.loadTextFieldsFromXml("xmlFile.xml");




C'est fini !
Je vous encourage à faire de nombreux tests, et à poser des questions sur d'eventuels points sensibles, le xml c'est le futur de flash (enfin plutôt déjà le présent, même ) !

 

Retour au choix des languages de programmation >> ici








[C++] [PHP] [XML] [javascript] [Actionscript] [HTML] [CSS] -- [logiciels] [Musiques] [Arrieres plans] [Emoticones] [Astuces MSN] [Videos insolites] -- [Intros flash] [Bannieres] [Boutons] [Menus] [Kits graphiques] [Tutoriaux]