206 lines
8.0 KiB
JavaScript
206 lines
8.0 KiB
JavaScript
// -- GESTION DU FORMULAIRE PERMETTANT D'AFFICHER ET RÉPONDRE À UN QUIZ
|
|
|
|
/// Il n'est pas nécessaire d'avoir une base de données locale active pour répondre à un quiz.
|
|
/// Mais si ce n'est pas déjà le cas et que cela semble techniquement possible, il est proposé au répondant de sauvegarder durablement son résultat.
|
|
/// Dans ce but, son résultat est d'abord stocké temporairement.
|
|
/// Si la base de donnée locale existe déjà, l'enregistrement de son résultat se fait automatiquement dans IndexedDB et ses éventuels précédents résultats sont affichés.
|
|
|
|
// Configurations générales provenant du backend :
|
|
import { availableLangs } from "../../../config/instance.js";
|
|
const lang=availableLangs[0];
|
|
|
|
// Textes :
|
|
const { wantToSaveResponses, wantToSeaPreviousResults }=require("../../../lang/"+lang+"/answer");
|
|
const { serverError }=require("../../../lang/"+lang+"/general");
|
|
|
|
// Fonctions :
|
|
import { addElement } from "./tools/dom.js";
|
|
import { helloDev } from "./tools/everywhere.js";
|
|
import { isEmpty } from "../../../tools/main";
|
|
import { loadMatomo } from "./tools/matomo.js";
|
|
|
|
// Classe s'occupant du stockage des résultats aux quizs :
|
|
import { userQuizsResults} from "./tools/userQuizsResults";
|
|
|
|
// Informations du quiz en cours, utiles pour les enregistrements dans la base de donnée locale :
|
|
const myForm=document.getElementById("quiz");
|
|
const quizInfos=
|
|
{
|
|
url: window.location.pathname,
|
|
GroupId: document.getElementById("groupId").value,
|
|
QuestionnaireId: document.getElementById("questionnaireId").value,
|
|
title: myForm.dataset.title
|
|
};
|
|
|
|
// Éléments du DOM manipulés :
|
|
const btnSave=document.getElementById("want2Save");
|
|
const btnSubmit=document.getElementById("checkResponses");
|
|
const propose2Save=document.getElementById("propose2Save");
|
|
const responseTxt=document.getElementById("response");
|
|
|
|
let userDB, allPreviousAnswers=[], btnShow, myResults;
|
|
const initialise = async () =>
|
|
{
|
|
try
|
|
{
|
|
// Pour les quizs uniques (non groupés), un bouton permet à l'utilisateur d'afficher le quiz après avoir lu le contenu Wikipédia proposé, ce qui déclenche le chrono :
|
|
if(quizInfos.url.indexOf("/gp/") == -1)
|
|
{
|
|
btnShow=document.getElementById("showQuestionnaire");
|
|
btnShow.style.display="inline"; // Le bouton est caché si le JS est inactif, car le JS est nécessaire pour la suite...
|
|
}
|
|
// Instanciation de la classe s'occupant du stockage des résultats aux quizs :
|
|
myResults=await userQuizsResults.initialise("myResults", 1);
|
|
// Si la base de données est fonctionnel et que des résultats sont déjà enregistrés, on affiche ceux pour le quiz en cours :
|
|
if(myResults.allResults.length !== 0)
|
|
await myResults.showPreviousResultsForId(quizInfos.QuestionnaireId, quizInfos.GroupId);
|
|
// Statistiques :
|
|
loadMatomo();
|
|
}
|
|
catch(e)
|
|
{
|
|
console.error(e);
|
|
}
|
|
}
|
|
initialise();
|
|
helloDev();
|
|
|
|
// Fonction affichant le quiz, quand il est caché par défaut+ déclenchant le chronomètre mesurant la durée de réponse aux questions.
|
|
const showQuestionnaire = () =>
|
|
{
|
|
chronoBegin=Date.now();
|
|
myForm.style.display="block";
|
|
btnShow.style.display="none";
|
|
const here=window.location; // window.location à ajouter pour ne pas quitter la page en mode "preview".
|
|
if(window.location.hash !== "")
|
|
{
|
|
window.location.hash="";// ! le "#" reste
|
|
window.location.assign(here+"questionnaire");
|
|
}
|
|
else
|
|
window.location.assign(here+"#questionnaire");
|
|
}
|
|
|
|
let chronoBegin;
|
|
if(btnShow)
|
|
{
|
|
btnShow.addEventListener("click", function(e)
|
|
{
|
|
try
|
|
{
|
|
e.preventDefault();
|
|
showQuestionnaire();
|
|
}
|
|
catch(e)
|
|
{
|
|
addElement(responseTxt, "p", serverError, "", ["error"]);
|
|
console.error(e);
|
|
}
|
|
});
|
|
// Un lien peut être passé pour voir directement le quiz :
|
|
if(location.hash !== "" && location.hash === "#questionnaire")
|
|
showQuestionnaire();
|
|
}
|
|
|
|
// Dans le cas d'un quiz groupé, le chrono est lancé dès l'affichage :
|
|
if(quizInfos.GroupId != "0")
|
|
{
|
|
chronoBegin=Date.now();
|
|
btnSubmit.style.display="block";
|
|
}
|
|
|
|
// Traitement de l'envoi de la réponse de l'utilisateur :
|
|
let answer;
|
|
myForm.addEventListener("submit", async function(e)
|
|
{
|
|
try
|
|
{
|
|
e.preventDefault();
|
|
btnSubmit.style.display="none"; // seulement une réponse à la fois, SVP :)
|
|
responseTxt.innerHTML=""; // supprime les éventuels messages déjà affichés
|
|
answer=userQuizsResults.checkUserAnswers(myForm);
|
|
answer.duration=Math.round((Date.now()-chronoBegin)/1000);
|
|
answer.QuestionnaireId=quizInfos.QuestionnaireId;
|
|
answer.GroupId=quizInfos.GroupId;
|
|
|
|
// Enregistrement et affichage du résultat, suivant les cas :
|
|
let getOuput=userQuizsResults.getResultOutput(answer);
|
|
// S'il y a déjà une réponse dans la bd, c'est que l'utilisateur est ok pour les enregister.
|
|
if(myResults.allResults.length !== 0)
|
|
{
|
|
const saveResponses=await myResults.addResult(answer);
|
|
if(saveResponses)
|
|
await myResults.showPreviousResultsForId(quizInfos.QuestionnaireId, quizInfos.GroupId);
|
|
getOuput+="<br><br>"+wantToSeaPreviousResults.replace("URL","#explanations");
|
|
// Nouveau quiz pour cette personne ?
|
|
await myResults.saveNewQuiz(quizInfos);
|
|
}
|
|
else
|
|
{
|
|
// S'il n'a pas encore de données, on stocke temporairement le résultat et propose de l'enregistrer :
|
|
if(myResults.saveResultTemp(answer) && myResults.dbIsReady)
|
|
{
|
|
getOuput+="<br><br>"+wantToSaveResponses;
|
|
propose2Save.style.display="block";
|
|
}
|
|
}
|
|
addElement(responseTxt, "p", getOuput, "", ["info"]);
|
|
// On redirige vers le résultat :
|
|
const here=window.location;
|
|
if(window.location.hash !== "")
|
|
{
|
|
window.location.hash=""; // ! le "#" reste
|
|
window.location.assign(here+"response");
|
|
}
|
|
else
|
|
window.location.assign(here+"#response");
|
|
|
|
// + Affichage des textes d'explication pour chaque question
|
|
const explanations=document.querySelectorAll(".help");
|
|
for(let i in explanations)
|
|
{
|
|
if(explanations[i].style != undefined) // sinon, la console affiche une erreur "TypeError: explanations[i].style is undefined", bien que tout fonctionne (?)
|
|
explanations[i].style.display="block";
|
|
}
|
|
}
|
|
catch(e)
|
|
{
|
|
addElement(responseTxt, "p", serverError, "", ["error"]);
|
|
console.error(e);
|
|
}
|
|
});
|
|
|
|
// L'utilisateur demande à sauvegarder son résultat :
|
|
btnSave.addEventListener("click", async function(e)
|
|
{
|
|
try
|
|
{
|
|
e.preventDefault();
|
|
if(!isEmpty(myResults.dbIsReady) && !isEmpty(answer)) // On ne devrait pas m'avoir proposé d'enregistrer dans ce cas, mais...
|
|
{
|
|
const saveResponses=await myResults.addResult(answer);
|
|
if(saveResponses)
|
|
{
|
|
// Nouvel enregistrement = actualisation nécessaire de la liste des résultats pour ce quiz :
|
|
await myResults.showPreviousResultsForId(quizInfos.QuestionnaireId, quizInfos.GroupId);
|
|
// Nouveau quiz (ce qui doit être le cas, mais...) :
|
|
await myResults.saveNewQuiz(quizInfos);
|
|
// Redirection vers la liste des résultats :
|
|
const here=window.location; // window.location à ajouter pour ne pas quitter la page en mode "preview".
|
|
if(window.location.hash !== "")
|
|
{
|
|
window.location.hash="";// ! le "#" reste
|
|
window.location.assign(here+"explanations");
|
|
}
|
|
else
|
|
window.location.assign(here+"#explanations");
|
|
}
|
|
propose2Save.style.display="none";
|
|
}
|
|
}
|
|
catch(e)
|
|
{
|
|
addElement(responseTxt, "p", serverError, "", ["error"]);
|
|
console.error(e);
|
|
}
|
|
}); |