JavaScript – DOM a BOM

Tento materiál slúži ako úvod a rozšírené vysvetlenie práce s DOM a BOM v JavaScripte. Naučíš sa, ako ovládať webovú stránku a prehliadač pomocou kódu.

1. DOM – Document Object Model

Čo je DOM?

DOM je objektová reprezentácia HTML dokumentu. Prehliadač premení HTML na strom objektov, s ktorými vie JavaScript pracovať.

Každý HTML prvok sa stáva objektom.

DOM ako strom

<html>
  <body id="page" class="main-page">

    <h1 id="title" class="heading main-title" style="color: yellow
    !important;">
      Nadpis DOM objekty
    </h1>

    <p id="text" class="paragraph">
      Tu je uvedený text.
    </p>

  </body>
</html>

Sa uloží ako strom objektov:

document
 └── html
      └── body#page.main-page
           ├── h1#title.heading.main-title
           │    └── "Nadpis DOM objekty"
           └── p#text.paragraph
                └── "Tu je uvedený text."

Výpis DOM objektu:

document = {
  html: {
    body: {
      id: "page",
      classList: ["main-page"],

      h1: {
        id: "title",
        classList: ["heading", "main-title"],
        style: {
          color: "yellow"
        },
        text: "Nadpis DOM objekty"
      },

      p: {
        id: "text",
        classList: ["paragraph"],
        text: "Tu je uvedený text."
      }
    }
  }
};

Výber prvkov zo stránky

Najčastejšie používané metódy:

//výpis DOM objektu
console.log("Cely DOM", document);        // celý DOM
console.log("body", document.body);   // body
console.dir(document);        // objektovo

//Podľa ID
let id1 = document.getElementById("text");
let id2 = document.getElementById("title");
console.log("ID", id1, id2);

//Podľa CLASS
let class1 = document.querySelector(".paragraph");
console.log("class", class1);

//Kombinácia
let komb1 = document.querySelector("h1.main-title");
let komb2 = document.querySelector("h1#title");
let komb3 = document.querySelector("h1#title.main-title");
console.log("kombinácia", komb1, komb2, komb3);

//Cez strom
let strom1 = document.body.children[0]; // h1
let strom2 = document.body.children[1]; // p
console.log("strom", strom1, strom2);

//Vyberie všetky p elementy na stránke.
let allp1 = document.querySelectorAll("p");
console.log("vsetky p tagy", allp1);

// p
let p1 = document.querySelector("p");
console.log("p tag", p1); // vráti prvý prvok

//p 3-ti v poradi
document.querySelector("p:nth-of-type(3)"); // vráti tag p 3-ti v poradí

// text v h1
let text1 = document.querySelector("h1").textContent;
console.log("text", text1);

// štýl
let style1 = document.querySelector("h1").style.color;
console.log("štýl", style1);

querySelector

👉 používa CSS selektory (tagy, id, class, kombinácie, atribúty)
👉 vždy vráti iba jeden prvok
👉 a to prvý, ktorý zodpovedá selektoru v HTML

Zmena obsahu

const p = document.getElementById("text");

// Zmena textu (bez HTML)
p.textContent = "Nový text";
// Zmena obsahu vrátane HTML
p.innerHTML = "<b>Tučný text</b>";

textContent je bezpečnejší ako innerHTML.

Zmena štýlov a tried

// zmena farby textu
p.style.color = "red";

// zmena veľkosti písma
p.style.fontSize = "20px";

//p.style umožňuje priamo meniť inline štýly elementu.

//pridajte si štýl do head
    <style>
        .active {
          color: red;
          font-size: 20px;
          font-weight: bold;
        }
    </style>

//Pridanie triedy
p.classList.add("active");

//Odstránenie triedy
p.classList.remove("active");

//Prepnúť (toggle)
p.classList.toggle("active");

//Ak trieda existuje → odstráni ju
//Ak trieda neexistuje → pridá ju

Prehľadávania DOM prvkov cyklami

