Obiectul Node - Navigarea în DOM
Fiecare nod individual, fie că este un element HTML, atributul acestuia sau text, în structura DOM este reprezentat de obiectul Node. Poate apărea întrebarea: cum sunt legate elementele unei pagini web de nodurile acelei pagini web? Și aici trebuie să subliniem că orice element al unei pagini web este un nod, dar nu orice nod este un element (de exemplu, atributele și textul elementelor sunt, de asemenea, noduri separate).
Obiectul Node oferă o serie de proprietăți, cu ajutorul cărora putem obține informații despre nodul respectiv:
- childNodes: conține colecția de noduri copil
- children: conține colecția de noduri copil, care sunt elemente
- firstChild: returnează primul nod copil al nodului curent
- firstElementChild: returnează primul nod copil, care este un element
- lastChild: returnează ultimul nod copil al nodului curent
- lastElementChild: returnează ultimul nod copil, care este un element
- previousSibling: returnează nodul anterior, care se află la același nivel cu nodul curent
- nextSibling: returnează următorul nod, care se află la același nivel cu nodul curent
- previousElementSibling: returnează nodul anterior, care este un element și care se află la același nivel cu nodul curent
- nextElementSibling: returnează nodul următor, care este un element și care se află la același nivel cu nodul curent
- ownerDocument: returnează nodul rădăcină al documentului
- parentNode: returnează nodul părinte al nodului curent
- parentElement: returnează nodul părinte, care este un element
- nodeName: returnează numele nodului
- nodeType: returnează tipul nodului sub formă numerică
- nodeValue: returnează textul unui nod text
În primul rând, putem folosi proprietățile nodeName și nodeType pentru a afla tipul nodului.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>FDC.COM</title>
</head>
<body>
<div id="article">
<h1 id="header">Home Page</h1>
<p>Page Text</p>
</div>
<script>
const article = document.getElementById("article");
console.log(article.nodeName); // DIV
console.log(article.nodeType); // 1
</script>
</body>
</html>
Aici obținem informații despre elementul cu id="header". În special, proprietatea nodeName va returna numele tag-ului elementului - div, iar proprietatea nodeType va returna numărul 1. Fiecarui tip de nod îi corespunde un anumit număr:

