Aller au menu - Aller au contenu

Icône Le DOM

Mise à jour : 22/08/2008
454 visites depuis 7 jours , dont 108 sur ce chapitre , classé 235/777
Nous allons ici mettre en pratique tout ce que nous avons vu sur le javascript, sur les noeuds et sur le parcours de fichiers XHTML.

Pour cela, nous allons utiliser ce que l'on appelle le Document Object Model, et vous n'avez plus qu'à apprendre comment on l'utilise en Javascript, car vous connaissez maintenant ce que c'est. Eh oui ! Ce sont les arbres que l'on a vus tout à l'heure. ;)

Il existe deux méthodes pour modifier dynamiquement un document XHTML, mais je ne vous parlerai volontairement que de l'une d'entre elle, qui respecte les standards du web. Je ne ferai que citer l'autre, mais je déconseille vivement de l'utiliser.

Alors on est partis... Bientôt les pages dynamiques seront à vous ^^ ;) .
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Savoir se placer sur un document XHTML

Reprenons donc notre cours. Avant toute chose, je dois avouer que je vous ai caché une information quand je vous ai fait mes 2 schémas. Il y a un node au-dessus de html qui nous donne accès à tous les autres. C'est le node document. Il va falloir passer par lui pour accéder à tous les autres dans notre page.


Je vous avais parlé de trois méthodes pour se positionner dans un document. La méthode pour se positionner grâce à un id s'utilise comme suit :

Code : JavaScript
1
var node = document.getElementById("mon_id");


Explication : nous créons une variable que l'on place à l'endroit voulu grâce à la méthode getElementById qui prend en argument l'id. C'est pas plus difficile que ça. Comme je vous l'ai dit dans le chapitre, plein de méthodes sont associées à nos variables. Dans le cas d'un node, on a désormais accès à des méthodes qui vont nous permettre de parcourir les noeuds d'un document, ce qui correspond à la deuxième méthode dont je vous ai parlé.


Il faut respecter l'orthographe et les majuscules / minuscules dans le nom des méthodes. Sinon, ça ne marchera pas, tout simplement.


Voici ces méthodes :

Code : JavaScript
1
2
3
4
5
6
7
var node = document.getElementById("mon_id");
var parent = node.parentNode; //place la variable parent sur le noeud parent de node
var childList = node.childNodes; //récupère tous les enfants de node dans un tableau childNodesList
var child1 = node.firstChild; //récupère le premier enfant de node
var childx = node.lastChild; //récupère le dernier enfant de node
var frerePrec = node.previousSibling; //récupère le frère précédent de node (l'enfant précédent du parent de node)
var frereSuiv = node.nextSibling; //récupère le frère suivant


Il existe aussi une troisième méthode, qui permet de récupérer toutes les balises identiques à partir de document, ou d'un node inférieur (dans l'arbre). Vous pouvez utiliser cette méthode pour compter le nombre de balises qu'il y a sur votre page, par exemple, ou pour naviguer dans votre document si vous connaissez bien sa structure.

Code : JavaScript
1
2
3
4
5
var titreList = document.getElementsByTagName("h1");
//quelques méthodes associées à une liste de node
titreList.length;  // nombre de h1 dans le document
titreList.item(2); // accession à la 3ème balise h1 rencontrée
titreList[2];      // accession à la 3ème balise h1 rencontrée


Dans tous les cas, quand le node voulu n'existe pas, la méthode utilisée renvoie undefined. Vous avez donc désormais la possibilité de vous promener à volonté dans votre fichier XHTML.

Ajouter du code XHTML dans vos pages

Déjà, on va commencer par le sujet qui fâche. Il existe bien une méthode facile et rapide pour changer le contenu d'une balise que l'on a sélectionnée avec ce que je vais vous apprendre. Mais je ne veux pas, et ne vais pas l'utiliser dans ce cours, parce que c'est une méthode propriétaire IE (Internet Explorer), et qu'elle ne respecte pas les standards du web.

Cette méthode s'appelle innerHTML, et s'utilise comme suit : node.innerHTML = "nouveau contenu texte ou/et html"

Cette méthode peut quand même vous être utile pour déboguer votre programme, car elle vous renvoie le contenu d'une balise brute avec les balises et le reste.


