diff --git a/templates/play.html b/templates/play.html index 1fce822e..f6945494 100644 --- a/templates/play.html +++ b/templates/play.html @@ -411,21 +411,39 @@ screensData = gameData.screens; const screenData = screensData.find(s => s.id === window.currentScreenId); const screenDiv = document.querySelector('.playScreen[data-screen-id="' + window.currentScreenId + '"]'); - if (!screenData || !screenDiv) return; - screenData.elements.filter(function(e){ return !e.parent_id; }).forEach(function(el) { - if (!el.rendered_html) return; - // "repeaterItem" (liste de données), "jaugeBar" (2.1 — jauge liée - // à une donnée) et "visibilityGated" (condition de visibilité — - // voir render_element_html.py) sont les types d'éléments dont le - // contenu/l'affichage dépend de la donnée elle-même plutôt que - // d'une action "Modifier un élément" posée à la main dans le - // graphe — eux seuls doivent être régénérés après un changement - // de donnée ou de variable. - if (el.rendered_html.indexOf('repeaterItem') === -1 && el.rendered_html.indexOf('jaugeBar') === -1 && el.rendered_html.indexOf('visibilityGated') === -1) return; - const wrapper = screenDiv.querySelector('.playElement[data-el-id="' + el.id + '"] .playElementInner'); - if (wrapper) wrapper.innerHTML = el.rendered_html; - }); - applyOpenRowBindings(); + // Le bloc ci-dessous (régénération du contenu de l'écran courant) + // est sauté si l'écran n'est pas trouvé, mais bindClicks() et les + // autres réattachements juste après ne doivent JAMAIS dépendre de + // cette condition : un retour anticipé ici a déjà laissé, dans la + // pratique, un Répéteur fraîchement régénéré sans AUCUN gestionnaire + // de clic pour le reste de la partie (plus aucune ligne ne + // répondait, silencieusement, sans erreur) — ces fonctions sont sans + // risque à rappeler même quand rien n'a changé. + if (screenData && screenDiv) { + // try/catch : une erreur inattendue pendant la régénération (ex. + // structure de données imprévue) ne doit jamais empêcher les + // réattachements ci-dessous de s'exécuter — sinon le Répéteur (ou + // tout autre élément cliquable) reste silencieusement inerte pour + // le reste de la partie, sans le moindre message d'erreur visible. + try { + screenData.elements.filter(function(e){ return !e.parent_id; }).forEach(function(el) { + if (!el.rendered_html) return; + // "repeaterItem" (liste de données), "jaugeBar" (2.1 — jauge liée + // à une donnée) et "visibilityGated" (condition de visibilité — + // voir render_element_html.py) sont les types d'éléments dont le + // contenu/l'affichage dépend de la donnée elle-même plutôt que + // d'une action "Modifier un élément" posée à la main dans le + // graphe — eux seuls doivent être régénérés après un changement + // de donnée ou de variable. + if (el.rendered_html.indexOf('repeaterItem') === -1 && el.rendered_html.indexOf('jaugeBar') === -1 && el.rendered_html.indexOf('visibilityGated') === -1) return; + const wrapper = screenDiv.querySelector('.playElement[data-el-id="' + el.id + '"] .playElementInner'); + if (wrapper) wrapper.innerHTML = el.rendered_html; + }); + applyOpenRowBindings(); + } catch (err) { + console.error('refreshRuntimeData: erreur pendant la régénération de l\'écran', err); + } + } bindClicks(); bindHoverTexts(); bindHoverTriggers();