# Propriétés de nœud : type, balise et contenu Voyons plus en détail les nœuds DOM. Dans ce chapitre, nous verrons plus en détail ce qu'ils sont et découvrirons leurs propriétés les plus utilisées. ## Classes de nœud DOM Différents nœuds DOM peuvent avoir des propriétés différentes. Par exemple, un nœud élément correspondant à la balise `` a des propriétés liées aux liens, et celui correspondant à `` a des propriétés liées aux entrées, etc. Les nœuds texte ne sont pas identiques aux nœuds élément. Mais il existe également des propriétés et des méthodes communes à chacun d'entre eux, car toutes les classes de nœuds DOM forment une hiérarchie unique. Chaque nœud DOM appartient à la classe intégrée correspondante. La racine de la hiérarchie est [EventTarget](https://dom.spec.whatwg.org/#eventtarget), hérité par [Node](http://dom.spec.whatwg.org/#interface-node), et d'autres nœuds DOM en héritent. Voici l'image, les explications à suivre : ![](dom-class-hierarchy.svg) Les classes sont : - [EventTarget](https://dom.spec.whatwg.org/#eventtarget) -- est la classe racine "abstraite". Les objets de cette classe ne sont jamais créés. Il sert de base, de sorte que tous les nœuds DOM prennent en charge les soi-disant "événements", nous les étudierons plus tard. - [Node](http://dom.spec.whatwg.org/#interface-node) -- est également une classe "abstraite", servant de base aux nœuds DOM. Elle fournit la fonctionnalité d'arborescence de base : `parentNode`, `nextSibling`, `childNodes` et ainsi de suite (ce sont des getters). Les objets de la classe `Node` ne sont jamais créés. Mais il existe des classes de nœuds concrets qui en héritent, à savoir: `Text` pour les nœuds texte, `Element` pour les nœuds élément et plus exotiques comme `Comment` pour les nœuds commentaire. - [Element](http://dom.spec.whatwg.org/#interface-element) -- est une classe de base pour les éléments DOM. Elle fournit une navigation au niveau des éléments comme `nextElementSibling`, `children` et des méthodes de recherche comme `getElementsByTagName`, `querySelector`. Un navigateur prend en charge non seulement HTML, mais aussi XML et SVG. La classe `Element` sert de base à des classes plus spécifiques : `SVGElement`, `XMLElement` et `HTMLElement`. - [HTMLElement](https://html.spec.whatwg.org/multipage/dom.html#htmlelement) -- est enfin la classe de base pour tous les éléments HTML. Elle est héritée d'éléments concrets HTML : - [HTMLInputElement](https://html.spec.whatwg.org/multipage/forms.html#htmlinputelement) -- la classe pour les éléments ``, - [HTMLBodyElement](https://html.spec.whatwg.org/multipage/semantics.html#htmlbodyelement) -- la classe pour les éléments ``, - [HTMLAnchorElement](https://html.spec.whatwg.org/multipage/semantics.html#htmlanchorelement) -- la classe pour les éléments ``, - ...et ainsi de suite. <<<<<<< HEAD Il existe de nombreuses autres balises avec leurs propres classes qui peuvent des propriétés et des méthodes spécifiques, tandis que certains éléments, tels que ``, `
`, `
` n'ont pas de propriétés spécifiques, ce sont donc des instances de la classe `HTMLElement`. ======= There are many other tags with their own classes that may have specific properties and methods, while some elements, such as ``, `
`, `
` do not have any specific properties, so they are instances of `HTMLElement` class. >>>>>>> 246c600f11b4e6c52b4ae14f83e65319671f998f Ainsi, l'ensemble complet des propriétés et des méthodes d'un nœud donné est le résultat de l'héritage. Par exemple, considérons l'objet DOM pour un élément ``. Il appartient à la classe [HTMLInputElement](https://html.spec.whatwg.org/multipage/forms.html#htmlinputelement). Il obtient les propriétés et les méthodes en superposition de (répertoriées dans l'ordre d'héritage) : - `HTMLInputElement` -- cette classe fournit des propriétés spécifiques à l'entrée, - `HTMLElement` -- elle fournit des méthodes d'élément HTML communes (et des getters/setters), - `Element` -- fournit des méthodes d'élément génériques, - `Node` -- fournit des propriétés de noeud DOM communes, - `EventTarget` -- apporte du support aux événements (à couvrir), - ...et finalement il hérite de `Object`, donc les méthodes "plain object" comme `hasOwnProperty` sont également disponibles. Pour voir le nom de la classe de noeud DOM, nous pouvons rappeler qu'un objet a généralement la propriété `constructor`. Il fait référence au constructeur de classe, et `constructor.name` est son nom : ```js run alert( document.body.constructor.name ); // HTMLBodyElement ``` ...Or we can just `toString` it: ```js run alert( document.body ); // [object HTMLBodyElement] ``` Nous pouvons également utiliser `instanceof` pour vérifier l'héritage : ```js run alert( document.body instanceof HTMLBodyElement ); // true alert( document.body instanceof HTMLElement ); // true alert( document.body instanceof Element ); // true alert( document.body instanceof Node ); // true alert( document.body instanceof EventTarget ); // true ``` Comme nous pouvons le voir, les nœuds DOM sont des objets JavaScript normaux. Ils utilisent des classes basées sur des prototypes pour l'héritage. C'est aussi facile à voir en sortant un élément avec `console.dir (elem)` dans un navigateur. Là, dans la console, vous pouvez voir `HTMLElement.prototype`, `Element.prototype` et ainsi de suite. ```smart header="`console.dir(elem)` versus `console.log(elem)`" La plupart des navigateurs prennent en charge deux commandes dans leurs outils de développement : `console.log` et `console.dir`. Elles sortent leurs arguments dans la console. Pour les objets JavaScript, ces commandes font généralement la même chose. Mais pour les éléments DOM, elles sont différents : - `console.log(elem)` affiche l'arborescence DOM de l'élément. - `console.dir(elem)` affiche l'élément en tant qu'objet DOM, bon pour explorer ses propriétés. Essayez les sur `document.body`. ``` ````smart header="IDL dans la spécification" Dans la spécification, les classes DOM ne sont pas décrites en utilisant JavaScript, mais une [Interface description language](https://en.wikipedia.org/wiki/Interface_description_language) spéciale (IDL), qui est généralement facile à comprendre. Dans IDL, toutes les propriétés sont précédées de leurs types. Par exemple, `DOMString`, `boolean` et ainsi de suite. En voici un extrait, avec des commentaires : ```js // Definir HTMLInputElement *!* // Le signe deux-points ":" signifie que HTMLInputElement hérite de HTMLElement */!* interface HTMLInputElement: HTMLElement { // ici les propriétés et méthodes des éléments *!* // "DOMString" signifie que la valeur d'une propriété est une chaîne de caractères */!* attribute DOMString accept; attribute DOMString alt; attribute DOMString autocomplete; attribute DOMString value; *!* // propriété de valeur booléenne (true/false) attribute boolean autofocus; */!* ... *!* // maintenant la méthode : "void" signifie que la méthode ne renvoie aucune valeur */!* void select(); ... } ``` ```` ## La propriété "nodeType" La propriété `nodeType` fournit une autre méthode "à l'ancienne" pour obtenir le "type" d'un nœud DOM. Il a une valeur numérique : - `elem.nodeType == 1` pour les nœuds élément, - `elem.nodeType == 3` pour les nœuds texte, - `elem.nodeType == 9` pour l'objet document, - il y a peu d'autres valeurs dans [la spécification](https://dom.spec.whatwg.org/#node). Par exemple : ```html run ``` Dans les scripts modernes, nous pouvons utiliser `instanceof` et d'autres tests basés sur les classes pour voir le type de nœud, mais parfois `nodeType` peut être plus simple. Nous pouvons seulement lire `nodeType`, pas le changer. ## Balise : nodeName et tagName Étant donné un nœud DOM, nous pouvons lire son nom de balise dans les propriétés `nodeName` ou `tagName` : Par exemple : ```js run alert( document.body.nodeName ); // BODY alert( document.body.tagName ); // BODY ``` Y a-t-il une différence entre `tagName` et `nodeName` ? Bien sûr, la différence se reflète dans leurs noms, mais c'est en effet un peu subtile. - La propriété `tagName` existe uniquement pour les nœuds `Element`. - Le `nodeName` est défini pour tout `Node` : - pour les éléments, cela signifie la même chose que `tagName`. - pour les autres types de nœuds (texte, commentaire, etc.), il a une chaîne de caractères avec le type de nœud. En d'autres termes, `tagName` est uniquement pris en charge par les nœuds élément (car il provient de la classe `Element`), tandis que `nodeName` peut dire quelque chose sur d'autres types de nœuds. Par exemple, comparons `tagName` et `nodeName` pour le `document` et un nœud de commentaire : ```html run ``` Si nous ne traitons que des éléments, nous pouvons utiliser à la fois `tagName` et `nodeName` - il n'y a pas de différence. ```smart header="Le nom de la balise est toujours en majuscule sauf en mode XML" Le navigateur a deux modes de traitement des documents: HTML et XML. Habituellement, le mode HTML est utilisé pour les pages Web. Le mode XML est activé lorsque le navigateur reçoit un document XML avec l'en-tête : `Content-Type: application/xml+xhtml`. En mode HTML, `tagName/nodeName` est toujours en majuscule : c'est `BODY` pour `` ou ``. En mode XML, la casse est conservée "en l'état". De nos jours, le mode XML est rarement utilisé. ``` ## innerHTML: les contenus La propriété [innerHTML](https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML) permet d'obtenir le HTML à l'intérieur de l'élément sous forme de chaîne de caractères. Nous pouvons également le modifier. C'est donc l'un des moyens les plus puissants de modifier la page. L'exemple montre le contenu de `document.body` puis le remplace complètement : ```html run

