/* * JavaScript library for the quiz module. * * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ function init_quiz_form() { var responseform = document.getElementById('responseform'); responseform.setAttribute('autocomplete', 'off'); YAHOO.util.Event.addListener(responseform, 'keypress', check_enter); YAHOO.util.Event.addListener(responseform, 'submit', quiz_timer.stop); } /* Use this in an onkeypress handler, to stop enter submitting the forum unless you are actually on the submit button. Don't stop the user typing things in text areas. */ function check_enter(e) { var target = e.target ? e.target : e.srcElement; var keyCode = e.keyCode ? e.keyCode : e.which; if (keyCode==13 && target.nodeName.toLowerCase()!='a' && (!target.type || !(target.type=='submit' || target.type=='textarea'))) { YAHOO.util.Event.preventDefault(e); } } // Code for updating the countdown timer that is used on timed quizzes. quiz_timer = { // The outer div, so we can get at it to move it when the page scrolls. timerouter: null, // The element that the time should be displayed in. timerdisplay: null, // The main quiz for, which we will need to submit when the time expires. quizform: null, // String that is displayed after the time has run out. strtimeup: '', // How long is left, in seconds. endtime: 0, // How often we update the clock display. Delay in milliseconds. updatedelay: 500, // This records the id of the timeout that updates the clock periodically, so we can cancel it // Once time has run out. timeoutid: null, // Colours used to change the timer bacground colour when time had nearly run out. // This array is indexed by number of seconds left. finalcolours: [ '#ff0000', '#ff1111', '#ff2222', '#ff3333', '#ff4444', '#ff5555', '#ff6666', '#ff7777', '#ff8888', '#ff9999', '#ffaaaa', '#ffbbbb', '#ffcccc', '#ffdddd', '#ffeeee', '#ffffff', ], // Initialise method. initialise: function(strtimeup, timeleft) { // Set some fields. quiz_timer.strtimeup = strtimeup; quiz_timer.endtime = new Date().getTime() + timeleft*1000; // Get references to some bits of the DOM we need. quiz_timer.timerouter = document.getElementById('quiz-timer'); quiz_timer.timerdisplay = document.getElementById('quiz-time-left'); quiz_timer.quizform = document.getElementById('responseform'); // Make the timer visible. quiz_timer.timerouter.style.display = 'block'; // Get things started. quiz_timer.update_time(); }, // Stop method. Stops the timer if it is running. stop: function() { if (quiz_timer.timeoutid) { clearTimeout(quiz_timer.timeoutid); } }, // Function that updates the text displayed in element timer_display. set_displayed_time: function(str) { var display = quiz_timer.timerdisplay if (!display.firstChild) { display.appendChild(document.createTextNode(str)) } else if (display.firstChild.nodeType == 3) { display.firstChild.replaceData(0, display.firstChild.length, str); } else { display.replaceChild(document.createTextNode(str), display.firstChild); } }, // Function to convert a number between 0 and 99 to a two-digit string. two_digit: function(num) { if (num < 10) { return '0' + num; } else { return num; } }, // Function to update the clock with the current time left, and submit the quiz if necessary. update_time: function() { var secondsleft = Math.floor((quiz_timer.endtime - new Date().getTime())/1000); // If time has expired, Set the hidden form field that says time has expired. if (secondsleft < 0) { quiz_timer.stop(); quiz_timer.set_displayed_time(quiz_timer.strtimeup); quiz_timer.quizform.elements.timeup.value = 1; if (quiz_timer.quizform.onsubmit) { quiz_timer.quizform.onsubmit(); } quiz_timer.quizform.submit(); return; } // If time has nearly expired, change the colour. if (secondsleft < quiz_timer.finalcolours.length) { quiz_timer.timerouter.style.backgroundColor = quiz_timer.finalcolours[secondsleft]; } // Update the time display. var hours = Math.floor(secondsleft/3600); secondsleft -= hours*3600; var minutes = Math.floor(secondsleft/60); secondsleft -= minutes*60; var seconds = secondsleft; quiz_timer.set_displayed_time('' + hours + ':' + quiz_timer.two_digit(minutes) + ':' + quiz_timer.two_digit(seconds)); // Arrange for this method to be called again soon. quiz_timer.timeoutid = setTimeout(quiz_timer.update_time, quiz_timer.updatedelay); } }; // Set up synchronisation between question flags and the corresponding button in the nav panel. function quiz_init_nav_flags() { var navblock = document.getElementById('quiznavigation'); var buttons = YAHOO.util.Dom.getElementsByClassName('qnbutton', 'a', navblock); for (var i = 0; i < buttons.length; i++) { var button = buttons[i]; var questionid = button.id.match(/\d+/)[0]; button.stateupdater = new quiz_nav_updater(button, questionid); } } // Make the links in the attempt nav panel submit the form. function quiz_init_attempt_nav() { var warning = document.getElementById('quiznojswarning'); warning.parentNode.removeChild(warning); var navblock = document.getElementById('quiznavigation'); var buttons = YAHOO.util.Dom.getElementsByClassName('qnbutton', 'a', navblock); for (var i = 0; i < buttons.length; i++) { var button = buttons[i]; if (YAHOO.util.Dom.hasClass(button, 'thispage')) { continue; } var pageidmatch = button.href.match(/page=(\d+)/); var nav = {pageid: pageidmatch[1]}; var questionidmatch = button.href.match(/#q(\d+)/); if (questionidmatch) { nav.questionid = questionidmatch[1]; } YAHOO.util.Event.addListener(button, 'click', quiz_nav_button_click, nav); } var endlink = YAHOO.util.Dom.getElementsByClassName('endtestlink', 'a', navblock)[0]; YAHOO.util.Event.addListener(endlink, 'click', quiz_end_test_click); } function quiz_nav_button_click(e, nav) { YAHOO.util.Event.preventDefault(e); document.getElementById('nextpagehiddeninput').value = nav.pageid; var form = document.getElementById('responseform'); if (nav.questionid) { form.action += '#q' + nav.questionid; } form.submit(); } function quiz_end_test_click(e) { YAHOO.util.Event.preventDefault(e); document.getElementById('nextpagehiddeninput').value = -1; document.getElementById('responseform').submit(); } function quiz_nav_updater(element, questionid) { this.element = element; question_flag_changer.add_flag_state_listener(questionid, this); }; quiz_nav_updater.prototype.flag_state_changed = function(newstate) { this.element.className = this.element.className.replace(/\s*\bflagged\b\s*/, ' '); if (newstate) { this.element.className += ' flagged'; } }; quiz_secure_window = { // The message displayed when the secure window interferes with the user. protection_message: null, // Used by close. The URL to redirect to, if we find we are not acutally in a pop-up window. close_next_url: '', // Code for secure window. This used to be in protect_js.php. I don't understand it, // I have just moved it for clenliness reasons. initialise: function(strmessage) { quiz_secure_window.protection_message = strmessage; if (document.layers) { document.captureEvents(Event.MOUSEDOWN); } document.onmousedown = quiz_secure_window.intercept_click; document.oncontextmenu = function() {alert(quiz_secure_window.protection_message); return false;}; }, // Code for secure window. This used to be in protect_js.php. I don't understand it, // I have just moved it for clenliness reasons. intercept_click: function(e) { if (document.all) { if (event.button==1) { return false; } if (event.button==2) { alert(quiz_securewindow_message); return false; } } if (document.layers) { if (e.which > 1) { alert(quiz_securewindow_message); return false; } } }, close: function(url, delay) { if (url != '') { quiz_secure_window.close_next_url = url; } if (delay > 0) { setTimeout(function() {quiz_secure_window.close('', 0);}, delay*1000); } else { if (window.opener) { window.opener.document.location.reload(); window.close(); } else if (quiz_secure_window.close_next_url != '') { window.location.href = quiz_secure_window.close_next_url; } } } }; function reveal_start_button() { document.getElementById('quizstartbutton').style.cssText = ''; }