SCORM Runtime APIとは、eラーニング教材(SCO)とLMS(学習管理システム)がブラウザ上でデータをやり取りするためのJavaScript APIです。本記事では、SCORM 1.2およびSCORM 2004の全メソッドを、実際のコード例とともに体系的に解説します。
1. SCORM Runtime APIの全体像
SCORM Runtime APIは、教材側のJavaScriptからLMSが提供するAPIオブジェクトのメソッドを呼び出すことで動作します。SCORM 1.2と2004ではAPIオブジェクト名とメソッド名が異なりますが、基本的な役割は同じです。
| 役割 | SCORM 1.2 | SCORM 2004 |
|---|---|---|
| APIオブジェクト名 | API | API_1484_11 |
| 通信開始 | LMSInitialize("") | Initialize("") |
| 値の取得 | LMSGetValue(element) | GetValue(element) |
| 値の設定 | LMSSetValue(element, value) | SetValue(element, value) |
| データ保存 | LMSCommit("") | Commit("") |
| 通信終了 | LMSFinish("") | Terminate("") |
| 最終エラー取得 | LMSGetLastError() | GetLastError() |
| エラー文字列取得 | LMSGetErrorString(code) | GetErrorString(code) |
| 診断情報取得 | LMSGetDiagnostic(code) | GetDiagnostic(code) |
すべてのメソッドは文字列を引数に取り、文字列を返すという点が共通しています。成功時は "true"、失敗時は "false" を返します(LMSGetValue / GetValue は値の文字列を返します)。
2. APIオブジェクトの探索(findAPI)
SCORM教材がLMS上で起動されると、LMSはブラウザのウィンドウ階層にAPIオブジェクトを配置します。教材はまずこのオブジェクトを探す必要があります。
SCORM 1.2用のfindAPI
function findAPI(win) {
var attempts = 0;
while (win.API == null && win.parent != null && win.parent != win) {
attempts++;
if (attempts > 10) return null;
win = win.parent;
}
return win.API || null;
}
function getAPI() {
var api = findAPI(window);
if (api == null && window.opener != null) {
api = findAPI(window.opener);
}
return api;
}
SCORM 2004用のfindAPI
function findAPI(win) {
var attempts = 0;
while (win.API_1484_11 == null && win.parent != null && win.parent != win) {
attempts++;
if (attempts > 10) return null;
win = win.parent;
}
return win.API_1484_11 || null;
}
function getAPI() {
var api = findAPI(window);
if (api == null && window.opener != null) {
api = findAPI(window.opener);
}
return api;
}
ポイントとして、LMSによってはAPIオブジェクトをwindow.parentではなくwindow.openerに配置する場合があります。両方を探索するようにしましょう。
3. Initialize / LMSInitialize——通信の開始
教材がロードされたら、最初に呼び出すメソッドです。これを呼ばないと、他のすべてのAPI呼び出しが失敗します。
// SCORM 1.2
var api = getAPI();
var result = api.LMSInitialize("");
if (result === "false") {
var errorCode = api.LMSGetLastError();
console.error("初期化失敗: " + api.LMSGetErrorString(errorCode));
}
// SCORM 2004
var api = getAPI();
var result = api.Initialize("");
if (result === "false") {
var errorCode = api.GetLastError();
console.error("初期化失敗: " + api.GetErrorString(errorCode));
}
注意: 引数は必ず空文字列
""を渡します。これはSCORM仕様で定められており、他の値を渡すとエラーになるLMSがあります。
4. GetValue / LMSGetValue——データの取得
LMSに保存されている学習データを取得します。取得できるデータ項目(データモデル要素)はSCORMのバージョンによって異なります。
// SCORM 1.2 — 学習ステータスを取得
var status = api.LMSGetValue("cmi.core.lesson_status");
// SCORM 1.2 — 学習者名を取得
var learnerName = api.LMSGetValue("cmi.core.student_name");
// SCORM 1.2 — スコアを取得
var score = api.LMSGetValue("cmi.core.score.raw");
// SCORM 2004 — 完了ステータスを取得
var completionStatus = api.GetValue("cmi.completion_status");
// SCORM 2004 — 成功ステータスを取得
var successStatus = api.GetValue("cmi.success_status");
// SCORM 2004 — 学習者名を取得
var learnerName = api.GetValue("cmi.learner_name");
よく使うデータモデル要素の対応表
| 用途 | SCORM 1.2 | SCORM 2004 |
|---|---|---|
| 学習ステータス | cmi.core.lesson_status | cmi.completion_status / cmi.success_status |
| スコア(素点) | cmi.core.score.raw | cmi.score.raw |
| スコア(最大値) | cmi.core.score.max | cmi.score.max |
| スコア(最小値) | cmi.core.score.min | cmi.score.min |
| 学習者名 | cmi.core.student_name | cmi.learner_name |
| 学習者ID | cmi.core.student_id | cmi.learner_id |
| 中断位置 | cmi.core.lesson_location | cmi.location |
| 自由データ領域 | cmi.suspend_data | cmi.suspend_data |
| 合計学習時間 | cmi.core.total_time | cmi.total_time |
| セッション時間 | cmi.core.session_time | cmi.session_time |
5. SetValue / LMSSetValue——データの設定
学習データをLMSに書き込みます。教材の進捗やスコアを記録するために使用します。
// SCORM 1.2 — ステータスを「完了」にする
api.LMSSetValue("cmi.core.lesson_status", "completed");
// SCORM 1.2 — スコアを設定する
api.LMSSetValue("cmi.core.score.raw", "85");
api.LMSSetValue("cmi.core.score.max", "100");
api.LMSSetValue("cmi.core.score.min", "0");
// SCORM 1.2 — 中断位置を保存(レジューム用)
api.LMSSetValue("cmi.core.lesson_location", "page-5");
api.LMSSetValue("cmi.suspend_data", JSON.stringify({ currentPage: 5, answers: [1,3,2] }));
// SCORM 2004 — 完了と合格を設定
api.SetValue("cmi.completion_status", "completed");
api.SetValue("cmi.success_status", "passed");
// SCORM 2004 — スコアを設定(0〜1のスケール値が必須)
api.SetValue("cmi.score.raw", "85");
api.SetValue("cmi.score.max", "100");
api.SetValue("cmi.score.min", "0");
api.SetValue("cmi.score.scaled", "0.85");
SCORM 2004の注意点:
cmi.score.scaled(-1.0〜1.0の小数)は必須項目です。cmi.score.rawだけ設定してもLMSによっては正しく記録されません。
6. Commit / LMSCommit——データの保存確定
SetValueで設定したデータをLMSに確実に保存させます。Commitを呼ばない場合、データがLMSに反映されないことがあります。
// SCORM 1.2
api.LMSSetValue("cmi.core.lesson_status", "completed");
api.LMSSetValue("cmi.core.score.raw", "90");
var result = api.LMSCommit("");
if (result === "false") {
console.error("Commit失敗: " + api.LMSGetErrorString(api.LMSGetLastError()));
}
// SCORM 2004
api.SetValue("cmi.completion_status", "completed");
api.SetValue("cmi.score.scaled", "0.9");
var result = api.Commit("");
if (result === "false") {
console.error("Commit失敗: " + api.GetErrorString(api.GetLastError()));
}
SetValueのたびにCommitを呼ぶ必要はありません。一連の値を設定し終わった後にまとめて1回呼ぶのが一般的です。ただし、ページ遷移のタイミングなど、データを失いたくないポイントではこまめにCommitすることを推奨します。
7. Finish / Terminate / LMSFinish——通信の終了
教材を閉じる前に呼び出します。これによりLMSはセッションを終了し、最終的なデータの保存処理を行います。
// SCORM 1.2
api.LMSSetValue("cmi.core.session_time", "0000:15:30.00");
api.LMSCommit("");
api.LMSFinish("");
// SCORM 2004
api.SetValue("cmi.session_time", "PT15M30S"); // ISO 8601形式
api.Commit("");
api.Terminate("");
セッション時間のフォーマットの違い: SCORM 1.2では
HHHH:MM:SS.SS形式、SCORM 2004ではISO 8601の期間表記(PT1H30M45Sなど)を使用します。
8. エラーハンドリングとエラーコード一覧
APIメソッドが "false" を返した場合、GetLastError でエラーコードを取得して原因を特定します。
SCORM 1.2 主要エラーコード
| コード | 意味 |
|---|---|
| 0 | エラーなし |
| 101 | 一般的な例外 |
| 201 | 引数エラー(無効な引数) |
| 202 | 要素は取得できない(書き込み専用) |
| 203 | 要素は設定できない(読み取り専用) |
| 301 | 初期化されていない |
| 401 | 未実装のデータモデル要素 |
| 402 | 無効なSetValue引数(データ型不正) |
| 403 | データモデル要素が読み取り専用 |
SCORM 2004 主要エラーコード
| コード | 意味 |
|---|---|
| 0 | エラーなし |
| 101 | 一般的な例外 |
| 102 | 初期化済み(二重Initialize) |
| 103 | 初期化されていない |
| 104 | 終了済み(Terminate後の呼び出し) |
| 111 | Terminate前にTerminateが呼ばれた |
| 201 | 一般的な引数エラー |
| 301 | 一般的な取得エラー |
| 351 | 一般的なセットエラー |
| 391 | 一般的なCommitエラー |
| 401 | 未定義のデータモデル要素 |
| 403 | データモデル要素が読み取り専用 |
| 406 | データモデル要素のデータ型不正 |
エラーハンドリングのユーティリティ関数例
function scormSetValue(element, value) {
var result = api.LMSSetValue(element, value);
if (result === "false") {
var code = api.LMSGetLastError();
var msg = api.LMSGetErrorString(code);
var diag = api.LMSGetDiagnostic(code);
console.error("SetValue失敗 [" + element + "=" + value + "] code:" + code + " " + msg + " / " + diag);
}
return result;
}
9. 実装パターン——教材のライフサイクル全体
ここまでの内容を踏まえ、教材が起動してから終了するまでの一連の処理をまとめた実装例を示します(SCORM 1.2版)。
var api = null;
// 教材起動時
function initSCORM() {
api = getAPI();
if (api == null) {
console.error("SCORM APIが見つかりません");
return false;
}
var result = api.LMSInitialize("");
if (result === "false") return false;
// 前回の中断位置を復元
var location = api.LMSGetValue("cmi.core.lesson_location");
if (location !== "") {
goToPage(location);
}
return true;
}
// ページ遷移時
function savePage(pageId) {
api.LMSSetValue("cmi.core.lesson_location", pageId);
api.LMSCommit("");
}
// テスト完了時
function reportScore(score, maxScore, passed) {
api.LMSSetValue("cmi.core.score.raw", String(score));
api.LMSSetValue("cmi.core.score.max", String(maxScore));
api.LMSSetValue("cmi.core.lesson_status", passed ? "passed" : "failed");
api.LMSCommit("");
}
// 教材終了時
function finishSCORM() {
if (api == null) return;
api.LMSSetValue("cmi.core.session_time", calculateSessionTime());
api.LMSCommit("");
api.LMSFinish("");
}
// ウィンドウを閉じる際に確実にFinishを呼ぶ
window.addEventListener("beforeunload", function() {
finishSCORM();
});
10. よくある質問(FAQ)
Q1. InitializeとFinish(Terminate)は必ず呼ぶ必要がありますか?
はい。Initializeを呼ばないと他のAPI呼び出しがすべて失敗します。Finish/Terminateを呼ばないとLMS側でセッションが正常終了せず、学習データが保存されない場合があります。
Q2. Commitはどのタイミングで呼ぶべきですか?
SetValueで値を設定した後、データを失いたくないタイミングで呼びます。ページ遷移時やテスト完了時など、区切りのよいタイミングが一般的です。SetValueのたびに呼ぶ必要はありませんが、Finish前には必ず呼んでおきましょう。
Q3. SCORM 1.2と2004の両方に対応するにはどうすればよいですか?
APIオブジェクトの探索時に API(1.2)と API_1484_11(2004)の両方を探し、見つかった方に応じてメソッド名を切り替えるラッパー関数を作るのが一般的です。多くのSCORMラッパーライブラリがこの方式を採用しています。
Q4. suspend_dataの容量制限はありますか?
SCORM 1.2では最低4,096バイト、SCORM 2004(第4版)では最低64,000文字が保証されています。大量のデータを保存する場合は、JSON.stringifyで圧縮するなどの工夫が必要です。
Q5. beforeunloadイベントでFinish/Terminateを呼んでも大丈夫ですか?
ブラウザによっては beforeunload 内の非同期処理が完了しない場合があります。可能であれば教材内に「終了」ボタンを設け、そこでFinish/Terminateを呼ぶ設計を推奨します。beforeunload はあくまでフォールバックとして使いましょう。
11. まとめ
- SCORM Runtime APIは、教材とLMSがブラウザ上でデータ通信するための8つのJavaScriptメソッドで構成される
- Initialize → GetValue/SetValue → Commit → Finish/Terminate の順序を守ることがすべての基本
- SCORM 1.2と2004ではAPIオブジェクト名・メソッド名・データモデルが異なるため、対応表を参照しながら実装する
- エラーコードを活用したハンドリングを実装することで、問題の早期発見と対処が可能になる
- 実装に不安がある場合は、実績あるSCORMラッパーライブラリの利用や専門家への相談が確実
SCORM APIの実装でお困りではありませんか?株式会社エレファンキューブはeラーニング専門18年・3,000件超のSCORM開発実績で、API実装のサポートからSCORM教材の制作・変換まで幅広く対応いたします。技術的なご相談もお気軽にお問い合わせください。
株式会社エレファンキューブ
eラーニング教材制作の専門会社。2008年の創業以来、3,000件超の制作実績を持ち、SCORM 1.2 / SCORM 2004 / xAPI / cmi5など各種規格に精通。企画からLMS搭載まで、ワンストップで対応しています。
コーポレートサイト