728x90
반응형
퀴즈 이펙트 CBT확인 유형을 보충 하였습니다.
<script>
const cbtQuiz = document.querySelector(".cbt__quiz");
const cbtomr = document.querySelector(".cbt__omr");
const cbtSubmit = document.querySelector(".cbt__submit");
const cbtLength = document.querySelector(".cbt_length");
const cbtRest = document.querySelector(".cbt__rest");
const cbtstart = document.querySelector(".cbt__start");
let questionAll = []; //모든 퀴즈 정보
let questionLength = 0; //전체 문제수
let questionRest = questionLength; //남은 문제수
document.querySelector(".start").addEventListener("click", () => {
cbtstart.style.display = "none"
});
전체 문제의 수와 남은 문제의 수를 가져오기 위해 우선 선택자를 추가 하였습니다.
그리고 문제가 바로 안보이게 하기 위해 블라인드 처리를 했는데 시작하기를 누르면 사라지게 만들었습니다.
//데이터 가져오기
const dataQuestion = () => {
fetch("json/gisa2020_01.json") //json을가져옴
.then(res => res.json()) //fetch에서 가져온것을 res.json로 변경 하여 가져온후 실행
.then(items => { //가져온 json을 items로 변경
// console.log(items)
questionAll = items.map((item, index) => {
const formattedQuestion = {
question: item.question,
number: index + 1,
}
const answerChoices = [...item.incorrect_answers]; //오답 불러오기
formattedQuestion.answer = Math.trunc(Math.random() * (answerChoices.length + 1)); //정답을 랜덤으로 불러오기
// console.log(formattedQuestion.answer)
answerChoices.splice(formattedQuestion.answer, 0, item.correct_answer); //정답을 랜덤으로 추가
//보기를 추가
answerChoices.forEach((choice, index) => {
formattedQuestion["choice" + (index + 1)] = choice;
});
//문제에 대한 해설이 있으면 출력
if (item.hasOwnProperty("question_desc")) {
formattedQuestion.question_desc = item.question_desc;
}
//문제에 대한 이미지가 있으면 출력
if (item.hasOwnProperty("question_img")) {
formattedQuestion.question_img = item.question_img;
}
//해설이 있으면 출력
if (item.hasOwnProperty("desc")) {
formattedQuestion.desc = item.desc;
}
// console.log(formattedQuestion);
return formattedQuestion;
});
newQuestion(); //문제 만들기
//전체 문제수 만들기
questionLength = questionAll.length;
cbtLength.innerHTML = questionLength;
cbtRest.innerHTML = questionLength;
}) //res.json을 items으로 하여 상수
.catch((err) => console.log(err));
}
데이터 가져오기에서 전체 문제수를 가져와 전체 문제수와 남은 문제수에 저장 해주고 있습니다.
//문제 만들기
const newQuestion = () => {
const exam = [];
const omr = [];
questionAll.forEach((question, number) => {
exam.push(`
<div class="cbt">
<div class="cbt__question"><span>${question.number} </span>. ${question.question}</div>
<div class="cbt__question__img"><img style='width:300px' src="${question.question_img}" alt=""></div>
<div class="cbt__question__desc">${question.question_desc}</div>
<div class="cbt__selects">
<input type="radio" id="select${number}_1" name="select${number}" value="${number}_0" onclick="answerSelect2(this)">
<label for="select${number}_1"><span>${question.choice1}</span></label>
<input type="radio" id="select${number}_2" name="select${number}" value="${number}_1" onclick="answerSelect2(this)">
<label for="select${number}_2"><span>${question.choice2}</span></label>
<input type="radio" id="select${number}_3" name="select${number}" value="${number}_2" onclick="answerSelect2(this)">
<label for="select${number}_3"><span>${question.choice3}</span></label>
<input type="radio" id="select${number}_4" name="select${number}" value="${number}_3" onclick="answerSelect2(this)">
<label for="select${number}_4"><span>${question.choice4}</span></label>
</div>
<div class="cbt__desc hide">${question.desc}</div>
</div>
`)
omr.push(`
<div class="omr">
<strong>${question.number}</strong>
<input type="radio" name="omr${number}" id="omr${number}_1" value="${number}_0" onclick="answerSelect(this)">
<label for="omr${number}_1"><span class="label-inner">1</span></label>
<input type="radio" name="omr${number}" id="omr${number}_2" value="${number}_1" onclick="answerSelect(this)">
<label for="omr${number}_2"><span class="label-inner">2</span></label>
<input type="radio" name="omr${number}" id="omr${number}_3" value="${number}_2" onclick="answerSelect(this)">
<label for="omr${number}_3"><span class="label-inner">3</span></label>
<input type="radio" name="omr${number}" id="omr${number}_4" value="${number}_3" onclick="answerSelect(this)">
<label for="omr${number}_4"><span class="label-inner">4</span></label>
</div>
`)
});
cbtQuiz.innerHTML = exam.join('');
cbtomr.innerHTML = omr.join('');
document.querySelectorAll(".cbt__question__desc").forEach(el => {
if(el.innerText == "undefined"){
el.style.display = "none";
}
});
};
문제 만들기 안에 문제의 설명이 없으면 undefined가 뜨는데 그것을 없애주기 위해 display = "none"을 해주었습니다.
//보기 체크
const answerSelect2 = (elem) => {
const answer = elem.value; //클릭 했을때 vlaue값을 가져옴
const answerNum = answer.split("_") //
const select = document.querySelectorAll(".cbt__omr .omr"); //전체 문항 수 100개를 가져온다
const label = select[answerNum[0]].querySelectorAll("input"); //보기 4개
label[answerNum[1]].checked = true;
const answerInputs = document.querySelectorAll(".cbt__selects input:checked");
cbtRest.innerHTML = questionLength - answerInputs.length;
}
//보기 체크2
const answerSelect = (elem) => {
const answer = elem.value;
const answerNum = answer.split("_") //
const select = document.querySelectorAll(".cbt__quiz .cbt"); //전체 문항 수 100개를 가져온다
const label = select[answerNum[0]].querySelectorAll("input"); //보기 4개
label[answerNum[1]].checked = true;
const answerInputs = document.querySelectorAll(".cbt__selects input:checked");
cbtRest.innerHTML = questionLength - answerInputs.length;
}
cbtSubmit.addEventListener("click", answerQuiz);
dataQuestion();
</script>
문제에 있는 정답 체크 들과 omr에 있는 정답 체크 들을 연동 시키기 위해 사용자가 체크를 하게 되면 체크된 정답의 값을 onclick의 answerSelect2을 통해 value를 가져 왔습니다. 그리고 그 value값 사이에있는 "_"를 구분자로하여 split 안에있는 숫자를 배열로 나워 주었습니다.그후 omr에 있는 전체 문항수를 가져오고 label 이라는 변수를 만들어 체크 되었을때 문제 밑에 있는 정답 4개중 하나를누르면 omr에 정답도 같은 숫자로 체크가 되게 할 수 있습니다.
밑에도 마찬가지로 omr을 눌렀을때 문제 밑에 있는 정답과 같은 번호로 체크가 되게 만들어 주었습니다.
그 후 남은 문제를 구하기 위해 체크한 값을 가져와 그값과 전체 문제 수를 빼고 선택자에게 다시 넣어주면 체크 할때 마다 남은 문자 수가 감소하는 것을 볼수 있습니다.