Table des matières

Retour d'un niveau
Retour à l'accueil


Une fois que l'on a atteint un élément HTML, il est possible de se déplacer de façon un peu plus précise, avec toute une série de méthodes et de propriétés. Dans ce deuxième chapitre nous allons aborder la modification du document via le DOM.

Ce chapitre est basé sur comment :


a. La propriété parentNode

La propriété parentNode permet d'accéder à l'élément HTML parent d'un élément HTML.

<blockquote>
    <p id="myP">Ceci est un paragraphe !</p>
</blockquote>

On veut accéder à l'élément HTML <p> contenant l'id myP, et que pour une autre raison on veut ensuite accéder à l'élément HTML <blockquote>, qui est le parent de myP.
Il suffit d'accéder à myP puis à son parent, avec parentNode :

var paragraph = document.getElementById('myP'); // on accède à l'élément HTML <p> par son id
var blockquote = paragraph.parentNode; // ensuite on accède à son parent


b. Propriétés nodeType et nodeName

Ils servent respectivement à vérifier le type d'un nœud et le nom d'un nœud.
nodeType retourne un nombre, qui correspond à un type de nœud.
nodeName retourne simplement le nom de l'élément HTML, en majuscule.

Numéro Type de nœud
1Nœud élément HTML
2Nœud attribut
3Nœud texte
4Nœud pour passage CDATA (relatif au XML)
5Nœud pour référence d'entité
6Nœud pour entité
7Nœud pour instruction de traitement
8Nœud pour commentaire
9Nœud document
10Nœud type de document
11Nœud de fragment de document
12Nœud pour notation

nodeName retourne simplement le nom de l'élément HTML en majuscule.

Attention : Il est conseillé d'utiliser les méthodes toLowerCase() ou toUpperCase() pour forcer un fomat de casse et ainsi éviter de mauvaises surprises.

2.2 Lister et parcourir des nœuds enfants


a. Propriétés firstChild et lastChild

Comme leur nom le laisse présager, firstChild et lastChild servent respectivement à accéder au premier et au dernier enfant d'un nœud.