Maintenant, nous allons voir le mécanisme propre pour ajouter des balises et du texte. La première chose à bien comprendre est que le modèle d'une page XHTML est tellement bien fait, que si l'on veut ajouter des balises proprement, il va falloir tout construire brique par brique.

Le principe est assez simple. D'abord, on doit récupérer toutes les briques ; ensuite on fait des assemblages ; et enfin on accroche le tout là où on veut.

Donc, pour récupérer nos briques, qui sont en fait des noeuds, il y a 3 méthodes à connaître :

Code : JavaScript
1
2
3
4
5
var titre = document.createElement("h1"); //Ici on crée une balise de type h1. Si on voyait ce qu'on créait, on aurait : <h1></h1>
titre.setAttribute("class","Titre_rouge"); //Ici on ajoute un attribut à notre balise
var lien = document.createElement("a");
lien.setAttribute("href","toto.html");
var texte = document.createTextNode("Titraille"); //Ici on a créé un texte


Il semblerait que la fonction setAttribute avec l'attribut class ne fonctionne pas sous IE7 (merci Microsoft :-° ). A la place de titre.setAttribute("class","Titre_rouge");, il faut utiliser :
Code : JavaScript
1
2
if(document.all) titre.className='Titre_rouge';
else titre.setAttribute("class","Titre_rouge");

La condition sera expliquée dans la partie suivante. Elle sert à utiliser un code différent selon que l'on est sur IE ou Firefox.

