Comment faire un simple questionnaire JavaScript – SitePoint


“Comment faire un quiz JavaScript?” est l’une des questions les plus fréquemment posées par les personnes qui apprennent le développement Web, et pour cause. Les quiz sont amusants! Ils sont un excellent moyen d’apprendre de nouveaux sujets et ils vous permettent d’engager votre public avec quelque chose d’amusant et de ludique.

Cet article populaire a été mis à jour en 2020 pour refléter les meilleures pratiques actuelles en JavaScript. Pour une connaissance plus approfondie de JavaScript, lisez notre livre, JavaScript: Novice to Ninja, 2nd Edition.

Comment faire un quiz JavaScript

Coder votre propre quiz JavaScript est également un exercice d’apprentissage fantastique. Il vous apprend à gérer les événements, à manipuler le DOM, à gérer les entrées de l’utilisateur, à donner des commentaires à l’utilisateur et à suivre son score (par exemple, en utilisant le stockage côté client). Et lorsque vous avez un quiz de base opérationnel, il y a tout un tas de possibilités pour ajouter des fonctionnalités plus avancées, telles que la pagination. J’y vais à la fin de l’article.

Dans ce didacticiel, je vais vous guider tout en créant un quiz JavaScript en plusieurs étapes que vous pourrez adapter à vos besoins et ajouter à votre propre site. Si vous souhaitez voir ce que nous allons finir, vous pouvez passer à l’étape suivante et voir le quiz de travail.

À savoir avant de commencer

Quelques choses à savoir avant de commencer:

  • Il s’agit d’un didacticiel frontal, ce qui signifie que toute personne qui sait parcourir le code source d’une page peut trouver les réponses. Pour les questionnaires sérieux, les données doivent être traitées via le back-end, ce qui dépasse le cadre de ce didacticiel.
  • Le code de cet article utilise la syntaxe JavaScript moderne (ES6 +), ce qui signifie qu’il ne sera compatible avec aucune version d’Internet Explorer. Cependant, cela fonctionnera très bien sur les navigateurs modernes, y compris Microsoft Edge.
  • Si vous devez prendre en charge des navigateurs plus anciens, j’ai écrit un Tutoriel de quiz JavaScript compatible avec IE8. Ou, si vous souhaitez un rafraîchissement sur ES6, consultez ce cours de Darin Haener sur SitePoint Premium.
  • Vous aurez besoin de vous familiariser avec HTML, CSS et JavaScript, mais chaque ligne de code sera expliquée individuellement.

La structure de base de votre quiz JavaScript

Idéalement, nous voulons que les questions et réponses du quiz soient dans notre code JavaScript et que notre script génère automatiquement le quiz. De cette façon, nous n’aurons pas besoin d’écrire beaucoup de balisage répétitif, et nous pouvons facilement ajouter et supprimer des questions.

Pour configurer la structure de notre quiz JavaScript, nous devons commencer par le code HTML suivant:

  • UNE
    tenir le quiz
  • UNE
  • UNE
    pour afficher les résultats

Voici à quoi cela ressemblerait:

Nous pouvons ensuite sélectionner ces éléments HTML et stocker leurs références dans des variables comme ceci:

const quizContainer = document.getElementById('quiz');
const resultsContainer = document.getElementById('results');
const submitButton = document.getElementById('submit');

Ensuite, nous aurons besoin d’un moyen de créer un quiz, d’afficher les résultats et de tout assembler. Nous pouvons commencer par définir nos fonctions, et nous les remplirons au fur et à mesure:

function buildQuiz(){}

function showResults(){}

// display quiz right away
buildQuiz();

// on submit, show results
submitButton.addEventListener('click', showResults);

Ici, nous avons des fonctions pour construire le quiz et afficher les résultats. Nous exécuterons notre buildQuiz fonctionner immédiatement, et nous aurons notre showResults La fonction s’exécute lorsque l’utilisateur clique sur le bouton Soumettre.

Affichage des questions du quiz

La prochaine chose dont notre quiz a besoin est quelques questions à afficher. Nous utiliserons des littéraux d’objets pour représenter les questions individuelles et un tableau pour contenir toutes les questions qui composent notre quiz. L’utilisation d’un tableau facilitera l’itération des questions:

