1
\$\begingroup\$

I created a simple quiz about HTML,CSS,JS it works fine but as always there is a lot of space for improvement in my code that's why I would love some feedback from you guys.

'use strict';

// ########################################################
// ########################################################
// ########################################################
// MAIN FUNCTIONALITY

const questionNumber = document.querySelector('.question-number');

let quizType;
let currentQuestionNuber = 1;
let goodAnswers = 0;

const displayCurrentQuestionNumber = () => {
  questionNumber.textContent = `${currentQuestionNuber}/5`;
};

displayCurrentQuestionNumber();

// ########################################################
// ########################################################
// ########################################################
// START QUIZ - DISPLAYING QUESTIONS AND ANSWERS

const htmlBtn = document.querySelector('.quiz-type__html');
const cssBtn = document.querySelector('.quiz-type__css');
const jsBtn = document.querySelector('.quiz-type__js');

const menu = document.querySelector('.menu');
const questionsBox = document.querySelector('.questions-box');
const resultsBox = document.querySelector('.result-box');
const quizTitle = document.querySelector('.quiz-title');

htmlBtn.addEventListener('click', () => {
  startQuiz('html');
});

cssBtn.addEventListener('click', () => {
  startQuiz('css');
});

jsBtn.addEventListener('click', () => {
  startQuiz('js');
});

const startQuiz = (type) => {
  quizType = type;
  quizTitle.textContent = quizType;
  setAnswersColor();
  menu.classList.add('swipeLeft');
  questionsBox.classList.add('swipeFromRight');
  draftQuestion();
};

// different background color for different technology
const setAnswersColor = () => {
  let answerBgc;
  if (quizType === 'html') {
    answerBgc = 'pink-red';
  } else if (quizType === 'css') {
    answerBgc = 'teal';
  } else {
    answerBgc = 'orange';
  }
  for (let i = 0; i < answers.children.length; i++) {
    answers.children[i].classList.add(`${answerBgc}`);
  }
};

// ########################################################
// ########################################################
// ########################################################
// END QUIZ - HIDE QUESTIONS AND ANSWERS, SHOW RESULT

const resultScore = document.querySelector('.correct-answers');

const hideQuestionsBox = () => {
  questionsBox.classList.toggle('display-none');
};

const showResultsBox = () => {
  resultsBox.classList.toggle('display-none');
};

const endGame = () => {
  hideQuestionsBox();
  showResultsBox();
  if (goodAnswers >= 3)
    resultScore.textContent = `Well done you answered ${goodAnswers}/5 correctly`;
  else
    resultScore.textContent = `You need to work a little because you answered ${goodAnswers}/5 questions correctly`;
};

// ########################################################
// ########################################################
// ########################################################
// DRAFTING QUESTIONS

const answers = document.querySelector('.questions-box__answers');
const question = document.querySelector('.question');

let htmlQuestions = {
  questions: [
    'HTML stands for?',
    'How is document type initialized in HTML5?',
    'Which of the following HTML Elements is used for making any text bold ?',
    'Which of the following HTML element is used for creating an unordered list?',
    'How many heading tags are there in HTML5?',
    'Which of the following attributes is used to add link to any element?',
    'Web pages starts with which of the following tag?',
  ],
  a: [
    'Hyper Text Markup Language',
    '</DOCTYPE HTML>',
    '<p>',
    '<ui>',
    '2',
    'link',
    '<html>',
  ],
  b: [
    'High Text Markup Language',
    '</DOCTYPE>',
    '<i>',
    '<b>',
    '3',
    'href',
    '<Title>',
  ],
  c: [
    'Hyper Tabular Markup Language',
    '<!DOCTYPE HTML>',
    '<li>',
    '<em>',
    '6',
    'ref',
    '<body>',
  ],
  d: [' None of these', '</DOCTYPE html>', '<b>', '<ul>', '5', 'src', '<form>'],
  goodAnswer: [
    'Hyper Text Markup Language',
    '<!DOCTYPE HTML>',
    '<b>',
    '<ul>',
    '6',
    'href',
    '<html>',
  ],
};

let cssQuestions = {
  questions: [
    'What property do you use to create spacing between HTML elements?',
    'What is the property used to set the class’s text color?',
    'CSS stands for?',
    'What property would you use to create space between the element’s border and inner content?',
    'What property do you use to set the background color?',
    'how do you give it a particular style when the user hovers over the element?',
    'How to set the style for a specific HTML element with an id of “special”?',
  ],
  a: [
    'margin',
    'text-color',
    'Cascading Style Sheets',
    'margin',
    'color',
    ':onHover',
    '#special{ }',
  ],
  b: [
    'spacing',
    'text',
    'Canvas Styling System',
    'spacing',
    'background-color',
    ':hover',
    '.special{ }',
  ],
  c: [
    'padding',
    'color',
    'Cascade Style System',
    'padding',
    'background',
    ':mouseOver',
    'id.special{ }',
  ],
  d: [
    'border',
    'font-color',
    'Cascading Style System',
    'border',
    'bg-color',
    ':active',
    'element.id.special{ }',
  ],
  goodAnswer: [
    'margin',
    'color',
    'Cascading Style Sheets',
    'padding',
    'background-color',
    ':hover',
    '#special{ }',
  ],
};

