DOM navigatsiya xususiyatlari elementlar bir-biriga yaqin bo’lganda ajoyib. Agar ular yaqin bo’lmasa-chi? Sahifaning ixtiyoriy elementini qanday olish mumkin?
Buning uchun qo’shimcha qidirish metodlari mavjud.
document.getElementById yoki shunchaki id
Agar elementda id atributi bo’lsa, uni qayerda joylashganidan qat’i nazar document.getElementById(id) metodidan foydalanib olishimiz mumkin.
Masalan:
<div id="elem">
<div id="elem-content">Element</div>
</div>
<script>
// elementni olish
let elem = document.getElementById('elem');
// uning fonini qizil qilish
elem.style.background = 'red';
</script>
Shuningdek, id nomi bilan global o’zgaruvchi mavjud bo’lib, u elementga havola qiladi:
<div id="elem">
<div id="elem-content">Element</div>
</div>
<script>
// elem - bu id="elem" bilan DOM-elementga havola
elem.style.background = 'red';
// id="elem-content" ichida defis bor, shuning uchun o'zgaruvchi nomi bo'la olmaydi
// ...lekin uni kvadrat qavslar yordamida olishimiz mumkin: window['elem-content']
</script>
…Bu xuddi shu nom bilan JavaScript o’zgaruvchisini e’lon qilmasagimizgina, aks holda u ustunlik qiladi:
<div id="elem"></div>
<script>
let elem = 5; // endi elem 5 ga teng, <div id="elem"> ga havola emas
alert(elem); // 5
</script>
Bu xatti-harakat spetsifikatsiyada tasvirlangan, shuning uchun bu standart hisoblanadi. Lekin u asosan muvofiqlik uchun qo’llab-quvvatlanadi.
Brauzer JS va DOM nomlar maydonlarini aralashtirish orqali bizga yordam berishga harakat qiladi. Bu HTML ga kiritilgan oddiy skriptlar uchun yaxshi, lekin umuman yaxshi narsa emas. Nom to’qnashuvi bo’lishi mumkin. Bundan tashqari, kimdir JS kodini o’qiganda va HTML ko’rinishda bo’lmasa, o’zgaruvchi qayerdan kelganini bilish qiyin.
Bu qo’llanmada biz qisqalik uchun element qayerdan kelgani aniq bo’lganda id dan bevosita foydalanish uchun ishlatamiz.
Haqiqiy hayotda document.getElementById afzal qilingan metod hisoblanadi.
id noyob bo’lishi kerakid noyob bo’lishi kerak. Hujjatda berilgan id bilan faqat bitta element bo’lishi mumkin.
Agar bir xil id bilan bir nechta elementlar bo’lsa, unda undan foydalanadigan metodlarning xatti-harakati oldindan aytib bo’lmaydi, masalan document.getElementById bunday elementlardan istalganini tasodifiy qaytarishi mumkin. Shuning uchun qoidaga rioya qiling va id ni noyob saqlang.
document.getElementById, anyElem.getElementById emasgetElementById metodi faqat document obyektida chaqirilishi mumkin. U berilgan id ni butun hujjatda qidiradi.
querySelectorAll {#querySelectorAll}
Hozirgacha eng ko’p qirrali metod elem.querySelectorAll(css) berilgan CSS selektoriga mos keladigan elem ichidagi barcha elementlarni qaytaradi.
Bu yerda oxirgi bola bo’lgan barcha <li> elementlarni qidiramiz:
<ul>
<li>Bu</li>
<li>test</li>
</ul>
<ul>
<li>muvaffaqiyatli</li>
<li>o'tdi</li>
</ul>
<script>
let elements = document.querySelectorAll('ul > li:last-child');
for (let elem of elements) {
alert(elem.innerHTML); // "test", "o'tdi"
}
</script>
Bu metod haqiqatan ham kuchli, chunki har qanday CSS selektordan foydalanish mumkin.
CSS selektordagi :hover va :active kabi pseudo-klasslar ham qo’llab-quvvatlanadi. Masalan, document.querySelectorAll(':hover') hozir kursor ustida turgan elementlar to’plamini qaytaradi (ichma-ich tartibda: eng tashqi <html> dan eng ichki gacha).
querySelector {#querySelector}
elem.querySelector(css) chaqiruvi berilgan CSS selektor uchun birinchi elementni qaytaradi.
Boshqacha qilib aytganda, natija elem.querySelectorAll(css)[0] bilan bir xil, lekin ikkinchisi barcha elementlarni qidirib, birini tanlaydi, elem.querySelector esa faqat birini qidiradi. Shuning uchun u tezroq va yozish uchun qisqaroq.
matches
Oldingi metodlar DOM ni qidirardi.
elem.matches(css) hech narsani qidirmaydi, u shunchaki elem berilgan CSS-selektorga mos kelishini tekshiradi. U true yoki false qaytaradi.
Bu metod elementlar ustida takrorlash (massivdagi kabi yoki boshqa narsa) va bizni qiziqtiradigan narsalarni filtrlashga harakat qilganda foydali bo’ladi.
Masalan:
<a href="http://example.com/file.zip">...</a>
<a href="http://ya.ru">...</a>
<script>
// document.body.children o'rniga har qanday to'plam bo'lishi mumkin
for (let elem of document.body.children) {
if (elem.matches('a[href$="zip"]')) {
alert("Arxiv havolasi: " + elem.href );
}
}
</script>
closest
Elementning ajdodlari bu: ota-ona, ota-onaning ota-onasi, uning ota-onasi va hokazo. Ajdodlar birga elementdan tepaga qadar ota-onalar zanjirini tashkil qiladi.
elem.closest(css) metodi CSS-selektorga mos keladigan eng yaqin ajdodni qidiradi. elem ning o’zi ham qidiruvga kiritiladi.
Boshqacha qilib aytganda, closest metodi elementdan yuqoriga chiqadi va har bir ota-onani tekshiradi. Agar u selektorga mos kelsa, qidiruv to’xtaydi va ajdod qaytariladi.
Masalan:
<h1>Mundarija</h1>
<div class="contents">
<ul class="book">
<li class="chapter">1-bob</li>
<li class="chapter">2-bob</li>
</ul>
</div>
<script>
let chapter = document.querySelector('.chapter'); // LI
alert(chapter.closest('.book')); // UL
alert(chapter.closest('.contents')); // DIV
alert(chapter.closest('h1')); // null (chunki h1 ajdod emas)
</script>
getElementsBy*
Teg, klass va hokazo bo’yicha tugunlarni qidirish uchun boshqa metodlar ham mavjud.
Bugungi kunda ular asosan tarix, chunki querySelector kuchliroq va yozish uchun qisqaroq.
Shuning uchun biz ularni asosan to’liqlik uchun yoritamiz, garchi eski skriptlarda ularni hali ham topishingiz mumkin.
elem.getElementsByTagName(tag)berilgan teg bilan elementlarni qidiradi va ularning to’plamini qaytaradi.tagparametri “har qanday teglar” uchun yulduzcha"*"ham bo’lishi mumkin.elem.getElementsByClassName(className)berilgan CSS klassiga ega elementlarni qaytaradi.document.getElementsByName(name)berilgannameatributiga ega elementlarni hujjat bo’ylab qaytaradi. Juda kamdan-kam qo’llaniladi.
Masalan:
// hujjatdagi barcha divlarni olish
let divs = document.getElementsByTagName('div');
Jadval ichidagi barcha input teglarini topaylik:
<table id="table">
<tr>
<td>Yoshingiz:</td>
<td>
<label>
<input type="radio" name="age" value="young" checked> 18 dan kichik
</label>
<label>
<input type="radio" name="age" value="mature"> 18 dan 50 gacha
</label>
<label>
<input type="radio" name="age" value="senior"> 60 dan katta
</label>
</td>
</tr>
</table>
<script>
let inputs = table.getElementsByTagName('input');
for (let input of inputs) {
alert( input.value + ': ' + input.checked );
}
</script>
"s" harfini unutmang!Yangi boshlovchi dasturchilar ba’zan "s" harfini unutadilar. Ya’ni ular getElementsByTagName o’rniga getElementByTagName ni chaqirishga harakat qiladi.
getElementById da "s" harfi yo’q, chunki u bitta elementni qaytaradi. Lekin getElementsByTagName elementlar to’plamini qaytaradi, shuning uchun ichida "s" bor.
Yana bir keng tarqalgan yangi boshlovchi xatosi:
// ishlamaydi
document.getElementsByTagName('input').value = 5;
Bu ishlamaydi, chunki u inputlar to’plamini oladi va qiymatni uning ichidagi elementlarga emas, balki unga tayinlaydi.
Biz yo’ki to’plam ustida takrorlashimiz yoki elementni indeksi orqali olib, keyin quyidagicha tayinlashimiz kerak:
// ishlashi kerak (agar input bo'lsa)
document.getElementsByTagName('input')[0].value = 5;
.article elementlarini qidirish:
<form name="my-form">
<div class="article">Maqola</div>
<div class="long article">Uzun maqola</div>
</form>
<script>
// name atributi bo'yicha topish
let form = document.getElementsByName('my-form')[0];
// forma ichida klass bo'yicha topish
let articles = form.getElementsByClassName('article');
alert(articles.length); // 2, "article" klassiga ega ikkita element topildi
</script>
Jonli to’plamlar
Barcha "getElementsBy*" metodlari jonli to’plamni qaytaradi. Bunday to’plamlar har doim hujjatning joriy holatini aks ettiradi va u o’zgarganda “avtomatik yangilanadi”.
Quyidagi misolda ikkita skript mavjud.
- Birinchisi
<div>to’plamiga havola yaratadi. Hozircha uning uzunligi1. - Ikkinchi skript brauzer yana bitta
<div>ni uchratgandan keyin ishlaydi, shuning uchun uning uzunligi2.
<div>Birinchi div</div>
<script>
let divs = document.getElementsByTagName('div');
alert(divs.length); // 1
</script>
<div>Ikkinchi div</div>
<script>
alert(divs.length); // 2
</script>
Aksincha, querySelectorAll statik to’plamni qaytaradi. Bu elementlarning qat’iy massiviga o’xshaydi.
Agar uni o’rniga ishlatilsa, ikkala skript ham 1 ni chiqaradi:
<div>Birinchi div</div>
<script>
let divs = document.querySelectorAll('div');
alert(divs.length); // 1
</script>
<div>Ikkinchi div</div>
<script>
alert(divs.length); // 1
</script>
Endi biz farqni osongina ko’rishimiz mumkin. Statik to’plam hujjatda yangi div paydo bo’lgandan keyin ko’paymadi.
Xulosa
DOM da tugunlarni qidirish uchun 6 ta asosiy metod mavjud:
| Metod | Nima bo'yicha qidiradi... | Elementda chaqirish mumkinmi? | Jonlimi? |
querySelector |
CSS-selektor | ✔ | - |
querySelectorAll |
CSS-selektor | ✔ | - |
getElementById |
id |
- | - |
getElementsByName |
name |
- | ✔ |
getElementsByTagName |
teg yoki '*' |
✔ | ✔ |
getElementsByClassName |
klass | ✔ | ✔ |
Eng ko’p ishlatiladiganlari querySelector va querySelectorAll, lekin getElement(s)By* vaqti-vaqti bilan foydali bo’lishi yoki eski skriptlarda topilishi mumkin.
Bundan tashqari:
elem.matches(css)elemberilgan CSS selektoriga mos kelishini tekshirish uchun mavjud.elem.closest(css)berilgan CSS-selektorga mos keladigan eng yaqin ajdodni qidirish uchun mavjud.elemning o’zi ham tekshiriladi.
Va bu yerda bola-ota-ona munosabatini tekshirish uchun yana bir metoddan gaplashaylik, chunki u ba’zan foydali bo’ladi:
elemA.contains(elemB)agarelemBelemAichida bo’lsa (elemAning avlodi) yokielemA==elemBbo’lsatrueqaytaradi.
Izohlar
<code>yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)