Been a while since I did anything worth writing down technically, but this might be handy for people.
I’m making a robust assessment with the Moodle Quiz activity. It needs to be user-friendly, so if someone fails, we want them to only have to re-answer the questions they got wrong. I had to bail on randomisation to do this, but nevermind. Standing on the shoulders of giants and doing some jiggery-pokery, I got it working for my instance.
I was HEAVILY helped (and indeed only edited) Dom Bauer’s fab work here:
https://moodle.org/mod/forum/discuss.php?d=395125
The problem I had with this code was that, with a multi-page quiz, the ‘i’ or ‘x’ ID would get out of sync with the true IDs of the questions with the 2nd page. So I changed how it picked up the ID based off the DIV IDs for the questions, not their order in jquery’s DOM or whatever.
I also added the above alert div with a button to show the questions they’d already answered, if they wanted to.
Not sure how well it works across more pages; I’ll update this if I need to in future.
For my use, I put the below code into a global filtercodes plugin field, and then just reference that on each quiz page, in the top label. Since that’s how I’m doing mine – but you could put it all in a block or something I suppose.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
// Clear sessionStorage after a certain delay
if (sessionStorage.getItem("setTime") != "set") {
nd = new Date();
lastTime = nd.getTime().toString();
sessionStorage.setItem("time", lastTime);
sessionStorage.setItem("setTime", "set");
}
// Set the delay to say 5 minutes: aferXmin = 5
// (Use 0.33 minutes, i.e. 20 sec, for demonstration purposes)
afterXmin = 5;
maxDelay = afterXmin * 60 * 1000;
d = new Date();
newTime = d.getTime()
lastTime = sessionStorage.getItem("time")
delay = newTime - lastTime;
if (delay > maxDelay) {
sessionStorage.clear();
}
// Show or hide correct or incorrect questions in the previous attempt:
i = 0;
var lbShowInfo = false;
$(".que").each(function() {
// #question-168-8 etc. (8 is the unique ID. ignores labels, page numbers etc. we need to refer to that, not i).
// to get the last number from divs obj_9 --- parseInt($("#objects .obj_item:last img").attr("ID").split("_")[1], 10) + 1;
var x = parseInt($(this).attr('id').split("-")[2]);
i++;
//var x = i.toString(); // supplied code; only works on one page without labels. new x should be ok with multi-page.
if ($(this).hasClass("correct")) {
sessionStorage.setItem(x, "correct");
console.log(x + " correct");
}
if ($(this).hasClass("incorrect")) {
sessionStorage.setItem(x, "incorrect");
console.log(x + " incorrect");
}
if ($(this).hasClass("answersaved") && sessionStorage.getItem(x) == "correct") {
console.log('hiding ' + x);
$(this).hide();
lbShowInfo = true;
} else {
console.log('showing ' + x);
$(this).show();
}
});
if (lbShowInfo == true) {
$("#responseform").before("<div class='alert alert-primary' id='lbAttemptAlert'><h6 class='alert-heading'>Re-attempt</h6>Only the questions you answered incorrectly on the last attempt are shown.</div>");
$("#lbAttemptAlert").append("<button class='btn btn-primary btn-block mt-2' onClick='function:(){$(\".que\").show(\"fast\");}'>Show all</button>");
}
console.log(sessionStorage);
});
</script>
A nice-to-add later will be to change the colour of the nav blocks to their Correct states, for the ones that were previously (and still) correct. But BY GOLLY I have wasted enough time on this today!
Leave a Reply