憂しと見し世ぞ今は恋しき

HTMLでオンラインテストを作ってみた話①

きっかけ

おそらく、塾の先生とか家庭教師とかしてる人なら、誰もが作っているでしょう小テスト。
自分も毎度毎度セコセコつくっております。

最初は塾販教材の切り貼りから始まって、手打ちで作ったりEXCELでシート化したり。
テストの中身は結構どうでもよくって、テストをすることで生徒の学習のサイクルを作っていく必要があるわけです。

1枚2枚ならいいんですが、毎度毎度印刷して○つけして、再テストでまた印刷して練習用にさらに印刷して・・・とやっていると思うわけです。
「タブレットとか携帯でやらせられたら楽だよな・・・」ということ。
ということで、チャレンジすることにしました。

プログラミングなど学んだことはありませんが、ご幼少のみぎりにはマイコンBasicマガジン読みながらSC3000HにBasicのプログラム打ち込んだ経験はありますし、ホームページを作るくらいのHTMLとCSSの知識、ツクールMVで遊ぶくらいのJavascriptの知識を持ち合わせてはいるので、何とかなるだろうと。

ちなみに、現時点でできているシステムのほとんどがググって出てきたコードのコピペです。
コピペだけでできるんですから世の中便利なもんですが、適当に作ってるのできっとプロの人から見たら無駄な部分が多いでしょう。
これからコードを公開していくので、通りがかったプロの人はぜひ「こうしたらいいよ」とか指摘してってください。

なんでコードを公開するかというと、屋上屋を重ねながら作ってたらわけわかんなくなったので、いったん整理するために0から書き直してみようと思ったんですね。
その副産物です。

こんなん書いてる暇あったら問題作ったほうがいいんでしょうけどね。

オンラインテストのシステムについて

とりあえず考えたのが、

  1. 問題表示ウィンドウをつくる
  2. 解答入力フォームをつくる
  3. 問題文を表示する
  4. 解答入力フォームの内容と、正解データの一致を判断する
  5. 正解、不正解の表示をする

という流れです。
そこまで作ることを考えたときに必要なのは、表示用のHTMLとCSS、出題処理をするJavaScriptということになります。

あとは問題文のデータですが、今後問題データを増やしていくときに編集しやすいように、外部ファイル化することを考えました。
よって最初につくるファイルは4つです。

後々に携帯アプリ化とか考えたときに、自分のサーバにデータだけ置いておければ更新しやすいだろうなあとか、それがどんなに面倒なことか深く考えもせずに適当に見切り発車です。

HTMLとCSSを書いてみる

ということで、まずは出題画面を作ってみます。
黒板の上に問題文が出る感じにしようかな、ということで黒板風の枠のCSSを探したら、すぐに発見。
https://love-wave.com/css-waku/
この枠をメインウインドウにして、その下に入力フォームを置いてみます。

入力フォームもなんか装飾して・・・ってことで、探してきました。https://kodocode.net/design-css-textbox/

で、ひとまず形ができました。

See the Pen オンラインクイズひな形 by Haru-You (@HaruYou) on CodePen.

いろいろググってる間に見つけた、codepenというサービスですが、とても面白いです。
入力内容がライブプレビューできるのでcssを試したいときなんかに使っています。

問題出力用のjavascriptを作ってみる

続いては、ここに問題を流し込むスクリプトです。
で、ここで気がついたのが「出題ボタン」を押して先に進むことと、「解答ボタン」を押して答え合わせに進むことです。
その辺の処理も合わせてコントロールできるスクリプトと、別で問題データを作ることにします。

で、問題をcsvにしようかと思ったんですが、算数なんかだと乱数で問題文の数字を書き換えたいですし、計算部分はjsで、社会なんかのテキストはそこから読み込むcsvで作れればいいかなと。

まずはquestioncontrol.jsというファイルを作り、HTMLにjavascriptの読み込みをするよう追記します。

このファイルでhtml上の出題ボタンをトリガーにして、問題文を表示すると同時に解答ボタンを表示。
解答ボタンを押したら正誤判定に行く、というイメージです。
ということで、ボタンのCSSを探しに。

DIV要素を出したり消したり

ここで気がついたのが、HTML上に設定したボタンを出したり消したりするにはどうしたらいいか、ということ。

ググってみたところ、

style="display:none"  //要素全体の除去(そのスペースを詰める)
style="display:block"  //noneにした要素の表示

style="visibility:hidden" //要素の非表示(そのスペースは空く)
style="visibility:visible"  //hiddenにした要素の表示  

みたいな感じでOKらしいです。

でもって、javascriptで

document.getElementById("input1").style.display="none";


なんてしてやることで任意のタイミングで切り替えられるということですね。

ボタンってどうやって操作する?

で、次の問題がHTMLに設置したボタンをどうやって操作するかです。
押したらjavascriptが反応して処理する仕組みですね。
こいつもググってみます。

ボタン属性を与えてあれば

onclick="関数名()"

ってやればの記述で、ボタン属性でなくCSSで装飾したclassは

a href="javascript:関数名()"

とすれば動くらしいです。
今回設置したボタンはcssでclassにしてあるものなので、aタグで動かすことにしました。
出題ボタンに、関数next()を割り当てます。

関数の名前を適当につけると後で死ぬことに、製作3日目くらいで気づきました。

まずは関数next()内で問題タイトル、問題文、解答の3つのデータを設定します。
せっかくなので問題文は乱数を発生させて数字を振ります。
で、

document.getElementById("pタグのid").innerHTML=[データを代入した変数]

ってして、次に解答ボタンに設定した関数answerset()で、入力データを拾っていきます。

var inputans=document.getElementById('input1').value


で変数inputansに入力値を拾わせ、前の関数で設定したanswerと比較すると。

ブルーノ・J・グローバル関数?


・・・と思ったら、うまく動かない。
ブラウザのコンソールを眺めてみると、どうやら変数answerがundefined。
なんでやねん、と思いながらググります。

どうやら、変数設定時に「var」をつけると関数内で働くローカル変数に、つけないとscript内で働くグローバル変数になるそうで。
同一ファイル内で動くのがローカルで、ファイル外まで動くのがグローバルだと思ってました。

他にも変数の宣言にはいろいろあるみたいでしたが、ひとまずvarの有る無しだけでよさそうなので、varを外したらうまく動きました。
あとは入力した解答が次の問題で残らないように、出題時に初期化することでひとまず完成。

See the Pen zQLEQx by Haru-You (@HaruYou) on CodePen.

やってみるとわかりますが、全角数字では正解判定されません。
全角半角変換する仕組みを探そうかと思いますが、それは後回し。

これでベースはできましたんで、次は問題を別ファイルにして、出題単元を替えたりできるシステムにしていきます。

https://haruyou-blog.com/2019/05/29/post-5144/