(Merci à Defkarz pour l'avoir notifié.)


À ce niveau de la préparation, rien n'est assemblé, mais surtout rien n'est affiché. Tout est encore virtuel. Il va maintenant falloir assembler nos briques, et surtout mettre le tout dans notre page XHTML. Voilà maintenant les méthodes à utiliser pour assembler des objets :

Code : JavaScript
1
2
lien.appendChild(texte); //Là, on accroche en dernier enfant (donc premier, puisque c'est le seul) le text node créé juste au-dessus. On aura donc un lien de ce type : <lien url="toto.html">Titraille</lien>
titre.appendChild(lien); //là, on accroche notre lien à la balise h1


On a donc un groupe de balises virtuelles sous cette forme prêtes à être mises dans le XHTML :

Code : HTML
1
<h1 class="titre_rouge"><a href="toto.html">Titraille</a></h1>


Il existe également deux autres méthodes pour accrocher une balise à une autre, qui sont :

Code : JavaScript
1
2
parent.insertBefore(child, referenceChild); //Ici, on accroche notre balise child à la balise parent, et dans l'ordre, elle se retrouve juste avant la balise referenceChild
parent.replaceChild(newChild, oldChild); //Ici, on remplace la balise enfant de parent oldChild par la balise newChild


On peut donc désormais construire un tableau (par exemple), toujours virtuel, prêt à être inséré dans la page. Pour cela, il faudra être assez méthodique, et créer tous les node texte qu'on accrochera chacun à un td. Puis il faudra accrocher tout les td à un tr pour chaque ligne, et il faudra enfin accrocher tous les tr à table. Sauf si vous voulez un tableau plus complexe. Là, ça sera un peu plus complexe ici aussi.

Vous savez maintenant construire des branches virtuelles, qu'il ne vous reste plus qu'à savoir accrocher à vos balises dans votre fichier XHTML.

Pour ça, rien de plus simple. Il vous suffit d'abord de sélectionner un élément de votre page, à l'aide d'une des 3 méthodes que je vous ai montrées (getElementById, getElementsByTagName, méthode relationnelle). Ensuite, vous utilisez une des 3 méthodes que l'on vient de voir pour accrocher un élément, et votre code passe enfin de virtuel à visible.

Ajouter un événement dynamiquement

En effet : ça peut vous arriver d'avoir besoin d'ajouter des événements sur un élément que vous avez fait apparaître sur la page.

Rien de plus facile. Suffit d'utiliser setAttribute("onEvenement"...


Eh bien sur le papier on devrait pouvoir le faire comme ça. Mais dans la réalité, il est bien plus propre, portable et sûr d'utiliser une méthode appelée addEventListener, ou attachEvent pour IE.

Comment comptes-tu faire quelque chose de compatible IE et FF (Firefox) s'il y a deux fonctions différentes ?

Je vous montrerai la technique plus tard, mais sachez qu'il y a moyen. Donc notre EventListener, c'est en fait une sorte de surveillant affecté à une balise, et qui va réagir si jamais l'événement se produit. Je ne compte pas rentrer dans les détails de cette fonction, je veux juste vous montrer comment elle marche, et comment nous allons pouvoir l'utiliser.

Tout d'abord, nous avons besoin d'un node :

Code : JavaScript
1
var node = document.createElement("input");


Bien. Ensuite, nous allons devoir appeler la fonction addEventListener comme suit :

Code : JavaScript
1
node.addEventListener("change",fonction,true)


Ici, une explication s'impose. D'abord, le premier paramètre est l'événement sans le "on" habituel. Ensuite, nous avons le nom (et le nom seulement... pas de ()) de la fonction appelée si l'événement se produit. Enfin, il y a un paramètre qui vaut true ou false. Vos scripts peuvent réagir de différentes manières selon que vous utilisez l'un ou l'autre, mais je ne veux pas vous détailler ce qu'il se passe. A la fin de ce cours, je vous donnerai des liens intéressants pour approfondir vos connaissances.

Je vous avais donc dit que nous allions pouvoir différencier les deux navigateurs de type Netscape et Internet Explorer. Chose promise, chose due, voilà la solution :

Code : JavaScript
1
2
3
4
5
6
if(document.all){
//instructions pour ie
}
else{
//instructions pour netscape et autres
}


Donc, nous allons pouvoir faire :

Code : JavaScript
1
2
if(document.all) node.attachEvent("onchange",fonction);
else node.addEventListener("change",fonction,true);


Notez bien les quelques différences entre les deux fonctions. Celle de IE prend le "on" avant le nom de l'événement, et il n'y a pas de paramètre valant true ou false.

Bien. Maintenant que vous savez tout ça, il faut que vous appreniez comment récupérer des informations qui peuvent être intéressantes pour savoir d'où vient l'événement, comment il s'est produit, ce qui a changé...

Donc : vous avez créé votre fonction dont vous avez mis le nom dans l'event listener. Voilà la forme qu'elle va devoir avoir :

Code : JavaScript
1
2
function maFonction(event){
}


Comme vous pouvez le voir, déjà elle reçoit un paramètre qui est un objet associé à notre événement. Il existe pas mal de méthodes à utiliser sur cet objet qui vont nous permettre de récupérer nos informations.

Les méthodes diffèrent pas mal de Firefox à Internet Explorer. Il va donc falloir une nouvelle fois mettre un if...else.


La principale méthode dont nous aurons besoin est target pour Firefox, et srcElement pour Internet Explorer. Ces méthodes nous renvoient le node sur lequel s'est produit l'événement. Pour pouvoir récupérer le noeud, quelque soit le navigateur, utilisez cette ligne de code :

Code : JavaScript
1
var node_source = (document.all)?event.srcElement:event.target;


Je ne rentrerai pas dans les détails d'une condition ternaire, mais sachez juste que notre node_source vaut maintenant le node où s'est produit l'événement.

Voici quelques idées de ce qu'on peut récupérer avec l'élement event : les coordonnées de la souris, la touche ou le bouton de souris pressé, ainsi que des méthodes concernant le drag and drop d'objet sur votre page.

Voilà : nous savons donc insérer des événements dynamiquement sur notre page. On va maintenant passer à quelques exercices.
Chapitre précédent Sommaire Chapitre suivant

Partager

19 commentaires pour "Le DOM"
Note moyenne : 3.26 / 4 (46 votes)
Pseudo Commentaire
Hors ligne Fedaykin # Posté le 18/05/2009 à 11:18:46
Avatar

Bonjour,

La balise br étant générique (sans id notamment) tu dois pouvoir faire quelque chose du genre :

Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var br = document.createElement('br');
P.appendChild(textepara1);
P.appendChild(br);
P.appendChild(textepara2);
P.appendChild(br);
P.appendChild(textepara3);
P.appendChild(br);
P.appendChild(textepara4);
P.appendChild(br);
P.appendChild(textepara5);
P.appendChild(br);
P.appendChild(textepara6);
P.appendChild(br);
P.appendChild(textepara7);
P.appendChild(br);


Ce code est à tester, mais je pense qu'il devrait marcher. Si il ne fais que déplacer un br dans le DOM par contre il faudrait remplacer la ligne P.appendChild('br') par :

Code : JavaScript
1
P.appendChild(br.cloneNode(false));

Image utilisateur
Such is the situation in our Fallen Galaxy
 
Hors ligne yohann27 # Posté le 24/05/2009 à 13:10:02
Fan de Blender

je ne comprends pas grand chose
Secret (cliquez pour afficher)
pas grands chose = rien
Hors ligne slifer # Posté le 04/11/2010 à 00:47:33

Études : Faculté des Sciences Ain Chock Casblanca

je donnerai 15/20, ce n'est pas très claire pour un débutant, par contre c'est un atout pour ceux qui s'y connaissent déjà en JS.

au faite pour la méthode innerHTML elle est compatible FF même si elle est conçu par IE, j'ai même trouvé sur un site qu'elle est favorable à addAdjacentHTML, je cherchais une alternative a cette dernière puisqu'elle ne marche pas sur tout les navigateur alors je suis tombé sur innerHTML.

PS: sympa la faute de frappe, surtout pour ceux qui font copier/coller lol.
PS: un grand merci
Hors ligne slifer # Posté le 28/11/2010 à 13:09:18

Études : Faculté des Sciences Ain Chock Casblanca

Bonjour, je tiens à remercier SdZ pour ses nombreux tuto, pour moi c'est devenu mon cours principale (plus simple que celui du prof ^^), bref voila mon problème :
je fais un programme qui insère des lignes de formulaire en cliquant sur un boutton(Nouveau), la

ligne contien :
zone de texte associé à un calendrier pour saisir les date:
deux liste déroulante
une zone de texte qui change de "value" quand les listes déroulantes changent.

l'insertion se passe à merveille, mais puisque j'ai utilisé innerHTML, il y a une différence entre IE et FF, sur IE ça marche quand j'insère une ligne je la remplie et je clique sur mon Bouton pour insérer une deuxième ligne, j'ai la nouvelle et c'est reparti pour la remplir, je peux à tout moment revenir sur les lignes déjà insérée et les modifier, le malheur :waw: c'est avec FireFox, la première ligne s'insère normalement, je la rempli, mais une fois je clique sur le bouton d'insertion pour insérer une nouvelle ligne, il est bien insérée mais toutes les ligne précédente sont réinitialisée, ça veut dire que tout ce que j'ai saisi disparait (les liste déroulante reviennent sur l'option selected parDefaut, les zone de texte sont vide) et le calendrier n'apparait plus quand je clique sur la zone de texte de la date (onfocus engendre l'apparition du calendrier), bref sur FF ça ne marche que sur la dernière ligne insère, les précédentes sont toutes réinitialisées.
Après lecture du tuto j'ai essayé de faire l'insertion par DOM, par contre je rencontre un gros problème :colere: , la majorité de mes fonctions qui sont associées à des évènement des objets insèré contient des paramètred alors que dans ce tuto j'ai que addEventListner(Event,fonction,true) ou addAttachment(onEvent,fonction) SANS PARAMÈTRE, après tout ce long discours ma question est :
Comment associer des fonction qui contient des paramètre à des évènement inséré? :-°

P.S : si besoin du code je peux le copier mais je vous préviens il est troop long (surtout le calendrier)
Hors ligne Fedaykin # Posté le 29/11/2010 à 14:22:47
Avatar

Bonjour Slifer,

Je ne sais pas trop quel type d'argument tu souhaiterais passé. Un des solution à ton problème serait de recourir aux closures :

Code : JavaScript
1
2
3
4
5
var myValue = 'blabla';

function(event){
  alert(myValue);
}


Pour résumer le principe, une fonction à accès au contexte dans lequel elle a été défini. Donc les variables définies juste avant la déclaration d'une fonction lui sont accesible (si aucune variable locale n'a le même nom bien sur).

Fedaykin

Image utilisateur
Such is the situation in our Fallen Galaxy
 

Voir tous les commentaires