Asynchronní události
Stránka má nastaveny tyto příznaky:
- Informace jsou dopředně nekompatibilní. Některé popsané jazykové pravidla nebo postupy byly v pozdějších verzích zavrženy.
Obsah
Asynchronní událost
Událost, která není synchronní s přehráváním nebo obecně s během scriptu. Je zpracována paralelně, je to událost jejiž načasování závisí na externím faktoru (jako je kliknutí myši, odpověď serveru a podobně).
Event framework (systém událostí, chcete-li) je v ActionScriptu 2.0 nejednotný, celkem bezzubý a chaotický ve vztahu k objektovým kontextům (to byl pokus o překlad slova scope).
Jsou zhruba tři základní způsoby spouštění asynchronních událostí. Jejich syntaxi už jsem popisoval, teď půjdeme víc do hloubky.
Event-handler
Řekli bychom Obsluha události, což celkem přesně vyjadřuje podstatu věci.
Event handler je neobsazená metoda objektu, kterou Flash zavolá při určité události. Při kliku myší nad MovieClipem například Flash zavolá metodu tohoto MovieClipu onMouseDown().
Definice událostí přímo instanci pomocí on/onClipEvent-handleru
onClipEvent(enterFrame){ this._x ++; } on(press){ this._x = 0; }
Relikt z doby AS1.0. Definuje události blokem on a onClipEvent (pro některé události MC). Proč není použito jen on netuším, asi aby programátor u práce neusnul.
Je to obecně zavržený způsob, protože ho není možné dále skriptově měnit. A i z uživatelsko-editačního hlediska je pročesávání objektového stromu, za účelem nalezení definice události, na přeshubu.
Pochopitelně je tato varianta použitelná jen u tlačítka a MovieClipu, jiné typy display-objektů ostatně v AS1 neexistovaly.
Externí definice event-handleru objektu
Asi nejčastější způsob, protože jej používají skoro všechny předdefinované objekty, včetně datových.
myMC.onEnterFrame = function(){ this._x ++; } myMC.onPress = function(){ this._x = 0; }
Jako obsah handler metody jsem použil anonymní funkce, ale často se taky používají metody vlastních tříd. To je přehlednější, ale přináší to jisté problémy s objektovými kontexty - viz dále.
Každý handler může mít jen jednu funkci/metodu.
Zajímavou možností je zde ruční zavolání event-handleru.
myMC.onPress();
on/onClipEvent-handlery takhle ale zavolat nelze.
Event-listener
Všimněte si změny terminologie, z Obsluhy se nám stal Posluchač. Tento modernější model využívají některé předdefinované objekty a skoro všechny komponenty.
Figurují zde dva prvky: Broadcaster (vysílač) a Listener (posluchač). Posluchačů může být více než jeden.
var mouseListener:Object = new Object(); mouseListener.onMouseWheel = function(delta, targetMC) { targetMC._y += delta; }; Mouse.addListener(mouseListener);
Vidíte, že zde byl objektu Mouse přiřazen listener mouseListener, což je v tomto případě běžný generický objekt. Objekt Mouse pak při zatočení kolečkem myši zavolá u všech svých listenerů metodu onMouseWheel. Dokonce této metodě předá dva argumenty (počet odrolovaných řádků a ukazatel na MovieClip, nad kterým byla zrovna myš).
Listenerů můžeme připojit libovolné množství. Každý listener může zpracovávat libovolnou skupinu událostí.
Vlastní event-broadcaster
Pokud chcete vytvářet vlastní události systémem broadcastů, je ideální na to použít předdefinovaný objekt AsBroadcaster.
Broadcaster
var motion:Object = new Object(); motion.shift = function(targetMC:MovieClip, distance:Number):Void { if(targetMC._x + distance >= 100){ targetMC._x = 100; this.broadcastMessage('onBoundary', targetMC); return; } targetMC._x += distance; } AsBroadcaster.initialize(motion); // umožní objektu motion vysílat broadcasty
Nejprve samotný objekt, který bude vysílat event-broadcasty. Máme tu objekt motion s metodou shift, který posune MovieClip předaný v parametru o nějakou vzdálenost.
Předpokládejme, že chceme vyslat událost, že MC dosáhl maximální vzdálenosti (v našem případě 100 pixelů).
Velmi důležitý je poslední řádek, který běžnému objektu přidá metody pro vysílání událostí a připojování listenerů. Událost pak můžeme vyslat metodou broadcastMessage. Všimněte si, že můžeme do události kromě názvu připojit i další parametry (v našem případě daný MovieClip).
Listener
var listenerObject:Object = new Object(); listenerObject.onBoundary = function(target:MovieClip):Void{ trace('Objekt '+target._name+' je na okraji.') }
A zde už máme listener, který bude událost dosažení okraje sledovat.
Připojení listeneru
To už probíhá zcela běžně.
motion.addListener(listenerObject);
Když pak opakovaně použijeme metodu, při překročení hranice je vyvolána naše událost.
_root.mc._x = 0; motion.shift(_root.mc, 20); motion.shift(_root.mc, 20); motion.shift(_root.mc, 20); motion.shift(_root.mc, 50); // Objekt mc je na okraji
Delegát (mx.utils.Delegate)
Jak dříve nebo později zjistíte, při použití metody vlastního objektu jako event listeneru/handleru má ActionScript 2.0 smysl pro zápletku.
Listenery a handlery jsou volány v objektovém kontextu broadcasteru.
Pakáž.
Metoda volaná v jiném kontextu pak samozřejmě nemůže používat identifikátor this, protože ten v tu chvíli směruje někam do pryč. Tím pádem pro ni nejsou dostupné sousední prvky objektu.
class trida { private var vlastnost:String = 'Lorem Ipsum'; public function trida() { _root.mc.onPress = this.onPressHandler; } public function onPressHandler():Void { trace(vlastnost); // undefined trace(typeof this); // movieclip } }
Použití delegáta
Jako řešení nastupuje třída Delegate z balíčku mx.utils jako mezičlen, který funkci zavolá ve správném kontextu metodou Function.apply.
import mx.utils.Delegate; class trida { private var vlastnost:String = 'Lorem Ipsum'; public function trida() { _root.mc.onPress = Delegate.create(this, this.onPressHandler); } public function onPressHandler():Void { trace(vlastnost); // Lorem Ipsum trace(typeof this); // object } }
Pokud máte chuť, můžete se na třídu Delegate podívat sami, najdete ji v adresáři předdefinovaných tříd.
Závěrem
Nic z toho, co je tu psáno, ve verzi 3.0 neplatí. Ani řádek.
Eventy AS3 už nejsou broadcastovány, ale probublávají objektovým stromem podobně jako výjimky. Kdokoliv po cestě může událost vyslat a kdokoliv zase zachytit.