• Facile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

TP : Questionnaire interactif en jQuery

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Vous voici donc arrivés au premier TP ! TP signifie « Travaux Pratiques ». En clair, vous allez pratiquer ce que nous venons de voir. Régulièrement, je vous ferai travailler grâce à ce genre d'exercices et vous allez vite voir que, mine de rien, vous savez beaucoup de choses. ;)

Évidemment, je ne vous demanderai jamais rien que vous ne soyez capables de faire. Enfin pas vraiment… Il se peut que cela arrive, mais dans ce cas je vous donnerai la marche à suivre pour parvenir à la fin du TP.

Bon, vous êtes prêts ? Alors allons-y ! Je vous propose de créer un QCM (questionnaire à choix multiples) interactif en jQuery.

Instructions pour réaliser le TP

Dans ce premier TP, vous allez mettre en place un QCM interactif en partant d'un modèle HTML que je vais vous fournir. En utilisant des instructions jQuery, vous devrez transformer ce modèle de base pour obtenir quelque chose ressemblant à l'image suivante.

Voilà à quoi devra ressembler le QCM
Voilà à quoi devra ressembler le QCM

Pour arriver à ce résultat, vous devrez :

  1. Dissimuler les réponses aux questions ;

  2. Mettre en forme les éléments affichés sur l'écran ;

  3. Réagir au survol du lien « Tester les réponses » en affichant, pour chaque question :

    1. L'icône bon.png si la réponse est bonne ou l'icône mauvais.png si la réponse est mauvaise.

    2. Le texte explicatif en vert si la réponse est bonne ou en rouge si elle est mauvaise.

Normalement, seule la troisième étape devrait vous poser un problème. Les autres ont déjà été vues. Si vous rencontrez le moindre problème, n'hésitez pas à (re)lire les chapitres précédents correspondants.

Si la troisième étape peut vous poser des problèmes, ce n'est pas tant par sa complexité que par le fait que vous devrez utiliser une instruction jQuery qui n'a pas encore été vue et qui donne de l'interactivité au QCM. J'aurais pu limiter votre travail à une pure mise en forme, mais cela aurait vraiment été dommage de ne pas intégrer de l'interactivité dans ce formulaire. Je vais donc vous donner l'instruction jQuery à utiliser, sans m'étendre sur le sujet ni expliquer son fonctionnement.

La méthode à utiliser est la suivante :

$('a').hover(
  function() {
    // Les instructions à exécuter au survol du lien
  },
  function() {
    // Les instructions à exécuter lorsque le lien n'est plus survolé
  }
);

Vous voyez, il n'y a rien de bien sorcier. Vous auriez presque pu trouver la méthode sans mon aide tant elle est proche de son homologue CSS hover.

Voici le code HTML de départ :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Questionnaire interactif en jQuery</title>
  </head>
  
  <body>
    <form>
    <a href="">Tester les réponses</a>

    <div class="question">
      <div class="texte">
        <h2>Question 1</h2>
          Le code jQuery s'exécute :<br>
          <input type="radio" id="r1" name="q1">Dans le navigateur<br>
          <input type="radio" id="r2" name="q1">Sur le serveur où est stocké le code<br>
        <input type="radio" id="r3" name="q1">Tantôt dans le navigateur, tantôt sur le serveur<br>
        <br><span class="reponse" id="reponse1">Le code jQuery n'est autre que du JavaScript. A ce titre, il s'exécute toujours sur les clients (ordinateurs, tablettes et téléphones) qui font référence à ce code via une page HTML. La bonne réponse est donc la première.</span>
      </div>  
      <img id="img1" src="question.png" />
    </div>

    <div class="question">
      <div class="texte">
        <h2>Question 2</h2>
        Lorsque l'on veut exécuter du code jQuery, attendre la disponibilité du DOM est :<br>
        <input type="radio" id="r4" name="q2">Vital<br>
        <input type="radio" id="r5" name="q2">Inutile<br>
        <input type="radio" id="r6" name="q2">Parfois important, parfois sans importance<br>
        <br><span class="reponse" id="reponse2">Il est impératif d'attendre la disponibilité du DOM avant d'exécuter du code jQuery. Sans quoi, ce code pourrait s'appliquer à un élément indisponible et provoquer un comportement inattendu, voire même un plantage du navigateur.</span>
      </div>
      <img id="img2" src="question.png" />
    </div>

    <div class="question">
      <div class="texte">
        <h2>Question 3</h2>
        Pour chaîner deux méthodes jQuery :<br>
        <input type="radio" id="r7" name="q3">Il faut les mettre l'une à la suite de l'autre en les séparant par une virgule<br>
        <input type="radio" id="r8" name="q3">Il faut les mettre l'une à la suite de l'autre en les séparant par un point décimal<br>
        <input type="radio" id="r9" name="q3">Il est impossible de chaîner deux méthodes jQuery<br>
        <br><span class="reponse" id="reponse3">L'exécution d'un sélecteur jQuery produit un objet jQuery sur lequel il est possible d'appliquer une méthode jQuery. Cette méthode produit elle-même un objet jQuery. Il est donc possible de lui appliquer une autre méthode en utilisant le caractère de liaison habituel : le point décimal.</span>
      </div>  
      <img id="img3" src="question.png" />
    </div>
    </form>
    
    <script src="jquery.js"></script>
    <script>
      $(function() {
        // Insérer le code jQuery ici
      }); 
    </script>
  </body>
