Skip to content

Instantly share code, notes, and snippets.

@batazo
Last active August 10, 2021 19:33
Show Gist options
  • Select an option

  • Save batazo/eb12d03b0978e9d00aa3edf933c6e4da to your computer and use it in GitHub Desktop.

Select an option

Save batazo/eb12d03b0978e9d00aa3edf933c6e4da to your computer and use it in GitHub Desktop.
Webdeveloper Quiz v14

Webdeveloper Quiz v14

Responsive Quiz Game built with HTML5 , CSS3 and Javascript.

A Pen by Bzozoo on CodePen.

License.

<div id="container">
<header>
<h1>Webdeveloper Quiz</h1><span id="verSpan"></span>
</header>
<div id="result" class="hidden"></div>
<div id="questionDIV">
<div class="load">
<img src="
https://c.tenor.com/I6kN-6X7nhAAAAAj/loading-buffering.gif" />
</div>
</div><!-- questionDIV end -->
<div id="actions">
<button id="evaluate" onclick="runEvaluation()">KIÉRTÉKEL</button>
</div>
</div><!-- Conmtainer end-->
//Globals
const version = "v14";
let answerareas;
let questionlimit = 10;
let qinputs;
//Inits
renerAllQuestions();
verSpan.innerHTML = `(${version})`;
//Renders
//Evaluation renders
async function renderEvaluation(answerareasN) {
answerareasN.nextElementSibling.innerHTML = "";
let renderString = await evaluationTemplate(
await evaluationTempleteVars(answerareasN)
);
answerareasN.nextElementSibling.innerHTML += renderString;
answerareasN.nextElementSibling.classList.remove("hidden");
}
async function renderAllEvaluation() {
for (let answerarea of answerareas) {
await renderEvaluation(answerarea);
}
}
//Score renders
async function renderScore() {
let renderString = await scoreTemplate(await scoreTemplateVars());
result.innerHTML = await renderString;
}
//Question renders
async function renerAllQuestions() {
questionDIV.innerHTML = "";
let renderString = "";
let questions = await getQuestionList();
if (!questions) {
renderString += `<p>SERVER ERROR <button onclick="renerAllQuestions()">REFRESH</button></p>`;
questionDIV.innerHTML += renderString;
} else {
for (let question of questions) {
renderString = await questionTemplate(await questionTemplateVars(question));
questionDIV.innerHTML += await renderString;
}
}
refreshSelectors();
}
//Templates amd TemplateVars
//Questions Templs
async function questionTemplateVars(injectedVars) {
return {
questionId: injectedVars.id,
questionNumber: injectedVars.qnumber,
question: injectedVars.question,
answerAreaHTML: allAnswerBoxTemplate(
allAnswerBoxTemplateVars(injectedVars.answers, injectedVars.qnumber)
),
default: "OK"
};
}
async function questionTemplate(templateVars) {
return `
<div id="question-${templateVars.questionNumber}" class="questioninput">
<h3 id="Q${templateVars.questionNumber}"> ${templateVars.questionNumber}. Kérdés: ${templateVars.question}</h3>
<div class="answerarea" id="answerarea-${templateVars.questionNumber}" data-qid="${templateVars.questionId}">
${templateVars.answerAreaHTML}
</div><!-- end of answerarea -->
<div id="explanOf${templateVars.questionNumber}_${templateVars.questionId}" class="explanation hidden"></div>
<hr>
</div><!-- questioninput end -->`;
}
//Answers Templs
function allAnswerBoxTemplateVars(injectedVarsAnswers, injectedVarsQNumber) {
let allansverboxHTML = "";
for (let injectedVarsAnswer of injectedVarsAnswers) {
allansverboxHTML += answerboxTemplate(
answerboxTemplateVars(injectedVarsAnswer, injectedVarsQNumber)
);
}
return {
answerboxes: allansverboxHTML
};
}
function allAnswerBoxTemplate(templateVars) {
return `
${templateVars.answerboxes}
`;
}
function answerboxTemplateVars(injectedVarsAnswer, injectedVarsQNumber) {
return {
questionNumber: injectedVarsQNumber,
answerNumber: injectedVarsAnswer.anumber,
answerId: injectedVarsAnswer.id,
answerString: injectedVarsAnswer.answer
};
}
function answerboxTemplate(templateVars) {
return `
<input type="radio" name="Q${templateVars.questionNumber}" id="Q${templateVars.questionNumber}A${templateVars.answerNumber}" data-aid="${templateVars.answerId}" />
<label for="Q${templateVars.questionNumber}A${templateVars.answerNumber}">${templateVars.answerString}</label>`;
}
//Evalution Templs
async function evaluationTempleteVars(answerareasN) {
let data = await checkAnswerByAnswerarea(answerareasN);
let explan =
data.explanation == undefined ? "Nem jelöltél ki választ" : data.explanation;
let correct = data.correct
? "A válaszod helyes!"
: "A válaszod sajnos helytelen!";
let correctColor = data.correct ? "green" : "red";
let success = data.correct ? true : false;
let whatCorrects = data.correctAnswers == undefined ? "" : data.correctAnswers;
let whatCorrectString = whatCorrects ? getGoodAnswersStringFromData(data) : "";
return {
explan: explan,
correct: correct,
success: success,
correctColor: correctColor,
whatCorrectString: whatCorrectString
};
}
function evaluationTemplate(templateVar) {
return `
<p data-chksuccess="${templateVar.success}"><b style="color: ${templateVar.correctColor}">${templateVar.correct}</b>
${templateVar.whatCorrectString}
</p>
<p>${templateVar.explan}</p>
`;
}
//Score Templs
async function scoreTemplateVars(injectedvars) {
let goodAnswers = document.querySelectorAll(
`.explanation p[data-chksuccess="true"] `
).length;
return {
score: goodAnswers,
scorePercent: goodAnswers / (questionlimit / 100)
};
}
async function scoreTemplate(templateVars) {
return `A pontjaid száma: ${templateVars.score} (${templateVars.scorePercent} %)`;
}
//Controllers
async function getQuestionList() {
try {
const questions = await getQuestion();
let questionNumber = 1;
let answerNumber = 0;
for (let question of questions) {
question.qnumber = questionNumber++;
for (let answer of question.answers) {
answer.anumber = answerNumber++;
}
}
return questions;
} catch (e) {
console.log(e);
return false;
}
}
function getAnswerareaDatasetQid(answerareasN) {
return answerareasN.dataset.qid;
}
function getAnswerareaSelectedDatasetAids(answerareasN) {
let checkedAnswers = document.querySelectorAll(
`#${answerareasN.id} input:checked`
);
let selected = [];
for (let checkedAnswer of checkedAnswers) {
selected.push(checkedAnswer.dataset.aid);
}
return selected;
}
function getAnswerareaAllDatasetAids(answerareasN) {
let answersInArea = document.querySelectorAll(`#${answerareasN.id} input`);
let answerareaAids = [];
for (let answerInArea of answersInArea) {
answerareaAids.push(answerInArea.dataset.aid);
}
return answerareaAids;
}
function getGoodAnswersFromData(fromdata) {
let goodAnswers = [];
for (let data of fromdata.correctAnswers) {
goodAnswers.push(data.id);
}
return goodAnswers;
}
function getGoodAnswersStringFromData(fromdata) {
let goodAnswers = "A helyes válasz(ok): ";
for (let data of fromdata.correctAnswers) {
goodAnswers += data.answer;
}
return goodAnswers;
}
async function checkAnswerByAnswerarea(answerareasN) {
let qid = getAnswerareaDatasetQid(answerareasN);
let aids = getAnswerareaSelectedDatasetAids(answerareasN);
return await checkAnswer(qid, aids);
}
//Data Queries
async function getQuestion() {
const endpoint =
"https://webdevquiz.mysqhost.ml:8090/api/questionlist/" + questionlimit;
const response = await fetch(endpoint);
const data = await response.json();
return data;
}
async function checkAnswer(qid, aids) {
const endpoint = "https://webdevquiz.mysqhost.ml:8090/api/check/";
const bodyData = {
questionId: qid,
selectedAnswerIds: aids
};
const options = {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(bodyData)
};
const response = await fetch(endpoint, options);
const data = await response.json();
return data;
}
//Helpers
function refreshSelectors() {
answerareas = document.querySelectorAll("[data-qid]");
qinputs = document.querySelectorAll(".questioninput");
}
//Evnent handlers
async function runEvaluation() {
result.innerHTML = "Scores loading....";
result.classList.remove("hidden");
window.scrollTo(0, 0);
await renderAllEvaluation();
renderScore();
}
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
* { box-sizing: border-box;
}
body {
background-image: url("https://i.imgur.com/qzpVNy0.jpg");
font-family: 'Roboto', sans-serif;
margin: 40px;
display: flex;
flex-wrap: wrap;
}
#container {
background-color:#2992bf;
border-radius: 10px;
display: block;
flex-wrap: wrap;
box-shadow: 3px 5px 7px 3px #8395a7;
align-items: center;
justify-content: center;
color: #fff;
padding: 15px;
}
header {
border-bottom:1px dotted white;
text-align:center;
}
header h1 { margin:0; padding:0;}
.hidden {
display: none;
}
.explanation {
color: gray;
padding: 10px;
border: 1px solid gray;
background-color: lightgray;
}
#result {
margin: 10px;padding: 10px;background-color: lightgray;border: 3px solid blue;color: darkblue;
}
.success {
color: lightgreen;
}
.unsuccessful {
color: red;
}
#container,
form { min-width:100%;}
.questioninput { margin-bottom:30px;}
.load {
text-align: center; padding-top:60px;padding-bottom:60px;
}
.questioninput input{
display: none;
padding: 15px;
}
.questioninput label{
color: black;
padding: 15px;
margin: 15px;
width: 300px;
display:inline-block;
text-align: center;
border-radius: 10px;
background-color: lightgray;
box-shadow: 3px 3px 9px 3px #075c77;
font-size: larger;
}
.questioninput label:hover{
background-color: gray;
}
.questioninput input[type="radio"]:checked + label {
border: 2px solid blue;
background-color: gray;
}
.questioninput hr{
height: 10px;
border: 0;
box-shadow: 0 10px 10px -10px #1f246c8a inset;
}
#actions {
text-align: center;
}
#actions button {
text-align: center;
padding: 20px;
border-radius: 15px;
color: white;
background-color: #2d8ae7;
}
.answerarea{
text-align: center;
}
@media screen and (max-width: 795px){
.questioninput label{
width: 90%;
}
body{
margin: 0px;
}
}
@media screen and (max-width: 600px) {
form {
margin:initial;
text-align:initial;
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment