diff --git a/templates/play.html b/templates/play.html
index 69369ca4..7e611467 100644
--- a/templates/play.html
+++ b/templates/play.html
@@ -351,26 +351,33 @@
// rechargement de page (flash à vide) à chaque clic sur une ligne.
//
// Parmi les éléments qui ont un {{champ}} non résolu, on ne garde que
- // les plus "hauts" dans l'arbre : si un ancêtre ET un de ses
- // descendants sont tous deux candidats, seul l'ancêtre est régénéré
- // (son rendered_html inclut déjà ce descendant) — sans ce filtre, le
- // descendant serait régénéré deux fois, la 2e fois à partir du DOM déjà
- // à jour de la 1re passe.
+ // les plus SPÉCIFIQUES (les plus profonds) : si un élément ET l'un de
+ // ses DESCENDANTS sont tous deux candidats, seul le descendant est
+ // régénéré (rendered_html d'un conteneur inclut TOUJOURS celui de ses
+ // descendants, donc un conteneur "candidat" ne l'est souvent que parce
+ // qu'un descendant à lui l'est — le garder en plus regénérerait
+ // inutilement tout son sous-arbre, à l'exact opposé du but recherché).
+ // ATTENTION : la version précédente de ce filtre vérifiait l'inverse
+ // (exclure un élément si un ANCÊTRE est candidat) — comme un ancêtre
+ // est presque toujours "candidat" dès qu'un descendant l'est (son HTML
+ // le contient), ce filtre ne gardait en pratique QUE l'ancêtre racine
+ // de l'écran, annulant complètement l'effet recherché par ce correctif.
const byId = {};
screenData.elements.forEach(function(e){ byId[e.id] = e; });
function hasUnresolvedPlaceholder(e) {
return !!(e.rendered_html && e.rendered_html.indexOf(PLACEHOLDER_OPEN) !== -1);
}
- function hasCandidateAncestor(e) {
+ function isDescendantOf(e, ancestorId) {
let p = e.parent_id ? byId[e.parent_id] : null;
while (p) {
- if (hasUnresolvedPlaceholder(p)) return true;
+ if (p.id === ancestorId) return true;
p = p.parent_id ? byId[p.parent_id] : null;
}
return false;
}
- const targets = screenData.elements.filter(function(e) {
- return hasUnresolvedPlaceholder(e) && !hasCandidateAncestor(e);
+ const candidates = screenData.elements.filter(hasUnresolvedPlaceholder);
+ const targets = candidates.filter(function(e) {
+ return !candidates.some(function(other) { return other.id !== e.id && isDescendantOf(other, e.id); });
});
targets.forEach(function(el) {
@@ -480,25 +487,33 @@
// qui portait le marqueur (le Répéteur imbriqué à l'intérieur)
// et se retrouvait régénéré en entier à sa place — potentiellement
// l'écran entier (jauges, onglets... compris) s'il n'y avait
- // qu'un seul gros conteneur racine. Comme pour
- // applyOpenRowBindings(), on ne garde que les éléments marqués
- // les plus "hauts" dans l'arbre, pour ne jamais régénérer un même
- // nœud deux fois.
+ // qu'un seul gros conteneur racine.
+ //
+ // Parmi les éléments marqués, on ne garde que les plus
+ // SPÉCIFIQUES (les plus profonds) : un ancêtre est presque
+ // toujours "marqué" lui aussi dès qu'un descendant l'est, puisque
+ // son rendered_html contient celui de ses descendants — le
+ // garder EN PLUS régénérerait tout son sous-arbre pour rien.
+ // (Une version antérieure de ce filtre vérifiait l'inverse —
+ // exclure un élément si un ANCÊTRE est marqué — ce qui ne
+ // gardait en pratique que l'ancêtre racine de l'écran et
+ // annulait complètement l'effet recherché.)
const byId = {};
screenData.elements.forEach(function(e){ byId[e.id] = e; });
function hasMarker(e) {
return !!(e.rendered_html && (e.rendered_html.indexOf('repeaterItem') !== -1 || e.rendered_html.indexOf('jaugeBar') !== -1 || e.rendered_html.indexOf('visibilityGated') !== -1));
}
- function hasMarkedAncestor(e) {
+ function isDescendantOf(e, ancestorId) {
let p = e.parent_id ? byId[e.parent_id] : null;
while (p) {
- if (hasMarker(p)) return true;
+ if (p.id === ancestorId) return true;
p = p.parent_id ? byId[p.parent_id] : null;
}
return false;
}
- screenData.elements.filter(function(e) {
- return hasMarker(e) && !hasMarkedAncestor(e);
+ const markedCandidates = screenData.elements.filter(hasMarker);
+ markedCandidates.filter(function(e) {
+ return !markedCandidates.some(function(other) { return other.id !== e.id && isDescendantOf(other, e.id); });
}).forEach(function(el) {
const target = screenDiv.querySelector('[data-element-id="' + el.id + '"]');
if (!target) return;