Moodle Quiz – only answer previously incorrect questions on second attempt

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.

Dirty-dog div slapped up top when the previously correctly answered questions are hidden.

I was HEAVILY helped (and indeed only edited) Dom Bauer’s fab work here:

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=""></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) {
        // 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]);
            //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);
                lbShowInfo = true;
            } else {
				console.log('showing ' + x);
        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>");

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!

Tech Reference:

Leave a Reply

Your email address will not be published. Required fields are marked *

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