Obținerea elementului părinte
Pentru a obține elementul părinte, se utilizează proprietățile parentNode și parentElement. De exemplu:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>FDC.COM</title>
</head>
<body>
<div id="article">
<h1 id="header">Home Page</h1>
<p>Page Text</p>
</div>
<script>
// selectăm toate elementele cu id="header"
const header = document.getElementById("header");
// obținem elementul părinte
const headerParent = header?.parentElement;
// se poate și așa
// const headerParent = header?.parentNode;
console.log(headerParent); // afișăm elementul părinte în consolă
</script>
</body>
</html>
Aici afișăm în consolă elementul în care este plasat elementul cu id="header".
Este important de menționat că, deși ambele metode returnează în principiu același element, există o excepție - elementul <html>. Pentru acesta, nodul părinte va fi obiectul document, iar elementul părinte nu va exista (va fi null):
const htmlEl = document.getElementsByTagName("html")[0];
const parentElem = htmlEl.parentElement;
const parentNode = htmlEl.parentNode;
console.log(parentElem); // null
console.log(parentNode); // obiectul document
Obținerea elementelor copil
Metoda hasChildNodes() returnează true dacă elementul conține noduri înglobate:
const article = document.querySelector("div");
if (article.hasChildNodes()) {
console.log("Există noduri copil");
} else {
console.log("Niciun nod copil");
}
Pentru a obține elementele copil, se poate utiliza proprietatea children:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>FDC.COM</title>
</head>
<body>
<div id="article">
<h1 id="header">Home Page</h1>
<p>Page Text</p>
</div>
<script>
// selectăm elementul cu id-ul "article"
const article = document.getElementById("article");
for (elem of article.children) {
console.log(elem);
}
</script>
</body>
</html>
Aici, se obține elementul cu id-ul "article" și se parcurg într-un ciclu toate elementele sale copil. Acestea sunt două elemente:
<h1 id="header">Home Page</h1>
<p>Page Text</p>
Dacă dorim să selectăm absolut toate nodurile copil (nu doar elementele, ci și atributele și textul), se folosește metoda childNodes:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>FDC.COM</title>
</head>
<body>
<div id="article">
<h1 id="header">Home Page</h1>
<p>Page Text</p>
</div>
<script>
// selectăm elementul cu id-ul "article"
const article = document.getElementById("article");
for (node of article.childNodes) {
let type = "";
if (node.nodeType === 1) type = "element";
else if (node.nodeType === 2) type = "atribut";
else if (node.nodeType === 3) type = "text";
console.log(node.nodeName, ": ", type);
}
</script>
</body>
</html>
Aici selectăm același element, dar acum parcurgem nodurile sale. Alegem elementul div cu clasa article și trecem prin nodurile sale copil într-un ciclu. În cadrul ciclului, afișăm numele nodului și tipul său folosind proprietățile nodeName și nodeType.
Și, chiar dacă în blocul div#article există doar două elemente: un titlu h1 și un paragraf, consola ne va afișa cinci noduri.
#text : text
H1 : element
#text : text
P : element
#text : text
Acest lucru se datorează faptului că spațiile între noduri sunt, de asemenea, considerate ca fiind noduri de text separate. Dacă nu ar fi fost spații, rezultatul ar fi fost diferit.
<div id="article"><h1 id="header">Home Page</h1><p>Page Text</p></div>
Deci, dacă am parcurge nodurile, am descoperi doar două noduri copil, așa cum era de așteptat.
În plus, pentru a obține primul și ultimul nod/element, se utilizează proprietățile firstChild/firstElementChild și lastChild/lastElementChild, respectiv.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>FDC.COM</title>
</head>
<body>
<div id="article">
<h1 id="header">Home Page</h1>
<p>Page Text</p>
</div>
<script>
const article = document.getElementById("article");
console.log("First Child:", article.firstElementChild);
console.log("Last Child:", article.lastElementChild);
</script>
</body>
</html>
Afișarea în consolă:
Primul Copil: `<h1 id="header">Home Page</h1>`
Ultimul Copil: `<p>Textul Paginii</p>`
Numărul de elemente
Pentru a obține numărul de elemente copil, se poate folosi proprietatea childElementCount. Această valoare va fi echivalentă cu valoarea children.length:
const article = document.getElementById("article");
console.log(article.childElementCount); // 2
console.log(article.children.length); // 2
Obținerea elementelor de același nivel
Proprietățile previousSibling/previousElementSibling și nextSibling/nextElementSibling permit obținerea elementelor anterioare și ulterioare, care se află la același nivel cu elementul curent. De exemplu:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>FDC.COM</title>
</head>
<body>
<div id="article">
<h1 id="header">Home Page</h1>
<p>Page Text 1</p>
<p>Page Text 2</p>
<p>Page Text 3</p>
</div>
<script>
const article = document.getElementById("article");
let tempNode = article.firstElementChild;
while(tempNode != null){
console.log(tempNode);
tempNode = tempNode.nextElementSibling
}
</script>
</body>
</html>
Aici, obținem din nou elementul cu id="article". Apoi, capturăm primul său element în variabila tempNode și, într-un ciclu, atât timp cât tempNode nu este egal cu null, afișăm valoarea sa în consolă și apoi atribuim acestei variabile următorul element de același nivel (elementul adiacent):
tempNode = tempNode.nextElementSibling;
Astfel, parcurgem toate elementele de același nivel. Afișarea în consolă:
<h1 id="header">Home Page</h1>
<p>Page Text 1</p>
<p>Page Text 2</p>
<p>Page Text 3</p>
De asemenea, este posibil să parcurgem nodurile în ordine inversă: mai întâi obținem ultimul nod, apoi ne referim la nodul anterior de același nivel (sora anterioară a nodului):
const article = document.getElementById("article");
let tempNode = article.lastElementChild;
while(tempNode != null){
console.log(tempNode);
tempNode = tempNode.previousElementSibling;
}
nodeValue și obținerea conținutului text
Proprietatea nodeValue permite obținerea conținutului unui nod text, adică textul său. De exemplu:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>FDC.COM</title>
</head>
<body>
<div id="article">
<h1 id="header">Home Page</h1>
<p id="text">Textul Paginii</p>
</div>
<script>
// obținem elementul cu id="text"
const pageText = document.getElementById("text");
console.log(pageText.nodeValue); // null
for(textNode of pageText.childNodes){
console.log(textNode.nodeValue);
}
</script>
</body>
</html>
În acest caz, încercăm să obținem textul elementului cu id="text". Mai întâi obținem acest element în constanta pageText. Cu toate acestea, nu putem apela direct proprietatea nodeValue pe acest element. Dacă o facem, vom obține null:
console.log(pageText.nodeValue); // null
Acest lucru se datorează faptului că elementul obținut de noi nu este un nod text. Nodul text este situat în interiorul elementului pageText. Pentru a obține textul, trebuie să ne adresăm acestui nod text prin colecția childNodes:
for(textNode of pageText.childNodes){
console.log(textNode.nodeValue);
}
Deși putem obține astfel conținutul text al elementelor, nu este cea mai optimă metodă, iar mai departe vom examina alte moduri.