const myQuestions = [
  {
    question: "Who invented JavaScript?",
    answers: {
      a: "Douglas Crockford",
      b: "Sheryl Sandberg",
      c: "Brendan Eich"
    },
    correctAnswer: "c"
  },
  {
    question: "Which one of these is a JavaScript package manager?",
    answers: {
      a: "Node.js",
      b: "TypeScript",
      c: "npm"
    },
    correctAnswer: "c"
  },
  {
    question: "Which tool can you use to ensure code quality?",
    answers: {
      a: "Angular",
      b: "jQuery",
      c: "RequireJS",
      d: "ESLint"
    },
    correctAnswer: "d"
  }
];

N’hésitez pas à poser autant de questions ou de réponses que vous le souhaitez.

Remarque: comme il s’agit d’un tableau, les questions s’affichent dans l’ordre dans lequel elles sont répertoriées. Si vous souhaitez trier les questions de quelque manière que ce soit avant de les présenter à l’utilisateur, consultez notre astuce rapide sur le tri d’un tableau d’objets en JavaScript.

Maintenant que nous avons notre liste de questions, nous pouvons les afficher sur la page. Nous allons parcourir la ligne JavaScript suivante ligne par ligne pour voir comment cela fonctionne:

function buildQuiz(){
  // variable to store the HTML output
  const output = [];

  // for each question...
  myQuestions.forEach(
    (currentQuestion, questionNumber) => {

      // variable to store the list of possible answers
      const answers = [];

      // and for each available answer...
      for(letter in currentQuestion.answers){

        // ...add an HTML radio button
        answers.push(
          ``
        );
      }

      // add this question and its answers to the output
      output.push(
        `
${currentQuestion.question}
${answers.join('')}
` ); } ); // finally combine our output list into one string of HTML and put it on the page quizContainer.innerHTML = output.join(''); }

Tout d’abord, nous créons un output variable pour contenir toute la sortie HTML, y compris les questions et les choix de réponse.

Ensuite, nous pouvons commencer à construire le code HTML pour chaque question. Nous devons parcourir chaque question comme suit:

myQuestions.forEach( (currentQuestion, questionNumber) => {
  // the code we want to run for each question goes here
});

Par souci de concision, nous utilisons une fonction de flèche pour effectuer nos opérations sur chaque question. Parce que c’est dans un pour chaque boucle, nous obtenons la valeur actuelle, l’index (le numéro de position de l’élément actuel dans le tableau), et le tableau lui-même en tant que paramètres. Nous avons seulement besoin de la valeur actuelle et de l’index, que nous appellerons à nos fins currentQuestion et questionNumber respectivement.

Regardons maintenant le code dans notre boucle:

// we'll want to store the list of answer choices
const answers = [];

// and for each available answer...
for(letter in currentQuestion.answers){

  // ...add an html radio button
  answers.push(
    ``
  );
}

// add this question and its answers to the output
output.push(
  `
${currentQuestion.question}
${answers.join('')}
` );

Pour chaque question, nous souhaitons générer le code HTML correct. Par conséquent, notre première étape consiste à créer un tableau contenant la liste des réponses possibles.

Ensuite, nous utiliserons une boucle pour remplir les réponses possibles à la question actuelle. Pour chaque choix, nous créons un bouton radio HTML, que nous enfermons dans un élément. Cela permet aux utilisateurs de cliquer n’importe où sur le texte de la réponse pour sélectionner cette réponse. Si l’étiquette était omise, les utilisateurs devraient cliquer sur le bouton radio lui-même, qui n’est pas très accessible.

Notez que nous utilisons littéraux de modèle, qui sont des chaînes mais plus puissantes. Nous utiliserons les fonctionnalités suivantes:

  • capacités multi-lignes
  • plus besoin de échapper guillemets entre guillemets parce que les littéraux de modèle utilisent des crochets
  • interpolation de chaînes, afin que vous puissiez incorporer des expressions JavaScript directement dans vos chaînes comme ceci: ${code_goes_here}.

Une fois que nous avons notre liste de boutons de réponse, nous pouvons pousser la question HTML et la réponse HTML sur notre liste globale de sorties.

Notez que nous utilisons un modèle littéral et des expressions intégrées pour créer d’abord le div de question, puis créer le div de réponse. le join expression prend notre liste de réponses et les rassemble dans une chaîne que nous pouvons sortir dans notre answers div.

Maintenant que nous avons généré le code HTML pour chaque question, nous pouvons le regrouper et l’afficher sur la page:

quizContainer.innerHTML = output.join('');

Maintenant notre buildQuiz la fonction est terminée.

Vous devriez pouvoir exécuter le quiz à ce stade et voir les questions affichées. Veuillez noter, cependant, que la structure de votre code est importante. En raison de quelque chose appelé zone morte temporelle, vous ne pouvez pas référencer votre tableau de questions avant qu’il ne soit défini.

Pour récapituler, voici la structure correcte:

// Functions
function buildQuiz(){ ... }
function showResults(){ ... }

// Variables
const quizContainer = document.getElementById('quiz');
const resultsContainer = document.getElementById('results');
const submitButton = document.getElementById('submit');
const myQuestions = [ ... ];

// Kick things off
buildQuiz();

// Event listeners
submitButton.addEventListener('click', showResults);

Affichage des résultats du quiz

À ce stade, nous voulons développer notre showResults pour parcourir les réponses, les vérifier et afficher les résultats.

Voici la fonction, que nous allons parcourir en détail ensuite:

function showResults(){

  // gather answer containers from our quiz
  const answerContainers = quizContainer.querySelectorAll('.answers');

  // keep track of user's answers
  let numCorrect = 0;

  // for each question...
  myQuestions.forEach( (currentQuestion, questionNumber) => {

    // find selected answer
    const answerContainer = answerContainers[questionNumber];
    const selector = `input[name=question${questionNumber}]:checked`;
    const userAnswer = (answerContainer.querySelector(selector) || {}).value;

    // if answer is correct
    if(userAnswer === currentQuestion.correctAnswer){
      // add to the number of correct answers
      numCorrect++;

      // color the answers green
      answerContainers[questionNumber].style.color = 'lightgreen';
    }
    // if answer is wrong or blank
    else{
      // color the answers red
      answerContainers[questionNumber].style.color = 'red';
    }
  });

  // show number of correct answers out of total
  resultsContainer.innerHTML = `${numCorrect} out of ${myQuestions.length}`;
}

Tout d’abord, nous sélectionnons tous les conteneurs de réponses dans le code HTML de notre quiz. Ensuite, nous créerons des variables pour garder une trace de la réponse actuelle de l’utilisateur et du nombre total de réponses correctes.

// gather answer containers from our quiz
const answerContainers = quizContainer.querySelectorAll('.answers');

// keep track of user's answers
let numCorrect = 0;

Maintenant, nous pouvons parcourir chaque question et vérifier les réponses.

// for each question...
myQuestions.forEach( (currentQuestion, questionNumber) => {

  // find selected answer
  const answerContainer = answerContainers[questionNumber];
  const selector = `input[name=question${questionNumber}]:checked`;
  const userAnswer = (answerContainer.querySelector(selector) || {}).value;

  // if answer is correct
  if(userAnswer === currentQuestion.correctAnswer){
    // add to the number of correct answers
    numCorrect++;

    // color the answers green
    answerContainers[questionNumber].style.color = 'lightgreen';
  }
  // if answer is wrong or blank
  else{
    // color the answers red
    answerContainers[questionNumber].style.color = 'red';
  }
});

L’essentiel général de ce code est:

  • trouver la réponse sélectionnée dans le HTML
  • gérer ce qui se passe si la réponse est correcte
  • gérer ce qui se passe si la réponse est fausse.

Voyons de plus près comment nous trouvons la réponse sélectionnée dans notre code HTML:

// find selected answer
const answerContainer = answerContainers[questionNumber];
const selector = `input[name=question${questionNumber}]:checked`;
const userAnswer = (answerContainer.querySelector(selector) || {}).value;

Tout d’abord, nous nous assurons que nous regardons à l’intérieur du conteneur de réponses pour la question actuelle.

Dans la ligne suivante, nous définissons un sélecteur CSS qui nous permettra de trouver quel bouton radio est coché.

Ensuite, nous utilisons JavaScript querySelector pour rechercher notre sélecteur CSS dans le précédemment défini answerContainer. Essentiellement, cela signifie que nous trouverons la case d’option de la réponse qui est cochée.

Enfin, nous pouvons obtenir la valeur de cette réponse en utilisant .value.

Gérer les entrées utilisateur incomplètes

Mais que se passe-t-il si l’utilisateur a laissé une réponse vide? Dans ce cas, en utilisant .value entraînerait une erreur, car vous ne pouvez pas obtenir la valeur de quelque chose qui n’est pas là. Pour résoudre ce problème, nous avons ajouté ||, ce qui signifie «ou», et {}, qui est un objet vide. Maintenant, la déclaration globale dit:

  • Obtenez une référence à notre élément de réponse sélectionné OU, s’il n’existe pas, utilisez un objet vide.
  • Obtenez la valeur de ce qui était dans la première instruction.

Par conséquent, la valeur sera la réponse de l’utilisateur ou undefined, ce qui signifie qu’un utilisateur peut ignorer une question sans planter notre questionnaire.

Évaluation des réponses et affichage du résultat

Les prochaines déclarations de notre boucle de vérification des réponses nous permettront de gérer les réponses correctes et incorrectes.

// if answer is correct
if(userAnswer === currentQuestion.correctAnswer){
  // add to the number of correct answers
  numCorrect++;

  // color the answers green
  answerContainers[questionNumber].style.color = 'lightgreen';
}
// if answer is wrong or blank
else{
  // color the answers red
  answerContainers[questionNumber].style.color = 'red';
}

Si la réponse de l’utilisateur correspond au bon choix, augmentez le nombre de bonnes réponses d’une unité et (éventuellement) colorez l’ensemble des choix en vert. Si la réponse est fausse ou vide, coloriez les choix de réponse en rouge (encore une fois, facultatif).

Une fois la boucle de vérification des réponses terminée, nous pouvons montrer combien de questions l’utilisateur a eu raison:

// show number of correct answers out of total
resultsContainer.innerHTML = `${numCorrect} out of ${myQuestions.length}`;

Et maintenant, nous avons un quiz JavaScript fonctionnel!

Si vous le souhaitez, vous pouvez envelopper l’ensemble du quiz dans un IIFE (expression de fonction immédiatement invoquée), qui est une fonction qui s’exécute dès que vous la définissez. Cela gardera vos variables hors de portée globale et garantira que votre quiz n’interfère pas avec les autres scripts en cours d’exécution sur la page.

(function(){
  // put the rest of your code here
})();

Maintenant vous êtes prêt! N’hésitez pas à ajouter ou supprimer des questions et des réponses et à personnaliser le quiz comme vous le souhaitez.

À ce stade, votre quiz pourrait ressembler à ceci (avec un tout petit peu de style):

Voir le stylo
Quiz JavaScript simple (sans pagination)
par SitePoint (@SitePoint)
sur CodePen.

Maintenant, notre quiz de base est en cours d’exécution, voyons quelques fonctionnalités plus avancées. Par exemple, supposons que vous ne souhaitiez afficher qu’une seule question à la fois.

Tu auras besoin:

  • un moyen d’afficher et de masquer les questions
  • pour naviguer dans le quiz.

Nous aurons besoin de faire quelques mises à jour, alors commençons par le HTML:

La plupart de ce balisage est le même qu’avant, mais nous avons maintenant ajouté des boutons de navigation et un conteneur de quiz. Le conteneur de quiz nous aidera à positionner les questions en tant que couches que nous pouvons afficher et masquer.

Ensuite, à l’intérieur du buildQuiz fonction, nous devons ajouter un

élément avec classe slide pour contenir les conteneurs de questions et réponses que nous venons de créer:

output.push(
  `
${currentQuestion.question}
${answers.join("")}
` );

Ensuite, nous pouvons utiliser un positionnement CSS pour faire en sorte que les diapositives s’asseyent en couches les unes sur les autres. Dans cet exemple, vous remarquerez que nous utilisons des index z et des transitions d’opacité pour permettre à nos diapositives de fondre en avant et en arrière. Voici à quoi pourrait ressembler ce CSS:

.slide{
  position: absolute;
  left: 0px;
  top: 0px;
  width: 100%;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.5s;
}
.active-slide{
  opacity: 1;
  z-index: 2;
}
.quiz-container{
  position: relative;
  height: 200px;
  margin-top: 40px;
}

Nous allons maintenant ajouter du JavaScript pour que la pagination fonctionne. Comme précédemment, l’ordre est important, voici donc la structure révisée de notre code:

// Functions
// New functions go here

// Variables
// Same code as before

// Kick things off
buildQuiz();

// Pagination
// New code here

// Show the first slide
showSlide(currentSlide);

// Event listeners
// New event listeners here

Nous pouvons commencer par certaines variables pour stocker les références à nos boutons de navigation et garder une trace de la diapositive sur laquelle nous nous trouvons. Ajoutez-les après l’appel à buildQuiz(), Comme montré ci-dessus:

// Pagination
const previousButton = document.getElementById("previous");
const nextButton = document.getElementById("next");
const slides = document.querySelectorAll(".slide");
let currentSlide = 0;

Ensuite, nous allons écrire une fonction pour afficher une diapositive. Ajoutez ceci sous les fonctions existantes (buildQuiz et showResults):

function showSlide(n) {
  slides[currentSlide].classList.remove('active-slide');
  slides[n].classList.add('active-slide');
  currentSlide = n;
  if(currentSlide === 0){
    previousButton.style.display = 'none';
  }
  else{
    previousButton.style.display = 'inline-block';
  }
  if(currentSlide === slides.length-1){
    nextButton.style.display = 'none';
    submitButton.style.display = 'inline-block';
  }
  else{
    nextButton.style.display = 'inline-block';
    submitButton.style.display = 'none';
  }
}

Voici ce que font les trois premières lignes:

  • Masquez la diapositive actuelle en supprimant le active-slide classe.
  • Affichez la nouvelle diapositive en ajoutant active-slide classe.
  • Mettez à jour le numéro de la diapositive actuelle.

Les lignes suivantes présentent la logique suivante:

  • Si nous sommes sur la première diapositive, cachez le Diapositive précédente bouton. Sinon, affichez le bouton.
  • Si nous sommes sur la dernière diapositive, cachez le Diapositive suivante bouton et afficher le Soumettre bouton. Sinon, montrez Diapositive suivante bouton et masquer le Soumettre bouton.

Après avoir écrit notre fonction, nous pouvons immédiatement appeler showSlide(0) pour afficher la première diapositive. Cela devrait venir après le code de pagination:

// Pagination
...

showSlide(currentSlide);

Ensuite, nous pouvons écrire des fonctions pour faire fonctionner les boutons de navigation. Celles-ci vont sous la showSlide une fonction:

function showNextSlide() {
  showSlide(currentSlide + 1);
}

function showPreviousSlide() {
  showSlide(currentSlide - 1);
}

Ici, nous utilisons notre showSlide pour permettre à nos boutons de navigation d’afficher la diapositive précédente et la diapositive suivante.

Enfin, nous devons connecter les boutons de navigation à ces fonctions. Cela vient à la fin du code:

// Event listeners
...
previousButton.addEventListener("click", showPreviousSlide);
nextButton.addEventListener("click", showNextSlide);

Maintenant, votre quiz a une navigation fonctionnelle!

Voir le stylo
Quiz JavaScript simple avec pagination
par SitePoint (@SitePoint)
sur CodePen.

Et après?

Maintenant que vous avez un quiz JavaScript de base, il est temps de faire preuve de créativité et d’expérimenter.

Voici quelques suggestions que vous pouvez essayer:

  • Essayez différentes façons de répondre à une réponse correcte ou à une mauvaise réponse.
  • Stylisez bien le quiz.
  • Ajoutez une barre de progression.
  • Laissez les utilisateurs examiner les réponses avant de soumettre.
  • Donnez aux utilisateurs un résumé de leurs réponses après leur soumission.
  • Mettez à jour la navigation pour permettre aux utilisateurs de passer à n’importe quel numéro de question.
  • Créez des messages personnalisés pour chaque niveau de résultats. Par exemple, si quelqu’un obtient un score de 8/10 ou plus, appelez-le un ninja de quiz.
  • Ajoutez un bouton pour partager les résultats sur les réseaux sociaux.
  • Sauvegardez vos meilleurs scores en utilisant stockage local.
  • Ajoutez un compte à rebours pour voir si les gens peuvent battre le chronomètre.
  • Appliquez les concepts de cet article à d’autres utilisations, comme un estimateur de prix de projet ou un quiz social «quel personnage êtes-vous».
Close Menu