見出し画像

[JavaScript] はじめてのJavaScript その3

こんにちは。tomoです。
今日もクイズアプリ作成のつづきです。

前回までのあらすじ

とりあえずレイアウトまでつくってみたけれど何もイベントを割り付けていないから当然動かないし、ダサい。

初回

前回


ではボタンやフォントを可愛くしたりするという積み残し課題はあるもののとりあえず動くものを作っていきましょう。

ざっくり作る① タイトル → クイズ

まずはタイトルでスタートボタンを押したときにクイズ画面に遷移する状況を考えてみます。

画像1

上記のようにやることは3つ。
1. 上部のラベル (#message) をタイトル文から問題文に変える
2. 画像 (#image) をクイズっぽい画像に変える
3. スタートボタン (#to-next) を消して選択肢 (#options) を表示する

この3つのことをスタートボタンをクリックしたときのイベントとして登録しておけばよさそうなので作っていきます。

index.html (JavaScriptの読み込みを追加しただけ)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>クイズ</title>
<link rel ="stylesheet" type="text/css" href="css/style.css">
</head>
<body bgcolor="aliceblue">
<label id="message">単位のクイズ!</label>
<div id="image-area">
   <img id='image' src='images/title/003.png' alt='character image'>
</div>
<div id='button-area'>
   <div id='options' style='display: none;'>
       <button id='option1' style='grid-row: 1; grid-column: 1'>0.001 dL</button>
       <button id='option2' style='grid-row: 1; grid-column: 2'>0.01 dL</button>
       <button id='option3' style='grid-row: 1; grid-column: 3'>0.1 dL</button>
       <button id='option4' style='grid-row: 2; grid-column: 1'>10 dL</button>
       <button id='option5' style='grid-row: 2; grid-column: 2'>100 dL</button>
       <button id='option6' style='grid-row: 2; grid-column: 3'>1000 dL</button>
   </div>
   <button id='to-next' style='display: inline;'>スタート</button>
</div>
<div id='to-title-area'>
   <button id="to-title">タイトルにもどる</button>
</div>
<script type="text/javascript" src="js/script.js"></script> <!-- JavaScriptを読み込む -->
</body>
</html>

script.js (new!!)

/* メッセージを問題文に変える */
function changeMessage() {
   var message = document.getElementById('message');
   message.innerHTML = '1Lは何dL?';
}

/* 画像ををクイズっぽいやつに変える */
function changeImage() {
   var image = document.getElementById('image');
   image.src = 'images/question/005.png';
}

/* スタートボタンを消して選択肢を表示する */
function changeButtonArea() {
   var startButton = document.getElementById('to-next');
   startButton.style.display = 'none';

   var options = document.getElementById('options');
   options.style.display = 'grid';
}

window.onload = function() {
   /* スタートボタンにクイズ画面に遷移するためのイベントを追加 */
   var startButton = document.getElementById('to-next');
   startButton.addEventListener('click', function() {
       changeMessage();
       changeImage();
       changeButtonArea();
   });
}

こんな感じ。特に解説すべき点が思いつかない。なんか解説してほしいところあったら言ってください。

ということで上記のようなJavaScriptを書いたら下のような遷移を実現できました。選択肢のボタンが思ったよりも大きいこと以外はすべて想定通り!

画像2

ざっくり作る② クイズ → タイトル

ここまででは当然選択肢を押しても何も起こりませんし、タイトルに戻るボタンを押してもタイトルには戻れません。ということでタイトルに戻る処理を実装していきます。

画像3

さっき (タイトル→クイズ) の逆ですね。関数をもうひとつずつ実装するのはちょっとバカっぽいのでそれぞれの関数の引数に遷移先の状態を与えられるようにしましょう。

script.js (タイトルへの遷移を実装)

function changeMessage(next) {
   var message = document.getElementById('message');
   
   /* next が "quiz" だったら問題文、そうでなければタイトル文を表示 */
   message.innerHTML = (next == 'quiz') ? '1Lは何dL?'
                                        : '単位のクイズ!';
}

function changeImage(next) {
   var image = document.getElementById('image');

   /* next が "quiz" だったらクイズ用、そうでなければタイトル用画像を表示 */
   image.src = (next == 'quiz') ? 'images/question/005.png'
                                : 'images/title/003.png';
}

function changeButtonArea(next) {
   var startButton = document.getElementById('to-next');
   var options = document.getElementById('options');

   /* next が "quiz" だったらクイズ用、そうでなければタイトル用のボタンを表示 */
   switch (next) {
       case 'quiz':
           startButton.style.display = 'none';
           options.style.display = 'grid';
           break;
       default:
           startButton.style.display = 'inline';
           options.style.display = 'none';
           break;
   }
}

window.onload = function() {
   /* change~の引数に "quiz" を与えるようにした */
   var startButton = document.getElementById('to-next');
   startButton.addEventListener('click', function() {
       changeMessage('quiz');
       changeImage('quiz');
       changeButtonArea('quiz');
   });

   /* タイトルにもどるボタンにタイトル画面に遷移するためのイベントを追加 */
   var titleButton = document.getElementById('to-title');
   titleButton.addEventListener('click', function() {
       changeMessage('title');
       changeImage('title');
       changeButtonArea('title');
   });
}

わりと嫌われがちな3項演算子ですが、個人的には単純な処理の場合はswitch文を使うよりも簡潔に書くことが出来て見やすいと思ってます。

これでタイトル画面とクイズ画面を行ったり来たりできるようになりました。

画像4

ざっくり作る③ リファクタリング

ここでお気づきでしょうか?

タイトル画面に遷移させるために、タイトル画面で表示する文字列や画像をJavaScriptで書きました。これらの情報はHTMLファイルにも記述されているので同じ情報が2か所で管理されることになってしまいます。

これでは修正を加える必要があった際に1つの修正をしたいだけなのに2か所に修正を加えなくてはいけなくなってしまい、口の悪い先輩にゴミ!カス!クズ!と罵られてしまいます。

ということでタイトル画面の表示もJavaScriptに任せてしまって、HTMLからは取り去ることにします。
このように動作を変えずに (いや、正確に言えば変わってるんですけど) コードを綺麗にしていく作業をリファクタリングと言います。きっと。

index.html (script.js と重複している箇所を削除)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>クイズ</title>
<link rel ="stylesheet" type="text/css" href="css/style.css">
</head>
<body bgcolor="aliceblue">
<label id="message"></label> <!-- 表示する文字列 ("単位のクイズ!") を削除 -->
<div id="image-area">
   <img id='image' alt='character image'> <!-- 表示する画像ファイル (src='images/title/003.png') を削除  -->
</div>
<div id='button-area'>
   <div id='options'> <!-- style='display: none' を削除 -->
       <button id='option1' style='grid-row: 1; grid-column: 1'>0.001 dL</button>
       <button id='option2' style='grid-row: 1; grid-column: 2'>0.01 dL</button>
       <button id='option3' style='grid-row: 1; grid-column: 3'>0.1 dL</button>
       <button id='option4' style='grid-row: 2; grid-column: 1'>10 dL</button>
       <button id='option5' style='grid-row: 2; grid-column: 2'>100 dL</button>
       <button id='option6' style='grid-row: 2; grid-column: 3'>1000 dL</button>
   </div>
   <button id='to-next'>スタート</button> <!-- style='display: inline' を削除 -->
</div>
<div id='to-title-area'>
   <button id="to-title">タイトルにもどる</button>
</div>
<script type="text/javascript" src="js/script.js"></script>
</body>
</html>

script.js (ロード時にタイトル画面を表示する処理を追加)

function changeMessage(next) {
   var message = document.getElementById('message');
   message.innerHTML = (next == 'quiz') ? '1Lは何dL?'
                                        : '単位のクイズ!';
}

function changeImage(next) {
   var image = document.getElementById('image');
   image.src = (next == 'quiz') ? 'images/question/005.png'
                                : 'images/title/003.png';
}

function changeButtonArea(next) {
   var startButton = document.getElementById('to-next');
   var options = document.getElementById('options');

   switch (next) {
       case 'quiz':
           startButton.style.display = 'none';
           options.style.display = 'grid';
           break;
       default:
           startButton.style.display = 'inline';
           options.style.display = 'none';
           break;
   }
}

window.onload = function() {
   var startButton = document.getElementById('to-next');
   startButton.addEventListener('click', function() {
       changeMessage('quiz');
       changeImage('quiz');
       changeButtonArea('quiz');
   });

   var titleButton = document.getElementById('to-title');
   titleButton.addEventListener('click', function() {
       changeMessage('title');
       changeImage('title');
       changeButtonArea('title');
   });

   /* 初回タイトル表示用の処理を追加 */
   changeMessage('title');
   changeImage('title');
   changeButtonArea('title');
}

という感じです。

はい。そうですね。明らかに初回タイトル表示用の処理とタイトルに戻るボタンを押したときに同じ処理をしてますね。知ってます。

ということで再度修正しましょう。ついでにタイトルに戻る処理や、クイズ画面に遷移する処理はベタで書くよりもひとまとまりの処理として関数にします。

script.js (まとまった処理を関数化)

function changeMessage(next) {
   var message = document.getElementById('message');
   message.innerHTML = (next == 'quiz') ? '1Lは何dL?'
                                        : '単位のクイズ!';
}

function changeImage(next) {
   var image = document.getElementById('image');
   image.src = (next == 'quiz') ? 'images/question/005.png'
                                : 'images/title/003.png';
}

function changeButtonArea(next) {
   var startButton = document.getElementById('to-next');
   var options = document.getElementById('options');

   switch (next) {
       case 'quiz':
           startButton.style.display = 'none';
           options.style.display = 'grid';
           break;
       default:
           startButton.style.display = 'inline';
           options.style.display = 'none';
           break;
   }
}

/* タイトル画面を表示 */
function showTitle() {
   changeMessage('title');
   changeImage('title');
   changeButtonArea('title');
}

/* クイズ画面を表示 */
function showQuiz() {
   changeMessage('quiz');
   changeImage('quiz');
   changeButtonArea('quiz');
}


window.onload = function() {
   var startButton = document.getElementById('to-next');
   startButton.addEventListener('click', function() {
       showQuiz(); /* 関数化した */
   });

   var titleButton = document.getElementById('to-title');
   titleButton.addEventListener('click', function() {
       showTitle(); /* 関数化した */
   });

   showTitle(); /* 関数化したッ!! */
}

HTMLもすっきりしてきたし、JavaScript側も変更を加える際にも管理しやすくなった気がします。

まとめ

ということでまたもや長くなってきたので今回はこの辺りで。
ついにJavaScriptの実装に入ることができました!
といってもまだクイズには答えられない状態なので次回はクイズに答えられる部分を実装していきたいと思います。

ゴミ!カス!クズ!のくだり以外は無駄な話もしていないつもりなのに思ったよりも長くなってしまい若干ひいています。それでは。

いいなと思ったら応援しよう!