Le DOM nous permet de faire nâimporte quoi avec les Ă©lĂ©ments et leur contenu, mais nous devons dâabord atteindre lâobjet DOM correspondant.
Toutes les opĂ©rations sur le DOM commencent par lâobjet document. Câest le âpoint dâentrĂ©eâ principal du DOM. De lĂ , nous pouvons accĂ©der Ă nâimporte quel nĆud.
Voici une image des liens qui permettent de voyager entre les nĆuds DOM :
Discutons-en plus en détail.
En haut : documentElement et body
Les nĆuds supĂ©rieurs de lâarbre sont disponibles directement en tant que propriĂ©tĂ©s de document :
<html>=document.documentElement- Le nĆud de document le plus haut est
document.documentElement. Câest le noeud DOM de la balise<html>. <body>=document.body- Un autre nĆud DOM largement utilisĂ© est lâĂ©lĂ©ment
<body>âdocument.body. <head>=document.head- La balise
<head>est disponible en tant quedocument.head.
document.body peut ĂȘtre nullUn script ne peut pas accĂ©der Ă un Ă©lĂ©ment qui nâexiste pas au moment de lâexĂ©cution.
En particulier, si un script se trouve dans <head>, alors document.body nâest pas disponible, car le navigateur ne lâa pas encore lu.
Ainsi, dans lâexemple ci-dessous, la premiĂšre alert affiche null :
<html>
<head>
<script>
alert( "From HEAD: " + document.body ); // null, il n'y a pas encore de <body>
</script>
</head>
<body>
<script>
alert( "From BODY: " + document.body ); // HTMLBodyElement maintenant existe
</script>
</body>
</html>
null signifie "nâexiste pas "Dans le DOM, la valeur null signifie ânâexiste pasâ ou âpas ce genre de nĆudâ.
Enfants : childNodes, firstChild, lastChild
Nous utiliserons désormais deux termes :
- Noeuds enfants (ou enfants) â Ă©lĂ©ments qui sont des enfants directs. En dâautres termes, ils sont imbriquĂ©s dans celui donnĂ©. Par exemple,
<head>et<body>sont des enfants de lâĂ©lĂ©ment<html>. - Descendants â tous les Ă©lĂ©ments imbriquĂ©s dans lâĂ©lĂ©ment donnĂ©, y compris les enfants, leurs enfants, etc.
Par exemple, ici <body> a des enfants <div> et <ul> (et quelques nĆuds texte vides) :
<html>
<body>
<div>Begin</div>
<ul>
<li>
<b>Information</b>
</li>
</ul>
</body>
</html>
⊠Et les descendants de <body> ne sont pas seulement des enfants directs <div>, <ul> mais aussi des Ă©lĂ©ments plus profondĂ©ment imbriquĂ©s, tels que <li> (un enfant de <ul> ) et <b> (un enfant de <li>) â le sous-arbre entier.
La collection childNodes rĂ©pertorie tous les nĆuds enfants, y compris les nĆuds texte.
Lâexemple ci-dessous montre des enfants de document.body :
<html>
<body>
<div>Begin</div>
<ul>
<li>Information</li>
</ul>
<div>End</div>
<script>
for (let i = 0; i < document.body.childNodes.length; i++) {
alert( document.body.childNodes[i] ); // Text, DIV, Text, UL, ..., SCRIPT
}
</script>
...more stuff...
</body>
</html>
Veuillez noter un dĂ©tail intĂ©ressant ici. Si nous exĂ©cutons lâexemple ci-dessus, le dernier Ă©lĂ©ment affichĂ© est <script>. En fait, le document contient plus de choses en dessous, mais au moment de lâexĂ©cution du script, le navigateur ne lâa pas encore lu, donc le script ne le voit pas.
Les propriétés firstChild et lastChild donnent un accÚs rapide aux premier et dernier enfants.
Ce ne sont que des raccourcis. Sâil existe des nĆuds enfants, ce qui suit est toujours vrai :
elem.childNodes[0] === elem.firstChild
elem.childNodes[elem.childNodes.length - 1] === elem.lastChild
Il y a aussi une fonction spĂ©ciale elem.hasChildNodes() pour vĂ©rifier sâil y a des nĆuds enfants.
Collections DOM
Comme nous pouvons le voir, childNodes ressemble Ă un tableau. Mais en rĂ©alitĂ© ce nâest pas un tableau, mais plutĂŽt une * collection * â un objet itĂ©rable spĂ©cial semblable Ă un tableau.
Il y a deux conséquences importantes :
- Nous pouvons utiliser
for..ofpour itérer dessus :
for (let node of document.body.childNodes) {
alert(node); // shows all nodes from the collection
}
Câest parce quâil est itĂ©rable (fournit la propriĂ©tĂ© Symbol.iterator, selon les besoins).
- Les mĂ©thodes de tableau ne fonctionneront pas, car ce nâest pas un tableau :
alert(document.body.childNodes.filter); // undefined (there's no filter method!)
La premiĂšre chose est sympa. La seconde est tolĂ©rable, car nous pouvons utiliser Array.from pour crĂ©er un âvraiâ tableau Ă partir de la collection, si nous voulons des mĂ©thodes de tableau :
alert( Array.from(document.body.childNodes).filter ); // function
Les collections DOM, et plus encore â toutes les propriĂ©tĂ©s de navigation rĂ©pertoriĂ©es dans ce chapitre sont en lecture seule.
Nous ne pouvons pas remplacer un enfant par autre chose en attribuant childNodes[i] = ....
Changer le DOM nĂ©cessite dâautres mĂ©thodes. Nous les verrons dans le prochain chapitre.
Presque toutes les collections DOM avec des exceptions mineures sont live. En dâautres termes, elles reflĂštent lâĂ©tat actuel du DOM.
Si nous gardons une rĂ©fĂ©rence Ă element.childNodes, et ajoutons/supprimons des nĆuds dans le DOM, alors ils apparaissent automatiquement dans la collection.
for..in pour parcourir les collectionsLes collections sont itĂ©rables en utilisant for..of. Parfois, les gens essaient dâutiliser for..in pour cela.
Ă ne pas faire. La boucle for..in parcourt toutes les propriĂ©tĂ©s Ă©numĂ©rables. Et les collections ont des propriĂ©tĂ©s âsupplĂ©mentairesâ rarement utilisĂ©es que nous ne voulons gĂ©nĂ©ralement pas obtenir :
<body>
<script>
// affiche 0, 1, length, item, values et plus encore.
for (let prop in document.body.childNodes) alert(prop);
</script>
</body>
FrĂšres, sĆurs et parent
Les frĂšres et sĆurs sont des nĆuds qui sont les enfants du mĂȘme parent.
Par exemple, ici <head> et <body> sont des frĂšres et sĆurs :
<html>
<head>...</head><body>...</body>
</html>
<body>est dit ĂȘtre le frĂšre âsuivantâ ou âdroitâ de<head>,<head>est dit ĂȘtre le frĂšre âprĂ©cĂ©dentâ ou âgaucheâ de<body>.
Le frĂšre suivant est dans la propriĂ©tĂ© nextSibling, et le prĂ©cĂ©dent â dans previousSibling.
Le parent est disponible en tant que parentNode.
Par exemple :
// le parent de <body> est <html>
alert( document.body.parentNode === document.documentElement ); // true
// aprĂšs <head> vient <body>
alert( document.head.nextSibling ); // HTMLBodyElement
// avant <body> vient <head>
alert( document.body.previousSibling ); // HTMLHeadElement
Navigation par élément uniquement
Les propriĂ©tĂ©s de navigation rĂ©pertoriĂ©es ci-dessus font rĂ©fĂ©rence Ă tous les nĆuds. Par exemple, dans childNodes, nous pouvons voir Ă la fois les nĆuds texte, les nĆuds Ă©lĂ©ment et mĂȘme les nĆuds commentaire sâil en existe.
Mais pour de nombreuses tĂąches, nous ne voulons pas de nĆuds texte ou commentaire. Nous voulons manipuler des nĆuds Ă©lĂ©ment qui reprĂ©sentent des balises et forment la structure de la page.
Voyons donc plus de liens de navigation qui ne prennent en compte que les nĆuds Ă©lĂ©ment :
Les liens sont similaires Ă ceux donnĂ©s ci-dessus, juste avec le mot Element Ă lâintĂ©rieur :
childrenâ seuls les enfants qui sont des nĆuds Ă©lĂ©ment.firstElementChild,lastElementChildâ enfants du premier et du dernier Ă©lĂ©ment.previousElementSibling,nextElementSiblingâ Ă©lĂ©ments voisins.parentElementâ Ă©lĂ©ment parent.
parentElement ? Le parent peut-il ne pas ĂȘtre un Ă©lĂ©ment ?La propriĂ©tĂ© parentElement renvoie lâĂ©lĂ©ment parent, tandis que parentNode retourne le parent âpeu importe le nĆudâ. Ces propriĂ©tĂ©s sont gĂ©nĂ©ralement les mĂȘmes : elles obtiennent toutes deux le parent.
Ă la seule exception de document.documentElement :
alert( document.documentElement.parentNode ); // document
alert( document.documentElement.parentElement ); // null
La raison en est que le nĆud racine document.documentElement (<html>) a
document comme parent. Mais document nâest pas un nĆud Ă©lĂ©ment, donc parentNode le renvoie et pas parentElement.
Ce dĂ©tail peut ĂȘtre utile lorsque nous voulons passer dâun Ă©lĂ©ment arbitraire elem Ă <html>, mais pas au document :
while(elem = elem.parentElement) { // remonter jusqu'Ă <html>
alert( elem );
}
Modifions lâun des exemples ci-dessus : remplaçons childNodes par children. Maintenant, il ne montre que des Ă©lĂ©ments :
<html>
<body>
<div>Begin</div>
<ul>
<li>Information</li>
</ul>
<div>End</div>
<script>
for (let elem of document.body.children) {
alert(elem); // DIV, UL, DIV, SCRIPT
}
</script>
...
</body>
</html>
Plus de liens : tableaux
JusquâĂ prĂ©sent, nous avons dĂ©crit les propriĂ©tĂ©s de navigation de base.
Certains types dâĂ©lĂ©ments DOM peuvent fournir des propriĂ©tĂ©s supplĂ©mentaires, spĂ©cifiques Ă leur type, pour plus de commoditĂ©.
Les tableaux en sont un excellent exemple et représentent un cas particuliÚrement important :
LâĂ©lĂ©ment <table> supporte (en plus de ce qui prĂ©cĂšde) ces propriĂ©tĂ©s :
table.rowsâ la collection dâĂ©lĂ©ments<tr>du tableau.table.caption/tHead/tFootâ rĂ©fĂ©rences aux Ă©lĂ©ments<caption>,<thead>,<tfoot>.table.tBodiesâ la collection dâĂ©lĂ©ments<tbody>(peut ĂȘtre multiple selon la norme, mais il y en aura toujours au moins une â mĂȘme si elle nâest pas dans le HTML source, le navigateur la mettra dans le DOM).
<thead>, <tfoot>, <tbody> les éléments fournissent la propriété rows :
tbody.rowsâ la collection de<tr>Ă lâintĂ©rieur.
<tr>:
tr.cellsâ la collection de cellules<td>et<th>Ă lâintĂ©rieur du<tr>donnĂ©.tr.sectionRowIndexâ la position (index) du<tr>donnĂ© Ă lâintĂ©rieur du<thead>/<tbody>/<tfoot>.tr.rowIndexâ le nombre de<tr>dans le tableau dans son ensemble (y compris toutes les lignes du tableau).
**<td> et <th> : **
td.cellIndexâ le numĂ©ro de la cellule Ă lâintĂ©rieur du<tr>qui lâentoure.
Un exemple dâutilisation :
<table id="table">
<tr>
<td>one</td><td>two</td>
</tr>
<tr>
<td>three</td><td>four</td>
</tr>
</table>
<script>
// obtenir td avec "two" (premiĂšre ligne, deuxiĂšme colonne)
let td = table.rows[0].cells[1];
td.style.backgroundColor = "red"; // le mettre en valeur
</script>
La spécification : tabular data.
Il existe également des propriétés de navigation supplémentaires pour les formulaires HTML. Nous les examinerons plus tard lorsque nous commencerons à travailler avec des formulaires.
Résumé
Ătant donnĂ© un nĆud DOM, nous pouvons aller vers ses voisins immĂ©diats en utilisant les propriĂ©tĂ©s de navigation.
Il en existe deux ensembles principaux :
- Pour tous les nĆuds :
parentNode,childNodes,firstChild,lastChild,previousSibling,nextSibling. - Pour les nĆuds Ă©lĂ©ment uniquement :
parentElement,children,firstElementChild,lastElementChild,previousElementSibling,nextElementSibling.
Certains types dâĂ©lĂ©ments DOM, par exemple , fournissent des propriĂ©tĂ©s et des collections supplĂ©mentaires pour accĂ©der Ă leur contenu.
Commentaires
<code>, pour plusieurs lignes â enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâŠ)