// Export Web/SCORM — port de screens/rendering/render_repeater.py. Lit // gameData.data/fields_meta (au lieu d'une requête SQL) et // gameData.element_type_templates (voir full_game_payload.py — l'arbre // d'un écran-modèle d'élément de jeu réutilisable, précalculé une fois à // l'export) au lieu de screens/element_types/load_template_tree.py. function forgeRenderRepeater(el, meta, gameData, childrenMap, ctx, parentFlexDirection) { var style = forgeStyleString(el, parentFlexDirection, el.widget) + " overflow:auto;"; var attrsRaw = el.attributes || {}; var definitionId = attrsRaw._definition_id; var definitionAttr = definitionId ? ' data-definition-id="' + forgeHtmlEscape(String(definitionId)) + '"' : ""; var templateTypeId = attrsRaw._template_type_id; var template = forgeApplyCtx(el.content || "", ctx); var children = (childrenMap && childrenMap[el.id]) || []; if (!definitionId) { return '
Répéteur : choisis un objet de données dans les propriétés.
'; } definitionId = String(definitionId); var fieldsMetaForDef = gameData.fields_meta && gameData.fields_meta[definitionId]; if (!fieldsMetaForDef) { return '
Objet introuvable — a-t-il été supprimé ?
'; } var rows = gameData.data[definitionId] || []; rows = forgeFilterRepeaterRows(gameData, definitionId, rows, attrsRaw); var templateTree = null; if (templateTypeId) { templateTree = gameData.element_type_templates && gameData.element_type_templates[String(templateTypeId)]; } var items = rows.map(function (row) { var rowCtx = Object.assign({}, ctx || {}); // gameData.data est déjà indexé par le nom D'AFFICHAGE du champ (voir // full_game_payload.py), jamais par sa colonne SQL — row[f.name] lit // donc directement la bonne valeur, y compris pour un champ "relation" // (voir filter-repeater-rows.js pour le détail de ce piège). fieldsMetaForDef.forEach(function (f) { var v = row[f.name]; rowCtx[f.name] = v === null || v === undefined ? "" : String(v); }); var inner; if (templateTree) { inner = templateTree.top.map(function (c) { return forgeRenderElementHtml(c, gameData, templateTree.children_map, rowCtx); }).join(""); } else if (children.length) { inner = children.map(function (c) { return forgeRenderElementHtml(c, gameData, childrenMap, rowCtx); }).join(""); } else { var line = template; Object.keys(rowCtx).forEach(function (fname) { if (fname === "_forge_play_mode") return; line = line.split("{{" + fname + "}}").join(rowCtx[fname]); }); inner = forgeHtmlEscape(line); } return '
' + inner + '
'; }); var emptyMsg = attrsRaw._filtre_champ ? "Aucune ligne ne correspond au filtre réglé." : "Aucune donnée dans cet objet pour l'instant."; var innerAll = items.length ? items.join("") : "" + emptyMsg + ""; return '
' + innerAll + '
'; } if (typeof module !== 'undefined' && module.exports) { module.exports = { forgeRenderRepeater }; var renderMod = require('./render-element.js'); ["forgeStyleString", "forgeHtmlEscape", "forgeAutoId", "forgeApplyCtx", "forgeRenderElementHtml"].forEach(function (name) { global[name] = global[name] || renderMod[name]; }); var filterMod = require('./filter-repeater-rows.js'); global.forgeFilterRepeaterRows = global.forgeFilterRepeaterRows || filterMod.forgeFilterRepeaterRows; }