</html>

Examinons la structure de ce document.

L'en-tête ne contient aucun code de mise en forme CSS, ce qui est tout à fait normal puisque vous devrez écrire ce code de mise en forme… en jQuery ! Le corps du document contient un formulaire — qui contient lui-même un lien hypertexte — ainsi que trois balises <div> qui correspondent aux trois questions du QCM.

Chaque balise <div> contient deux éléments essentiels :

  1. Une autre balise <div> dans laquelle seront affichés tous les éléments textuels ;

  2. Une balise <img> d'identifiant img1, qui pointe vers l'image question.png.

Cet agencement a été créé pour faciliter la mise en forme flottante de l'image par rapport au texte.

À l'intérieur de la balise <div> de classe texte, six éléments :

  • Un titre de niveau 2 ;

  • Le texte de la question ;

  • Trois boutons radio (d'identifiants r1, r2 et r3 et d'attribut nameq1) suivis des réponses possibles ;

  • Une balise <span> dans laquelle s'affiche le texte qui explique la bonne réponse lorsque l'utilisateur place le pointeur de la souris sur le lien « Tester les réponses ».

Le code se termine de façon très classique par l'intégration de la bibliothèque jQuery et par l'attente de la disponibilité du DOM. C'est ici que vous interviendrez en insérant autant d'instructions jQuery que nécessaires pour arriver au résultat demandé.

Avant de vous laisser à votre imagination et à votre clavier, je vais vous fournir les trois images utilisées dans le document.

question.png
bon.png
mauvais.png

Allez, c'est à vous de jouer !

Correction

J'espère que vous n'avez pas eu trop de problèmes dans ce TP. Voici ma correction, dans laquelle je passe en revue tous les points qui auraient pu « coincer ».

Dissimuler les réponses aux questions

Toutes les réponses ont la même classe : reponse. Pour les dissimuler, il suffit d'exécuter la méthode hide() sur les objets renvoyés par le sélecteur $('.reponse') dès la disponibilité du DOM :

