Úvod Kaskádové styly Ukázky © Jiří Kosek
Dynamické HTML
Některé ukázky Javascriptu v tomto článku používají zastaralé a nestandardní vlastnosti rozhraní DOM a jsou funkční pouze v Internet Exploreru. Místo nich byste měli vždy používat pouze standardní metody – viz http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html.

JavaScript

JavaScript je jednoduchý programovací jazyk, který je možno zapisovat přímo do HTML stránky. Pochází z vývojářské dílny firmy Netscape, ale dnes ho podporuje i Internet Explorer.

Příčinou vzniku JavaScriptu byl požadavek na zvýšení uživatelského komfortu pro uživatele stránek. JavaScript můžeme použít například při vstupní kontrole dat vkládaných do formulářů ještě předtím, než jsou vyplněné údaje odeslány na server. Kontrolu údajů nemusí provádět server a výsledkem je rychlejší odezva pro uživatele. JavaScript ve svých prvních verzích navíc umožnil i vytváření interaktivnějšího uživatelského rozhraní stránek. Stránka mohla reagovat na různé události vyvolané uživatelem a například doplňovat pole do formulářů nebo vyvolat otevření nového okna prohlížeče. Tyto možnosti pak dále rozšířil nový koncept dynamického HTML.

My se nyní stručně seznámíme se základy programování v JavaScriptu. Poté si ukážeme, jak se skripty (tak se říká programům v JavaScriptu) zařazují do HTML stránky. V poslední části se podíváme na to, jak jsou v JavaScriptu přístupné jednotlivé komponenty prohlížeče a stránky pomocí objektového modelu dokumentu (DOM).

JavaScript za devět a půl minuty

JavaScript je velice jednoduchý jazyk. I přesto nemůžeme na tomto omezeném prostoru postihnout všechny jeho vlastnosti. Zmíníme se tedy proto jen o těch nejpodstatnějších. Zájemce o podrobnější informace odkážeme na specializované knihy, které se věnují problematice JavaScriptu na několika stech stran. V současné době je na trhu již několik takových knih i v českém jazyce.

Každý program se skládá z příkazů, které se provádí sekvenčně v pořadí, v jakém jsou zapsány. jednotlivé příkazy se od sebe oddělují středníkem a je dobrým zvykem psát každý příkaz na samostatnou řádku -- program je pak mnohem přehlednější.

V programech můžeme používat proměnné, které slouží k uložení různých hodnot podle našich potřeb. Proměnné není potřeba předem deklarovat, ale je to lepší. Deklarace proměnné se uvozuje klíčovým slovem var:

var Pocitadlo = 0;
var PocetMesicu = 12;
var i, j;
var Pozdrav = "Ahoj Karle!";
var Nalezeno = false;
V našem příkladě jsme deklarovali šest proměnných. První dvě z nich jsme již přímo inicializovali počáteční hodnotou. Názvy proměnných by se měly skládat z písmen, číslic a podtžítek. První písmeno názvu přitom nesmí být číslice. JavaScript rozlišuje velikost písmen v názvech. Proměnné Pocitadlo a POCITADLO jsou tedy dvě různé.

Proměnné mohou obsahovat jeden ze tří typů dat -- číslo, textový řetězec a logická hodnota. Logická hodnota odpovídající pravdě se jmenuje true. Nepravdě odpovídá hodnota false.

Mezi nejjednodušší příkazy patří přiřazovací příkaz. Jeho tvar

proměnná = výraz
Do proměnné se přiřadí hodnota výrazu uvedeného na pravé straně. Výraz může obsahovat proměnné a konstanty různě pospojované pomocí operátorů.

K dispozic jsou samozřejmě běžné operátory jako '+' (sčítání), '-' (odčítání), '*' (násobení) a '/' (dělení).

delta = y - x;
obvod = 2 * 3.14 * polomer;
palce = centimetry / 2.54;
Pokud chceme obsah nějaké promměnné zvýšit nebo snížit o jedničku, můžeme použít operátor '++' nebo '--'. Následující dva příkazy jsou ekvivalentní:
x = x + 1;
x++;
Zestručnění zápisu některých operací je možné i pomocí dalších "vychytávek". JavaScript obsahuje i operátory '+=', '-=', '*=' a '/='. Jejich význam bude zřejmý z ukázky, která opět obsahuje dva příkazy, které mají stejný efekt.
PoziceX = PoziceX + KrokX;
PoziceX += KrokX;
Pokud zapisujeme logické výrazy, můžeme použít několik relačních a logických operátorů. Pro porovnání je v JavaScriptu operátor '=='. Hodnota výrazu (3+2)==5 je tedy true. Pokud chceme testovat nerovnost, použijeme operátor '!='.