Si on désire récupérer que les enfants qui sont considérés comme des élément HTML (et donc éviter les nœuds #text par exemple), sachez qu'il existe les propriétés firstElementChild et lastElementChild. Malheureusement, ces deux propriétés ne sont supportées qu'à partir de la version 9 d'Internet Explorer.


b. Propriétés nodeValue et data

Comment faire pour récupérer le texte du premier enfant et ensuite le contenu dans un élément HTML <strong> ?
Soit on utilise la propriété nodeValue soit la propriété data comme ceci :

<blockquote>
    <p id="myP">Ceci est un paragraphe !</p>
</blockquote>
var paragraph = document.getElementById('myP'); // on accède à l'élément HTML <p> par son id
var first = paragraph.firstChild; // first récupère le premier noeud
var last  = paragraph.lastChild;  // last récupère le dernier noeud
 
alert(first.nodeValue); // on lui applique la propriété nodeValue
alert(last.firstChild.data); 

Explications :
first contient le premier nœud, un nœud textuel. Il suffit de lui appliquer la propriété nodeValue ou data pour récupérer son contenu ; pas de difficulté ici.

En revanche, il y a une petite différence avec notre élément HTML <strong> : vu que les propriétés nodeValue et data ne s'appliquent que sur des nœuds textuels, il nous faut d'abord accéder au nœud textuel que contient notre élément HTML, c'est-à-dire son nœud enfant.
Pour cela, on utilise firstChild (et non pas firstElementChild), et ensuite on récupère le contenu avec nodeValue ou data.

c. Propriété childNodes

La propriété childNodes retourne un tableau contenant la liste des enfants d'un élément HTML.
On utilise bien sure une boucle pour afficher le tableau.

d. Propriétés nextSibling et previousSibling

nextSibling et previousSibling sont deux propriétés qui permettent d'accéder respectivement au nœud suivant et au nœud précédent.

Comme pour firstChild et lastChild, sachez qu'il existe les propriétés nextElementSibling et previousElementSibling qui permettent, elles aussi, de ne récupérer que les élément HTML. Ces deux propriétés ont les mêmes problèmes de compatibilité que firstElementChild et lastElementChild.


e. Attention aux nœuds vides (solutions)

En considérant le code HTML suivant, on peut penser que l'élément HTML ne contient que trois enfants <p> :

<div> // attention ceci est un espace entre les élément HTML !!
    <p>Paragraphe 1</p> // attention ceci est un espace entre les élément HTML !!
    <p>Paragraphe 2</p> // attention ceci est un espace entre les élément HTML !!
    <p>Paragraphe 3</p> // attention ceci est un espace entre les élément HTML !!
</div>

Le code ci dessus n'a rien à voir avec ce code ci :

<div><p>Paragraphe 1</p><p>Paragraphe 2</p><p>Paragraphe 3</p></div>

Heureusement, il existe une solution à ce problème !
Les attributs firstElementChild, lastElementChild, nextElementSibling et previousElementSibling ne retournent que des élément HTML et permettent donc d'ignorer les nœuds textuels.
Ils s'utilisent exactement de la même manière que les attributs de base (firstChild, lastChild, etc.). Attention, ces attributs ne sont pas supportés par les versions d'Internet Explorer antérieures à la 9.


2.3 Créer et insérer des élément HTML


Avec le DOM :

  1. On crée l'élément HTML
  2. On lui affecte des attributs
  3. On l'insère dans le document, et ce n'est qu'à ce moment-là qu'il sera « ajouté ».


a. Création de l'élément HTML

La création d'un élément HTML se fait avec la méthode createElement(), un sous-objet de l'objet racine, c'est-à-dire document dans la majorité des cas :

var newLink = document.createElement('a');

Chemin complet: window.document.createElement()

L'élément HTML <a> est créé il n'est pas encore inséré dans le document, donc il n'est pas visible. Mais on peut travailler dessus en lui ajoutant des attributs ou des événements.

Si vous travaillez dans une page Web, l'élément HTML racine sera toujours document, sauf dans le cas des frames. La création d'élément HTML au sein de fichiers XML sera abordée plus tard.


b. Affectation des attributs

on définit les attributs, soit avec setAttribute(), soit directement avec les propriétés adéquates.

newLink.id    = 'sdz_link';
newLink.href  = 'http://www.siteduzero.com';
newLink.title = 'Découvrez le Site du Zéro !';
newLink.setAttribute('tabindex', '10');


c. Insertion de l'élément HTML

On utilise la méthode appendChild() pour insérer l'élément HTML. Append child signifie « ajouter un enfant », ce qui signifie qu'il nous faut connaître l'élément HTML auquel on va ajouter l'élément HTML créé.
Considérons donc le code suivant :

<body>
    <div>
        <p id="myP">Un peu de texte <a>et un lien</a></p>
    </div>
</body>

On va ajouter notre élément HTML <a> dans l'élément HTML <p> portant l'ID myP.
Pour ce faire, il suffit de récupérer cet élément HTML, et d'ajouter notre élément HTML <a> via appendChild() :

document.getElementById('myP').appendChild(newLink);


d. Ajouter des nœuds textuels

L'élément HTML a été inséré, seulement il manque quelque chose : le contenu textuel !
La méthode createTextNode() sert à créer un nœud textuel (de type #text) qu'il nous suffira d'ajouter à notre élément HTML fraîchement inséré, comme ceci :

var newLinkText = document.createTextNode("Le Site du Zéro"); // création du noeud avec createTextNode()
newLink.appendChild(newLinkText); 

L'insertion se fait ici aussi avec appendChild(), sur l'élément HTML newLink.
Afin d'y voir plus clair, résumons le code :

<body>
    <div>
        <p id="myP">Un peu de texte <a>et un lien</a></p>
    </div>
    <script>
        var newLink = document.createElement('a');
        newLink.id    = 'sdz_link';
        newLink.href  = 'http://www.siteduzero.com';
        newLink.title = 'Découvrez le Site du Zéro !';
        newLink.setAttribute('tabindex', '10');
 
        document.getElementById('myP').appendChild(newLink);
        var newLinkText = document.createTextNode("Le Site du Zéro");
        newLink.appendChild(newLinkText);
    </script>
</body>


2.4 Notions sur les références


En JavaScript et comme dans beaucoup de langages, le contenu des variables est « passé par valeur ». Cela veut donc dire que si une variable nick1 contient le prénom « Clarisse » et qu'on affecte cette valeur à une autre variable, la valeur est copiée dans la nouvelle.
On obtient alors deux variables distinctes, contenant la même valeur :

var nick1 = 'Clarisse';
var nick2 = nick1;


a. Les références

Outre le « passage par valeur », le JavaScript possède un « passage par référence ». En fait, quand une variable est créée, sa valeur est mise en mémoire par l'ordinateur. Pour pouvoir retrouver cette valeur, elle est associée à une adresse que seul l'ordinateur connaît et manipule (on ne s'en occupe pas).

Quand on passe une valeur par référence, on transmet l'adresse de la valeur, ce qui va permettre d'avoir deux variables qui pointent sur une même valeur ! Malheureusement, un exemple théorique d'un passage par référence n'est pas vraiment envisageable à ce stade du tutoriel, il faudra attendre d'aborder le chapitre sur la création d'objets. Cela dit, quand on manipule une page Web avec le DOM, on est confronté à des références, tout comme dans le chapitre suivant sur les événements.

b. Les références avec le DOM

Schématiser le concept de référence avec le DOM est assez simple : deux variables peuvent accéder au même élément HTML.
Regardez cet exemple :

var newLink     = document.createElement('a');
var newLinkText = document.createTextNode('Le Site du Zéro');
 
newLink.id  = 'sdz_link';
newLink.href = 'http://www.siteduzero.com';
newLink.appendChild(newLinkText);
 
document.getElementById('myP').appendChild(newLink);
 
// On récupère, via son ID, l'élément HTML fraîchement inséré
var sdzLink = document.getElementById('sdz_link');
sdzLink.href = 'http://www.siteduzero.com/forum.html';
 
// newLink.href affiche bien la nouvelle URL :
alert(newLink.href);

La variable newLink contient en réalité une référence vers l'élément HTML <a> qui a été créé. La variable newLink ne contient pas l'élément HTML, il contient une adresse qui pointe vers ce fameux élément HTMH <a>. Une fois que l'élément HTML est inséré dans la page, on peut y accéder de nombreuses autres façons, comme avec getElementById(). Quand on accède à un élément HTML via getElementById(), on le fait aussi au moyen d'une référence.

2.5 Cloner, remplacer, supprimer


a. Cloner un élément HTML

Pour cloner un élément HTML, rien de plus simple : cloneNode().
Cette méthode requiert un paramètre booléen ( true ou false):
- si on désire cloner le nœud avec ses enfants et ses différents attributs on utilisera true.
- si on désire cloner le nœud sans ses enfants et ses différents attributs on utilisera false.

Exemple : on crée un élément HTML <hr> et on veut un deuxième, donc on va cloner le premier.

// On va cloner un élément HTML créé :
var hr1 = document.createElement('hr');
var hr2 = hr1.cloneNode(false); // Il n'a pas d'enfant...
 
// Ici, on clone un élément HTML existant :
var paragraph1 = document.getElementById('myP'); // on attrape l'élément par son id avec ses enfants
var paragraph2 = paragraph1.cloneNode(true); // on le clone
 
// Et attention, l'élément HTML est cloné, mais pas « inséré » tant que l'on n'a pas appelé appendChild() :
paragraph1.parentNode.appendChild(paragraph2); // on l'insère

Test du code

Une chose très importante à retenir, bien qu'elle ne vous concernera qu'au chapitre suivant, est que la méthode cloneNode() ne copie malheureusement pas les événements associés et créés avec le DOM (avec addEventListener()), même avec un paramètre à true. Pensez bien à cela !


b. Remplacer un élément HTML par un autre

Pour remplacer un élément HTML par un autre, rien de plus simple, il y a replaceChild().
Cette méthode accepte deux paramètres : le premier est le nouvel élément HTML, et le deuxième est l'élément HTML à remplacer.
Tout comme cloneNode(), cette méthode s'utilise sur tous les types de nœuds (élément HTML, nœuds textuels, etc.).

Dans l'exemple suivant, le contenu textuel (pour rappel, il s'agit du premier enfant de l'élément HTML <a>) du lien va être remplacé par un autre. La méthode replaceChild() est exécutée sur l'élément HTML <a>, c'est-à-dire le nœud parent du nœud à remplacer.

<body>
    <div>
        <p id="myP">Un peu de texte <a>et un lien</a></p>
    </div>
    <script>
        var link = document.querySelector('a');
        var newLabel = document.createTextNode('et un hyperlien');
        link.replaceChild(newLabel, link.firstChild);
    </script>
</body>


c. Supprimer un élément HTML

Pour insérer un élément HTML, on utilise appendChild(), et pour en supprimer un, on utilise removeChild().
Cette méthode prend en paramètre le nœud enfant à retirer.
Si on se calque sur le code HTML de l'exemple précédent, le script ressemble à ceci :

var link = document.querySelector('a');
 
link.parentNode.removeChild(link);

Il n'y a pas besoin de récupérer myP (l'élément HTML parent) avec getElementById(), autant le faire directement avec la propriété parentNode.
À noter que la méthode removeChild() retourne l'élément HTML supprimé, ce qui veut dire qu'il est parfaitement possible de supprimer un élément HTML pour ensuite le réintégrer où on le souhaite dans le DOM

var link = document.querySelector('a');
var oldLink = link.parentNode.removeChild(link); // On supprime l'élément HTML et on le garde en stock
document.body.appendChild(oldLink); // On réintègre ensuite l'élément HTML supprimé où on veut et quand on veut


2.6 Autres actions


a. Vérifier la présence d'élément HTML enfants

Rien de plus facile pour vérifier la présence d'élément HTML enfants : hasChildNodes().
Il suffit d'utiliser cette méthode sur l'élément HTML de votre choix ; si cet élément HTML possède au moins un enfant, la méthode renverra true :

<div>
      <p id="myP">Un peu de texte <a>et un lien</a></p>
</div>
<script>
    var paragraph = document.querySelector('p');
 
    alert(paragraph.hasChildNodes()); // Affiche true
</script>
<code>
\\
 
=== b. Insérer à la bonne place : insertBefore() ===
La méthode **<fc #ff00ff>insertBefore()</fc>** permet d'insérer un élément HTML avant un autre. \\
Elle reçoit __deux paramètres__ : le __premier__ est l'élément HTML à insérer, tandis que le __deuxième__ est l'élément HTML avant lequel l'élément HTML va être inséré. 
**Exemple : **\\
 
<code java>
<p id="myP">Un peu de texte <a>et un lien</a></p>
 
<script>
    var paragraph    = document.querySelector('p');
    var emphasis     = document.createElement('em'),
        emphasisText = document.createTextNode(' en emphase légère ');	  
        emphasis.appendChild(emphasisText);
        paragraph.insertBefore(emphasis, paragraph.lastChild);
</script>

Comme pour appendChild(), cette méthode s'applique sur l'élément HTML parent.


c. Une bonne astuce : insertAfter()

Le JavaScript met à disposition insertBefore(), mais pas insertAfter(). C'est dommage car, bien que l'on puisse s'en passer, cela est parfois assez utile. Qu'à cela ne tienne, créons donc une telle fonction.

Malheureusement, il ne nous est pas possible, à ce stade-ci du cours, de créer une méthode, qui s'appliquerait comme ceci :

element.insertAfter(newElement, afterElement)
 
Non, il va falloir nous contenter d'une « simple » fonction :
insertAfter(newElement, afterElement)


Algorithme
Pour insérer après un élément HTML, on va d'abord récupérer l'élément HTML parent.
C'est logique, puisque l'insertion de l'élément HTML va se faire soit via appendChild(), soit via insertBefore() :
si on veut ajouter notre élément HTML après le dernier enfant, c'est simple, il suffit d'appliquer appendChild().
Par contre, si l'élément HTML après lequel on veut insérer notre élément HTML n'est pas le dernier, on va utiliser insertBefore() en ciblant l'enfant suivant, avec la propriété nextSibling :

function insertAfter(newElement, afterElement) {
 
    var parent = afterElement.parentNode;
    if (parent.lastChild === afterElement) { // Si le dernier élément HTML est le même que l'élément HTML après lequel on veut insérer, il suffit de faire appendChild()
 
        parent.appendChild(newElement);
 
    } else { // Dans le cas contraire, on fait un insertBefore() sur l'élément HTML suivant
 
        parent.insertBefore(newElement, afterElement.nextSibling);
    }
}



Retour d'un niveau
Retour à l'accueil