Hujjat (DOM)

DOM bo'ylab harakatlanish

DOM bizga har qanday element va uning mazmuni bilan istalgan narsani qilishga imkon beradi. Ammo avval kerakli DOM obyektiga yetib borishimiz kerak. DOM ustidagi barcha amallar document obyektidan boshlanadi โ€” u asosiy "kirish nuqtasi". Undan istalgan tugunga yetib borishimiz mumkin. Ushbu darsda tugunlar orasida qanday harakatlanishni chuqur o'rganamiz.

Eng yuqoridagi tugunlar: html, body, head

Eng ustki daraxt tugunlari document obyektining maxsus xossalari sifatida to'g'ridan-to'g'ri mavjud:

// eng yuqori tugunlarga to'g'ridan-to'g'ri murojaat
alert(document.documentElement); // <html>
alert(document.body);            // <body>
alert(document.head);            // <head>
document.body null bo'lishi mumkin! Skript <head> ichida turgan bo'lsa, brauzer hali <body>ni o'qimagan bo'ladi, shu sababli u yerda document.body qiymati null bo'ladi. DOM'da mavjud bo'lmagan narsaga murojaat qilib bo'lmaydi. Shuning uchun DOM bilan ishlaydigan skriptlar odatda </body>dan oldin yoki hujjat yuklangach ishga tushiriladi.
<html>
<head>
  <script>
    alert('HEAD ichidan: ' + document.body); // null, hali body yo'q
  </script>
</head>
<body>
  <script>
    alert('BODY ichidan: ' + document.body); // <body>, endi mavjud
  </script>
</body>
</html>

Bolalar: childNodes, firstChild, lastChild

Endi ikkita atamani ajratamiz:

childNodes to'plami barcha bola tugunlarni, jumladan matn tugunlarini ro'yxatlaydi:

<html>
<body>
  <div>Boshi</div>
  <ul>
    <li>Ma'lumot</li>
  </ul>
  <div>Oxiri</div>

  <script>
    for (let i = 0; i < document.body.childNodes.length; i++) {
      alert( document.body.childNodes[i] );
      // matn, DIV, matn, UL, ..., matn, SCRIPT
    }
  </script>
</body>
</html>
E'tibor bering: yuqoridagi ro'yxatda <script> ham bor. Chunki skript document.body mazmunini o'qiganda, brauzer hali skriptdan keyingi narsalarni ko'rmagan bo'ladi. Shu sababli childNodes ro'yxati faqat skriptgacha bo'lgan tugunlarni oladi.

firstChild va lastChild xossalari birinchi va oxirgi bolalar tuguniga tez kirish beradi:

// quyidagilar bir-biriga teng
elem.childNodes[0] === elem.firstChild;
elem.childNodes[elem.childNodes.length - 1] === elem.lastChild;

Bolalar bor-yo'qligini tekshirish uchun maxsus funksiya bor โ€” hasChildNodes():

if (elem.hasChildNodes()) {
  // elementning bola tugunlari bor
}

DOM to'plamlari (collections)

childNodes oddiy massiv (array) EMAS, balki maxsus, massivga o'xshash iteratsiyalanuvchi obyekt โ€” NodeList deb ataladi. Bundan ikkita muhim natija chiqadi:

  1. Uni for..of bilan aylantirishimiz mumkin, chunki u iteratsiyalanuvchi;
  2. Ammo massiv metodlari (filter, map va h.k.) unda mavjud emas, chunki u haqiqiy massiv emas.
for (let node of document.body.childNodes) {
  alert(node); // to'plamdagi barcha tugunlarni ko'rsatadi
}

Agar massiv metodlari kerak bo'lsa, uni haqiqiy massivga aylantirishimiz mumkin:

