필요없는 목록/CSS 스타일

(보충)CBT퀴즈 따라 만들기

비밀안 2023. 4. 4. 18:38
클릭

버튼을 클릭하면 명언이 나와요

-

이름이 나와요

보충 작업 완성물

최종 완성된 사이트

 

어제가 지나고 화가 가라 앉으니간 어느정도 따라가기 시작하네요.

HTML코드

<body>
<header id="header">
    <h1>
        <a href="../assets/javascript/javascript14.html">Quiz</a> <em>객관식 확인 CBT 유형</em>
    </h1>
    <ul>
        <li><a href="quizEffect01.html">1</a></li>
        <li><a href="quizEffect02.html">2</a></li>
        <li><a href="quizEffect03.html">3</a></li>
        <li><a href="quizEffect04.html">4</a></li>
        <li><a href="quizEffect05.html">5</a></li>
        <li><a href="quizEffect06.html">6</a></li>
        <li class="active"><a href="quizEffect07.html">7</a></li>
    </ul>
</header>
<!-- testAnGyonam -->
<!-- //header -->


<!-- 
    문제 정보
    (면제) 정보처리기능사 10년 7월 11일 4회 [기능사 면제]
    (해야해) 웹디자인기능사 필기 기출문제 및 CBT 2011년 02월 13일(1회) 정리(60번까지) 