Pro porovnávání hodnot máme k dispozici relační operátory '<', '>', '<=' a '>='.

Logické výrazy můžeme navzájem spojovat pomocí logických spojek '&&' (a zároveň) a '||' (nebo). Negaci výrazu provedeme zapsáním vykřičníku '!' před jeho začátek.

JeVIntervalu = (x >= DolniMez) && (x <= HorniMez);
Běh programu můžeme ovlivňovat pomocí podmíněných příkazů. Jejich tvar je následující:
if (podmínka) {
    příkazy, které se provedou při splnění podmínky
    }
else {
    příkazy, které se provedou při nesplnění podmínky
    }
Část else je nepovinná a nemusí se tedy používat. podmínka je libovolný výraz, jehož výsledek je true nebo false.
if (hodina > 12) {
    hlaseni = "Dobré odpoledne!";
    }
else {
    hlaseni = "Dobré ráno!";    
    }
Pokud se má podmíněně provést pouze jeden příkaz, nemusíme jej uzavírat do složených závorek:
if (hodina > 12) 
    hlaseni = "Dobré odpoledne!"
else 
    hlaseni = "Dobré ráno!";
Pokud potřebujeme několik příkazů provést opakovaně, můžeme s výhodou použít cyklů. JavaScript nabízí několik typů cyklů, my se seznámíme s cyklem for a while.

Cyklus for má tvar:

for (počáteční inicializace; podmínka; inkrementace) {
    příkazy
    }
Praktické použití si ukážeme na programu, který spočítá hodnotu faktoriálu z čísla n:
var i,
    faktorial = 1;

for (i=1; i<=n; i++) {
    faktorial *= i;
    }
Cyklus while má syntaxi ještě jednodušší:
while (podmínka) {
    příkazy
    }
Příkazy uvedené v těle cyklu se provádí, dokud je splněna podmínka. Musíme si tedy dát pozor na to, aby podmínka závisela na nějaké proměnné, kterou měníme uvnitř cyklu. Jinak se nám může stát, že získáme nekonečnou smyčku.

Velice užitečnou pomůcku nabízí JavaScript v možnosti definovat si vlastní funkce. Funkce použijeme v případech, kdy potřebujeme v programu na různých místech provádět stejné činnosti. Použitím funkcí kód programu zkrátíme, zpřehledníme a půjde snadněji modifikovat. Definujme funkci pro výpočet faktoriálu. Funkce bude navíc rekurzivní, protože bude volat sama sebe:

function Faktorial(n) {
    if ((n==1) || (n==0)) 
        return 1 
    else 
        return (n * Faktorial(n-1));
    }
Takto definovanou funkci můžeme použít pro vypsání tabulky faktoriálů od 1 do 10:
var i;
for (i=1; i<=10; i++) {
    document.writeln(i, "! = ", Faktorial(n));
    }
Jako výsledek dostaneme tabulku:
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
Funkce vrací hodnotu, která je uvedena za slovem return. Funkce nemusí vracet žádnou hodnotu, pak ji používáme jako samostatný příkaz a ne jako část výrazu.

Funkce může mít i více parametrů, oddělují se pak čárkou.

V poslední ukázce se objevila konstrukce document.writeln. Tento zápis specifikuje vyvolání metody writeln u objektu document. Popis objektů vážících se k prohlížeči a stránce uvedeme na konci tohoto článku. JavaScript však obsahuje i několik objektů, které s HTML vůbec nesouvisí. Jedná se objekty String, Date a Math. Ty umožňují práci s řetezci, s údaji o datu a čase a s matematickými funkcemi.

ObvodKruhu = 2 * Math.PI * Polomer;
c = Math.sqrt(a*a+b*b);   // důsledek Pythagorovy věty
Druhá řádka obsahuje ukázku komentáře. Vše za znaky '//' až do konce řádky se ignoruje a považuje se pouze za komentář, který vysvětluje význam programu.

Zakomponování JavaScriptu do HTML

Podívejme se nyní na prostředky, které nám HTML nabízí pro vkládání skriptů do stránek. Skripty můžeme v zásadě rozdělit na dvě skupiny: Skript se do stránky vkládá pomocí párového elementu SCRIPT. Skript můžeme vložit do stránky buď přímo nebo uvést pouze odkaz na URL, které obsahuje program v příslušném skriptovacím jazyce. Pro určení typu skriptovací jazyka bychom měli použít atribut LANGUAGE. Vložení jednoduchého skriptu do stránky může vypadat např. takto:
<SCRIPT LANGUAGE="JavaScript">
  window.status = "Právě si prohlížíte moji stránku."
