Web Storage を用いた学習システムの雛型
Web StorageとJSONを用いた学習システムの雛型プログラムを作りました。
本記事は、以下の記事の続き記事になります。
- Web Storage の試作プログラム
- Web Storage とJSON の試作プログラム
今回の試作プログラムは前回と比べて、学習画面を俯瞰する「ナビゲータ」機能を追加しました。
また、プログラム全体を見直し、試作プログラムとしての完成度を高めました。
- ナビゲータ機能の追加
- 試作プログラムの完成度向上
雛型プログラムの仕様
仕様
- 学習画面が「初級」と「中級」の2画面ある
- 「初級」修了者のみ「中級」に進める
- 学習記録が残る
- 学習記録は消去できる
- ナビゲータ機能がある
動きの確認
- [Lesson Start]ボタンをクリック
レッスンA ページに移動 - [Practice!]ボタンをクリック
1回カウント:数字が0から1に変化 - [Navigator]ボタンをクリック
各レッスンの状態を確認
・レッスンA:未修了(NG)、練習回数(1):クリック可
・レッスンB:未修了(NG)、練習回数(1):クリック不可 - [Lesson A]ボタンをクリック
レッスンA ページに移動 - [Practice!]ボタンを、4回クリック
5回カウント:数字が5に変化 - [Navigator]ボタンをクリック
各レッスンの状態を確認
・レッスンA: 修了(OK)、練習回数(5):クリック可
・レッスンB:未修了(NG)、練習回数(1):クリック可 - [Lesson B]ボタンをクリック
レッスンB ページに移動 - [Practice!]ボタンを、5回クリック
5回カウント:数字が5に変化 - [Navigator]ボタンをクリック
各レッスンの状態を確認
・レッスンA: 修了(OK)、練習回数(5):クリック可
・レッスンB: 修了(OK)、練習回数(5):クリック可 - [Remove All Lesson Data]ボタンをクリック
Lesson の得点が残っていないことを確認
試作プログラムを作るため、Web Storage とJSON を利用しています。
Web Storage に関しては、記事「Web Storage の試作プログラム」に詳細を記述しました。
Web Storage の詳細は記事「Web Storage の試作プログラム」をご参照ください。
JSON に関しては、記事「Web Storage とJSON の試作プログラム」をご参照ください。
データ構造
JSONを用いて、以下のデータ構造としました。
{ "lessonData789":[ { "lessonNo":0, "workable":true , "pass":false, "count":0 }, { "lessonNo":1, "workable":false, "pass":false, "count":0 } ] }
Web Storageへの保存
上記データ構造は、以下の形をしています。
{ key : value }
key とvalue は、それぞれ以下となります。
key = "lessonData789" value = [ { "lessonNo":0, "workable":true , "pass":false, "count":0 }, { "lessonNo":0, "workable":false, "pass":false, "count":0 } ]
(注)上記value は、配列(Array)です。
Web Storage はデータを、key とvalue のペアとして保存します。
上式で与えられるkey とvalue をペアとして、Web Storage に保存しました。
各レッスンのデータ構造
[ { "lessonNo":0, "workable":true , "pass":false, "count":0 }, { "lessonNo":0, "workable":false, "pass":false, "count":0 } ]
各項目の意味は以下の通りです。
- lessonNo: レッスン番号
- workable: レッスンが学習可能か否か(true / false)
- pass: レッスンを修了したか否か(true / false)
- count: レッスンの練習回数
例1. initialLessonArray
例1. は、レッスンデータの初期値です。 データの意味は以下となります。
- 初級コース:レッスン番号:0、学習可能 、未修了、練習回数:0
- 中級コース:レッスン番号:0、学習不可能、未修了、練習回数:0
(注)中級コースは「初級コース修了」により、学習可能になります。
雛型プログラム
ユーティリティ
Web Storage のアクセス、JSON 関連のプログラムです。
- プログラム名: utilWSneo.js
utilWSneo.js
const KEY = "lessonData789"; // Web Storage Key var lessonArray; // var initialLessonArray = [ {"lessonNo":0, "workable":true , "pass":false, "count":0}, {"lessonNo":1, "workable":false , "pass":false, "count":0} ]; function createWebStorageData() { var webStorageData = JSON.stringify(initialLessonArray); //(stringify) localStorage.setItem(KEY, webStorageData); // setItem lessonArray = initialLessonArray; //(object copy) } function readWebStorageData() { // lessonArray <- Web Storage var webStorageData = localStorage.getItem(KEY); // getItem if (!webStorageData) { createWebStorageData(); } else { lessonArray = JSON.parse(webStorageData); //(parse) } } function writeWebStorageData() { // lessonArray -> Web Storage var webStorageData = JSON.stringify(lessonArray); //(stringify) localStorage.setItem(KEY, webStorageData); // setItem } function removeWebStorageData() { localStorage.removeItem(KEY); // removeItem }
utilWSneo.js の説明
utilWSneo.js は、記事「Web Storage とJSON の試作プログラム」でのutilWS.js とほぼ同じです。
詳細は、記事「Web Storage とJSON の試作プログラム」をご参照ください。
ここでは、各関数の機能などを簡単に説明します。
定数・グローバル変数
- KEY: Web Storage にデータを保存する際のKey。”lessonData789”
- lessonArray: レッスンの進捗状況を保存する配列
- initialLessonArray: レッスン進捗状況の初期値
各関数
- createWebStorageData()
- Web Storage にinitialLessonArray を保存
- lessonArray の初期化
- readWebStorageData()
- Web Storage からlessonArray にレッスンデータ読込
- writeStorageData()
- lessonArray からWeb Storage にレッスンデータ保存
- removeWebStorageData()
- Web Storage からレッスンデータ消去
初級ページ
2頁ある学習ページの初級ページです。
プログラム名: lessonA.html
lessonA.html
<!DOCTYPE html> <html> <head> <meta charset="uft-8"> <title>Webstorage based Learning System</title> <script type="text/javascript" src="utilWSneo.js"></script> <script> const BORDERLINE = 5; // pass: {count >= 5} const LESSON_NO = 0; // Lesson A const FINAL_LESSON = false; // final lesson: true/false function lesson() { /* lesson contents here */ return true; } </script> <script type="text/javascript" src="commonFunc.js"></script> </head> <body> <h2>Lesson A</h2> <input type="button" value="Practice!" onclick="lessonDriver()"> <output> 0</output><br><br><br> <input type="button" value="Navigator" onclick="location.href='navigator.html'"><br> <output></output> </body> </html>
lessonA.html の説明
JavaScriptファイルの読込み
lessonA.html の6 行目、19 行目で、以下のプログラムを読込んでいます。
- utilWSneo.js: Web Storage、JSON 関連の関数
- commonFunc.js:各レッスンページに共通の関数
body部
<body> <h2>Lesson A</h2> <input type="button" value="Practice!" onclick="lessonDriver()"> <output> 0</output><br><br><br> <input type="button" value="Navigator" onclick="location.href='navigator.html'"><br> <output></output> </body>
lessonA.html の各要素は、Fig.1 を参照してください。
<input>要素は2個、タイプはボタンです。
各ボタンは、クリックすると以下のプログラムが動きます。
- [Practice!]ボタン: lessonDriver()
- [Navigator]ボタン: navigator.html
<output>要素は2個あります。
それぞれ、以下の情報をテキスト表示します。
- 各レッスンの練習回数
- Fig.1 での使用例: 「6」
- Web Storage の使用状況
- Fig.1 での使用例: 「Local Storage: use now」
定数
const BORDERLINE = 5; // pass: {count >= 5} const LESSON_NO = 0; // Lesson A const FINAL_LESSON = false; // final lesson: true/false
- BORDERLINE: レッスンA 修了に必要な練習回数
- 例. レッスンA は、練習5回で修了(修得済み)
- LESSON_NO: レッスンの通番
- 例. レッスンA は、レッスン番号が0 番
- FINAL_LESSON: 最終レッスンか否か
- レッスンA は、次(レッスンB)があるので、最終レッスンではない
lesson() 関数
function lesson() { /* lesson contents here */ return true; }
lessonA.html の本体です。
コメントアウトしている部分に、具体的な「レッスンの内容」を記述します。
16 行目、「true」を返すことで、レッスンA が「1 回カウント」されます。
中級ページ
2 頁ある学習ページの中級ページです。
- プログラム名: lessonB.html
lessonB.html
<!DOCTYPE html> <html> <head> <meta charset="uft-8"> <title>Webstorage based Learning System</title> <script type="text/javascript" src="utilWSneo.js"></script> <script> const BORDERLINE = 5; // pass: {count >= 5} const LESSON_NO = 1; // Lesson B const FINAL_LESSON = true; // final lesson: true/false function lesson() { /* lesson contents here */ return true; } </script> <script type="text/javascript" src="commonFunc.js"></script> </head> <body> <h2>Lesson B</h2> <input type="button" value="Practice!" onclick="lessonDriver()"> <output> 0</output><br><br><br> <input type="button" value="Navigator" onclick="location.href='navigator.html'"><br> <output></output> </body> </html>
lessonB.html の説明
lessonB.html は、基本的にlessonA.html と同じプログラムです。
lessonB.html と、lessonA.html の違う部分にラインマークしました。
8 行目から10 行目まで
BORDERLINE: レッスンB のボーダーライン、「5」
LESSON_NO: レッスンB のレッスン番号は、「1」
FINAL_LESSON: レッスンB が最後のレッスンなので、「true」
13 行目から15 行目まで
レッスンB でレッスンする具体的内容を記述します。
今回は雛形なので何も記述していません。
22 行目
ページの表題を、「Lesson A」から「Lesson B」に変更しました。
レッスンページに共通のプログラム
LessonA.html とLessonB.html において、共通するプログラムを集めました。
- プログラム名: commonFunc.js
commonFunc.js
var input_element; // <input> var output_element; // <output> var outputWS_element; // <output> function lessonDriver() { readWebStorageData(); // lessonArray <- Web Storage if (lesson()) lessonArray[LESSON_NO].count++; // lesson() judgeLesson(); writeLessonData(); writeWebStorageData(); // lessonArray -> Web Storage } function judgeLesson() { if ( lessonArray[LESSON_NO].count >= BORDERLINE ) { lessonArray[LESSON_NO].pass = true; if (!FINAL_LESSON) { lessonArray[LESSON_NO+1].workable = true; } } else { lessonArray[LESSON_NO].pass = false; if (!FINAL_LESSON) { lessonArray[LESSON_NO+1].workable = false; } } } function setDisabled() { if ( lessonArray[LESSON_NO].workable ) { input_element.disabled = false; } else { input_element.disabled = true; } } function writeLessonData() { output_element.innerHTML = " " + lessonArray[LESSON_NO].count; } function setLessonData() { input_element = document.getElementsByTagName("input" )[0]; output_element = document.getElementsByTagName("output")[0]; setDisabled(); writeLessonData(); } window.onload = function() { outputWS_element = document.getElementsByTagName("output")[1]; if (!localStorage) { outputWS_element.innerHTML = "Local Storage can't use." return; } readWebStorageData(); // lessonArray <- Web Storage setLessonData(); outputWS_element.innerHTML = "Local Storage: use now" }
commonFunc.js の説明
グローバル変数
- input_element: [Practice!]ボタン
- output_element: [Practice!]ボタン横のテキスト表示エリア
- Fig.2 での使用例、「7」
- outputWS_element: [Navigator]ボタン下のテキスト表示エリア
- Fig.2 での使用例、「Local Storage: use now」
lessonDriver()関数
機能: レッスンが1 回終わったら、カウンター(練習回数)に1 を足す。
function lessonDriver() { readWebStorageData(); // lessonArray <- Web Storage if (lesson()) lessonArray[LESSON_NO].count++; // lesson() judgeLesson(); writeLessonData(); writeWebStorageData(); // lessonArray -> Web Storage }
処理: 以下の処理を順次実行
- Web Storage からレッスンデータをlessonArray に読込
- レッスンが1 回終われば(lesson()関数の返り値が、true)、カウンターに1 を足す
- レッスン状況を判断する(judgeLesson)
- カウンターの値(練習回数)を画面表示
- lessonArray をWeb Storage に保存
judgeLesson() 関数
機能:
- カウンター(練習回数)がBORDERLINE 以上ならば、レッスン修了とする。
- 次のレッスンがあれば、そのレッスンを学習可能にする。
setDisabled() 関数
機能: レッスンが学習可能(workableがtrue)ならば、[Practice!]ボタンをクリック可能にする。
setLessonData() 関数
機能: setDisabled()関数とwriteLessonData()関数を動かす。
window.onload = function() 関数
機能: オンロード後、ページを初期設定する。
- Web Storage が使用可能かチェック
- Web Storage からlessonArray にデータを読込
- setLessonData() 関数を動作
ナビゲータ
レッスンの進捗状況を表示するナビゲータ・ページです。
- プログラム名: navigator.html
navigator.html
<!DOCTYPE html> <html> <head> <meta charset="uft-8"> <title>Webstorage based Learning System</title> <script type="text/javascript" src="utilWSneo.js"></script> <script> const LESSONS = 2; // Number of Lessons var input_element; // <input> var output_element; // <output> var outputWS_element; // Web Storage Information function removeLessonData() { removeWebStorageData(); lessonArray = initialLessonArray; setLessonData(); outputWS_element.innerHTML = "Local Storage: not use"; } function setDisabled(i) { if ( lessonArray[i].workable ) { input_element.disabled = false; } else { input_element.disabled = true; } } function writeLessonData(i) { var str = " "; if ( lessonArray[i].pass ) { str += "OK "; } else { str += "NG "; } output_element.innerHTML = str + lessonArray[i].count; } function setLessonData() { for (var i=0; i<LESSONS; i++) { input_element = document.getElementsByTagName("input" )[i]; output_element = document.getElementsByTagName("output")[i]; setDisabled(i); writeLessonData(i); } } window.onload = function() { outputWS_element = document.getElementsByTagName("output")[LESSONS]; if (!localStorage) { outputWS_element.innerHTML = "Local Storage can't use." return; } readWebStorageData(); // lessonArray <- Web Storage setLessonData(); outputWS_element.innerHTML = "Local Storage: use now"; } </script> </head> <body> <h2>Navigator</h2> <input type="button" value="Lesson A" onclick="location.href='lessonA.html'"> <output> NG 0</output><br> <input type="button" value="Lesson B" onclick="location.href='lessonB.html'"> <output> NG 0</output><br><br> <input type="button" value="Remove All Lesson Data" onclick="removeLessonData()"><br> <output></output> </body> </html>
navigator.html の説明
body部
Fig.3 navigator.html の画面
navigator.html の各要素は、Fig.3 を参照してください。
<input>要素は3 個、タイプはボタンです。
各ボタンは、クリックすると以下のプログラムが動きます。
- [Lesson A]ボタン: lessonA.html
- [Lesson B]ボタン: lessonB.html
- [Remove All Lesson Data]ボタン:removeLessonData()
<output>要素は3 個あります。
それぞれ、以下の情報をテキスト表示します。
- レッスンA の練習状況
- Fig.3 での使用例: 未修了「NG」、練習回数「2」
- レッスンB の練習状況
- Fig.3 での使用例: 未修了「NG」、練習回数「0」
- Web Storage の使用状況
- Fig.3 での使用例: 「Local Storage: use now」
定数
navigator.html の8 行目
- LESSONS: 練習ページの数、今回は「2」
removeLessonData() 関数
機能: Web Storage からレッスンデータを消去する。
処理: 以下の処理を順次実行
- removeWebStorageData() 関数を動作
- lessonArray を初期化
- setLessonData() 関数を動作
setDisabled(i) 関数
機能: 各レッスン(A/B)が学習可能(workableがtrue)ならば、[Lesson A/B]ボタンをクリック可能にする。
引数: i 番目のレッスン
setLessonData() 関数
機能: setDisabled(i)関数とwriteLessonData(i)関数を動かす。
window.onload = function() 関数
機能: オンロード後、ページを初期設定する。
- Web Storage が使用可能かチェック
- Web Storage からlessonArray にデータを読込
- setLessonData() 関数を動作