-->
<main id="main">
    <div class="container">

        <div class="quiz__wrap__cbt">
           <!-- 답안지 -->
           <div class="cbt__header">
               <h2>2011년 1회 웹디자인기능사 기출문제</h2>

               <div class="cbt__ts">
                   <div class="cbt__time">
                       <!-- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
                           <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" />
                       </svg>             -->
                       남은 시간 59분 10초
                   </div>
                   <div class="cbt__sumit">답안지 제출하기</div>
               </div>
           </div>
           <div class="cbt__conts">
              <div class="container">

                  <div class="cbt__quiz">
                      <!-- <div class="cbt"> 
                          <div class="cbt__question"><span>1.</span>객체지향 프로그램에서 데이터를 추상화하는 단위는?</div>
                          <div class="cbt__question__img"><img src="img2/2020-02-01.jpg" alt="정보처리기능사 1회 문제?"></div>
                          <div class="cbt__selects">
                                  <input type="radio" id="select1" >
                                  <label for="select1"><span>클래스</span></label>
                                  <input type="radio" id="select2">
                                  <label for="select2"><span>메소드</span></label>
                                  <input type="radio" id="select3" >
                                  <label for="select3"><span>상속</span></label>
                                  <input type="radio" id="select4" >
                                  <label for="select4"><span>메시지</span></label>
                          </div>
                          <div class="cbt__desc">객체지향언어는 이다.</div>
                          <div class="cbt__keyword">객체지향언어</div>
                      </div>
                      <div class="cbt">
                          <div class="cbt__question">2.다음 빈칸을 채우시오</div>
                          <div class="cbt__question__desc">객체지향 언어는 ______이다.</div>
                          <div class="cbt__selects">
                              <input type="radio" id="select1" >
                              <label for="select1"><span>클래스</span></label>
                              <input type="radio" id="select2">
                              <label for="select2"><span>메소드</span></label>
                              <input type="radio" id="select3" >
                              <label for="select3"><span>상속</span></label>
                              <input type="radio" id="select4" >
                              <label for="select4"><span>메시지</span></label>
                          </div>
                          <div class="cbt__desc">객체지향언어는 이다.</div>
                          <div class="cbt__keyword">객체지향언어</div>
                      </div>
                      <div class="cbt">
                          <div class="cbt__question">객체지향 프로그램에서 데이터를 추상화하는 단위는?</div>
                          <div class="cbt__question__img">여기는 이미지가 있으면 들어옵니다.</div>
                          <div class="cbt__question__desc">객체지향 언어는 ______이다.</div>
                          <div class="cbt__selects">
                              <div>
                                  <input type="radio" id="select1" >
                                  <label for="select1">클래스</label>
                              </div>
                              <div>
                                  <input type="radio" id="select2">
                                  <label for="select2">메소드</label>
                              </div>
                              <div>
                                  <input type="radio" id="select3" >
                                  <label for="select3">상속</label>
                              </div>
                              <div>
                                  <input type="radio" id="select4" >
                                  <label for="select4">메시지</label>
                              </div>
                          </div>
                          <div class="cbt__desc">객체지향언어는 이다.</div>
                          <div class="cbt__keyword">객체지향언어</div>
                      </div>
                      <div class="cbt">
                          <div class="cbt__question">객체지향 프로그램에서 데이터를 추상화하는 단위는?</div>
                          <div class="cbt__question__img">여기는 이미지가 있으면 들어옵니다.</div>
                          <div class="cbt__question__desc">객체지향 언어는 ______이다.</div>
                          <div class="cbt__selects">
                              <div>
                                  <input type="radio" id="select1" >
                                  <label for="select1">클래스</label>
                              </div>
                              <div>
                                  <input type="radio" id="select2">
                                  <label for="select2">메소드</label>
                              </div>
                              <div>
                                  <input type="radio" id="select3" >
                                  <label for="select3">상속</label>
                              </div>
                              <div>
                                  <input type="radio" id="select4" >
                                  <label for="select4">메시지</label>
                              </div>
                          </div>
                          <div class="cbt__desc">객체지향언어는 이다.</div>
                          <div class="cbt__keyword">객체지향언어</div>
                      </div> -->
              </div>
               </div>

               <!-- 남은 시간 59분 10초
            </div>
            <div class="cbt__sumit">답안지 제출하기</div>
        </div>
        <div>
             <div class="cbt__title">수험자 : <em></em></div>
             <div class="cbt__score">
                 <span>전체 문제수 : <em>60</em>문항</span>
                 <span>남은 문제수 : <em>59</em>문항</span>
             </div>
        </div> -->

           </div>
           <div class="cbt__aside">

               <div class="cbt__time2">
                 <div class="cbt__box">
                     <div class="time2__box">
                         <em class="time2__img"></em><span>59분 10초</span>
                     </div>
                     <div class="submit__box">
                         <strong class="submit__img"></strong><buttopn class="submit">답안지 제출하기</button>
                     </div>
                 </div>
               </div>
               <div class="cbt__info">
                   <div>

                   </div>
                    <div>
                        <div class="title">수험자 : 안교남</div>
                        <div class="score">
                            <span class="">전체 문제수 : <em class="cbt__length">0</em></span>
                            <span class="">남은 문제수 : <em class="cbt__rest">0</em></span>
                        </div>
                    </div>
               </div>
               <div class="cbt__omr2">
                   <div class="cbt__omr">
                       <div class="cbt__omr2">
                           <div class="omr">
                               <strong>1</strong>
                               <input type="radio" id="omr0_1">
                               <label for="omr0_1">
                                   <span class="label-inner">1</span>
                               </label>
                               <input type="radio" id="omr0_2">
                               <label for="omr0_2">
                                   <span class="label-inner">2</span>
                               </label>
                               <input type="radio" id="omr0_3">
                               <label for="omr0_3">
                                   <span class="label-inner">3</span>
                               </label>
                               <input type="radio" id="omr0_4">
                               <label for="omr0_4">
                                   <span class="label-inner">4</span>
                               </label>
                           </div>
                       </div>
                    </div>
               </div>
            </div>
            <div class="cbt__start">
                <div class="cbt__modall">
                    <div class="cbt__star">
                        <div class="cbt__box">
                            <h2>필기 시험 공부하기</h2>

                            <div class="cbtTime__box">
                                <select name="cbtTime" id="cbtTime">
                                    <option value="gineungsaJC2005_02">정보처리기능사 2005년 2회</option>
                                    <option value="gineungsaJC2005_04">정보처리기능사 2005년 4회</option>
                                    <option value="gineungsaJC2005_05">정보처리기능사 2005년 5회</option>
                                    <option value="gineungsaJC2006_01">정보처리기능사 2006년 1회</option>
                                    <option value="gineungsaJC2006_02">정보처리기능사 2006년 2회</option>
                                    <option value="gineungsaJC2006_03">정보처리기능사 2006년 3회</option>
                                    <option value="gineungsaJC2006_05">정보처리기능사 2006년 5회</option>
                                    <option value="gineungsaJC2007_01">정보처리기능사 2007년 1회</option>
                                    <option value="gineungsaJC2007_02">정보처리기능사 2007년 2회</option>
                                    <option value="gineungsaJC2007_05">정보처리기능사 2007년 5회</option>
                                    <option value="gineungsaJC2008_01">정보처리기능사 2008년 1회</option>
                                    <option value="gineungsaJC2008_02">정보처리기능사 2008년 2회</option>
                                    <option value="gineungsaJC2008_04">정보처리기능사 2008년 4회</option>
                                    <option value="gineungsaJC2008_05">정보처리기능사 2008년 5회</option>
                                    <option value="gineungsaJC2009_01">정보처리기능사 2009년 1회</option>
                                    <option value="gineungsaJC2009_05">정보처리기능사 2009년 5회</option>
                                    <option value="gineungsaJC2010_02">정보처리기능사 2010년 2회</option>
                                    <option value="gineungsaJC2010_05">정보처리기능사 2010년 5회</option>
                                    <option value="gineungsaJC2011_01">정보처리기능사 2011년 1회</option>
                                    <option value="gineungsaJC2011_02">정보처리기능사 2011년 2회</option>
                                    <option value="gineungsaJC2011_04">정보처리기능사 2011년 4회</option>
                                    <option value="gineungsaJC2011_05">정보처리기능사 2011년 5회</option>
                                </select>
                                <select name="cbtTime" id="cbtTime">
                                    <option value="gineungsaWD2009_05">웹디자인기능사 2009년 5회</option>
                                    <option value="gineungsaWD2010_01">웹디자인기능사 2010년 1회</option>
                                    <option value="gineungsaWD2010_02">웹디자인기능사 2010년 2회</option>
                                    <option value="gineungsaWD2010_04">웹디자인기능사 2010년 4회</option>
                                    <option value="gineungsaWD2010_05">웹디자인기능사 2010년 5회</option>
                                    <option value="gineungsaWD2011_01">웹디자인기능사 2011년 1회</option>
                                    <option value="gineungsaWD2011_02">웹디자인기능사 2011년 2회</option>
                                    <option value="gineungsaWD2011_04">웹디자인기능사 2011년 4회</option>
                                    <option value="gineungsaWD2011_05">웹디자인기능사 2011년 5회</option>
                                    <option value="gineungsaWD2012_02">웹디자인기능사 2012년 2회</option>
                                    <option value="gineungsaWD2012_04">웹디자인기능사 2012년 4회</option>
                                    <option value="gineungsaWD2012_05">웹디자인기능사 2012년 5회</option>
                                    <option value="gineungsaWD2013_02">웹디자인기능사 2013년 2회</option>
                                    <option value="gineungsaWD2013_04">웹디자인기능사 2013년 4회</option>
                                    <option value="gineungsaWD2013_05">웹디자인기능사 2013년 5회</option>
                                    <option value="gineungsaWD2014_01">웹디자인기능사 2014년 1회</option>
                                    <option value="gineungsaWD2014_04">웹디자인기능사 2014년 4회</option>
                                    <option value="gineungsaWD2014_05">웹디자인기능사 2014년 5회</option>
                                    <option value="gineungsaWD2015_01">웹디자인기능사 2015년 1회</option>
                                    <option value="gineungsaWD2015_03">웹디자인기능사 2015년 3회</option>
                                    <option value="gineungsaWD2015_04">웹디자인기능사 2015년 4회</option>
                                    <option value="gineungsaWD2015_05">웹디자인기능사 2015년 5회</option>
                                    <option value="gineungsaWD2016_01">웹디자인기능사 2016년 1회</option>
                                    <option value="gineungsaWD2016_04">웹디자인기능사 2016년 4회</option>
                                </select>
                            </div>

                            <div data-lit-hue="20" data-lit-count="100" class="lit-container">
                                <button class="minimal">시작하기</button>
                              </div>
                        </div>
                    </div>
                </div>
            </div>
       </div>
      </div>
    </div>
