Diese Beispielanwendung veranschaulicht geeignete Techniken für den Datenaustausch zwischen ActionScript und JavaScript in einem Webbrowser im Kontext einer Instant Messaging-Anwendung, die es einer Person ermöglicht, mit sich selbst zu chatten (daher der Name der Anwendung: Introvert IM). Nachrichten werden mithilfe der externen API zwischen einem in die Webseite integrierten HTML-Formular und einer SWF-Benutzeroberfläche ausgetauscht. In diesem Beispiel werden folgende Techniken demonstriert:
-
Ordnungsgemäßes Initiieren des Datenaustauschs durch Überprüfen, ob der Browser bereit ist, bevor ein Datenaustausch gestartet wird
-
Überprüfen, ob der Container die externe API unterstützt
-
Aufrufen von JavaScript-Funktionen aus ActionScript, Übergeben von Parametern und Empfangen von Rückgabewerten
-
Verfügbarmachen von ActionScript-Methoden für Aufrufe aus JavaScript und Ausführen dieser Aufrufe
Die Anwendungsdateien für dieses Beispiel finden Sie unter
www.adobe.com/go/learn_programmingAS3samples_flash_de
. Die Dateien der Anwendung „Introvert IM“ befinden sich im Ordner „Samples/IntrovertIM_HTML“. Die Anwendung umfasst die folgenden Dateien:
Datei
|
Beschreibung
|
IntrovertIMApp.fla
oder
IntrovertIMApp.mxml
|
Die Hauptanwendungsdatei im Flash-Format (FLA) oder Flex-Format (MXML).
|
com/example/programmingas3/introvertIM/IMManager.as
|
Die Klasse, mit der der Datenaustausch zwischen ActionScript und dem Container aufgebaut und verwaltet wird.
|
com/example/programmingas3/introvertIM/IMMessageEvent.as
|
Ein benutzerdefinierter Ereignistyp, der von der IMManager-Klasse ausgelöst wird, wenn eine vom Container stammende Nachricht empfangen wurde.
|
com/example/programmingas3/introvertIM/IMStatus.as
|
Eine Aufzählung, deren Werte die verschiedenen Statuswerte für die „Verfügbarkeit“ angeben, die in der Anwendung ausgewählt werden kann.
|
html-flash/IntrovertIMApp.html
oder
html-template/index.template.html
|
Für Flash die HTML-Seite der Anwendung (html-flash/IntrovertIMApp.html) oder für Adobe Flex die Vorlage, die zum Erstellen der Container-HTML-Seite der Anwendung verwendet wird (html-template/index.template.html). Diese Datei enthält alle JavaScript-Funktionen der Containerkomponente der Anwendung.
|
Vorbereiten der Kommunikation mit dem ActionScript-Browser
Einer der häufigsten Einsatzzwecke für die externe API ist der Datenaustausch zwischen ActionScript-Anwendungen und einem Webbrowser. Mithilfe der externen API kann mit ActionScript-Methoden JavaScript-Code aufgerufen werden und umgekehrt. Aufgrund der Komplexität von Browsern und der Art, wie diese Seiten intern darstellen, gibt es keine Möglichkeit sicherzustellen, dass ein SWF-Dokument die zugehörigen Callback-Funktionen registriert hat, bevor die erste JavaScript-Anweisung in der HTML-Seite ausgeführt wird. Aus diesem Grund sollte das SWF-Dokument stets zuerst die HTML-Seite aufrufen und darüber benachrichtigen, dass es verbindungsbereit ist, bevor aus JavaScript Funktionen des SWF-Dokuments aufgerufen werden.
In der Anwendung „Introvert IM“ wird beispielsweise durch eine Reihe von Schritten in der IMManager-Klasse ermittelt, ob der Browser für den Datenaustausch bereit ist, und die SWF-Datei dann darauf vorbereitet. Der erste Schritt – Ermitteln, ob der Browser für den Datenaustausch bereit ist – erfolgt im IMManager-Konstruktor:
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.");
}
}
Zunächst wird mithilfe der
ExternalInterface.available
-Eigenschaft überprüft, ob die externe API im aktuellen Container überhaupt verfügbar ist. Wenn dies der Fall ist, beginnt der Aufbau der Kommunikation. Da beim Kommunikationsaufbau mit externen Anwendungen Sicherheitsausnahmen und andere Fehler auftreten können, ist der Code in einen
try
-Block eingeschlossen. (Die entsprechenden
catch
-Blöcke sind aus Platzgründen nicht aufgeführt.)
Anschließend wird die im Folgenden aufgeführte
isContainerReady()
-Methode aufgerufen:
private function isContainerReady():Boolean
{
var result:Boolean = ExternalInterface.call("isReady");
return result;
}
Die
isContainerReady()
-Methode verwendet wiederum wie folgt die
ExternalInterface.call()
-Methode, um die JavaScript-Funktion
isReady()
aufzurufen:
<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>
Die
isReady()
-Funktion gibt den Wert der Variablen
jsReady
zurück. Diese Variable erhält zu Anfang den Wert
false
. Nachdem das
onload
-Ereignis der Webseite ausgelöst wurde, ist der Wert der Variablen
true
. Mit anderen Worten: Wenn ActionScript die
isReady()
-Funktion aufruft, bevor die Seite geladen ist, gibt JavaScript beim Aufruf von
ExternalInterface.call("isReady")
den Wert
false
zurück. Daraufhin gibt auch die ActionScript-Methode
isContainerReady()
den Wert
false
zurück. Nachdem die Seite geladen wurde, gibt die JavaScript-Funktion
isReady()
den Wert
true
zurück, daraufhin gibt auch die ActionScript-Methode
isContainerReady
den Wert
true
zurück.
Je nach Bereitschaft des Containers werden im IMManager-Konstruktor zwei verschiedene Aktionen ausgeführt. Wenn
isContainerReady()
den Wert
true
zurückgibt, wird die
setupCallbacks()
-Methode aufgerufen, die den Aufbau der Kommunikation mit JavaScript abschließt. Wenn
isContainerReady()
jedoch
false
zurückgibt, wird der Vorgang vorerst ausgesetzt. Es wird wie folgt ein Timer-Objekt erstellt, das alle 100Millisekunden die
timerHandler()
-Methode aufrufen soll:
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();
}
}
Bei jedem Aufruf der
timerHandler()
-Methode wird erneut das Ergebnis der
isContainerReady()
-Methode überprüft. Wenn der Container initialisiert ist, gibt diese Methode Folgendes zurück:
true.
Daraufhin wird der Timer angehalten und die
setupCallbacks()
-Methode aufgerufen, um den Aufbau der Kommunikation mit dem Browser abzuschließen.
Bereitstellen von ActionScript-Methoden für JavaScript
Wie im vorangegangenen Beispiel gezeigt wurde, wird die
setupCallbacks()
-Methode aufgerufen, nachdem ermittelt wurde, dass der Browser bereit ist. Mit dieser Methode wird ActionScript wie folgt darauf vorbereitet, Aufrufe aus JavaScript zu empfangen:
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");
}
Die
setCallBacks()
-Methode schließt die Vorbereitung der Kommunikation mit dem Container ab, indem
ExternalInterface.addCallback()
aufgerufen wird, um die beiden Methoden zu registrieren, die für den Aufruf aus JavaScript verfügbar sein sollen. Im Codebeispiel stimmt der erste Parameter – der Name, unter dem die Methode in JavaScript bekannt ist (
„newMessage"
und
„getStatus"
) – mit dem Namen der Methode in ActionScript überein. (In diesem Fall brachte es keine Vorteile, unterschiedliche Namen zu verwenden, deshalb wurde aus Gründen der Einfachheit derselbe Name verwendet.) Schließlich wird die
ExternalInterface.call()
-Methode verwendet, um die JavaScript-Funktion
setSWFIsReady()
aufzurufen, die den Container darüber benachrichtigt, dass die ActionScript-Funktionen nun registriert sind.
Datenübertragung von ActionScript zum Browser
In der Anwendung „Introvert IM“ werden viele Beispiele für das Aufrufen von JavaScript-Funktionen in der Containerseite vorgestellt. Im einfachsten Fall (ein Beispiel aus der
setupCallbacks()
-Methode) wird die JavaScript-Funktion
setSWFIsReady()
aufgerufen, ohne dass Parameter übergeben oder ein Rückgabewert zurückgegeben wird:
ExternalInterface.call("setSWFIsReady");
In einem anderen Beispiel aus der
isContainerReady()
-Methode ruft ActionScript die
isReady()
-Funktion auf und erhält als Rückgabewert einen booleschen Wert:
var result:Boolean = ExternalInterface.call("isReady");
Sie können mithilfe der externen API auch Parameter an JavaScript-Funktionen übergeben. Dies erfolgt beispielsweise mit der
sendMessage()
-Methode der IMManager-Klasse, die aufgerufen wird, wenn der Benutzer eine neue Nachricht an den „Gesprächspartner“ sendet:
public function sendMessage(message:String):void
{
ExternalInterface.call("newMessage", message);
}
Wieder wird
ExternalInterface.call()
verwendet, um die entsprechende JavaScript-Funktion aufzurufen, mit der der Browser über die neue Nachricht informiert wird. Zusätzlich wird die Nachricht selbst als weiterer Parameter an
ExternalInterface.call()
übergeben und dann als Parameter an die JavaScript-Funktion
newMessage()
weitergeleitet.
Aufrufen von ActionScript-Code aus JavaScript
Eine wirkliche Kommunikation findet erst statt, wenn der Datenaustausch in beide Richtungen erfolgt, und die Anwendung „Introvert IM“ stellt dabei keine Ausnahme dar. Nicht nur der Flash Player-IM-Client ruft JavaScript-Funktionen auf, um Nachrichten zu senden, sondern auch das HTML-Formular verwendet JavaScript, um Nachrichten an die SWF-Datei zu senden und Informationen abzufragen. Wenn beispielsweise die SWF-Datei den Container benachrichtigt, dass die Kontaktaufnahme abgeschlossen und Kommunikationsbereitschaft hergestellt ist, ruft der Browser zunächst die
getStatus()
-Methode der IMManager-Klasse auf, um vom SWF-IM-Client den Anfangsstatus der Benutzerverfügbarkeit abzurufen. Dies erfolgt mithilfe der
updateStatus()
-Funktion in der Webseite:
<script language="JavaScript">
...
function updateStatus()
{
if (swfReady)
{
var currentStatus = getSWF("IntrovertIMApp").getStatus();
document.forms["imForm"].status.value = currentStatus;
}
}
...
</script>
Es wird der Wert der Variablen
swfReady
überprüft, in der gespeichert ist, ob die SWF-Datei den Browser darüber benachrichtigt hat, dass die Methoden nun bei der ExternalInterface-Klasse registriert sind. Wenn die SWF-Datei kommunikationsbereit ist, wird mit der nächsten Zeile (
var currentStatus =
...) die
getStatus()
-Methode der IMManager-Klasse aufgerufen. In dieser Codezeile werden drei Vorgänge durchgeführt:
-
Die JavaScript-Funktion
getSWF()
wird aufgerufen, die einen Verweis auf das JavaScript-Objekt zurückgibt, mit dem die SWF-Datei angegeben wird. Mit dem an
getSWF()
übergebenen Parameter wird festgelegt, welches Browserobjekt zurückgegeben wird, wenn pro HTML-Seite mehrere SWF-Dateien vorhanden sind. Der Wert dieses Parameters muss mit dem
id
-Attribut des
object
-Tags und dem
name
-Attribut des
embed
-Tags übereinstimmen, die zum Einfügen der SWF-Datei verwendet wurden.
-
Mithilfe des Verweises auf die SWF-Datei wird die
getStatus()
-Methode aufgerufen, als wäre sie eine Methode des SWF-Objekts. In diesem Fall wird der Funktionsname
getStatus
verwendet, da die ActionScript-Funktion mithilfe von
ExternalInterface.addCallback()
unter diesem Namen registriert wurde.
-
Die ActionScript-Methode
getStatus()
gibt einen Wert zurück. Dieser Wert wird der Variablen
currentStatus
zugewiesen, die dann als Inhalt des Textfelds
status
(über die
value
-Eigenschaft) zugewiesen wird.
Hinweis:
Wenn Sie den Code mitverfolgt haben, ist Ihnen wahrscheinlich aufgefallen, dass im Quellcode für die Funktion
updateStatus()
die Codezeile, die die Funktion
getSWF()
aufruft, folgendermaßen geschrieben ist: var currentStatus = getSWF("${application}").getStatus(); Der Text
${application}
ist ein Platzhalter in der HTML-Seitenvorlage. Wenn Adobe Flash Builder die tatsächliche HTML-Seite für die Anwendung generiert, wird dieser Platzhalter durch den Text ersetzt, der für das
object
-Tag als
id
-Attribut und für das
embed
-Tag als
name
-Attribut verwendet wird (in diesem Beispiel
IntrovertIMApp
). Dies ist der Wert, der von der
getSWF()
-Funktion erwartet wird.
Die JavaScript-Funktion
sendMessage()
veranschaulicht das Übergeben von Parametern an eine ActionScript-Funktion. (Die
sendMessage()
-Funktion wird aufgerufen, wenn der Benutzer auf der HTML-Seite auf die Schaltfläche „Send“ klickt.)
<script language="JavaScript">
...
function sendMessage(message)
{
if (swfReady)
{
...
getSWF("IntrovertIMApp").newMessage(message);
}
}
...
</script>
Die ActionScript-Methode
newMessage()
erwartet einen Parameter, deshalb wird die JavaScript-Variable
message
an ActionScript übergeben, indem sie im JavaScript-Code beim Aufruf der
newMessage()
-Methode als Parameter verwendet wird.
Erkennen des Browsertyps
Aufgrund der browserspezifischen Unterschiede beim Zugriff auf Inhalte ist es wichtig, immer den vom Benutzer verwendeten Browser zu ermitteln und auf den Film der jeweiligen Syntax entsprechend zuzugreifen. Dies erfolgt mithilfe von JavaScript und des Window- oder Document-Objekts, wie in der JavaScript-Funktion
getSWF()
in diesem Beispiel dargestellt ist:
<script language="JavaScript">
...
function getSWF(movieName)
{
if (navigator.appName.indexOf("Microsoft") != -1)
{
return window[movieName];
}
else
{
return document[movieName];
}
}
...
</script>
Wenn der Browsertyp des Benutzers im Skript nicht erkannt wird, kann es bei der Wiedergabe von SWF-Dateien in einem HTML-Container zu unerwartetem Verhalten kommen.
|
|
|