Exemple d’API externe : communications entre ActionScript et JavaScript dans un navigateur WebFlash Player 9 et ultérieur, Adobe AIR 1.0 et ultérieur Cette application exemple illustre les techniques de communication possibles entre ActionScript et JavaScript au sein d’un navigateur Web. Il s’agit d’une application de messagerie instantanée qui permet à l’utilisateur de discuter avec lui-même (d’où le nom de l’application : Introvert IM). L’API externe permet d’envoyer les messages entre un formulaire HTML dans la page Web et une interface SWF. Les techniques décrites dans cet exemple sont les suivantes :
Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers de l’application Introvert IM se trouvent dans le dossier Samples/IntrovertIM_HTML. L’application se compose des fichiers suivants :
Préparation de la communication entre ActionScript et le navigateurL’API externe est le plus souvent utilisée pour permettre aux applications ActionScript de communiquer avec le navigateur Web. Grâce à elle, les méthodes ActionScript peuvent appeler du code écrit dans JavaScript, et inversement. En raison de la complexité des navigateurs et de leurs processus internes de rendu des pages, il est impossible de garantir qu’un document SWF pourra enregistrer ses rappels avant l’exécution du premier code JavaScript de la page HTML. Par conséquent, avant d’appeler les fonctions du document SWF à partir de JavaScript, le document SWF doit toujours appeler la page HTML pour lui indiquer qu’il est prêt à accepter des connexions. Par exemple, grâce à une série d’étapes effectuées par la classe IMManager, Introvert IM détermine si le navigateur est prêt à communiquer et prépare le fichier SWF à la communication. La première étape, qui vérifie que le navigateur est prêt à communiquer, a lieu dans le constructeur IMManager, comme suit : 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."); } } Tout d’abord, le code vérifie si l’API externe est disponible dans le conteneur actuel à l’aide de la propriété ExternalInterface.available. Si c’est le cas, le processus de mise en place de la communication commence. Pour parer aux éventuelles exceptions de sécurité et autres erreurs qui peuvent se produire pendant les communications avec une application externe, le code est enveloppé dans un bloc try (les blocs catch correspondants ont été omis de l’exemple pour plus de concision). Le code appelle ensuite la méthode isContainerReady(), présentée ici : private function isContainerReady():Boolean { var result:Boolean = ExternalInterface.call("isReady"); return result; } La méthode isContainerReady() utilise à son tour la méthode ExternalInterface.call() pour appeler la fonction JavaScript isReady(), comme suit : <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> La fonction isReady() renvoie simplement la valeur de la variable jsReady. Cette variable a au départ la valeur false. Une fois que l’événement onload de la page Web est déclenché, la valeur de la variable devient true. En d’autres termes, si ActionScript appelle la fonction isReady() avant que la page soit chargée, JavaScript renvoie la valeur false à ExternalInterface.call("isReady"), à la suite de quoi la méthode ActionScript isContainerReady() renvoie la valeur false. Une fois la page chargée, la fonction JavaScript isReady() renvoie la valeur true, donc la méthode ActionScript isContainerReady() renvoie aussi la valeur true. Dans le constructeur IMManager, deux solutions sont possibles en fonction de la disponibilité du conteneur. Si isContainerReady() renvoie la valeur true, le code appelle simplement la méthode setupCallbacks(), qui achève la mise en place de la communication avec JavaScript. Dans l’autre cas, si isContainerReady() renvoie la valeur false, le processus est pratiquement mis en attente. Un objet Timer est créé pour appeler la méthode timerHandler() toutes les 100 millisecondes, comme suit : 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(); } } Chaque fois que la méthode timerHandler() est appelée, elle vérifie à nouveau le résultat de la méthode isContainerReady(). Lorsque le conteneur est initialisé, la méthode renvoie la valeur true. Le code arrête alors le minuteur et appelle la méthode setupCallbacks() pour finir la mise en place de la communication avec le navigateur. Présentation des méthodes ActionScript à JavaScriptComme le montre l’exemple précédent, une fois que le code établit que le navigateur est prêt, la méthode setupCallbacks() est appelée. Cette méthode prépare ActionScript pour recevoir des appels à partir de JavaScript, comme le montre cet exemple : 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"); } La méthode setCallBacks() achève la préparation de la communication avec le conteneur en appelant ExternalInterface.addCallback() afin d’enregistrer deux méthodes qui pourront être appelées par JavaScript. Dans ce code, le premier paramètre (le nom qui sert à désigner la méthode dans JavaScript, soit "newMessage" et "getStatus") est identique au nom de la méthode dans ActionScript (dans ce cas, il n’y avait pas d’intérêt à utiliser des noms différents, on a donc réutilisé les mêmes noms par souci de simplification). Enfin, la méthode ExternalInterface.call() est utilisée pour appeler la fonction JavaScript setSWFIsReady(), qui avertit le conteneur que les fonctions ActionScript ont été enregistrées. Communication d’ActionScript vers le navigateurL’application Introvert IM met en évidence plusieurs exemples d’appel de fonctions JavaScript dans la page conteneur. Dans le cas le plus simple (un exemple issu de la méthode setupCallbacks()), la fonction JavaScript setSWFIsReady() est appelée sans transmettre de paramètres ni recevoir de valeur en retour : ExternalInterface.call("setSWFIsReady"); Dans un autre exemple issu de la méthode isContainerReady(), ActionScript appelle la fonction isReady() et reçoit une valeur booléenne en réponse : var result:Boolean = ExternalInterface.call("isReady"); Vous pouvez également transmettre des paramètres aux fonctions JavaScript à l’aide de l’API externe. Considérez par exemple la méthode sendMessage() de la classe IMManager, qui est appelée lorsque l’utilisateur envoie un nouveau message à son interlocuteur. public function sendMessage(message:String):void { ExternalInterface.call("newMessage", message); } Là encore, ExternalInterface.call() sert à appeler la fonction JavaScript désignée pour avertir le navigateur du nouveau message. En outre, le message lui-même est transmis comme paramètre supplémentaire à ExternalInterface.call(). Il est ensuite transmis comme paramètre à la fonction JavaScript newMessage(). Appel du code ActionScript à partir de JavaScriptUne communication se fait normalement de manière bidirectionnelle, ce que respecte l’application Introvert IM. D’un côté, le client de messagerie Flash Player appelle JavaScript pour envoyer des messages, de l’autre, le formulaire HTML appelle le code JavaScript pour envoyer des messages au fichier SWF et recevoir de celui-ci des informations. Par exemple, lorsque le fichier SWF avertit le conteneur qu’il a établi le contact et peut communiquer, la première action du navigateur consiste à appeler la méthode getStatus() de la classe IMManager pour recevoir du client de messagerie SWF le statut de disponibilité de l’utilisateur initial. Cela se fait dans la page Web, avec la fonction updateStatus(), comme illustré ci-après : <script language="JavaScript"> ... function updateStatus() { if (swfReady) { var currentStatus = getSWF("IntrovertIMApp").getStatus(); document.forms["imForm"].status.value = currentStatus; } } ... </script> Le code vérifie la valeur de la variable swfReady, qui vérifie si le fichier SWF a averti le navigateur qu’il avait enregistré ses méthodes auprès de la classe ExternalInterface. Si le fichier SWF est prêt à recevoir la communication, la ligne suivante (var currentStatus = ...) appelle la méthode getStatus() dans la classe IMManager. Trois opérations se produisent dans cette ligne de code :
Remarque : si vous vous référez au code, vous avez probablement noté que dans le code source relatif à la fonction updateStatus(), la ligne qui appelle la fonction getSWF() est en fait écrite comme suit : var currentStatus = getSWF("${application}").getStatus(). Le texte ${application} est un espace réservé dans le modèle de page HTML. Lorsqu’Adobe Flash Builder génère la page HTML en tant que telle pour l’application, cet espace réservé est remplacé par le texte faisant office d’attribut id de la balise object et d’attribut name de la balise embed (soit IntrovertIMApp dans l’exemple). Il s’agit de la valeur attendue par la fonction getSWF().
La fonction JavaScript sendMessage() illustre la transmission d’un paramètre à la fonction ActionScript (sendMessage() est la fonction appelée lorsque l’utilisateur appuie sur le bouton Envoyer de la page HTML). <script language="JavaScript"> ... function sendMessage(message) { if (swfReady) { ... getSWF("IntrovertIMApp").newMessage(message); } } ... </script> La méthode ActionScript newMessage() attend un seul paramètre. De ce fait, la variable JavaScript message est transmise à ActionScript en l’utilisant comme paramètre dans l’appel de la méthode newMessage() du code JavaScript. Détection du type de navigateurL’accès au contenu varie d’un navigateur à l’autre. Pour cette raison, il est important de toujours utiliser JavaScript pour détecter le navigateur utilisé et accéder ensuite à la séquence selon la syntaxe propre au navigateur à l’aide de l’objet de fenêtre ou de document, comme le montre la fonction JavaScript getSWF() de cet exemple : <script language="JavaScript"> ... function getSWF(movieName) { if (navigator.appName.indexOf("Microsoft") != -1) { return window[movieName]; } else { return document[movieName]; } } ... </script> Si votre script ne détecte pas le type de navigateur de l’utilisateur, ce dernier peut noter un comportement inattendu lors de la lecture des fichiers SWF dans un conteneur HTML. |
|