torierettsegifelkeszito/include/sQuiz/sQuiz.js

274 lines
12 KiB
JavaScript
Raw Normal View History

2019-08-08 13:56:20 +00:00
/**
* /sQuiz/sQuiz.js
* @version 1.4
* @desc sQuiz main class file
* @author Fándly Gergő Zoltán (gergo@systemtest.tk, systemtest.tk)
* @copy 2017 Fándly Gergő Zoltán
* License:
sQuiz for creating small jQuery based quizs in an implementable way
Copyright (C) 2017 Fándly Gergő Zoltán
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
**/
(function($){
/**
* sQuiz(element, quiz)
* @desc Creating a new quiz based on a json file
* @param $ element Container in which the quiz will be running
* @param string quiz A JSON string/JSON object containing an sQuiz parameter list
*/
$.sQuiz=function(element, quiz){
this.element=(element instanceof $)?element:$(element);
this.quiz=(typeof quiz=="object")?quiz:JSON.parse(quiz);
this.current=-1;
this.currentQustion;
this.reg;
this.countdown;
this.elapsedPerTest=(this.quiz.timeLimitPerTest>0)?0:-2;
this.elapsed=(this.quiz.timeLimit>0)?0:-2;
this.answers=[];
this.quizDoneCallback;
this.quizDoneOptions;
};
$.sQuiz.prototype={
/**
* sQuiz.setRegionalization(lang)
* @desc Assing an Object which has all the needed vars for language (startQuiz, timeRemaining, etc. Full list in /sQuiz/lang.json), or leave it on default for English
* @param object lang Object storing language settings
*/
setRegionalization: function(lang){
this.reg=lang;
},
/**
* sQuiz.setQuizDoneCallback(callback)
* @desc Assign a function to run when the quiz is finished
* @param function callback Function to call
*/
setQuizDoneCallback: function(callback){
this.quizDoneCallback=callback;
},
/**
* sQuiz.setQuizDoneOptions(options)
* @desc Set options to offer when quiz is finished. Set download to true, to offer downloading. Set upload to true, to offer online submit to upload_url. Set custom to a JS function call to do self made stuff. Custom action's label regionalization is customAction.
* @param object options Object containing the settings
*/
setQuizDoneOptions: function(options){
this.quizDoneOptions=options;
},
/**
* sQuiz.secToTime(sec)
* @desc Function for converting seconds to traditional MM:SS format
* @param int sec Seconds to convert
* @return string
*/
secToTime: function(sec){
var mins=Math.floor(sec/60);
var secs=sec%60;
var minstr=(mins.toString().length==1)?"0"+mins.toString():mins.toString();
var secstr=(secs.toString().length==1)?"0"+secs.toString():secs.toString();
var time=minstr+":"+secstr;
return time;
},
/**
* sQuiz.quizDone()
* @desc Function to call when a test is finished
*/
quizDone: function(){
var points=0;
$.each(this.answers, function(key, val){
if(val.correct){
points++;
}
});
var self=this;
this.element.slideUp(function(){
var buttons="<div class=\"sq sq-menu\">";
if(self.quizDoneOptions.download==true){
buttons+="<button class=\"sq sq-big\" type=\"button\" id=\"sqDownloadResults\"><i class=\"fa fa-save\"></i>"+self.reg.downloadResults+"</button>";
}
if(self.quizDoneOptions.upload==true){
buttons+="<button class=\"sq sq-big\" type=\"button=\" id=\"sqUploadResults\"><i class=\"fa fa-upload\"></i>"+self.reg.uploadResults+"</button>";
}
if(self.quizDoneOptions.custom!=undefined){
buttons+="<button class=\"sq sq-big\" type=\"button=\" id=\"sqCustomAction\" onclick=\""+self.quizDoneOptions.custom+"\">"+self.reg.customAction+"</button>";
}
buttons+="</div>";
self.element.html("<h2>"+self.reg.quizFinished+"</h2><hr class=\"sq sq-placeholder\" style=\"height: 10vh\"><div class=\"sq sq-center\"><h3>"+self.reg.resultsGot+": <b>"+points.toString()+"/"+self.quiz.questions.length+"</b></h3><br><br>"+buttons);
$("#sqDownloadResults").on("click", function(){
var json=JSON.stringify(self.answers);
var send="text/json;charset=utf-8,"+encodeURIComponent(json);
$("<a href=\"data:"+send+"\" download=\""+self.quiz.name+"_answers_sQuiz.json\"></a>")[0].click();
});
$("#sqUploadResults").on("click", function(){
var json=JSON.stringify(self.answers);
var submitter=prompt(self.reg.yourname+":");
$.ajax({
url: (self.quizDoneOptions.upload_url!=undefined)?self.quizDoneOptions.upload_url:"",
type: "POST",
data: {
"submitResult": json,
"submitResult_submitter": submitter
},
success: function(res){
alert(self.reg.idForResult+": "+res);
}
});
});
self.element.slideDown();
});
if(this.quizDoneCallback!=undefined){
this.quizDoneCallback(this.answers, this.quiz);
}
},
/**
* sQuiz.nextQuestion()
* @desc Start the next question. Should be called only internally!
*/
nextQuestion: function(){
var self=this;
this.current++;
if(this.current>=this.quiz.questions.length){
this.quizDone();
}
else{
var type=this.quiz.questions[this.current].type;
this.element.slideUp(function(){
var timer="<p id=\"sqTimer\">"+(self.quiz.timeLimit>0?"<b>"+self.reg.timeLeft+":</b> <span id=\"sqTimeLeft\"></span><br>":"")+(self.quiz.timeLimitPerTest>0?"<b>"+self.reg.timeLeftPerTest+":</b> <span id=\"sqTimeLeftPerTest\"></span>":"")+"</p>";
var submitbutton="<br><br><div class=\"sq sq-center\"><button class=\"sq green sq-big\" id=\"sqSubmitButton\"><i class=\"fa fa-check\"></i>"+self.reg.submit+"</button></div>";
self.element.html(timer+"<hr class=\"sq-placeholder\"><div id=\"sqTestArea\" style=\"overflow: auto\"></div>"+submitbutton);
self.element.children("#sqTimeLeft").html(self.secToTime(self.timeLimit));
self.element.children("#sqTimeLeftPerTest").html(self.secToTime(self.timeLimitPerTest));
self.currentQuestion=new $["sQuiz_module_"+type](self, self.quiz.questions[self.current]);
$("#sqSubmitButton").on("click", function(){
self.currentQuestion.submit();
$("#sqSubmitButton").unbind();
$("#sqSubmitButton").fadeOut(function(){
$(this).html("<i class=\"fa fa-arrow-right\"></i>"+self.reg.nextQuestion);
$(this).fadeIn();
});
$("#sqSubmitButton").on("click", function(){
self.nextQuestion();
});
});
self.currentQuestion.load();
self.element.slideDown(function(){
self.startTimer();
});
});
}
},
/**
* sQuiz.init()
* @desc set up styles and so for the container
*/
init: function(){
var self=this;
if(this.reg==undefined){
this.reg={
"downloadResults":"Download results",
"uploadResults":"Upload results",
"customAction":"Custom action name goes here",
"quizFinished":"Quiz finished!",
"resultsGot":"You've got the following results",
"yourname":"Your name",
"idForResult":"Share this ID with anybody you want to know your results",
"timeLeft":"Time left for entire quiz",
"timeLeftPerTest":"Time left for this question",
"submit":"Submit",
"nextQuestion":"Next question",
"startQuiz":"Start quiz",
"answer":"Answer"
};
}
this.element.hide();
this.element.addClass("sq sq-container");
this.element.html("<hr class=\"sq sq-placeholder\" style=\"height: 20vh\"><h2>"+this.quiz.name+"</h2><p>"+this.quiz.description+"</p><hr><div class=\"sq sq-center\"><button class=\"sq sq-big\" id=\"sqStart\">"+this.reg.startQuiz+"</button></div>");
$("#sqStart").on("click", function(){
self.nextQuestion();
});
this.element.slideDown();
},
/**
* sQuiz.startTimer
* @desc Starts the countdown
*/
startTimer: function(){
if(this.quiz.timeLimitPerTest>0 || this.quiz.timeLimit>0){
var self=this;
this.elapsedPerTest=0;
if(self.quiz.timeLimitPerTest>0){
self.elapsedPerTest++;
self.element.children("#sqTimer").children("#sqTimeLeftPerTest").html(self.secToTime(self.quiz.timeLimitPerTest-self.elapsedPerTest));
if(self.elapsedPerTest>=self.quiz.timeLimitPerTest){
$("#sqSubmitButton")[0].click();
}
}
if(self.quiz.timeLimit>0){
self.elapsed++;
self.element.children("#sqTimer").children("#sqTimeLeft").html(self.secToTime(self.quiz.timeLimit-self.elapsed));
if(self.elapsed>=self.quiz.timeLimit){
$("#sqSubmitButton")[0].click();
}
}
this.countdown=window.setInterval(function(self){
if(self.quiz.timeLimitPerTest>0){
self.elapsedPerTest++;
self.element.children("#sqTimer").children("#sqTimeLeftPerTest").html(self.secToTime(self.quiz.timeLimitPerTest-self.elapsedPerTest));
if(self.elapsedPerTest>=self.quiz.timeLimitPerTest){
$("#sqSubmitButton")[0].click();
}
}
if(self.quiz.timeLimit>0){
self.elapsed++;
self.element.children("#sqTimer").children("#sqTimeLeft").html(self.secToTime(self.quiz.timeLimit-self.elapsed));
if(self.elapsed>=self.quiz.timeLimit){
$("#sqSubmitButton")[0].click();
}
}
}, 1000, self);
}
},
/**
* sQuiz.stopTimer
* @desc Stops the countdown
*/
stopTimer: function(){
clearInterval(this.countdown);
}
}
}(jQuery));