219 lines
8.5 KiB
JavaScript
219 lines
8.5 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, on propose au répondant de sauvegarder son résultat.
|
|
/// Dans ce but son résultat est 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, theme } from "../../config/instance.js";
|
|
const lang=availableLangs[0];
|
|
const configTemplate=require("../../views/"+theme+"/config/"+lang+".js");
|
|
|
|
// Fonctions :
|
|
import { checkAllPreviousResults, checkUserAnswers, getResultOutput, resultsOpenDb, saveNewQuiz, saveResult, saveResultTemp, showPreviousResults } from "./tools/answers.js";
|
|
import { saveIsReady } from "./tools/clientstorage.js";
|
|
import { addElement } from "./tools/dom.js";
|
|
import { helloDev } from "./tools/everywhere.js";
|
|
import { isEmpty } from "../../tools/main";
|
|
import { loadMatomo } from "./tools/matomo.js";
|
|
|
|
// Textes :
|
|
const { wantToSaveResponses, wantToSeaPreviousResults }=require("../../lang/"+lang+"/answer");
|
|
const { localDBConnexionFail, serverError }=require("../../lang/"+lang+"/general");
|
|
|
|
// Informations du quiz, utile pour enregistrement dans base de donnée locale :
|
|
const myForm=document.getElementById("quiz");// quiz
|
|
const quizInfos=
|
|
{
|
|
url: window.location.pathname,
|
|
GroupId: document.getElementById("groupId").value,
|
|
QuestionnaireId: document.getElementById("questionnaireId").value,
|
|
title: myForm.dataset.title
|
|
};
|
|
|
|
// Autres éléments du DOM manipulés :
|
|
const propose2Save=document.getElementById("propose2Save");
|
|
const btnSave=document.getElementById("want2Save");
|
|
const btnSubmit=document.getElementById("checkResponses");
|
|
const divResponse=document.getElementById("response");
|
|
|
|
// L'url permet de savoir si nous sommes sur un quiz unique ou groupé :
|
|
let btnShow;
|
|
if(quizInfos.url.indexOf("/gp/") == -1)
|
|
btnShow=document.getElementById("showQuestionnaire"); // le quiz est affiché directement pour les groupes
|
|
|
|
let userDB, allPreviousAnswers=[];
|
|
const initialise = async () =>
|
|
{
|
|
try
|
|
{
|
|
if(btnShow)
|
|
btnShow.style.display="inline"; // Le bouton est caché si le JS inactif, car le JS est nécessaire pour la suite...
|
|
// On vérifie si la navigateur accepte l'utilisation d'IndexedDB :
|
|
const saveIsPossible=saveIsReady();
|
|
if(saveIsPossible)
|
|
{
|
|
// On essaye ensuite de se connecter à la base de données (ce qui va la créer si inexistante) :
|
|
userDB=await resultsOpenDb("myAnswers", 1);
|
|
if(userDB === undefined)
|
|
console.error(localDBConnexionFail);
|
|
else
|
|
{
|
|
// Vérifie si l'utilisateur a déjà sauvegardé au moins un résultat (et donc est ok pour les sauvegardes) :
|
|
allPreviousAnswers=await checkAllPreviousResults(userDB);
|
|
if(allPreviousAnswers.length !== 0)
|
|
await showPreviousResults(userDB, quizInfos.QuestionnaireId, quizInfos.GroupId);
|
|
}
|
|
}
|
|
loadMatomo();
|
|
}
|
|
catch(e)
|
|
{
|
|
console.error(e);
|
|
}
|
|
}
|
|
initialise();
|
|
helloDev();
|
|
|
|
// Affichage du quiz, quand il est caché par défaut (= l'internaute doit d'abord lire un article Wikipédia).
|
|
// Déclenche en même temps 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");
|
|
}
|
|
|
|
// L'utilisateur demande à voir le quiz :
|
|
let chronoBegin=0;
|
|
if(btnShow)
|
|
{
|
|
btnShow.addEventListener("click", function(e)
|
|
{
|
|
try
|
|
{
|
|
e.preventDefault();
|
|
showQuestionnaire();
|
|
}
|
|
catch(e)
|
|
{
|
|
addElement(divResponse, "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 :)
|
|
divResponse.innerHTML=""; // supprime les éventuels messages déjà affichés
|
|
answer=checkUserAnswers(myForm);
|
|
answer.duration=Math.round((Date.now()-chronoBegin)/1000);
|
|
answer.QuestionnaireId=quizInfos.QuestionnaireId;
|
|
answer.GroupId=quizInfos.GroupId;
|
|
|
|
// Affichage du résultat, suivant les cas :
|
|
let getOuput=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(allPreviousAnswers.length !==0)
|
|
{
|
|
const saveResponses=await saveResult(userDB, answer);
|
|
if(saveResponses)
|
|
await showPreviousResults(userDB, quizInfos.QuestionnaireId, quizInfos.GroupId);
|
|
getOuput+="<br><br>"+wantToSeaPreviousResults.replace("URL","#explanations");
|
|
// Nouveau quiz pour cette personne ?
|
|
await saveNewQuiz(userDB, quizInfos);
|
|
}
|
|
else
|
|
{
|
|
// S'il n'a pas encore de données, on stocke temporairement le résultat et propose de l'enregistrer :
|
|
if(saveResultTemp(answer) && !isEmpty(userDB))
|
|
{
|
|
getOuput+="<br><br>"+wantToSaveResponses;
|
|
propose2Save.style.display="block";
|
|
}
|
|
}
|
|
addElement(divResponse, "p", getOuput, "", ["info"]);
|
|
// On redirige vers le résultat :
|
|
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+"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(divResponse, "p", serverError, "", ["error"]);
|
|
console.error(e);
|
|
}
|
|
})
|
|
|
|
// L'utilisateur demande à sauvegarder son résultat :
|
|
btnSave.addEventListener("click", async function(e)
|
|
{
|
|
try
|
|
{
|
|
e.preventDefault();
|
|
if(!isEmpty(userDB) && !isEmpty(answer)) // On ne devrait pas me proposer d'enregistrer dans ce cas, mais...
|
|
{
|
|
const saveResponses=await saveResult(userDB, answer);
|
|
if(saveResponses)
|
|
{
|
|
// Nouvel enregistrement = actualisation nécessaire de la liste des résultats pour ce quiz :
|
|
await showPreviousResults(userDB, quizInfos.QuestionnaireId, quizInfos.GroupId);
|
|
// Nouveau quiz
|
|
await saveNewQuiz(userDB, 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(divResponse, "p", serverError, "", ["error"]);
|
|
console.error(e);
|
|
}
|
|
|
|
}); |