C# týden Slevový týden - Březen
Využij náš slevový týden a získej až 30 % bodů navíc zdarma! Zároveň také probíhá C# týden se slevou na e-learning až 80 %
Hledáme fulltime programátora do ITnetwork týmu -100% homeoffice, 100% časově flexibilní #bezdeadlinu Mám zájem!

Lekce 9 - Manipulace s DOM v JavaScriptu

V minulé lekci, Základy práce s DOM a události v JavaScriptu, jsme začali tou nejčastěji používanou metodou DOMu - getElementById() a řekli jsme si něco o událostech. Dnešní JavaScript tutoriál bude ryze teoretický. Ukážeme si, co vše lze provádět v DOMu a v příští lekci vytvoříme již skutečně rozsáhlejší webovou aplikaci, která bude čerpat právě ze znalostí nabytých v této lekci.

Výběr elementů

Než se do manipulace elementů pustíme, musíme si je nějak najít. Metoda getElementById() je sice velmi účelná (a rychlá), ale není vždy ideální. Někdy je potřeba vybrat více elementů a někdy je třeba vybrat elementy bez id. Není totiž podmínkou, že budeme vybírat z dokumentu, ke kterému máme přístup a přítomnost id si zajistíme sami.

Výběr na základě třídy

Tento výběr zajišťuje metoda getElementsByClassName(). Při jejím psaní si dávejte pozor, že elements je množné číslo a každé první písmeno slova (kromě prvního slova) je velké. Pokud to spletete, obdržíte chybu (asi ji však neuvidíte, chyby zobrazují pouze starší verze IE). Metoda vrací pole všech elementů, které mají danou třídu. Pokud takovou třídu nemá žádný element, vrátí metoda prázdné pole (zcela přesně, vrátí prázdný HTMLCollection, což je hloupější pole určené k uchovávání HTML elementů).

document.getElementsByClassName("class");

Výběr na základě tagu

Každý element má tag, což je jeho značka (typ). Metoda getElementsByTagName() vrací všechny elementy, které mají danou značku. Tímto způsobem můžeme například vybrat všechny textové elementy. Pokud žádný element takový tag nemá, vrátí prázdnou HTMLCollection.

document.getElementsByTagName("tag");

Existují ještě metody pro výběr na základě tagu a jeho jmenného prostoru (getElementsByTagNameNS()). Ty ocení zejména znalci XML a vyhledávání na základě jména (getElementsByName()), což se používá pro vyhledávání prvků ve formulářích, kde se atribut name používá. Obě metody v případě, kdy nic nesplňuje zadané podmínky, vrátí rovněž prázdnou HTMLCollection.

document.getElementsByName("name");
document.getElementsByTagNameNS("tag", "NS");

Výběr podle CSS selektoru

V HTML dokumentu můžeme vyhledávat ještě mnohem pohodlněji a to pomocí CSS selektorů, jak jsme zvyklí z webdesignu. Existují dvě metody, které mám toto umožní. Metoda querySelector() vrátí první element, který tento selektor splňuje a metoda querySelectorAll() vrátí pole všech elementů, pro které daný selektor platí. Ukážeme si to rovnou na příkladu.

document.querySelector("input[type=text].hezky#uvodni");

Tento selektor vrátí element <input>, jehož atribut type je nastavený na text, má třídu .hezky a zároveň id #uvodni. Možná jste si všimli, že když vyhledáváme na základě id, stačil by teoreticky selektor pouze takto (id musí být jedinečné).

document.querySelector("#uvodni");

O trochu zajímavější to bude s metodou querySelectorAll(), která v mnohých případech může být jediná možnost jak něco vybrat.

document.querySelectorAll("div[data-countdown]");

Tento selektor vrátí všechny elementy, které mají nastavený atribut data-countdown. Když jsme již schopni vybrat úplně každý element v DOM, můžeme se pustit do jejich editace.

Editace obsahu DOM

