[SPIP Zone] HTML5, required, afficher_si et performance

Holla,

sur la page
https://www.planete-sciences.org/astro/campagne-astronomie/inscription nous avons un formulaire formidable qui utilise massivement les afficher_si. En dehors même du fait qu'on pourrait améliorer certains éléments du formulaire, je ne pense pas qu'on puisse substantiellement simplifier ce formulaire (je connais plutot bien le besoin !).

Depuis qu'on est passé en HTML 5, il y a une latence de 10 secondes à chaque changement de valeur. Pourquoi : à cause des des bascules sur les attributs required.

En effet, à chaque changement dans le formulaire, tous les afficher_si sont testés en JS (j'explique cela en PS). Si la condition d'affichage est rempli, alors .show() est appliqué à la saisie, sinon .hide() est appliqué à la saisie. Cette partie là ne pose pas trop de problème en terme de perf, car on applique cela directement sur la saisie elle-même (sur le div englobant).

En revanche, si, et uniquement si, HTML 5 est autorisé, alors il faut basculer automatiquement les attribut required des input/textarea INCLUENT dans les saisies (donc pas le div englobant). Et c'est là où cela ralentit.
Evidemment, si on pouvait n'executer le js que pour les saisies effectivement impactées par un changement dans le formulaire, ce serait idéal, mais ce n'est pas simple (cf. PS).

En revanche, mon constat est que le ralentissement est essentiellement lié au selecteur jquery utilisé pour impacter les saisies.
Le sélecteur est défini ici
https://zone.spip.net/trac/spip-zone/browser/spip-zone/plugins/saisies/trunk/inc/saisies_afficher_si.php#L131
et permet de couvrir tous les cas de saisies contenant des AFFICHER_SI, quel que soit leur type (textarea, input, etc.).
J'ai fait un test en modifiant rapidement inc/afficher_si.php, de sorte que le selecteur jquery pour la bascule des required corresponde précisément à la saisie concernée par l'afficher_si. Et là le lague devient minime (sachant que mon formulaire est particulièrement complexe). De plus je passe de 64ko de js à 23ko.

Donc j'aurais tendance à dire, allons vers cette piste. MAIS, et c'est là où le bât blesse, étant donné que les saisies, notamment lorsqu'elle sont complexe (date, evenements) peuvent avoir une structure assez particulière, on ne peut se contenter de mon test rapide, et il faudrait que les selecteur jquery dépende de chaque type de saisie, y compris pour les saisie qui ne sont pas livrées avec le plugin.

De plus, dans le cas de la saisie évènements (plugin agenda), les paramètres de la saisie peuvent aussi influencer les selecteur jquery a à émettre, selon la valeur de type_choix.

Du coup, on doit avoir des js saisie individuelle par saisie individuelle. Je vois plusieurs manières de résoudre cela.

1. un squelette js.html pour chaque saisie potentiellement concernée. Avantage : on profite du cache. Inconvénient : on fait beaucoup d'écriture pour pas grand chose.
2. une fonction pour chaque saisie potentiellement concernée
3. un pipeline qui reçois en $flux['data'] le sélecteur jquery et en $flux['arg'] la description de la saisie.

Mes questions sont donc
1. Est-ce que vous voyez d'autres solutions
2. Entre les 3 pistes, laquelle vous semble la plus pertinente
3. Y-a-il moyen d'avoir une liste des plugins qui proposent des saisies supplémentaires pour adapter le cas échéant?

Bises

Amitiés

Maïeul

Ps: pourquoi tout les tests conditionnels sont effectué en JS à chaque changement dans le formulaire, et non pas uniquement celle pour les saisies qui viennent de subir une modif ?
Les afficher_si ce sont des saisies SOURCES qui impactent des saisies CIBLES. Mais ils sont définis saisie CIBLE par saisie CIBLE, et non pas saisies SOURCE saisie CHAMP SOURCE. Et pour cause : pour pouvoir faire cela de manière sélective, en ne testant que les champs (CIBLE) impactés par les modifs d'une saisie SOURCE, il faudrait pourvoir extraire en PHP les saisies SOURCE concernées pour produire des js qui ne fassent les tests que lors que la saisie SOURCE connaît un changement (bascule de select, modif de texte, etc.). C'est pas impossible en théorie, mais je ne suis pas sur que le jeu en vaut la chandelle. En tout cas ce serait un gros poubelle de réécriture coté PHP, je suis pas sur qu'en plus y gagnerait en terme de poids js, et on aurait un js encore plus complexe. Bref, je me lancerai pas dans l'aventure là.

Du reste cet optimisation n'es pas incompatible avec l'optimisation que je propose dans le corps de mail.

Ps2 :
https://framadrop.org/r/nMRDIKaDXk#4QuCwHlvU4fayDH5R9RGd1H2gl72k5Ue5yd1RVSNDm8=
https://framadrop.org/r/RMFAGAMt3K#AMdRwKk+orlbapIGh3QASQNM+nAqkHSa6Gyxt+isSBU=

Le yaml du formulaire + mon saisies_afficher_si modifié

Le 28/04/2019 à 19:17, Maïeul a écrit :

sur la page
https://www.planete-sciences.org/astro/campagne-astronomie/inscription nous avons un formulaire formidable qui utilise massivement les afficher_si. En dehors même du fait qu'on pourrait améliorer certains éléments du formulaire, je ne pense pas qu'on puisse substantiellement simplifier ce formulaire (je connais plutot bien le besoin !).
Depuis qu'on est passé en HTML 5, il y a une latence de 10 secondes à chaque changement de valeur. Pourquoi : à cause des des bascules sur les attributs required.

Je n'ai pas vraiment compris tes explications mais voici une idée.

Dans le code que tu pointes
https://zone.spip.net/trac/spip-zone/browser/spip-zone/_plugins_/saisies/trunk/inc/saisies_afficher_si.php#L131
tu génères dynamiquement les sélecteurs cibles du javascript,
mais tu utilises des sélecteurs totalement génériques,
identiques pour tout formulaire formidable.

Or, contrairement à toi qui code un générateur de formulaire (et non un formulaire),
Formidable connaît en détail le contenu des formulaires générés.

Donc au lieu de ces sélecteurs génériques, peut être te serait t il possible
de coder ce qui permet à formidable
de générer précisément les sélecteurs CSS utiles pour ce formulaire,
en intégrant seulement ceux qui sont réellement requis,
et en les ciblant de manière pas générique du tout mais efficace.
Par exemple les cibler directement par leur id.

JL

Le 28/04/2019 à 20:41, JLuc a écrit :

tu génères dynamiquement les sélecteurs cibles du javascript,
mais tu utilises des sélecteurs totalement génériques,
identiques pour tout formulaire formidable.

Salut,

pour pratiquer pas mal les afficher_si, je vois à peu près le problème soulevé par maïeul.
Je n'ai pas de réponse là tout de suite, mais par contre ça ne se limite pas à Formidable : les afficher_si fonctionnent aussi avec des saisies déclarées en tableaux PHP et générées avec #GENERER_SAISIES.

--
nicod_

Le 28/04/2019 à 19:17, Maïeul a écrit :

Mes questions sont donc
1. Est-ce que vous voyez d'autres solutions
2. Entre les 3 pistes, laquelle vous semble la plus pertinente
3. Y-a-il moyen d'avoir une liste des plugins qui proposent des saisies
supplémentaires pour adapter le cas échéant?

Pas étudié le code en détail pour l'instant, donc juste des remarques
rapides.

- Je ne suis pas pour faire des spécificités par saisies, encore moins
des fichiers dédiés, c'est déjà assez le bordel comme ça. :smiley:
Au max il faut trouver une solution générique.

- Dans le HTML de base qui est en dur, quand ya HTML5, on génère déjà
les attributs "required". Donc pourquoi vouloir sélectionner pour chaque
type de saisie ? Je pose la question mais est-ce qu'il n'y aurait pas
moyen de directement sélectionner ceux qui ont cet attribut, peu importe
quoi, au lieu d'avoir 10 sélecteurs et autant de traitement par jquery
du coup ? Du genre
.obligatoire > [required]
En plus yorait même pas à tester "if html5", et simplifier le JS, vu que
si ya ces attributs, c'est forcément qu'il y a html5…

- Je comprends même pas pourquoi ya plusieurs fois les mêmes
$sel.obligatoire > textarea ou $sel.obligatoire > select en parlant de
fieldsets…

- Cette génération de code est totalement illisible, quitte à y passer
du temps sur ce morceau de code, moi ça fait des années que je pense que
ça devrait être refactoré complètement en stockant les conditions dans
des data-afficher_si et en n'ayant plus qu'un JS STATIQUE, absolument
pas différent pour chaque page.

--
RastaPopoulos

Le 28/04/2019 à 21:09, nicod_ a écrit :

Le 28/04/2019 à 20:41, JLuc a écrit :

tu génères dynamiquement les sélecteurs cibles du javascript,
mais tu utilises des sélecteurs totalement génériques,
identiques pour tout formulaire formidable.

pour pratiquer pas mal les afficher_si, je vois à peu près le problème soulevé par maïeul.

Je n'ai pas de réponse là tout de suite, mais par contre ça ne se limite pas à Formidable : les afficher_si fonctionnent aussi avec des saisies déclarées en tableaux PHP et générées avec #GENERER_SAISIES.

Ok.
Je ne pense pas que cela obère ma suggestion.
JL

Le 28/04/2019 à 20:41, JLuc a écrit :

Le 28/04/2019 à 19:17, Maïeul a écrit :

sur la page
https://www.planete-sciences.org/astro/campagne-astronomie/inscription nous avons un formulaire formidable qui utilise massivement les afficher_si. En dehors même du fait qu'on pourrait améliorer certains éléments du formulaire, je ne pense pas qu'on puisse substantiellement simplifier ce formulaire (je connais plutot bien le besoin !).
Depuis qu'on est passé en HTML 5, il y a une latence de 10 secondes à chaque changement de valeur. Pourquoi : à cause des des bascules sur les attributs required.

Je n'ai pas vraiment compris tes explications mais voici une idée.

Dans le code que tu pointes
https://zone.spip.net/trac/spip-zone/browser/spip-zone/_plugins_/saisies/trunk/inc/saisies_afficher_si.php#L131

tu génères dynamiquement les sélecteurs cibles du javascript,
mais tu utilises des sélecteurs totalement génériques,
identiques pour tout formulaire formidable.

Or, contrairement à toi qui code un générateur de formulaire (et non un formulaire),
Formidable connaît en détail le contenu des formulaires générés.

Donc au lieu de ces sélecteurs génériques, peut être te serait t il possible
de coder ce qui permet à formidable
de générer précisément les sélecteurs CSS utiles pour ce formulaire,
en intégrant seulement ceux qui sont réellement requis,
et en les ciblant de manière pas générique du tout mais efficace.
Par exemple les cibler directement par leur id.

JL

----
spip-zone@rezo.net - https://listes.rezo.net/mailman/listinfo/spip-zone

c'est plus ou moins ma proposition, de choisir les selecteurs saisies par saisie (puisqu'il faut avoir l'info sur la saisie mère tout de même, on peut pas faire un test sur tout les required

Le 29/04/2019 à 00:55, RastaPopoulos a écrit :

Le 28/04/2019 à 19:17, Maïeul a écrit :

Mes questions sont donc
1. Est-ce que vous voyez d'autres solutions
2. Entre les 3 pistes, laquelle vous semble la plus pertinente
3. Y-a-il moyen d'avoir une liste des plugins qui proposent des saisies
supplémentaires pour adapter le cas échéant?

Pas étudié le code en détail pour l'instant, donc juste des remarques
rapides.

- Je ne suis pas pour faire des spécificités par saisies, encore moins
des fichiers dédiés, c'est déjà assez le bordel comme ça. :smiley:
Au max il faut trouver une solution générique.

- Dans le HTML de base qui est en dur, quand ya HTML5, on génère déjà
les attributs "required". Donc pourquoi vouloir sélectionner pour chaque
type de saisie ? Je pose la question mais est-ce qu'il n'y aurait pas
moyen de directement sélectionner ceux qui ont cet attribut, peu importe
quoi, au lieu d'avoir 10 sélecteurs et autant de traitement par jquery
du coup ? Du genre
.obligatoire > [required]

le > posera problème (cf fieldest englobé).
le souci est moins sur la suppression de required (si le afficher_si n'est pas validé) que sur la reinsertion (si le afficher_si est validé).
cela étant, ta remarque me fait dire qu'on pourrait sans doute s'en sortir en faisant qu'au moment du masquage du required (avec ton selecteur) on stocke le fait qu'il était required.

Genre
si condition pas rempli
('$sel [required]').attr('required','false').attr('afficher-si-required', true)
si condition remplie
('$sel [afficher-si-required=]').attr('afficher-si-required',false).attr('required',true)

ca devrait pouvoir marcher (et à terme je sais, plus de $sel, mais cf ma réponse plus bas)

En plus yorait même pas à tester "if html5", et simplifier le JS, vu que
si ya ces attributs, c'est forcément qu'il y a html5…

oui et non. C'est une petite optimisation pour un js qui n'est pas le meêm. Et le souci est moins sur masquage des attributs que sur leur reinsertion lorsqu'on reafficher un champ :slight_smile:

- Je comprends même pas pourquoi ya plusieurs fois les mêmes
$sel.obligatoire > textarea ou $sel.obligatoire > select en parlant de
fieldsets…

l'espace est important
$sel .obligatoire > textarea
vs
$sel.obligatoire > select,

$sel pouvant être un fieldset ou bien une saisie simple

- Cette génération de code est totalement illisible, quitte à y passer
du temps sur ce morceau de code, moi ça fait des années que je pense que
ça devrait être refactoré complètement en stockant les conditions dans
des data-afficher_si et en n'ayant plus qu'un JS STATIQUE, absolument
pas différent pour chaque page.

oui je suis d'accord... mais j'ai des problèmes courts termes (et je voulais justement pas aborder ce refactoring long terme... j'ai deja passé pas mal de tps sur le refactoring php...).
Et pour le coup la partie illisible est celle qui genere les tests à partir des afficher_si, pas celle concernant les actions a appliquer en fonction du résultat du test. Donc en amont.

Suite aux remarques de Rastapopoulos dans un thread, un meilleur selcteur a été fait, se basant sur la propriété required, et qui permet de gérer correctement la bascule dans les deux sens (c'était cela le sens des sélecteurs hyper complexe).

Avant de le commiter, j'aimerais avoir des retours de test. Le patch est joint,

Je ferais moi même des tests sur chacune des saisies mentionnés en commentaires des sélecteurs actuels. Mais plusieurs tests valent mieux qu'un. (même si je pense que globalement le système du patch devrait marcher dans tous les cas, puisque cela désactive/reactive le required sur la base des required existant au moment de la def du formulaire, et pas, comme actuellement, sur la base de spéculation sur les balises qui devraient avoir des required)

afficher_si_patch.diff (2.07 KB)

Le 29/04/2019 à 23:21, Maïeul a écrit :

Suite aux remarques de Rastapopoulos dans un thread, un meilleur selcteur a été fait, se basant sur la propriété required, et qui permet de gérer correctement la bascule dans les deux sens (c'était cela le sens des sélecteurs hyper complexe).

Avant de le commiter, j'aimerais avoir des retours de test. Le patch est joint,

Je ferais moi même des tests sur chacune des saisies mentionnés en commentaires des sélecteurs actuels. Mais plusieurs tests valent mieux qu'un. (même si je pense que globalement le système du patch devrait marcher dans tous les cas, puisque cela désactive/reactive le required sur la base des required existant au moment de la def du formulaire, et pas, comme actuellement, sur la base de spéculation sur les balises qui devraient avoir des required)

----
spip-zone@rezo.net - https://listes.rezo.net/mailman/listinfo/spip-zone

voilà j'ai commité. J'ai fait des test en réels, et c'est bon. En plus d'un point de vue logique, il y a pas d'exception, donc pas de raison que cela marche pas.