Fonction javascript dans Topaze?

Bonjour à tous,
Je viens vous consulter à propos d’une idée qui me traverse l’esprit ces derniers temps :
je souhaiterais pouvoir faire des calculs statistiques sur des données gérées dans Topaze. Ces calculs concernent par exemple la moyenne, la variance, etc.
Je peux les programmer en javascript dans un indicateur ou une variable calculée automatiquement mais je trouve assez lourd de devoir toujours réécrire ce calcul à chaque fois que j’utilise l’indicateur ou la variable. D’où ma question :
est-il possible de stocker d’une manière ou d’une autre la fonction écrite en javascript pour effectuer ce calcul et l’utiliser dans un indicateur ou une variable ?
Par exemple :
function moyenne(values) {…}

et ensuite l’utiliser en l’appelant dans un indicateur :
val_moyenne = moyenne({1,2,3,4});

Merci d’avance pour vos pistes
Cordialement
Philippe vignoles

Bonjour,

Le seul moyen que je vois pour ajouter un bibliothèque JS perso serait de l’inclure dans un habillage guidé élaboré avec SCENARIstyler, dans skin.js.

Par contre ceci veut dire que votre contenu ne marchera plus avec un autre skin.

Bonjour Sam,
Merci pour cette piste : c’est déjà une très bonne idée il me semble. Il faudra simplement penser à rajouter les scripts dans les nouveaux skins le cas échéant mais c’est un moindre mal je pense.
Merci
Cordialement
Philippe

Bonjour,
une autre solution est peut-être d’utiliser la fonction « eval() » du javascript. On peut par exemple rassembler les fonctions dans un tableau dans une première variable calculée automatiquement :

Puis on utilise la bibliothèque là où on en a besoin :

Exemple complet (Topaze 5) : EvalString.scar (3,8 Ko)

Pas optimal car on insère à chaque fois la bibliothèque dans le script qui l’utilise. Il y a peut-être moyen d’améliorer l’idée en utilisant des variables sessionStorage

1 « J'aime »

Bonjour Eric,

Encore une suggestion très intéressante.

En pratique, je pourrais en fait créer autant de variables que de fonctions ce qui permettrait alors de n’utiliser que la fonction utile au moment de l’appel.
D’un point de vue fonctionnel, je suppose aussi que l’interprétation de la fonction via la fonction eval doit prendre du temps dans l’exécution : est-ce sensible si on doit appliquer cette « évaluation » sur une bonne dizaine de fonctions ? D’après ma compréhension du code, qu’on charge la variable contenant toutes les fonctions en entier et qu’on « évalue » une seule fonction ou qu’on charge une variable contenant une seule fonction et qu’on l’évalue ensuite doit grosso-modo revenir au même temps d’exécution… Est-ce que je me trompe ?

Je vais ajouter une question de néophyte concernant la condition évitant la répétition du script : que désigne ‹ varMachin › ? Est-ce une méthode spécifique à document ?

Merci encore pour vos suggestions, remarques et aides plus qu’efficaces.
Cordialement
Philippe

Pour moi, le plus propre reste l’ajout dans skin.js, les variables peuvent être re-exécutés plusieurs fois par page.

1 « J'aime »

Je n’ai aucune idée concernant la vitesse d’exécution (d’autant qu’il s’agit de javascript et donc d’une exécution locale, tout dépend ainsi de la machine de l’usager) mais j’imagine que plus on imbrique des éléments dans d’autres éléments, plus ça prend du temps à faire le chemin dans l’autre sens… :grinning:
Concernant la répétition du script, il s’agit d’un « truc » fourni par @sam il y a 2 ans ici.

Bonjour Sam,
J’ai essayé l’intégration d’une fonction javascript dans le fichier skin.js « à la main » sans restyliser (à postériori : après génération du site).
Est-ce que cette méthode est possible ?
Dans le cas positif, je n’ai pas réussi à utiliser la fonction en question. Quelle serait la syntaxe pour l’appel de la fonction déclarée dans skin.js dans un indicateur calculé automatique ?
Merci d’avance
Cordialement
Philippe Vignoles

Bonjour,
Je relance le sujet concernant les fonctions javascript dans skin.js…
Je viens d’identifier un problème concernant la disponibilité des fonctions insérées dans le fichier skin.js :
si je ne change rien, l’appel aux fonctions provoque une erreur car de toute évidence, lorsque la page est chargée, l’appel au fichier skin.js apparait tardivement (en fin de fichier). J’ai essayé de placer l’appel au script skin.js en haut de page (avec les autres appels de scripts) : et là, les fonctions centralisées dans skin.js sont correctement utilisées.
Comment puis-je faire pour standardiser l’appel à skin.js ?
Merci d’avance
Cordialement
Philippe Vignoles