</main>
<!-- //main -->

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

코드설명

1.div태그 .cbt__header에는 h2태그가 있습니다. 현재 제목 부분입니다.

2.div태그 .cbt__time은 이제 시간이 나오게 할 것입니다.(아직 안했습니다.)

3.div태그 .cbt__sumit은 클릭하면 정답 체크를 해줍니다.(이거 코드 고치다보니 어디로 사라졌네요~)

4.div태그 .cbt__quiz에는 이제 push를 통해서 json파일 내용을 읽어서 문제를 넣어 줄것입니다.

5.div태그 .cbt__aisde는 우측에서 "정답 체크", "수험자", "남은 문제", "전체 문제" 등등을 담아줍니다.

6.div태그 .cbt__modall은 모달창입니다. 처음에 CBT퀴즈를 키면 제일 처음에 나오는 곳입니다.

7.div태그 .cbt__box의 h2태그는 모달창 제목입니다.

8.div태그 .cbt__box의 select는 이제 "정보처리기능사"와 "웹디자인기능사"를 표시해 줍니다.

9.div태그 .cbt__box의 button태그 .minimal은 클릭하면 화면이 사라지게 만들었습니다.

JAVASCRIPT코드

<script>
// WD
const cbtQuiz = document.querySelector(".cbt__quiz");
const omr = [];
const cbtOmr = document.querySelector(".cbt__omr");
const cbt__submit = document.querySelector(".cbt__time2 .submit");
const fullScore = document.querySelector(".full__score");
const oddScore = document.querySelector(".odd__score");
const startBtn = document.querySelector(".cbt__start .minimal");

let questionAll = [];               //모든 퀴즈 정보
let questionLength = 0;             //전체 문제수
let questionRest = questionLength; //남은 문제수
const cbtRest = document.querySelector(".cbt__rest");
const cbtLength = document.querySelector(".cbt__length");