//vložte si na stránku
<div id="container">
    <p class="text">Prvý odstavec</p>
    <p class="text">Druhý odstavec</p>
    <p class="text">Tretí odstavec</p>
</div>

//Získanie prvkov do NodeList / HTMLCollection
// querySelectorAll → NodeList
const pcka = document.querySelectorAll(".text");

//1. Prechod NodeList pomocou forEach
pcka.forEach((p, index) => {
    console.log(`Odstavec ${index + 1}: ${p.textContent}`);
});

//Popis
forEach funguje priamo na NodeList
p = aktuálny <p> element
index = poradové číslo v NodeList

//2. Klasický for cyklus
for (let i = 0; i < pcka.length; i++) {
    console.log(`Odstavec ${i + 1}: ${pcka[i].textContent}`);
}
//Popis
Prístup pre HTMLCollection aj NodeList
Prístup k prvkom cez index [i]

//3. for...of cyklus
let count = 1;
for (let p of pcka) {
    console.log(`Odstavec ${count}: ${p.textContent}`);
    count++;
}

//Popis
for...of iteruje cez iterovateľné objekty (NodeList áno, HTMLCollection od ES6)
Jednoduchšie ako klasický for

//4. for...in (nie úplne ideálne pre NodeList)
for (let i in pcka) {
    if (pcka[i].textContent) { // overenie, že ide o element
        console.log(pcka[i].textContent);
    }
}

//Popis
for...in iteruje vlastnosti objektu
Menej vhodné, pretože môže ísť aj o metódy a dĺžku (length)

//5. Prechod HTMLCollection (getElementsByTagName)
// getElementsByTagName → HTMLCollection
const pcka2 = document.getElementsByTagName("p");

for (let i = 0; i < pcka2.length; i++) {
    console.log(pcka2[i].textContent);
}

//HTMLCollection nie je priamo pole, preto forEach nefunguje
  (treba Array.from() ak chceme forEach)

Array.from(pcka2).forEach(p => console.log(p.textContent));

//6. Zmena obsahu počas cyklu
pcka.forEach(p => {
    p.textContent += " druháci";
});

//INFO
| Cyklus   | Použitie                  | Poznámka                  |
| -------- | ------------------------- | ------------------------- |
| forEach  | NodeList                  | Moderné, jednoduché       |
| for      | NodeList / HTMLCollection | Univerzálne               |
| for...of | NodeList / iterables      | Moderné, čitateľné        |
| for...in | Objektové vlastnosti      | Menej vhodné pre NodeList |


Udalosti (Events)

Udalosti sú spôsob, ako reagovať na akcie používateľa alebo systému – napríklad kliknutie, pohyb myši, stlačenie klávesu, načítanie stránky a mnoho ďalších.

| Typ udalosti | Popis                             |
| ------------ | --------------------------------- |
| `click`      | kliknutie myšou                   |
| `dblclick`   | dvojklik myšou                    |
| `mouseover`  | myš nad elementom                 |
| `mouseout`   | myš opustí element                |
| `mousedown`  | stlačenie tlačidla myši           |
| `mouseup`    | uvoľnenie tlačidla myši           |
| `keydown`    | stlačenie klávesu                 |
| `keyup`      | uvoľnenie klávesu                 |
| `input`      | zmena hodnoty v inpute            |
| `change`     | zmena hodnoty po potvrdení inputu |
| `submit`     | odoslanie formulára               |
| `load`       | načítanie stránky alebo obrázka   |
| `resize`     | zmena veľkosti okna               |
| `scroll`     | posúvanie stránky alebo elementu  |


//vytvoríme button v html
<button id="btn">Klikni ma!</button>
<p id="output">Tu sa zobrazí správa po kliknutí.</p>

//2. Pridanie udalosti
a) addEventListener (najlepšie)
const btn = document.getElementById("btn");

btn.addEventListener("click", function() {
  alert("Klik!");
});

//POPIS
btn = element, na ktorý chceme reagovať
"click" = názov udalosti
funkcia = čo sa má vykonať, keď nastane udalosť

