Es gibt einige Fälle wo es nötig ist, das die Flashdatei mit dem JavaScript auf einer Webseite interagiert.
Die häufigste Form hierzu findet man in so genannten Flashlayern, diese legen sich über den eigentlichen Webseiten Inhalt, werden aber mit einen Klick auf den Schließen Knopf geschlossen.
Würde man dies nur in Flash alleine realisieren, so würde die Flashdatei zwar nichts mehr anzeigen aber der entsprechende unsichtbare Container würde immer noch über der Webseite liegen.
In diesem Fall müsste also der entsprechende Container bei einem Klick aus der Seite entfernt werden.
Dieser Artikel soll helfen zu verstehen welches Möglichkeiten es gibt damit die Flashdatei mit dem JavaScript der Webseite interagieren kann.
Vor allen in älteren Browsern kann es nötig sein anstatt FSCommand, dem entsprechende JavaScript Calls zu verwenden.
Sollte jedoch die Webseite selbst nur in modernen Browser funktionieren so sollte man überlegen ob FSCommands nicht sinnvoller sind.
FScommand würde keinen JavaScript Fehler verursachen wenn die Flashdatei einen nicht definierten FScommand aufruft.
Auch hört man bei der Lösung über getURL und navigateToURL ein entsprechendes klicken sobald der JavaScript Call gesendet wird.
Inhalt
JavaScript Aufruf mit getURL (ActionScript 2)
JavaScript Aufruf mit navigateToURL (ActionScript 3)
JavaScript Aufruf mit der External API
JavaScript Aufruf mit der External API mit Rückgabewert (Callback)
In ActionScript und Adobe Flash gibt es viele Events, zu den wichtigsten zählen onclick, onrelease, onrollover und onrollout.
Hier werden diese genauer beschrieben und auch wird versucht den Sinn der einzelnen Events genauer zu erklären.
Die einfachste Möglichkeit ist über einen einfachen getURL Aufruf entsprechende JavaScript Aufrufe zu erzeugen.
Wichtig ist hierbei das als Ziel natürlich "_self" verwendet wird, damit das JavaScript nicht versucht wird im einem neuen und leeren Fenster ausgeführt zu werden.
HTML Textbox:
Je nachdem welcher Button gedrückt wird erscheint "Hello World!" in der HTML Textbox.
<div>
<object type="application/x-shockwave-flash" id="javascript-geturl" data="javascript-geturl.swf" width="400" height="200">
<param name="movie" value="javascript-geturl.swf">
<param name="allowScriptAccess" value="always">
</object>
</div>
...
<p>
HTML Textbox: <input name="geturl_output" id="geturl_output" type="text" value="-">
<script type="text/javascript">
var geturl_output = document.getElementById('geturl_output');
function hello() {
if (geturl_output) {
geturl_output.value = 'Hello World !';
}
}
function clear() {
if (geturl_output) {
geturl_output.value = '';
}
}
</script>
</p>
Da in diesem Fall JavaScript aus der Flashdatei ausgeführt werden soll, muss allowScriptAccess auf always stehen.
Der JavaScript Code prüft einfach ob das Textfeld mit der id geturl_output existiert und setzte den Wert auf "Hello World!" oder auf leer.
btn_hello.onRelease = function() {
getURL('JavaScript:hello();', '_self');
};
btn_clear.onRelease = function() {
getURL('JavaScript:clear();', '_self');
};
Da die JavaScript Funktion sich im selben Fenster befindet, muss hier als Zielfenster _self verwendet werden.
Wird dieser Wert leer gelassen wird abhängig von der Browser Version und der Flashplayer Version der Standardwert _self oder _blank verwendet.
Somit sollte in diesem Fall der Wert immer auf _self gesetzt werden um evt. Probleme bei bestimmten Browser Versionen und Flashplayer Versionen zu vermeiden.
Da bei ActionScript 3 getURL nicht mehr existiert, sieht dieses Beispiel nur im ActionScript Code ein wenig anders aus.
Der HTML bzw. JavaScript Code ist genau der gleicher, dieser ist also unabhängig von der verwendeten ActionScript Version.
HTML Textbox:
Je nachdem welcher Button gedrückt wird erscheint "Hello World!" in der HTML Textbox.
<div>
<object type="application/x-shockwave-flash" id="javascript-navigatetourl" data="javascript-navigatetourl.swf" width="400" height="200">
<param name="movie" value="javascript-navigatetourl.swf">
<param name="allowScriptAccess" value="always">
</object>
</div>
...
<p>
HTML Textbox: <input name="navigatetourl_output" id="navigatetourl_output" type="text" value="-">
<script type="text/javascript">
var navigatetourl_output = document.getElementById('navigatetourl_output');
function hello() {
if (navigatetourl_output) {
navigatetourl_output.value = 'Hello World !';
}
}
function clear() {
if (navigatetourl_output) {
navigatetourl_output.value = '';
}
}
</script>
</p>
Da in diesem Fall JavaScript aus der Flashdatei ausgeführt werden soll, muss allowScriptAccess auf always stehen.
Der JavaScript Code prüft einfach ob das Textfeld mit der ID navigatetourl_output existiert und setzte den Wert auf "Hello World!" oder auf leer.
btn_hello.addEventListener(MouseEvent.MOUSE_UP, function() {
navigateToURL(new URLRequest('JavaScript:navigatetourl_hello();'),'_self');
});
btn_clear.addEventListener(MouseEvent.MOUSE_UP, function() {
navigateToURL(new URLRequest('JavaScript:navigatetourl_clear();'),'_self');
});
Da die JavaScript Funktion sich im selben Fenster befindet, muss hier als Zielfenster _self verwendet werden.
Wird dieser Wert leer gelassen wird abhängig von der Browser Version und der Flashplayer Version der Standardwert _self oder _blank verwendet.
Somit sollte in diesem Fall der Wert immer auf _self gesetzt werden um evt. Probleme bei bestimmten Browser Versionen und Flashplayer Versionen zu vermeiden.
Die External API bietet eine Menge Möglichkeiten damit die Flashdatei und JavaScript kommunizieren können.
Da es sich jedoch um eine API handelt die direkt auf die Flashdatei zugreift, spielen hier Sicherheitsaspekte eine große Rolle.
Mit der Methode über getURL oder navigateToURL muss man nur darauf achten im HTML Code der Webseite allowScriptAccess richtig zu setzen.
Bei der External API muss man jedoch zusätzlich noch allowDomain innerhalb der Flashdatei richtig verwenden.
HTML Textbox:
Je nachdem welcher Button gedrückt wird erscheint "Hello World!" in der HTML Textbox.
<div>
<object type="application/x-shockwave-flash" id="javascript-externalinterface" data="javascript-externalinterface.swf" width="400" height="200">
<param name="movie" value="javascript-externalinterface.swf">
<param name="allowScriptAccess" value="always">
</object>
</div>
...
<p>
HTML Textbox: <input name="externalinterface_output" id="externalinterface_output" type="text" value="-">
<script type="text/javascript">
var externalinterface_output = document.getElementById('externalinterface_output');
function hello() {
if (externalinterface_output) {
externalinterface_output.value = 'Hello World !';
}
}
function clear() {
if (externalinterface_output) {
externalinterface_output.value = '';
}
}
</script>
</p>
Da in diesem Fall JavaScript aus der Flashdatei ausgeführt werden soll, muss allowScriptAccess auf always stehen.
Der JavaScript Code prüft einfach ob das Textfeld mit der id externalinterface_output existiert und setzte den Wert auf "Hello World!" oder auf leer.
Bei externalinterface ist es wichtig das der Object TAG eine ID enthält auch wenn diese nicht verwendet wird.
Nur so kann der Flashplayer die Flashdatei auf der HTML Seite finden und die entsprechenden benötigten JavaScript Handler hinzufügen.
btn_hello.addEventListener(MouseEvent.MOUSE_UP, function() {
if (ExternalInterface.available) {
ExternalInterface.call("externalinterface_hello");
}
});
btn_clear.addEventListener(MouseEvent.MOUSE_UP, function() {
if (ExternalInterface.available) {
ExternalInterface.call("externalinterface_clear");
}
});
Mit dem Befehl ExternalInterface.available wird geprüft ob die Flashdatei in einer Umgebung ausgeliefert wird in der JavaScript ausgeführt werden kann.
Es werden hiermit keine Sicherheitsrichtlinien geprüft sondern nur ob dies generell möglich wäre.
Dies ist also Vergleichbar wie der <noscript>...</noscript> Part in HTML Webseiten.
Es muss auserdem darauf geachtet werden das die gewünschte Aktionen erst ausgeführt werden wenn die Seite komplett geladen ist.
Wenn man kann sicher gehen will, sollte man die Flashdateien beim laden verstecken und erst einblenden nachdem die Seite komplett geladen worden ist.
Die external API bietet eine menge Möglichkeiten, so ist es sogar möglich die Flashdtei über JavaScript anzusprechen und zu steuern.
Es gibt einige Fälle wo die entsprechenden Parameter auch nach dem Laden der Seite an die Flashdatei übergeben werden müssen.
Dies wäre mit FlashVars nicht möglich, das diese nur beim Laden der Seite ausgeführt werden.
Die veraltete Methode womit man ohne external API die Flashdatei ansteuern kann, sollte nicht mehr verwendet werden.
Klar kann diese in manchen Fällen hilfreich sein, da damit jede Flashdatei von außen gesteuert werden kann.
Jedoch wird diese Methode nicht mehr von Adobe unterstützt und wird in späteren FlashPlayer Versionen entfernt.
Flashdatei mit Callback
HTML Formular
Der entsprechende Text von der HTML Box wird an die Flashdatei übertragen oder von der Flashdatei zu der HMTL Box.
Dies wurde mit recht einfachen JavaScript und ActionScript realisiert.
Es ist wie gesagt wichtig, das die HTML Datei und die Flashdatei auf der selben Domain liegen.
Auch ist ein offline Test im Firefox aus Sicherheitsbeschränkungen nicht möglich.
Ihr müsst euren Test also online testen damit Ihr keine lokalen Sicherheitsrichtlinien verletzt.
<!-- Flashfile -->
<h3>Flashdatei mit Callback</h3>
<p>
<object type="application/x-shockwave-flash" id="flash" data="javascript-externalinterface-callback.swf" width="450" height="300">
<param name="movie" value="javascript-externalinterface-callback.swf">
<param name="allowScriptAccess" value="always">
</object>
</p>
<!-- HTML Formular -->
<h3>HTML Formular</h3>
<p>
<input name="input" id="input" type="text" value="- Text der an die Flashdatei geschickt werden soll -"> <input type="submit" value="Sende" onclick="send_to_flash_handler();"><br>
<textarea name="output" id="output" rows=10 cols=90></textarea><br>
</p>
<!-- JavaScript Code -->
<script type="text/javascript">
var
flash = document.getElementById('flash'),
input = document.getElementById('input'),
output = document.getElementById('output');
function received_from_flash(text) {
if (text && output) {
output.value = output.value + text + "\n";
}
}
function send_to_flash_handler() {
if (input && callback) {
if (input.value && typeof flash.send_to_flash !== 'undefined') {
flash.send_to_flash(input.value);
}
}
}
</script>
Die entsprechenden Variablen und ID wurden farblich markiert damit diese leichter zuzuordnen sind.
Die Flashdatei wird mit einer id "flash" eingebunden über welche wird später die Flashdatei ansprechen können.
Anschließend wird mit document.getElementById(...) das entsprechende HTML Object in einer JavaScript Variable gespeichert die genauso heißt.
Die Funktion received_from_flash wird aufgerufen sobald die Flashdatei eine entsprechende Anfrage schickt.
An diese Funktion wird der Text der Flashdatei übergeben und dann in das entsprechende HTML Output Textfeld geschrieben.
Die Funktion send_to_flash_handler wird aufgerufen sobald man auf den "Sende" Button des HTML Formular klickt.
Diese prüft ob ein entsprechender Text eingeben worden ist und ob die entsprechenden Funktion existiert.
Erst dann wird der CallBack Handler der Flashdatei send_to_flash ausgeführt und der entsprechende Text des HTML Formulars übergeben.
if (ExternalInterface.available) {
/* Füge Callback Funktion für JavaScript hinzu */
ExternalInterface.addCallback("send_to_flash", received_from_javascript);
/* Füge Aktion für Sende Button hinzu */
btn_send.addEventListener(MouseEvent.MOUSE_UP, function() {
if (ti_input.text) {
ExternalInterface.call("received_from_flash",ti_input.text);
}
});
} else {
/* Blende Elemente aus, falls kein ExternalInterface möglich ist */
btn_send.visible = ta_output.visible = ti_input.visible = false;
}
function received_from_javascript(msg:String) {
if (msg) {
ta_output.appendText(msg + "\n");
}
}
Mit ExternalInterface.addCallback wird die entsprechende CallBack Funktion definiert.
Als erster Wert wird der Namen des JavaScript Object erwartet, das erzeugt werden soll.
Der zweite Wert legt fest welche ActionScript Funktion damit angesprochen werden soll.
Dieser ActionScript Code blendet außerdem alle Objecte aus, falls keine JavaScript Kommunikation möglich sein sollte.
Hier kann man den User natürlich eine Meldung anzeigen lassen das JavaScript benötigt wird oder eine Warnung ausgeben das die Daten nicht in Echtzeit aktualisiert werden können.
In manchen Situation ist es hilfreich mehrzeilige JavaScript in Flash zu verwenden.
Was viele nicht wissen ist, das dies auch mit ExternalInterface ohne weiteres möglich ist.
Somit kann man ganze JavaScript Programme innerhalb der Flashdatei definieren und später auf der Webseite ausführen.
Das nachfolgende Beispiel enthält nur JavaScript innerhalb der Flashdatei und vergrößert oder verkleinert auf einen entsprechenden Klick die Flashdatei.
Dieses Beispiel vergrößert über JavaScript das OBJECT das in der HTML Seite hinterlegt ist.
Natürlich ist es auch möglich ohne scale = exactfit die Flashdatei zu vergrößern.
So wäre es möglich die Element innerhalb der Flashdatei mit Actionscript anzupassen ohne das diese eine größere Schrift, Rahmen oder andere Vergrößerungen erhalten.
Auch kann man natürlich andere komplexe Sachen realisieren, ohne das zusätzlicher JavaScript auf der Webseite nötig ist.
<div>
<object type="application/x-shockwave-flash" id="javascript_externalinterface_block" data="javascript-externalinterface-block.swf" width="440" height="300">
<param name="movie" value="javascript-externalinterface-block.swf">
<param name="scale" value="exactfit">
<param name="allowScriptAccess" value="always">
</object>
</div>
Da der komplette JavaScript Code innerhalb der Flashdatei liegt, wird nur der HTML Code für die Auslieferung der Flashdatei als OBJECT benötigt.
Das einzige was beachtet werden muss ist, das eine eindeutige ID verwendet wird. Mit Hilfe dieser ID können wir nachher direkt auf den OBJECT TAG zugreifen und diesen manipulieren.
Da in diesem Fall JavaScript von der Flashdatei ausgeführt werden soll muss allowScriptAccess auf always stehen.
var
current_width = Math.floor(this.stage.width),
max_width = 790,
min_width = Math.floor(this.stage.width),
scale = this.stage.height / this.stage.width;
btn_max.addEventListener(MouseEvent.MOUSE_UP, function() {
js_resize(Math.floor(current_width + 10));
});
btn_min.addEventListener(MouseEvent.MOUSE_UP, function() {
js_resize(Math.floor(current_width - 10));
});
function js_resize(width) {
if (ExternalInterface.available && width >= min_width && width <= max_width) {
current_width = width;
var height = Math.floor(width * scale);
var js_call:String = ''
+ 'function(){\n'
+ ' var test_flashfile = document.getElementById("javascript_externalinterface_block");\n'
+ ' if (test_flashfile) {\n'
+ ' test_flashfile.width = Number(' + width + ');\n'
+ ' test_flashfile.height = Number(' + height + ');\n'
+ ' }\n'
+ '}\n';
trace('JavaScript: \n' + js_call);
ExternalInterface.call(js_call);
}
}
Der JavaScript Code sucht anhand der ID nach dem OBJECT TAG und ändern dann falls dieser vorhanden ist dem entsprechend die Größe.
Bitte beachtet dafür folgende Beschränkungen:
-
document.write(...) kann nur ausgeführt werden solange die Seite lädt, wenn diese fertig geladen hat, kann dieses nicht mehr verwendet werden.
Es würde sonst die komplette Seite überschreiben, was sicherlich nicht gewollt ist !
-
document.getElementById und andere DOM Methoden können erst verwendet werden wenn die Seite (nicht die Flashdatei) fertig geladen hat.
Erst dann weiß der Browser wo sich welches Element befindet und kann diese dem entsprechend manipulieren.
Hier muss also mit Event Handler gearbeitet werden die nach laden der Seite ausgeführt werden.
Da in diesem Fall der User auf Button klickt und dann das entsprechende JavaScript ausführt ist es eigentlich nicht nötig Event Handler zu verwenden.
Der User kann erst auf die Button klicken wenn die Flashdatei geladen ist und bei einer kleinen Flashdatei passiert dies zeitgleich mit der Webseite.
