Veškeré vymoženosti skriptů ve WWW stránkách by byly k ničemu bez možnosti volat funkce a provádět akce podle toho, co
se se stránkou právě děje. S "čistým" javascriptem vlastně můžeme něco udělat pouze během načítání kódu - když
při načítání stránky narazí prohlížeč na nějaký příkaz v sekci <script>, provede jej a zase pokračuje
v natahování dalšího obsahu. Poté, co se načítání stránky ukončí, skončí však i tyto aktivity a více bychom se ke skriptům
nedostali. Naštěstí existují tzv. události (events), které poskytují právě tu hlavní sílu skriptů: spouštět
akce na základě změn, které v dokumentu nastaly.
Většina těchto událostí je v prohlížečích předdefinována a pokrývají takřka všechny změny, které na stránce mohou
nastat. Od pohybu ukazatele (kurzoru myši) nad nějakým objektem, kliknutí myši či stisku klávesy, přes načtení nějakého
prvku či celého dokumentu, otevření a zavření okna, změnu fokusu okna (přesun do popředí/do pozadí) či nějakého
prvku, až po vypršení nastavené doby časovače či situaci, kdy nastane nějaká chyba v běhu programu. Každá z těchto předdefinovaných
událostí má přiřazen svůj ovladač (handler). Tento ovladač je pojmenován ve tvaru onUdálost - tedy
např. onClick, onLoad, onChange atd. - ten se zavolá, pokud tato událost nastane.
Události podporované v prohlížečích jsou uvedeny v následující tabulce, kde je kromě názvu a popisu události uvedeno i
v jakém prohlížeči je možné ji použít (NN = Netscape Navigator, IE = MS Internet Explorer, O = Opera).
| Ovladač (handler) |
Kdy událost nastane |
Prohlížeč |
| onabort |
Bylo přerušeno načítání obrázku (jen pro prvky <IMG>). |
IE4, NN3, 03 |
| onafterprint |
Byl ukončen tisk. |
IE5 |
| onafterupdate |
Po aktualizaci obsahu (je-li obsah vytvářen z databáze). |
IE4 |
| onback |
Uživatel stiskl tlačítko Zpět (Back) v prohlížeči. |
NN4 |
| onbeforecopy |
Těsně před zahájením kopírování do schránky (Ctrl-C). |
IE5 |
| onbeforecut |
Těsně před zahájením vyjmutí do schránky (Ctrl-X). |
IE5 |
| onbeforeeditfocus |
Před tím, než je fokus přesměrován na jiný prvek. |
IE5 |
| onbeforepaste |
Těsně před zahájením vložení ze schránky (Ctrl-V). |
IE5 |
| onbeforeprint |
Před zahájením tisku. |
IE5 |
| onbeforeunload |
Před tím, než je zavolána událost onunload (viz dále). |
IE4 |
| onbeforeupdate |
Před aktualizací obsahu (je-li obsah vytvářen z databáze). |
IE4 |
| onblur |
Prvek ztratil fokus, tj. uživatel vybral jiný prvek. |
IE3, NN2, 03 |
| onbounce |
Pokud obsah prvku <MARQUEE> "narazí" na okraj rámečku.
Jen pro prvky <MARQUEE>. |
IE4 |
| onchange |
Byla změněna hodnota prvku (používá se vesměs jen na formulářové prvky). Událost se většinou generuje až po opuštění
(změna fokusu) prvku. |
IE4, NN2, 03 |
| onclick |
Uživatel kliknul na prvek (stiskl a poté uvolnil tlačítko myši ve chvíli, kdy byl kurzor nad prvkem). |
IE3, NN2, 03 |
| oncontentready |
Bylo ukončeno načítání/zpracování prvku, jenž je přiřazen danému objektu. |
IE5 |
| oncontextmenu |
Uživatel si vyžádal kontextové menu (např. stiskl pravé tlačítko myši). |
IE5 |
| oncopy |
Uživatel si vyžádal kopírování do schránky (Ctrl-C). |
IE5 |
| oncut |
Uživatel si vyžádal vyjmutí do schránky (Ctrl-X). |
IE5 |
| ondataavailable |
Pokud asynchronně dorazila nějaká data z appletu či datového zdroje. |
IE4 |
| ondatasetchanged |
Pokud datový zdroj změnil obsah nebo jsou nějaká výchozí data jsou připravena ke zpracování. |
IE4 |
| ondatasetcomplete |
Pokud již nejsou žádná další data k přenosu z datového zdroje. |
IE4 |
| ondblclick |
Uživatel provedl dvojklik na prvku (dvojí stisknutí tlačítka myši v krátkém
intervalu po sobě). |
IE4, NN4, 03 |
| ondrag |
Nastala operace Táhnout (Drag&Drop) - uživatel přesunuje objekt se stisknutým
tlačítkem myši. |
IE5 |
| ondragdrop |
Do okna prohlížeče byla (po tažení) puštěna nějaká data. |
NN4 |
| ondragend |
Ukončení operace Táhnout. |
IE5 |
| ondragenter |
Tažený objekt "vstoupil" do daného objektu. |
IE5 |
| ondragleave |
Tažený objekt "opustil" daný objekt. |
IE5 |
| ondragover |
Volá se opakovaně, když je objekt tažený nad daným objektem (tj. mousemove mezi dragenter
a dragleave). |
IE5 |
| ondragstart |
Uživatel zahájil výběr dat tažením myši. |
IE5 |
| ondrop |
Do okna prohlížeče byla (po tažení) puštěna nějaká data. |
IE5 |
| onerror |
Nastala chyba. Jako atribut v HTML je implementován jen tagy pro <IMG>,
<LINK>, <OBJECT>, <SCRIPT> a <STYLE>
a je generován, nastane-li chyba při načítání obrázku. V JS je ale možné použít i window.onerror pro zpracování
chyb při běhu skriptu. |
IE4, NN3, 03 |
| onerrorupdate |
Nastala chyba při přenosu dat z datového zdroje. |
IE4 |
| onfilterchange |
Filtr změnil stav prvku nebo byl ukončen přechod/střih. |
IE4 |
| onfinish |
Objekt <MARQUEE> ukončil smyčku (jen pro prvky <MARQUEE>). |
IE4 |
| onfocus |
Prvek je vybrán jako aktivní, je označen pro vstup (získal fokus). |
IE3, NN2, 03 |
| onforward |
Uživatel stiskl tlačítko Vpřed (Forward) v prohlížeči. |
NN4 |
| onhelp |
Uživatel si vyžádal nápovědu (např. stisk F1, výběr Nápověda/Help z menu). |
IE4 |
| onkeydown |
Byla stisknuta klávesa. |
IE4, NN4, 03 |
| onkeypress |
Byla stisknuta a poté uvolněna klávesa. |
IE4, NN4, 03 |
| onkeyup |
Byla uvolněna klávesa. |
IE4, NN4, 03 |
| onload |
Bylo dokončeno načtení objektu. |
IE3.02, NN2, 03 |
| onlosecapture |
Prvek ztratil oprávnění pro "zachycování" událostí. |
NN4 |
| onmousedown |
Bylo stisknuto tlačítko myši. |
IE4, NN4, 03 |
| onmousedrag |
Pohyb se stisknutým tlačítkem myši. |
IE5 |
| onmousemove |
Generuje se peridicky, pokud se kurzor myši pohybuje nad prvkem. |
IE4, NN4 |
| onmouseout |
Kurzor myši opustil prostor, který na obrazovce zabírá prvek reprezentující daný objekt. |
IE4, NN3, 03 |
| onmouseover |
Kurzor myši vstoupil do prostoru, který na obrazovce zabírá prvek reprezentující daný
objekt. |
IE4, NN3, 03 |
| onmouseup |
Bylo uvolněno tlačítko myši. |
IE4, NN3, 03 |
| onmove |
Bylo pohnuto oknem prohlížeče. |
NN4 |
| onpaste |
Uživatel si vyžádal vložení ze schránky (Ctrl-V). |
IE5 |
| onpropertychange |
Byla změněna nějaká vlastnost objektu (obdoba watch() v NN). |
IE5 |
| onreadystatechange |
Objekt v okně změnil svůj stav připravenosti (readyState). |
IE4 |
| onreset |
Uživatel stiskl tlačítko Obnovit/Reset ve formuláři. |
IE4, NN3, 03 |
| onresize |
Byly změněny rozměry okna prohlížeče. |
IE4, NN4 |
| onrowenter |
Mění se data v poli svázaná s datovým zdrojem. |
IE4 |
| onrowexit |
Data v poli svázaná s datovým zdrojem byla změněna. |
IE4 |
| onrowsdelete |
Z databáze budou smazána nějaká data. |
IE4 |
| onrowsinserted |
Do databáze budou vložena nová data. |
IE4 |
| onscroll |
Obsah okna byl posunut (skrollováním). |
IE4 |
| onselect |
Byl označen (selektován) textový obsah v okně. |
IE4, NN2, 03 |
| onselectstart |
Zahájení operace označování (selekce) textu. |
IE4 |
| onstart |
Objekt <MARQUEE> zahájil smyčku (jen pro prvky <MARQUEE>). |
IE4 |
| onstop |
Uživatel přerušil načítání stránky. |
NN4 |
| onsubmit |
Uživatel stiskl tlačítko Odeslat/Submit ve formuláři. |
IE3, NN2, 03 |
| onunload |
Dokument bude uzavřen (tj. před zavřením okna prohlížeče nebo načtením nového dokumentu).
Není zde prostor na dlouhé či složité operace, doporučuje se pouze nějaký "úklid" (smazání nepotřebných
dat apod.) |
IE3, NN2, 03 |
Pozn. 1: Prohlížeč NN před verzí 6 má ještě další možnosti práce s událostmi (např. captureEvents, releaseEvents),
NN6 již ale přešel na práci s událostmi podle DOM-2, a tak funkce NN4 již nemají další perspektivu. Nebudeme se jim zde
proto věnovat.
Pozn. 2: DOM ve verzi 2 přinesl změnu do zpracování událostí: pomocí objektů EventTarget a EventListener
umožnil zobecnění definování eventů a jejich zpracování. Této technologii se však budeme věnovat později - prozatím
si vystačíme s faktem, že prohlížeče podporující DOM-2 (Mozilla) podporují i většinu původních událostí ze starších verzí
prohlížečů. Za "standardní" lze pokládat ty, které jsou dle výše uvedené tabulky podporovány
v prohlížečích NN i MSIE.
Zpracování událostí
Každý z výše uvedených ovladačů (handlerů) může mít přiřazen kód, který se má provést, pokud událost nastane. Výchozí
hodnotou je většinou null, tzn. že událost nevyvolá žádnou akci. Chceme-li akci pro daný objekt při určité
události přiřadit, existují dvě možnosti:
- Přímo v HTML pomocí atributu odpovídajímu názvu ovladače. Jeho hodnotou je tělo funkce, která se má
provést, když událost nastane. Jméno atributu v HTML není case-sensitive (nerozlišují se malá/velká písmena),
může být tedy použito např. onload, onLoad, ONLOAD (v XHTML však již musí být jména atributů pouze malými písmeny).
Syntaxe je tedy: <tag ... onEvent="kód" ...>
např. <a href="..." onclick="alert('Zprava');return false">
nebo:<a href="..." onClick="ovladacOnClick()">
- Ve skriptu přiřazením hodnoty té metodě objektu, která reprezentuje daný ovladač. Tyto metody rovněž
odpovídají názvům ovladačů (viz tabulka výše), musí být psány malými písmeny (ačkoli
některé prohlížeče, třeba NN4, akceptují i jména handlerů s velkými písmeny, rozhodně se to nedoporučuje používat).
Jejich hodnotou je jméno funkce, na niž ovladač přesměrujete - tato funkce se pak sama stává ovladačem dané události:
Syntaxe: mujObjekt.onevent = nazev_funkce;
např.: mujObjekt.onclick = ovladacOnClick;
Pozn.: Ovladače událostí by měly vracet logickou hodnotu true|false (důvod viz Předávání událostí
níže). Pokud ji nevracejí, není to chybou a v naprosté většině případů to nezpůsobí žádný problém - v budoucnu však mohou
být požadavky prohlížečů již přísnější, je proto vhodné si vracení hodnoty z ovladače osvojit jako dobrý zvyk.
Je důležité dát si pozor na rozdíl v definování ovladačů v HTML a ve skriptu - zatímco v HTML ovladači přiřazujete
přímo kód, ve skriptu je jeden mezikrok navíc: objektu přiřazujete pouze název funkce, která se tak sama stává ovladačem
- kód, který se má provést, je až v těle této funkce. V podstatě jsou však oba případy shodné - pouze u HTML proběhne
toto přiřazení skrytě: napíšeme-li např.:
<div id="prvek" onclick="alert('Ahoj');return true">...
vytvoří se vlastně (skrytá, anonymní) funkce, které se volá pokaždé, když uživatel klikne na objekt "prvek".
Stane se tedy totéž, jako bychom ve skriptu napsali:
document.getElementById('prvek').onclick = function() {
alert('Ahoj');
return true;
}
Zdůrazňuji to zde především proto, abychom se vyvarovali časté chyby, která pramení právě z nedostatečného pochopení tohoto
mechanismu, kdy autor do metody onevent nějakého objektu přiřadí místo funkce její hodnotu, obdobně jako při zápisu
v atributu HTML značky. Ukažme si to na příkladu: celkem časté je potřeba spuštění nějaké inicializační funkce po načtení
stránky (tedy po události onload celého dokumentu). Připravíme si např. funkci Init(), která se má po načtení
stránky zavolat; událost pak můžeme přiřadit dvěma způsoby:
<script type="text/javascript">
...
function Init() {
...
}
...
</script>
</head>
<body onload="Init()">
...
nebo pomocí javascriptu (načtení dokumentu odpovídá onload objektu window):
<script type="text/javascript">
...
window.onload = Init;
function Init() {
...
}
...
</script>
</head>
<body>
...
Velmi často se však stane, že autor ve druhém případě omylem zapíše:
window.onload = Init();
což rozhodně nebude produkovat to, co autor zamýšlel. Prvním zápisem <body onload="Init()">
vlastně definujeme tělo nějaké skryté funkce, stejně jako bychom napsali window.onload = function() { Init() }
- když při načítání stránky prohlížeč narazí na značku <body>, vytvoří tuto anonymní funkci, která
se stane ovladačem události onload. Po načtení celé stránky se tato událost aktivuje, zavolá se její ovladač (ona
anonymní funkce) a provede se její tělo - tedy zavolá se funkce Init().
Zápisem window.onload = Init(); však definujeme příkaz - a příkazy se provádějí ihned. My zde tímto
příkazem přiřazujeme metodě window.onload hodnotu funkce Init() - jelikož tato funkce žádnou
hodnotu nevrací, provedeme vlastně přiřazení window.onload = null, takže po načtení stránky žádná
akce neproběhne, protože ovladač window.onload má hodnotu null. Abychom dosáhli požadovaného účinku,
musíme tedy ovladači onload přiřadit ne hodnotu funkce (Init()), ale funkci samu (Init).
Je tedy důležité rozlišovat oba zápisy:
<body onload="Init()">
ale
window.onload = Init;
Předávání událostí
Na každé stránce se vždy nachází několik objektů na sobě - tak jak jsou uspořádány ve stromu dokumentů. V okně (objekt
window) se nachází document, v něm např. <DIV>, v něm je <P> a v něm
pak <A>. Javascript řeší předávání událostí mezi překrývajícími se prvky, a to pomocí technologie,
která se anglicky výstižně jmenuje event bubbling (česky - řekněme - probublávání událostí). Funguje to
tak, že nastalou událost dostane jako první ke zpracování prvek, který je umístěn na ploše stránky "nejvýše"
(tedy je nejhlouběji ve stromu dokumentu), potom ji předá svému rodičovskému prvku, ten pak svému atd. - takto událost
probublá až na vrchol stromu.
Kdykoli v průběhu zpracování události je ale možné ji zastavit a další předávání zakázat - zpracuje-li nějaký prvek událost,
jeho rodičovský prvek se tak už o ní nemusí dozvědět. Dostáváme se zde k již zmíněným návratovým hodnotám ovladačů - ty
slouží právě k řízení bubblingu událostí. Logická hodnota, kterou vrátí ovladač, říká, zda se má událost přepustit
dál:
- vrátí-li ovladač události true, událost se předá dalšímu prvku v hierachii
- vrátí-li ovladač události false, událost se "skartuje" a rodičovské prvky ji nedostanou
Pozn.: Pokud ovladač nevrací žádnou hodnotu, je další zpracování události na prohlížeči - obvykle se však chová
tak, jako by byla vrácena hodnota true (ale jak již bylo řečeno, v budoucnu se může chování prohlížečů změnit a
je proto dobré zvyknout si logickou hodnotu z ovladače vracet vždy).
S probubláváním je důležité počítat i u skrytých událostí. Některé prvky v sobě totiž mají integrováno zpracování
událostí, které je jinak skryto a je vlastní jen danému typu prvku - typickou ukázkou může být hypertextový odkaz (HTML
značka <A>), který provede akci (přesměruje dokument na novou adresu), když na něj uživatel klikne
(nebo jej jiným způsobem aktivuje). Pokud do této značky přidáme vlastní ovladač události, např. onclick, dostane
sice přednost před původním zpracováním aktivace odkazu, to však zůstane nad ním v hierachii. Nezakážeme-li další předávání
události, po zpracování našeho onclick se kliknutí dostane i k původnímu ovladači a proběhne tedy běžné přesměrování.
Porovnejme následující dvě ukázky:
<a href="novastranka.html" onclick="nejakaFunkce()">odkaz</a>
<a href="novastranka.html" onclick="nejakaFunkce();return false">odkaz</a>
V prvním případě náš ovladač onclick nevrací žádnou hodnotu (tedy jakoby vracel true) - po kliknutí na odkaz
se nejprve provede naše funkce a poté se událost kliknutí myši dostane k samotnému prvku <a>,
který do okna prohlížeče načte nový dokument novastranka.html. Ve druhém případě však náš ovladač vrací hodnotu
false, která zakáže další zpracování události - takže samotný prvek <a> se o kliknutí nedozví
a k žádnému přesměrování nedojde. S tímto je důležité počítat například při otevírání odkazů do nového okna daných vlastností
- např. otevření obrázku ve vyšším rozlišení v okně dialogového typu (bez menu, scrollbarů, nástrojové lišty, daných rozměrů
atd.)
function otevriObrazek(url) {
window.open(url,'obrazek','toolbar=0,location=0,status=0,...');
return false;
}
...
<a href="obrazek_velky.jpg" onclick="return otevriObrazek('obrazek_velky.jpg')">
<img src="obrazek_maly.jpg" alt="" ...></a>
Pokud bychom zde nevrátili hodnotu false, obrázek by se sice otevřel v novém okně, ale poté by se načetl i do okna
místo původního dokumentu, což většinou není žádoucí.
Návratových hodnot můžeme také využít pro řízení událostí podle nějakého předchozího nastavení - např. podle dříve zjištěných
možností prohlížeče či podle předvoleb uživatele. Uživatel si např. v předvolbách zvolí, zda chce otevírat texty příspěvků
ve zvláštním okně, či v okně stávajícím. Pokud tento údaj budeme mít v nějaké proměnné, můžeme podle ní řídit chování
odkazů:
var vNovemOkne;
...
function otevriOdkaz(url) {
if (vNovemOkne) {
window.open(url,....);
return false;
}
else return true;
}
...
<a href="adresa" onclick="return otevriOdkaz(this.href)">odkaz</a>
Po kliknutí na odkaz se nejprve zavolá funkce (ovladač) otevriOdkaz() a ta podle hodnoty globální proměnné vNovemOkne
buďto otevře odkaz v novém okně (daných vlastností) a vrátí false (událost se zahodí a nic dalšího se nestane)
- anebo neudělá nic a vrátí true (odkaz se pak zpracuje běžným způsobem).
Příště se budeme věnovat dalším podrobnostem práce s událostmi.
Použitelnost prvků zmíněných v tomto díle:
Element.onevent
- viz tabulka výše
Staníček Petr
|