Chapitre 2.4 — Le cycle de vie d’un SCO
⏱️ TL;DR — Un SCO (Sharable Content Object) n’est pas une page web ordinaire : c’est un contenu qui dialogue avec le LMS pendant qu’il tourne. Son cycle de vie est toujours le même : le LMS le lance dans une iframe ou une fenêtre → le SCO trouve l’API dans la fenêtre parente → il appelle
Initializepour ouvrir la session → pendant la navigation, il lit et écrit des données CMI (statut, score, position,suspend_data) et appelleCommitpour demander l’enregistrement → à la sortie, il appelleTerminate→ le LMS persiste statut et score. Un asset, lui, ne fait rien de tout ça : c’est un fichier passif (PDF, image) qui ne parle pas. Maîtriser ce cycle, c’est savoir où un module casse quand « ça ne remonte pas ».
🎯 Objectifs
- Décrire, dans l’ordre, les étapes de vie d’un SCO : lancement, découverte de l’API,
Initialize, échanges CMI,Commit,Terminate. - Comprendre qui fait quoi : ce qu’initie le LMS, ce qu’initie le SCO.
- Distinguer nettement un SCO (qui dialogue) d’un asset (passif).
- Savoir où placer un point d’arrêt mental quand un module « ne remonte rien ».
- Lire un diagramme de séquence du cycle complet.
Un SCO, ce n’est pas une page web comme une autre
Ouvre une page HTML : elle s’affiche, point. Un SCO fait plus. Le LMS le lance dans une fenêtre ou une iframe dont il est le parent, et il attend que le SCO lui parle — qu’il ouvre une session, remonte un statut, un score, une position, puis referme proprement. Le SCO est donc un contenu actif : il a un cycle de vie rythmé par des appels d’API précis.
Ce cycle est identique dans les deux versions de SCORM ; seuls les noms changent. Pour rester lisible, ce chapitre décrit la logique avec les méthodes SCORM 2004 (Initialize, Commit, Terminate) ; les équivalents 1.2 sont LMSInitialize, LMSCommit, LMSFinish. Retiens la logique, pas seulement les mots.
| Étape | SCORM 2004 | SCORM 1.2 |
|---|---|---|
| Ouvrir la session | Initialize("") | LMSInitialize("") |
| Lire une valeur | GetValue(elt) | LMSGetValue(elt) |
| Écrire une valeur | SetValue(elt, val) | LMSSetValue(elt, val) |
| Demander l’enregistrement | Commit("") | LMSCommit("") |
| Fermer la session | Terminate("") | LMSFinish("") |
Les six temps de la vie d’un SCO
1. Le LMS lance le SCO
Tout commence côté LMS. L’apprenant clique sur l’activité ; le LMS ouvre le SCO dans une iframe ou une fenêtre et se place comme fenêtre parente. À ce stade, le SCO est chargé, mais il n’a encore rien dit.
2. Le SCO trouve l’API (find the API)
Avant de parler, le SCO doit trouver l’objet API que le LMS a exposé. Il le cherche en remontant la hiérarchie des fenêtres : d’abord dans window.parent, puis, si besoin, via window.opener (cas d’une fenêtre pop-up). C’est le rituel du « find the API ».
// Recherche simplifiee de l'API SCORM 2004 dans les fenetres parentes.
function findAPI(win) {
var tries = 0;
while (win.API_1484_11 == null && win.parent != null && win.parent != win) {
tries++;
if (tries > 50) return null; // garde-fou anti-boucle
win = win.parent;
}
return win.API_1484_11 || null; // en 1.2, on chercherait "API"
}
var api = findAPI(window);
if (api == null) {
// Pas d'API : on n'est pas lance par un LMS conforme. On ne remontera rien.
}⚠️ Piège — Si le SCO ne trouve pas l’API, il n’y a aucun dialogue possible : le module s’affiche mais ne remonte rien. Causes classiques : le module a été ouvert hors LMS (double-clic sur le fichier local), une iframe cross-origin bloque l’accès à la fenêtre parente, ou le module cherche le mauvais objet (
APIalors qu’il est lancé en 2004, ou l’inverse — voir chapitre 2.2). Le tout premier réflexe de débogage : l’API a-t-elle été trouvée ?
3. Initialize — ouvrir la session
Une fois l’API en main, le SCO appelle Initialize("") (ou LMSInitialize("") en 1.2). C’est le « bonjour » obligatoire : il ouvre la session de communication. Tant qu’il n’est pas appelé, aucune lecture ni écriture de données n’est valide. C’est l’oubli n°1 des modules qui « ne remontent rien ».
4. La navigation — lire et écrire des données CMI
Pendant que l’apprenant progresse, le SCO lit (GetValue) et écrit (SetValue) des champs du modèle CMI :
- au démarrage, il peut lire l’identité (
cmi.core.student_nameen 1.2) et relire soncmi.suspend_datapour reprendre où l’apprenant s’était arrêté ; - au fil de la progression, il écrit le statut, le score, la position, l’état de reprise.
// Reprise, puis progression (SCORM 2004).
var repriseEtat = api.GetValue("cmi.suspend_data"); // relire l'etat sauvegarde
// ... l'apprenant avance ...
api.SetValue("cmi.completion_status", "incomplete");
api.SetValue("cmi.score.scaled", "0.62");
api.SetValue("cmi.suspend_data", "ecran=7;q3=B"); // memoriser l'etat5. Commit — demander l’enregistrement
SetValue écrit dans le modèle en mémoire, mais ne garantit pas la persistance durable côté serveur. Pour demander au LMS d’enregistrer ce qui a été posé, le SCO appelle Commit("") (ou LMSCommit("")). On l’appelle typiquement régulièrement (à des jalons de progression) et avant de terminer.
⚠️ Piège — Écrire de belles valeurs avec
SetValuesans jamais appelerCommit(niTerminate, qui provoque en général un enregistrement final) : si l’apprenant ferme brutalement l’onglet, tout ce qui n’a pas été commité peut être perdu. Beaucoup de « le score du milieu de parcours a disparu » viennent de là.
6. Terminate — fermer proprement, le LMS persiste
À la sortie (fin du module, fermeture), le SCO appelle Terminate("") (ou LMSFinish("")). C’est le « au revoir » : il ferme la session et déclenche en général la persistance finale. Le LMS enregistre alors durablement le statut et le score dans son carnet de suivi. La boucle est bouclée : ce que le SCO a dit devient une donnée exploitable côté plateforme.
💡 Réflexe — Ordre canonique à ne jamais casser : trouver l’API →
Initialize→ (GetValue/SetValue+Commit) →Terminate. Toute écriture avantInitializeou aprèsTerminateest invalide. Quand « ça ne remonte pas », déroule cette chaîne dans l’ordre : c’est presque toujours un maillon manquant.
Le diagramme de séquence
SCO ou asset : dialoguer ou se taire
SCORM distingue deux types de ressources, et cette distinction structure tout ce chapitre :
- Un SCO (Sharable Content Object) dialogue : il trouve l’API, s’initialise, remonte des données, se termine. Tout le cycle de vie ci-dessus le concerne. Dans le manifeste, sa ressource porte
adlcp:scormType="sco". - Un asset est passif : une image, un PDF, une vidéo qu’on affiche mais qui ne parle pas au LMS. Il n’a pas de cycle de vie SCORM — pas d’API, pas d’
Initialize, pas de statut remonté. Dans le manifeste, sa ressource porteadlcp:scormType="asset".
<resource identifier="RES-1" adlcp:scormtype="sco" href="module/index.html" />
<resource identifier="RES-2" adlcp:scormtype="asset" href="docs/fiche.pdf" />⚠️ Piège — Déclarer en
assetun contenu qui devrait remonter des résultats : le LMS l’affiche mais n’attend aucun statut, donc rien ne se trace, et c’est « normal ». Inversement, marquerscoun simple PDF n’a aucun sens : un asset ne sait pas dialoguer. Le typagescormTypedoit refléter la nature réelle de la ressource. C’est un contrôle à faire dès la lecture d’un manifeste.
🔌 Côté intégration — Côté LMS, un SCO est ce qui alimente le carnet de suivi ; un asset est un simple fichier servi. Quand un client dit « le suivi ne marche pas sur telle ressource », vérifie d’abord son type dans le manifeste : un contenu attendu comme traçable mais typé
assetne remontera jamais rien, quel que soit son code. Le problème n’est pas le runtime, c’est le CAM.
🧭 Sur FormaCampus — Chaque module de cours FormaCampus est un SCO unique : il trouve l’API
API(SCORM 1.2), appelleLMSInitialize, écritcmi.core.lesson_statusetcmi.core.score.raw, commit à chaque jalon important, puisLMSFinishà la sortie. Les annexes (fiches PDF, modèles à télécharger) sont livrées comme assets dans le même paquet : l’école y accède, mais FormaCampus n’attend aucun suivi dessus — et c’est voulu. Résultat lisible côté client : un statut et un score par module dans le carnet Moodle, des annexes accessibles sans « faux » indicateurs de complétion.
✏️ Exercices
Exercice 1 — « Le module s’affiche mais rien ne remonte ». Un module SCORM 1.2 s’ouvre bien dans le LMS, l’apprenant le parcourt, mais le carnet reste vide. Donne trois causes possibles, dans l’ordre où tu les vérifierais.
✅ Solution
Dans l’ordre du cycle de vie :
- L’API n’est pas trouvée (« find the API » échoue) — le module cherche
APIdans les mauvaises fenêtres, une iframe cross-origin bloque l’accès, ou il a été ouvert hors LMS. Sans API, aucun dialogue. LMSInitializen’est jamais appelé — sans l’ouverture de session, toute écriture est invalide.- Aucun
LMSCommit/LMSFinish— les valeurs sont posées en mémoire mais jamais persistées ; à la fermeture, elles sont perdues.
(Bonus : une valeur invalide dans cmi.core.lesson_status, comme "réussi" au lieu de passed, peut aussi faire échouer l’écriture.)
Exercice 2 — SCO ou asset ? Pour chacun, dis si tu le déclarerais sco ou asset : (a) un module interactif avec quiz noté ; (b) une fiche PDF de synthèse téléchargeable ; (c) une vidéo qui doit remonter « vue à 90 % » comme complétion.
✅ Solution
- (a) →
sco. Il dialogue (score, statut), il a un cycle de vie complet. - (b) →
asset. Fichier passif, aucun suivi attendu. Le déclarerscon’aurait aucun sens. - (c) →
sco. Dès qu’on veut tracer quelque chose (« vue à 90 % » = complétion remontée), il faut un contenu qui dialogue : donc un SCO (typiquement un lecteur vidéo enveloppé de code qui appelle l’API et écrit le statut). Une vidéo livrée en simpleassetne remontera jamais de complétion.
Exercice 3 — Remettre le cycle dans l’ordre. On te donne ces appels en désordre : Commit, Terminate, SetValue, Initialize, « trouver l’API ». Remets-les dans l’ordre canonique et dis lesquels peuvent se répéter.
✅ Solution
Ordre canonique :
- trouver l’API (une fois, au démarrage) ;
Initialize(une fois, ouvre la session) ;SetValue(répétable, autant de fois que nécessaire pendant la navigation ; souvent précédé/entrelacé deGetValue) ;Commit(répétable, à des jalons de progression et avant de terminer) ;Terminate(une fois, ferme la session et déclenche la persistance finale).
Répétables : SetValue, GetValue, Commit. Uniques : trouver l’API, Initialize, Terminate. Toute écriture avant Initialize ou après Terminate est invalide.
🧠 Quiz de révision
1. Qui lance le SCO, et où ?
Le LMS lance le SCO dans une iframe ou une fenêtre dont il est la fenêtre parente. Le SCO devra ensuite y retrouver l’API exposée par le LMS pour pouvoir dialoguer.
2. Que signifie « find the API » et pourquoi est-ce critique ?
C’est la recherche de l’objet API par le SCO, en remontant les fenêtres parentes (window.parent, puis window.opener). C’est critique parce que sans API trouvée, aucun dialogue n’est possible : le module s’affiche mais ne remonte rien. C’est le premier point à vérifier en débogage.
3. À quoi servent Initialize, Commit et Terminate ?
Initialize ouvre la session (obligatoire avant toute écriture). Commit demande au LMS d’enregistrer durablement ce qui a été posé par SetValue. Terminate ferme la session à la sortie et déclenche en général la persistance finale du statut et du score. (En 1.2 : LMSInitialize, LMSCommit, LMSFinish.)
4. Quelle est la différence entre un SCO et un asset ?
Un SCO dialogue avec le LMS (trouve l’API, Initialize, remonte statut/score, Terminate) : il a un cycle de vie. Un asset est passif (PDF, image, vidéo simple) : il s’affiche mais ne parle pas au LMS, donc ne trace rien. Le manifeste les distingue via adlcp:scormType (sco ou asset).
5. Pourquoi un score écrit avec SetValue peut-il ne jamais arriver dans le carnet ?
Parce que SetValue écrit en mémoire, pas durablement. Sans Commit (et sans Terminate, qui déclenche la persistance finale), une fermeture brutale de l’onglet perd les valeurs non enregistrées. Il faut Commit aux jalons et terminer proprement pour que le LMS persiste les données.
Chapitre suivant : Forces & limites de SCORM — pourquoi il domine encore, ce qu’il ne sait pas faire, et pourquoi xAPI et cmi5 ont dû naître.