Vlastnosti navigace DOM jsou skvělé, když jsou prvky blízko sebe. Co když nejsou? Jak získat libovolný prvek stránky?
K tomu existují další metody vyhledávání.
document.getElementById nebo jen id
Pokud má prvek id
atribut, můžeme prvek získat pomocí metody document.getElementById(id)
, bez ohledu na to, kde to je.
Například:
<div id="elem">
<div id="elem-content">Element</div>
</div>
<script>
// get the element
let elem = document.getElementById('elem');
// make its background red
elem.style.background = 'red';
</script>
Existuje také globální proměnná pojmenovaná id
který odkazuje na prvek:
<div id="elem">
<div id="elem-content">Element</div>
</div>
<script>
// elem is a reference to DOM-element with id="elem"
elem.style.background = 'red';
// id="elem-content" has a hyphen inside, so it can't be a variable name
// ...but we can access it using square brackets: window['elem-content']
</script>
…Pokud nedeklarujeme proměnnou JavaScriptu se stejným názvem, pak má přednost:
<div id="elem"></div>
<script>
let elem = 5; // now elem is 5, not a reference to <div id="elem">
alert(elem); // 5
</script>
Pro přístup k prvkům nepoužívejte globální proměnné s názvem id Toto chování je popsáno ve specifikaci, jde tedy o jakýsi standard. Ale je podporován hlavně kvůli kompatibilitě.
Prohlížeč se nám snaží pomoci smícháním jmenných prostorů JS a DOM. To je v pořádku pro jednoduché skripty vložené do HTML, ale obecně to není dobrá věc. Může docházet ke konfliktům pojmenování. Když člověk čte kód JS a nemá v zobrazení HTML, není zřejmé, odkud proměnná pochází.
Zde v tutoriálu používáme id
přímo odkazovat na prvek kvůli stručnosti, když je zřejmé, odkud prvek pochází.
V reálném životě document.getElementById
je preferovanou metodou.
id
musí být jedinečný
id
musí být jedinečný. V dokumentu může být pouze jeden prvek s daným id
.
Pokud existuje více prvků se stejným id
, pak je chování metod, které jej používají, nepředvídatelné, kupř. document.getElementById
může náhodně vrátit kterýkoli z těchto prvků. Držte se prosím pravidla a dodržujte id
jedinečný.
document.getElementById
, nikoli anyElem.getElementById
Metoda getElementById
lze volat pouze na document
objekt. Hledá daný id
v celém dokumentu.
querySelectorAll
Zdaleka nejuniverzálnější metoda, elem.querySelectorAll(css)
vrátí všechny prvky uvnitř elem
odpovídající danému selektoru CSS.
Zde hledáme všechny <li>
prvky, které jsou posledními potomky:
<ul>
<li>The</li>
<li>test</li>
</ul>
<ul>
<li>has</li>
<li>passed</li>
</ul>
<script>
let elements = document.querySelectorAll('ul > li:last-child');
for (let elem of elements) {
alert(elem.innerHTML); // "test", "passed"
}
</script>
Tato metoda je skutečně výkonná, protože lze použít jakýkoli selektor CSS.
Může také používat pseudotřídy
Pseudotřídy v selektoru CSS jako :hover
a :active
jsou také podporovány. Například document.querySelectorAll(':hover')
vrátí kolekci s prvky, nad kterými je ukazatel nyní (v pořadí vnoření:od nejvzdálenějšího <html>
k nejvíce vnořenému).
querySelector
Volání na elem.querySelector(css)
vrátí první prvek pro daný selektor CSS.
Jinými slovy, výsledek je stejný jako elem.querySelectorAll(css)[0]
, ale druhý hledá všechny prvků a vybrat jeden, zatímco elem.querySelector
jen hledá jednu. Psaní je tedy rychlejší a také kratší.
odpovídá
Předchozí metody prohledávaly DOM.
elem.matches(css) nic nehledá, pouze kontroluje, zda elem
odpovídá danému CSS-selektoru. Vrací true
nebo false
.
Tato metoda se hodí, když iterujeme prvky (jako pole nebo tak něco) a snažíme se odfiltrovat ty, které nás zajímají.
Například:
<a href="http://example.com/file.zip">...</a>
<a href="http://ya.ru">...</a>
<script>
// can be any collection instead of document.body.children
for (let elem of document.body.children) {
if (elem.matches('a[href$="zip"]')) {
alert("The archive reference: " + elem.href );
}
}
</script>
nejbližší
Předkové prvku jsou:rodič, rodič rodiče, jeho rodič a tak dále. Předkové společně tvoří řetězec rodičů od živlu až po vrchol.
Metoda elem.closest(css)
hledá nejbližšího předka, který odpovídá selektoru CSS. elem
sám je také zahrnut do vyhledávání.
Jinými slovy, metoda closest
zvedne se od živlu a zkontroluje každého z rodičů. Pokud odpovídá selektoru, hledání se zastaví a vrátí se předchůdce.
Například:
<h1>Contents</h1>
<div class="contents">
<ul class="book">
<li class="chapter">Chapter 1</li>
<li class="chapter">Chapter 2</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 (because h1 is not an ancestor)
</script>
getElementsBy*
Existují také další metody, jak hledat uzly podle značky, třídy atd.
Dnes jsou většinou historií, jako querySelector
je výkonnější a kratší pro zápis.
Zde je tedy uvádíme hlavně pro úplnost, zatímco stále je můžete najít ve starých skriptech.
elem.getElementsByTagName(tag)
vyhledá prvky s danou značkou a vrátí jejich kolekci.tag
parametr může být také hvězdička"*"
pro „libovolné značky“.elem.getElementsByClassName(className)
vrátí prvky, které mají danou CSS třídu.document.getElementsByName(name)
vrátí prvky s danýmname
atribut, celý dokument. Velmi zřídka používané.
Například:
// get all divs in the document
let divs = document.getElementsByTagName('div');
Pojďme najít všechny input
tagy uvnitř tabulky:
<table id="table">
<tr>
<td>Your age:</td>
<td>
<label>
<input type="radio" name="age" value="young" checked> less than 18
</label>
<label>
<input type="radio" name="age" value="mature"> from 18 to 50
</label>
<label>
<input type="radio" name="age" value="senior"> more than 60
</label>
</td>
</tr>
</table>
<script>
let inputs = table.getElementsByTagName('input');
for (let input of inputs) {
alert( input.value + ': ' + input.checked );
}
</script>
Nezapomeňte na "s"
dopis!
Začínající vývojáři někdy zapomínají na písmeno "s"
. To znamená, že se snaží zavolat getElementByTagName
místo getElementsByTagName
.
"s"
písmeno v getElementById
chybí , protože vrací jeden prvek. Ale getElementsByTagName
vrací kolekci prvků, takže je zde "s"
uvnitř.
Další rozšířenou chybou začátečníků je psát:
// doesn't work
document.getElementsByTagName('input').value = 5;
To nebude fungovat, protože to vyžaduje sbírku vstupů a přiřadí hodnotu jemu spíše než prvkům v něm.
Měli bychom buď iterovat kolekci, nebo získat prvek podle jeho indexu a poté přiřadit takto:
// should work (if there's an input)
document.getElementsByTagName('input')[0].value = 5;
Hledám .article
prvky:
<form name="my-form">
<div class="article">Article</div>
<div class="long article">Long article</div>
</form>
<script>
// find by name attribute
let form = document.getElementsByName('my-form')[0];
// find by class inside the form
let articles = form.getElementsByClassName('article');
alert(articles.length); // 2, found two elements with class "article"
</script>
Živé sbírky
Všechny metody "getElementsBy*"
vrátit živý sbírka. Takové kolekce vždy odrážejí aktuální stav dokumentu a „automaticky se aktualizují“, když se změní.
V níže uvedeném příkladu jsou dva skripty.
- První vytvoří odkaz na kolekci
<div>
. Nyní je jeho délka1
. - Druhé skripty se spustí poté, co prohlížeč splňuje ještě jeden
<div>
, takže jeho délka je2
.
<div>First div</div>
<script>
let divs = document.getElementsByTagName('div');
alert(divs.length); // 1
</script>
<div>Second div</div>
<script>
alert(divs.length); // 2
</script>
Naproti tomu querySelectorAll
vrátí statický sbírka. Je to jako pevné pole prvků.
Pokud jej místo toho použijeme, pak oba skripty vydají 1
:
<div>First div</div>
<script>
let divs = document.querySelectorAll('div');
alert(divs.length); // 1
</script>
<div>Second div</div>
<script>
alert(divs.length); // 1
</script>
Nyní snadno vidíme rozdíl. Po objevení nového div
se statická kolekce nezvýšila v dokumentu.
Shrnutí
Existuje 6 hlavních metod hledání uzlů v DOM:
Metoda | Vyhledává podle... | Lze volat na prvek? | Žít? |
querySelector | Výběr CSS | ✔ | - |
querySelectorAll | Výběr CSS | ✔ | - |
getElementById | id | - | - |
getElementsByName | name | - | ✔ |
getElementsByTagName | tag nebo '*' | ✔ | ✔ |
getElementsByClassName | třída | ✔ | ✔ |
Zdaleka nejpoužívanější jsou querySelector
a querySelectorAll
, ale getElement(s)By*
mohou být sporadicky užitečné nebo je lze nalézt ve starých skriptech.
Kromě toho:
- Je zde
elem.matches(css)
zkontrolujte, zdaelem
odpovídá danému selektoru CSS. - Je zde
elem.closest(css)
hledat nejbližšího předka, který odpovídá danému CSS-selektoru.elem
sám je také zkontrolován.
A zmiňme zde ještě jednu metodu, jak ověřit vztah dítě-rodič, protože je někdy užitečná:
elemA.contains(elemB)
vrátí hodnotu true, pokudelemB
je uvnitřelemA
(potomekelemA
) nebo kdyželemA==elemB
.