// 데이터 가져오기
const dataQuestion = () => {
    // 가져온 다음에 처리함
    // .then.then 체인기능
    fetch("json/gisa2020_01.json") //json파일을 읽어 오고
    // then(res => res.json)에서 res는 이름을 마음대로 설정 가능.
    .then(res => res.json()) //json파일을 객체로 변환합니다.
    // items에 파일 안의 내용이 전부 저장되어있음
    .then(items => { //객체를 출력합니다
        // console.log(items);      

        questionAll = items.map((item, index, array) => {
            console.log(item.question_img);
            const formatedQuestion = {
                Question: item.question,
                Number : (index+1),
                choice1: "정답",
                choice2: "오답",
                choice3: "오답",
                choice4: "오답"
            }
            // ...item을 써서 데이터만을 불러옴
            const answerChoices = [...item.correct_answer];  //오답 불러오기
            // console.log(item.incorrect_answers);

            // 정답체크
            // 정답 랜덤으로 불러오기
            // console.log(answerChices.length); // 3나옴
            // 상수 formatedQuestion에다가 answer이라는 키값을 부여함.
            formatedQuestion.answer = Math.round(Math.random() * answerChoices.length) + 1;
            // console.log(Math.floor(Math.random() * answerChices.length));
            // 정답을 랜덤으로 추가
            answerChoices.splice(formatedQuestion.answer-1, 0, item.correct_answer); 

            // 보기를 추가
            answerChoices.forEach((choice, index) => {
                // 보기 3개 + 정답 1개 가져옴
                // 0,1,2,3까지 갖고 오고
                // console.log("알려줘~:",choice, index);
                formatedQuestion["choice" + (index+1)] = choice;
            });

            // 문제에 대한 해설이 있으면 출력
            if(item.hasOwnProperty("question_desc")){
                formatedQuestion.QuestionDesc = item.desc;
            }

            // 문제에 대한 이미지가 있으면 출력
            if(item.hasOwnProperty("question_img")){
                formatedQuestion.QuestionImg = item.question_img;
            }

             // 문제에 대한 이미지가 있으면 출력
            if(item.hasOwnProperty("desc")){
                formatedQuestion.desc = item.desc;
            }

             // 문제에 대한 이미지가 있으면 출력
            if(item.hasOwnProperty("keyword")){
                formatedQuestion.keyword = item.keyword;
            }



            // 리턴값 없이 questionAll 호출하면 undefinde가 나옴
            // console.log(formatedQuestion);
            return formatedQuestion;
        });

        newQuestion(); // 문제 만들기 
        questionLength = questionAll.length;
        cbtLength.innerHTML = questionLength + "문항";
        cbtRest.innerHTML = questionLength + "문항";
        // console.log(questionAll);
    })//.catch((err) => console.log(err));
};

// 문제 만들기
const newQuestion = () => {
    const exam = [];

    // console.log(questionAll);
    questionAll.forEach((question, number) => {
        exam.push(`
            <div class="cbt"> 
                <div class="cbt__question"><span>${number+1}</span>. ${question.Question}</div>
                <div class="cbt__question__img">${question.question_img}</div>
                <div class="cbt__question__img">${question.question_desc}</div>
                <div class="cbt__selects">
                        <input type="radio" id="select${number}_1" name="select${number}" value="${number}_1" onclick="answerSelect2(this)">
                        <label for="select${number}_1"><span>${question.choice1}</span></label>
                        <input type="radio" id="select${number}_2" name="select${number}" value="${number}_2" onclick="answerSelect2(this)">
                        <label for="select${number}_2"><span>${question.choice2}</span></label>
                        <input type="radio" id="select${number}_3" name="select${number}" value="${number}_3" onclick="answerSelect2(this)">
                        <label for="select${number}_3"><span>${question.choice3}</span></label>
                        <input type="radio" id="select${number}_4" name="select${number}" value="${number}_4" onclick="answerSelect2(this)">
                        <label for="select${number}_4"><span>${question.choice4}</span></label>
                </div>
                <div class="cbt__desc hide">${question.desc}</div>
                <div class="cbt__keyword">${question.keyword}</div>
            </div>
        `);
        cbtQuiz.innerHTML = exam.join("");

        omr.push(`
          <div class="cbt__omr">
               <div class="cbt__omr">
                   <div class="omr">
                       <strong>${number+1}</strong>
                       <input type="radio" name="omr${number}" id="omr${number}_1" value="${number}_1" onclick="answerSelect(this)">
                       <label for="omr${number}_1">
                           <span class="label-inner">1</span>
                       </label>
                       <input type="radio" name="omr${number}" id="omr${number}_2" value="${number}_2" onclick="answerSelect(this)">
                       <label for="omr${number}_2">
                           <span class="label-inner">2</span>
                       </label>
                       <input type="radio" name="omr${number}" id="omr${number}_3" value="${number}_3" onclick="answerSelect(this)">
                       <label for="omr${number}_3">
                           <span class="label-inner">3</span>
                       </label>
                       <input type="radio" name="omr${number}" id="omr${number}_4" value="${number}_4" onclick="answerSelect(this)">
                       <label for="omr${number}_4">
                           <span class="label-inner">4</span>
                       </label>
                   </div>
               </div>
           </div>
           `);
        });
        cbtQuiz.innerHTML = exam.join("");
        cbtOmr.innerHTML = omr.join(""); 
    }


