기초부터 시작하는 코딩/Javascript

Javascript를 이용한 사이트 만들기! - 퀴즈 효과 사이트 만들기07_1

kebab00 2023. 4. 4. 22:57

728x90

- 자 오늘도 어제하던 것을 마저 해봅시다.

- 오늘은 추가한 것들은 바로 omr과 문제보기의 value값을 통일시켜서 하나를 눌러도 양쪽에서 표시가나게 해주었고, 문제를 하나씩 풀 때마다 남은 문제의 수가 하나씩 줄어들게 해주었습니다. 그리고 창이 켜졌을 때 문제풀기 버튼을 띄워주는 것등을 하였습니다.

 

- 추가된 코드를 같이 보시죠

  <div class="cbt__start">
                <div class="cbt__modal1">
                    <h2>기능사 시험 시작하기</h2>
                    <div class="cbt__choice">
                        <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>
                    <button data-lit-hue="20" data-lit-count="100" class="minimal">시작하기</button>
                </div>

            </div>

- 모달 창을 추가하고 select태그를 사용해서 다른 년도의 다른 회차 문제를 선택할 수 있게 해줄 것입니다.(아직 스크립트는 안함)

- 아무튼 시작버튼을 누르면 모달창이 사라지며 문제가 시작이 됩니다.

- 스크립트를 같이 보시죠

// 시작버튼을 누르면 모달 창이 사라짐

const cbtStart = document.querySelector(".cbt__start");
const cbtMinimal = document.querySelector(".minimal");

cbtMinimal.addEventListener("click", () => {
    cbtStart.style.display = "none";
});

// 문제설명이 없는 문제의 설명박스 숨기기 - 다른 함수안에 들어가 있어야 실행됨
const quizDesc = document.querySelectorAll(".cbt__question__desc");
quizDesc.forEach(el => {
    if(el.innerHTML == "undefined"){
        el.style.display = "none";
    };
        
let questionRest = questionLength;
// 전체 문제 수
questionLength = questionAll.length
cbtLength.innerHTML = questionLength
cbtRest.innerHTML = questionLength

// 보기체크 
 const answerSelect2 = (elem) => {
    const answer = elem.value;
    const answerNum = answer.split("_");

    const select = document.querySelectorAll(".cbt__omr .omr");         // 전체 문항 수 100개
    const label = select[(answerNum[0])].querySelectorAll("input");     // 보기 4개
    label[answerNum[1]-1].checked = true;                             

    const answerInputs = document.querySelectorAll(".cbt__selects input:checked");
    cbtRest.innerHTML = questionLength - answerInputs.length;    // 함수가 실행될 때 (체크가 될 때 전체문항수 - 체크한 갯수의 빼기가 진행됨)
 }
// 보기체크2
const answerSelect = (elem) => {
    const answer = elem.value;
    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;                               

    const answerInputs = document.querySelectorAll(".cbt__selects input:checked");
    cbtRest.innerHTML = questionLength - answerInputs.length;  // 함수가 실행될 때 (체크가 될 때 전체문항수 - 체크한 갯수의 빼기가 진행됨)
}

- 추가된 것이 이정도 입니다.

- 이외에도 value값을 맞춰주거나 하는 등의 소소한 수정이 있었지만 추가된 건 아니니 패스하도록 하겠습니다.

- 궁금하시면 github에 가셔서 코드를 보시는 것을 추천드립니다.

- 먼저 시작버튼을 누르면 모달 창이 사라지는 것과 undefined값을 가진 div박스를 없애는 것을 보겠습니다.

// 시작버튼을 누르면 모달 창이 사라짐

const cbtMinimal = document.querySelector(".minimal");

cbtMinimal.addEventListener("click", () => {
    cbtStart.style.display = "none";
});

// 문제설명이 없는 문제의 설명박스 숨기기 - 다른 함수안에 들어가 있어야 실행됨
const quizDesc = document.querySelectorAll(".cbt__question__desc");
quizDesc.forEach(el => {
    if(el.innerHTML == "undefined"){
    	el.style.display = "none";
    };
});

- 이부분 입니다.

- 사실 아주 간단합니다. 둘 다 선택자를 만들어주고 모달 창은 addEventListener를 사용해서 클릭했을 때 display = "none"을 undefined값을 가진 div박스 계속 처음부터 실행되는 함수 안에 넣어 바로 실행되도록 해주시면 됩니다.

- 다음은 먼저 보기와 omr를 체크했을 때 value값을 맞춰주는 것을 해보겠습니다.

// 보기체크 
 const answerSelect2 = (elem) => {
    const answer = elem.value;
    const answerNum = answer.split("_");

    const select = document.querySelectorAll(".cbt__omr .omr");         // 전체 문항 수 100개
    const label = select[(answerNum[0])].querySelectorAll("input");     // 보기 4개
    label[answerNum[1]-1].checked = true;                             

    const answerInputs = document.querySelectorAll(".cbt__selects input:checked");
    cbtRest.innerHTML = questionLength - answerInputs.length;    // 함수가 실행될 때 (체크가 될 때 전체문항수 - 체크한 갯수의 빼기가 진행됨)
 }
// 보기체크2
const answerSelect = (elem) => {
    const answer = elem.value;
    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;                               

    const answerInputs = document.querySelectorAll(".cbt__selects input:checked");
    cbtRest.innerHTML = questionLength - answerInputs.length;  // 함수가 실행될 때 (체크가 될 때 전체문항수 - 체크한 갯수의 빼기가 진행됨)
}

- 비슷한 형식의 이름만 다른 함수 2개 입니다.

- 각 함수 안에 선언된 변수들은 지역변수라 이름이 같아도 오류가 나지 않습니다. ^^

- 변수 안에 elem의 value값을 가져왔습니다. 여기서 elem은 문제보기의 value입니다. 그리고 그 값에서 split를 사용하여 필요한 값만 뽑아 왔습니다.

- 그 이유는 elem의 value값이 문제번호-1_선택한 번호 값으로 되어 있는데 저희에게 필요한 것은 선택한 번호만 있으면 되기 때문입니다.

- 그리고 omr과 cbt를 선택하는 선택자를 만들어준 뒤 input태그들을 lavel이라는 선택자로 만들어 줍니다.

- 그리고 label[answerNum[1]-1].checked = true;  를 해주면 value값을 맞춰주는 것은 끝이 납니다.

- 자 이제 마지막인 문제를 풀 때마다 남은 문제가 줄어드는 것입니다.

// 전체 문제 수
questionLength = questionAll.length
cbtLength.innerHTML = questionLength
cbtRest.innerHTML = questionLength

// 함수안에 있는실행문
const answerInputs = document.querySelectorAll(".cbt__selects input:checked");
cbtRest.innerHTML = questionLength - answerInputs.length;  // 함수가 실행될 때 (체크가 될 때 전체문항수 - 체크한 갯수의 빼기가 진행됨)

- 먼저 전역변수로 전체문제의 갯수를 저장해주고 보기체크가 있는 함수에 checked된 모든 input을 지역변수로 저장을 해줍니다.

- 그리고 두개를 빼준 것을 해당 요소에 innerHTML로 넣어주면 끝이 납니다.

- omr과 문제중 하나만 선택하더라도 빼기가 진행되어야 하기 때문에 보기체크와 보기체크2에 전부 넣어 주면 끝이납니다.

-끝!