</SCRIPT>
Výše uvedený skript zobrazí zadaný text ve stavové řádce. Určení druhu skriptovacího jazyka pomocí atributu LANGUAGE je důležité, protože de HTML lze vkládat i skripty zapsané v jiných jazycích jako je VBScript nebo Tcl.

Druhou možností je vložit skript pouze pomocí odkazu. I v tomto případě však musíme použít ukončovací tag </SCRIPT>:

<SCRIPT LANGUAGE="JavaScript"
        SRC="http://netscape.com/exmpl/demo.js">
</SCRIPT>
Skripty mohou být na stránce umístěny kdekoliv -- v záhlaví (HEAD) i v těle dokumentu (BODY). Do záhlaví bychom měli umístit vše, co musí být vykonáno ještě dřívě, než začne uživatel pracovat s dokumentem -- např. definice funkcí, které se vyvolávají různými událostmi.

Při vkládání skriptů je rovněž vhodné jejich obsah skrýt před staršími prohlížeči pomocí triku s komentáři:

<HEAD>
<TITLE>Stránka, která vám popíše stavovou řádku</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
  window.status = "Právě si prohlížíte moji stránku."
// -->
</SCRIPT>
</HEAD>
Před ukončením HTML komentáře --> použijeme dvě lomítka, aby se interpretr JavaScriptu nepokoušel konec HTML komentáře považovat za část skriptu. To má ve zvyku zejména Netscape Navigator.

Pokud používáme skripty pro dynamické vygenerování části dokumentu, můžeme použít element NOSCRIPT a umístit do něj alternativní text pro starší prohlížeče, které nepodporují skripty:

<BODY>
<SCRIPT LANGUAGE="JavaScript">
<!--
  document.write("Používáte prohlížeč " + navigator.appName
                                  + " " + navigator.appVersion)
// -->
</SCRIPT>
<NOSCRIPT>
Používáte prohlížeč, který nepodporuje JavaScript.
</NOSCRIPT>
</BODY>
Z předchozí ukázky vidíme, že text vygenerovaný programem v JavaScriptu se stává součástí stránky. Příkazy uvedené uvnitř elementu SCRIPT se provedou pouze jednou při načítání stránky.

Aby byly naše dokumenty opravdu interaktivní, je potřeba, aby provedení určité části skriptu bylo vyvoláno událostí, kterou způsobil uživatel. Událostí může být přejetí myší přes určitý element, kliknutí myší apod.

U každého elementu můžeme použít několik nových atributů, které odpovídají jednotlivým událostem. Jako jejich hodnota se uvádí příkazy, které se po vyvolání dané události mají provést -- tzv. obsluha události.

Obecně můžeme použití události u nějakého elementu zapsat jako:

<TAG událost=obsluha události>
Události, které lze obsloužit skriptem
UdálostPopis
onLoad Událost je vyvolána po natažení dokumentu do okna prohlížeče nebo do všech rámů v rámci jednoho FRAMESET. Atribut může být použit u elementů BODY a FRAMESET.
onUnLoad Událost je vyvolána po odstranění dokumentu z okna nebo rámu. Atribut může být použit s elementy BODY a FRAMESET.
onClick Událost je vyvolána po kliknutí myší na element. Atribut může být použit u většiny elementů.
onDblClick Událost je vyvolána po dvojitém kliknutí myší na element. Atribut může být použit u většiny elementů.
onMouseDown Událost je vyvolána po stisknutí tlačítka myši nad elementem. Atribut může být použit u většiny elementů.
onMouseUp Událost je vyvolána po uvolnění tlačítka myši nad elementem. Atribut může být použit u většiny elementů.
onMouseOver Událost je vyvolána při přesunutí myši nad element. Atribut může být použit u většiny elementů.
onMouseMove Událost je vyvolána při pohybu myši nad elementem. Atribut může být použit u většiny elementů.
onMouseOut Událost je vyvolána po odsunutí myši z elementu. Atribut může být použit u většiny elementů.
onFocus Událost je vyvolána v okamžiku, kdy je element aktivován myší nebo pomocí tabulátoru. Atribut je možno použít u elementů LABEL, INPUT, SELECT, TEXTAREA a BUTTON.
onBlur Událost je vyvolána v okamžiku, kdy element přestává být aktivní. Atribut je možno použít u elementů LABEL, INPUT, SELECT, TEXTAREA a BUTTON.
onKeyPress Událost je vyvolána po stisku a následném uvolnění tlačítka na klávesnici. Atribut může být použit u většiny elementů.
onKeyDown Událost je vyvolána po stisku tlačítka na klávesnici. Atribut může být použit u většiny elementů.
onKeyUp Událost je vyvolána po uvolnění tlačítka na klávesnici. Atribut může být použit u většiny elementů.
onSubmit Událost je vyvolána při odesílání formuláře. Atribut může být použit pouze u elementu FORM.
onReset Událost je vyvolána po vynulování formuláře. Atribut může být použit pouze u elementu FORM.
onSelect Událost je vyvolána po označení textu ve vstupním poli. Atribut může být použit u elementů INPUT a TEXTAREA.
onChange Událost je vyvolána pokud se změnila hodnota vstupního pole formuláře. Atribut může být použit u elementů INPUT, SELECT a TEXTAREA.