// 정답 확인
// em.submit
const answerQuiz = () => {
    const cbtselects = document.querySelectorAll(".cbt__selects");
    
    questionAll.forEach((question, number) => {
        const quizSelectsWrap = cbtselects[number];
        const userSelector = `input[name=select${number}]:checked`;
        const userAnswer = (quizSelectsWrap.querySelector(userSelector) || {}).value;
        const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;

        if(numberAnswer == question.answer){
            console.log("정답");
            cbtselects[number].parentElement.classList.add("good");
            // 전체 문제수 : 60문항
        } 
        else {
            console.log("모야");
            cbtselects[number].parentElement.classList.add("bad");

            const label = cbtselects[number].querySelectorAll("label");
            // label[question.answer-1].classList.add("corrent");
        }
        const quizDesc = document.querySelectorAll(".cbt__desc");

        if(quizDesc[number].innerText == "undefined"){
            quizDesc[number].classList.add("hide");
        }else {
            quizDesc[number].classList.remove("hide");
        }
    });
}

// 보기 체크 
const answerSelect2 = (elem) => {
    const answer = elem.value;
    // 1번 문제 : 0_1 / 0_2 / 0_3 / 0_4
    console.log(answer);
    const answerNum = answer.split("_");
    const select = document.querySelectorAll(".cbt__omr .omr"); // 전체 문항 수 : 100문제
    const label = select[answerNum[0]].querySelectorAll("input"); //보기 4개

    const answerInputs = document.querySelectorAll(".cbt__selects input:checked");
    label[answerNum[1]-1].checked = true;
    cbtRest.innerHTML = questionLength - answerInputs.length;

    // console.log(answerNum);
    // console.log(answerNum[1]);
};

// 보기 체크2
const answerSelect = (elem) => {
    const answer = elem.value;
    console.log(answer);
    const answerNum = answer.split("_");
    const select = document.querySelectorAll(".cbt__quiz .cbt"); // 전체 문항 수 : 100문제
    const label = select[answerNum[0]].querySelectorAll("input"); //보기 4개
    label[answerNum[1]-1].checked = true;

    console.log(answerNum);
    // console.log(answerNum[1]);
};


cbt__submit.addEventListener("click", answerQuiz);

dataQuestion();

startBtn.addEventListener("click",function(){
    console.log("클릭");
    document.querySelector(".cbt__start").classList.add("hide");
});

//화면 초반에 나오는 시작하기 버튼
// 버블 버튼
const bubbleBtn = () => {
    const clip = (v, min, max = Infinity) => {
        if (v < min) return min;
        else if (v > max) return max;
        else return v;
    };

    // generated random value from given range
    const randRange = (min, max) => Math.random() * max + min;

    // create bubble on x and y position inside target with given hue theme
    function bubble(x, y, rect, hue, target) {
        // variables
        // 변수 설정
        const size = randRange(20, rect.width / 5);
        const circleHue = hue + randRange(-20, 20);
        const animDuration = randRange(clip(size ** 2/1000, 1), 6) 
        const zIndex = Math.random() < 0.1 ? 2 : -1;
        // apply to DOM
        // 원 만들기
        const circle = document.createElement("span");
        circle.className = "lit";
        circle.style.left = x + "px";
        circle.style.top = y + "px";
        circle.style.width = size + "px";
        circle.style.height = size + "px";
        circle.style.background = `hsl(${circleHue}deg, 100%, 60%)`;
        circle.style.zIndex = zIndex
        circle.style.animationDuration = animDuration + "s";
        target.appendChild(circle);
    }

    document.querySelectorAll("[data-lit-hue]").forEach((target) => {
        const rect = target.getBoundingClientRect();
        const hue = Number(target.getAttribute("data-lit-hue"));
        const count = Number(target.getAttribute("data-lit-count") || 50);

        for (let i = 0; i < count; i++) {
            const x = randRange(0, rect.width);
            const y = randRange(0, rect.height);
            bubble(x, y, rect, hue, target);
        }
    });
}
bubbleBtn();
</script>

코드설명

1.

// WD
const cbtQuiz = document.querySelector(".cbt__quiz");
const omr = [];
const cbtOmr = document.querySelector(".cbt__omr");
const cbt__submit = document.querySelector(".cbt__time2 .submit");
const fullScore = document.querySelector(".full__score");
const oddScore = document.querySelector(".odd__score");
const startBtn = document.querySelector(".cbt__start .minimal");

let questionAll = [];               //모든 퀴즈 정보
let questionLength = 0;             //전체 문제수
let questionRest = questionLength; //남은 문제수
const cbtRest = document.querySelector(".cbt__rest");
const cbtLength = document.querySelector(".cbt__length");

querySelector("");을 통해서 클래스, 아이디, 태그를 찾습니다.

 

2.

// 데이터 가져오기
const dataQuestion = () => {
    // 가져온 다음에 처리함
    // .then.then 체인기능
    fetch("json/gisa2020_01.json") //json파일을 읽어 오고
    // then(res => res.json)에서 res는 이름을 마음대로 설정 가능.
    .then(res => res.json()) //json파일을 객체로 변환합니다.
    // items에 파일 안의 내용이 전부 저장되어있음
    .then(items => { //객체를 출력합니다
        // console.log(items);      

        questionAll = items.map((item, index, array) => {
            console.log(item.question_img);
            const formatedQuestion = {
                Question: item.question,
                Number : (index+1),
                choice1: "정답",
                choice2: "오답",
                choice3: "오답",
                choice4: "오답"
            }
            // ...item을 써서 데이터만을 불러옴
            const answerChoices = [...item.incorrect_answers];  //오답 불러오기
            // console.log(item.incorrect_answers);

            // 정답체크
            // 정답 랜덤으로 불러오기
            // console.log(answerChices.length); // 3나옴
            // 상수 formatedQuestion에다가 answer이라는 키값을 부여함.
            formatedQuestion.answer = Math.round(Math.random() * answerChoices.length) + 1;
            // console.log(Math.floor(Math.random() * answerChices.length));
            // 정답을 랜덤으로 추가
            answerChoices.splice(formatedQuestion.answer-1, 0, item.correct_answer); 

            // 보기를 추가
            answerChoices.forEach((choice, index) => {
                // 보기 3개 + 정답 1개 가져옴
                // 0,1,2,3까지 갖고 오고
                // console.log("알려줘~:",choice, index);
                formatedQuestion["choice" + (index+1)] = choice;
            });

            // 문제에 대한 해설이 있으면 출력
            if(item.hasOwnProperty("question_desc")){
                formatedQuestion.QuestionDesc = item.desc;
            }

            // 문제에 대한 이미지가 있으면 출력
            if(item.hasOwnProperty("question_img")){
                formatedQuestion.QuestionImg = item.question_img;
            }

             // 문제에 대한 이미지가 있으면 출력
            if(item.hasOwnProperty("desc")){
                formatedQuestion.desc = item.desc;
            }

             // 문제에 대한 이미지가 있으면 출력
            if(item.hasOwnProperty("keyword")){
                formatedQuestion.keyword = item.keyword;
            }



            // 리턴값 없이 questionAll 호출하면 undefinde가 나옴
            // console.log(formatedQuestion);
            return formatedQuestion;
        });

        newQuestion(); // 문제 만들기 
        questionLength = questionAll.length;
        cbtLength.innerHTML = questionLength + "문항";
        cbtRest.innerHTML = questionLength + "문항";
        // console.log(questionAll);
    })//.catch((err) => console.log(err));
};

여기는 단순하게 데이터를 넣는 곳입니다.

(밑에서부터 올라왔는데. 너무 힘드네요.ㅈㅈ)

 

3.

