Lumpy Space Princess - Adventure Time

JAVASCRIPT

Quiz Effect 04 - 객관식 확인하기 유형에 대해서 알아보자

jongyung 2023. 3. 18. 09:46

“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90

객관식 확인하기 유형을 만들어 보겠습니다.

링크: 퀴즈 이펙트 04 (daanbi1345.github.io)

객관식 문제를 풀면, 정답인지 오답인지를 확인하고, 정답을 확인하는 버튼이 사라지고 해설이 나오게 했습니다.

 

body의 main부분과 script를 나눠서 보여드리겠습니다.

body의 main

<main id="main">
    <div class="quiz__wrap">
        <div class="quiz">
            <div class="quiz__header">
                <h2 class="quiz__title"></h2>                    
            </div>
            <div class="quiz__main">
                <div class="quiz__question"></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__choice">
                    <label for="choice1">
                        <input type="radio" id="choice1" name="choice" value="1">
                        <span></span>
                    </label>
                    <label for="choice2">
                        <input type="radio" id="choice2" name="choice" value="2">
                        <span></span>
                    </label>
                    <label for="choice3">
                        <input type="radio" id="choice3" name="choice" value="3">
                        <span></span>
                    </label>
                    <label for="choice4">
                        <input type="radio" id="choice4" name="choice" value="4">
                        <span></span>
                    </label>                        
                </div>
                <div class="quiz__answer">                        
                    <button class="confirm">정답 확인하기</button>                        
                </div>
                <div class="quiz__desc"></div>
            </div>
        </div>          
    </div>
</main>

지난 번과 같은 틀 안에 주관식 답을 적는 칸은 없애고, 객관식 선택 버튼을 추가했습니다.

div class="quiz__choice"로 묶어서 label for 태그에 input typs="radio" 태그를 넣었습니다.

 

label은 폼의 양식에 이름 붙이는 태그입니다. 주요 속성은 for입니다.

label의 for의 값과 양식의 id의 값이 같으면 연결됩니다.

label을 클릭하면, 연결된 양식에 입력할 수 있도록 하거나, 체크를 하거나, 체크를 해제합니다.

 

input 요소의 동작 방식은 type 특성에 따라 현격히 달라지므로, 각각의 유형은 별도의 참고 문서에서 더 자세히 확인할 수 있습니다.

특성을 지정하지 않은 경우, 기본값은 text입니다.
input 요소가 강력한 이유는 바로 다양한 속성 때문입니다. 그 중에서도, type 속성이 제일 중요합니다.

모든 input 요소는 유형에 상관하지 않고 HTMLInputElement (en-US) 인터페이스에 기반하므로, 기술적으로는 모든 input이 동일한 속성을 가집니다. 그러나 사실 대부분의 속성은 일부 유형에서만 효과를 보입니다.

게다가, 어떤 속성은 유형별로 그 영향이 달라집니다.

 

radio 유형의 input 요소는 보통 서로 관련된 옵션을 나타내는 라디오 버튼 콜렉션, 라디오 그룹에 사용합니다.

임의의 그룹 내에서는 동시에 하나의 라디오 버튼만 선택할 수 있습니다.

라디오 버튼은 흔히 원형으로 그려지며, 선택한 경우 속을 채우거나 강조 표시를 합니다.
오래된 라디오의 버튼과 비슷한 형태와 동작 방식을 가졌기에 라디오 버튼이라고 부릅니다.

script

