Pro práci s DOMem toho není potřeba znát zase až tak moc – najít konkrétní podstrom(y) či element(y), změnit nějaké jejich vlastnosti (typicky viditelnost, rozměry nebo jiný styl) či obsah (tedy potomky).
V dalším si ukážeme pár základních technik, abyste se měli do projektů od čeho odpíchnout a měli lepší představu, po čem se při hledání odpovědí na internetu koukat.
Původní DOMovské metody pro nalezení konkrétního elementu byly pouze následující dvě (volat se dají buď v kontextu celého document
u nebo na již konkrétním podstromě):
.getElementById('ID-elementu')
– vrací element, jehož atribut @id
má uvedenou hodnotu;
.getElementsByTagName('JménoElementu')
– vždy vrací seznam (tzv. nodeList) vyhovujících elementů, i kdyby měl být pouze jeden.
Pak se ještě daly elementy dohledávat přímým průchodem po stromě (tedy procházením potomků potomků, např. pomocí metod .firstChild()
, .nextSibling()
apod.), ale to bylo samozřejmě velmi pracné (zvlášť když si uvědomíte, že spousta takto nalezených uzlů byly prázdné textové – i kdyby HTML z principu libovolný počet po sobě následujících bílých znaků nesráželo na jednu mezeru, stejně byste ve většině případů naráželi na samé prázdné textové uzly).
Nedostatky oficiálního DOMu začaly brzo nahrazovat nejrůznější javascriptové knihovny (například jedna z nejstarších a nejpopulárnějších jQuery) a postupem času i sami výrobci prohlížečů, takže dneska už můžeme vybírat elementy například i pomocí CSSkových selektorů (a opět buď v kontextu celého document
u nebo jenom na daném podstromě):
.querySelector('selektor')
– vrátí první vyhovující uzel;
.querySelectorAll('selektor')
– vrátí seznam (pole) všech vyhovujících uzlů.
Popravdě ještě dříve, než se prohlížeče shodly na použití CSS-selektorů pro výběr podstromů DOMu, byly k dispozici – dokonce (skoro) standardizované – metody pro využití XPathu. Jenže příslušný standard byl neuvěřitelně zhůvěřilý a na praxi webu hleděl ještě méně, než jiné části DOMu -- plný formát volání totiž vypadá takto:
Ze všech možných variant volání je nejpoužitelnější asi následující:
Jiné návratové typy vrací objekty, které byste z XPath-dotazu nečekali.
K dohledání domovské reprezentace konkrétního elementu je v poslední době třeba přidat i něco, co dříve fungovávalo pouze uvnitř formulářů, totiž možnost referencovat element přímo pomocí jeho @ID:
Ale netřeba asi dodávat, že tohle čitelnosti moc nepomůže, pokud nebudete velmi důslední ve vybírání jmen pro atributy id…
Je třeba si uvědomit, že:
Abyste mohli uzly referovat, musí už v DOMovské reprezentaci existovat, tzn. HTML-parser je musí nejdříve najít a zpracovat!
Což samozřejmě nastane až v nějakém okamžiku po načtení (a zpracování) ne sice nutně celé stránky (vámi hledaný element nebývá typicky až na konci a parser pracuje inkrementálně), ale rozhodně později, než byste měli tendenci se na ně ptát v rámci elementu <script>
v hlavičce HTML-dokumentu.
Typicky se to řeší navěšením obsluhy události onload na tělo HTML-dokumentu – k této události totiž dojde až ve chvíli kompletního zpracování zdrojového textu HTML-stránky, takže už je zaručena existence všech uzlů ve stromě:
Ale pozor – tímto způsobem můžete na událost load pověsit pouze jeden handler! Pokud začnete document.onload
přepisovat, zabere jenom jeden z nich (a to ten poslední).
Omezením na jeden handler netrpí přiřazování pomocí metody addEventListener()
, které v případě události onload vypadá takto:
Takovýchto handlerů můžete navěsit kolik chcete a vykonají se postupně všechny.
Podobně nahradit obsah či potomky nějakého uzlu standardními DOMovými metodami je neuvěřitelně komplikované. (A dvojnásob zbytečné v kontextu HTML, kde se na pravidla správného formátování podle XML nikdy nehrálo, že.)
Naštěstí pro nás lenochy se výrobci prohlížečů brzo shodli na velmi šikovné zkratce – vlastnosti .innerHTML
, která je dostupná prakticky na všech elementech, kde má nějaký smysl. Jejím vstupem je řetězec, který obsahuje (s trochou štěstí) kus HTML-kódu, který chcete na příslušné místo stránky „nacpat“:
PS: Jelikož jsme v HTML, tak vkládaný HTML-fragment (zde obsah proměnné txt
) vůbec nemusí být nějak správně naformátovaný. Ale ve vlastním zájmu pište raději HTML co nejčistěji – snáze se pak zjišťuje, kde došlo k chybě.
Asi nejčastější operací na nalezeném uzlu budu změna jeho nějakého CSSkového stylu. To zařizuje vlastnost .style
, která obsahuje kompletní reprezentaci úplně všech CSSkových vlastností, které je možné nastavit (takže je fakt, ale fakt dlouhá). Jen vlastnosti s delším názvem se píší v CSS s pomlčkou (mínusem), což v JavaScriptu nejde, takže se nahrazují kapitalizací:
PS: Dají se dokonce měnit i pravidla v samotném přiloženém CSS-stylu, ale to už je hodně složitá záležitost. Pro začátek zkoukněte úvodní článek na Mozille.
Cokoliv pomocí CSS – ať už přímo nebo z JavaScriptu – nastavujete, vždy dávejte pozor:
Každý číselný údaj s rozměrem musí provázet příslušná jednotka!
Zapomenete-li na jednotky, v lepším případě obdržíte chybu (typicky uvnitř CSS), v horším si parser nějakou doplní (např. JavaScript často dodá 'px'). Každopádně to skoro nikdy nebude dělat to, co jste měli na mysli ^_~
Ošetřit události na nějakém uzlu můžete buď přímo v HTML pomocí vhodných atributů (například onclick
a podobně), ale stejně dobře můžete tohle zařídit po načtení stromu do paměti pomocí dodatečného navěšení tzv. obsluhovačů událostí (event handler) na příslušné uzly pomocí JavaScriptu:
Při vývoji velmi často potřebujete kontrolovat stav vybraných proměnných. Prohlížeče dnes obsahují celou sadu vývojářských nástrojů, ale velmi často vám bude stačit vypsat si do webové konzole (typicky otvírána klávesovou zkratkou CTRL+Shift+I, resp. CTRL+Shift+K) nějakou hodnotu nebo referenci na příslušný (domovský) objekt.
O uvedené se dnes stará objekt console
, především jeho metoda console.log()
, která dokáže vypsat libovolný počet vstupních parametrů libovolného typu:
PS: Kdysi se daly údaje z prohlížečů dostat jen pomocí nechvalně proslulé funkce alert()
. Představte si ji uvnitř nějaké hodně dlouhé smyčky for a je vám jasné, že to bylo peklo ^_~
Proměnné v JavaScriptu (a to tedy zahrnuje i funkce!) jsou viditelné podle místa, ve kterém byly nadefinovány – na globální úrovni jsou vidět všude, uvnitř nějaké funkce pouze v ní a v ní zanořených funkcích.
Navíc platí:
Proměnné (i funkce!) nadefinované pomocí klíčového slova var jsou platné pouze pro aktuální kontext, bez něj se automaticky stávají globálními.
Přitom objekty nadefinované uvnitř funkcí jako globální (tedy bez klíčového slova var) jsou sice globální, ale až po vykonání těla příslušné funkce. Do té doby nejsou ve vnějším kontextu vidět.
Kdybyste chtěli vědět víc, podívejte se třebas na přehled webových API Mozilly, v něm se dá snadno utopit ^_^
Pravdou je, že prohlížeče se v posledních letech KONEČNĚ naučily věci, které měly (a mohly) umět už v minulém tisíciletí, takže dnes můžete ovládat stránky pomocí gamepadů, zjišťovat GPS-souřadnice, přehrávat videa, tvořit zvuky a kdo ví co všechno ještě.