La capture ci-dessus suppose que vous êtes familier avec l'utilisation de la console javascript présente dans tous vos navigateurs. Elle vous permettra d'utiliser la fonction console.log("écrire"); qui enverra une ligne de texte et vous permettra de connaitre le contenu des symboles ou évènements que vous mettez en place. (cmd-alt-J sur Chrome)

Le document de départ

Dans le document fourni, j'ai simplement créé 3 ellipses de couleurs différentes, mauve, bleue et verte, nommées E1, E2 et E3, auxquelles j'ai assigné 1 code au clic (en cliquant sur les petites accolades de la bonne ellipse). J'ai ensuite converti chacune en symbole (cmd/ctrl-Y), nommé Emauve, Ebleue et Everte.

EgAn-Closures-01.png

Tout le reste va se dérouler dans la fenêtre de code (cmd/ctrl-E) qui me permettra d'avoir accès de manière plus synthétique aux différents symboles et au code les concernant.

On voit dans la capture ci-dessous que le symbole "Everte" comporte bien un élément "E1" sur lequel j'utilise l'évènement "click".

Notez que le bouton "Code Complet" en haut à droite est éteint, ce qui rend chaque symbole du panneau de gauche accessible.

EgAn-Closures-02.png

Au clic sur l'ellipse “E1" de mon symbole "Everte", j'ai associé 3 fonctions console.log, qui me permettent de suivre le déroulé de l'exécution. Tout d'abord pour bien spécifier que je suis bien dans l'ellipse verte et détecter les erreurs de clic dès le départ.

Puis j'appelle "maFonctionInacessible", que j'ai nommé ainsi parce qu'elle se trouve à l'intérieur d'un autre symbole, ma scène, et que Animate ne pourra pas l'atteindre.

Fonction posée sur la scène/Stage

Il est courant lors des phases de présentation et d'exercices de créer de simples boutons sur la scène, et d'y associer des fonctions que l'on appelle directement depuis la stage, un rectangle, un clic, un appel de fonction, un autre rectangle, tout roule.

Testez d'ailleurs (je vous ai rajouté un simple rectangle jaune sur la scène), depuis cet élément, et parce que son code est directement sous la scène, il atteindra maFonctionInaccessible sans souci.

EgAn-Closures-03.png

Et puis on arrive au cas grandeur réelle, à coups de symboles, et là, plus moyen d'afficher cette fonction, qui déclenche l'erreur fatale

    Javascript error in event handler! Event Type = element

Ça se complique : vous essayez d'aller du E1.click, à l'intérieur du symbole Everte vers une fonction définie dans Stage. Or ce n'est pas possible simplement, parce que les actions sur Stage et Everte sont définies de manière séparée dans le code, à cause des fameuses closures que je vous présente plus bas.

Accéder à une fonction depuis n'importe quel symbole

Rassurez-vous, on pourra quand même atteindre plusieurs fois la même fonction. Vous ne serez pas obligés de dupliquer votre code dans chaque bouton. Pour cela, on va placer la fonction (que je nomme maFonctionAccessible) en dehors des définitions de la Stage ou des autres symboles (la Stage EST un symbole).

Mais pour accéder à cet "espace" hors symboles, nous devons ruser et accéder au Code complet, via le bouton en haut à droite. Celui-ci rend vos différents symboles et évènements grisés dans le panneau de gauche, mais vous pourrez toujours y accéder sous leur forme brute.

EgAn-Closures-04.png

Les fonctions relatives aux symboles et à la scène sont indiquées sous la forme (function($…){ … })("NomDuSymbole");

Il vous suffira donc d'écrire vos fonctions accessibles partout en dehors du reste de ce code, à la manière de maFonctionAccessible() sur la capture ci-dessus.

Et désormais, vous pouvez appeler cette fonction de partout !

Test en grandeur réelle

Il ne vous reste plus qu'à essayer via le fichier de test.

EgAn-Closures-00.png

L'ordre des fonctions dans un évènement aura aussi son importance. Par exemple, pour l'ellipse verte, j'appelle d'abord ma fonction inaccessible, puis ma fonction accessible. Forcément, je déclenche une erreur (la fonction "n'existe pas" hors de ce symbole)… et l'appel à la fonction accessible est oublié.

Si je demande d'abord la fonction accessible, puis l'inaccessible, la première fonctionne, la seconde déclenche l'erreur, mais ce n'est pas bien grave, si je ne regarde pas la console, je ne m'en rends pas compte.

Au final, l'ellipse mauve n'appelle que la fonction accessible, et tout est plus propre, pas d'erreur. Ça tombe sous le sens, mais ça valide votre manière de coder.

Mais alors qu'est-ce qu'une Closure/Fermeture… et est-ce qu'on a vraiment besoin de ça ici ?

Quand j'ai commencé cet article, je pensais avoir compris le fonctionnement et des notions importantes de développement en javascript. Mais après avoir échangé avec David Deraedt il semblerait que je n'y sois pas encore, que je confonde les closures, les iife (prononcer ifi), la portée (ou scope), les fonctions anonymes, etc.

J'utilisais closure/fermeture parce que si "Fermeture" est le terme utilisé en français dans l'API d'Animate vous aurez beaucoup plus de résultats et de ressources en anglais avec "Closure".

Pour le reste, je vous laisse chercher la différence entre closures et iife, comprendre la notion de scope (ou portée) et retenir l'adage qui veut que ce qui a lieu à Vegas reste à Vegas, les fonctions et les variables que vous déclarez peuvent rester inaccessibles au reste du code. Ça permet de limiter les interactions accidentelles entre deux parties de code qui ne sont pas sensées échanger des informations.

Et dans Animate, chaque symbole est construit sous cette forme, comme on le voit dans ce visuel :

EgAn-Closures-05.png

Bref, ce n'est pas aujourd'hui que je vous expliquerai ça, retenez surtout qu'en plaçant vos fonctions tout à l'extérieur, en haut du code complet, elles restent accessibles.

Petit bonus pour la fin :

Jusqu'ici j'appelle maFonctionAccessible(); Si je souhaite personnaliser sa réaction, ne pas hésiter à appeler maFonctionAccessible(e); qui me permettra de renvoyer l'évènement (clic, déclencheur, etc) et surtout dans la définition de la fonction, demander à visualiser le contenu de cet évènement (c'est là que se trouvent les infos utiles)

    maFonctionAccessible(quelEvenement)
    {
         console.log(quelEvenement);
    }