【ミニアプリ作成】ラジオボタンを使用したクイズ【HTML,CSS,JavaScript】


HTML、CSS、JavaScriptの学習を終えて何か作ってみようと思い、ミニアプリ３問クイズを作ってみました。

備忘録を兼ねて記載。

## ラジオボタンを使用したクイズ

作ったミニアプリは3問の４択クイズ。
最後に解答ボタンをクリックすると点数が表示される。

HTML、CSS、JavaScriptのみで作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690542/a252c1a0-c43c-e362-d31e-4d605413698b.png)

## コード

まずはhtmlから。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>quiz</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://unpkg.com/ress/dist/ress.min.css">
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h2>問題１</h2>
    <p>2024年のオリンピック開催都市は？</p>
   <form name="quiz1">
        <ul>
            <li><input type="radio" name="q1" value="ロサンゼルス" id="los">
                <label for="los">ロサンゼルス</label></li>
            <li><input type="radio" name="q1" value="パリ" id="paris">
                <label for="paris">パリ</label></li>
            <li><input type="radio" name="q1" value="ベルリン" id="ber">
                <label for="ber">ベルリン</label></li>
            <li><input type="radio" name="q1" value="ニューデリー" id="newdel">
                <label for="newdel">ニューデリー</label></li>
        </ul>
    </form>
    <h2>問題２</h2>
    <p>世界で4番目に人口が多い国は？</p>
    <form name="quiz2">
        <ul>
            <li><input type="radio" name="q2" value="中国" id="china">
                <label for="china">中国</label></li>
            <li><input type="radio" name="q2" value="イギリス" id="uk">
                <label for="uk">イギリス</label></li>
            <li><input type="radio" name="q2" value="アメリカ" id="us">
                <label for="us">アメリカ</label></li>
            <li><input type="radio" name="q2" value="インドネシア" id="indonesia">
                <label for="indonesia">インドネシア</label></li>
        </ul>
    </form>
    <h2>問題３</h2>
    <p>日本よりGDPが高い国は？</p>
    <form name="quiz3">
        <ul>
            <li><input type="radio" name="q3" value="インド" id="ind">
                <label for="ind">インド</label></li>
            <li><input type="radio" name="q3" value="イタリア" id="italy">
                <label for="italy">イタリア</label></li>
            <li><input type="radio" name="q3" value="カナダ" id="canada">
                <label for="canada">カナダ</label></li>
            <li><input type="radio" name="q3" value="ドイツ" id="germ">
                <label for="germ">ドイツ</label></li>
        </ul>
    </form>
    <div>
        <button id="btn">解答</button>
        <p id="answer"></p>
    </div>
    <script src="script.js"></script>
</body>

</html>

```

各問題はformタグで囲んだが、今回の場合サーバーとのやり取りはないため、なくても問題なかった。


```css

@charset "UTF-8";

html {
    font-size: 100%;
}

body {
    color: #383E45;
    font-size: 0.9rem;
    text-align: center;
}

.list {
    
    margin:auto;
}

ul {
    max-width: 500px;
    display: flex;
    margin: 20px auto;
}

li {
    list-style: none;
    margin:auto;
}

h2 {
    margin: 30px 0 10px 0;
}

#btn {
    display: block;
    text-align: center;
    text-decoration: none;
    width: 200px;
    margin: 70px auto;
    padding: 1rem 4rem;
    font-weight: bold;
    border: 2px solid #27acd9;
    color: #27acd9;
    border-radius: 100vh;
    transition: 0.5s;
}
    #btn:hover {
        color: #fff;
        background: #27acd9;
}

```

CSSはメインではないので装飾は凝らず、解答ボタンのみタグは[こちら](https://excellent.ne.jp/homepage/6562/)からいただきました。

```Javascript
'use strict';

const calScore = function() {
    let score =0;

    const selectedRadio1 = document.querySelector('input[name="q1"]:checked');
    const selectedRadio2 = document.querySelector('input[name="q2"]:checked');
    const selectedRadio3 = document.querySelector('input[name="q3"]:checked');
        
        if (selectedRadio1 && selectedRadio2 && selectedRadio3) {
            if (selectedRadio1.value === "パリ") {
                score++;
            }
            if (selectedRadio2.value === "インドネシア") {
                score++;
            }
            if (selectedRadio3.value === "ドイツ") {
                score++;
            }
        
        return score;
        };
    };

