Lumpy Space Princess - Adventure Time

JAVASCRIPT

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

jongyung 2023. 3. 9. 13:17

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

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

지난번 게시글에 이어서 다른 부분을 추가적으로 만들었습니다.

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

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>퀴즈 이펙트 02</title>

    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/quiz.css">
</head>
<body>
    <header id="header">
        <h1><a href="../javascript14.html"> Quiz </a> <em>주관식 확인하기 유형</em></h1>
        <ul>
            <li><a href="quizEffect01.html">1</a></li>
            <li class="active"><a href="quizEffect02.html">2</a></li>
        </ul>
    </header>
    <!-- header -->

    <main id="main">
        <div class="quiz__wrap">
            <div class="quiz">
                <div class="quiz__header">
                    <h2 class="quiz__title"> <span></span> <em></em></h2>                    
                </div>
                <div class="quiz__main">
                    <div class="quiz__question">
                        <em></em>. <span></span>
                    </div>
                    <div class="quiz__view">
                        <div class="dog__wrap">
                            <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" placeholder="정답을 적어주세요!">
                        <button class="confirm">정답 확인하기</button>                        
                        <div class="result">연변대비</div>
                    </div>
                </div>
                <div class="quiz__footer">
                    <div class="quiz__desc">설명</div>
                </div>
            </div>
        </div>
    </main>
    <!-- main -->

    <footer id="footer">
        <a href="mailto:daanbi1345@gmail.com">daanbi1345@gmail.com</a>
    </footer>
    <!-- footer -->

    <script>
        //선택자
        const quizWrap = document.querySelector(".quiz__wrap");
        const quizTitle = quizWrap.querySelector(".quiz__title span"); // quizWrap는 wrap안에서 찾으라는 의미
        const quizTime = quizWrap.querySelector(".quiz__title em");
        const quizQuestionNum = quizWrap.querySelector(".quiz__question em");
        const quizQuestion = quizWrap.querySelector(".quiz__question span");
        const quizDesc = quizWrap.querySelector(".quiz__desc");

        //문제 정보
        const infoType = "정보처리 기능사";
        const infoTime = "2011년 5회";
        const infoNumber = "2";
        const infoQuestion = "프레젠테이션에서 화면 전체를 전환하는 단위를 의미하는 것을?";
        const infoAnswer = "슬라이드"; //정답, 전역변수
        const infoDesc = "슬라이드는 프레젠테이션의 화면 전체를 말하고 개체는 화면을 구성하는 개개의 요소를 말한다.";
        const quizAnswerConfirm = quizWrap.querySelector(".quiz__answer .confirm");//버튼
        const quizAnswerResult = quizWrap.querySelector(".quiz__answer .result");
        const quizAnswerInput = quizWrap.querySelector(".input");
        const dogWrap = quizWrap.querySelector(".dog__wrap");
        const quizFooter = quizWrap.querySelector(".quiz__footer");

        //문제 출력
        quizTitle.textContent = infoType; //innerText와 textContent는 큰 차이가 없고 같은 역할을 함
        quizTime.textContent = infoTime;
        quizQuestionNum.textContent = infoNumber;
        quizQuestion.textContent = infoQuestion;
        quizDesc.textContent = infoDesc;
        quizAnswerResult.textContent = infoAnswer;

        //정답 & 해설 숨기기
        quizAnswerResult.style.display = "none";
        quizFooter.style.display = "none";       

        //사용자 정답
        quizAnswerConfirm.addEventListener("click", function(){
            const userAnswer = quizAnswerInput.value.trim(); //지역변수, 사용자가 쓴 값을 변수에 저장함
            quizAnswerInput.style.display  = "none"; //인풋 박스 숨김
            quizAnswerConfirm.style.display = "none"; //정답 확인 버튼 숨김
            quizAnswerResult.style.display = "block"; //정답 보이기
            quizFooter.style.display = "block"; //해설 보이기
            
            if(infoAnswer == userAnswer){
                alert("정답입니다.")//정답 뒤에 빈 칸도 인식해서 오답으로 처리되는 버그가 있음 > trim()메서드를 쓰면 뒤에 것들을 잘라줌
                dogWrap.classList.add("like");               
            } else {
                alert("오답입니다.")                
                dogWrap.classList.add("dislike");    
            }
        });

               
    </script>
</body>
</html>

형식은 지난 번과 같습니다.

 

새로 쓴 식은 textContenttrim()이 있습니다.

 

먼저 textContent에 대해서 설명하겠습니다.

