Leeyanggoo
[JS] 퀴즈 이펙트 만들기3!! 주관식이 여러 개!? 본문
더 많아진 댕댕이 ㄷㄷ;
지난번에는 주관식 문제가 1개 있는 퀴즈 유형을 알아봤습니다!
선택자와 메서드, 속성을 이용하면 다양한 이펙트를 만들 수 있다고 말씀드렸습니다.
그렇다면 이번엔 주관식이 여러 개 있는 퀴즈는 어떻게 만들어야 할까요? 🧐
선택자 querySelectorAll()을 잘 이용하자!
<main id="main">
<div class="quiz__wrap">
<div class="quiz">
<div class="quiz__header">
<h2 class="quiz__title"></h2>
</div>
<div class="quiz__mian">
<div class="quiz__question">
<em></em>. <span></span>
</div>
<div class="quiz__view">
<div class="dog__wrap">
<div class="true">정답입니다!</div>
<div class="false">땡!</div>
<div class="card-container">
<div class="dog">
<div class="head">
<div class="ears"></div>
<div class="face"></div>
<div class="eyes">
<div class="teardrop"></div>
</div>
<div class="nose"></div>
<div class="mouth">
<div class="tongue"></div>
</div>
<div class="chin"></div>
</div>
<div class="body">
<div class="tail"></div>
<div class="legs"></div>
</div>
</div>
</div>
</div>
</div>
<div class="quiz__answer">
<input class="input" type="text" placeholder="정답을 입력해주세요.">
<button class="confirm">정답 확인하기</button>
<div class="result"></div>
</div>
<div class="quiz__desc">설명</div>
</div>
</div>
<div class="quiz">
<div class="quiz__header">
<h2 class="quiz__title"></h2>
</div>
<div class="quiz__mian">
<div class="quiz__question">
<em></em>. <span></span>
</div>
<div class="quiz__view">
<div class="dog__wrap">
<div class="true">정답입니다!</div>
<div class="false">땡!</div>
<div class="card-container">
<div class="dog">
<div class="head">
<div class="ears"></div>
<div class="face"></div>
<div class="eyes">
<div class="teardrop"></div>
</div>
<div class="nose"></div>
<div class="mouth">
<div class="tongue"></div>
</div>
<div class="chin"></div>
</div>
<div class="body">
<div class="tail"></div>
<div class="legs"></div>
</div>
</div>
</div>
</div>
</div>
<div class="quiz__answer">
<input class="input" type="text" placeholder="정답을 입력해주세요.">
<button class="confirm">정답 확인하기</button>
<div class="result"></div>
</div>
<div class="quiz__desc">설명</div>
</div>
</div>
<div class="quiz">
<div class="quiz__header">
<h2 class="quiz__title"></h2>
</div>
<div class="quiz__mian">
<div class="quiz__question">
<em></em>. <span></span>
</div>
<div class="quiz__view">
<div class="dog__wrap">
<div class="true">정답입니다!</div>
<div class="false">땡!</div>
<div class="card-container">
<div class="dog">
<div class="head">
<div class="ears"></div>
<div class="face"></div>
<div class="eyes">
<div class="teardrop"></div>
</div>
<div class="nose"></div>
<div class="mouth">
<div class="tongue"></div>
</div>
<div class="chin"></div>
</div>
<div class="body">
<div class="tail"></div>
<div class="legs"></div>
</div>
</div>
</div>
</div>
</div>
<div class="quiz__answer">
<input class="input" type="text" placeholder="정답을 입력해주세요.">
<button class="confirm">정답 확인하기</button>
<div class="result"></div>
</div>
</div>
<div class="quiz__desc">설명</div>
</div>
</div>
</main>
이 길게 늘어진 HTML 코드가 보이십니까..?
문제가 3개로 늘었으니 그에 따라 <div class="quiz"> 박스도 3배 늘었습니다.
이렇게 HTML 요소가 여러 개 있고 이를 선택해야 할 때는 "querySelectorAll()"을 이용해야 합니다!
//선택자
const quizWrap = document.querySelector(".quiz__wrap");
const quizTitle = quizWrap.querySelectorAll(".quiz__title") //시험 종목+시간
const quizQuestionNum = quizWrap.querySelectorAll(".quiz__question em") //문제 번호
const quizQuestion = quizWrap.querySelectorAll(".quiz__question span"); //문제 질문
const quizAnswerResult = quizWrap.querySelectorAll(".quiz__answer .result"); //문제 정답
const quizDesc = quizWrap.querySelectorAll(".quiz__desc") //문제 해설
const quizAnswerConfirm = quizWrap.querySelectorAll(".quiz__answer .confirm"); //정답 버튼
const dogWrap = quizWrap.querySelectorAll(".dog__wrap"); //갱얼쥐
const quizAnswerInput = quizWrap.querySelectorAll(".quiz__answer .input"); //input 박스
스크립트 코드를 보게 되면 이렇게 복수의 HTML 요소에는 "querySelectAll()"을 이용하게 됩니다.
"querySelectAll()"은 CSS 선택자를 사용하여 HTML 문서에서 모든 일치하는 요소를 선택합니다.
예를 들어 상수 "quizTitle"은 HTML class 중 "quiz__title"을 모두 선택한 것이라고 할 수 있습니다.
이렇게 선택을 했다면 어떻게 요소에 우리가 원하는 정보를 입력해야 할까요?
//문제 정보
const quizInfo = [
{
infoType: "정보처리기능사",
infoTime: "2011년 4회",
infoNumber: "1",
infoQuestion: "주파수분할 다중화 방식에서 각 채널 간 간섭을 막기 위해서 일종의 완충지역 역할을 하는 것은?",
infoAnswer: "가드밴드",
infoDesc: "가드밴드(Guard Band)는 채널간의 간섭을 방지하기 위해 설정합니다."
},
{
infoType: "정보처리기능사",
infoTime: "2011년 4회",
infoNumber: "2",
infoQuestion: "사용자의 명령으로 시스템이 수행되고 그에 따른 결과를 나타내 주는 대화식 운영체제는 무엇인가?",
infoAnswer: "UNIX",
infoDesc: "UNIX는 사용자의 명령으로 시스템이 수행되고 그에 따른 결과를 나타내 주는 대화식 운영체제입니다."
},
{
infoType: "정보처리기능사",
infoTime: "2011년 4회",
infoNumber: "3",
infoQuestion: "프로세스들이 서로 다른 프로세스가 차지하고 있는 자원을 무한정 기다려 시스템이 멈춘것 처럼 보이는 상태를 무엇이라 하는가?",
infoAnswer: "교착상태",
infoDesc: "교착상태(Deadlock)는 2개 이상의 프로세스들이 서로 다른 프로세스가 차지하고 있는 자원을 무한정 기다려 시스템이 멈춘것 처럼 보이는 상태를 말합니다."
}
];
우리가 원하는 정보는 문제에 대한 정보겠죠?
하지만 문제도 3개로 늘어남에 따라 우리는 "quizInfo"라는 상수를 만들어서 저장했습니다.
"quizInfo = [" 이렇게 대괄호로 먼저 시작을 했다면 배열이라는 뜻이겠죠?
그렇다면 우리가 넣은 배열 하나하나는 1문제의 정보라고 할 수 있습니다.
또한 문제는 출시년도나 문제번호, 문제 등 여러 정보를 담고 있기 각 분류를 key로 설정해서 객체로 만들었습니다.
//시험 종목
quizTitle[0].textContent = quizInfo[0].infoType;
quizTitle[1].textContent = quizInfo[1].infoType;
quizTitle[2].textContent = quizInfo[2].infoType;
"querySelectAll()"을 사용했기 때문에 하나하나의 개별 HTML 요소를 선택하기 위해선 배열 형식을 사용해야 합니다.
근데 이렇게 많아진 문제... 일일이 모두 지정을 한다면 너무 오래 걸리고 코드도 복잡해지지 않을까요?
이럴 때 배열을 "반복하는" 기능을 이용한다면 쉽게 쓸 수 있지 않을까요!?
계산을 반복하는 자바스크립트.. 이거 어디서 본 건데...?
for(let i=0; i<quizInfo.length; i++){
quizTitle[i].innerHTML = quizInfo[i].infoType + " " + quizInfo[i].infoTime;
quizQuestionNum[i].textContent = quizInfo[i].infoNumber;
quizQuestion[i].textContent = quizInfo[i].infoQuestion;
quizAnswerResult[i].textContent = quizInfo[i].infoAnswer;
quizDesc[i].textContent = quizInfo[i].infoDesc;
}
짠!
"querySelectAll()"로 선택한 요소들은 하나씩 배열의 데이터처럼 순서를 갖는 걸 이용한 코드입니다.
이렇게 for문의 변수 i를 배열의 인덱스처럼 활용한다면 나머지 문제의 데이터 입력 부분도 아주 쉽게 할 수 있습니다!!
quizInfo.forEach(function(e, i){
quizAnswerResult[i].style.display = "none";
quizDesc[i].style.display = "none";
});
//정답 확인
quizAnswerConfirm.forEach(function(btn, num){
btn.addEventListener("click", function(){
//사용자 정답
const userAnswer = quizAnswerInput[num].value.trim();
quizAnswerConfirm[num].style.display = "none"; //정답 확인 숨기기
quizAnswerInput[num].style.display = "none"; //인풋 버튼 숨기기
quizAnswerResult[num].style.display = "block"; //정답 보이기
quizDesc[num].style.display = "block" //해설 보이기
//사용자 정답 == 문제 정답
if(userAnswer == quizInfo[num].infoAnswer){
dogWrap[num].classList.add("like");
} else {
dogWrap[num].classList.add("dislike");
}
});
});
우리는 for문뿐만 아니라 forEach문을 이용해도 배열의 인덱스를 추출하고 넣을 수 있습니다.
forEach(요소, 인덱스, 배열)의 순서로 데이터를 불러오기 때문에 반드시 순서를 지켜서 넣어야 합니다!
😮💨 이전 포스팅 보러 가기
😮💨 이번 예제 보러 가기
😮💨 codepen design by David López