Let's Practice Vocab 05-01
05-01 Let's Practice Vocab
TOPIC: データを外部ファイルから読み込む
CHECK
import { data } from "./data.js"
でdata.js
の中にある data 変数を import するquestions
変数を data で置き換える- 使ってきた
quesitons
を消す
// ELEMENTS
// --------------------------------
// NEW!!
import { data } from "./data.js"
// 画面最初のスタートボタン
const startBtnEl = document.getElementById("start-btn")
// QuestionボックスとAnswersボックスが入っているElement
const questionAnswersContainerEl = document.getElementById(
"question-answers-container"
)
// ゲーム開始時のHeaderを表すElement
const headerContainerEl = document.getElementById("header-container")
// ゲームが始まったあとの画面上部の小さなHeaderを表すElement
const headerSmallEl = document.getElementById("header-small")
// 次のの問題を表示するボタン
const nextBtnEl = document.getElementById("next-btn")
// 4択全てを入れておくElement
const answersEl = document.getElementById("answers")
// Questionボックス内の日本語
const jpTextEl = document.getElementById("jp-text")
// Questionボックス内の英語
const enTextEl = document.getElementById("en-text")
// 画面上部に現れる結果を表示するElement
const resultEl = document.getElementById("result-box")
// resultElの中のCircleを表すElement
const circleEl = document.getElementById("circle")
// VARIABLES
// --------------------------------
// ランダムにシャッフルされたQuestionオブジェクトが入っているarray
let shuffledQuestions
// 現在の問題のIndex番号(1ずつたされる)
let currentQuestionIndex
// EVENT LISTENERS
// --------------------------------
// スタートボタンのクリックを聞くListener
startBtnEl.addEventListener("click", startGame)
// Nextボタンのクリックを聞くListener
nextBtnEl.addEventListener("click", () => {
// currentQuestionIndexに1を足す
currentQuestionIndex++
// 次のQuestionを表示する
setNextQuestion()
})
// Enterボタンが押されたのを聞くListener
document.addEventListener("keyup", (e) => {
// 押されたKeyが"Enter"キーなら
if (e.key === "Enter") {
// currentQuestionIndexに1を足す
currentQuestionIndex++
// 次のQuestionを表示する
setNextQuestion()
}
})
// FUNCTIONS
// --------------------------------
// ゲームを始めるFunction
function startGame() {
// スタートボタンを隠す
startBtnEl.classList.add("hide")
// questions array にある全てのQuestionオブジェクトをランダムに並べ替える
shuffledQuestions = questions.sort(() => Math.random() - 0.5)
// currentQuestionIndexを0に設定する
currentQuestionIndex = 0
// questionAnswersContainerEl についてhideを消し、表示する
questionAnswersContainerEl.classList.remove("hide")
// スタート画面のHeaderを消す
headerContainerEl.style["display"] = "none"
// 小さなHeaderを画面上部に表示する
headerSmallEl.classList.remove("hide")
// 次の質問を表示する
setNextQuestion()
}
// 次の質問を表示するFunction
function setNextQuestion() {
// Nextボタンを消し、現在表示されている4択Answerを全て消す
resetState()
// 画面に表示されているCircleの結果を隠す
hideResult()
// 質問を表示する
showQuestion(shuffledQuestions[currentQuestionIndex])
}
// Nextボタンを消し、現在表示されている4択Answerを全て消すFunction
function resetState() {
// Nextボタンを隠す
nextBtnEl.classList.add("hide")
// Answers Element(全ての4択が入っているElement)に
// childが見つかるうちは
while (answersEl.children[0]) {
// Answer Elementのなかのchildを消す
// つまりAnswer Elementの中身を空っぽにする
answersEl.removeChild(answersEl.children[0])
}
}
// Questionオブジェクトを受け取り、質問を表示するFunction
function showQuestion(question) {
// 日本語を受け取ったQuestionオブジェクトのjpプロパティに変更する
jpTextEl.innerText = question.jp
// 英語を受け取ったQuestionオブジェクトのenプロパティに変更する
enTextEl.innerText = question.en
// Questionオブジェクトのanswersプロパティ(array)にある一つ一つのanwerをループする
question.answers.forEach((answer, idx) => {
// 1個のAnswer HTML を文字で作成し、ところどころQuestionオブジェクトのデータを挿入する
const el = `
<div class="answer-box">
<div class="answer-number">
<span>${idx + 1}</span>
</div>
<h3 id="answer1" class="answer" data-number="1">${answer.text}</h3>
</div>
`
// 新しいdiv Elementを作成する
const div = document.createElement("div")
// CSSのためにそのElementにclassを追加する
div.classList.add("answer-container")
// そのElementのHTMLを先程作ったHTML文字列を挿入する
div.innerHTML = el
// Answerオブジェクトのcorrectプロパティがtrueなら
if (answer.correct) {
// div Elementの中にある最初のchild
// つまり <div class="answer-box"> に data-correct="true" を追加する
// datasetの使い方は特殊!
// 後でどの選択肢が正解かを判断するために使うよ
// data-correct="true"がついている<div class="answer-box"></div>にCSSで色をつけたりする
div.children[0].dataset.correct = answer.correct
}
// div Element にクリックされたことを聞くEvent Listenerを追加
// クリックされたら selectAnswer Functionを実行
div.addEventListener("click", selectAnswer)
// Answers Element(全ての4択が入っているElement)に新しくできたAnswer ElementとChildとして追加する
answersEl.appendChild(div)
})
}
// Answer(4択)をクリックしたときに呼ぶFunction
// e = Event クリックされたときのイベント情報を受取る
function selectAnswer(e) {
// クリックしたElementの最初のChildを取得
// つまり<div class="answer-container">の中にある
// 最初のChildの<div class="answer-box">を取得する
const selectedAnswer = e.currentTarget.children[0]
// div class="answer-box">に設定した"data-correct=true"があるかをさがし
// もしあれば"data-correct=true"の"true"をcorrect変数に格納する
const correct = selectedAnswer.dataset.correct
// Answers Elementの中にある4つの4択AnswerをArrayに変換しループする
Array.from(answersEl.children).forEach((answerEl) => {
// answer Elementの最初のChildである<div class="answer-box">を取得
const answerBoxEl = answerEl.children[0]
// <div class="answer-box"> にsetStatusClassを使って
// <div class="answer-box" class="correct"> もしくは
// <div class="answer-box" class="wrong"> のように
// classを追加する
setStatusClass(answerBoxEl, answerBoxEl.dataset.correct)
})
// 結果を表すCircleを画面上部に表示する
showResult(correct)
// もし、問題数(shuffledQuestion.length)が解いた問題(currentQuestionIndex)
// よりも多い場合は
if (shuffledQuestions.length > currentQuestionIndex + 1) {
// Nextボタンを隠す
nextBtnEl.classList.remove("hide")
} else {
// そうでない場合はstartボタンのテキストRestartに変更する
startBtnEl.innerText = "Restart"
// startボタンを表示する
startBtnEl.classList.remove("hide")
}
}
// ElementにAnswerが正しい場合はclass="correct"、
// そうでない場合はclass="wrong"と追加するFunction
function setStatusClass(el, correct) {
// 現在、そのelementについているclassを消す
clearStatusClass(el)
// もし、correctがtrueなら
if (correct) {
// そのElementにclass="correct"を追加する
el.classList.add("correct")
} else {
// そのElementにclass="wrong"を追加する
el.classList.add("wrong")
}
}
// そのelementについているclassを消すFunction
function clearStatusClass(el) {
el.classList.remove("correct")
el.classList.remove("wrong")
}
// 結果を知らせる画面上部のCircleを表示するFunction
function showResult(correct) {
// Circleについているclassを消す
clearStatusClass(circleEl)
// もしcorrectがtrueなら
if (correct) {
// circle Elementの最初のChildであるh1 Elementのテキストを変更
circleEl.children[0].innerText = "You're Right!!"
} else {
// circle Elementの最初のChildであるh1 Elementのテキストを変更
circleEl.children[0].innerText = "You're Wrong..."
}
// circle Elementにclass="correct" か class="wrong" を追加
setStatusClass(circleEl, correct)
// result Elementのclass="hide"を消し、表示する
resultEl.classList.remove("hide")
}
// result Elementのclass="hide"を追加し、消す
function hideResult() {
resultEl.classList.add("hide")
}
// NEW!!
// data.jsにある全てのQuestionオブジェクトをquestions変数に格納する
const questions = data