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