Dev #5
+47
-31
@@ -265,28 +265,39 @@
|
||||
}
|
||||
|
||||
// Trouve, pour un élément et un type de déclencheur ("clic"/"soumission"),
|
||||
// le nœud Déclencheur qui lui est rattaché — c'est le point d'entrée du
|
||||
// graphe à exécuter. On cherche dans TOUS les écrans (pas seulement
|
||||
// l'écran courant) : bindClicks() attache les gestionnaires une seule
|
||||
// fois, sur tous les éléments de tous les écrans (déjà tous présents dans
|
||||
// le DOM, seuls les écrans non actifs sont masqués) — chaque identifiant
|
||||
// d'élément est unique dans tout le jeu, donc pas d'ambiguïté possible.
|
||||
// Cette recherche globale couvre aussi les écrans-MODÈLES (un élément de
|
||||
// jeu réutilisable, ex. "mail content", posé sur une scène) : un
|
||||
// déclencheur "Au clic"/"Au survol" posé dans l'éditeur du modèle, sur un
|
||||
// de SES PROPRES enfants, est donc retrouvé même quand ce modèle est
|
||||
// utilisé ailleurs — d'où le besoin de renvoyer aussi l'écran d'origine du
|
||||
// nœud (screenIdKey), pas seulement le nœud : runFlowFrom() doit exécuter
|
||||
// le graphe dans CET écran-là (celui du modèle), jamais dans celui
|
||||
// réellement affiché, sans quoi le nœud trouvé n'existerait pas dans le
|
||||
// graphe utilisé et l'action ne se déclencherait jamais.
|
||||
function findTriggerNode(elementId, event) {
|
||||
// TOUS les nœuds Déclencheur qui lui sont rattachés — ce sont les points
|
||||
// d'entrée des graphes à exécuter. Renvoie un TABLEAU (jamais un seul
|
||||
// nœud) : rien n'empêche de poser plusieurs déclencheurs indépendants
|
||||
// "Au clic" sur le MÊME élément (ex. l'un ouvre une ligne de Répéteur,
|
||||
// l'autre éteint une surbrillance) — un seul clic doit alors exécuter
|
||||
// CHACUN de ces graphes, pas seulement le premier trouvé (régression
|
||||
// vécue : un second déclencheur posé sur un élément qui en avait déjà un
|
||||
// restait silencieusement inerte, aucune erreur, juste jamais exécuté).
|
||||
//
|
||||
// On cherche dans TOUS les écrans (pas seulement l'écran courant) :
|
||||
// bindClicks() attache les gestionnaires une seule fois, sur tous les
|
||||
// éléments de tous les écrans (déjà tous présents dans le DOM, seuls les
|
||||
// écrans non actifs sont masqués) — chaque identifiant d'élément est
|
||||
// unique dans tout le jeu, donc pas d'ambiguïté possible. Cette recherche
|
||||
// globale couvre aussi les écrans-MODÈLES (un élément de jeu réutilisable,
|
||||
// ex. "mail content", posé sur une scène) : un déclencheur "Au clic"/"Au
|
||||
// survol" posé dans l'éditeur du modèle, sur un de SES PROPRES enfants,
|
||||
// est donc retrouvé même quand ce modèle est utilisé ailleurs — d'où le
|
||||
// besoin de renvoyer aussi l'écran d'origine de CHAQUE nœud (screenIdKey),
|
||||
// pas seulement le nœud : runFlowFrom() doit exécuter le graphe dans CET
|
||||
// écran-là (celui du modèle), jamais dans celui réellement affiché, sans
|
||||
// quoi le nœud trouvé n'existerait pas dans le graphe utilisé et l'action
|
||||
// ne se déclencherait jamais.
|
||||
function findTriggerNodess(elementId, event) {
|
||||
const found = [];
|
||||
for (const screenIdKey in gameData.flows) {
|
||||
const flow = gameData.flows[screenIdKey];
|
||||
const found = flow.nodes.find(n => n.node_type === 'trigger' && n.trigger_element_id === elementId && (n.trigger_event || 'clic') === event);
|
||||
if (found) return { node: found, screenId: screenIdKey };
|
||||
gameData.flows[screenIdKey].nodes.forEach(function(n) {
|
||||
if (n.node_type === 'trigger' && n.trigger_element_id === elementId && (n.trigger_event || 'clic') === event) {
|
||||
found.push({ node: n, screenId: screenIdKey });
|
||||
}
|
||||
});
|
||||
}
|
||||
return null;
|
||||
return found;
|
||||
}
|
||||
|
||||
// Ré-attache les gestionnaires de clic sur chaque élément — appelé au
|
||||
@@ -313,8 +324,8 @@
|
||||
function bindClicks() {
|
||||
document.querySelectorAll('[data-element-id]').forEach(elDiv => {
|
||||
const elementId = parseInt(elDiv.dataset.elementId, 10);
|
||||
const trigger = findTriggerNode(elementId, 'clic');
|
||||
if (trigger) {
|
||||
const triggers = findTriggerNodess(elementId, 'clic');
|
||||
if (triggers.length) {
|
||||
// Garde-fou anti-doublon : refreshRuntimeData() rappelle bindClicks()
|
||||
// après chaque changement de donnée, mais un élément qui n'est ni un
|
||||
// Répéteur ni une Jauge garde le MÊME nœud DOM d'un rafraîchissement
|
||||
@@ -337,7 +348,9 @@
|
||||
const rowEl = ev.target.closest('.repeaterItem');
|
||||
window.lastClickedRowId = rowEl ? parseInt(rowEl.dataset.rowId, 10) : null;
|
||||
window.lastClickedDefinitionId = elDiv.dataset.definitionId ? parseInt(elDiv.dataset.definitionId, 10) : null;
|
||||
runFlowFrom(trigger.node.id, trigger.screenId);
|
||||
// Exécute CHAQUE déclencheur "Au clic" posé sur cet élément, pas
|
||||
// seulement le premier (voir le commentaire de findTriggerNodess).
|
||||
triggers.forEach(trigger => runFlowFrom(trigger.node.id, trigger.screenId));
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -354,12 +367,15 @@
|
||||
document.querySelectorAll('[data-element-id]').forEach(elDiv => {
|
||||
if (elDiv.dataset.hoverTriggerBound) return;
|
||||
const elementId = parseInt(elDiv.dataset.elementId, 10);
|
||||
const enterTrigger = findTriggerNode(elementId, 'survol');
|
||||
const leaveTrigger = findTriggerNode(elementId, 'fin_survol');
|
||||
if (!enterTrigger && !leaveTrigger) return;
|
||||
const enterTriggers = findTriggerNodess(elementId, 'survol');
|
||||
const leaveTriggers = findTriggerNodess(elementId, 'fin_survol');
|
||||
if (!enterTriggers.length && !leaveTriggers.length) return;
|
||||
elDiv.dataset.hoverTriggerBound = '1';
|
||||
if (enterTrigger) elDiv.addEventListener('mouseenter', () => runFlowFrom(enterTrigger.node.id, enterTrigger.screenId));
|
||||
if (leaveTrigger) elDiv.addEventListener('mouseleave', () => runFlowFrom(leaveTrigger.node.id, leaveTrigger.screenId));
|
||||
// Exécute CHAQUE déclencheur trouvé, pas seulement le premier — voir
|
||||
// le commentaire de findTriggerNodess (plusieurs déclencheurs
|
||||
// indépendants sur le même élément/événement doivent tous s'exécuter).
|
||||
if (enterTriggers.length) elDiv.addEventListener('mouseenter', () => enterTriggers.forEach(t => runFlowFrom(t.node.id, t.screenId)));
|
||||
if (leaveTriggers.length) elDiv.addEventListener('mouseleave', () => leaveTriggers.forEach(t => runFlowFrom(t.node.id, t.screenId)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -982,10 +998,10 @@
|
||||
// continue sur son (ou ses) fil de sortie ; chaque nœud Condition évalue
|
||||
// une donnée du jeu et suit le(s) fil(s) "Vrai" ou "Faux" en conséquence.
|
||||
// flowScreenId : l'écran PROPRIÉTAIRE du graphe à exécuter — par défaut
|
||||
// l'écran affiché, mais peut être un écran-MODÈLE (voir findTriggerNode)
|
||||
// l'écran affiché, mais peut être un écran-MODÈLE (voir findTriggerNodes)
|
||||
// quand le nœud de départ vient d'un déclencheur posé dans l'éditeur d'un
|
||||
// élément de jeu réutilisable, sur un de ses propres enfants. Sans ce
|
||||
// paramètre, un tel déclencheur était bien retrouvé (findTriggerNode
|
||||
// paramètre, un tel déclencheur était bien retrouvé (findTriggerNodes
|
||||
// cherche dans tous les écrans) mais son graphe n'existait jamais dans
|
||||
// l'écran réellement affiché : rien ne se déclenchait, silencieusement.
|
||||
function runFlowFrom(nodeId, flowScreenId) {
|
||||
@@ -1018,7 +1034,7 @@
|
||||
// Déclenche un événement personnalisé (voir screens/custom_events/,
|
||||
// action "declencher_evenement") : une pure NOTIFICATION, sans aucun
|
||||
// paramètre — scan GLOBAL de gameData.flows, même principe que
|
||||
// findTriggerNode()/runScreenShowTriggers() ci-dessus, puisqu'un
|
||||
// findTriggerNodes()/runScreenShowTriggers() ci-dessus, puisqu'un
|
||||
// écouteur (nœud Déclencheur trigger_event="evenement") peut vivre sur
|
||||
// N'IMPORTE QUELLE autre scène ou modèle, pas seulement l'écran affiché.
|
||||
// C'est à CHAQUE écouteur de décider quoi faire ensuite (via sa propre
|
||||
|
||||
Reference in New Issue
Block a user