Questionnaire avec jQuery
1 Introduction à jQuery: construction d'un questionnaire
Pour comprendre jQuery, il est nécessaire au moins une bonne connaissance de HTML et de CSS et de JavaScript. Afin de reproduire les exemples de questionnaire présents sur cette page, un éditeur de texte qui permette la mise en évidence de la syntaxe JavaScript et jQuery est conseillé.
1.1 Exemple d'éditeur de texte
2 Définition de jQuery et ses fonctionnalités
jQuery est un bibliothèque JavaScript parmi les plus utilisées actuellement dans le développement web. Elle est utilisée dans le cadre de simple site web, RIA (Rich Internet Applications), jeux en HTML5, etc. Sa flexibilité permet en effet à jQuery de s’intégrer avec d’autres bibliothèques.
Bien que les fonctionnalités possibles grâce à jQuery soient potentiellement infinies, nous pouvons les regrouper en 7 fonctions :
- Accéder aux éléments du DOM : jQuery met à disposition une notation simple pour accéder aux éléments du document.
- Modification de l’apparence d’une page : son intégration avec les CSS permet à jQuery d’apporter toute sorte de modification de style.
- Modifier le contenu d’une page : jQuery permet de modifier le contenu d’un document, par exemple en remplaçant le texte d’un paragraphe ou la labellisation d’un bouton.
- Rendre la page interactive : jQuery permet d’intercepter plusieurs types d’événements sur la page (mouvement de la souris, click, etc.) et par conséquent de créer des changements en fonction de ces événements.
- Créer des animations : jQuery permet facilement d’animer des éléments du DOM grâce à une combinaison de CSS et changement de contenu.
- Fonctionnalités asynchrones (AJAX) : jQuery permet de charger le contenu d’une page de manière asynchrone, c’est-à-dire sans la mise à jour de la page dans le navigateur.
3 Installation de jQuery
jQuery est une bibliothèque JavaScript qui ne nécessite pas d’une installation particulière. Il suffit d’intégrer le fichier de la bibliothèque dans vos pages HTML. Cela peut se faire de deux manières :
- En faisant le download depuis le site officiel
- À travers une CDN (Content Delivery Network) qui met à disposition le fichier à travers un URL spécifique, par exemple http://code.jquery.com/jquery-1.11.0.min.js
Dans les deux cas, un tag de type script doit pointer au fichier JS qui contient le code de la bibliothèque. À ce sujet il faut noter que la bibliothèque est disponible en deux fichiers alternatifs : un fichier « minified » et une un fichier « normal ». Les deux fichiers sont exactement les même si ce n’est pour le fait que le « minified » ne contient pas d’espace ou de retours à la ligne, ce qui « comprime » son poids et par conséquent réduit le temps de chargement. Le fichier « minified » devrait être inclus dans vos pages, tandis que le « normal » peut-être utile si vous avez la nécessité de lire le code, surtout dans la perspective de développer des extensions ou des plugins.
À présent, il existe deux version stables de jQuery : la version 1.11.x et la version 2.0.x. Les deux versions sont équivalentes au niveau des fonctionnalités, mais la version 2.0.x n’est plus compatible avec les anciennes versions de Internet Explorer (avant IE9).
Pour inclure la version « minified » 1.11.0 à travers un CDN, le script à insérer dans vos pages est le suivant :
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
Si vous avez téléchargé la bibliothèque depuis le site officiel ainsi qu'elle sera disponible physiquement dans votre espace web, l'attribut src devra pointer au parcours relative du répertoire dans lequel vous avez placé le fichier. Une bonne organisation du code consiste à créer un dossier "js" à la racine de votre site. Selon ce schéma, le code pour inclure votre copie de la bibliothèque jQuery sera le suivant:
<script src="js/jsquery-1.11.0.min.js"></script>
Cette deuxième option est particulièrement utile pendant le développement, car la copie de la bibliothèque présent sur votre ordinateur vous permet de développer aussi "offline". Dans un site disponible online, le recours à une bibliothèque CDN garantie une majeure vitesse de téléchargement, et de plus il est probable que d'autres sites disposent de la même version de la bibliothèque, et par conséquent les utilisateurs ont déjà dans leur cache la même version du fichier.
Dans les exemples de ce guide, nous utiliserons une feuille de style déjà disponible pour faciliter les opérations. La feuille de style est celle du Framework Bootstrap. Si vous voulez obtenir exactement les mêmes résultats que dans les exemples du guide, il vous suffit d'inclure dans le head de votre page la référence suivante :
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
Soyez tout de même au courant que jQuery ne nécessite d'aucune feuille de style particulière et vous pouvez bien entendu remplacer vos propres déclarations de style aux exemples du guide.
4 Construction d'un questionnaire - Tutoriel
4.1 Version 1 - Construction d'un questionnaire vrai/faux
Pour la construction d'un simple questionnaire vrai/faux qui permettra aux apprenants d'obtenir un feedback tout de suite après avoir cliqué sur le bouton vrai ou sur le bouton faux, voici le code HTML utilisé dans l'exemple:
<p>jQuery est une bibliothèque ActionScript ?</p>
<button id="question1-true" class="btn btn-success">Vrai</button> <button id="question1-false" class="btn btn-danger">Faux</button><br />
<label id="question1-feedback">Veuillez cliquer sur la bonne réponse</label>
Il a été donné aux boutons des classes ainsi qu'il soient de deux couleurs différents ainsi qu'une identification univoque à travers l'attribut id="question1-true" ou id="question1-false". Ensuite, le label, placé après les boutons, lui aussi avec un attribut id="question1-feedback".
Voici le code jQuery utilisé dans l'exemple :
<script>
//Bouton vrai
$("#question1-true").click(function() {
$("#question1-feedback")
.addClass("text-danger")
.text("Non, jQuery est une bibliothèque JavaScript !");
$("#question1-false").attr("disabled", "disabled");
});
//Bouton faux
$("#question1-false").click(function() {
$("#question1-feedback")
.addClass("text-success")
.text("Votre réponse est correcte, félicitations !");
$("#question1-true").attr("disabled", "disabled");
});
</script>
4.1.1 Analyse du code
Analysons maintenant le code. On ne le fera que pour la partie concernant le bouton vrai, car pour le bouton faux le principe est le même mais avec quelques modifications mineures :
- $("#question1-true") fait référence à la fonctionnalité de sélection des éléments du DOM qu'on a vu plus haut dans la présentation des fonctionnalités de jQuery. Notons d'abord, cependant, que la notation $() est la notation clé de jQuery. Elle représente un raccourci pour la fonction générale jQuery() qui met à dispositions tous les méthodes et fonctions de la bibliothèque. Dans ce cas spécifique, la fonction s'occupe d'identifier dans le DOM un élément dont l'id correspond à question1-true. Vous pouvez remarquer qu'il s'agit de la même notation utilisée dans les feuilles de style CSS : la déclaration des propriétés de style d'un élément à travers son identification se fait effectivement à travers le caractère #. Il en suit que pour identifier un élément à travers sa balise, un paragraphe par exemple, la notation sera $("p"). L'identification d'une classe se fera par contre à travers la notation $(".nomdelaclasse"). Il faut en même temps savoir que ce type de notation peut se composer : la notation $("p a.external-link") identifie tous les balises <a> à l'intérieur d'un paragraphe qui présentent l'attribut class="external-link".
- .click(...) fait référence à la fonctionnalité d'interactivité citée plus haut dans le document. En effet, ce type de fonction est déclenchée par l'événement "click" du mouse. Dans le cas de notre exemple, nous avons associé cette fonction aux boutons "vrai" et "faux" à travers leur attribut id qu'on vient de voir au point précédent. À l'intérieur de la fonction click nous avons inséré une fonction anonyme, c'est-à-dire une simple fonction qui n'a pas de nom et qui ne pourra donc pas être appelée en dehors de cet événement. On aurait pu à ce propos déclarer une fonction giveTrueFeedback() ou giveFalseFeedback() et l'insérer à la place de la fonction anonyme.
- $("#question1-feedback").addClass("text-danger").text("Non, jQuery est une bibliothèque JavaScript !") fait référence à deux fonctionnalités à la fois : la modification de l'apparence et la modification du contenu. D'abord, notons que dans le code cette déclaration est écrite sur trois lignes différentes, mais ce n'est qu'une question de convention : le code sur une seule et même ligne fonctionnerait exactement de la même manière. Le fait de l'avoir mis sur trois ligne nous permet d'introduire un mécanisme important de jQuery qui concerne l’enchaînement des fonctions : on peut en effet déclarer plusieurs fonctions de suite pour le même élément et elles seront exécutée l'une après l'autre. Par conséquent, ce code est tout à fait pareil à écrire d'abord $("question1-feedback").addClass("text-danger") et ensuite $("question1-feedback").text("Non, jQuery est une bibliothèque JavaScript !"). Le principe est le même du premier point : on identifie d'abord le label avec id="question1-feedback" dans le DOM, on lui ajoute une classe de type "text-danger" avec la fonction addClass() ainsi que la couleur du texte soit rouge, et enfin - à travers la fonction text() - on replace le contenu du noued avec la phrase.
- $("#question1-true").attr("disabled", "disabled") fonctionne de la même manière, mais avec les attributs d'une balise. Dans ce cas il définit disabled="disabled" pour le bouton avec id="question1-true" ainsi que l'apprenant ne puisse pas modifier sa réponse une fois obtenu le feedback.
4.2 Version 2 - Questionnaire vrai/faux avec questions différentes
Nous allons maintenant retravailler cet exemple afin de proposer 4 questions différentes, toujours avec un mécanisme vrai/faux, mais sans faire 4 fois le copier/coller du code d'exemple. Voici le résultat qu'on veut obtenir :
Voici le code HTML:
<div class="question question-true">
<p>La capitale de la Suisse est Berne ?</p>
</div>
<hr />
<div class="question question-false">
<p>La Suisse est plus étendue que la France ?</p>
</div>
<hr />
<div class="question question-false">
<p>L'anglais est une des 4 langues nationales en Suisse ?</p>
</div>
<hr />
<div class="question question-true">
<p>Le drapeau de la Suisse a une croix blanche sur un fond rouge ?</p>
</div>
Comme vous pouvez le voir, contrairement à l'exemple précédent, dans le code HTML il n'y a pas trace ni des boutons, ni du label pour le feedback. Au contraire, tout ce qui apparait sont des
<script>
//Pour chaque question...
$(".question").each(function() {
// Ajouter le bouton vrai
$("<button>")
.addClass("btn btn-success")
.text("Vrai")
.css("margin-right", "15px")
.appendTo(this);
// Ajouter le bouton faux
$("<button>")
.addClass("btn btn-danger")
.text("Faux")
.css("margin-right", "15px")
.appendTo(this);
});
//Lorsqu'on clique sur un bouton dans une question
$(".question button").click(function() {
//Contrôler s'il y a correspondance entre le bouton cliquer (vrai/faux) et le type de question (question-true/question-false)
if(($(this).text() == "Vrai" & $(this).parent().hasClass("question-true")) || ($(this).text() == "Faux" & $(this).parent().hasClass("question-false"))) {
$('<label>').addClass('text-success').text('Correct !').appendTo($(this).parent());
} else {
$('<label>').addClass('text-danger').text('Erreur !').appendTo($(this).parent());
}
//désactiver l'autre bouton de la question
$(this).siblings("button").attr("disabled", "disabled");
});
</script>
4.2.1 Analyse du code
- $(".question").each(...) introduit une possibilité très utile qui est mise à disposition par la notation de sélection des éléments du DOM de jQuery. En effet, à travers la sélection $(".question") nous avons à disposition un Array avec tous les éléments qui disposent de cette classe, c'est-à-dire, dans notre cas spécifique, les 4 questions du test. La fonction each() nous permet l'itération à travers les différents éléments. Pour déterminer quoi faire pour chaque question, nous définons une fonction anonyme qui va exécuter différents actions.
- $("<button>") est l'équivalent de la fonction JavaScript document.createElement("button"), c'est-à-dire qu'elle permet de créer un nouveau élément HTML en prévision de l'ajouter dans le DOM. Une fois déclaré le nouveau élément, une classe lui est attribuée ainsi qu'un texte. À travers la fonction css() nous pouvons déterminer tous les propriétés de style qu'on peut normalement utiliser dans une feuille CSS. La fonction appendTo(), enfin, permet d'ajouter le nouveau élément créer à l'intérieur d'un élément spécifique. Notez à ce propos que dans l'exemple cet élément est définie par le mot this. C'est un terme qu'on va rencontrer souvent dans le développement jQuery. Il définit en effet l'élément "courant". Dans notre exemple, nous avons créé une boucle pour toutes les . Le this utilisé à l'intérieur de la fonction each() fait donc référence à l'élément courant du cycle. L'instruction appendTo(this) se traduit donc de cette manière : ajoute le bouton à l'intérieur du tagmais après tous les éléments qui sont déjà présents. En effet, lecontient déjà un paragraphe avec le texte de la question. Si on avait voulu placer les boutons avant le paragraphe, on aurait dû utiliser prependTo() au lieu d'appendTo().
- $(".question button").click(...) est exécuté chaque fois qu'un bouton qui se trouve à l'intérieur d'un élément avec class="question" est cliqué. En d'autres termes, la fonction anonyme sera déclenchée chaque fois qu'on clique sur un bouton vrai ou faux. Dans cette fonction anonyme nous contrôlons la correspondance entre le bouton cliqué (identifie à travers son texte Vrai ou Faux) et la class du qui contient la question (question-true ou question-false). Notons à ce propos que pour déterminer le type de class du, nous utilisons la notation $(this).parent(). Dans ce cas, on se trouve à l'intérieur de la fonction click() attribuée à l'élément bouton, et donc le mot this se réfère justement au bouton cliqué. Par conséquent, pour déterminer la class duqui le contient, il faut remonter dans la structure du DOM à son élément supérieur, c'est-à-dire son élément parent(). Le même principe est utilisé pour ajouter le nouveau élément <label> avec le texte du feedback. Il est placé, grâce à la fonction appendTo() qu'on a déjà vue à l'intérieur de l'élément parent du bouton, mais après tout autre élément (donc après le paragraphe et les deux boutons). Par contre, lorsqu'on veut désactiver l'autre bouton de chaque question, on utilise plutôt la fonction siblings() qui cherche un élément défini à son intérieur (dans ce cas <button>) dans le même niveau du DOM.
4.3 Version 3 - Questionnaire avec ficher XML externe
Cette troisième version du questionnaire permet assez facilement des réponses multiples. Nous allons proposer le même questionnaire de la deuxième version, mais cette fois les questions seront récupérées dans un fichier XML externe. Pour ce faire, nous utiliserons une requête asynchrone (AJAX). Le code HTML dont on a besoin pour cette version du questionnaire est très simple : il nous suffit un élément qu'on puisse identifier pour y insérer les questions générées à travers la requête asynchrone. Nous utiliserons dans ce cas le code suivant :
<div id="questionnaire"></div>
<source>
D'abord, nous allons analyser le code nécessaire pour une requête asynchrone et seulement dans un deuxième temps nous y ajouterons les éléments nécessaire à construire notre questionnaire :
<source lang=JavaScript>
<script>
$(document).ready(function(e) {
$.ajax({
type: "GET",
url: "xml/true-false.xml",
dataType: "xml",
success: function(xml) {
//Quoi faire avec le contenu obtenu
},
error: function() {
//Quoi faire en cas d'erreur de la requête
}
});
}
</script>
4.3.1 Analyse du code
- $(document).ready() est une fonction très utile qui correspond à la fonction JavaScript window.onload, mais avec quelques avantages significatifs. D'abord, la version JavaScript doit attendre que tout élément soit téléchargé, y compris des images externes qui peuvent parfois être lourdes. Au contraire, la fonction jQuery est déclenchée dès que la structure du DOM est disponible. Un autre avantage important concerne le fait que la fonction jQuery peut être déclarée plusieurs fois dans le même document, tandis que window.onload peut être utilisé une seule fois.
- $.ajax() est la fonction qui s'occupe des requêtes asynchrones. Voyons en détails les arguments, en sachant que la documentation officielle de jQuery est plus exhaustive et que d'autres arguments sont disponibles :
- type : le type de requête, dans notre cas il s'agit d'une requête GET (une alternative est la méthode POST)
- url : l'adresse de la page intéressée
- dataType : le forma des données, dans notre cas il s'agit d'une page XML mais d'autres formats sont aussi supportés
- success : quoi faire une fois que la requête a été menée à bien ? Notons qu'à l'intérieur de la fonction à exécuter en cas de succès, nous avons un argument - dans notre cas appelé "xml" - qui représente le contenu du fichier téléchargé
- error : quoi faire si la requête n'a pas abouti, par exemple à cause d'une erreur de l'url ou du server non disponible ?
Voyons maintenant comment insérer et adapter notre code afin de téléchargée les questions depuis le fichier XML. Voici la structure du fichier avec les 4 questions du questionnaire :
<?xml version="1.0" encoding="utf-8"?>
<questionnaire>
<question>
<texte>La capitale de la Suisse est Berne ?</texte>
<option correcte="1">Vrai</option>
<option>Faux</option>
</question>
<question>
<texte>La Suisse est plus étendue que la France ?</texte>
<option>Vrai</option>
<option correcte="1">Faux</option>
</question>
<question>
<texte>L'anglais est une des 4 langues nationales en Suisse ?</texte>
<option>Vrai</option>
<option correcte="1">Faux</option>
</question>
<question>
<texte>Le drapeau de la Suisse a une croix blanche sur un fond rouge ?</texte>
<option correcte="1">Vrai</option>
<option>Faux</option>
</question>
</questionnaire>
Et voici enfin le code jQuery :
<script>
$(document).ready(function(e) {
$.ajax({
type: "GET",
url: "xml/true-false.xml",
dataType: "xml",
success: function(xml) {
//Quoi faire avec le contenu obtenu
//Pour chaque question...
$(xml).find("question").each(function() {
var div = $('<div>');
$('<p>').text($(this).find("texte").text()).appendTo(div);
$(this).find("option").each(function() {
var btn = $('<button>')
.addClass("btn btn-primary btn-block")
.css("margin-bottom", "10px")
.css("display", "block")
.text($(this).text());
if($(this).attr("correcte") == 1) {
btn.addClass("correcte");
}
btn.click(function() {
if($(this).hasClass("correcte")) {
$(this).addClass("btn-success");
} else {
$(this).addClass("btn-danger");
}
$(this)
.siblings("button")
.attr("disabled", "disabled")
.removeClass("btn-primary");
});
btn.appendTo(div);
});
div.appendTo("#questionnaire");
$('<hr />').appendTo("#questionnaire");
});
},
error: function() {
alert("Erreur dans la requête Ajax");
}
});
});
</script>
4.3.2 Analyse du code
Par rapport à la deuxième version du code il y a eu quelques changements, mais aucune nouvelle fonction si ce n'est pour les fonctions propres au document XML téléchargée. Nous analyserons donc seulement ces fonctions :
- $(xml).find("question").each(...) : au lieu de faire une cycle itérative sur les comme dans le cas précédent, ici la boucle se construit grâce à la fonction find() qui cherche tous les nœuds <question> du contenu du fichier (xml).
- $(this).find("option").each(...) : le même principe s'applique aux options possibles, avec la différence que dans ce cas on se trouve déjà à l'intérieur du cycle des questions, et donc avec le mot this on peut chercher les nœuds <option> à l'intérieur du nœud <question> dans lequel on se trouve.
4.3.3 Résultat final version 3
5 Source du contenu de la page
5.1 Liens utiles
5.2 Bibliographie
- Bibeault, B., & Katz, Y. (2008). jQuery in Action. Greenwich, CT: Manning.
- Chaffer, J. & Swedberg, K. (2013). Learning jQuery. Fourth Edition. Birmingham, UK: Packt Publishing