//b) Inline HTML (menej odporúčané)
<button onclick="alert('Klik!')">Klikni</button>

//c) Priama vlastnosť objektu
const btn = document.getElementById("btn");
btn.onclick = function() {
  alert("Klik!");
};

//3. Odstránenie udalosti
function clickHandler() {
  alert("Klik!");
}

btn.addEventListener("click", clickHandler);

// Odstráni udalosť
btn.removeEventListener("click", clickHandler);

//4. Správanie udalostí
//a) Bubbling (bublanie)

//vytvoríme div v html
 <div id="outer">
  <button id="inner">Klikni</button>
</div>

document.getElementById("outer").addEventListener("click",
    () => console.log("outer"));
document.getElementById("inner").addEventListener("click",
    () => console.log("inner"));

//Najprv sa spustí listener na button
//Potom sa spustí listener na div – pretože udalosť bublá hore
//Inými slovami: kliknutie „bublá“ z dieťaťa na rodiča v DOM strome.

//b) Capturing (zachytávanie)
document.getElementById("outer").addEventListener("click",
    () => console.log("outer"), true);

//Posledný parameter true = capturing (zachytávanie)
//false alebo nepísané = bubbling (predvolené)
//Capturing je opačný smer ako bubbling.
//Udalosť ide z koreňa DOM stromu smerom nadol k cieľovému elementu.
//Inými slovami: najprv „prechádza“ cez rodičov a až nakoniec dorazí na element,
//kde sa udalosť stala.

//5. Objekt udalosti (event object)
//Každá funkcia môže dostať informácie o udalosti:
btn.addEventListener("click", function(event) {
console.log(event.type);     // "click"
console.log(event.target);   // element, na ktorý sa kliklo
console.log(event.currentTarget); // element, ktorý má listener
});

//POPIS
event.target = pôvodný element, kde udalosť nastala
event.currentTarget = element, ktorý spracúva listener
event.preventDefault() = zruší predvolené správanie (napr. submit form)
event.stopPropagation() = zastaví bublanie udalosti


//6. Odosielanie formulára s kontrolou

//vytvoríme form v html
<form id="form">
  <input type="text" required>
  <button type="submit">Odoslať</button>
</form>

document.getElementById("form").addEventListener("submit", function(event) {
  event.preventDefault(); // zabráni odoslaniu, kým nespĺňa podmienky
  alert("Formulár je pripravený na odoslanie");
});

//7. Príklad viac udalostí na jednom prvku
const input = document.querySelector("input");

input.addEventListener("focus", () => console.log("Zamerané"));
input.addEventListener("blur", () => console.log("Stratil fokus"));
input.addEventListener("input", () => console.log("Zmenený text"));

//TIPY
addEventListener je moderný a bezpečný spôsob
Každý element môže mať viac listenerov
Udalosti sa šíria podľa bubbling / capturing
event objekt obsahuje veľa užitočných informácií (typ, target, súradnice, atď.)

Event reaguje na činnosť používateľa.

Vytváranie a mazanie prvkov v DOM

const p = document.createElement("p");
//document.createElement("p") → vytvorí nový <p> element
//Zatiaľ nie je vložený do dokumentu, iba existuje v pamäti.

p.textContent = "Nový odstavec";
//textContent vloží text do elementu

document.body.append(p);
//append() vloží element na koniec <body>
//Element sa teraz zobrazí na stránke

    | Metóda          | Kam vloží element                       |
    | --------------- | --------------------------------------- |
    | `appendChild()` | na koniec ako dieťa                     |
    | `prepend()`     | na začiatok ako dieťa                   |
    | `after()`       | **za** existujúci element (súrodenec)   |
    | `before()`      | **pred** existujúci element (súrodenec) |
    | `replaceWith()` | nahradí existujúci element              |
    | `afterend()`    | vloží element priamo za tag             |
    | `beforebegin()` | vloží pred tag                          |
    | `beforeend()`   | vloží do tagu, na koniec                |
    | `afterbegin()`  | vloží do tagu, na začiatok              |