지난번에 쓴 innerText 와의 차이점은 크지 않지만, 어떤 식으로 쓰이는 지를 알아보기 위해서 비교해보겠습니다.

  • innerText
    : innerText는 마크업 언어가 적용된 상태로 읽어옵니다. 즉 태그와 마크업 언어와 같은 태그값은 불러들이지 않습니다. 또한 사용자가 보이는 상태 style등 마크업 언어가 적용된 상태입니다.
    따라서 사용자에게 보이지 않는 값들은 불러들이지 않습니다.
    즉 display : none; 한 값들은 불러들이지 않습니다.
  • textContent 
    : 마크업 태그를 제외한 모든 문자열을 읽고 변경할 수 있습니다.
    innerHTML은 textContent에 비해서 매번 스타일링까지 적용해서 헤비한 메소드입니다.
    따라서 textContent를 이용하는 것이 성능적으로 좋은 퍼포먼스를 보입니다.

innerText와 다른 점은, innerText는 사용자에게 보이지 않는 텍스트 값은 가져오지 않지만,
textContent는 마크업 태그를 제외한 텍스트라면 모두 불러들일 수 있습니다. 

 

글로만 설명하기에는 헷갈리기 쉬우니 예시로 화면을 캡쳐해서 보여드리면서 설명하겠습니다.

 

그리고 이번에는 정답을 기입하는 칸을 만들고, 정답을 확인하여 맞으면 "정답입니다."와 오답을 적으면 "오답입니다."가 알림창으로 뜨고, 정답 기입 칸 밑에 tip이 적힌 공간이 새로 생기는 방식으로 만들었습니다. 

메인 화면

메인 화면

<input>을 이용하면, 평범하게 글자나 텍스트칸을 넣을 수있는 공간이 생깁니다.

 

placeholder 속성은 input 요소와 textarea 요소에 알맞은 힌트를 제공하는 목적으로 사용됩니다.

이러한 힌트는 사용자가 입력상자에 데이터를 입력하는데 도움을 줍니다.

 

사용 방법은 <input type="text" placeholder="내용 입력.">이렇게 써줄 수가 있습니다.

const quizAnswerInput = quizWrap.querySelector(".input");

<input class="input" placeholder="정답을 적어주세요!"> 

선택자를 quizAnswerInput으로 정해주고, input class를 input으로 지정해서 써주면, 위와 같이 출력됩니다.

정답 입력 중인 화면

정답 입력 중인 화면

이제 정답을 맞추는 기능을 보여드리겠습니다.

답이 맞으면, "정답입니다." 창이 뜨게 할 겁니다.

정답입니다 창

창을 뜨게 하는 방법은 간단합니다.

alert를 써서 입력해주면 됩니다.(alert("정답입니다."))

quizAnswerInput.style.display  = "none"; //인풋 박스 숨김
quizAnswerConfirm.style.display = "none"; //정답 확인 버튼 숨김
quizAnswerResult.style.display = "block"; //정답 보이기
quizFooter.style.display = "block"; //해설 보이기
            
 if(infoAnswer == userAnswer){
      alert("정답입니다.")

      //정답 뒤에 빈 칸도 인식해서 오답으로 처리되는 버그가 있음 > trim()메서드를 쓰면 뒤에 것들을 잘라줌
       dogWrap.classList.add("like");               
 }

이 부분을 보면 알기 쉽습니다.

여기에서 쓰인 trim()메서드는 문자열 앞뒤 공백을 제거합니다. 문자열 내부의 공백은 제거 불가능합니다. 

그렇기 때문에 정답을 입력하면서 앞이나 뒤에 빈 공백이 생겨도 답으로 인식하게 할 수 있습니다.

정답 입력 후의 화면

정답을 입력한 화면

인풋 박스와 정답 확인 버튼을 숨기고(none) 정답과 tip을 보이게(block) 한 화면입니다. 

강아지가 웃는 모습을 설정해주기 위해서 미리 설정해둔 값을 불러왔습니다. (dogWrap.classList.add("Like:);)

오답 입력 중인 화면

오답 입력 하는 중인 화면
오답입니다 창

"몰라"라는 오답을 입력해보겠습니다.

이 창은 alert("오답입니다.")

오답 입력 후의 화면

오답을 입력한 화면

오답을 입력했을 때에도 같은 방식으로 처리해줬습니다. 

if(infoAnswer == userAnswer){
    alert("정답입니다.")
    dogWrap.classList.add("like");
} else {
    alert("오답입니다.")
    dogWrap.classList.add("dislike");
}

if를 써서 입력한 값이 const infoAnswer = "슬라이드";

즉 정답이자 전역변수인 값과 같으면 "정답입니다."가 나오면서, 웃는 얼굴(like)의 설정값이 나오도록 했고,

같지 않으면 "오답입니다."가 나오면서, 우는 얼굴(dislike)의 설정값이 나오도록 했습니다.