ng-scorm-player
v1.0.0
Published
Lecteur SCORM 1.2 et SCORM 2004 pour Angular : joue un paquet SCORM et remonte progression, score, temps passé et données de reprise.
Maintainers
Readme
ng-scorm-player
Lecteur SCORM pour Angular. Il joue un paquet SCORM 1.2 ou SCORM 2004, expose l'API d'exécution que le contenu attend, et vous rend un résultat exploitable : progression, score, temps passé, données de reprise.
Installation
npm install ng-scorm-playerAngular 20 ou supérieur. La bibliothèque a besoin de HttpClient pour lire imsmanifest.xml.
Démarrage
import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';
import { provideNgScormPlayer } from 'ng-scorm-player';
bootstrapApplication(App, {
providers: [
provideHttpClient(),
provideNgScormPlayer({ learnerName: 'Dupont, Marie', learnerId: '42' }),
],
});import { Component } from '@angular/core';
import { NgScormPlayerComponent, ScormResult } from 'ng-scorm-player';
@Component({
selector: 'app-cours',
imports: [NgScormPlayerComponent],
template: `
<ng-scorm-player
urlDirSco="/assets/paquets/securite-incendie"
(finished)="enregistrer($event)"
(committed)="enregistrer($event)"
/>
`,
})
export class CoursComponent {
enregistrer(resultat: ScormResult) {
// resultat.completed, resultat.scorePercent, resultat.suspendData…
}
}Le composant occupe toute la hauteur de son conteneur : donnez-lui un parent dimensionné.
Entrées
| Entrée | Type | Description |
| --- | --- | --- |
| urlDirSco | string | Dossier du paquet décompressé. Le manifeste y est lu pour trouver la page de lancement. |
| urlLaunchPage | string | Page de lancement directe. Le manifeste n'est alors pas lu. |
| openInNewWindow | boolean | Ouvre le contenu dans une fenêtre séparée au lieu du cadre intégré. |
Donnez urlDirSco ou urlLaunchPage. Si les deux sont fournis, urlLaunchPage l'emporte.
Sorties
| Sortie | Émise quand |
| --- | --- |
| initialized | le contenu appelle Initialize / LMSInitialize |
| valueChanged | à chaque SetValue |
| committed | à chaque Commit — c'est ici qu'il faut enregistrer |
| finished | le contenu appelle Terminate / LMSFinish |
| loadError | la page de lancement n'a pas pu être déterminée |
Écoutez committed autant que finished : beaucoup de contenus enregistrent régulièrement sans jamais terminer proprement, et un apprenant qui ferme son navigateur ne déclenche pas Terminate.
Le résultat
interface ScormResult {
version: '1.2' | '2004';
timeSpent: number; // secondes, session en cours
totalTime: number; // secondes, cumul avec les sessions précédentes
progression: number | null; // 0 à 100, null si le contenu ne le remonte pas
completed: boolean;
passed: boolean | null; // null tant que le contenu ne tranche pas
completedOn: Date | null;
score: number | null;
scoreMin: number | null;
scoreMax: number | null;
scorePercent: number | null;
location: string; // signet de reprise
suspendData: string; // état interne du contenu
exit: string;
runtimeData: Record<string, string>;
}null signifie « le contenu n'a rien remonté », ce qui n'est pas la même chose que zéro. Un module sans quiz laisse score à null ; un quiz raté remonte score: 0.
Reprise de session
Rendez au contenu ce qu'il vous avait confié :
provideNgScormPlayer({
initialData: {
'cmi.suspend_data': resultatPrecedent.suspendData,
'cmi.location': resultatPrecedent.location,
'cmi.total_time': 'PT0H20M0S',
},
});cmi.entry passe automatiquement à resume, ce que le contenu vérifie avant de proposer de reprendre. En SCORM 1.2, utilisez les clés cmi.core.lesson_location et cmi.core.total_time.
Configuration
| Option | Défaut | Description |
| --- | --- | --- |
| debug | false | Trace tous les échanges avec le contenu dans la console. |
| strict | false | Applique les règles d'accès de la spécification (erreur 404 sur écriture en lecture seule). Utile pour valider un paquet, à laisser désactivé en production. |
| learnerId / learnerName | '' | Identité rendue au contenu. |
| initialData | — | Modèle de données d'une session précédente. |
| openInNewWindow | false | Fenêtre séparée plutôt que cadre intégré. |
| iframeTitle | 'Contenu SCORM' | Titre accessible du cadre. |
Le contenu doit être servi depuis la même origine
Un SCO cherche son API en remontant la hiérarchie des cadres : window.parent.API. Si le contenu est servi depuis une autre origine, le navigateur bloque cet accès et SCORM ne fonctionne pas — ce n'est pas une limite de cette bibliothèque, c'est la politique de même origine.
Le sandbox appliqué au cadre est :
allow-scripts allow-forms allow-same-origin allow-modals allow-popups allow-downloadsIl n'est pas configurable, et ce n'est pas un oubli : Angular refuse toute liaison dynamique sur cet attribut (erreur NG0910), parce qu'une valeur calculée pourrait en retirer silencieusement les restrictions. allow-top-navigation, présent en 0.1.x, en est retiré — il permettait à un contenu tiers de rediriger la page entière de votre application.
Un seul lecteur par page
Le contenu cherche window.parent.API, qui est un point d'entrée unique. Deux composants ng-scorm-player sur la même page se disputent ce nom ; le second écrase le premier et un avertissement est émis dans la console. Si vous avez besoin d'afficher deux modules simultanément, isolez-les dans des cadres distincts.
Utilitaires exportés
Les fonctions internes sont exportées, elles servent aussi hors du composant :
import { parseScormDuration, resolveLaunchHref, scormErrorString } from 'ng-scorm-player';
parseScormDuration('00:05:32'); // 332 (SCORM 1.2)
parseScormDuration('PT1H30M5S'); // 5405 (SCORM 2004)
resolveLaunchHref(xmlDuManifeste); // { href, resourceId, resolvedBy }
scormErrorString(403); // 'Data model element value not initialized'Applications organisées en NgModule
Le composant est autonome. Pour du code existant, NgScormPlayerModule.forRoot(config) reste disponible, marqué déprécié.
Migrer depuis la 0.1.x
La 1.0 corrige des écarts à la spécification qui changent le comportement observable. Les points à vérifier :
Les fonctions de l'API renvoient des chaînes. SCORM impose "true" et "false", pas des booléens. Si vous appeliez le service directement, adaptez vos comparaisons.
ScormResult a changé de forme. score et scoreMax, déclarés mais jamais renseignés en 0.1.x, le sont désormais. completed est un vrai booléen. Les nouveaux champs totalTime, passed, location, suspendData, exit et version s'ajoutent. Les champs non renseignés valent null plutôt qu'undefined.
L'entrée scormResult a disparu. Elle ne servait à rien : le résultat sort du composant, il n'y entre pas. Pour la reprise, utilisez initialData.
Le module n'est plus obligatoire. NgScormPlayerModule fonctionne toujours, mais provideNgScormPlayer() est la voie recommandée.
Ce qui est corrigé
| | 0.1.x | 1.0 |
| --- | --- | --- |
| Temps passé en SCORM 1.2 | perdu — le format HH:MM:SS n'était pas reconnu, l'exception était avalée | lu correctement |
| Résultat sur un paquet SCORM 1.2 | vide — seules les clés SCORM 2004 étaient lues | les deux modèles sont lus |
| score et scoreMax | jamais renseignés | renseignés |
| scorePercent | seulement si le contenu remontait score.scaled | calculé aussi depuis raw, min et max |
| Codes d'erreur | inventés (1 à 6) | codes normalisés SCORM |
| GetLastError | renvoyait la première erreur, à jamais | renvoie la dernière, remise à zéro après un appel réussi |
| Valeur de retour | booléens JavaScript | chaînes "true" / "false" |
| Appels hors séquence | acceptés silencieusement | refusés avec le code attendu (103, 112, 122, 132…) |
| Valeurs initiales | modèle de données vide | valeurs par défaut de la spécification |
| _children et _count | absents | fournis et tenus à jour |
| Page de lancement | première ressource du manifeste, souvent la mauvaise | suit l'organisation par défaut et identifierref |
| xml:base du manifeste | ignoré | appliqué |
| Reprise de session | impossible | initialData |
| Cadre ciblé par getElementById | collision entre instances | référence locale au composant |
| API laissée sur window | après destruction du composant | retirée proprement |
| allow-top-navigation | activé | retiré |
Licence
MIT — voir LICENSE.
Développé et maintenu par Geduk, plateforme de formation en ligne française.