let jsQuestions = {
  questions: [
    'To insert a JavaScript into an HTML page, which tag is used?',
    'How to append a value to an array of Java Script?',
    'Which of the following function of String object executes the search for a match between a regular expression and a specified string?',
    'Which built-in method calls a function for each element in the array?',
    'How can we check the length of an array?',
    'How to log text in console?',
    'Which variable definition is correct',
  ],
  a: [
    `<script='java'>`,
    'arr[arr.length] = value',
    'concat()',
    'for',
    'length(arr)',
    'console.log()',
    'var 1a',
  ],
  b: [
    '<javascript>',
    'arr[arr.length-1] = value',
    'includes()',
    'loop',
    'arr.length',
    'clog()',
    'let 1a',
  ],
  c: [
    '<script>',
    'arr[arr.length+1] = new Arrays()',
    'match()',
    'while',
    'arr.length()',
    'console.text()',
    'let a1',
  ],
  d: [
    '<js>',
    'arr[arr.length*1] = value',
    'test',
    'forEach',
    'arr(length)',
    'print()',
    'int a ',
  ],
  goodAnswer: [
    '<script>',
    'arr[arr.length] = value',
    'match()',
    'forEach',
    'arr.length',
    'console.log()',
    'let a1',
  ],
};

function getRandomInt(max) {
  return Math.floor(Math.random() * Math.floor(max));
}

let randomNumber;
let answeredQuestions = [];

const draftQuestion = () => {
  randomNumber = getRandomInt(7);
  if (quizType === 'html') {
    if (!answeredQuestions.includes(randomNumber)) {
      question.textContent = htmlQuestions.questions[randomNumber];
      answers.children[0].textContent = htmlQuestions.a[randomNumber];
      answers.children[1].textContent = htmlQuestions.b[randomNumber];
      answers.children[2].textContent = htmlQuestions.c[randomNumber];
      answers.children[3].textContent = htmlQuestions.d[randomNumber];
      answeredQuestions.push(randomNumber);
    } else {
      draftQuestion('html');
    }
  } else if (quizType === 'css') {
    if (!answeredQuestions.includes(randomNumber)) {
      question.textContent = cssQuestions.questions[randomNumber];
      answers.children[0].textContent = cssQuestions.a[randomNumber];
      answers.children[1].textContent = cssQuestions.b[randomNumber];
      answers.children[2].textContent = cssQuestions.c[randomNumber];
      answers.children[3].textContent = cssQuestions.d[randomNumber];
      answeredQuestions.push(randomNumber);
    } else {
      draftQuestion('css');
    }
  } else {
    if (!answeredQuestions.includes(randomNumber)) {
      question.textContent = jsQuestions.questions[randomNumber];
      answers.children[0].textContent = jsQuestions.a[randomNumber];
      answers.children[1].textContent = jsQuestions.b[randomNumber];
      answers.children[2].textContent = jsQuestions.c[randomNumber];
      answers.children[3].textContent = jsQuestions.d[randomNumber];
      answeredQuestions.push(randomNumber);
    } else {
      draftQuestion('js');
    }
  }
};

// ########################################################
// ########################################################
// ########################################################
// CHECK IN ANSWER IS GOOD OR NOT

const isGoodAnswer = (answer) => {
  if (quizType === 'html') {
    if (answer.textContent === htmlQuestions.goodAnswer[randomNumber])
      return true;
    return false;
  } else if (quizType === 'css') {
    if (answer.textContent === cssQuestions.goodAnswer[randomNumber])
      return true;
    return false;
  }
  if (answer.textContent === jsQuestions.goodAnswer[randomNumber]) return true;
  return false;
};