Přehled událostí, které můžeme použít, uvádí tabulka. Ukážeme si část stránky, kde se po najetí myší nad odkaz ve stavové řádce prohlížeče objeví vysvětlující text:

O rozvoj Webu se stará konsorcium
<A HREF="http://www.w3.org"
   onMouseOver="window.status='Kliknutím na odkaz se dostanete'
   + ' na domovskou stránku konsorcia W3C'">
W3C</A>
Jako obsluhu události bychom měli používat vyvolání dříve definované funkce, která zajistí všechny potřebné akce. Toto řešení nám usnadní pozdější změny v chování obsluhy události a zpřehlední zápis stránky v HTML.

Objektový model dokumentu

Objektový model dokumentu (DOM) uspořádává všechny objekty, které reprezentují prohlížeč a právě zobrazené stránky, do hierarchie, odkud je možné k jednotlivým objektům přistupovat a pracovat s nimi.

Základní hierarchie objektů
window
  |--location 
  |--frames 
  |--history 
  |--navigator 
  |--event 
  |--screen 
  +--document 
       |--links
       |--anchors
       |--images
       |--filters
       |--forms
       |--applets
       |--embeds
       |--plugins
       |--frames
       |--scripts
       |--all
       |--selection
       |--styleSheets
       +--body

Základním objektem je window, přes který jsou dostupné všechny další objekty. Nejdůležitějším objektem je document, který v sobě zahrnuje všechny objekty a vlastnosti vztahující se k aktuálnímu dokumentu. Na jednotlivé objekty v hierarchii (viz obrázek 5) se odvoláváme pomocí tečkové notace: window.screen, window.document, window.document.body.

Protože jsou všechny objekty potomky objektu window, může tento vynechávat. Zkráceně můžeme psát window.screen, document, document.body.

Na dalších nižších úrovních v objektové hierarchii mohou být buď další objekty anebo přímo vlastnosti a metody jednotlivých objektů. Vše si ukážeme na příkladě. Objekt document.all obsahuje všechny elementy obsažené v dokumentu. Přístupné jsou pomocí svého jména definovaného atributem ID:

<H1 ID=Nadpis>Pokusný nadpis</H1>
<P ID=Odstavec1>Text odstavce teď není důležitý
Nyní můžeme ve skriptech na stránce používat objekty document.all.Nadpis a document.all.Odstavec1, které zastupují element pro nadpis a odstavec. U těchto objektů máme k dispozici vlastnosti, které odpovídají atributům použitelným u odpovídajících elementů. Pomocí vlastnosti document.all.Nadpis.align můžeme měnit způsob zarovnání nadpisu. Následující ukázka obsahuje skript, který po kliknutí myší na nadpis změní jeho zarovnání zleva doprostřed. Jde o první ukázku skutečného dynamického HTML v dnešním tématu týdne.
<HTML>
<HEAD>
<TITLE>Ukázka dynamického HTML 1.</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
function ChangeAlign()
{
  document.all.Nadpis.align = "center";
}
// -->
</SCRIPT>
</HEAD>
<BODY>
<H1 ID=Nadpis ALIGN=LEFT
    onClick="ChangeAlign()">Pokusný nadpis</H1>
<P ID=Odstavec1>Text odstavce teď není důležitý
</BODY>
</HTML>
Z principu práce s dynamickým HTML vidíme, že stránka bez problémů bude pracovat i s prohlížeči, které dynamické HTML nepodporují. Jen se po kliknutí myší na nadpis nic nestane, protože tyto prohlížeče neumějí dynamicky měnit obsah stránky po jejím zobrazení. To však nijak dramaticky nesníží informační hodnotu stránky.

