Jak bylo už zmíněno, JavaScript umí přistupovat k HTML prvkům na stránce a měnit je. Jak to funguje?
Prohlížeč přečte HTML a zobrazí všechny tagy uživateli. Zároveň ale pro každý tag vytvoří i JavaScriptový objekt, se kterým můžeš pracovat ve svém programu. Pokud na něm uděláš jakékoliv změny, prohlížeč je okamžitě aplikuje i v tom, jak tag zobrazuje.
Tomuto systému se říká DOM, Document Object Model. Tato lekce tě naučí, jak s ním lze pracovat.
Vytvoř si HTML stránku s několika tagy a připojeným souborem dom.js:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>PyLadies</title>
<script src="dom.js"></script>
</head>
<body>
<h1>PyLadies</h1>
<p></p>
</body>
</html>
Náš první JavaScriptový program, který pracuje s DOMem, bude vypadat následovně:
function pridejText() {
var odstavce = document.getElementsByTagName('p');
var prvniOdstavec = odstavce[0];
prvniOdstavec.innerText = 'JavaScript je fajn!';
}
window.onload = pridejText;
V JavaScriptu je několik objektů, které máš k dispozici kdekoliv ve svém programu a proto se jim říká globální. Zpřístupňují určité věci z prohlížeče. S objektem window ses již setkala, ten představuje okno prohlížeče (nebo spíš prohlížeč jako takový). K tagům na stránce se můžeš dostat přes jiný globální objekt, document.
Jeho metoda getElementsByTagName() přijímá název tagu a vrátí pole všech tagů toho názvu, jaké najde na stránce. My víme, že máme na stránce jeden tag s názvem p, tak si z pole vytáhneme první prvek a změníme mu následně text, který obsahuje. To se dělá přiřazením do vlastnosti innerText.
Kód, který manipuluje s DOMem, je dobré spouštět až ve chvíli, kdy má prohlížeč celé HTML přečtené a všechny tagy zobrazené. Když se prohlížeč snaží zobrazit HTML stránku, čte totiž HTML tagy postupně, shora dolů. JavaScript připojujeme ke stránce dřív, než se na ní vyskytuje tag <p></p>, takže by se mohlo stát, že v době spuštění našeho programu ještě prohlížeč o žádném p nebude vědět. Potom by metoda getElementsByTagName('p') mohla vrátit prázdné pole a program by nefungoval.
Naštěstí lze tomuto předejít. Ve chvíli, kdy má prohlížeč celou stránku zpracovanou, spustí funkci, která bude přiřazená do vlastnosti window.onload. Toho je využito i v příkladu výše.
Když si načteme stránku, objeví se nadpis a odstavec s naším dynamicky doplněným textem.
JavaScript je fajn!
Když se podíváš do zdrojového kódu stránky (Ctrl + U, popřípadě Cmd + Alt + U), uvidíš stále své původní HTML, kde je <p></p> prázdné:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>PyLadies</title>
<script src="dom.js"></script>
</head>
<body>
<h1>PyLadies</h1>
<p></p>
</body>
</html>
Pokud bys chtěla vidět i změny, které provedl JavaScript, musíš si v prohlížeči otevřít vývojářské nástroje a přepnout se v menu na Elements.