const newQuestion = () => {
    const exam = [];

    questionAll.forEach((question, number) => {
    exam.push(`
        <div class="cbt"> 
            <div class="cbt__question"><span>${number+1}</span>. ${question.Question}</div>
            <div class="cbt__question__img">${question.question_img}</div>
            <div class="cbt__question__img">${question.question_desc}</div>
            <div class="cbt__selects">
                    <input type="radio" id="select${number}_1" name="select${number}" value="${number}_1" onclick="answerSelect2(this)">
                    <label for="select${number}_1"><span>${question.choice1}</span></label>
                    <input type="radio" id="select${number}_2" name="select${number}" value="${number}_2" onclick="answerSelect2(this)">
                    <label for="select${number}_2"><span>${question.choice2}</span></label>
                    <input type="radio" id="select${number}_3" name="select${number}" value="${number}_3" onclick="answerSelect2(this)">
                    <label for="select${number}_3"><span>${question.choice3}</span></label>
                    <input type="radio" id="select${number}_4" name="select${number}" value="${number}_4" onclick="answerSelect2(this)">
                    <label for="select${number}_4"><span>${question.choice4}</span></label>
            </div>
            <div class="cbt__desc hide">${question.desc}</div>
            <div class="cbt__keyword">${question.keyword}</div>
        </div>
    `);
    cbtQuiz.innerHTML = exam.join("");

    omr.push(`
      <div class="cbt__omr">
           <div class="cbt__omr">
               <div class="omr">
                   <strong>${number+1}</strong>
                   <input type="radio" name="omr${number}" id="omr${number}_1" value="${number}_1" onclick="answerSelect(this)">
                   <label for="omr${number}_1">
                       <span class="label-inner">1</span>
                   </label>
                   <input type="radio" name="omr${number}" id="omr${number}_2" value="${number}_2" onclick="answerSelect(this)">
                   <label for="omr${number}_2">
                       <span class="label-inner">2</span>
                   </label>
                   <input type="radio" name="omr${number}" id="omr${number}_3" value="${number}_3" onclick="answerSelect(this)">
                   <label for="omr${number}_3">
                       <span class="label-inner">3</span>
                   </label>
                   <input type="radio" name="omr${number}" id="omr${number}_4" value="${number}_4" onclick="answerSelect(this)">
                   <label for="omr${number}_4">
                       <span class="label-inner">4</span>
                   </label>
               </div>
           </div>
       </div>
       `);
    });
    
cbtQuiz.innerHTML = exam.join("");
cbtOmr.innerHTML = omr.join(""); 
}

백틱 기호를 사용해서 json에 저장된 파일만큼 반복해서 호출합니다.

exam.join(""); /// omr.join("");은 백틱 기호를 호출하면 배열이라 "," 콤마가 붙습니다.

그것들을 제거하기 위해 사용합니다.

 

2.

const cbtselects = document.querySelectorAll(".cbt__selects");

questionAll.forEach((question, number) => {
const quizSelectsWrap = cbtselects[number];
const userSelector = `input[name=select${number}]:checked`;
const userAnswer = (quizSelectsWrap.querySelector(userSelector) || {}).value;
const numberAnswer = userAnswer ? userAnswer.slice(-1) : undefined;



// console.log(userAnswer.split("_")[1]);

if(numberAnswer == question.answer){
    console.log("정답");
    cbtselects[number].parentElement.classList.add("good");
    // 전체 문제수 : 60문항
} 
else {
    console.log("모야");
    cbtselects[number].parentElement.classList.add("bad");

    const label = cbtselects[number].querySelectorAll("label");
    // label[question.answer-1].classList.add("corrent");
}
const quizDesc = document.querySelectorAll(".cbt__desc");

if(quizDesc[number].innerText == "undefined"){
    quizDesc[number].classList.add("hide");
}else {
    quizDesc[number].classList.remove("hide");
}
});

●const cbtselects은 div태그인 .cbt__selects를 찾습니다.

(.cbt__selects 안에는 label태그 4개와 input태그 4개가 있습니다.)

●const quizSelectsWrap은 .cbt__selects에 있는 input태그를 가져옵니다.

●const userAnswer은 quizSelectsWrap에 저장된 input타입에서 checked된 것들을 찾습니다.

●const numberAnswer은 userAnswer에 저장된 데이터가 값이 있으면 데이터를 반환하고 없으면 undefined를 반환합니다.

●if문을 통해서 userAnswer에 저장된 데이터와 Math.round를 통해서 random()값을 가져온 값을 비교합니다.

그 값이 맞으면 정답을 맞췄습니다가 표시 됩니다.

●else문이라면 오답이 나옵니다.

●if(quizDesc[number].innerText == "underfined") {}

div태그인 .cbt__desc에 저장된 값과 undefined를 비교합니다. 참,거짓 여부에 따라 CSS style부여합니다.

 

4.

// 보기 체크 
const answerSelect2 = (elem) => {
    const answer = elem.value;
    // 1번 문제 : 0_1 / 0_2 / 0_3 / 0_4
    console.log(answer);
    const answerNum = answer.split("_");
    const select = document.querySelectorAll(".cbt__omr .omr"); // 전체 문항 수 : 100문제
    const label = select[answerNum[0]].querySelectorAll("input"); //보기 4개

    const answerInputs = document.querySelectorAll(".cbt__selects input:checked");
    label[answerNum[1]-1].checked = true;
    cbtRest.innerHTML = questionLength - answerInputs.length;
};