A paragraph

A div
``` Nous pouvons essayer d'insérer du code HTML invalide, le navigateur corrigera nos erreurs : ```html run ``` ```smart header="Les scripts ne s'exécutent pas" Si `innerHTML` insère une balise ` ``` **Attention : contrairement à `innerHTML`, l'écriture dans `outerHTML` ne modifie pas l'élément. Au lieu de cela, il le remplace dans le DOM.** Oui, cela semble étrange, et c'est étrange, c'est pourquoi nous en faisons une note séparée ici. Jetez-y un oeil. Prenons l'exemple : ```html run
Hello, world!
``` Ça a l'air vraiment bizarre, non ? Dans la ligne `(*)` nous avons remplacé `div` par `

A new element

`. Dans le document externe (le DOM), nous pouvons voir le nouveau contenu au lieu de `
`. Mais, comme nous pouvons le voir dans la ligne `(**)`, la valeur de l'ancienne variable `div` n'a pas changé ! L'affectation `outerHTML` ne modifie pas l'élément DOM (l'objet référencé, dans ce cas, la variable 'div'), mais le supprime du DOM et insère le nouveau HTML à sa place. Donc, ce qui s'est passé dans `div.outerHTML=...` est : - `div` a été supprimé du document. - Un autre morceau du HTML `

