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) {