// 보기 체크2
const answerSelect = (elem) => {
    const answer = elem.value;
    console.log(answer);
    const answerNum = answer.split("_");
    const select = document.querySelectorAll(".cbt__quiz .cbt"); // 전체 문항 수 : 100문제
    const label = select[answerNum[0]].querySelectorAll("input"); //보기 4개
    label[answerNum[1]-1].checked = true;
};

cbt__submit.addEventListener("click", answerQuiz);

●const answer Select2와 const answerSelect는 input의 radio버튼을 하나하나 클릭할때마다 실행되는 익명함수 입니다.

(const answer Select2은 좌측 문제 내용의 radio //// const answerSelect은 우측 문제 체크의 radio)

 

●const answerSelect2에서는 radio버튼이 클릭되면 valuie값을 가져옵니다.(const answer)

●value값은 1번문제에서 -- 0_1 / 0_2 / 0_3 / 0_4

●value값은 2번문제에서 -- 1_1 / 1_2 / 1_3 / 1_4 이렇게 가져옵니다

●const answerNum은 const answer에서 가져온 값들에서 "_"언더바를 제거하고 [0,1], [0,2], [0,3], [0,4] 이런식으로 가져옵니다.

●const select는 div태그인 .cbt에는 "문제 번호", "문제", "문제와 관련된 이미지", "문제를 풀어야 하는 이미지", "문제 내용" 등이 있습니다.

●const label은 div태그인 .cbt + answerNum에 저장된 [좌,우] 값중 "좌"에 해당하는 값을 가져오고 + input태그를 찾아서 합칩니다. 

(1번 문제는 .cbt클래스에서 0번지에 있는 4개의 input 태그를 가져옵니다)

●label[answerNum[1]]로 들고오면 [좌,우] 중 "우"의 값이 0_2, 0_3, 0_4, 0_5이렇게 시작합니다.

그래서 1을 빼줘서 0_1, 0_2, 0_3, 0_4로 만들어 줍니다. 그리고 그중에서 체크가 된게 맞으면 값을 가져옵니다.

● questionLength의 값은 0입니다 /// answerInputs.length로 input태그가 체크 되어잇을떄마다 길이를 가져옵니다

(1번 문제 체크시 +1 /// 2번 문제 체크시 +2 /// 3번 문제 체크시 +3)

 

 

5.

 // button태그인 .minimal을 클릭했다면
// div태그인 .cbt__start 모달창을 숨깁니다.
startBtn.addEventListener("click",function(){
    console.log("클릭");
    document.querySelector(".cbt__start").classList.add("hide");
});

●button태그인 .minimal을 클릭했다면 실행이 됩니다.

●그리고 div태그 .cbt__start인 모달창을 position: absolute로 날려 보낸다음 

   애니메이션으로 위로 올라가도록 만들어봤습니다.

●월래 다른 방법도 있지만.. absolute를 주고 싶어서 만들어 봤습니다.

 

6.

// button태그인 .minimal의 CSS를 꾸며주기 위해 
// CSS 애니메이션을 퍼와서 합쳐봤습니다
// 버블 버튼
const bubbleBtn = () => {
    const clip = (v, min, max = Infinity) => {
        if (v < min) return min;
        else if (v > max) return max;
        else return v;
    };

    // generated random value from given range
    const randRange = (min, max) => Math.random() * max + min;

    // create bubble on x and y position inside target with given hue theme
    function bubble(x, y, rect, hue, target) {
        // variables
        // 변수 설정
        const size = randRange(20, rect.width / 5);
        const circleHue = hue + randRange(-20, 20);
        const animDuration = randRange(clip(size ** 2/1000, 1), 6) 
        const zIndex = Math.random() < 0.1 ? 2 : -1;
        // apply to DOM
        // 원 만들기
        const circle = document.createElement("span");
        circle.className = "lit";
        circle.style.left = x + "px";
        circle.style.top = y + "px";
        circle.style.width = size + "px";
        circle.style.height = size + "px";
        circle.style.background = `hsl(${circleHue}deg, 100%, 60%)`;
        circle.style.zIndex = zIndex
        circle.style.animationDuration = animDuration + "s";
        target.appendChild(circle);
    }

    document.querySelectorAll("[data-lit-hue]").forEach((target) => {
        const rect = target.getBoundingClientRect();
        const hue = Number(target.getAttribute("data-lit-hue"));
        const count = Number(target.getAttribute("data-lit-count") || 50);

        for (let i = 0; i < count; i++) {
            const x = randRange(0, rect.width);
            const y = randRange(0, rect.height);
            bubble(x, y, rect, hue, target);
        }
    });
}
bubbleBtn();

●const bubbleBtn은  단순하게 CSS 애니메이션 중에 마음에 드는 것을 퍼오고

   button태그인 .minimal에 CSS Style을 넣어봤습니다.