alert( Array.from(document.body.childNodes).filter ); // function
DOM to'plamlari faqat o'qish uchun (read-only)! Biz childNodes[i] = ... deb tugunni almashtira olmaymiz. Element bolalarini o'zgartirish uchun boshqa maxsus metodlar kerak (ular keyingi darslarda).
DOM to'plamlarining aksariyati jonli (live). Ya'ni ular hujjatning joriy holatini aks ettiradi. Agar biz havolani (referens) saqlab, keyin DOM'ga yangi element qo'shsak, u avtomatik ravishda to'plamda paydo bo'ladi.
To'plamlarni aylantirish uchun for..in siklidan FOYDALANMANG! for..in obyektning barcha sanaladigan (enumerable) xossalarini aylanadi, bu esa to'plamda ortiqcha "texnik" maydonlarni (length, item va h.k.) ham qamrab oladi. Buning o'rniga for..of ishlating.

Qo'shnilar va ota (siblings, parent)

Qo'shnilar (siblings) โ€” bir xil otaga ega tugunlar. Masalan, <head> va <body> โ€” qo'shni, chunki ularning otasi <html>.

// <body> uchun "ota" โ€” <html>
alert( document.body.parentNode === document.documentElement ); // true

// <head>dan keyin โ€” <body>
alert( document.head.nextSibling ); // HTMLBodyElement

// <body>dan oldin โ€” <head>
alert( document.body.previousSibling ); // HTMLHeadElement

Faqat elementlar bo'yicha navigatsiya

Yuqoridagi childNodes, firstChild, lastChild, nextSibling, previousSibling, parentNode xossalari barcha tugunlarni oladi โ€” matn tugunlari, izohlar ham. Ammo ko'p vazifalarda bizga faqat element tugunlari โ€” teglar kerak bo'ladi.

Shuning uchun ularning "faqat elementlar bo'yicha" versiyalari bor:

for (let elem of document.body.children) {
  alert(elem); // DIV, UL, DIV, SCRIPT โ€” faqat elementlar
  // matn tugunlari e'tiborga olinmaydi
}

parentNode va parentElement deyarli bir xil, bitta nozik farq bilan. "Ota" element bo'lmasligi mumkin bo'lgan yagona holat โ€” bu document.documentElement (<html>):

alert( document.documentElement.parentNode ); // document
alert( document.documentElement.parentElement ); // null

Chunki <html>ning otasi โ€” document, lekin document element emas. Shu sababli parentElement bu holda null beradi. Bu farq ba'zan elementdan yuqoriga <html>gacha ko'tarilishda foydali:

while (elem = elem.parentElement) {
  // yuqoriga ko'tarilamiz, <html> dan yuqoriga chiqmaymiz
  alert( elem );
}

Jadvallar bilan navigatsiya

Ba'zi element turlari qo'shimcha, maxsus navigatsiya xossalarini beradi. Jadvallar bunga eng yaxshi misol โ€” ular juda muhim va tez-tez ishlatiladigan qulayliklarni taqdim etadi.

<table> elementi quyidagilarni qo'llab-quvvatlaydi:

<thead>, <tfoot>, <tbody> elementlari rows xossasini beradi:

<tr> (qator) uchun:

<td> va <th> (katak) uchun:

Misol โ€” jadvalning ikkinchi qatoridagi birinchi katak mazmunini o'qiymiz:

<table id="table">
  <tr>
    <td>bir</td><td>ikki</td>
  </tr>
  <tr>
    <td>uch</td><td>to'rt</td>
  </tr>
</table>

<script>
  // 'uch' matnini oladi (2-qator, 1-katak)
  let td = table.rows[1].cells[0];
  alert( td.textContent ); // uch
</script>
Bu maxsus jadval xossalari childNodes orqali qo'lda o'tishdan ancha qulay va ishonchli. Chunki brauzer avtomatik qo'shgan <tbody> kabi nozikliklarni ular o'zi hisobga oladi.
Boshqa elementlar uchun ham maxsus navigatsiya xossalari bor: masalan, formalar (<form>) va ularning elementlari. Ular bilan formalarga bag'ishlangan bo'limda tanishamiz.

Xulosa