Události a jejich obsluha
Jedním ze základních paradigmat při vývoji počítačových programů všeho druhu je už několik desetiletí obsluha na událostí – hovoří se o programování řízeném událostmi (event-driven programming). Nastane-li nějaká událost, která je pro program významná, v reakci na ni se vykoná určitý kód.
Události mohou vznikat jak v programu, tak velmi často mimo něj. Nejčastějšími událostmi u webových aplikací je nějaká akce uživatele (třeba najetí kliknutí, stisk klávesy atd.), načtení dokumentu, dokončení nějakého efektu a podobně.
V řadě případů mají události implementovánu ve webovém prohlížeči nějakou výchozí reakci. Pokud si implementujeme svoji, lze ponechat i tu výchozí nebo ji nahradit. Některé události tzv. probublávají hierarchií DOM, takže pokud se na ně nereaguje na nižší úrovni, lze na ně reagovat výše.
Reakce na události v jQuery
V jQuery se využívají v zásadě dva způsoby, jak nastavovat reakce na události. Jednak jsou to speciální metody určené přímo pro tento účel, druhým způsobem je přiřazení do položek v objektu, který se předává nějaké metodě. Nyní se podíváme na první způsob, používaný například pro reakci na akce uživatele.
Metody on() a off()
Pro širokou škálu událostí lze použít metodu on()
pro nastavení reakce, resp. off()
pro její odebrání. Tady je příklad:
function showImageAlt() { alert($(this).attr('alt')); } $('img').on('click', showImageAlt);
Funkce showImageAlt()
slouží k zobrazení alternativního textu obrázku, na který uživatel klikne. Obsluha kliknutí se přiřadí zavoláním metody on()
. Obslužná funkce se vnitřně stane metodou instance třídy Element pro daný obrázek (kde událost nastala), takže lze s instancí pracovat přes this. Zrušení reakce je podobné:
$('img').off('click', showImageAlt);
Tento způsob volání se hodí pro případy, kdy je potřeba odebrat jen tuto konkrétní reakci (lze jich totiž nastavit libovolný počet). Pro globálnější odebírání lze někdy použít i jednodušší volání:
$('img').off('click'); $('img').off();
První řádek odebere všechny reakce na daný typ události (zde kliknutí), druhý odebere všechno, co bylo předtím nastaveno.
Dříve se pro nastavování a rušení reakcí na události používaly i další metody – bind()
/unbind()
, live()
a delegate()
. Od verze 1.7 ale není příliš důvod je používat, on()
a off()
totiž nabízejí vše pohromadě s jednotným rozhraním.
Pomocí metod on()
a off()
lze pracovat s mnoha různými událostmi – jejich přehled najdete v dokumentaci. Konkrétní škála se liší podle typu objektu v DOM, například událost submit
(odeslání) může vzniknout jen ve formuláři, zatímco keyup
(uvolnění klávesy) může nastat v libovolném vizuálním elementu. S metodou on()
lze dělat i další „kouzla“:
$('#abc').on('click.myApp', 'img', showImageAlt);
Příklad ukazuje hned dvě věci. Jednak je to vlastní jmenný prostor myApp
. Při pozdějším volání off()
lze pak použít celý název události, což způsobí odebrání jen té obsluhy, která je nastavena pro tento jmenný prostor; ostatních se to nedotkne:
$('#abc').off('click.myApp');
Druhá část se týká delegace obsluhy. Obsluha se nenastavuje pro obrázek (img)
, nýbrž pro nějaký nadřazený element a pak se filtruje. Kliknutí z obrázku probublá do daného nadřazeného elementu a použije se obslužná funkce nastavená pro tento element. Je to užitečné v případech, kdy se příslušný podstrom DOM mění (zde například přibývají a ubývají obrázky) a při přidání každého objektu by se jinak musela obsluha explicitně nastavit, což by bylo otravné. Tady se to dělat nemusí.
K záležitostem okolo probublávání událostí a delegace obsluhy se vrátíme příště. Je to relativně komplikovaná oblast a zaslouží si dostatečný prostor k vysvětlení.
Metoda one()
Výše uvedené metody nastavují obsluhu natrvalo, tedy do jejího odebrání, případně do zániku příslušného objektu DOM. Někdy je ale potřeba, aby se na událost reagovalo jen jednou. K tomu slouží metoda one()
, pracuje se s ní jako s on()
.
$('#menu').one('mouseenter', function() { alert('Toto je menu.'); });
Uvedený příklad zajistí, že když se poprvé najede kurzorem myši na prvek s identifikátorem „menu“, vyskočí informace o tom, k čemu prvek slouží. Při dalším najetí už obsluha události nebude aktivní a nic se tedy nestane. V příkladu vidíte využití anonymní funkce – toto řešení se v takových případech používá poměrně často (viz minulý díl).
Zjednodušené metody
Kromě uvedených univerzálních metod poskytuje jQuery celou řadu metod zjednodušených, určených pro konkrétní události. Znamenají poněkud méně psaní a hodí se pro případy, kdy není třeba využívat rozšířených vlastností univerzálních metod. Například příslušná část prvního příkladu s klikáním na obrázky by se dala přepsat takto:
$('img').click(showImageAlt);
Podobně existují například metody mouseenter()
, change()
, submit()
, resize()
a mnoho dalších. Zajímavé postavení zaujímá metoda ready()
, která se společně s metodou click()
objevila hned v první příkladu seriálu (ve druhém dílu). Ta se používá pro reakci na úplné dokončení přípravy nějakého objektu, nejčastěji celého dokumentu. Právě u dokumentu má největší význam, protože zajistí spuštění inicializačního kódu v okamžiku, kdy je celý dokument připraven k použití:
$(document).ready(function() { … });
Nevýhodou zjednodušených metod je, že nemají své „odebírací“ verze. Pro odebírání obsluhy se tedy musí volat off()
. Většinou se ale zjednodušené metody používají tam, kde se obsluha jednou nastaví a pak už neodebírá.
Vyvolání událostí
Pro ladicí účely i běžné použití je často potřeba nějakou událost vyvolat, i když obvykle nastává z jiného podnětu. Typickým případem je třeba automatický upload souboru hned po jeho výběru, bez nutnosti klikat na další tlačítko. Můžeme mít například následující formulář:
<form id="fileform" action="upload.php" method="post" enctype="multipart/form-data"> <input type="file" id="file" name="file" accept="image/*"> </form>
A potřebujeme, aby hned poté, co uživatel vybere soubor k odeslání, se data rovnou přenesla, bez nutnosti někam klikat (ani tu žádné odesílací tlačítko není). Jsou tedy potřeba dvě věci (v nejjednodušším případě; pro „blbuvzdornou“ aplikaci by bylo potřeba toho udělat trochu víc) – zareagovat na událost výběru souboru a formulář odeslat.
$('#file').change(function() { $('#fileform').submit(); });
Jak si můžete všimnout, formulář lze odeslat stejnou metodou, jakou se mu nastavuje obsluha této události. To platí obecně – pokud se zjednodušené metodě nedají žádné parametry, místo nastavení obsluhy události danou událost vyvolá. Další možností je použít metodu trigger()
, která umožňuje i předat obslužné funkci další parametry, což ale tady není potřeba.
Probublávání, delegace a další „věda“ okolo událostí
Tímto úvodem není samozřejmě problematika událostí a jejich obsluhy rozhodně vyčerpána. Vrátíme se k ní hned příště, protože si některá témata zaslouží podívat se na ně podrobněji.