U objektů, které odpovídají elementům stránky, máme k dispozici vlastnost i objekt style. Pomocí vlastnosti style můžeme přistupovat k definici stylu elementu stejně jako pomocí atributu STYLE. Následující kód by změnil barvu a velikost nadpisu:

document.all.Nadpis.style = "color: red; font-size: 30px";
Zajímavé je, že style je zároveň vlastnost i celý objekt. Vlastnosti objektu style odpovídají jednotlivým vlastnostem stylů. Poslední efekt tedy můžeme dosáhnout i následujícím kódem:
document.all.Nadpis.style.color = "red";
document.all.Nadpis.style.fontSize = "30px"
Zajímavá je vlastnost innerText. Ta obsahuje text uvnitř elementu. Zápisem do této vlastnosti můžeme text změnit. Zkusme následující legrácku:
<HTML>
<HEAD>
<TITLE>Ukázka dynamického HTML 2.</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
function ChangeText()
{
  document.all.Nadpis.innerText = "Posloucháte mě pěkně!!!";
  document.all.Nadpis.style.color = "blue";
  document.all.Nadpis.style.fontSize = "50px";
}
// -->
</SCRIPT>
</HEAD>
<BODY>
<H1 ID=Nadpis onClick="ChangeText()">
Klikněte na tenhle nadpis a uvidíte, co se stane.</H1>
</BODY>
</HTML>
Dokonce lze měnit celý element, ne jen jeho obsah. Použijeme vlastnost outerHTML a předchozí ukázku upravíme tak, aby se po kliknutí místo nadpisu objevil obrázek:
<HTML>
<HEAD>
<TITLE>Ukázka dynamického HTML 3.</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
function ChangeText()
{
  document.all.Nadpis.outerHTML = "<IMG SRC=astro.gif>"
        + "<P>Kromě obrázku přidám i krátký odstavec textu.";
}
// -->
</SCRIPT>
</HEAD>
<BODY>
<H1 ID=Nadpis onClick="ChangeText()">
Klikněte na tenhle nadpis a uvidíte, co se stane.</H1>
</BODY>
</HTML>
V objektovém modelu nalezneme pod objektem document i kolekci styleSheets, která obsahuje jednotlivé styly připojené ke stránce. Pomocí její metody addRule(selektor, deklarace, index) můžeme do stylu přidávat nová pravidla. Následující dokument se po kliknutí myší celý vycentruje.
<HTML>
<HEAD>
<TITLE>Ukázka dynamického HTML 4.</TITLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
function ChangeDocumentAlign()
{
    document.styleSheets[0].addRule("BODY", "text-align: center", 0);
}
// -->
</SCRIPT>
<STYLE></STYLE>
</HEAD>
<BODY onClick="ChangeDocumentAlign()">
<H1>Nadpis</H1>
<P>A několik odstavců textu
</BODY>
</HTML>
Abychom mohli do kolekce stylů něco přidávat, musí kolekce existovat. Proto stránka obsahuje prázdný element STYLE, který vytvoří kolekci styleSheets s jedním prvkem.

Bohužel zde nemůžeme rozebrat celou objektovou hierarchii. Zmíníme se však ještě alespoň o několika zajímavostech. Adresa dokumentu, který je právě zobrazován, je přístupná přes objekt location. Pokud tedy chceme přímo skriptem změnit stránku, která se právě zobrazuje, můžeme použít příkaz location="http://někde.jinde.cz".

Pokud máme stránku rozdělenou na rámy, můžeme z jakéhokoliv rámu měnit stránku zobrazenou v ostatních rámech. Stačí novou adresu zapsat do parent.jméno_rámu.location. Tímto způsobem můžeme dosáhnout speciálních efektů, jako je změna obsahu více rámů najednou po zvolení jednoho odkazu. Vždy bychom však měli zvážit, zda je chováni stránky snadno pochopitelné pro její uživatele.

Úvod | Kaskádové styly | Ukázky | Přehled vlastností stylů | DHTML vs. Java


© Copyright 1998 Jiří Kosek, All Rights Reserved.
Stránka obsahuje plný text článku otištěného v týdeníku Computerworld dne 30. ledna 1998 (CW5/98).
Stránku připravil Jiří Kosek, jirka@kosek.cz
Poslední modifikace: 24-01-98