├── countdown.mp3
├── style.css
├── index.html
└── script.js
/countdown.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/opensource-coding/Javascript-Quiz-App/HEAD/countdown.mp3
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=Poppins:100,100italic,200,200italic,300,300italic,regular,italic,500,500italic,600,600italic,700,700italic,800,800italic,900,900italic);
2 |
3 | * {
4 | margin: 0;
5 | padding: 0;
6 | box-sizing: border-box;
7 | font-family: "Poppins", sans-serif;
8 | }
9 | body {
10 | min-height: 100vh;
11 | display: flex;
12 | align-items: center;
13 | justify-content: center;
14 | background: #dddfeb;
15 | }
16 | .container {
17 | position: relative;
18 | width: 100%;
19 | max-width: 400px;
20 | background: #1f2847;
21 | padding: 30px;
22 | overflow: hidden;
23 | border-radius: 10px;
24 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
25 | }
26 |
27 | .heading {
28 | text-align: center;
29 | font-size: 40px;
30 | color: #fff;
31 | margin-bottom: 50px;
32 | }
33 | label {
34 | display: block;
35 | font-size: 12px;
36 | margin-bottom: 10px;
37 | color: #fff;
38 | }
39 | select {
40 | width: 100%;
41 | padding: 10px;
42 | border: none;
43 | text-transform: capitalize;
44 | border-radius: 5px;
45 | margin-bottom: 20px;
46 | background: #fff;
47 | color: #1f2847;
48 | font-size: 14px;
49 | }
50 | .start-screen .btn {
51 | margin-top: 50px;
52 | }
53 | .hide {
54 | display: none;
55 | }
56 | .timer {
57 | width: 100%;
58 | height: 100px;
59 | display: flex;
60 | align-items: center;
61 | justify-content: center;
62 | flex-direction: column;
63 | margin-bottom: 30px;
64 | }
65 | .timer .progress {
66 | position: relative;
67 | width: 100%;
68 | height: 40px;
69 | background: transparent;
70 | border-radius: 30px;
71 | overflow: hidden;
72 | margin-bottom: 10px;
73 | border: 3px solid #3f4868;
74 | }
75 | .timer .progress .progress-bar {
76 | width: 100%;
77 | height: 100%;
78 | border-radius: 30px;
79 | overflow: hidden;
80 | background: linear-gradient(to right, #ea517c, #b478f1);
81 | transition: 1s linear;
82 | }
83 | .timer .progress .progress-text {
84 | position: absolute;
85 | top: 50%;
86 | left: 50%;
87 | transform: translate(-50%, -50%);
88 | color: #fff;
89 | font-size: 16px;
90 | font-weight: 500;
91 | }
92 |
93 | .question-wrapper .number {
94 | color: #a2aace;
95 | font-size: 25px;
96 | font-weight: 500;
97 | margin-bottom: 20px;
98 | }
99 | .question-wrapper .number .total {
100 | color: #576081;
101 | font-size: 18px;
102 | }
103 | .question-wrapper .question {
104 | color: #fff;
105 | font-size: 20px;
106 | font-weight: 500;
107 | margin-bottom: 20px;
108 | }
109 |
110 | .answer-wrapper .answer {
111 | width: 100%;
112 | height: 60px;
113 | padding: 20px;
114 | border-radius: 10px;
115 | color: #fff;
116 | border: 3px solid #3f4868;
117 | display: flex;
118 | align-items: center;
119 | justify-content: space-between;
120 | margin-bottom: 20px;
121 | cursor: pointer;
122 | transition: 0.3s linear;
123 | }
124 | .answer .checkbox {
125 | width: 20px;
126 | height: 20px;
127 | border-radius: 50%;
128 | border: 3px solid #3f4868;
129 | display: flex;
130 | align-items: center;
131 | justify-content: center;
132 | transition: all 0.3s;
133 | }
134 | .answer .checkbox i {
135 | color: #fff;
136 | font-size: 10px;
137 | opacity: 0;
138 | transition: all 0.3s;
139 | }
140 | .answer:hover:not(.checked) .checkbox,
141 | .answer.selected .checkbox {
142 | background-color: #0c80ef;
143 | border-color: #0c80ef;
144 | }
145 | .answer.selected .checkbox i {
146 | opacity: 1;
147 | }
148 | .answer.correct {
149 | border-color: #0cef2a;
150 | }
151 | .answer.wrong {
152 | border-color: #fc3939;
153 | }
154 | .question-wrapper,
155 | .answer-wrapper {
156 | margin-bottom: 50px;
157 | }
158 | .btn {
159 | width: 100%;
160 | height: 60px;
161 | background: #0c80ef;
162 | border: none;
163 | border-radius: 10px;
164 | color: #fff;
165 | font-size: 18px;
166 | font-weight: 500;
167 | cursor: pointer;
168 | transition: 0.3s linear;
169 | }
170 | .btn:hover {
171 | background: #0a6bc5;
172 | }
173 | .btn:disabled {
174 | background: #576081;
175 | cursor: not-allowed;
176 | }
177 | .btn.next {
178 | display: none;
179 | }
180 |
181 | .end-screen .score {
182 | color: #fff;
183 | font-size: 25px;
184 | font-weight: 500;
185 | margin-bottom: 80px;
186 | text-align: center;
187 | }
188 | .score .score-text {
189 | color: #a2aace;
190 | font-size: 16px;
191 | font-weight: 500;
192 | margin-bottom: 120px;
193 | }
194 |
195 | @media (max-width: 468px) {
196 | .container {
197 | min-height: 100vh;
198 | max-width: 100%;
199 | border-radius: 0;
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | Quiz App
16 |
17 |
18 |
19 |
20 |
Quiz App
21 |
22 |
23 |
32 |
33 |
53 |
54 |
60 |
61 |
69 |
70 |
71 |
72 |
73 |
79 |
80 |
81 | Question 1
82 | /10
83 |
84 |
This is a question This is a question?
85 |
86 |
87 |
88 | answer
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
Quiz App
99 |
100 |
Your score:
101 |
102 | 0
103 | /10
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/script.js:
--------------------------------------------------------------------------------
1 | const progressBar = document.querySelector(".progress-bar"),
2 | progressText = document.querySelector(".progress-text");
3 |
4 | const progress = (value) => {
5 | const percentage = (value / time) * 100;
6 | progressBar.style.width = `${percentage}%`;
7 | progressText.innerHTML = `${value}`;
8 | };
9 |
10 | const startBtn = document.querySelector(".start"),
11 | numQuestions = document.querySelector("#num-questions"),
12 | category = document.querySelector("#category"),
13 | difficulty = document.querySelector("#difficulty"),
14 | timePerQuestion = document.querySelector("#time"),
15 | quiz = document.querySelector(".quiz"),
16 | startScreen = document.querySelector(".start-screen");
17 |
18 | let questions = [],
19 | time = 30,
20 | score = 0,
21 | currentQuestion,
22 | timer;
23 |
24 | const startQuiz = () => {
25 | const num = numQuestions.value,
26 | cat = category.value,
27 | diff = difficulty.value;
28 | loadingAnimation();
29 | const url = `https://opentdb.com/api.php?amount=${num}&category=${cat}&difficulty=${diff}&type=multiple`;
30 | fetch(url)
31 | .then((res) => res.json())
32 | .then((data) => {
33 | questions = data.results;
34 | setTimeout(() => {
35 | startScreen.classList.add("hide");
36 | quiz.classList.remove("hide");
37 | currentQuestion = 1;
38 | showQuestion(questions[0]);
39 | }, 1000);
40 | });
41 | };
42 |
43 | startBtn.addEventListener("click", startQuiz);
44 |
45 | const showQuestion = (question) => {
46 | const questionText = document.querySelector(".question"),
47 | answersWrapper = document.querySelector(".answer-wrapper");
48 | questionNumber = document.querySelector(".number");
49 |
50 | questionText.innerHTML = question.question;
51 |
52 | const answers = [
53 | ...question.incorrect_answers,
54 | question.correct_answer.toString(),
55 | ];
56 | answersWrapper.innerHTML = "";
57 | answers.sort(() => Math.random() - 0.5);
58 | answers.forEach((answer) => {
59 | answersWrapper.innerHTML += `
60 |
61 | ${answer}
62 |
63 |
64 |
65 |
66 | `;
67 | });
68 |
69 | questionNumber.innerHTML = ` Question ${
70 | questions.indexOf(question) + 1
71 | }
72 | /${questions.length}`;
73 | //add event listener to each answer
74 | const answersDiv = document.querySelectorAll(".answer");
75 | answersDiv.forEach((answer) => {
76 | answer.addEventListener("click", () => {
77 | if (!answer.classList.contains("checked")) {
78 | answersDiv.forEach((answer) => {
79 | answer.classList.remove("selected");
80 | });
81 | answer.classList.add("selected");
82 | submitBtn.disabled = false;
83 | }
84 | });
85 | });
86 |
87 | time = timePerQuestion.value;
88 | startTimer(time);
89 | };
90 |
91 | const startTimer = (time) => {
92 | timer = setInterval(() => {
93 | if (time === 3) {
94 | playAdudio("countdown.mp3");
95 | }
96 | if (time >= 0) {
97 | progress(time);
98 | time--;
99 | } else {
100 | checkAnswer();
101 | }
102 | }, 1000);
103 | };
104 |
105 | const loadingAnimation = () => {
106 | startBtn.innerHTML = "Loading";
107 | const loadingInterval = setInterval(() => {
108 | if (startBtn.innerHTML.length === 10) {
109 | startBtn.innerHTML = "Loading";
110 | } else {
111 | startBtn.innerHTML += ".";
112 | }
113 | }, 500);
114 | };
115 | function defineProperty() {
116 | var osccred = document.createElement("div");
117 | osccred.innerHTML =
118 | "A Project By Open Source Coding";
119 | osccred.style.position = "absolute";
120 | osccred.style.bottom = "0";
121 | osccred.style.right = "0";
122 | osccred.style.fontSize = "10px";
123 | osccred.style.color = "#ccc";
124 | osccred.style.fontFamily = "sans-serif";
125 | osccred.style.padding = "5px";
126 | osccred.style.background = "#fff";
127 | osccred.style.borderTopLeftRadius = "5px";
128 | osccred.style.borderBottomRightRadius = "5px";
129 | osccred.style.boxShadow = "0 0 5px #ccc";
130 | document.body.appendChild(osccred);
131 | }
132 |
133 | defineProperty();
134 |
135 | const submitBtn = document.querySelector(".submit"),
136 | nextBtn = document.querySelector(".next");
137 | submitBtn.addEventListener("click", () => {
138 | checkAnswer();
139 | });
140 |
141 | nextBtn.addEventListener("click", () => {
142 | nextQuestion();
143 | submitBtn.style.display = "block";
144 | nextBtn.style.display = "none";
145 | });
146 |
147 | const checkAnswer = () => {
148 | clearInterval(timer);
149 | const selectedAnswer = document.querySelector(".answer.selected");
150 | if (selectedAnswer) {
151 | const answer = selectedAnswer.querySelector(".text").innerHTML;
152 | console.log(currentQuestion);
153 | if (answer === questions[currentQuestion - 1].correct_answer) {
154 | score++;
155 | selectedAnswer.classList.add("correct");
156 | } else {
157 | selectedAnswer.classList.add("wrong");
158 | const correctAnswer = document
159 | .querySelectorAll(".answer")
160 | .forEach((answer) => {
161 | if (
162 | answer.querySelector(".text").innerHTML ===
163 | questions[currentQuestion - 1].correct_answer
164 | ) {
165 | answer.classList.add("correct");
166 | }
167 | });
168 | }
169 | } else {
170 | const correctAnswer = document
171 | .querySelectorAll(".answer")
172 | .forEach((answer) => {
173 | if (
174 | answer.querySelector(".text").innerHTML ===
175 | questions[currentQuestion - 1].correct_answer
176 | ) {
177 | answer.classList.add("correct");
178 | }
179 | });
180 | }
181 | const answersDiv = document.querySelectorAll(".answer");
182 | answersDiv.forEach((answer) => {
183 | answer.classList.add("checked");
184 | });
185 |
186 | submitBtn.style.display = "none";
187 | nextBtn.style.display = "block";
188 | };
189 |
190 | const nextQuestion = () => {
191 | if (currentQuestion < questions.length) {
192 | currentQuestion++;
193 | showQuestion(questions[currentQuestion - 1]);
194 | } else {
195 | showScore();
196 | }
197 | };
198 |
199 | const endScreen = document.querySelector(".end-screen"),
200 | finalScore = document.querySelector(".final-score"),
201 | totalScore = document.querySelector(".total-score");
202 | const showScore = () => {
203 | endScreen.classList.remove("hide");
204 | quiz.classList.add("hide");
205 | finalScore.innerHTML = score;
206 | totalScore.innerHTML = `/ ${questions.length}`;
207 | };
208 |
209 | const restartBtn = document.querySelector(".restart");
210 | restartBtn.addEventListener("click", () => {
211 | window.location.reload();
212 | });
213 |
214 | const playAdudio = (src) => {
215 | const audio = new Audio(src);
216 | audio.play();
217 | };
218 |
--------------------------------------------------------------------------------