Factorisation de fonctions javascript
Pour la partie admin de mon projet, il y a pas mal de choses qui vont servir pour différents contrôleurs, par exemple les listes d’éléments ainsi que les opérations d’ajout, d’édition ou de suppression.
Pour la partie vue, j’ai donc créé deux composants, un fichier list.blade.php ainsi qu’un fichier row.blade.php.
Pour la partie javascript j’avais déjà créé un système d’export import des fonctions.
Pour quasiment tous les contrôleurs, il y a trois fonctions principales Create, Update, Delete, pour les deux premières, une fancybox est affichée et une fois les données saisies, l’utilisateur peut les enregistrer, pour la suppression elle se fait directement.
Les appels correspondant dans mon schéma sont :
bindUserCreate
bindUserUpdate
bindUserDelete
Après avoir testé le contrôleur, ce qui ajoute encore deux lignes, puisque pour Rights par exemple, ce serait :
bindRightCreate
bindRightUpdate
bindRightDelete
Afin de factoriser au mieux ces trois appels, j’ai donc procédé ainsi :
Création d’une fonction d’attente qui va recevoir l’objet controller_functions
, le nom du contrôleur singularisé et pour lequel on ajoute une majuscule au début, l’action cible, le ou les paramètres si nécessaire, ce qui donne pour les appels qui nous intéressent :
context_functions.backClass.bind(controller_functions, aiop_setFunctionName(controller_functions.name), 'Delete');
context_functions.backClass.bind(controller_functions, aiop_setFunctionName(controller_functions.name), 'Update', Fancybox);
context_functions.backClass.bind(controller_functions, aiop_setFunctionName(controller_functions.name), 'Create', Fancybox);
A noter qu’on pourrait sans doute encore factoriser en utilisant les deux derniers champs en un tableau, mais pour le moment ces trois lignes me suffisent.
La fonction aiop_setFunctionName
reçoit le nom de la page, par exemple users ou categories, et va devoir transformer ces chaines respectivement en User ou Category.
Pour arriver à ce résultat, j’ai créé une constante d’environnement dans le fichier .env pour les correspondances pluriel / singulier :
PLURAL_SINGULAR = '{"ies": "y", "s": ""}'
Cette constante pouvant être enrichie à la demande pour de nouveaux cas.
Elle est récupérée dans les paramètres globaux du fichier Controller.php
'plural_singular' => env('PLURAL_SINGULAR')
Ensuite dans la vue on ajoute la variable au javascript
var plural_singular = {!! $global_parameters->plural_singular !!};
Attention lorsque vous utilisez {{
dans blade, la variable est passée avec htmlspecialchars, ce qui dans notre cas transformerait les "
en "
, pour éviter cela et si vous êtes certain de la chaine à traiter, il faut utiliser {!!
qui passe la variable brute.
Ensuite les fonctions de capitalisation ainsi que celle de définition du nom :
/* Global functions */
function aiop_capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function aiop_setFunctionName(name) {
for (var key in plural_singular) {
if (name.indexOf(key) != -1) {
name = name.substring(0, name.length - key.length)+plural_singular[key];
}
}
return aiop_capitalize(name);
}
aiop_setFunctionName
va donc parcourir la liste des éléments de la constante PLURAL_SINGULAR
, vérifiant si la fin de la chaine à traiter correspond à une clé pour la remplacer, puis on capitalise la première lettre.
Pour users, la fonction d’attente va donc recevoir :context_functions.backClass.bind(controller_functions, 'User', 'Update', Fancybox);
Enfin la fonction d’attente va traiter la demande … :
/**
* Bind object method
*
* @param object object Needed object
* @param string function_name Function name to call
* @param string action action to apply
* @param object fancybox Fancybox object (optionnal)
*
* @return void
*/
bind : function(object, function_name, action, fancybox = null) {
backClass.executeFunctionByName(object, 'bind'+function_name+action, fancybox);
},
… Et appeler l’exécution de la fonction finale :
/**
* Execute object function from its name and object
*
* @param object object Needed object
* @param string function_name Function name to call
* @param object fancybox Args (optionnal)
*
* @return void
*/
executeFunctionByName : function(object, function_name, args = null) {
object[function_name](args);
},
Cette méthode permet de factoriser au mieux les appels récurrent qui demanderaient 5 lignes par appel sinon en comptant le test pour connaitre le contrôleur appelant.