document.addEventListener('DOMContentLoaded', (event) => {
    const btn = document.getElementById('btn');
    btn.addEventListener('click', () => {
        const score = calScore();
        document.getElementById('answer').textContent = `あなたは3問中${score}問正解です。`;
    });
});
```
Javascriptのコード。

calScoreで点数を計算する関数を定義。

Score０点を初期値として、各クイズでチェックされているラジオボタンを確認。
それぞれの解答が正しい場合にScoreに＋１加点していく。
解答ボタンを押したら正解数が表示される。

## JSコードの解説

```js
let score =0;
```
はじめにlet scoreでscoreに0を代入。
const scoreにすると、後から点数を足した時にscoreを変更できないので変数を使用。

```js
const selectedRadio1 = document.querySelector('input[name="q1"]:checked');
const selectedRadio2 = document.querySelector('input[name="q2"]:checked');
const selectedRadio3 = document.querySelector('input[name="q3"]:checked');   
```
selectedRadio1の場合、querySelector()メソッドで<input>タグのname属性がq1となっている要素の中からchecked、つまりラジオボタンが選択されている要素を取得する。

※querySelector()メソッドは一番最初にマッチした１つの要素のみ取得可能だが、:checkedによってimputタグのnameがq1の要素の中でチェックがついている要素＝４つの中の選択された１つの要素となる。

```js
if (selectedRadio1 && selectedRadio2 && selectedRadio3) {
    if (selectedRadio1.value === "パリ") {
        score++;
    }
    if (selectedRadio2.value === "インドネシア") {
        score++;
    }
    if (selectedRadio3.value === "ドイツ") {
        score++;
    }
```

if文は入れ子構造にしたが、複雑な条件になっていくとわかりにくく、あまり推奨されないよう・・・

最初の条件で(selectedRadio1 && selectedRadio2 && selectedRadio3)を指定することで、選択されていないラジオボタンがないか確認する。
これがないと何も選択されていない時にエラーが発生する。

selectedRadio.valueでそれぞれの問題の選択されたチェックボタンが解答と一致するか確認。
一致していればスコアに１点を加える。

最後にreturn scoreで得点を返す。

```js
document.addEventListener('DOMContentLoaded', (event) => 
```

addEventListener()は、処理を行うためのスイッチとなるイベントが発生し（処理を行うために必要な操作、例えばクリックなど）が行われたかどうかをチェックする。

対象要素.addEventListener(種類,関数)

これが基本構文。

種類には以下のようなイベントが使用できる。

| イベント種類 |  |
|:--|:--|
|load|Webページの読み込みが完了した時に発動（画像などのリソースすべて含む|
|DOMContentLoaded|Webページが読み込みが完了した時に発動（画像などのリソースは含まない）|
|click|マウスボタンをクリックした時に発動|
|mousedown|マウスボタンを押している時に発動|
|mouseup|マウスボタンを離したときに発動|
|mousemove|マウスカーソルが移動した時に発動|
|keydown|キーボードのキーを押したときに発動|
|keyup|キーボードのキーを離したときに発動|
|keypress|キーボードのキーを押している時に発動|
|change|フォーム部品の状態が変更された時に発動|
|submmit|フォームのsubmitボタンを押したときに発動|
|scroll|画面がスクロールした時に発動|

(引用：[【JavaScript入門】addEventListener()によるイベント処理の使い方！ | 侍エンジニアブログ](https://www.sejuku.net/blog/57625))



今回の場合は、document(対象要素)で'DOMContentLoaded'(種類)が行われたら、(event) => {}の関数処理を行う訳される。

DOMContentLoadedは、htmlが完全に読み込まれたら処理を実行するもので、document.addEventListener('DOMContentLoaded', (event) => {}
この部分はなくても動作するが、これがあることで読み込みと処理が早くなる。
削除してテストした際、解答ボタンをクリックすると処理実行されるまでに待ち時間が発生した。

```js
    const btn = document.getElementById('btn');
    btn.addEventListener('click', () => {});
```

document.getElementById('btn')でid=btnの<button id="btn">解答</button>要素を取得し、「btn」へ代入。

btnにaddEventListenerメソッドで'click'(マウスボタンをクリックした時に発生する)イベントを設定。

その時に行う処理が、以下。

```js
const score = calScore();
        document.getElementById('answer').textContent = `あなたは3問中${score}問正解です。`;
```

変数scoreにcalScore()関数の処理で行う得点を代入。

document.getElementById('answer').textContentでid='answer'要素のtext部分を=以下に書き換え、scoreを表示する。

## まとめ

ProgateやUdemy、書籍などでhtml、CSS、JavaScriptを学習後、自分でコードを書いて何か作ってみようと思い、クイズを作ってみました。

実際に書くとどこから書き始めたらいいのか、どういう方法で情報を読み取って加工・出力するのがスマートかという疑問から、学習していない記述やメソッドなどもあり、とても学びになりました。

わからないところはchatGPTを利用することで、解決の糸口を見付けられ、情報検索が容易になりました。（本当にわからないと何て検索したらいいかさえわからないのでchatGPTは偉大・・・）

手を動かし、自分で考えたり調べたりして作るのは、受け身の学習と違うのでかなり楽しく、完成したときの達成感も得られ嬉しいですね。

また、アウトプット意識して学習進めていきます。