Tuto metodu už sis vyzkoušela. Hodí se, pokud chceš nějakým způsobem upravit např. všechny prvky stejného typu na stránce. Vrací pole objektů pro všechny nalezené tagy.
<h1>O Popelce<h1>
<h2>Mluvila na zvířátka<h2>
<p>Doktor diagnostikoval samomluvu.</p>
<h2>Převlékala se za jiné lidi<h2>
<p>Podezření na mnohočetnou poruchu osobnosti.</p>
// vrátí objekty pro všechny <h2>
document.getElementsByTagName('h2');
Metoda vrací všechny tagy na stránce, které mají danou třídu.
<ul>
<li class="odd first">první</li>
<li class="even">druhý</li>
<li class="odd">třetí</li>
<li class="even">čtvrtý</li>
</ul>
// vrátí objekty pro první a třetí <li>
document.getElementsByClassName('odd');
Kromě tříd lze tagům přiřadit i tzv. ID, tedy nějaký identifikátor. Ten musí být v rámci jedné HTML stránky jedinečný, tedy dva prvky nesmí mít stejné ID.
Metoda, která hledá tagy podle ID, tedy nevrací pole, ale právě jeden výsledek.
<h1>O Popelce<h1>
<div id="kapitola-mluvila-na-zviratka">
<h2>Mluvila na zvířátka</h2>
<p>Doktor diagnostikoval samomluvu.</p>
</div>
<div id="kapitola-prevlekala-se-za-jine-lidi">
<h2>Převlékala se za jiné lidi<h2>
<p>Podezření na mnohočetnou poruchu osobnosti.</p>
</div>
// vrátí druhý tag <div>
var id = 'kapitola-prevlekala-se-za-jine-lidi';
document.getElementById(id);
Malá odbočka: atribut id se dá použít i pro odkazování na část stránky.
Odkaz v rámci jedné stránky na nadpis z příkladu výše by vypadal takto:
<a href="#kapitola-mluvila-na-zviratka">…</a>
Kdybychom odkazovali z jiné stránky a tato se jmenovala o-popelce.html, vypadalo by to takto.
<a href="o-popelce.html#kapitola-mluvila-na-zviratka">…</a>
Po otevření takového odkazu, prohlížeč odskroluje stránku tak, aby byl vidět začátek elementu s daným ID.
ID lze použít i v selektorech v CSS #nejake-id { color: red; }, ale má to spoustu nevýhod a proto to se tomu vyhni.
S těmito metodami můžeme použít na hledání tagů celý CSS selektor.
<h1 class="nadpis">O Popelce<h1>
<div>
<h2 class="nadpis">Mluvila na zvířátka</h2>
<p>Doktor diagnostikoval samomluvu.</p>
</div>
// vrátí objekt pro právě jeden tag, nadpis <h2>
document.querySelector('div .nadpis');
// vrátí objekt pro právě jeden tag, nadpis <h1>
document.querySelector('.nadpis');
// vrátí pole objektů, nadpisy <h1> a <h2>
document.querySelectorAll('.nadpis');
V JavaScriptu existují tzv. události (angl. event), na které může tvůj program čekat a když se stanou, může něco vykonat. Je to dobré na to, abys mohla stránku ovlivňovat i v jiný okamžik, než když se načte.
Už jsi se setkala s událostí window.onload. Vlastnost onload je ale jen taková zkratka. Standardně se s událostmi pracuje následovně:
function poNacteni() {
console.log('Načetla se stránka!');
}
window.addEventListener('load', poNacteni);
Tedy na objektu, u kterého chceš na událost číhat, použiješ metodu addEventListener() se dvěma parametry, a to názvem události a funkcí, která má událost obsloužit, když nastane. Zajímavější událost může vypadat takto:
<input type="submit" value="Klikni na mě">
function vystrasUzivatele() {
window.alert('Baf!');
}
function poNacteni() {
var cudlik = document.querySelector('input');
cudlik.addEventListener('click', vystrasUzivatele);
}
window.addEventListener('load', poNacteni);
Na stránce máš tlačítko. Samo o sobě nic nedělá, protože není ve formuláři. Pomocí JavaScriptu ale můžeme nastavit, že pokud na něj uživatel stránek klikne (událost click), spustí se tvoje funkce vystrasUzivatele(). Celý kód pak bylo opět potřeba spustit až ve chvíli, kdy na objektu window proběhne událost load.
Program, který je v předešlé sekci, by se dal zapsat i následovně:
window.addEventListener('load', function () {
var cudlik = document.querySelector('input');
cudlik.addEventListener('click', function () {
window.alert('Baf!');
});
});
V JavaScriptu lze totiž funkce vytvářet i bez toho, abychom jim dávali jméno. Jsou to potom tzv. anonymní funkce, jednorázové.
Umět změnit třídu HTML tagu je zásadní, protože tím můžeš ovlivnit, jaká CSS pravidla se na něj budou aplikovat. Ulož si následující HTML:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>PyLadies</title>
<script src="dom.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<p>
Žilo jednou jedno děvčátko
a to dostalo od babičky
k narozeninám dárek – červenou
čepičku. Rádo ji nosilo, a proto
jí říkali Červená karkulka.
</p>
</body>
</html>
Do připojeného souboru dom.js vytvoř program, který přidá odstavci třídu red, pokud na něj uživatel stránky najede kurzorem:
window.addEventListener('load', function () {
var odstavec = document.querySelector('p');
odstavec.addEventListener('mouseover', function () {
odstavec.className = 'red';
});
odstavec.addEventListener('mouseout', function () {
odstavec.className = '';
});
});
Když si stránku načteš v prohlížeči a zkusíš jezdit kurzorem na odstavec a z něj, neuvidíš žádnou změnu. Ale pokud si otevřeš vývojářské nástroje a přepneš se na záložku Elements, uvidíš, že se hodnota atributu <p class="..."> s pohybem kurzoru mění.
Možná sis všimla, že k HTML v tomto příkladu byl připojen i CSS soubor style.css, ale ten zatím neexistuje. Vytvoř ho tedy a přiřaď v něm třídě red nějaké vlastnosti.
p {
padding: 10px;
background-color: skyblue;
}
.red {
background: red;
color: white;
}
Aby se po odstavci trochu lépe jezdilo myší, přidali jsme mu nějakou vnitřní výplň po okrajích (padding) a pozadí, aby bylo vidět, kde končí. Nyní zkus stránku obnovit v prohlížeči.
Najetí a odjetí kurzoru myši by mělo měnit barvu odstavce.
Často elementy nemají jen jednu třídu, ale několik.
Vlastnost className je potom poněkud nepraktická:
<p class="big warning">Nesahat!</p>
var odstavec = document.querySelector('p');
console.log(odstavec.className); // 'big warning'
Proto je v moderních prohlížečích k dispozici i jiný způsob pro práci s třídami:
var odstavec = document.querySelector('p');
console.log(odstavec.classList); // ['big', 'warning']
Vlastnost classList má navíc metody na přidávání (add), odebírání (remove).
Metoda toggle dělá to co add, pokud třída není a to co remove, když třída je.
Metoda contains pak vrací true nebo false podle toho, zda element třídu má nebo ne, to se může hodit třeba pro zjištění, v jakém stavu nějaký prvek je.
var odstavec = document.querySelector('p');
odstavec.classList.add('red'); // ['big', 'warning', 'red']
odstavec.classList.remove('big'); // ['warning', 'red']
odstavec.classList.toggle('warning'); // ['red']
odstavec.classList.toggle('warning'); // ['warning', 'red']
odstavec.classList.contains('big'); // false