오늘의 JS 놀이: 정적 페이지를 위한 퀴즈엔진 제작
반응형
객관식 퀴즈나 간단한 심리테스트 등에 이용할 수 있는 마크업 규칙과 그것을 작동하게 하는 스크립트를 만들어보려고 합니다. 이전 글 오늘의 JS 놀이: 정적 페이지를 위한 퀴즈 엔진을 만들 계획에 이어서, 계획을 실제로 작동하게 하는 스크립트를 제작합니다. 스크립트는 초기화 단계와 작동 단계로 나눌 수 있습니다.
퀴즈 초기화
document.addEventListener('DOMContentLoaded', (event) => {
// 컨텐츠 로드 후에 할 일
});
웹 페이지가 모든 요소를 표시할 준비가 끝나면 퀴즈를 초기화하도록 합니다. 모종의 이유로 마크업을 모두 표시하기 전에 작동해버리면 오류로 인해 멈출 수 있거든요.
document.addEventListener('DOMContentLoaded', (event) => {
document.querySelectorAll('.quiz-list').forEach((quiz_container) => {
// 각 변수의 초기값을 컨테이너의 속성에 추가한다
quiz_container.setAttribute('quiz-num', 1);
quiz_container.setAttribute('quiz-tot', 1);
quiz_container.setAttribute('point-tot', 0);
quiz_container.setAttribute('point-get', 0);
// 컨테이너 안에 있는 퀴즈 페이지 갯수 세기
let quiz_count = 1;
quiz_container.querySelectorAll('quiz').forEach((quiz_page) => {
// 첫 페이지가 아니면 숨김
if (quiz_count > 1) quiz_page.style.display = 'none';
// 페이지마다 번호 속성 주기
quiz_page.setAttribute('page', quiz_count);
quiz_count++;
});
quiz_container.setAttribute('quiz-tot', quiz_count - 1);
// 총 점수 세기
let point_count = 0;
quiz_container.querySelectorAll('answer').forEach((answer_item) => {
if (answer_item.hasAttribute('point')) {
point_count += Number(answer_item.getAttribute('point'));
}
});
quiz_container.setAttribute('point-tot', point_count);
// 총점 태그에 값 넣기
quiz_container.querySelectorAll('total').forEach((tot_str) => {
tot_str.innerHTML = point_count;
});
// 답안에 온클릭 이벤트 넣기
quiz_container.querySelectorAll('answer').forEach((answer_item) => {
answer_item.onclick = (event) => {
let quiz_page = event.target.closest('quiz');
let quiz_container = quiz_page.parentNode;
let next = Number(quiz_page.getAttribute('page')) + 1;
let get_point = Number(quiz_container.getAttribute('point-get'));
// 클릭한 답안에 포인트가 있는 경우 점수에 합산
if (event.target.hasAttribute('point')) {
get_point += Number(event.target.getAttribute('point'));
quiz_container.setAttribute('point-get', get_point);
}
// 포인트 표시 태그 업데이트
quiz_container.querySelectorAll('point').forEach((get_str) => {
get_str.innerHTML = get_point;
});
// 다음 페이지로 이동
quiz_page.style.display = 'none';
quiz_container.querySelector(`quiz[page="${next}"]`).style.display = 'block';
quiz_container.setAttribute('quiz-num', next);
}
});
// 리셋 태그에 온클릭 이벤트 넣기
quiz_container.querySelectorAll('reset').forEach((reset_btn) => {
reset_btn.onclick = (event) => {
let quiz_page = event.target.closest('quiz');
let quiz_container = quiz_page.parentNode;
// 퀴즈 컨테이너의 변수 초기화
quiz_container.setAttribute('quiz-num', 1);
quiz_container.setAttribute('point-get', 0);
// 첫 페이지로 넘어가기
quiz_page.style.display = 'none';
quiz_container.querySelector(`quiz[page="1"]`).style.display = 'block';
}
});
});
});
마크업 예시
<div class="quiz-list">
<quiz>
<ask>첫 번째 문제입니다</ask>
<answer point="10">정답</answer>
<answer>오답</answer>
</quiz>
<quiz>
<ask>두 번째 문제입니다</ask>
<answer>오답</answer>
<answer point="20">정답</answer>
<answer>오답</answer>
</quiz>
<quiz>
<ask>세 번째 문제입니다</ask>
<answer>오답</answer>
<answer>오답</answer>
<answer point="30">정답</answer>
</quiz>
<quiz>
획득한 점수는
<point></point> / <total></total>
입니다.
<reset>다시하기</reset>
</quiz>
</div>
스타일시트 예시
대충 알아볼 수 있을 정도로만 했습니다. 추가로 여러 스타일 속성을 써서 보기 좋게 만들면 됩니다.
.quiz-list {
width: 100%;
height: 120px;
background: #EEEEEE;
border-radius: 2px;
}
quiz {
display: block;
padding: 0.5rem;
width: 100%;
height: 100%;
text-align: center;
}
quiz p {
display: block;
margin: 0.5rem 0;
}
answer,
reset {
display: inline-block;
padding: 0.2rem 0.3rem;
border-radius: 2px;
border: orange 1px solid;
cursor: pointer;
}
결과
첫 번째 문제입니다
두 번째 문제입니다
세 번째 문제입니다
획득한 점수는
반응형
'프로그래밍 > 웹 프로그래밍' 카테고리의 다른 글
순수 JavaScript로 만드는 자동 목차 기능 (0) | 2019.11.22 |
---|---|
스킨 업데이트: <kbd> 스타일 추가 (0) | 2019.11.22 |
오늘의 JS 놀이: 정적 페이지를 위한 퀴즈엔진을 만들 계획 (0) | 2019.11.20 |
CSS: 그리드(Grid) 아이템 속성 (0) | 2019.11.19 |
CSS: 그리드(Grid) 컨테이너 속성 (0) | 2019.11.18 |
댓글