この記事では、JavaScriptのfor (let i =)
のループを使って、10問の質問の回答でスコアを出してリダイレクトをかける方法について解説しています。
比較的診断系のコンテンツで使えそうなスニペットなので、参考にしてみてください。
for (let i =)
JavaScriptのfor
ループは、コードブロックを繰り返し実行します。
基本的な形はfor (初期化; 条件; ステップ) {...}
です。
- 初期化: この部分で、ループが始まる前に一度だけ実行される式を書きます。よく使われるのはカウンタ変数の初期化です。
- 条件: この式が
true
を返す限り、ループは繰り返されます。false
を返すと、ループは終了します。 - ステップ: この部分のコードは、ループ内のコードブロックが実行された後に毎回実行されます。
例えば、以下の通りです。
let numbers = [1, 2, 3, 4, 5];
for (let idx = 0; idx < numbers.length; idx++) {
console.log(numbers[idx]);
}
このコードでは、idx
というカウンタ変数を使用しています。idx
は、index
(インデックス)の略で、配列の位置を指すための番号としてよく使われる名前です。
idx
の初期値は0(最初の要素の位置)とし、idx
が配列の長さ未満である間、console.log
を使用して配列の要素を順番に表示します。そして、毎回のループの終わりでidx
を1増やしています。
ループを覚えると、色々できるようになるのでおさえておきましょう。
スコアを出してリダイレクトをするサンプル
早速、サンプルです。
表示される10個の質問に回答していくと、最終的に合計得点が表示されます。合計得点表示後2秒経つと、取得した合計得点に応じて、2秒後にリダイレクトがかかりページ遷移します。
Question 1: YES or NO?
Question 2: YES or NO?
Question 3: YES or NO?
Question 4: YES or NO?
Question 5: YES or NO?
Question 6: YES or NO?
Question 7: YES or NO?
Question 8: YES or NO?
Question 9: YES or NO?
Question 10: YES or NO?
リダイレクトのページは用意していないので「404」が表示されます。
後述するJavaScriptのコードで「得点の配点」と「リダイレクト」の2つはそれぞれ設定可能です。
実装の手順と方法
コードの詳細の前に、実装の手順と方法について解説していきます。
まずは、HTMLを記述します。
設置したい場所に記述しましょう。
<div class="quiz__container">
<div class="question" data-value="10">
<p class="question__title">Question 1: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="9">
<p class="question__title">Question 2: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="8">
<p class="question__title">Question 3: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 4: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 5: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 6: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 7: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 8: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 9: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="1">
<p class="question__title">Question 10: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
</div>
<div class="result__container" style="display: none;">
Your score is: <span id="score">0</span>/100
</div>
次に、JavaScriptのコードを記述します。
コードは <body>〜</body>
で、</body>
の閉じタグ(クロージングタグ)の前に記述しましょう。
// 現在の質問のインデックスを管理する変数
let currentQuestion = 0;
// 合計得点を管理する変数
let totalScore = 0;
// 全質問要素を取得
const questions = document.querySelectorAll('.question');
// 結果表示部分の要素を取得
const resultContainer = document.querySelector('.result__container');
// スコア表示部分の要素を取得
const scoreElem = document.getElementById('score');
// ボタンがクリックされた時の処理を行う関数
function nextQuestion(clickedButton, isYes) {
// クリックされたボタンにactiveクラスを追加
clickedButton.classList.add('active');
// YESが選択された場合、得点を加算
if (isYes) {
const scoreForThisQuestion = parseInt(questions[currentQuestion].getAttribute('data-value'), 10);
totalScore += scoreForThisQuestion;
}
// 1秒待機後に次の処理へ進む
setTimeout(function() {
// activeクラスをクリックされたボタンから削除
clickedButton.classList.remove('active');
// 現在の質問を非表示にする
questions[currentQuestion].style.display = 'none';
// 質問のインデックスを進める
currentQuestion++;
// 次の質問を表示するか、結果を表示するか判断
if (currentQuestion < questions.length) {
questions[currentQuestion].style.display = 'block';
} else {
scoreElem.textContent = totalScore;
resultContainer.style.display = 'block';
// 得点に応じて異なるページへリダイレクトする
setTimeout(function() {
if (totalScore <= 20) {
window.location.href = 'URL_for_0-20';
} else if (totalScore <= 40) {
window.location.href = 'URL_for_21-40';
} else if (totalScore <= 60) {
window.location.href = 'URL_for_41-60';
} else if (totalScore <= 80) {
window.location.href = 'URL_for_61-80';
} else if (totalScore < 100) {
window.location.href = 'URL_for_81-99';
} else {
window.location.href = 'URL_for_100';
}
}, 2000); // 結果表示後、2秒でリダイレクト
}
}, 1000); // 1秒後に次の処理を行う
}
// 起動時に2番目以降の質問を非表示に設定
for (let i = 1; i < questions.length; i++) {
questions[i].style.display = 'none';
}
最後にCSSを書いて、見た目を整えましょう。
button:active, .question__btn button.active {
background: #707070;
color: #fff;
}
.question {
display: block;
animation: fadeIn 0.8s ease 0s 1 normal;
}
.question__btn button {
display: inline-flex;
margin: 0;
}
.question__btn {
display: flex;
justify-content: center;
gap: 40px;
}
p.question__title {
display: block;
width: 100%;
text-align: center;
position: relative;
}
ざっくりとしたコードの解説
コードは、HTML・JavaScript・CSSの3種類です。ざっくりですが、順に解説していきます。
HTML
HTMLのコードは、診断の質問や、ボタンなどインターフェイス部分を表現しています。
<div class="quiz__container">
<div class="question" data-value="10">
<p class="question__title">Question 1: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="9">
<p class="question__title">Question 2: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="8">
<p class="question__title">Question 3: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 4: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 5: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 6: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 7: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 8: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="10">
<p class="question__title">Question 9: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
<div class="question" data-value="1">
<p class="question__title">Question 10: YES or NO?</p>
<div class="question__btn">
<button onclick="nextQuestion(this, true)">YES</button>
<button onclick="nextQuestion(this, false)">NO</button>
</div>
</div>
</div>
<div class="result__container" style="display: none;">
Your score is: <span id="score">0</span>/100
</div>
コードが多いので、箇条書きで解説すると以下の通りです。
- コンテナ: <div class="quiz__container"> はクイズ全体のラッピング要素です。この中に各質問が配置されています。
- 各質問: <div class="question" data-value="10"> は、個々の質問を示しています。data-value 属性はその質問に対するスコアの値を保持しています。例えば、第一の質問の正解は10点の価値があります。
- 質問のタイトル: 各質問の上部には、<p class="question__title"> を使用して、質問文が表示されます。
- 回答ボタン: 各質問にはYESとNOの2つのボタンがあります。ユーザーがクリックすると、nextQuestion 関数が呼び出され、クリックしたボタンとその回答が渡されます。
- 結果の表示: 最後に、<div class="result__container"> があります。初めは style="display: none;" で非表示に設定されていますが、クイズが終了すると表示されるようになっています。この中にはユーザーの合計スコアが<span id="score"> 要素内に表示されます。
このコードを使用して、ユーザーは質問に回答し、最終的にそのスコアを確認。そして、対応したページにリダイレクトが行われます。
質問の「Question」の文章は、HTMLで制御します。
JavaScript
JavaScriptのコードで、主に「得点の計算方法」「リダイレクト先の指定」「表示の時間差指定」の3つを設定します。
// 現在の質問のインデックスを管理する変数
let currentQuestion = 0;
// 合計得点を管理する変数
let totalScore = 0;
// 全質問要素を取得
const questions = document.querySelectorAll('.question');
// 結果表示部分の要素を取得
const resultContainer = document.querySelector('.result__container');
// スコア表示部分の要素を取得
const scoreElem = document.getElementById('score');
// ボタンがクリックされた時の処理を行う関数
function nextQuestion(clickedButton, isYes) {
// クリックされたボタンにactiveクラスを追加
clickedButton.classList.add('active');
// YESが選択された場合、得点を加算
if (isYes) {
const scoreForThisQuestion = parseInt(questions[currentQuestion].getAttribute('data-value'), 10);
totalScore += scoreForThisQuestion;
}
// 1秒待機後に次の処理へ進む
setTimeout(function() {
// activeクラスをクリックされたボタンから削除
clickedButton.classList.remove('active');
// 現在の質問を非表示にする
questions[currentQuestion].style.display = 'none';
// 質問のインデックスを進める
currentQuestion++;
// 次の質問を表示するか、結果を表示するか判断
if (currentQuestion < questions.length) {
questions[currentQuestion].style.display = 'block';
} else {
scoreElem.textContent = totalScore;
resultContainer.style.display = 'block';
// 得点に応じて異なるページへリダイレクトする
setTimeout(function() {
if (totalScore <= 20) {
window.location.href = 'URL_for_0-20';
} else if (totalScore <= 40) {
window.location.href = 'URL_for_21-40';
} else if (totalScore <= 60) {
window.location.href = 'URL_for_41-60';
} else if (totalScore <= 80) {
window.location.href = 'URL_for_61-80';
} else if (totalScore < 100) {
window.location.href = 'URL_for_81-99';
} else {
window.location.href = 'URL_for_100';
}
}, 2000); // 結果表示後、2秒でリダイレクト
}
}, 1000); // 1秒後に次の処理を行う
}
// 起動時に2番目以降の質問を非表示に設定
for (let i = 1; i < questions.length; i++) {
questions[i].style.display = 'none';
}
- 変数の初期化: currentQuestion は現在の質問のインデックスを管理し、totalScore はユーザーの合計得点を保存します。
- DOM要素の取得: questions には全質問要素が格納され、resultContainer と scoreElem には結果とスコアの表示部分が格納されます。
- ボタンクリック時の処理: nextQuestion 関数は、ユーザーが回答ボタンをクリックした際に呼び出されます。この関数は、得点の計算、現在の質問の非表示、次の質問の表示、または結果の表示といった一連の処理を行います。
- 得点の判断: ユーザーが全ての質問に答えた後、その得点に基づいて異なるページへリダイレクトします。このリダイレクト処理は、結果の表示から2秒後に実行されます。
- 初期設定: アプリの起動時に、2番目以降の質問を非表示にするループがあります。これにより、最初に1つ目の質問のみが表示され、残りの質問は非表示に設定されます。
このコードで、質問に回答し、最終的にそのスコアに基づいて適切な結果ページにリダイレクトがかかります。
CSS
CSSで、指定されたIDやクラスを持つ要素に対して様々なスタイルを適用して、見た目を整えます。
button:active, .question__btn button.active {
background: #707070;
color: #fff;
}
.question {
display: block;
animation: fadeIn 0.8s ease 0s 1 normal;
}
.question__btn button {
display: inline-flex;
margin: 0;
}
.question__btn {
display: flex;
justify-content: center;
gap: 40px;
}
p.question__title {
display: block;
width: 100%;
text-align: center;
position: relative;
}
さいごに
今回は、JavaScriptで質問の回答でスコアを出してリダイレクトをかける「診断系」についての解説でした。
見た目はかなり簡素に作っているので、自分好みにカスタマイズして使ってみてください。