Prohlížeč parsuje HTML a vytvoří z něj stromovou strukturu objektů — Document Object Model. JavaScript pak může tento strom číst a měnit, což způsobuje viditelné změny na stránce.
document
└── html
├── head
│ ├── title"Moje stránka"
│ └── metacharset="UTF-8"
└── body
├── header
│ └── h1"Nadpis"
├── main
│ └── p#uvod"Text..."
└── footer
Každý uzel stromu je Node — element, text nebo komentář. JS přistupuje k uzlům přes globální objekt document.
🛠️
DevTools → Elements: Otevřete F12 → Elements záložku v prohlížeči. Vidíte živý DOM — kliknutím na element ho zvýrazníte na stránce. V Console záložce pak píšete JS přímo proti aktuální stránce.
querySelector vs getElementById:getElementById je marginálně rychlejší pro výběr podle ID. V praxi je rozdíl zanedbatelný — querySelector je flexibilnější a konzistentní s CSS znalostmi.
🧠 Kvíz: Co vrátí document.querySelector('.btn') pokud na stránce jsou tři elementy s třídou btn?
const el = document.querySelector('#muj-element');
// ── OBSAH ──
el.textContent // čte/zapisuje text (bezpečné, bez HTML)
el.innerHTML // čte/zapisuje HTML (pozor na XSS!)
el.innerText // podobné textContent, ale bere v potaz CSS
el.textContent = "Nový text";
el.innerHTML = "<strong>Tučný text</strong>";
// ── ATRIBUTY ──
el.getAttribute('href') // čte atribut
el.setAttribute('href', '/nova') // zapisuje atribut
el.removeAttribute('disabled') // odebere atribut
el.hasAttribute('hidden') // boolean
// Zkrácené vlastnosti pro běžné atributy
el.id // čte/zapisuje id
el.href // pro
el.src // pro ,
Dynamické vytváření elementů je základ každé interaktivní aplikace — todo listy, komentáře, produkty načtené z API...
// createElement — vytvoří element (zatím není v DOM)
const li = document.createElement('li');
li.textContent = "Nová položka";
li.classList.add('polozka');
li.dataset.id = "42";
// Vložení do DOM
const seznam = document.querySelector('ul');
seznam.appendChild(li); // přidá na konec
seznam.prepend(li); // přidá na začátek
seznam.insertBefore(li, cil); // před konkrétní element
cil.after(li); // za element (moderní)
cil.before(li); // před element (moderní)
cil.replaceWith(li); // nahradí element
// insertAdjacentHTML — rychlé vložení HTML stringu
seznam.insertAdjacentHTML('beforeend', '<li>Rychlá položka</li>');
// pozice: beforebegin | afterbegin | beforeend | afterend
// Odstranění
el.remove(); // odstraní element
el.parentNode.removeChild(el); // starší způsob
// Klonování
const klon = el.cloneNode(true); // true = včetně children
Události "probublávají" (bubble) od cílového elementu nahoru ke document. Toto chování můžeme využít — místo přidávání listeneru na každý child element, přidáme jeden listener na rodiče:
// ❌ Špatně — listener na každou položku
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', handler); // N listenerů!
});
// Problém: dynamicky přidané položky listener nemají!
// ✅ Event delegace — jeden listener na rodiče
document.querySelector('.seznam').addEventListener('click', (e) => {
// e.target = element, na který bylo skutečně kliknuto
if (e.target.matches('.item')) {
console.log('Kliknuto na item:', e.target.textContent);
}
if (e.target.closest('.btn-delete')) {
const item = e.target.closest('.item');
item.remove();
}
});
Nejčastější způsob interakce JS s CSS je přidávání/odebírání CSS tříd. Přímé nastavování style je vhodné jen pro dynamické hodnoty (barvy z API, pozice při dragování...).
Vytvořte sadu karet s kategorií (data-kategorie) a tlačítka pro filtrování. Kliknutím na tlačítko se zobrazí jen karty dané kategorie. Použijte event delegaci pro tlačítka a classList pro show/hide karet.
📋
Checklist: Karty mají data-kategorie="...", filtr tlačítka mají data-filtr="...", jeden listener na kontejner tlačítek (delegace), classList.toggle('skryty', podmínka) pro karty, aktivní tlačítko označte třídou.
Vaše řešení
🏅
Odznak: DOM Manipulátor
Zvládáte selektory, události, vytváření prvků, delegaci a classList.
document.querySelector('css-selektor') // první shoda
document.querySelectorAll('css-selektor') // NodeList všech
el.querySelector('.child') // hledá uvnitř el