Ta aplikacja przykładowa prezentuje odpowiednie techniki komunikacji między kodami ActionScript i JavaScript w przeglądarce sieci Web, w kontekście aplikacji Instant Messaging, która umożliwia użytkownikowi czatowanie z samym sobą (stąd nazwa aplikacji: Introvert IM). Komunikaty są wysyłane między HTML na stronie sieci Web, a interfejsem SWF za pomocą zewnętrznego interfejsu API. Technika przedstawiona na tym przykładzie obejmuje:
-
Poprawne zainicjowanie komunikacji poprzez sprawdzenie, czy przeglądarka jest gotowa do komunikacji, następnie skonfigurowanie komunikacji
-
Sprawdzenie, czy kontener obsługuje zewnętrzny interfejs API
-
Wywołanie funkcji JavaScript z kodu ActionScript, przekazanie parametrów i odebranie wartości w odpowiedzi
-
Udostępnienie ActionScript metod do wywołania przez kod JavaScript, a następnie wykonanie wywołań
Aby pobrać pliki tej przykładowej aplikacji, należy przejść na stronę
www.adobe.com/go/learn_programmingAS3samples_flash_pl
. Pliki aplikacji Introvert IM są dostępne w folderze Samples/IntrovertIM_HTML. Aplikacja składa się z następujących plików:
File
|
Opis
|
IntrovertIMApp.fla
lub
IntrovertIMApp.mxml
|
Główny plik aplikacji w formacie Flash (FLA) lub Flex (MXML).
|
com/example/programmingas3/introvertIM/IMManager.as
|
Klasa, która nawiązuje i utrzymuje połączenie między ActionScript a kontenerem.
|
com/example/programmingas3/introvertIM/IMMessageEvent.as
|
Niestandardowe zdarzenie wywoływane przez klasę IMManager po odebraniu komunikatu z kontenera.
|
com/example/programmingas3/introvertIM/IMStatus.as
|
Uporządkowanie, którego wartości reprezentują różne wartości statusu „dostępność”, jakie mogą być wybierane w aplikacji.
|
html-flash/IntrovertIMApp.html
lub
html-template/index.template.html
|
Strona HTML dla aplikacji Flash (html-flash/IntrovertIMApp.html) lub szablonu, który służy do tworzenia strony HTML kontenera dla aplikacji dla Adobe Flex (html-template/index.template.html). Ten plik zawiera wszystkie funkcje JavaScript, które tworzą część kontenera aplikacji.
|
Przygotowanie do komunikacji kodu ActionScript z przeglądarką
Jednym z najczęstszych zastosowań zewnętrznego interfejsu API jest umożliwianie komunikacji aplikacji ActionScript z przeglądarką sieci Web. Dzięki zewnętrznemu interfejsowi API metody ActionScript mogą wywoływać kod zapisany w języku JavaScript i vice versa. Z powodu złożoności przeglądarek i sposobu, w jaki renderują wewnętrznie strony nie ma możliwości zagwarantowania, że dokument SWF zarejestruje swoje wywołania przed uruchomieniem pierwszego kodu JavaScript na stronie HTML. Z tego powodu przed wywołaniem funkcji w dokumencie SWF (z kodu JavaScript) dokument SWF zawsze powinien wywołać stronę HTML, aby powiadomić ją o tym, że dokument SWF jest gotowy do zaakceptowania połączeń.
Na przykład: w serii kroków wykonanych przez klasę IMManager aplikacja Introvert IM określa, czy przeglądarka jest gotowa na komunikację, a następnie przygotowuje plik SWF dla komunikacji. Pierwszy krok — określenie, czy przeglądarka jest gotowa do komunikacji — odbywa się w konstruktorze IMManager:
public function IMManager(initialStatus:IMStatus)
{
_status = initialStatus;
// Check if the container is able to use the external API.
if (ExternalInterface.available)
{
try
{
// This calls the isContainerReady() method, which in turn calls
// the container to see if Flash Player has loaded and the container
// is ready to receive calls from the SWF.
var containerReady:Boolean = isContainerReady();
if (containerReady)
{
// If the container is ready, register the SWF's functions.
setupCallbacks();
}
else
{
// If the container is not ready, set up a Timer to call the
// container at 100ms intervals. Once the container responds that
// it's ready, the timer will be stopped.
var readyTimer:Timer = new Timer(100);
readyTimer.addEventListener(TimerEvent.TIMER, timerHandler);
readyTimer.start();
}
}
...
}
else
{
trace("External interface is not available for this container.");
}
}
Najpierw kod sprawdza, czy zewnętrzny interfejs API jest dostępny w bieżącym kontenerze — w tym celu korzysta z właściwości
ExternalInterface.available
. Jeśli jest dostępny, kod rozpoczyna konfigurowanie komunikacji. Podczas próby nawiązania połączenia z aplikacją zewnętrzną mogą wystąpić wyjątki zabezpieczeń i inne błędy, dlatego kod jest opakowany blokiem
try
(odpowiadające bloki
catch
zostały usunięte z przykładu w celu jego skrócenia).
Następnie kod wywołuje metodę
isContainerReady()
, co przedstawiono poniżej:
private function isContainerReady():Boolean
{
var result:Boolean = ExternalInterface.call("isReady");
return result;
}
Z kolei metoda
isContainerReady()
wykorzystuje metodę
ExternalInterface.call()
w celu wywołania funkcji
isReady()
JavaScript w następujący sposób:
<script language="JavaScript">
<!--
// ------- Private vars -------
var jsReady = false;
...
// ------- functions called by ActionScript -------
// called to check if the page has initialized and JavaScript is available
function isReady()
{
return jsReady;
}
...
// called by the onload event of the <body> tag
function pageInit()
{
// Record that JavaScript is ready to go.
jsReady = true;
}
...
//-->
</script>
Funkcja
isReady()
po prostu zwraca wartość zmiennej
jsReady
. Ta zmienna na początkowo wartość
false
; po wywołaniu zdarzenia
onload
strony sieci Web wartość zmiennej zostaje zmieniona na
true
. Innymi słowy: gdy kod ActionScript wywoła funkcję
isReady()
przed załadowaniem strony, kod JavaScript zwraca wartość
false
do
ExternalInterface.call("isReady")
, a w konsekwencji metoda ActionScript
isContainerReady()
również zwraca wartość
false
. Po załadowaniu strony funkcja JavaScript
isReady()
zwraca wartość
true
, dlatego metoda ActionScript
isContainerReady()
również zwraca
true
.
W konstruktorze IMManager dochodzi do jednej z dwóch operacji w zależności od gotowości konstruktora. Jeśli metoda
isContainerReady()
zwróci wartość
true
, kod po prostu wywołuje metodę
setupCallbacks()
, która kończy proces konfigurowania komunikacji z JavaScript. Z drugiej strony: jeśli
isContainerReady()
zwraca
false
, proces jest wstrzymywany. Następuje utworzenie obiektu Timer, który wywołuje metodę
timerHandler()
co 100 milisekund:
private function timerHandler(event:TimerEvent):void
{
// Check if the container is now ready.
var isReady:Boolean = isContainerReady();
if (isReady)
{
// If the container has become ready, we don't need to check anymore,
// so stop the timer.
Timer(event.target).stop();
// Set up the ActionScript methods that will be available to be
// called by the container.
setupCallbacks();
}
}
Przy każdym wywołaniu metoda
timerHandler()
ponownie sprawdza wynik metody
isContainerReady()
. Po zainicjowaniu kontenera metoda zwraca wartość
true.
Następnie kod zatrzymuje obiekt Timer i wywołuje metodę
setupCallbacks()
w celu zakończenia konfigurowania komunikacji z przeglądarką.
Aktywacja metod ActionScript w JavaScript
Zgodnie z poprzednim przykładem — gdy kod ustali, że przeglądarka jest gotowa, następuje wywołane metody
setupCallbacks()
. Ta metoda przygotowuje kod ActionScript w celu odbierania wywołań z JavaScript:
private function setupCallbacks():void
{
// Register the SWF client functions with the container
ExternalInterface.addCallback("newMessage", newMessage);
ExternalInterface.addCallback("getStatus", getStatus);
// Notify the container that the SWF is ready to be called.
ExternalInterface.call("setSWFIsReady");
}
Metoda
setCallBacks()
kończy zadanie przygotowania komunikacji z kontenerem — w tym celu wywołuje metodę
ExternalInterface.addCallback()
w celu zarejestrowania dwóch metod, które będą mogły być wywoływane z JavaScript. W tym kodzie pierwszy parametr — nazwa, pod którą metoda jest znana w kodzie JavaScript (
"newMessage"
oraz
"getStatus"
) — jest taki sam jak nazwa metody w ActionScript. (W tym przypadku używanie różnych nazw nie przyniosło żadnych korzyści, dlatego w celu uproszczenia ponownie użyto tej samej nazwy). Na koniec metoda
ExternalInterface.call()
wywołuje funkcję
setSWFIsReady()
JavaScript, która powiadamia kontener o tym, że funkcje ActionScript zostały zarejestrowane.
Komunikacja kodu ActionScript z przeglądarką
Aplikacja Introvert IM prezentuje gamę przykładowych wywołań funkcji JavaScript na stronie kontenera. W najprostszym przypadku (przykład z metody
setupCallbacks()
), funkcja
setSWFIsReady()
JavaScript zostaje wywołana bez użycia żadnych parametrów i bez odbierania wartości zwracanych:
ExternalInterface.call("setSWFIsReady");
W innym przykładzie z metodą
isContainerReady()
kod ActionScript wywołuje funkcję
isReady()
i odbiera wartość logiczną w odpowiedzi:
var result:Boolean = ExternalInterface.call("isReady");
Za pomocą zewnętrznego interfejsu API można również przekazywać parametry do kodu JavaScript. Na przykład: rozważmy metodę
sendMessage()
klasy IMManager, która zostaje wywołana, gdy użytkownik wysyła nowy komunikat do „partnera konwersacji”:
public function sendMessage(message:String):void
{
ExternalInterface.call("newMessage", message);
}
Ponownie metoda
ExternalInterface.call()
służy do wywołania wyznaczonej funkcji JavaScript, powiadamiając przeglądarkę o nowym komunikacie. Ponadto komunikat jest przekazywany jako dodatkowy parametr do metody
ExternalInterface.call()
i w konsekwencji jest przekazywany do funkcji
newMessage()
JavaScript.
Wywołanie kodu ActionScript z kodu JavaScript
Komunikacja powinna odbywać się w dwóch kierunkach, a aplikacja Introvert IM nie jest wyjątkiem od tej zasady. Klient IM Flash Player nie tylko wywołuje JavaScript w celu wysyłania komunikatów, ale ponadto HTML wywołuje kod JavaScript w celu wysyłania komunikatów do pliku SWF i żądania informacji z pliku SWF. Na przykład: gdy plik SWF powiadomi kontener o tym, że ukończył nawiązywanie połączenia i jest gotowy do komunikacji, wówczas przeglądarka najpierw wywołuje metodę
getStatus()
klasy IMManager w celu uzyskania wstępnego statusu dostępności użytkownika od klienta IM SWF. Odbywa się to na stronie sieci Web, w funkcji
updateStatus()
:
<script language="JavaScript">
...
function updateStatus()
{
if (swfReady)
{
var currentStatus = getSWF("IntrovertIMApp").getStatus();
document.forms["imForm"].status.value = currentStatus;
}
}
...
</script>
Kod sprawdza wartość zmiennej
swfReady
, która śledzi, czy plik SWF powiadomił przeglądarkę o tym, że jej metody zostały zarejestrowane w klasie ExternalInterface. Jeśli plik SWF jest gotowy na odbieranie komunikacji, następna linia (
var currentStatus =
...) wywołuje metodę
getStatus()
w klasie IMManager. Ta linia kodu wykonuje trzy operacje:
-
Wywołuje funkcję
getSWF()
JavaScript, zwracając odwołanie do obiektu JavaScript reprezentującego plik SWF. Parametr przekazany do
getSWF()
określa obiekt przeglądarki, który jest zwracany w przypadku, gdy strona HTML zawiera więcej niż jeden plik SWF. Wartość przekazana do tego parametru musi być zgodna z atrybutem
id
znacznika
object
i atrybutem
name
znacznika
embed
, dzięki któremu możliwe jest dołączenie pliku SWF.
-
Odwołanie do pliku SWF powoduje wywołanie metody
getStatus()
w taki sposób, jakby była to metoda obiektu SWF. W tym przypadku używana jest nazwa funkcji „
getStatus
”, ponieważ jest to nazwa, pod jaką funkcja ActionScript została zarejestrowana za pomocą metody
ExternalInterface.addCallback()
.
-
Metoda
getStatus()
ActionScript zwraca wartość, a ta wartość zostaje przypisana do zmiennej
currentStatus
, która następnie zostaje przypisana jako treść (właściwość
value
) pola tekstowego
status
.
Uwaga:
Osoby, które śledzą kod, zauważyły zapewne, że w kodzie źródłowym funkcji
updateStatus()
linia kodu, która wywołuje funkcję
getSWF()
jest zapisana w następujący sposób: var currentStatus = getSWF("${application}").getStatus(); Tekst
${application}
jest obiektem zastępczym w szablonie strony HTML; gdy program Adobe Flash Builder wygeneruje rzeczywistą stronę HTML dla aplikacji, ten tekst zastępczy zostanie zastąpiony przez tekst używany jako atrybut
id
znacznika
object
oraz atrybut
name
znacznika
embed
(w tym przykładzie
IntrovertIMApp
). Jest to wartość oczekiwana przez funkcję
getSWF()
.
Funkcja
sendMessage()
JavaScript prezentuje przekazanie parametru do funkcji ActionScript. (
sendMessage()
to funkcja wywoływana, gdy użytkownik naciśnie przycisk Wyślij na stronie HTML).
<script language="JavaScript">
...
function sendMessage(message)
{
if (swfReady)
{
...
getSWF("IntrovertIMApp").newMessage(message);
}
}
...
</script>
Metoda
newMessage()
ActionScript oczekuje jednego parametru, dlatego zmienna
message
JavaScript zostaje przekazana do ActionScript, ponieważ została wykorzystana jako parametr w wywołaniu metody
newMessage()
w kodzie JavaScript.
Wykrywanie typu przeglądarki
Z powodu różnic w sposobach, w jakie przeglądarki uzyskują dostęp do treści, bardzo ważne jest zawsze użycie kodu JavaScript w celu wykrywania używanej przeglądarki oraz w celu uzyskania dostępu do filmu zgodnie ze składnią właściwą dla przeglądarki — za pomocą obiektu okna lub dokumentu, co przedstawiono w funkcji
getSWF()
JavaScript w poniższym przykładzie:
<script language="JavaScript">
...
function getSWF(movieName)
{
if (navigator.appName.indexOf("Microsoft") != -1)
{
return window[movieName];
}
else
{
return document[movieName];
}
}
...
</script>
Jeśli skrypt nie wykrywa typu przeglądarki użytkownika, działanie plików SWF w kontenerze HTML może być niezgodne z oczekiwaniami.
|
|
|