innerHTML

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Nejprve se podíváme na samotný obsah elementů. Jednou z nejzákladnějších vlastností elementů z DOM je vlastnost innerHTML, která reprezentuje obsah elementu. Na elementu <p>:

<p><span>Hello</span>world</p>

Načtení této vlastnosti

p.innerHTML

vrátí <span>Hello</span>world. Obsah elementu můžeme úplně stejně i měnit. Jen je potřeba pamatovat na to, že se vnitřní HTML tagy zpracují.

innerText

Podobně jako innerHTML funguje i vlastnost innerText. Jediný rozdíl je, že innerText neobsahuje vnořené HTML elementy, ale pouze jejich textový obsah. Použijeme-li stejný obsah jako u příkladu výše, p.innerText vrátí "Hello world". Vlastnost byla dříve nestandardní, ale všechny prohlížeče ji dnes již podporují.

textContent

textContent dělá téměř totéž co innerText. Rozdíl mezi vlastnostmi je, že innerText vrací pouze viditelný text, zatímco textContent vrací i text skrytý přes CSS.

Nyní již víme jak číst/měnit obsah elementů. Nyní se podíváme na jejich atributy.

Editace atributů DOM

Má atribut?

Základní otázkou je zda element hledaný atribut vůbec má. To zjistíme metodou hasAttribute(), která jako parametr bere název atributu a vrací booleanovskou hodnotu. Existuje i metoda hasAttributes() (množné číslo), která vrací, jestli má element vůbec nějaký atribut. Pokud nemá žádný, vrátí false, pokud má alespoň jeden, vrátí true. Tato metoda nebere žádný parametr. Metoda má i variantu se jmenným prostorem a může vracet i Node atributu (jeho uzel ve stromu) volitelně se jmenným prostorem.

p.hasAttribute("data-velikost");

Potomci elementu

Element může a nemusí mít potomky. Jsou to všechny elementy, které jsou v něm vnořené. Jako příklad si uvedeme formulář:

<form>
    <input type="text" />
    <button>Odeslat</button>
</form>

Elementy <input> a <button> jsou potomky elementu <form>.

Výběr potomků

Seznam všech potomků elementu je v jeho vlastnosti, poli childNodes (zcela přesně to opět není pole, ale tentokrát NodeList).

firstChild

Potomci jsou samozřejmě nějak řazeni a to od nejstaršího po nejmladšího co do doby vložení. Jednodušeji řečeno, jsou v takovém pořadí, v jakém je prohlížeč načítal (již víme, že odshora dolů). Vlastnost firstChild obsahuje prvního z nich.

lastChild

Je naopak poslední potomek.

Je třeba dodat, že vlastnosti firstChild a lastChild nemusí nutně obsahovat jen fyzické elementy, ale třeba i HTML komentáře, textové řetězce (typicky má element <p> potomka, což je jeho obsah - text) a spoustu dalších, které nás většinou nezajímají (pokud parsujeme XML, je to jiná, k tomu se dostaneme u AJAXu). Z praktického hlediska tu máme proto ještě firstElementChild a lastElementChild, kteří vynechávají všechny "serepetičky" kolem (dost zákeřné jsou bílé znaky :) ) a vrátí nám pouze HTML elementy.

Tvorba elementů

Metodou createElement(), vytvoříme element. Tag se udává jako textový řetězec v prvním parametru. Metoda vrátí nový element, se kterým můžeme jakkoliv pracovat, ale musíme si pamatovat, že tento element nikde v dokumentu zatím ještě není. Můžeme do něj vytvářet a vkládat další elementy, ale dokud jej někam do dokumentu nevložíme, neuvidíme je. Existuje ještě varianta, která vytvoří element a předá mu jmenný prostor - createElementNS().

let span = document.createElement("span");
let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");

Vkládání a přesouvání elementů

Element vložíme do jiného elementu pomocí metody appendChild(). Metoda nový element vloží za posledního potomka. Pokud metodě předáme element, který již je někde vložený, element přesuneme. Na původním místě se odstraní.