Bonjour à tous,
J’apporte finalement une réponse aux interrogations que je me posais concernant l’ajout de fonctions JS personnalisées.
Tout d’abord, avec beaucoup de difficultés et d’appréhensions, j’ai enfin décidé de me lancer dans Builder afin de reprendre le code source du modèle Topaze. J’ai identifié les entrées concernant le fichier skin.js dans les différents items de Mirage.
Effectivement, l’appel à ce fichier se fait dans la partie body de la page et je l’ai donc placé dans la partie head après les appels aux css.
J’ai fait cette manipulation pour chaque item de Mirage contenant l’appel à skin.js (on ne sait jamais).
Pour information, j’ai pris soin également de renommer le modèle pour éviter d’écraser l’original,
puis compilation de la modification pour obtenir un nouveau wsppack.
J’ai ensuite utilisé ce nouveau pack dans mon atelier avec succès : maintenant, l’appel au fichier skin.js se fait bien et les fonctions qu’il contient sont disponibles sans erreur.
J’ai également stylisé le modèle afin d’inclure un skin.js complet contenant mes fonctions JS. En suivant la documentation, j’ai donc compilé un nouveau skin dont le seul but est d’ajouter le fichier skin.js contenant mes fonctions.
Bon cela reste assez « classique » en fin de compte mais je suis assez fier de moi (il m’en faut peu) d’avoir pu faire ces ajustements qui me paraissaient pourtant hors de portée jusqu’à présent.
Pour aller plus loin encore (mais ce sera une autre histoire je pense car là, ça semble plus compliqué que de rajouter une ligne dans un fichier), j’aimerais bien arriver à reprendre le code topaze pour ajouter une liste déroulante optionnelle sur les indicateurs apprenants pour la saisie.
Merci à tous ceux qui m’ont apporté des informations plus qu’efficaces dans ce problème. J’espère aussi que ces informations pourront apporter des réponses à d’autres personnes que moi.
Cordialement
Philippe Vignoles

Bonjour,

Bravo pour votre incursion dans le monde de SCENARIbuilder !

J’ai quelques remarques et questions.
L’inclusion de skin.js à la fin du body mais avant les appels aux fonctions init des managers Javascript permet dans presque tout les cas de soit injecter du contenu dans la page ou modifier les librairies standards avant leur appel.
Mettre skin.js avant le body veux dire qu’un skin ne peut pas avoir directement connaissance du DOM de la page, du coup vous cassez tout skin qui a été conçu dans ce sens.

Pouvez-vous le fournir votre skin et un scar d’exemple qui montre une situation ou vous n’arrivez pas à utiliser une fonction JS posé dans le skin ?

Bonjour,

Une remarque : pour éviter les problèmes éventuels signalés par Samuel, si vous avez vraiment besoin d’un script js dans le head de la page (je n’ai pas compris non plus pourquoi vous avez ce besoin), vous pourriez ajouter un 2ème fichier, par exemple skinHead.js plutôt que de déplacer l’appel à skin.js.

Bonjour Sam,
En fait, je me suis aperçu que rajouter des fonctions js dans skin.js ne donnait pas le résultat escompté car l’appel à ces fonctions échouait. J’ai donc testé l’appel de skin.js dans la partie head et là cela a fonctionné.
En pratique, j’ai réalisé un doublon d’appel dans la page car je n’ai pas supprimé la ligne d’appel présente dans la partie body (l’appel existe donc à la fois dans head et dans body)…
Oui, bien entendu, je peux fournir une sauvegarde de l’atelier utilisé pour les besoins. Où puis-je le déposer ?
Cordialement
Philippe Vignoles

Bonjour,
Formellement, je peux me passer d’un fichier script contenant les fonctions statistiques en JS dont j’ai besoin mais dans ce cas de figure, il faut que je les intègre systématiquement dans mes indicateurs calculés (ça fait redondant avec un risque élevé d’inclure des erreurs, etc.).
Effectivement, je pourrais ajouter un fichier moins « officiel » et je retiens votre idée. Au départ, je suivais l’idée que Sam avait suggérée en éditant skin.js.
Cordialement
Philippe Vignoles

C’est justement ce point que je cherche à comprendre.
Vous pouvez déposer une archive sur service comme https://drop.picasoft.net/ et me fournir le lien en MP.

Bonjour,

J’ai pu un peut jouer avec votre exemple et j’ai trouvé une solution, c’est un hack mais il fonctionne.

En effet l’affichage des indicateurs se fait en direct lors de la construction du DOM de la page, par conséquent les fonctions apportés par skin.js arrivent trop tard.

Il y a plusieurs solutions à ce problème mais la plus simple dans l’immédiat, qui reste compatible avec la version standard de Topaze tout en continuant de faire porter la déclaration des fonctions supplémentaires par le skin, est de les déclarer dans un sous objet de scServices, c.a.d. d’en faire un service transverse scenari.
Normalement un service est déclaré dans index.html mais ici je l’initialise dans skin.js si il n’a pas encore été déclaré. Comme skin.js est chargé dans 100% des pages, y compris la première page, c’est au chargement de cette page d’accueil que le service est déclaré, il est donc ensuite disponible pour toutes les étapes du cas. La seule limite à ce hack : il n’est pas possible d’utiliser ce service sur l’accueil du cas.
Il suffit ensuite de revoir l’appel des fonctions dans les indicateurs pour refléter leur inclusion dans un service.

Voici donc en exemple la déclaration de la librairie en scService (avec une seule fonction) :

// skin.js
if (!scServices.statLib) scServices.statLib = {
    // Fonction pour calculer la moyenne
    maMoyenne : function (arr) {
        return arr.reduce((sum, value) => sum + value, 0) / arr.length;
    },
}

Ici je déclare donc scServices.statLib si il existe pas déjà. Ensuite je peux utiliser la fonction maMoyenne comme ceci :

return scServices.statLib.maMoyenne([INPUT1, INPUT2, INPUT3]) ;

Dans la prochaine version de Topaze on pourra réfléchir à d’autres solutions.