html

quiz 유형 사이트 만들기 - 05

grovy 2023. 3. 25. 14:34
728x90

퀴즈퀴즈 사이트 만들기 !  ( 객관식유형 * 6문제 한번에 만들기  )

이번엔 객관식 퀴즈 6문제가 있는 사이트를 만들어볼까해요 

 전체 소스는 요기 

 

객관식 유형을 만들기위해 해야할일을 아래 소스로 살펴볼게요

<div class="quiz__choice">
    <label for="choice1">
        <input type="radio" id="choice1" name="choice" value="1">
        <span class="choice"></span>
    </label>
    <label for="choice2">
        <input type="radio" id="choice2" name="choice" value="2">
        <span class="choice"></span>
    </label>
    <label for="choice3">
        <input type="radio" id="choice3" name="choice" value="3">
        <span class="choice"></span>
    </label>
    <label for="choice4">
        <input type="radio" id="choice4" name="choice" value="4">
        <span class="choice"></span>
    </label>
</div>

위처럼 코딩을 해야했는데 6번 반복하기엔 너무 코드가 복잡해지죠 ? 

 

그래서 

아래처럼 값을 가진 

quizInfo 배열에 obj형태로 6문제를 만들었어요 ! 

const quizInfo = [
    {  
        infoType:"웹디자인기능사",
        infoTime:"2012년 2회",
        infoNumber:"20120201",
        infoQuestion: "입체에 대한 설명으로 옳지 않은 것은?",
        infoChoice: {
             1: "소극적 입체는 현실적 형, 확실히 지각되는 형을 말한다." ,
             2: "입체는 면이 이동한 자취이다.",
             3: "두 면과 각도를 가진 방향으로 이동하거나 면의 회전에 의해 생긴다.",
             4: "순수한 입체는 구, 원통, 육면체 등과 같은 형이다"
        },
        infoAnswer: "1",
        infoDesc: "입체는 3차원 함수를 생각하면 쉬워요 "
    },{
    ... },{
    ... },{
    ... },{
    ... },{
    ... }
    //6개를 만들었어요 ! 
]

문제는 만들었고 이제 

문제를 6번 반복하며 문제 + body 소스를 

exam이라는 배열을 생성한곳에 넣어줄거에요 ! 

const exam = [];
quizInfo.forEach((question, num)=>{
    exam.push(`
                <div class="quiz">
                    <div class="quiz__header">
                        <h2 class="quiz__title">${question.infoType} ${question.infoTime}</h2>
                    </div>
                    <div class="quiz__main">
                        <div class="quiz__question">
                            <em>${num+1}</em>. ${question.infoQuestion}
                        </div>
                        <div class="quiz__view">
                            <div class="wrapper">
                                <div class="dog__wrap ">
                                    ...... 4번 참조 강아지 div구조입니다.
                                </div>
                            </div>
                        </div>
                        <div class="quiz__choice">
                            <label for="choice1${num}">
                                <input type="radio" id="choice1${num}" name="choice${num}" value="1">
                                <span class="choice">${question.infoChoice[1]}</span>
                            </label> 
                            .......... 4번 참조 객관식보기 부분입니다.
                            <label for="choice4${num}">
                                <input type="radio" id="choice4${num}" name="choice${num}" value="4">
                                <span class="choice">${question.infoChoice[4]}</span>
                            </label>
                        </div>
                        <div class="quiz__desc">
                            정답은 <em>${question.infoAnswer}</em>번입니다
                            <br>${question.infoDesc}
                        </div>
                    </div>
                </div>
				quizWrap.innerHTML = exam.join('');
            `);
});
quizWrap.innerHTML = exam.join('');

quizWrap.innerHTML = exam.join(''); 이 구문으로 

exam[]을 화면에 추가시켜주면 문제 출력부분은 끝이에요 

quiz__wrap 아래 문제가 들어가요 ~~

<main id="main">
        <div class="quiz__wrap">
        
        <!--   <div class="quiz">
                           
        </div> -->
        <!-- <div class="quiz__check">정답 확인하기</div> -->
        </div>
    </main>

 

객관식 답안을 체크하는 로직 ! 

const answerQuiz = () =>{
    const quizChoices = document.querySelectorAll(".quiz__choice");
	//정답 초기화
	quizScore = 0;

    quizInfo.forEach((question, num)=>{
        const userSelector = `input[name=choice${num}]:checked`;
        const quizSelectorWrap = quizChoices[num];
        const userAnswer = (quizSelectorWrap.querySelector(userSelector)||{}).value;
        const dogWrap =quizWrap.querySelectorAll(".dog__wrap");                       

        if(userAnswer == question.infoAnswer){
            dogWrap[num].classList.remove("dislike");
            dogWrap[num].classList.add("like");
            quizScore++;
        }else{
            dogWrap[num].classList.remove("like");
            dogWrap[num].classList.add("dislike");
        }   
        document.querySelectorAll(".quiz__desc").forEach(el=> el.style.display="block");
    });
    document.querySelector(".quiz__info").innerHTML=Math.ceil((quizScore/quizInfo.length*100))+"점";
}
// 정답클릭할때 answerQuiz 함수가 실행되도록 설정 
document.querySelector(".quiz__check").addEventListener("click", answerQuiz);

addEventListener 함수를 이용해서 click 하였을때 작동하도록 했어요

forEach문을 이용하여 한번에 모든 문제의 값을 체점하도록 했구요 

 

userSelector = `input[name=choice${num}]:checked`; 구문을 통해 유저가 체크한 항목을을 가져오구 

const userAnswer = (quizSelectorWrap.querySelector(userSelector)||{}).value;

구문을 통해서 객관식 문제의 체크한 값을 가져와요 !

그 값을 비교해서

맞을경우 강아지가 웃고 틀릴경우 강아지가 울게 만들었어요 ! 

 

(quiz.querySelector(userSelector)||{}) 에서 ||{} 은 값이 없을경우 정답체크할때 에러가 나기 때문에 넣었어요 

 

😝😝😝 위 레이아웃 만들면서 햇갈리는 javascript를 정리 해봤어요 ! 

innerHTML textContent, innerText 과 같은동작을 하지만
style tag를 쓸수 있어요
(quizQuestion.innerHTML= "<em>"+quizInfo[0].infoNumber+"</em>)
array.forEach
(element, number =>{  });
forEach문 반환하는 값이 있는 함수에요 
array순서대로 반환하며
element(array[0]번째부터 끝까지 array의 값을 반환)
number(array[0]번째 부터 끝까지 반복하며 배열의순서를 반환해요=> ex 0, 1,2)
querySelector() document.querySelector("div.user-panel.main input[name=login]"); 

위처럼 선택자를 사용할 수 있습니다.
예제의 결과는 클래스가 "user-panel main"인
<div>(<div class="user-panel main">)안의,
이름이 "login"인 <input> 중 첫 번째 요소입니다.
위처럼 강력하게 선택을 할수도 있다는걸 알았어요 !