p.appendChild(span);

Vkládání před nějaký element

Čas od času se nám moc nehodí, když nám metoda appendChild() přidá element až za poslední. Existuje metoda insertBefore(), která jako první parametr příjme nový element a jako druhý element, před který se nový element vloží/přesune.

document.body.insertBefore(span, p);

Nahrazování potomků

Potomka elementu můžeme nahradit. Dělá to metoda replaceChild(), která jako první parametr přijímá nového potomka a jako druhý parametr původního potomka.

svg.replaceChild(arc, rect);

Mazání potomků

Potomka elementu můžeme odstranit metodou removeChild(), která jako parametr bere potomka:

p.removeChild(span);

Rodič elementu

Každý element má svého rodiče (element, do kterého náleží). Pouze jediný element ho nemá – kořenový element <html>. Rodiče elementu získáme pomocí vlastnosti parentElement (funguje i parentNode, které vrací i ty většinou nevyužitelné uzly okolo). U elementu <html> vrátí Null. Element HTML se v dokumentech i někdy úplně vynechává, podle specifikace není nutný.

No a jsme na konci. Vyjmenovali jsme si takřka (možná na nějakou s NS jsem zapomněl) všechny metody a vlastnosti, které nám nějakou cestou vrátí jiný element/atribut/ob­sah elementu a ukázali jsme si, jak můžeme měnit obsah a atributy elementu. Abychom si znalosti ukotvili v paměti, tak si v příští lekci, Editor tabulek v JavaScriptu, vše prakticky vyzkoušíme. Konečně si vytvoříme skutečně rozsáhlou aplikaci, kterou si už těžko půjde splést s webovou stránkou. :)


 

 

Článek pro vás napsal Michal Žůrek - misaz
Avatar
Jak se ti líbí článek?
36 hlasů
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Předchozí článek
Základy práce s DOM a události v JavaScriptu
Všechny články v sekci
Základní konstrukce jazyka JavaScript
Miniatura
Následující článek
Editor tabulek v JavaScriptu
Aktivity (10)

 

 

Komentáře
Zobrazit starší komentáře (26)

Avatar
Lenka
Redaktor
Avatar
Lenka:12.6.2017 22:15

No pri tomto zapisu by to fungovalovo jen pro getElementById, kde p by mel patricne id, protoze getElements... vraci jako vysledek oindexovane objekty, kdezto v prvnim pripade je jen jeden mozny odstavec.

Hodne stesti pri reseni, se mi v zivote jeste nepovedlo nic z takovych a podobnych ustrku vyresit.

 
Odpovědět
12.6.2017 22:15
Avatar
Karel Chrobák:1.1.2018 21:14

Ahoj, prosím o navedení na správnou cestu...
Mám seznam států a jejich popis. Názvy států jsou viditelné, ale jejich popis je ve výchozím stavu skrytý. Pokud klepnu na název státu, zobrazí se mi jeho popis. Tzn. klepnutím na název státu si s getElementById vyhledám příslušné pole s popisem a s setAttribute vložím do pole style="displa­y:block". To mi zobrazí popis státu. Dál už ale tápu. Pokud klepnu na další název státu, zobrazí se mi sice příslušný blok s popisem, ale ten původní zůstane zobrazen, protože tam je stále vložen style="displa­y:block". Jak bych to měl udělat, aby se mi při klepnutí na další stát skryl popis předchozího, tedy aby se z něj opět odebral atribut style="..."?
Děkuji

Odpovědět
1.1.2018 21:14
Stále se učím a stále toho vím míň a míň.
Avatar
Jiří Fencl
Člen
Avatar
Odpovídá na Karel Chrobák
Jiří Fencl:1.1.2018 21:32

