/* JS for the quiz. Some of this code runs immediately when the script is referenced (i.e. not in response to user
action) so it's important to import this script at the end of the page to ensure that the HTML objects it references
are created by the time the script runs.

It's inelegant in that it loops through all of the questions each time a single button is clicked. There's 
probably nicer ways to do this, but this approach has some desirable features --
- Works in all browsers I tested 
- Gracefully handles a page refresh where this script gets reinitialized but the state of the 
    radio buttons does not (also back/forward navigation, etc.)
- Should work even under browsers that allow one to explicitly deselect a selected radio    
    button (although none of my test browsers seem to permit this).
*/ 

// This constant is defined as Node.ELEMENT_NODE in Mozilla, document.ELEMENT_NODE in other browsers 
// and not at all in IE.
var ELEMENT_NODE = 1;

/* Global variables */

// I cache several items: a list of the questions (each is a list item) in the quiz, the correct answer text
// (built on the fly) and handles to some commonly-accessed elements.
var questions = document.getElementById("quiz").getElementsByTagName("li");
var correctAnswerText = [ ];
var completeDiv = document.getElementById("complete");
var incompleteDiv = document.getElementById("incomplete");

{
    // This is init code meant to be executed once when the page (re)loads. It is in brackets only
    // to prevent namespace pollution.
    var buttons = document.getElementById("quiz").getElementsByTagName("input");
    var label = null;
    
    // For each question in the quiz, find & cache the correct answer text.
    for (var i = 0; i < questions.length; i++) {
        label = questions[i].getElementsByTagName("label")[correctAnswers[i]];
        correctAnswerText[i] = label.textContent || label.innerText;
    }
    
    // Attach the function evaluateAnswers to the onlick event of each radio button.
    for (var i = 0; i < buttons.length; i++)
        buttons[i].onclick = evaluateAnswers;
}

function getResultDiv(li) { return li.getElementsByTagName("div")[0]; }

function findUserAnswer(li) {
    // Returns the (zero-based) index of the user's answer for this question, or -1 if unanswered.
    var buttons = li.getElementsByTagName("input");
    var i = 0;
    
    while ((i < buttons.length) && (!buttons[i].checked))
        i++;
        
    return (i < buttons.length) ? i : -1;
}

function removeChildren(e) { while(e.firstChild) e.removeChild(e.firstChild); }

function setElementText(e, s) {
    // textContent is the W3C standard. Want to guess which browser doesn't support it?
    (e.textContent == undefined) ? e.innerText = s : e.textContent = s;
}

function evaluateAnswers() {
	// This function is inelegant in that it loops through all of the questions twice. The first time
	// it counts the number of questions answered. The second time it hides or shows the result DIVs
	// depending on whether or not all of the questions have been answered. I tried doing it in one 
	// loop but browsers don't repaint properly when I update hidden elements and then display them.
	var questionsCompleted = 0;
    var questionsAnsweredCorrectly = 0;
	var em;
	var i;
	var userAnswers = [ ];

    for (i = 0;  i < questions.length; i++) {
        userAnswers[i] = findUserAnswer(questions[i]);
        
        if (userAnswers[i] != -1)
            questionsCompleted += 1;
    }
    
    for (i = 0;  i < questions.length; i++) {
        div = getResultDiv(questions[i]);
        
        if (questionsCompleted == questions.length) {
            // Each question has been answered so I display the results.
            div.style.display = "block";
            removeChildren(div);

            if (userAnswers[i] == correctAnswers[i]) {
                questionsAnsweredCorrectly += 1;
                div.appendChild(document.createTextNode("Correct!"));
                div.style.borderLeft = "4px solid green";
                div.style.backgroundColor = "#c2ffbf";
            }
            else {
                div.appendChild(document.createTextNode("The correct answer is "));
                em = document.createElement("em");
                em.appendChild(document.createTextNode(correctAnswerText[i] + "."));
                div.appendChild(em);
                div.style.borderLeft = "4px solid red";
                div.style.backgroundColor = "#ffb4b4";
            }
        }
        else
            div.style.display = "none";
    }


    if (questionsCompleted == questions.length) {
	    setElementText(completeDiv, 
	                   "You answered " + questionsAnsweredCorrectly.toString() + " of " + questions.length.toString() + " questions correctly.");
		completeDiv.style.display = "block";
		incompleteDiv.style.display = "none";
    }
}


// Initialize the state of the page.
evaluateAnswers();


