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:
<html>=document.documentElementโ eng ildiz hujjat tuguni;<body>=document.bodyโ sahifa tanasi;<head>=document.headโ sahifa boshi.
// 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:
- Bola tugunlar (child nodes yoki children) โ bevosita ichma-ich joylashgan tugunlar. Masalan,
<head>va<body><html>ning bolalaridir; - Avlodlar (descendants) โ barcha ichma-ich joylashgan tugunlar, jumladan bolalar, ularning bolalari va hokazo โ butun daraxt shohobchasi.
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>
<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:
- Uni
for..ofbilan aylantirishimiz mumkin, chunki u iteratsiyalanuvchi; - Ammo massiv metodlari (
filter,mapva 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
childNodes[i] = ... deb tugunni almashtira olmaymiz. Element bolalarini o'zgartirish uchun boshqa maxsus metodlar kerak (ular keyingi darslarda).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>.
nextSiblingโ keyingi qo'shni tugun;previousSiblingโ oldingi qo'shni tugun;parentNodeโ ota tugun.
// <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:
childrenโ faqat element bola tugunlar;firstElementChild,lastElementChildโ birinchi va oxirgi bola elementlar;previousElementSibling,nextElementSiblingโ qo'shni elementlar;parentElementโ ota element.
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:
table.rowsโ jadvaldagi barcha<tr>lar to'plami;table.caption / table.tHead / table.tFootโ mos ravishda<caption>,<thead>,<tfoot>elementlariga havola;table.tBodiesโ<tbody>lar to'plami (spetsifikatsiyaga ko'ra kamida bittasi bo'ladi).
<thead>, <tfoot>, <tbody> elementlari rows xossasini beradi:
tbody.rowsโ ichidagi<tr>lar to'plami.
<tr> (qator) uchun:
tr.cellsโ berilgan qatordagi<td>va<th>kataklari to'plami;tr.sectionRowIndexโ qatorning o'z<thead>/<tbody>/<tfoot>ichidagi tartib raqami;tr.rowIndexโ qatorning butun<table>ichidagi tartib raqami.
<td> va <th> (katak) uchun:
td.cellIndexโ katakning o'z<tr>si ichidagi tartib raqami.
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>
childNodes orqali qo'lda o'tishdan ancha qulay va ishonchli. Chunki brauzer avtomatik qo'shgan <tbody> kabi nozikliklarni ular o'zi hisobga oladi.<form>) va ularning elementlari. Ular bilan formalarga bag'ishlangan bo'limda tanishamiz.Xulosa
- Berilgan tugundan biz uning bevosita qo'shnilari va bolalariga o'ta olamiz;
- Ikki xil to'plam bor: barcha tugunlar uchun (
childNodes,firstChild,lastChild,nextSibling,previousSibling,parentNode) va faqat elementlar uchun (children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling,parentElement); - DOM to'plamlari massivga o'xshash, iteratsiyalanuvchi (
for..of), aksariyati jonli (live) va faqat o'qish uchun; - Jadvallar kabi ba'zi elementlar qo'shimcha navigatsiya xossalarini beradi (
rows,cellsva h.k.).