Misto nastavovani primo style nastavuj unikatni tridu, skryvani vyres pres CSS definici te tridy, pak pri kliku vyhledej elementy s danou tridou, tu odstran a pridej jen aktivnimu popisku

 
Odpovědět
1.1.2018 21:32
Avatar
Odpovídá na Karel Chrobák
Michal Žůrek - misaz:2.1.2018 9:04

buď to udělej přes třídu jak radí Jiří Fencl nebo prostě použil cykl a všechny nejprve vresetuj na display:none a teprve pak ten jeden na display:block

 
Odpovědět
2.1.2018 9:04
Avatar
Petr Kalich
Člen
Avatar
Petr Kalich:8. ledna 12:39

Ahoj, chtěl jsem se zeptat na innerText(potažmo innerHTML a textContent)jak je v článku, už to tady bylo nakousnuto, mohl by teda někdo napsat,jak teda správně vypadá zápis,aby byl vrácený text v <p> <span>Hello</span>wor­ld?, mé snahy byly neúspěšné

<body>
<p id="sit"><span>Hello</span>world</p>

<script>
        let p = document.getElementById("sit").innerHTML;
             p.innerHTML=p

</script>
</body>

pokud ovšem do proměnné dám textový řetězec s <p>,tak to už funguje

<body>
<p id="sit"><span>Hello</span>world</p>

<script>
        let p = document.getElementById("sit")
        let s = "<span>Hello</span>world"
             p.innerText= s;

</script>
</body>

takže, jde mi přímo měnit obsah elemntu,ale né aby se určitý elemnt vracel v zápisu jak bych chtěl:)
děkuji za případnou reakci

 
Odpovědět
8. ledna 12:39
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Virlupus
Překladatel
Avatar
Odpovídá na Petr Kalich
Virlupus:8. ledna 23:33

Nevím zda Tě dobře chápu, ale chceš měnit obsah elementu, že? V tomto případě

<p id=sit>Zde změnit text</p>

, jestli se nemýlím?

<p id="sit"><span>Hello</span>world</p>

<script>
    let p = document.getElementById("sit");
    p.innerHTML = "Nějaký text v elementu p s id=sit";
</script>
 
Odpovědět
8. ledna 23:33
Avatar
Virlupus
Překladatel
Avatar
Odpovídá na Petr Kalich
Virlupus:8. ledna 23:37

PS: Vlastně by to měl být nějaký text ve všech elementech s id=sit :-D. I Když identifikátor byl měl být unikátní, třídy již nikoli.

Editováno 8. ledna 23:39
 
Odpovědět
8. ledna 23:37
Avatar
Petr Kalich
Člen
Avatar
Odpovídá na Virlupus
Petr Kalich:15. ledna 11:27

díky za odpověď, spíš mě zajímalo, jak by vypadal ten kod,aby vypsat to pečko
<p id="sit"><spa­n>Hello</span>wor­ld</p>
jako "textový řetězec",jak je to tady v článku, tedy aby to nevracelo "Hello world" ale "<span>Hello</span>wor­ld"
Díky:)

 
Odpovědět
15. ledna 11:27
Avatar
Virlupus
Překladatel
Avatar
Odpovídá na Petr Kalich
Virlupus:15. ledna 11:49

Pro výpis obsahu v nějakém elementu s tagy element.innerHTML, pro výpis bez tagů element.innerText,

<p id="sit"><span>Hello</span>world</p>

<script>
    let p = document.getElementById("sit").innerHTML;
</script>

Výsledek v p bude <span>Hello</span>world

 
Odpovědět
15. ledna 11:49
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:6. března 9:37

Pokud to spletete, obdržíte chybu (asi ji však neuvidíte, chyby zobrazují pouze starší verze IE)

Ach jo, proč rovnou nenaučíte lidi pracovat s debuggerem? Aspoň co se týče konzoli.
Minimálně právě tam by viděli, jestli jim kód hlásí nebo nehlásí žádnou chybu. Proč to už teď nezmínit?

Odpovědět
6. března 9:37
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 36. Zobrazit vše