Visão geral
O bloco Código incorporado pode mostrar uma pasta que carrega: um index.html com os seus recursos, a correr dentro da lição. Por predefinição, esse pacote é uma caixa fechada. Se levar também um pequeno manifesto e falar com a lição através de algumas mensagens, pode:
- avisar a lição de que o formando terminou (para que a lição o espere);
- indicar a sua altura, para que a moldura se ajuste ao conteúdo;
- entregar o seu progresso, para que o formando o encontre onde o deixou;
- enviar uma nota e cada decisão, o que o torna uma simulação que conta na classificação, em SCORM e em xAPI;
- expor variáveis que o conteúdo condicional pode ler.
Esta página destina-se a quem constrói o pacote. Pode ser seguida sem ler qualquer código do Creator. Para o lado do autor (o painel do bloco, a nota e os avisos), consulte Bricks de Conteúdo.
Tudo é opcional. Um pacote sem manifesto funciona na mesma: é mostrado, conta como concluído ao ser visto e nunca trava o formando.
Como o pacote é executado
O pacote corre numa moldura isolada: pode executar scripts, mas não tem acesso à aplicação (nem cookies, nem armazenamento da aplicação, nem origem partilhada). A lição só escuta as mensagens que vêm da moldura desse mesmo bloco, pelo que nada mais na página se pode fazer passar pelo seu pacote. Uma mensagem inválida é ignorada em silêncio.
Um código incorporado que aponta para um URL externo em vez de uma pasta carregada não tem pacote: as suas mensagens são sempre ignoradas e nunca declara nada.
O manifesto: slxd-embed.json
Coloque um ficheiro chamado slxd-embed.json na raiz da pasta, junto a index.html:
{
"protocol": "slxd-embed",
"version": 1,
"capabilities": ["complete", "resize", "state", "result", "interaction"],
"variables": { "trust": "number", "reused": "boolean" }
}
| Campo | Significado |
|---|---|
protocol | Sempre "slxd-embed". |
version | Sempre 1; é a única versão compreendida. |
capabilities | O que o pacote vai enviar. Cada comportamento só funciona se a sua capacidade estiver declarada. O que for desconhecido é ignorado. Até 32 entradas. |
variables | Opcional. As variáveis de state.vars que o pacote envia, com o seu tipo (number ou boolean). Até 64. O conteúdo condicional só pode nomear estas. |
Sem o ficheiro, com JSON inválido, com outra versão ou com mais de 16 KB, o pacote simplesmente não declara nada.
O manifesto é lido quando carrega a pasta no bloco. Carregue slxd-embed.json juntamente com o resto da pasta. Se alterar o manifesto, volte a carregar a pasta: um pacote carregado antes mantém o que declarava então.
| Capacidade | O que permite |
|---|---|
complete | O pacote pode dizer «terminei». Necessária para que o bloqueio do bloco espere pelo pacote. |
resize | O pacote pode definir a altura da sua moldura. |
state | A lição guarda o progresso do pacote e devolve-o quando o formando volta. |
result | O pacote pode enviar uma nota. |
interaction | O pacote pode enviar cada decisão (interações SCORM e xAPI). |
Nomes de variável reservados
grade, score, maxScore, ending e kind leem sempre o último result do pacote (ver abaixo), pelo que não podem ser também variáveis do seu estado. Um pacote cujo variables declare algum deles não é aceite ao carregá-lo: o editor mostra o erro e a pasta não é usada até mudar esses nomes. Dentro de state.vars, uma chave com nome reservado é simplesmente ignorada.
Os nomes de variável começam por uma letra ou _, continuam com letras, algarismos ou _ e têm no máximo 64 carateres. Uma entrada com outro nome ou tipo é ignorada sem rejeitar o resto.
Mensagens
Cada mensagem é um objeto simples enviado com postMessage, com o mesmo envelope:
const send = (type, data = {}) =>
window.parent.postMessage({ channel: "slxd-embed", version: 1, type, ...data }, "*");
A origem de destino é "*" porque a moldura não pode conhecer a origem da lição; nestas mensagens não viaja nada sensível.
Do pacote para a lição
type | Campos | Requer | O que o Creator faz |
|---|---|---|---|
ready | — | — | Envie-o assim que o pacote tiver carregado. Se o pacote declarar state, a lição responde com restore. |
complete | — | complete | Marca o bloco como concluído e levanta o seu bloqueio. Numa simulação, também a encerra (ver abaixo). |
resize | height: número ≥ 0, em píxeis CSS | resize | A moldura assume essa altura, limitada entre 100 e 4000 px e arredondada por excesso. Até à primeira mensagem, vale a altura configurada no bloco. |
state | state: objeto JSON; done: booleano | state | Guarda state tal como veio. done: true indica que é um final: encerra a simulação e conclui o bloco. Envie-o após cada decisão e ao chegar a um final. |
result | score, maxScore, grade, ending, kind | result | Só atualiza a nota. Pode chegar parcial e prevalece o último. Não conclui o bloco nem encerra a simulação. |
interaction | attempt, n, response, description, result, weighting | interaction | Regista uma decisão. Envie-o após cada decisão. |
Uma mensagem que não se ajuste a estas formas é ignorada por inteiro, sem qualquer aviso. Verifique cada campo:
state.state: um objeto JSON simples (não uma lista nem um valor solto) com no máximo 1024 carateres depois de serializado.state.doneé obrigatório. O Creator trata o estado como opaco, exceto um membro opcional,vars: um objeto de números e valores verdadeiro/falso que o conteúdo condicional lê.result.score: qualquer número finito (pode ser negativo).maxScore: número finito ≥ 0.grade: um número de 0 a 100 que o seu pacote calcula; é o único valor que conta para a classificação.ending: um identificador.kind:good,mixedoubad.interaction.attempten(o número da decisão dentro da tentativa): inteiros de 1 a 9999.response: o identificador da opção escolhida.description: texto de no máximo 250 carateres, obrigatório (uma cadeia vazia serve).result:correct,incorrectouneutral.weighting: um número maior que 0 (envie 1 se a decisão valia 0).- Identificadores (
ending,response): minúsculas, algarismos e_, começando por uma letra, até 64 carateres.
Da lição para o pacote
type | Campos | Quando |
|---|---|---|
restore | state: o último estado guardado, ou null | Em resposta a ready, se o pacote declarar state. É null se não havia nada guardado. |
reset | — | Quando o exame abre uma nova tentativa. Recomece do zero: o estado e a nota guardados já foram apagados. |
Um pacote mínimo
const send = (type, data = {}) =>
window.parent.postMessage({ channel: "slxd-embed", version: 1, type, ...data }, "*");
let scene = "s1";
let vars = { trust: 0, reused: false };
window.addEventListener("message", (event) => {
const msg = event.data;
if (!msg || msg.channel !== "slxd-embed") return;
if (msg.type === "restore" && msg.state) {
scene = msg.state.scene;
vars = msg.state.vars;
render();
}
if (msg.type === "reset") {
scene = "s1";
vars = { trust: 0, reused: false };
render();
}
});
function choose(option) {
vars.trust += option.points;
scene = option.next;
send("interaction", {
attempt: 1,
n: 1,
response: option.id,
description: option.label,
result: option.points > 0 ? "correct" : "incorrect",
weighting: Math.abs(option.points) || 1,
});
send("state", { state: { scene, vars }, done: false });
render();
}
send("ready");
send("resize", { height: document.body.scrollHeight });
Terminar: result antes de complete
Uma simulação é encerrada por complete ou por um state com done: true. Um result nunca a encerra. A nota que conta é a do último result recebido antes do encerramento; depois de encerrada, os resultados posteriores são ignorados. Se o pacote encerrar sem ter enviado nenhum result, a simulação vale 0.
A ordem correta num final é, portanto:
send("result", { score: 8, maxScore: 10, grade: 80, ending: "agreement", kind: "good" });
send("state", { state: { scene: "end", vars }, done: true }); // ou: send("complete")
Um state sem done depois de um final é um jogo novo: a nota anterior é esquecida.
Um pacote que vá ser marcado como Avaliável tem, por isso, de declarar complete ou state; de outro modo, a sua nota nunca poderia ser encerrada.
O que o Creator faz com cada coisa
Bloqueio do avanço. O bloco de código incorporado não trava o formando por predefinição. Se o autor ativar o bloqueio (no bloco ou nas definições do tema para o código incorporado), só funciona com um pacote que declare complete: o formando não pode continuar até chegar a mensagem, sem tempo limite nem botão para desbloquear. state e result não o levantam. Um pacote sem complete, e qualquer URL externo, contam como concluídos ao serem vistos. O editor avisa quando o bloqueio está ativado mas o pacote não o pode cumprir.
Altura. A moldura segue o último resize (entre 100 e 4000 px). Até ao primeiro, usa a altura configurada no bloco.
Estado ao voltar. O estado da simulação é guardado sob o seu identificador de simulação, por conteúdo. Quando o pacote carrega e diz ready, recebe restore com o último estado. Numa exportação SCORM, o estado sobrevive entre sessões (viaja nos dados de suspensão do LMS); na pré-visualização, nas ligações partilhadas e na revisão, dura a sessão. Se o estado não couber no espaço do LMS, o Creator corta o indispensável por uma ordem fixa: primeiro as simulações que nem contam nem são lidas pelo conteúdo condicional, depois o estado das restantes, mantendo o mais possível as suas variáveis e notas.
Nota. Para que a simulação conte, o autor dá ao bloco um identificador de simulação (único no conteúdo), marca-o como Avaliável e atribui-lhe um peso; o pacote tem de declarar result, além de complete ou state. Dentro de um exame, a simulação conta junto das perguntas: cada simulação vale o seu peso vezes grade / 100, e o exame só fecha quando todas as simulações que contam estão encerradas. Num conteúdo sem exames, a nota do conteúdo é a média ponderada das suas simulações avaliáveis quando todas terminaram, com o limiar de aprovação do conteúdo (mostrado na página de exportar). As simulações avaliáveis que acompanham exames classificáveis não contam; o editor avisa.
Interações em SCORM. Numa exportação SCORM, cada interaction torna-se uma entrada de cmi.interactions do tipo choice, com o id <identificador de simulação>-<tentativa>-<n>, a opção escolhida, o resultado (correct, wrong/incorrect ou neutral) e a ponderação; o SCORM 2004 guarda também a descrição. Na pré-visualização não há LMS, pelo que nada é registado.
xAPI. Onde o xAPI está ativo, cada interaction é comunicada como «respondeu» sobre uma atividade de decisão (com a descrição, a opção escolhida e success para correct e incorrect; neutral não o leva) e, quando a simulação é encerrada, uma única declaração de «pontuou» transporta a nota que conta, com o final e o tipo como extensões. Um result parcial não emite nada. Começar um jogo novo permite emitir de novo a declaração. O autor pode desativar o xAPI no bloco.
Limites num relance
| O quê | Limite |
|---|---|
slxd-embed.json | 16 KB, só versão 1 |
| Capacidades | até 32 entradas |
| Variáveis | até 64, number ou boolean |
state | objeto JSON, ≤ 1024 carateres |
| Altura da moldura | 100–4000 px |
| Descrição de uma decisão | ≤ 250 carateres |
attempt, n | inteiros 1–9999 |
| Identificadores | [a-z][a-z0-9_]*, ≤ 64 carateres |
| Progresso guardado (SCORM) | orçamento partilhado de 4096 carateres para todo o conteúdo |
Próximos passos
- Conteúdo condicional: mostrar ou ocultar blocos consoante o que o formando fez numa simulação.
- Bricks de Conteúdo: o painel do bloco de código incorporado.
- Monitorização xAPI e Exportar Conteúdo.
- Servidor MCP: como um assistente carrega um pacote e escreve o bloco.