import $ from "cash-dom";
import gsap from "gsap";
-import { MotionPathPlugin } from "gsap/MotionPathPlugin.js";
+import {MotionPathPlugin} from "gsap/MotionPathPlugin.js";
import {CubeSCORM} from '/application/resources/scorm/scorm';
-import lottie from "lottie-web";
-import SplitType from 'split-type'
-import SimpleBar from 'simplebar'
-import 'simplebar/dist/simplebar.css'
-import Handlebars from "handlebars";
import QuizResize from "./quiz.resize";
import QuizAnimations from "./quiz.animations";
import QuizScore from './quiz.score';
import QuizScorm from './quiz.scorm';
import QuizQuestion from './quiz.question';
+import QuizAccessibility from './quiz.accessibility';
+import QuizUtils from './quiz.utils';
+import QuizScreens from './quiz.screens';
window.cubeSCORM = new CubeSCORM();
window.$ = window.jQuery = $;
-window.key = require('keymaster-reloaded');
-
import ResizeObserver from 'resize-observer-polyfill';
+
window.ResizeObserver = ResizeObserver;
function Quiz() {
// Initialisation des modules
this.animations = new QuizAnimations(this);
- this.score=new QuizScore(this);
- this.scorm=new QuizScorm(this);
+ this.score = new QuizScore(this);
+ this.scorm = new QuizScorm(this);
this.resize = new QuizResize(this);
this.question = new QuizQuestion(this);
+ this.utils = new QuizUtils(this);
+ this.accessibility = new QuizAccessibility(this);
+ this.screens = new QuizScreens(this);
// Ici seront injectées dans this.data toutes les données du quiz et du thème pour qu'elles soient disponibles
// dans l'object à tout moment
this.timeoutAnimation = false
// commencer
- $(document).on("click", "#start", function() {
+ $(document).on("click", "#start", function () {
$this.start()
})
//
- $("#quiz").css("background-image","url("+this.data.theme.backgroundImage+")")
+ $("#quiz").css("background-image", "url(" + this.data.theme.backgroundImage + ")")
// La fonction resize est appelée à chaque fois qu'un resize de la fenêtre survient (et à l'init de l'app)
$(window).on('resize', function () {
});
this.quizResize();
- //animer le texte d'intro
- let title = new SplitType("#welcome h2", { types: 'words, chars' })
- let text = new SplitType("#welcome p", { types: 'words, chars' })
- gsap.from(title.words, {
- opacity: 0,
- y: 20,
- duration: 1,
- stagger: 0.05,
- onStart: () => {
- $(title.elements).removeClass("none")
- }
- })
- gsap.to(text.words, {
- opacity: 1,
- y: 0,
- duration: 1,
- ease: "power1.inOut",
- stagger: {
- amount: 0.2
- },
- onStart: () => {
- $(text.elements).removeClass("none")
- }
- })
+ // Afficher l'écran d'introduction et lancer l'animation
+ this.screens.intro.show();
// Préparer les réponses du joueur dans l'objet this.responses
// à chaque fois que le formulaire change de valeur
- $(document).on("change", ".active-screen form", function(e) {
+ $(document).on("change", ".active-screen form", function (e) {
$this.responses = []
- $(this).find("input:checked").each(function() {
+ $(this).find("input:checked").each(function () {
$this.responses.push(parseInt($(this).val()))
});
})
$this.next(responses);
$this.responses = []
})
- key('space', function (e){
- e.preventDefault()
- $this.next();
- })
// Réinitialiser les réponses
- $(document).on("click", ".btn.reset", function() {
- $this.resetForm()
- })
- key('r', function (e){
- e.preventDefault()
+ $(document).on("click", ".btn.reset", function () {
$this.resetForm()
})
- if(key.isPressed('R')) {
- alert('r')
- }
-
- $(document).on("mousedown", ".btn", function() {
- gsap.to($(this), { scale: .95, duration: .2, ease: "back.inOut" });
- }).on("mouseup", ".btn", function() {
- gsap.to($(this), { scale: 1, duration: .2 });
+ $(document).on("mousedown", ".btn", function () {
+ gsap.to($(this), {scale: .95, duration: .2, ease: "back.inOut"});
+ }).on("mouseup", ".btn", function () {
+ gsap.to($(this), {scale: 1, duration: .2});
})
//
this.activeNav()
},
- start: function() {
+ start: function () {
const $this = this
gsap.timeline().to("#welcome-screen", {
opacity: 0,
- onComplete: function() {
+ onComplete: function () {
let responses = $this.responses
$this.next(responses);
$("#welcome-screen").removeClass("next active-screen").addClass("none").next(".container-screen").removeClass("none").addClass("next active-screen")
quiz.score.updateScore()
// if form exist and responses are validated
// dont miss to add this second condition
- if($(".active-screen form").length > 0) {
- if(status.length > 0) {
- if(status[this.question.currentPosition()].ok === "not answered") {
+ if ($(".active-screen form").length > 0) {
+ if (status.length > 0) {
+ if (status[this.question.currentPosition()].ok === "not answered") {
this.validateResponse(responses);
this.updateBtnValidation("validated")
return false
this.resetForm()
// on incrémente de 1 la position actuelle de la question (qui commence à l'index zero)
// pour récupérer le premier enfant de la nav
- this.activeNav( (parseInt(this.question.currentPosition())+1) )
+ this.activeNav((parseInt(this.question.currentPosition()) + 1))
this.updateBtnValidation()
// si c'est la dernière question a été validée alors on affiche le résultat au prochain screen
- if(this.question.last(currentPosition)) {
- this.result()
+ if (this.question.last(currentPosition)) {
+ this.screens.outro.show();
}
},
// marque page automatique
// si le joueur recharge la page, le rediriger là où il en était
- setDisplay: function() {
- const currentQuestion = quiz.score.lastAnsweredQuestion + 1,
- questions = this.quiz.questions
+ setDisplay: function () {
+ const currentQuestion = quiz.score.lastAnsweredQuestion + 1,
+ questions = this.quiz.questions
- if(questions.length > 0) {
+ if (questions.length > 0) {
if (quiz.score.lastAnsweredQuestion > -1 && questions.length <= currentQuestion) {
//
}
$("form").find("input").prop("checked", false)
},
- updateBtnValidation: function(status) {
+ updateBtnValidation: function (status) {
let $btnAction = $(".footer-question .action"),
validationText = $btnAction.data("validation-text"),
continueText = $btnAction.data("continue-text")
$btnAction.find('.text').text(status === "validated" ? continueText : validationText)
},
- validateResponse: function(responses) {
+ validateResponse: function (responses) {
const form = $(".active-screen form")
const activeScreen = $(".active-screen")
const position = activeScreen.data("position")
- if(form) {
- if(form.length > 0) {
- let validated = quiz.score.setAnswer(position,responses);
- if(validated.ok === "ok") {
+ if (form) {
+ if (form.length > 0) {
+ let validated = quiz.score.setAnswer(position, responses);
+ if (validated.ok === "ok") {
this.animationValidation("OK")
- }else {
+ } else {
this.animationValidation("NOK")
}
this.resultAfterValidation(validated.status[position].answers)
}
},
- activeNav: function(position = 1) {
+ activeNav: function (position = 1) {
const questionStatus = quiz.score.questionStatus
const lastAnsweredQuestion = quiz.score.lastAnsweredQuestion
- if($(".active-screen").find(".progress-item").length > 0) {
+ if ($(".active-screen").find(".progress-item").length > 0) {
let $el = $(".progress-container .progress-item:nth-child(" + position + ")")
$(".progress-container .progress-item").removeClass("active")
}
},
- animationValidation: function(status) {
+ animationValidation: function (status) {
let selector = $("#anim")
let text = status === "NOK" ? "Not quite" : "Perfect"
let $this = this
this.animations.load(status, selector, {'\\$text': text});
selector.addClass("active")
- this.timeoutAnimation = setTimeout(function(e){
+ this.timeoutAnimation = setTimeout(function (e) {
$this.stopAnimationValidation()
}, 10000)
},
- stopAnimationValidation: function() {
+ stopAnimationValidation: function () {
$("#anim").removeClass("active").empty()
- if(this.timeoutAnimation)
+ if (this.timeoutAnimation)
clearTimeout(this.timeoutAnimation)
},
- resultAfterValidation: function(datas) {
- for(let k in datas) {
+ resultAfterValidation: function (datas) {
+ for (let k in datas) {
let n = (parseInt(k) + 1)
let icon = getSpriteIcon("quiz-ok")
- let $el = $(".active-screen .question-multiple .list-item:nth-of-type("+n+") label")
+ let $el = $(".active-screen .question-multiple .list-item:nth-of-type(" + n + ") label")
$el.addClass(datas[k])
- if(datas[k] === "nok") {
+ if (datas[k] === "nok") {
icon = getSpriteIcon("quiz-wrong")
}
- if(datas[k] !== "neutral") {
+ if (datas[k] !== "neutral") {
$el.find(".access").addClass(datas[k]).html(icon)
}
}
},
- result: function() {
- let maxScore = quiz.score.maxScore,
- score = quiz.score.score
-
- let status = quiz.score.questionStatus
- let reviewList = this.question.getAll();
-
- const counter = $("#progress-counter")
- if(score < (maxScore / 2)) {
- counter.addClass("nok")
- }else if(score >= (maxScore / 2)) {
- counter.addClass("ok")
- }
-
- reviewList = reviewList.map((c,i) => {
- return {
- 'question': c['question'],
- 'answers': c['answers'].filter((c) => {
- return c['correct'] === 1
- }),
- 'status': status[i].ok
- }
- })
- let $ul = $("#answers-list")
-
- $("[id^=score-]").text(score)
- $("[id^=maxScore-]").text(maxScore)
-
- //
- // HANDLEBARS TEMPLATING
- //
- // on applique une incrementation de +1
- // utilisé pour la numérotation des questions
- Handlebars.registerHelper("inc", (value) => { return parseInt(value) + 1; });
-
- // on envoie le html avec les nouvelles données
- const source = $("#template-answers-review").html();
- const template = Handlebars.compile(source);
- const html = template({reviewList: reviewList});
- $ul.html(html)
-
- // mise en place de la scrollbar personnalisé
- // https://github.com/Grsmto/simplebar/tree/master/packages/simplebar
- const simpleBar = new SimpleBar($ul.get(0))
- },
- restart: function() {
+ restart: function () {
}
}