Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

Leeyanggoo

[JS] 퀴즈 이펙트 만들기3!! 주관식이 여러 개!? 본문

2023/JavaScript

[JS] 퀴즈 이펙트 만들기3!! 주관식이 여러 개!?

Leeyanggoo 2023. 3. 14. 14:10

더 많아진 댕댕이 ㄷㄷ;

 

지난번에는 주관식 문제가 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