$(function() {
  // Dissimulation des réponses
  $('.reponse').hide();

Mettre en forme les éléments affichés sur l'écran

Dans un premier temps, vous allez mettre en forme les balises <div> de classe question, c'est-à-dire les balises qui correspondent aux questions posées dans le QCM. En utilisant le sélecteur $('.question'), vous pouvez facilement isoler les trois balises <div> de classe question. Il suffit alors d'appliquer à plusieurs reprises la méthode jQuery css() à ce sélecteur pour modifier les caractéristiques des balises <div> :

var q = $('.question');          //Mémorisation du sélecteur dans une variable pour optimiser le code
q.css('background', '#9EEAE0');  //Couleur d'arrière-plan
q.css('border-style', 'groove'); //Type de la bordure
q.css('border-width', '4px');    //Largeur de la bordure
q.css('width', '900px');         //Largeur des balises <div> de classe « question »
q.css('height', '250px');        //Hauteur des balises <div> de classe « question »
q.css('margin', '20px');         //Marge autour des balises <div> de classe « question »

Textes et images en affichage flottant

Les caractéristiques de mise en forme des balises de classe question étant définies, nous allons maintenant faire flotter les éléments textuels à gauche et l'image à droite de ces balises. Cette mise en page se fera en agissant sur la propriété CSS float des balises de classe texte et des images.

La première instruction fait flotter la balise <div> de classe texte à gauche de la balise <div> parente, c'est-à-dire de la balise <div> de classe question :

$('.texte').css('float', 'left');

La deuxième instruction donne 90% de la largeur disponible à la balise <div> de classe texte. Ainsi, cette balise aura toujours la même largeur et, par voie de conséquence, les images affichées à sa droite auront toujours la même position et seront alignées verticalement :

$('.texte').css('width', '90%');

La troisième instruction fait flotter l'image à droite de la balise <div> parente, c'est-à-dire de la balise <div> de classe question :

$('img').css('float', 'right');

Enfin, la quatrième instruction décale l'image vers le bas en définissant une marge supérieure de 80 pixels :

$('img').css('margin-top', '80px');

La mise en page est maintenant terminée. Si vous exécutez le code, vous devriez obtenir quelque chose ressemblant à l'image suivante.

Le texte et les images sont maintenant bien positionnés
Le texte et les images sont maintenant bien positionnés

Réagir au survol du lien « Tester les réponses »

Arrivés à ce point, la mise en page est terminée, il vous est possible de répondre aux questions posées, mais pas de tester les réponses. Pour cela, vous devez écrire le code de la méthode $('a').hover(). Lorsque le lien « Tester les réponses » est pointé, les actions à accomplir sont les suivantes pour chaque question :

  1. Test de la réponse.

  2. Si la réponse est bonne, affichage de l'icône bon.png et du texte explicatif en vert.

  3. Si la réponse est mauvaise, affichage de l'icône mauvais.png et du texte explicatif en rouge.

Lorsque le lien « Tester les réponses » n'est plus pointé, les actions à accomplir sont les suivantes :

  1. Dissimulation des réponses.

  2. Affichage de l'icône question.png dans les trois balises <img>.

Voici la fonction mise à jour :

$('a').hover(
  function() { 
    $('.reponse').show();
    if ($(':radio[id="r1"]:checked').val()) {
      $('#img1').attr('src', 'bon.png'); 
      $('#reponse1').css('color', 'green');
    }  
    else {
      $('#img1').attr('src', 'mauvais.png');
      $('#reponse1').css('color', 'red');
    } 

    if ($(':radio[id="r4"]:checked').val()) {
      $('#img2').attr('src', 'bon.png');
      $('#reponse2').css('color', 'green');
    }
    else {
      $('#img2').attr('src', 'mauvais.png');
      $('#reponse2').css('color', 'red');
    } 

    if ($(':radio[id="r8"]:checked').val()) {
      $('#img3').attr('src', 'bon.png'); 
      $('#reponse3').css('color', 'green');
    }
    else {
      $('#img3').attr('src', 'mauvais.png');
      $('#reponse3').css('color', 'red');
    }
  },
  function() { 
    $('.reponse').hide(); 
    $('#img1').attr('src', 'question.png');
    $('#img2').attr('src', 'question.png');
    $('#img3').attr('src', 'question.png');
  }
);

Ne vous laissez pas impressionner par la longueur du code ! Vous allez voir, toutes ces lignes sont vraiment simples à comprendre !

La première fonction contient trois blocs d'instructions quasiment identiques. Chacun d'entre eux s'intéresse à une des questions posées dans le QCM. Nous allons nous intéresser au premier bloc d'instructions. Vous pourrez sans problème transférer les explications qui vont être données aux deux autres blocs.

Après avoir validé l'affichage des balises de classe reponse :

$('.reponse').show();

… l'état du premier bouton radio est testé (ce choix représente la bonne réponse). Si ce bouton a été sélectionné :

if ($(':radio[id="r1"]:checked').val()) {

… l'image bon.png est affichée dans la balise <img> d'identifiant #img1 :

$('#img1').attr('src', 'bon.png');

… et les explications sont affichées en vert dans la balise d'identifiant #reponse1 :

$('#reponse1').css('color', 'green');

Si ce bouton radio n'est pas sélectionné :

else {

… l'image mauvais.png est affichée dans la balise <img> d'identifiant #img1 :

$('#img1').attr('src', 'mauvais.png');

… et les explications sont affichées en rouge dans la balise d'identifiant #reponse1 :

$('#reponse1').css('color', 'red');

Les deux autres blocs de code effectuent un traitement similaire, si ce n'est qu'ils testent un autre bouton radio, et qu'ils agissent sur d'autres balises <img> et <span>.

Le deuxième paramètre de la méthode hover() indique ce qu'il faut faire quand le lien n'est plus pointé par la souris. La réponse doit être cachée :

function() { 
  $('.reponse').hide();

… et l'image question.png doit être affichée dans les trois balises <img> :

$('img').each(function() {
  $(this).attr('src', 'question.png');
});

Le code complet

Ça y est, le code est entièrement opérationnel. Bien entendu, vous pouvez le modifier pour créer vos propres QCM…

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Questionnaire interactif en jQuery</title>
  </head>
  
  <body>
    <form>
    <a href="">Tester les réponses</a>

    <div class="question">
      <div class="texte">
        <h2>Question 1</h2>
          Le code jQuery s'exécute :<br>
          <input type="radio" id="r1" name="q1">Dans le navigateur<br>
          <input type="radio" id="r2" name="q1">Sur le serveur où est stocké le code<br>
        <input type="radio" id="r3" name="q1">Tantôt dans le navigateur, tantôt sur le serveur<br>
        <br><span class="reponse" id="reponse1">Le code jQuery n'est autre que du JavaScript. À ce titre, il s'exécute toujours sur les clients (ordinateurs, tablettes et téléphones) qui font référence à ce code via une page HTML. La bonne réponse est donc la première.</span>
      </div>  
      <img id="img1" src="question.png" />
    </div>

    <div class="question">
      <div class="texte">
        <h2>Question 2</h2>
        Lorsque l'on veut exécuter du code jQuery, attendre la disponibilité du DOM est :<br>
        <input type="radio" id="r4" name="q2">Vital<br>
        <input type="radio" id="r5" name="q2">Inutile<br>
        <input type="radio" id="r6" name="q2">Parfois important, parfois sans importance<br>
        <br><span class="reponse" id="reponse2">Il est impératif d'attendre la disponibilité du DOM avant d'exécuter du code jQuery. Sans quoi, ce code pourrait s'appliquer à un élément indisponible et provoquer un comportement inattendu, voire même un plantage du navigateur.</span>
      </div>
      <img id="img2" src="question.png" />
    </div>

    <div class="question">
      <div class="texte">
        <h2>Question 3</h2>
        Pour chaîner deux méthodes jQuery :<br>
        <input type="radio" id="r7" name="q3">Il faut les mettre l'une à la suite de l'autre en les séparant par une virgule<br>
        <input type="radio" id="r8" name="q3">Il faut les mettre l'une à la suite de l'autre en les séparant par un point décimal<br>
        <input type="radio" id="r9" name="q3">Il est impossible de chaîner deux méthodes jQuery<br>
        <br><span class="reponse" id="reponse3">L'exécution d'un sélecteur jQuery produit un objet jQuery sur lequel il est possible d'appliquer une méthode jQuery. Cette méthode produit elle-même un objet jQuery. Il est donc possible de lui appliquer une autre méthode en utilisant le caractère de liaison habituel : le point décimal.</span>
      </div>  
      <img id="img3" src="question.png" />
    </div>
    </form>
    
    <script src="jquery.js"></script>
    <script>
      $(function() {
        // Dissimulation des réponses
        $('.reponse').hide();
        
        // Mise en forme des div du QCM
        var q = $('.question');
        q.css('background', '#9EEAE0');
        q.css('border-style', 'groove');
        q.css('border-width', '4px');
        q.css('width', '900px');
        q.css('height', '250px');
        q.css('margin', '20px');

        $('.texte').css('float', 'left');
        $('.texte').css('width', '90%');
        $('img').css('float', 'right');
        $('img').css('margin-top', '80px');
        
        // Action au survol du lien « Tester les réponses »
        $('a').hover(
          function() { 
            $('.reponse').show();
            if ($(':radio[id="r1"]:checked').val()) {
              $('#img1').attr('src', 'bon.png'); 
              $('#reponse1').css('color', 'green');
            }  
            else {
              $('#img1').attr('src', 'mauvais.png');
              $('#reponse1').css('color', 'red');
            } 
            if ($(':radio[id="r4"]:checked').val()) {
              $('#img2').attr('src', 'bon.png');
              $('#reponse2').css('color', 'green');
            }
            else {
              $('#img2').attr('src', 'mauvais.png');
              $('#reponse2').css('color', 'red');
            } 
            if ($(':radio[id="r8"]:checked').val()) {
              $('#img3').attr('src', 'bon.png'); 
              $('#reponse3').css('color', 'green');
            }
            else {
              $('#img3').attr('src', 'mauvais.png');
              $('#reponse3').css('color', 'red');
            }
          },
          function() { 
            $('.reponse').hide(); 
            $('img').each(function() {
              $(this).attr('src', 'question.png');
          });
}

        );  
      }); 
    </script>    
  </body>
</html>
Exemple de certificat de réussite
Exemple de certificat de réussite