//appendChild je na pridanie do vnútra elementu
//after/before je na pridanie vedľa elementu
//append a appendChild sa líšia len tým, že append môže pridať
//viacero prvkov naraz a aj text


// vytvoríme nový odstavec pred h1
const p_new = document.createElement("p");
p_new.textContent = "Nový odstavec za h1";

const h1 = document.getElementById("title");
// vložíme **pred h1**
h1.before(p_new);

// po 3 sekundách ho odstránime
setTimeout(() => {
    p_new.remove();
}, 3000);

Dôležité DOM funkcie a vlastnosti

Mini cvičenia – DOM

  1. Vyber odstavec a zmeň jeho farbu.
  2. Po kliknutí na tlačidlo zmeň text nadpisu.
  3. Vytvor nový div pomocou JS.
  4. Pridaj triedu k vybranému prvku.

BOM – Browser Object Model

BOM (Browser Object Model) je rozhranie, ktoré umožňuje JavaScriptu komunikovať s prehliadačom.

Vďaka BOM vieš:

Hlavný objekt: window

// príklad použitia
window.alert("Ahoj");
alert("Ahoj"); // to isté, window je implicitné

1. Alert

// JS
document.getElementById("btn1")
.addEventListener("click", () => {
    alert("Ahoj");
});
<button id="btn1">Skús alert</button>

2. location

// JS
document.getElementById("btn2")
.addEventListener("click", () => {
    console.log(location.href);
});
<button id="btn2">Vypíš URL</button>
// JS
document.getElementById("btn3")
.addEventListener("click", () => {
    location.href = "https://google.com";
});
<button id="btn3">Presmeruj</button>

3. history

// JS
document.getElementById("btn4")
.addEventListener("click", () => {
    history.back();
});
<button id="btn4">Späť</button>
// JS
document.getElementById("btn5")
.addEventListener("click", () => {
    history.forward();
});
<button id="btn5">Dopredu</button>

4. navigator

// JS
document.getElementById("btn6")
.addEventListener("click", () => {
    alert(navigator.language);
});
<button id="btn6">Zisti jazyk</button>

5. screen

// JS
document.getElementById("btn7")
.addEventListener("click", () => {
    alert(screen.width + "x" + screen.height);
});
<button id="btn7">Veľkosť</button>

6. Confirm

// JS
document.getElementById("btn8")
.addEventListener("click", () => {
    let r = confirm("Si si istý?");
    console.log(r);
});
<button id="btn8">Confirm</button>

7. Prompt

// JS
document.getElementById("btn9")
.addEventListener("click", () => {
    let meno = prompt("Meno:");
    alert(meno);
});
<button id="btn9">Prompt</button>

8. setTimeout

// JS
document.getElementById("btn10")
.addEventListener("click", () => {
    setTimeout(() => {
        alert("Po 3 sekundách");
    }, 3000);
});
<button id="btn10">Timeout</button>

9. setInterval

// JS
document.getElementById("btn11")
.addEventListener("click", () => {
    let i = 0;
    let id = setInterval(() => {
        console.log(i++);
        if (i > 5) clearInterval(id);
    }, 1000);
});
<button id="btn11">Interval</button>

10. Confirm + redirect

// JS
document.getElementById("btn12")
.addEventListener("click", () => {
    if (confirm("Chceš odísť?")) {
        location.href = "https://google.com";
    }
});
<button id="btn12">Odísť</button>

🧪 Cvičenia (45 min)

Úloha 1 (DOM) – zmena farby

Zadanie: Po kliknutí na tlačidlo zmeň farbu textu na červenú.

Tento text sa zmení na červenú

Úloha 2 (DOM) – počítadlo

Zadanie:

0

Úloha 3 (DOM) – input

Zadanie:

Úloha 4 (BOM) – confirm

Zadanie:

Úloha 5 (BOM) – presmerovanie

Zadanie:

Úloha 6 (BOM) – jazyk

Zadanie:

Úloha 7 (DOM + BOM) – časovač

Zadanie:

0