La modification DOM est la clĂ© pour crĂ©er des pages âliveâ.
Ici, nous verrons comment crĂ©er de nouveaux Ă©lĂ©ments âĂ la volĂ©eâ et modifier le contenu de la page existante.
Exemple : afficher un message
Démontrons en utilisant un exemple. Nous allons ajouter un message sur la page qui est plus joli que alert.
Voici Ă quoi cela ressemblera :
<style>
.alert {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<div class="alert">
<strong>Hi there!</strong> You've read an important message.
</div>
CâĂ©tait un exemple HTML. CrĂ©ons maintenant la mĂȘme div avec JavaScript (en supposant que les styles sont dĂ©jĂ dans le HTML ou un fichier CSS externe).
CrĂ©ation dâun Ă©lĂ©ment
Pour crĂ©er des nĆuds DOM, il existe deux mĂ©thodes :
document.createElement(tag)-
Crée un nouveau noeud élément avec la balise donnée :
let div = document.createElement('div'); document.createTextNode(text)-
CrĂ©e un nouveau nĆud texte avec le texte donnĂ© :
let textNode = document.createTextNode('Here I am');
La plupart du temps, nous devons crĂ©er des nĆuds dâĂ©lĂ©ment, tels que le div pour le message.
Création du message
La création du message div prend 3 étapes :
// 1. Create <div> element
let div = document.createElement('div');
// 2. Set its class to "alert"
div.className = "alert";
// 3. Fill it with the content
div.innerHTML = "<strong>Hi there!</strong> You've read an important message.";
Nous avons créé lâĂ©lĂ©ment. Mais pour le moment, ce nâest que dans une variable nommĂ©e div, pas encore dans la page. Nous ne pouvons donc pas le voir.
MĂ©thodes dâinsertion
Pour faire apparaĂźtre la div, nous devons lâinsĂ©rer quelque part dans document. Par exemple, dans lâĂ©lĂ©ment <body>, rĂ©fĂ©rencĂ© par document.body.
Il existe une méthode spéciale append pour cela : document.body.append(div).
Voici le code complet :
<style>
.alert {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<script>
let div = document.createElement('div');
div.className = "alert";
div.innerHTML = "<strong>Hi there!</strong> You've read an important message.";
document.body.append(div);
</script>
Ici, nous avons appelĂ© append sur document.body, mais nous pouvons appeler la mĂ©thode append sur nâimporte quel autre Ă©lĂ©ment, pour y mettre un autre Ă©lĂ©ment. Par exemple, nous pouvons ajouter quelque chose Ă <div> en appelant div.append(anotherElement).
Voici plus de mĂ©thodes dâinsertion, elles spĂ©cifient diffĂ©rents endroits oĂč insĂ©rer :
node.append(...nodes or strings)â ajouter des nĆuds ou des chaĂźnes de caractĂšres Ă la fin denode,node.prepend(...nodes or strings)â insĂ©rer des nĆuds ou des chaĂźnes de caractĂšres au dĂ©but denode,node.before(...nodes or strings)â- insĂ©rer des nĆuds ou des chaĂźnes de caractĂšres avantnode,node.after(...nodes or strings)â- insĂ©rer des nĆuds ou des chaĂźnes de caractĂšres aprĂšsnode,node.replaceWith(...nodes or strings)â- remplacenodeavec les nĆuds ou chaĂźnes de caractĂšres donnĂ©s.
Les arguments de ces mĂ©thodes sont une liste arbitraire de nĆuds DOM Ă insĂ©rer ou des chaĂźnes de texte (qui deviennent automatiquement des nĆuds de texte).
Voyons-les en action.
Voici un exemple dâutilisation de ces mĂ©thodes pour ajouter des Ă©lĂ©ments Ă une liste et le texte avant/aprĂšs :
<ol id="ol">
<li>0</li>
<li>1</li>
<li>2</li>
</ol>
<script>
ol.before('before'); // insĂšre la chaĂźne de caractĂšres "before" avant <ol>
ol.after('after'); // insĂšre la chaĂźne de caractĂšres "after" aprĂšs <ol>
let liFirst = document.createElement('li');
liFirst.innerHTML = 'prepend';
ol.prepend(liFirst); // insÚre liFirst au début de <ol>
let liLast = document.createElement('li');
liLast.innerHTML = 'append';
ol.append(liLast); // insĂšre liLast Ă la fin de <ol>
</script>
Voici une image visuelle de ce que font les méthodes :
La liste finale sera donc :
before
<ol id="ol">
<li>prepend</li>
<li>0</li>
<li>1</li>
<li>2</li>
<li>append</li>
</ol>
after
Comme indiquĂ©, ces mĂ©thodes peuvent insĂ©rer plusieurs nĆuds et morceaux de texte en un seul appel.
Par exemple, ici une chaßne de caractÚres et un élément sont insérés :
<div id="div"></div>
<script>
div.before('<p>Hello</p>', document.createElement('hr'));
</script>
Remarque: le texte est insĂ©rĂ© âen tant que texteâ, pas âen tant que HTMLâ, avec un Ă©chappement appropriĂ© des caractĂšres tels que <, >.
Le HTML final est donc :
<p>Hello</p>
<hr>
<div id="div"></div>
En dâautres termes, les chaĂźnes de caractĂšres sont insĂ©rĂ©es de maniĂšre sĂ»re, comme le fait elem.textContent.
Ainsi, ces mĂ©thodes ne peuvent ĂȘtre utilisĂ©es que pour insĂ©rer des nĆuds DOM ou des morceaux de texte.
Mais que se passe-t-il si nous voulons insĂ©rer du HTML âen tant que htmlâ, avec toutes les balises et les trucs qui fonctionnent, comme elem.innerHTML le fait ?
insertAdjacentHTML/Text/Element
Pour cela, nous pouvons utiliser une autre méthode assez polyvalente : elem.insertAdjacentHTML(where, html).
Le premier paramĂštre est un mot de code, spĂ©cifiant oĂč insĂ©rer par rapport Ă elem. Doit ĂȘtre lâun des suivants :
"beforebegin"â insĂšrehtmlimmĂ©diatement avantelem,"afterbegin"â insĂšrehtmldanselem, au dĂ©but,"beforeend"â insĂšrehtmldanselem, Ă la fin,"afterend"â insĂšrehtmlimmĂ©diatement aprĂšselem.
Le second paramĂštre est une chaĂźne HTML insĂ©rĂ©e âau format HTMLâ.
Par exemple :
<div id="div"></div>
<script>
div.insertAdjacentHTML('beforebegin', '<p>Hello</p>');
div.insertAdjacentHTML('afterend', '<p>Bye</p>');
</script>
âŠConduirait Ă :
<p>Hello</p>
<div id="div"></div>
<p>Bye</p>
VoilĂ comment nous pouvons ajouter du code HTML arbitraire Ă la page.
Voici lâimage des variantes dâinsertion :
Nous pouvons facilement remarquer des similitudes entre cette image et lâimage prĂ©cĂ©dente. Les points dâinsertion sont en fait les mĂȘmes, mais cette mĂ©thode insĂšre du HTML.
La mĂ©thode a deux sĆurs :
elem.insertAdjacentText(where, text)â la mĂȘme syntaxe, mais une chaĂźne de caractĂšrestextest insĂ©rĂ©een tant que texteau lieu de HTML,elem.insertAdjacentElement(where, elem)â la mĂȘme syntaxe, mais insĂšre un Ă©lĂ©ment.
Elles existent principalement pour rendre la syntaxe âuniformeâ. En pratique, seule insertAdjacentHTML est utilisĂ©e la plupart du temps. Parce que pour les Ă©lĂ©ments et le texte, nous avons des mĂ©thodes append/prepend/before/after â elles sont plus courtes Ă Ă©crire et peuvent insĂ©rer des nĆuds/morceaux de texte.
Voici donc une variante alternative pour afficher un message :
<style>
.alert {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<script>
document.body.insertAdjacentHTML("afterbegin", `<div class="alert">
<strong>Hi there!</strong> You've read an important message.
</div>`);
</script>
Suppression de noeuds
Pour supprimer un nĆud, il existe une mĂ©thode node.remove().
Faisons disparaĂźtre notre message aprĂšs une seconde :
<style>
.alert {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<script>
let div = document.createElement('div');
div.className = "alert";
div.innerHTML = "<strong>Hi there!</strong> You've read an important message.";
document.body.append(div);
setTimeout(() => div.remove(), 1000);
</script>
Veuillez noter : si nous voulons dĂ©placer un Ă©lĂ©ment vers un autre endroit â il nâest pas nĂ©cessaire de le supprimer de lâancien.
Toutes les mĂ©thodes dâinsertion suppriment automatiquement le nĆud de lâancien emplacement.
Par exemple, permutons les éléments :
<div id="first">First</div>
<div id="second">Second</div>
<script>
// pas besoin d'appeler remove
second.after(first); // prend #second et aprĂšs insĂšre #first
</script>
Clonage de Noeuds : cloneNode
Comment insérer un autre message similaire ?
Nous pourrions crĂ©er une fonction et y mettre le code. Mais lâalternative serait de cloner la div existant et de modifier le texte Ă lâintĂ©rieur (si nĂ©cessaire).
Parfois, lorsque nous avons un gros Ă©lĂ©ment, cela peut ĂȘtre plus rapide et plus simple.
- Lâappel
elem.cloneNode(true)crĂ©e un clone âprofondâ de lâĂ©lĂ©ment â avec tous les attributs et sous-Ă©lĂ©ments. Si nous appelonselem.cloneNode(false), alors le clone est fait sans Ă©lĂ©ments enfants.
Un exemple de copie du message :
<style>
.alert {
padding: 15px;
border: 1px solid #d6e9c6;
border-radius: 4px;
color: #3c763d;
background-color: #dff0d8;
}
</style>
<div class="alert" id="div">
<strong>Hi there!</strong> You've read an important message.
</div>
<script>
let div2 = div.cloneNode(true); // clone the message
div2.querySelector('strong').innerHTML = 'Bye there!'; // change le clone
div.after(div2); // affiche le clone aprĂšs le div existant
</script>
DocumentFragment
DocumentFragment est un nĆud DOM spĂ©cial qui sert de wrapper pour passer autour des listes de nĆuds.
Nous pouvons y ajouter dâautres nĆuds, mais lorsque nous lâinsĂ©rons quelque part, son contenu est insĂ©rĂ© Ă la place.
Par exemple, getListContent ci-dessous génÚre un fragment avec des éléments <li>, qui sont ensuite insérés dans <ul> :
<ul id="ul"></ul>
<script>
function getListContent() {
let fragment = new DocumentFragment();
for(let i=1; i<=3; i++) {
let li = document.createElement('li');
li.append(i);
fragment.append(li);
}
return fragment;
}
ul.append(getListContent()); // (*)
</script>
Veuillez noter quâĂ la derniĂšre ligne (*) nous ajoutons DocumentFragment, mais il âsâadapteâ, donc la structure rĂ©sultante sera :
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
DocumentFragment est rarement utilisĂ© explicitement. Pourquoi ajouter Ă un type spĂ©cial de nĆud, si nous pouvons renvoyer un tableau de nĆuds Ă la place ? Exemple réécrit :
<ul id="ul"></ul>
<script>
function getListContent() {
let result = [];
for(let i=1; i<=3; i++) {
let li = document.createElement('li');
li.append(i);
result.push(li);
}
return result;
}
ul.append(...getListContent()); // append + "..." operator = friends!
</script>
Nous mentionnons DocumentFragment principalement parce quâil y a quelques concepts dessus, comme lâĂ©lĂ©ment template, que nous couvrirons beaucoup plus tard.
MĂ©thodes dâinsertion/suppression Ă lâancienne
Il existe Ă©galement des mĂ©thodes de manipulation du DOM âĂ lâancienneâ, qui existent pour des raisons historiques.
Ces mĂ©thodes viennent dâune Ă©poque trĂšs ancienne. De nos jours, il nây a aucune raison de les utiliser, depuis quâil existe des mĂ©thodes modernes, telles que append, prepend, before, after, remove, replaceWith, qui sont plus flexibles.
La seule raison pour laquelle nous listons ces méthodes ici est que vous pouvez les trouver dans de nombreux anciens scripts :
parentElem.appendChild(node)-
Appends
nodeas the last child ofparentElem.The following example adds a new
<li>to the end of<ol>:<ol id="list"> <li>0</li> <li>1</li> <li>2</li> </ol> <script> let newLi = document.createElement('li'); newLi.innerHTML = 'Hello, world!'; list.appendChild(newLi); </script> parentElem.insertBefore(node, nextSibling)-
InsĂšre
nodeavantnextSiblingdansparentElem.Le code suivant insÚre un nouvel élément de liste avant le second
<li>:<ol id="list"> <li>0</li> <li>1</li> <li>2</li> </ol> <script> let newLi = document.createElement('li'); newLi.innerHTML = 'Hello, world!'; list.insertBefore(newLi, list.children[1]); </script>Pour insérer
newLicomme premier élément, nous pouvons le faire comme ceci :list.insertBefore(newLi, list.firstChild); parentElem.replaceChild(node, oldChild)-
Remplace
oldChildavecnodechez les enfants deparentElem. parentElem.removeChild(node)-
Supprime
nodedeparentElem(en supposant quenodeest son enfant).Lâexemple suivant supprime dâabord
<li>de<ol>:<ol id="list"> <li>0</li> <li>1</li> <li>2</li> </ol> <script> let li = list.firstElementChild; list.removeChild(li); </script>
Toutes ces mĂ©thodes renvoient le nĆud insĂ©rĂ©/supprimĂ©. En dâautres termes, parentElem.appendChild(node) renvoie node. Mais gĂ©nĂ©ralement, la valeur retournĂ©e nâest pas utilisĂ©e, nous exĂ©cutons simplement la mĂ©thode.
Un mot sur âdocument.writeâ
Il existe une autre méthode trÚs ancienne pour ajouter quelque chose à une page Web : document.write.
La syntaxe :
<p>Somewhere in the page...</p>
<script>
document.write('<b>Hello from JS</b>');
</script>
<p>The end</p>
Lâappel Ă document.write(html) Ă©crit le html dans la page âici et maintenantâ. La chaĂźne de caractĂšres html peut ĂȘtre gĂ©nĂ©rĂ©e dynamiquement, donc câest un peu flexible. Nous pouvons utiliser JavaScript pour crĂ©er une page Web Ă part entiĂšre et lâĂ©crire.
La mĂ©thode vient de lâĂ©poque oĂč il nây avait pas de DOM, pas de standards ⊠Des temps vraiment anciens. Il vit toujours, car il existe des scripts qui lâutilisent.
Dans les scripts modernes, nous le voyons rarement, en raison de la limitation importante suivante :
Lâappel Ă document.write ne fonctionne que pendant le chargement de la page.
Si nous lâappelons ensuite, le contenu du document existant est effacĂ©.
Par exemple :
<p>After one second the contents of this page will be replaced...</p>
<script>
// document.write aprĂšs 1 seconde
// cela aprÚs que la page soit chargée, donc il efface le contenu existant
setTimeout(() => document.write('<b>...By this.</b>'), 1000);
</script>
Câest donc un peu inutilisable au stade âpost chargementâ, contrairement aux autres mĂ©thodes DOM que nous avons couvertes ci-dessus.
VoilĂ lâinconvĂ©nient.
Il y a aussi un avantage. Techniquement, lorsque document.write est appelĂ© pendant que le navigateur lit (âanalyseâ) le HTML entrant, et quâil Ă©crit quelque chose, le navigateur le consomme comme sâil Ă©tait initialement lĂ , dans le texte HTML.
Cela fonctionne donc trĂšs rapidement, car il nây a aucune modification du DOM impliquĂ©e. Il Ă©crit directement dans le texte de la page, tandis que le DOM nâest pas encore construit.
Donc, si nous devons ajouter beaucoup de texte en HTML de maniĂšre dynamique, et que nous sommes en phase de chargement de page, et que la vitesse compte, cela peut aider. Mais dans la pratique, ces exigences se rencontrent rarement. Et gĂ©nĂ©ralement, nous pouvons voir cette mĂ©thode dans les scripts simplement parce quâils sont anciens.
Résumé
-
MĂ©thodes pour crĂ©er de nouveaux nĆuds :
document.createElement(tag)â crĂ©e un Ă©lĂ©ment avec la balise donnĂ©e,document.createTextNode(value)â crĂ©e un nĆud texte (rarement utilisĂ©),elem.cloneNode(deep)â clone lâĂ©lĂ©ment, sideep==truetous les descendants viennent avec.
-
Insertion et suppression :
node.append(...nodes or strings)â insĂšre dansnode, Ă la fin,node.prepend(...nodes or strings)â insĂšre dansnode, au dĂ©but,node.before(...nodes or strings)â- insĂšre juste avantnode,node.after(...nodes or strings)â- insĂšre juste aprĂšsnode,node.replaceWith(...nodes or strings)â- remplacenode.node.remove()â- supprime lenode.
Les chaĂźnes de caractĂšres texte sont insĂ©rĂ©es âsous forme de texteâ.
-
Il existe Ă©galement des mĂ©thodes âold schoolâ :
parent.appendChild(node)parent.insertBefore(node, nextSibling)parent.removeChild(node)parent.replaceChild(newElem, node)
Toutes ces méthodes retournent le
node. -
Ătant donnĂ© un peu de HTML dans
html,elem.insertAdjacentHTML(where, html)lâinsĂšre en fonction de la valeur dewhere:"beforebegin"â insĂšrehtmljuste avantelem,"afterbegin"â insĂšrehtmldanselem, au dĂ©but,"beforeend"â insĂšrehtmldanselem, Ă la fin,"afterend"â insĂšrehtmljuste aprĂšselem.
Il existe également des méthodes similaires,
elem.insertAdjacentTextetelem.insertAdjacentElement, qui insÚrent des chaßnes de caractÚres texte et des éléments, mais ils sont rarement utilisés. -
Pour ajouter du HTML Ă la page avant la fin du chargement :
document.write(html)
Une fois la page chargée, un tel appel efface le document. Surtout vu dans les anciens scripts.
Commentaires
<code>, pour plusieurs lignes â enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâŠ)