From ed4dd78dad24bdcba72bf0b9a2a4d2cc1ab15260 Mon Sep 17 00:00:00 2001
From: william
Date: Fri, 28 Aug 2026 09:58:50 +0200
Subject: [PATCH] =?UTF-8?q?Corrige=20le=20clignotement=20de=20la=20bo?=
=?UTF-8?q?=C3=AEte=20de=20dialogue=20enti=C3=A8re=20au=20lieu=20du=20seul?=
=?UTF-8?q?=20texte?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Suite du correctif précédent (124f250, marqueur "dataBound") : le
rafraîchissement fonctionnait, mais remplaçait tout l'élément de PREMIER
NIVEAU marqué — pour un Texte "Donnée liée" posé DANS un élément de jeu
réutilisable (ex. une boîte de dialogue), le seul élément de premier
niveau existant est l'EXEMPLAIRE lui-même (ses descendants internes ne
sont jamais des entrées séparées de la scène, voir list_elements.py) :
tout l'exemplaire — voile plein écran, boîte, tout — était donc remplacé
d'un bloc, ce qui le faisait visuellement disparaître puis réapparaître
pour un simple changement de texte à l'intérieur.
Correctif (templates/play.html, refreshRuntimeData()) : avant de
remplacer un élément marqué en bloc, on cherche d'abord, DANS le nouveau
fragment, des descendants plus précis portant eux-mêmes un marqueur en
commentaire ("visibilityGated"/"dataBound" — jamais "repeaterItem"/
"jaugeBar", qui restent volontairement régénérés en bloc, un
comportement déjà correct pour un Répéteur/une Jauge). S'il en existe,
seuls CES éléments précis sont patchés individuellement (retrouvés via
leur propre data-element-id) ; sinon, comportement inchangé (remplace
l'élément entier, cas normal d'un Texte "Donnée liée" posé directement
sur une scène, hors élément de jeu réutilisable).
155 tests toujours au vert (changement purement côté client — le
rendu serveur et la présence du marqueur, eux, étaient déjà couverts par
les tests du commit précédent). Vérifié structurellement (adjacence
confirmée dans le rendu réel du projet "test").
Co-Authored-By: Claude Sonnet 5
---
templates/play.html | 43 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/templates/play.html b/templates/play.html
index b82160f9..206db1aa 100644
--- a/templates/play.html
+++ b/templates/play.html
@@ -584,6 +584,31 @@
}
return false;
}
+ // "visibilityGated"/"dataBound" sont posés comme un COMMENTAIRE
+ // HTML juste après la balise concernée (voir _mark() dans
+ // render_element_html.py) — jamais comme une classe CSS, à la
+ // différence de "repeaterItem"/"jaugeBar" (qui, eux, désignent
+ // un widget à régénérer EN BLOC, lignes/valeur comprises, un
+ // comportement déjà correct pour ces deux-là). Repérer ce
+ // commentaire permet de retrouver, à l'intérieur d'un fragment
+ // fraîchement rendu, l'élément PRÉCIS qui a changé — même s'il
+ // est niché dans un exemplaire d'élément de jeu réutilisable
+ // (ex. un Texte "Donnée liée" à l'intérieur d'une boîte de
+ // dialogue), où lui seul porte l'attribut data-element-id qui
+ // l'identifie, son marqueur ne remontant jusqu'au SEUL élément
+ // de premier niveau existant (l'exemplaire) que parce que son
+ // HTML est imbriqué dans le sien.
+ const COMMENT_MARKERS = ['visibilityGated', 'dataBound'];
+ function findCommentMarkedDescendants(root) {
+ const found = [];
+ root.querySelectorAll('[data-element-id]').forEach(function(node) {
+ const sib = node.nextSibling;
+ if (sib && sib.nodeType === Node.COMMENT_NODE && COMMENT_MARKERS.indexOf(sib.data) !== -1) {
+ found.push(node);
+ }
+ });
+ return found;
+ }
const markedCandidates = screenData.elements.filter(hasMarker);
markedCandidates.filter(function(e) {
return !markedCandidates.some(function(other) { return other.id !== e.id && isDescendantOf(other, e.id); });
@@ -593,7 +618,23 @@
const container = document.createElement('div');
container.innerHTML = el.rendered_html;
const newNode = container.firstElementChild;
- if (newNode) target.replaceWith(newNode);
+ if (!newNode) return;
+ const innerMarked = findCommentMarkedDescendants(newNode);
+ if (innerMarked.length) {
+ // Des éléments plus précis existent À L'INTÉRIEUR (ex. un
+ // Texte "Donnée liée" posé dans un élément de jeu
+ // réutilisable) : on ne patche QUE ceux-là, en préservant
+ // tout le reste — une boîte de dialogue ne doit ni
+ // disparaître ni réapparaître juste parce qu'un texte à
+ // l'intérieur a changé.
+ innerMarked.forEach(function(innerNode) {
+ const innerId = innerNode.getAttribute('data-element-id');
+ const liveInner = target.querySelector('[data-element-id="' + innerId + '"]');
+ if (liveInner) liveInner.replaceWith(innerNode);
+ });
+ } else {
+ target.replaceWith(newNode);
+ }
});
applyOpenRowBindings();
} catch (err) {