JavaScript, ExtJS 3.0 a Flash

Třetí verze JavaScriptové knihovny ExtJs vyšla loni v červnu. Jedna z nepřehlédnutelných funkcí, uvedených v nové verzi tohoto frameworku, je možnost zobrazovat data v grafech, realizována pomocí technologie Flash. V článku si popíšeme komunikaci mezi Flash objektem, JavaScriptem a ExtJs.
Nálepky:
Použité názvy a terminologie
Ujasněme si několik termínů:
- Adobe Flash je software pro vytváření animací ve formátu SWF pro přehrání v přehrávači Adobe Flash Player.
- Adobe Flex je je framework pro vytváření aplikací ve formátu SWF pro přehrávač Adobe Flash Player.
Laskavý čtenář jistě pochopí, budu-li pro zjednodušení dále v textu nazývat oboje Flash.
Flash (i Flex) využívá skriptovací jazyk ActionScript, který se v současné době nachází ve třetí verzi, což je nezbytné uvést, vzhledem ke značným odlišnostem od verzí předchozích.
JavaScript a Flash
Pro integraci Flashe s JavaScriptem nalezneme v dokumentaci jazyka Actionscript 3 rozhraní (realizované statickou třídou) flash.external.ExternalInterface. Toto rozhraní nám umožňuje zavolat funkci JavaScriptu metodou call anebo naopak definovat jméno metody viditelné v JavaScriptu a její propojení na metodu ve ActionScript objektu pomocí metody addCallback.
Test, zda je externí rozhraní dostupné, se provádí pomocí proměnné available. Tento test je nezbytný pokud budeme Flash spouštět ve Flash Playeru, tak i v prohlížeči.
Registrace metody doAlert, viditelné v JavaScriptu (ActionScript 3)
if (flash.external.ExternalInterface.available) { flash.external.ExternalInterface.addCallback('doAlert', doAlert); }
Tuto metodu je pak možné zavolat takto (JavaScript)
document.getElementById('flashObjectId').doAlert('Zpráva z JavaScriptu')
Volání metody alert
v JavaScriptu (ActionScript 3)
if (flash.external.ExternalInterface.available) { flash.external.ExternalInterface.call('alert', 'Javascript Alert called form Flash'); }
Alternativou použití tohoto interface je funkce fscommand, podporovaná v nižších verzích Actionscriptu a Flash Playeru, v současné době nedoporučovaná.
ExtJS a Flash
Ext.FlashComponent
ExtJS od verze 3.0 obsahuje třídu Ext.FlashComponent, potomka třídy Ext.BoxComponent. To znamená, že instance této třídy obsahuje metody pro pozicování a nastavení rozměrů komponent, čímž je postaráno o umístění a layout Flashe v rámci okna aplikace. Také to pro nás znamená, že instance bude umět pracovat s událostmi – jelikož je Ext.FlashComponent také potomkem Ext.util.Observable, jak můžeme zjistit pohledem na strom dědičnosti.
Události
Pro zajištění komunikace z Flashe do Javascriptu není nutné předávat data přímým voláním jednotlivých funkcí JavaScriptové aplikace pomocí funkce call
. ExtJS totiž z Flash objektu zachycuje události, které pak převádí na události ExtJS (třída Ext.EventObject). Realizuje to singletonem Ext.FlashEventProxy
, který najdete v dokumentaci (záhadně) přejmenovaný na Ext.FlashProxy
.
Název metody zpracovávající události (callback) se předává Flash objektu v parametru flashvars
v proměnné eventHandler
(obvyklou hodnotou je právě Ext.FlashEventProxy.onEvent
). Flash dostává zároveň v parametru flashvars
proměnnou elementID
, obsahující id komponenty ExtJS.
Událost se pak vyvolá metodou call
:
flash.external.ExternalInterface.call('Ext.FlashEventProxy.onEvent', id, data);
To vede ke spuštění metody onEvent
singletonu Ext.FlashEventProxy
. Metoda onEvent
najde podle předaného id příslušnou instanci Ext.FlashComponent
zavolá její metodu onFlashEvent
a předá jí data události. Metoda onFlashEvent
způsobí přímo vyvolání události ExtJS. Jméno události je uloženo ve vlastnosti type
objektu data
. Stručně řečeno, tento mechanismus nám umožňuje jednoduše převádět volání metody z Flashe na události ExtJS.
Aby objekt ExtJS byl schopen rozeznat, že Flash je již inicializován, je třeba vyvolat událost s rezervovaným jménem swfReady
, která způsobí inicializaci ExtJS komponenty a zároveň vyvolá událost initialize
. Je třeba zmínit, že druhým rezervovaným názvem události je log,
jejíž obsluha, jak je patrné při pohledu do kódu metody onFlashEvent
třídy Ext.FlashObject
, nedělá nic.
Volání metody ve Flashi
Při vykreslení instance Ext.FlashComponent
dojde k nastavení vlastnosti swf
, která obsahuje referenci na DOM element object
. Je-li ve Flashové animaci zaregistrována metoda pomocí addCallback
, pak je dostupná právě jako metoda objektu ve vlastnosti swf
.
Metodu doAlert
pak zavoláme takto:
this.swf.doAlert(message);
Parametrem metody může být i složitější datová struktura než pouhý textový řetězec, proto je výhodnější využít např. pro nastavení implicitních hodnot Flash objektu volání metody (setteru), než předávat hodnoty přes parametr flashvars
, který právě umožňuje předat pouze řetězec znaků.
Příklad
Zmíněné znalosti by nám měly stačit k vytvoření objektu, který bude umět zavolat metodu ve Flashi ( doAlert
) a také vyvolat událost ExtJS ( alert
).
Budeme vytvářet aplikaci, která po otevření indexové stránky zobrazí dvě tlačítka, jedno v HTML, jedno ve Flashi, kliknutí na „DoAlert“ vyvolá zobrazení message boxu ve Flashi, klinutí na „Call JavaScript method“ naopak zobrazí message box z ExtJS.
Vytvoříme třídu ExtJS, potomka Ext.FlashComponent, obsahující definici metody pro zobrazení zprávy ve Flashi (ExtTest.js)
var ExtTest = Ext.extend(Ext.FlashComponent, { url: 'ExampleExtJS.swf', doAlert: function(message) { this.swf.doAlert(message); } });
Při načtení stránky (index.html) a ExtJS provedeme skript, který nám vytvoří instanci třídy s flashovou animací a tlačítko, při jehož stisknutí pošleme zprávu do Flashe.
Ext.onReady(function() { var flashTest = new ExtTest({ renderTo: Ext.getBody(), width: 300, height: 200, listeners: { alert: function(event) { Ext.Msg.alert('Message', event.message); } } }); new Ext.Button({ renderTo: Ext.getBody(), text: 'Do Alert', handler: function() { flashTest.doAlert('Message form ExtJs') } }); });
Hlavní soubor flashové části aplikace obsahuje taktéž definici tlačítka, které naopak bude vyvolávat událost ExtJS (Main.mxml)
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="creationCompleteHandler()"> <mx:Button id="button1" label="Call Javascript method" click="clickHandler()" /> <mx:Script source="script.as"></mx:Script> </mx:Application>
Action skript flashové komponenty (script.as)
import flash.external.ExternalInterface; private function creationCompleteHandler():void { if (flash.external.ExternalInterface.available) { flash.external.ExternalInterface.addCallback('doAlert', doAlert); } this.addEventListener(Event.ADDED_TO_STAGE, function(): void { fireEvent({type: 'swfReady'}); }); } private function doAlert(text:String): void { mx.controls.Alert.show(text); } private function fireEvent(event: Object): void { var params : Object = LoaderInfo(this.root.loaderInfo).parameters; var eventHandler: String = params.eventHandler; if (flash.external.ExternalInterface.available) { flash.external.ExternalInterface.call(params.eventHandler, params.elementID, event); } } private function clickHandler(): void { fireEvent({ type: 'alert', message: 'Message from Flash' }); }
Můžete si stáhnout zdrojový kód příkladu, vyžaduje ExtJS.
Co je pod kapotou?
Flash Player běží v Internet Exploreru jako komponenta ActiveX, v ostatních prohlížečích využívá Netscape Plugin Application Programming Interface (NPAPI).
Při volání metody Flashe z JavaScriptu se využívá rozhraní ActiveX/NPAPI pro volání JavaScriptu, toto volání je však ještě zpracováváno dalšími interními funkcemi v JavaScriptu, které přidává Flash Player, lze je rozeznat podle prefixu __flash__. Interní JavaScriptové funkce Flash Playeru slouží k převodu parametrů volání externí JavaScriptové funkce do XML formátu a poté volají interní metodu CallFunction
, která zprostředkuje volání příslušné funkce.
Volání metody doAlert můžeme potom lze provést přímým voláním metody CallFunction
:
document.getElementById('flashObjectId').CallFunction("<invoke name="doAlert" returntype="javascript"><arguments><string>Message from JavaScript</string></arguments></invoke>")