for (let i = 0; i < answers.children.length; i++) {
  answers.children[i].addEventListener('click', () => {
    if (isGoodAnswer(answers.children[i])) {
      goodAnswers++;
    }
    if (currentQuestionNuber === 5) endGame();
    else {
      currentQuestionNuber++;
      displayCurrentQuestionNumber();
      draftQuestion();
    }
  });
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style/main.css">
    <title>Quiz</title>
</head>
<body>
    <main>
        <div class="menu">
            <h2>Quiz</h2>
            <p>Web site technologies</p>
            <p>Select quiz </p>
            <div class="quiz-type">
                <div class="quiz-type__html">HTML</div>
                <div class="quiz-type__css">CSS</div>
                <div class="quiz-type__js">JavaScript</div>
            </div>
        </div>
        <div class="questions-box">
            <h3 class='quiz-title'></h3>
            <p class='question'></p>
            <p class="question-number"></p>
            <div class="questions-box__answers">
                <a class="questions-box__answer"></a>
                <a class="questions-box__answer"></a>
                <a class="questions-box__answer"></a>
                <a class="questions-box__answer"></a>
            </div>
        </div>
        <div class="result-box display-none">
            <h3>RESULTS</h3>
            <p class="correct-answers">aa</p>
        </div>
    </main>
    <script src="script.js"></script>
</body>
</html>
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;600&display=swap");
*,
*::after,
*::before {
  padding: 0;
  margin: 0;
  -webkit-box-sizing: border-box;
          box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}

body {
  background-color: #111010;
  height: 100vh;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
}

main {
  background-color: #fffbfc;
  padding: 10rem 20rem;
  border-radius: 5px;
  overflow: hidden;
  position: relative;
}

main .menu {
  text-align: center;
  -webkit-transition: all 1s;
  transition: all 1s;
}

main .menu h2 {
  font-size: 2rem;
  font-weight: 600;
  color: black;
}

main .menu p {
  font-size: 1rem;
  font-weight: 300;
  color: #353535;
  margin-bottom: 1.3rem;
}

main .menu .quiz-type {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
}

main .menu .quiz-type div {
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  padding: 1rem 2rem;
  border-radius: 5px;
  cursor: pointer;
  font-size: 0.8rem;
  font-weight: 600;
  color: white;
}

main .menu .quiz-type div:not(:first-child) {
  margin-left: 0.2rem;
}

main .menu .quiz-type__html {
  background-color: #d81159;
}

main .menu .quiz-type__html:hover {
  background-color: #bd0f4f;
}

main .menu .quiz-type__css {
  background-color: #008f8f;
}

main .menu .quiz-type__css:hover {
  background-color: teal;
}

main .menu .quiz-type__js {
  background-color: #fbb13c;
}

main .menu .quiz-type__js:hover {
  background-color: #fba823;
}

main .questions-box {
  padding: 3rem 10rem;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translateX(200%) translateY(-50%);
          transform: translateX(200%) translateY(-50%);
  -webkit-transition: all 1s;
  transition: all 1s;
  text-align: center;
}

main .questions-box .quiz-title {
  font-size: 1.7rem;
  font-weight: 600;
  color: black;
  text-transform: uppercase;
}

main .questions-box .question {
  font-size: 1rem;
  font-weight: bold;
  color: #1b1b1b;
  margin-bottom: 1.3rem;
  margin-top: 2.5rem;
}

main .questions-box .question-number {
  position: absolute;
  top: 3rem;
  left: 3rem;
  font-weight: bold;
  font-size: 1.2rem;
}

main .questions-box__answer {
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  outline: none;
  display: block;
  color: White;
  font-weight: 300;
  border-radius: 5px;
  padding: 1rem 0;
  cursor: pointer;
}

main .questions-box__answer:not(:first-child) {
  margin-top: 0.7rem;
}

main .result-box {
  padding: 3rem 10rem;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  text-align: center;
}

main .result-box h3 {
  font-size: 1.7rem;
  font-weight: 600;
  color: black;
}

main .result-box .correct-answers {
  margin-top: 2.5rem;
}

.swipeLeft {
  -webkit-transform: translateX(-200%);
          transform: translateX(-200%);
}

.swipeFromRight {
  -webkit-transform: translateX(-50%) translateY(-50%) !important;
          transform: translateX(-50%) translateY(-50%) !important;
}

.pink-red {
  background-color: #d81159;
}

.pink-red:hover {
  background-color: #bd0f4f;
}

.teal {
  background-color: #008f8f;
}

.teal:hover {
  background-color: teal;
}

.orange {
  background-color: #faa00f;
}

.orange:hover {
  background-color: #dc8904;
}

.display-none {
  display: none;
}
\$\endgroup\$
1
\$\begingroup\$

Well, the code is not bad.

JS:

htmlBtn.addEventListener('click', () => {
  startQuiz('html');
});

could be shortened to

htmlBtn.addEventListener('click', () => startQuiz('html'));

or

const showResultsBox = () => {
  resultsBox.classList.toggle('display-none');
};

to

const showResultsBox = () => resultsBox.classList.toggle('display-none');

CSS:

display: -webkit-box;
  display: -ms-flexbox;
  display: flex;

are you sure You need to use all of those prefixes ? Isn't display: flex enough ?

  background-color: #d81159; 

is used twice. Create a selector that covers multiple elements instead of repeating the code :)

Aditionally:

  • I'd add the colors declarations to the separate file :)
  • I heard that it's better to get the elements in JS by getElementByID() (if possible) because it's faster but I'm not 100% sure about that. Maybe it's worth taking a look :)
  • Your quiz-type-buttons are divs which is a mistake because of the accessibility standards. They should be regular buttons so that screen readers understand what's going on
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.