A new element

` a été inséré à sa place. - `div` a toujours son ancienne valeur. Le nouveau HTML n'a été enregistré dans aucune variable. Il est si facile de faire une erreur ici : modifiez `div.outerHTML` puis continuez à travailler avec `div` comme s'il contenait le nouveau contenu. Mais ce n'est pas le cas. Ce genre de chose est correcte pour `innerHTML`, mais pas pour `outerHTML`. Nous pouvons écrire dans `elem.outerHTML`, mais nous devons garder à l'esprit que cela ne change pas l'élément dans lequel nous écrivons ('elem'). Il place le nouveau HTML à sa place. Nous pouvons obtenir des références aux nouveaux éléments en interrogeant le DOM. ## nodeValue/data : contenu du nœud texte La propriété `innerHTML` n'est valide que pour les nœuds élément. D'autres types de nœuds, tels que les nœuds texte, ont leur contrepartie : les propriétés `nodeValue` et `data`. Ces deux sont presque les mêmes pour une utilisation pratique, il n'y a que des différences de spécifications mineures. Nous allons donc utiliser `data`, car il est plus court. Un exemple de lecture du contenu d'un nœud texte et d'un commentaire : ```html run height="50" Hello ``` Pour les nœuds texte, nous pouvons imaginer une raison de les lire ou de les modifier, mais pourquoi des commentaires ? Parfois, les développeurs incorporent des informations ou des instructions de modèle dans HTML, comme ceci : ```html
Welcome, Admin!
``` ...Ensuite, JavaScript peut le lire à partir de la propriété `data` et traiter les instructions intégrées. ## textContent: texte pur Le `textContent` donne accès au *texte* à l'intérieur de l'élément : seulement le texte, moins tous les ``. Par exemple : ```html run

Headline!

Martians attack people!

``` Comme nous pouvons le voir, seul le texte est renvoyé, comme si tous les `` étaient supprimés, mais le texte qu'ils contenaient est resté. En pratique, la lecture d'un tel texte est rarement nécessaire. **Ecrire dans `textContent` est beaucoup plus utile, car il permet d'écrire du texte de "manière sûre".** Disons que nous avons une chaîne de caractères arbitraire, par exemple entrée par un utilisateur, et que nous voulons l'afficher. - Avec `innerHTML` nous allons l'insérer "au format HTML", avec toutes les balises HTML. - Avec `textContent` nous allons l'insérer "en tant que texte", tous les symboles sont traités littéralement. Comparez les deux : ```html run
``` 1. La première `
` obtient le nom "en HTML" : toutes les balises deviennent des balises, nous voyons donc le nom en gras. 2. La seconde `
` obtient le nom "sous forme de texte", donc nous voyons littéralement `Winnie-the-pooh!`. Dans la plupart des cas, nous attendons le texte d'un utilisateur et souhaitons le traiter comme du texte. Nous ne voulons pas de HTML inattendu sur notre site. Une affectation à `textContent` fait exactement cela. ## La propriété "cachée" L'attribut "hidden" (caché) et la propriété DOM spécifient si l'élément est visible ou non. Nous pouvons l'utiliser dans le HTML ou l'attribuer en utilisant JavaScript, comme ceci : ```html run height="80"
Both divs below are hidden
JavaScript assigned the property "hidden"
``` Techniquement, `hidden` fonctionne de la même manière que `style="display:none"`. Mais c'est plus court à écrire. Voici un élément clignotant : ```html run height=50
A blinking element
``` ## Plus de propriétés Les éléments DOM ont également des propriétés supplémentaires, en particulier celles qui dépendent de la classe : - `value` -- la valeur pour ``, `