예제/퀴즈 이펙트

퀴즈 이펙트_여러문제를 풀 수 있도록 만들어 봅시다!(JSON)_보충

아라라_ 2023. 4. 4. 23:40

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

Frederick Philips Brooks
Mythical Man-Month 저자
728x90

모달창 추가 html

 <div class="cbt__start">
    <div class="cbt_modall">
        <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="gineungsaJC2004_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>시작하기</button>
    </div>
</div>

우선 문제를 풀기 전에 문제 선택창을 만들었는데 아직 구동은 되지 않지만 시작버튼은 구동이 되도록 합니다.

시작하기 버튼을 누르면 사용자의 이름을 입력하는 창이 뜨는데 이때 무조건 어떠한 값이라도 적지 않으면 넘어가지 않도록 하였습니다.

 

 

모달창 css

.cbt__start {
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100vh;
    z-index: 10000;
    background-color: rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(10px);
    display: flex;
    align-items: center;
    justify-content: center;
}
.cbt__start.hide {
    display: none;
}
.cbt__start > div {
    width: 50%;
    height: 50vh;
    background-color: #fff;
    border: 8px ridge #fff;
    text-align: center;
}
.cbt__start > div h2 {
    font-size: 40px;
    color: rgb(221, 170, 221);
    margin: 50px;
}
.cbt__start > div select {
    border: 2px solid rgb(221, 170, 221);
    padding: 10px 30px;
    margin-bottom: 20px;
    font-family: 'EliceDigitalBaeum';
}
.cbt__start > div button {
    box-shadow: 2px 2px 5px rgba(221, 170, 221,0.4);
    background: #fff;
    display: grid;
    align-content: center;
    justify-content: center;
    border-radius: 5px;
    width: 300px;
    height: 80px;
    margin: 0 auto;
    font-family: 'PyeongChang';
    border: 1px solid rgb(222, 171, 222)
}
.cbt__start > div button:hover {
    background: #deabde;
}

 

모달창 script

const cbtStart = document.querySelector(".cbt__start")
const cbtBtn = document.querySelector(".cbt__start button")

const cbtQuestionImgDesc = () => {
    cbtStart.classList.add("hide");
    const getUserName = () => {
        const userName = prompt('여러분의 이름을 적어주세요😆');
        if(userName === ""){
            return getUserName();
        }if(userName === null){
            return getUserName();
        }
        return userName;
    };
    const userName = getUserName();
    cbtName.textContent = userName;
}

cbtBtn.addEventListener("click", cbtQuestionImgDesc);

만약 창에 값을 안넣고 확인을 누를경우에는 빈 문자열""이, 취소를 누를경우에는 null값이 반환됩니다. 이때 반환되는 값을 조건문에 걸어 재귀함수를 사용하여 다시 함수가 실행되도록하였습니다.

 

문제의 설며과 이미지가 없을경우

const questionDesc = document.querySelectorAll(".cbt__question__desc");

questionDesc.forEach(el => {
    if(el.innerHTML == "undefined"){
        el.style.display = "none";
    }
});   

const questionImg = document.querySelectorAll(".cbt__question__img"); 

questionImg.forEach(el => {
        if(el.innerHTML == "undefined"){
            el.style.display = "none";
        }
    });
}

 

문제의 설명과 이미지가 없는경우 undefined가 나오는데 이때 없는 경우에 undefined조차 나올수 없도록 여러개의 해설과 이미지를 선택해서 적용하여야 하기때문에 forEach를 사용하여 안에 if문을 넣어 undefined일 때 아예 그부분이 나오지 못하도록 el.style.display = "none";을 사용하엿습니다.

 

문제 보기 답 연동하기 ( omr, question )

//보기체크
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;
}

answerSelect와 answerSelect2 함수는 매개변수로 선택한 보기의 요소를 받습니다. 이때 보기는 라디오 버튼으로 구성되어 있으며, 각 보기는 그룹화를 위해 name 속성이 같습니다.
보기에서 선택한 값을 answer 변수에 저장하고, _를 구분자로 해서 answer 변수의 값을 배열 answerNum에 저장합니다. 이때 answerNum[0]은 문항 번호를 의미하고, answerNum[1]은 보기 번호를 의미합니다.
select 변수는 해당 문항에 대한 보기 요소들을 저장하며, querySelectorAll 메서드를 사용하여 문항 번호에 해당하는 보기를 가져옵니다.
그리고 label 변수는 select 요소 중에서 보기 번호에 해당하는 라디오 버튼 요소를 가져옵니다. answerNum[1]에서 1을 뺀 이유는 배열 인덱스가 0부터 시작하기 때문입니다.
그 후 label 요소 중에서 answerNum[1]에 해당하는 라디오 버튼 요소에 checked 속성을 설정하여 보기를 선택한 것처럼 체크합니다.
마지막으로, querySelectorAll 메서드를 사용하여 선택한 보기의 개수를 가져온 후, questionLength에서 빼서 남은 문항 수를 계산합니다. 이를 cbtRest 요소에 출력하여 사용자가 몇 문항이나 남았는지 알 수 있도록 합니다.