버튼을 클릭하면 명언이 나와요
-이름이 나와요
보충 작업 완성물
어제가 지나고 화가 가라 앉으니간 어느정도 따라가기 시작하네요.

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을 넣어봤습니다.
