Grafika publishing webtip.cz grafika.cz mujiPod.cz mujmac.cz fotografovani.cz printing.cz builder.cz galerie
webtip.cz
adresář  | práce  | diskuse  | redakce  | inzerce
 
 


  DHTML pro každého - 6. díl: Události a spouštění akcí
o autorovi 
poslat mailem 
tisknout článek 
aktuální rubrika 
Zpracování událostí (events) ve stránce, spouštění akcí na základě činnosti uživatele a změn ve stránce. Tabulka všech událostí a jejich podpora v prohlížečích.

Staníček Petr - 22.05.2002 - clanek - Rubrika: DHTML
Předchozí díl: DHTML pro každého - 5. díl: (Ne)viditelnost objektů
Seriál: 
Následující díl: Sothink DHTMLMenu - dynamické menu

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:

  1. 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()">
  2. 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


Hodnocení článku: -1- -2- -3- -4- -5-  Aktuální hodnocení: 2.77 (4493)

Relevantní články
Žádné články


Příspěvky do diskuse o aktuálním článku
Michal Aichinger14.01.20:35onDrag
Patrik17.06.16:21Probublávání
pikous24.05.9:33Přesně to co jsem hledal
Scorpi23.05.10:03Pochvala
  

 

  O vydavateli | Kontakt | Ceník reklamy | Ochrana osobních dat
©2002 Grafika Publishing. Všechna práva vyhrazena!