<script>
    //선택자
    const quizWrap = document.querySelector(".quiz__wrap");
    const quizTitle = quizWrap.querySelector(".quiz__title");
    const quizQuestion = quizWrap.querySelector(".quiz__question");
    const quizChoice = quizWrap.querySelectorAll(".quiz__choice span");
    const quizSelect = quizWrap.querySelectorAll(".quiz__choice input");
    const quizDesc = quizWrap.querySelector(".quiz__desc");
    const quizConfirm = quizWrap.querySelector(".quiz__answer .confirm");//정답 버튼
    const dogWrap = quizWrap.querySelector(".dog__wrap");
    const quizAnswer = quizWrap.querySelector(".quiz__answer")

    //문제 정보
    const quizInfo = [
        {
            infoType : "웹디자인 기능사",
            infoTime : "2016년 4회",
            infoNumber : "1",
            infoQuestion : "다음 중 디자인의 기본 요소들로 옳은 것은?",
            infoChoice : ["선, 색채, 공간, 수량","점, 선, 면, 질감","시간, 수량, 구조, 공간","면, 구조, 공간, 수량"],
            infoAnswer : "2",
            infoDesc : "디자인의 기본 요소에는 점, 선, 면, 질감이 있습니다."
        }
    ]

    //문제 출력    
    function updateQUiz(){
        quizTitle.innerHTML = quizInfo[0].infoType +" "+ quizInfo[0].infoTime;
        quizQuestion.innerHTML = "<em>"+quizInfo[0].infoNumber+"</em>"+". "+quizInfo[0].infoQuestion;
        quizDesc.innerHTML = quizInfo[0].infoDesc;

		//for문으로
        // for(let i=0; i<quizChoice.length; i++){
        //     quizChoice[i].innerHTML = quizInfo[0].infoChoice[i];
        // }
		
        //forEach문으로
        // quizInfo[0].infoChoice.forEach(function(el,i){
        //     quizChoice[i].innerHTML = quizInfo[0].infoChoice[i];
        // });

		quizChoice.forEach(function(el,i){
            el.innerHTML = quizInfo[0].infoChoice[i];
        });
        
 		//해설 숨기기
        quizDesc.style.display = "none";
    }

    //정답 확인
    function answerQuiz(){
        //사용자가 선택한 input box(checked) == 문제 정답(quizinfo[0].infoAnswer)인지를 알아야 함.
        for(let i=0; i<quizChoice.length; i++){
            if(quizSelect[i].checked == true){  //사용자가 보기를 체크한 상태
                if(quizSelect[i].value == quizInfo[0].infoAnswer){
                    //정답
                    dogWrap.classList.add("like");

                } else {
                    //오답
                    dogWrap.classList.add("dislike");
                }
                //해설 보이기
                quizDesc.style.display = "block";

                //정답 버튼 숨기기
                quizAnswer.style.display = "none";
            } 
        }
    }

    quizConfirm.addEventListener("click", answerQuiz); //정답 클릭

    updateQUiz();   //문제 출력
</script>

선택자를 querySelector와 querySelectorAll로 만들었습니다.

 

querySelector()는 Element 인터페이스의 메소드 입니다. 

querySelector() 메소드는 CSS 선택자에 매치되는 하나 이상의 element 중 첫 번째 항목을 반환해줍니다. 
querySelector() 메소드는 document 객체나 모든 Element 객체에서 사용 가능합니다. 

querySelector() 외에도 querySelectorAll() 메소드도 사용할 수 있는데 이는 CSS 선택자나 CSS 선택자 그룹에 매치되는 모든 element를 반환합니다.

 

문제 정보는 배열안에 객체를 넣은 형태로 만들었습니다. 

키와 값을 정해서 불러오기 쉽게 하기 위해서 입니다.

 

Element 속성 innerHTML 은 요소 내에 포함 된 HTML 또는 XML 마크업을 가져오거나 설정합니다.
element.innerText 속성은 element 안의 text 값들만을 가져오지만, element.innerHTML 속성은 innerText와는 달리 element 안의 HTML이나 XML을 가져옵니다.

 

문제 번호는 css에서 다음과 같이 em태그에 색을 넣어줬습니다.

.quiz__question em {
    color: #ff3737;
}

반복되는 식들은 for문이나 forEach문을 이용해서 줄일 수 있습니다.

객관식 4개의 식은 동일하므로 for문과 forEach문을 이용해서 표현해보겠습니다.

 

  • for(let i=0; i<quizChoice.length; i++){
    quizChoice[i].innerHTML = quizInfo[0].infoChoice[i];
    };
  • quizInfo[0].infoChoice.forEach(function(el,i){
    quizChoice[i].innerHTML = quizInfo[0].infoChoice[i];
    });
  • quizChoice.forEach(function(el,i){
    el.innerHTML = quizInfo[0]infoChoice[i];
    });

해설 부분은 .style.display: "none";으로 숨겨놓았습니다.

 

if(quizSelect[i].checked == true)식은 객관식을 선택하면 true로 값을 반환해주고, 아니면 false로 반환합니다.

이 if식에 또 if(quizSelect[i].value == quizInfo[0].infoAnswer)식을 넣었습니다.

선택한 닶이 정답과 같으면 true 값을 출력하고, 아니면 false 값을 출력합니다.

 

전과 마찬가지로 정답이면 웃는 강아지가 나오고, 오답이면 우는 강아지가 나오도록 설정했습니다.