mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 00:46:50 +02:00
quiz: MDL-19891 fix that quiz navigation block that was broken by the blocks changes.
Sadly it now requries JavaScript again, at least for best operation.
This commit is contained in:
parent
75003899ae
commit
d18675a8d7
9 changed files with 331 additions and 133 deletions
|
@ -434,6 +434,7 @@ $string['multichoice'] = 'Multiple Choice';
|
||||||
$string['multipleanswers'] = 'Choose at least one answer.';
|
$string['multipleanswers'] = 'Choose at least one answer.';
|
||||||
$string['multiplier'] = 'Multiplier';
|
$string['multiplier'] = 'Multiplier';
|
||||||
$string['name'] = 'Name';
|
$string['name'] = 'Name';
|
||||||
|
$string['navnojswarning'] = 'Warning: these links will not save your answers. Use the next button at the bottom of the page.';
|
||||||
$string['neverallononepage'] = 'Never, all questions on one page';
|
$string['neverallononepage'] = 'Never, all questions on one page';
|
||||||
$string['newattemptfail'] = 'Error: Could not start a new attempt at the quiz';
|
$string['newattemptfail'] = 'Error: Could not start a new attempt at the quiz';
|
||||||
$string['newpage'] = 'New page';
|
$string['newpage'] = 'New page';
|
||||||
|
@ -675,6 +676,7 @@ $string['showbreaks'] = 'Show page breaks';
|
||||||
$string['showcategorycontents'] = 'Show category contents $a->arrow';
|
$string['showcategorycontents'] = 'Show category contents $a->arrow';
|
||||||
$string['showcorrectanswer'] = 'In feedback, show correct answers?';
|
$string['showcorrectanswer'] = 'In feedback, show correct answers?';
|
||||||
$string['showdetailedmarks'] = 'Show mark details';
|
$string['showdetailedmarks'] = 'Show mark details';
|
||||||
|
$string['showeachpage'] = 'Show one page at a time';
|
||||||
$string['showfeedback'] = 'After answering, show feedback?';
|
$string['showfeedback'] = 'After answering, show feedback?';
|
||||||
$string['showhidden'] = 'Also show old questions';
|
$string['showhidden'] = 'Also show old questions';
|
||||||
$string['showinsecurepopup'] = 'Use a \'secure\' popup window for attempts';
|
$string['showinsecurepopup'] = 'Use a \'secure\' popup window for attempts';
|
||||||
|
|
|
@ -86,7 +86,6 @@
|
||||||
$PAGE->blocks->add_pretend_block($navbc, $firstregion);
|
$PAGE->blocks->add_pretend_block($navbc, $firstregion);
|
||||||
|
|
||||||
// Print the page header
|
// Print the page header
|
||||||
$PAGE->requires->yui_lib('event');
|
|
||||||
$title = get_string('attempt', 'quiz', $attemptobj->get_attempt_number());
|
$title = get_string('attempt', 'quiz', $attemptobj->get_attempt_number());
|
||||||
$headtags = $attemptobj->get_html_head_contributions($page);
|
$headtags = $attemptobj->get_html_head_contributions($page);
|
||||||
if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
|
if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
|
||||||
|
@ -123,9 +122,7 @@
|
||||||
// A quiz page with a lot of questions can take a long time to load, and we
|
// A quiz page with a lot of questions can take a long time to load, and we
|
||||||
// want the protection afforded by init_quiz_form immediately, so include the
|
// want the protection afforded by init_quiz_form immediately, so include the
|
||||||
// JS now.
|
// JS now.
|
||||||
echo $PAGE->requires->yui_lib('event')->asap();
|
echo $PAGE->requires->js_function_call('init_quiz_form')->now();
|
||||||
echo $PAGE->requires->js('mod/quiz/quiz.js')->asap();
|
|
||||||
echo $PAGE->requires->js_function_call('init_quiz_form')->asap();
|
|
||||||
echo '<div>';
|
echo '<div>';
|
||||||
|
|
||||||
/// Print all the questions
|
/// Print all the questions
|
||||||
|
@ -137,17 +134,15 @@
|
||||||
echo '<div class="submitbtns">';
|
echo '<div class="submitbtns">';
|
||||||
if ($attemptobj->is_last_page($page)) {
|
if ($attemptobj->is_last_page($page)) {
|
||||||
$nextpage = -1;
|
$nextpage = -1;
|
||||||
$nextpageforie = 'gotosummary';
|
|
||||||
} else {
|
} else {
|
||||||
$nextpage = $page + 1;
|
$nextpage = $page + 1;
|
||||||
$nextpageforie = 'gotopage' . $nextpage;
|
|
||||||
}
|
}
|
||||||
echo '<input type="submit" name="' . $nextpageforie . '" value="' . get_string('next') . '" />';
|
echo '<input type="submit" value="' . get_string('next') . '" />';
|
||||||
echo "</div>";
|
echo "</div>";
|
||||||
|
|
||||||
// Some hidden fields to trach what is going on.
|
// Some hidden fields to trach what is going on.
|
||||||
echo '<input type="hidden" name="attempt" value="' . $attemptobj->get_attemptid() . '" />';
|
echo '<input type="hidden" name="attempt" value="' . $attemptobj->get_attemptid() . '" />';
|
||||||
echo '<input type="hidden" name="nextpage" value="' . $nextpage . '" />';
|
echo '<input type="hidden" name="nextpage" id="nextpagehiddeninput" value="' . $nextpage . '" />';
|
||||||
echo '<input type="hidden" name="timeup" id="timeup" value="0" />';
|
echo '<input type="hidden" name="timeup" id="timeup" value="0" />';
|
||||||
echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';
|
echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,39 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* This class handles loading all the information about a quiz attempt into memory,
|
|
||||||
* and making it available for attemtp.php, summary.php and review.php.
|
|
||||||
* Initially, it only loads a minimal amout of information about each attempt - loading
|
|
||||||
* extra information only when necessary or when asked. The class tracks which questions
|
|
||||||
* are loaded.
|
|
||||||
*//** */
|
|
||||||
|
|
||||||
if (!defined('MOODLE_INTERNAL')) {
|
// This file is part of Moodle - http://moodle.org/
|
||||||
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page.
|
//
|
||||||
}
|
// Moodle 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.
|
||||||
|
//
|
||||||
|
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Back-end code for handling data about quizzes and the current user's attempt.
|
||||||
|
*
|
||||||
|
* There are classes for loading all the information about a quiz and attempts,
|
||||||
|
* and for displaying the navigation panel.
|
||||||
|
*
|
||||||
|
* @package quiz
|
||||||
|
* @copyright 2008 onwards Tim Hunt
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for quiz exceptions. Just saves a couple of arguments on the
|
* Class for quiz exceptions. Just saves a couple of arguments on the
|
||||||
* constructor for a moodle_exception.
|
* constructor for a moodle_exception.
|
||||||
|
*
|
||||||
|
* @copyright 2008 Tim Hunt
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
* @since Moodle 2.0
|
||||||
*/
|
*/
|
||||||
class moodle_quiz_exception extends moodle_exception {
|
class moodle_quiz_exception extends moodle_exception {
|
||||||
function __construct($quizobj, $errorcode, $a = NULL, $link = '', $debuginfo = null) {
|
function __construct($quizobj, $errorcode, $a = NULL, $link = '', $debuginfo = null) {
|
||||||
|
@ -25,8 +45,16 @@ class moodle_quiz_exception extends moodle_exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base class for holding and accessing information about a quiz and its questions,
|
* A class encapsulating a quiz and the questions it contains, and making the
|
||||||
* before details of a particular attempt are loaded.
|
* information available to scripts like view.php.
|
||||||
|
*
|
||||||
|
* Initially, it only loads a minimal amout of information about each question - loading
|
||||||
|
* extra information only when necessary or when asked. The class tracks which questions
|
||||||
|
* are loaded.
|
||||||
|
*
|
||||||
|
* @copyright 2008 Tim Hunt
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
* @since Moodle 2.0
|
||||||
*/
|
*/
|
||||||
class quiz {
|
class quiz {
|
||||||
// Fields initialised in the constructor.
|
// Fields initialised in the constructor.
|
||||||
|
@ -63,10 +91,19 @@ class quiz {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions for loading more data =====================================================
|
// Functions for loading more data =====================================================
|
||||||
|
/**
|
||||||
|
* Convenience method. Calls {@link load_questions()} with the list of
|
||||||
|
* question ids for a given page.
|
||||||
|
*
|
||||||
|
* @param integer $page a page number.
|
||||||
|
*/
|
||||||
public function load_questions_on_page($page) {
|
public function load_questions_on_page($page) {
|
||||||
$this->load_questions($this->pagequestionids[$page]);
|
$this->load_questions($this->pagequestionids[$page]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load just basic information about all the questions in this quiz.
|
||||||
|
*/
|
||||||
public function preload_questions() {
|
public function preload_questions() {
|
||||||
if (empty($this->questionids)) {
|
if (empty($this->questionids)) {
|
||||||
throw new moodle_quiz_exception($this, 'noquestions', $this->edit_url());
|
throw new moodle_quiz_exception($this, 'noquestions', $this->edit_url());
|
||||||
|
@ -79,7 +116,7 @@ class quiz {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load some or all of the questions for this quiz.
|
* Fully load some or all of the questions for this quiz. You must call {@link preload_questions()} first.
|
||||||
*
|
*
|
||||||
* @param array $questionids question ids of the questions to load. null for all.
|
* @param array $questionids question ids of the questions to load. null for all.
|
||||||
*/
|
*/
|
||||||
|
@ -301,14 +338,20 @@ class quiz {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private methods =====================================================================
|
// Private methods =====================================================================
|
||||||
// Check that the definition of a particular question is loaded, and if not throw an exception.
|
/**
|
||||||
|
* Check that the definition of a particular question is loaded, and if not throw an exception.
|
||||||
|
* @param $id a questionid.
|
||||||
|
*/
|
||||||
protected function ensure_question_loaded($id) {
|
protected function ensure_question_loaded($id) {
|
||||||
if (isset($this->questions[$id]->_partiallyloaded)) {
|
if (isset($this->questions[$id]->_partiallyloaded)) {
|
||||||
throw new moodle_quiz_exception($this, 'questionnotloaded', $id);
|
throw new moodle_quiz_exception($this, 'questionnotloaded', $id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function determine_layout() {
|
/**
|
||||||
|
* Populate {@link $questionids} and {@link $pagequestionids} from the layout.
|
||||||
|
*/
|
||||||
|
protected function determine_layout() {
|
||||||
$this->questionids = array();
|
$this->questionids = array();
|
||||||
$this->pagequestionids = array();
|
$this->pagequestionids = array();
|
||||||
|
|
||||||
|
@ -340,7 +383,9 @@ class quiz {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number the questions.
|
/**
|
||||||
|
* Number the questions, adding a _number field to each one.
|
||||||
|
*/
|
||||||
private function number_questions() {
|
private function number_questions() {
|
||||||
$number = 1;
|
$number = 1;
|
||||||
foreach ($this->pagequestionids as $page => $questionids) {
|
foreach ($this->pagequestionids as $page => $questionids) {
|
||||||
|
@ -368,6 +413,10 @@ class quiz {
|
||||||
/**
|
/**
|
||||||
* This class extends the quiz class to hold data about the state of a particular attempt,
|
* This class extends the quiz class to hold data about the state of a particular attempt,
|
||||||
* in addition to the data about the quiz.
|
* in addition to the data about the quiz.
|
||||||
|
*
|
||||||
|
* @copyright 2008 Tim Hunt
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
* @since Moodle 2.0
|
||||||
*/
|
*/
|
||||||
class quiz_attempt extends quiz {
|
class quiz_attempt extends quiz {
|
||||||
// Fields initialised in the constructor.
|
// Fields initialised in the constructor.
|
||||||
|
@ -424,7 +473,12 @@ class quiz_attempt extends quiz {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load basic information about the state of each question.
|
||||||
|
*
|
||||||
|
* This is enough to, for example, show the state of each question in the
|
||||||
|
* navigation panel, but only takes one DB query.
|
||||||
|
*/
|
||||||
public function preload_question_states() {
|
public function preload_question_states() {
|
||||||
if (empty($this->questionids)) {
|
if (empty($this->questionids)) {
|
||||||
throw new moodle_quiz_exception($this, 'noquestions', $this->edit_url());
|
throw new moodle_quiz_exception($this, 'noquestions', $this->edit_url());
|
||||||
|
@ -435,6 +489,14 @@ class quiz_attempt extends quiz {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a particular state of a particular question. Used by the reviewquestion.php
|
||||||
|
* script to let the teacher walk through the entire sequence of a student's
|
||||||
|
* interaction with a question.
|
||||||
|
*
|
||||||
|
* @param $questionid the question id
|
||||||
|
* @param $stateid the id of the particular state to load.
|
||||||
|
*/
|
||||||
public function load_specific_question_state($questionid, $stateid) {
|
public function load_specific_question_state($questionid, $stateid) {
|
||||||
global $DB;
|
global $DB;
|
||||||
$state = question_load_specific_state($this->questions[$questionid],
|
$state = question_load_specific_state($this->questions[$questionid],
|
||||||
|
@ -508,6 +570,12 @@ class quiz_attempt extends quiz {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current state of a question in the attempt.
|
||||||
|
*
|
||||||
|
* @param $questionid a questionid.
|
||||||
|
* @return object the state.
|
||||||
|
*/
|
||||||
public function get_question_state($questionid) {
|
public function get_question_state($questionid) {
|
||||||
$this->ensure_state_loaded($questionid);
|
$this->ensure_state_loaded($questionid);
|
||||||
return $this->states[$questionid];
|
return $this->states[$questionid];
|
||||||
|
@ -612,16 +680,16 @@ class quiz_attempt extends quiz {
|
||||||
|
|
||||||
// URLs related to this attempt ========================================================
|
// URLs related to this attempt ========================================================
|
||||||
/**
|
/**
|
||||||
* @param integer $page if specified, the URL of this particular page of the attempt, otherwise
|
|
||||||
* the URL will go to the first page.
|
|
||||||
* @param integer $questionid a question id. If set, will add a fragment to the URL
|
* @param integer $questionid a question id. If set, will add a fragment to the URL
|
||||||
* to jump to a particuar question on the page.
|
* to jump to a particuar question on the page.
|
||||||
|
* @param integer $page if specified, the URL of this particular page of the attempt, otherwise
|
||||||
|
* the URL will go to the first page. If -1, deduce $page from $questionid.
|
||||||
|
* @param integer $thispage if not -1, the current page. Will cause links to other things on
|
||||||
|
* this page to be output as only a fragment.
|
||||||
* @return string the URL to continue this attempt.
|
* @return string the URL to continue this attempt.
|
||||||
*/
|
*/
|
||||||
public function attempt_url($questionid = 0, $page = -1) {
|
public function attempt_url($questionid = 0, $page = -1, $thispage = -1) {
|
||||||
global $CFG;
|
return $this->page_and_question_url('attempt', $questionid, $page, false, $thispage);
|
||||||
return $CFG->wwwroot . '/mod/quiz/attempt.php?attempt=' . $this->attempt->id .
|
|
||||||
$this->page_and_question_fragment($questionid, $page);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -641,32 +709,46 @@ class quiz_attempt extends quiz {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param integer $questionid a question id. If set, will add a fragment to the URL
|
||||||
|
* to jump to a particuar question on the page. If -1, deduce $page from $questionid.
|
||||||
* @param integer $page if specified, the URL of this particular page of the attempt, otherwise
|
* @param integer $page if specified, the URL of this particular page of the attempt, otherwise
|
||||||
* the URL will go to the first page.
|
* the URL will go to the first page.
|
||||||
* @param integer $questionid a question id. If set, will add a fragment to the URL
|
|
||||||
* to jump to a particuar question on the page.
|
|
||||||
* @param boolean $showall if true, the URL will be to review the entire attempt on one page,
|
* @param boolean $showall if true, the URL will be to review the entire attempt on one page,
|
||||||
* and $page will be ignored.
|
* and $page will be ignored.
|
||||||
* @param $otherattemptid if given, link to another attempt, instead of the one we represent.
|
* @param integer $thispage if not -1, the current page. Will cause links to other things on
|
||||||
|
* this page to be output as only a fragment.
|
||||||
* @return string the URL to review this attempt.
|
* @return string the URL to review this attempt.
|
||||||
*/
|
*/
|
||||||
public function review_url($questionid = 0, $page = -1, $showall = false) {
|
public function review_url($questionid = 0, $page = -1, $showall = false, $thispage = -1) {
|
||||||
global $CFG;
|
return $this->page_and_question_url('review', $questionid, $page, $showall, $thispage);
|
||||||
return $CFG->wwwroot . '/mod/quiz/review.php?attempt=' . $this->attempt->id .
|
|
||||||
$this->page_and_question_fragment($questionid, $page, $showall);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bits of content =====================================================================
|
// Bits of content =====================================================================
|
||||||
|
/**
|
||||||
|
* Initialise the JS etc. required all the questions on a page..
|
||||||
|
* @param mixed $page a page number, or 'all'.
|
||||||
|
*/
|
||||||
public function get_html_head_contributions($page = 'all') {
|
public function get_html_head_contributions($page = 'all') {
|
||||||
return get_html_head_contributions($this->get_question_ids($page),
|
global $PAGE;
|
||||||
$this->questions, $this->states);
|
// The JS does important things like navigation and so must be initialised
|
||||||
|
// as seen as possible, particularly if the page is loading slowly.
|
||||||
|
$PAGE->requires->yui_lib('dom')->in_head();
|
||||||
|
$PAGE->requires->yui_lib('event')->in_head();
|
||||||
|
$PAGE->requires->js('mod/quiz/quiz.js')->in_head();
|
||||||
|
get_html_head_contributions($this->get_question_ids($page), $this->questions, $this->states);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the JS etc. required by one question.
|
||||||
|
* @param integer $questionid the question id.
|
||||||
|
*/
|
||||||
public function get_question_html_head_contributions($questionid) {
|
public function get_question_html_head_contributions($questionid) {
|
||||||
return get_html_head_contributions(array($questionid),
|
get_html_head_contributions(array($questionid), $this->questions, $this->states);
|
||||||
$this->questions, $this->states);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the HTML for the start new preview button.
|
||||||
|
*/
|
||||||
public function print_restart_preview_button() {
|
public function print_restart_preview_button() {
|
||||||
global $CFG;
|
global $CFG;
|
||||||
echo '<div class="controls">';
|
echo '<div class="controls">';
|
||||||
|
@ -675,6 +757,10 @@ class quiz_attempt extends quiz {
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the HTML of the quiz timer.
|
||||||
|
* @return string HTML content.
|
||||||
|
*/
|
||||||
public function get_timer_html() {
|
public function get_timer_html() {
|
||||||
return '<div id="quiz-timer">' . get_string('timeleft', 'quiz') .
|
return '<div id="quiz-timer">' . get_string('timeleft', 'quiz') .
|
||||||
' <span id="quiz-time-left"></span></div>';
|
' <span id="quiz-time-left"></span></div>';
|
||||||
|
@ -702,17 +788,34 @@ class quiz_attempt extends quiz {
|
||||||
$this->quiz, $options);
|
$this->quiz, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the sending of the notification emails at the end of this attempt.
|
||||||
|
*/
|
||||||
public function quiz_send_notification_emails() {
|
public function quiz_send_notification_emails() {
|
||||||
quiz_send_notification_emails($this->course, $this->quiz, $this->attempt,
|
quiz_send_notification_emails($this->course, $this->quiz, $this->attempt,
|
||||||
$this->context, $this->cm);
|
$this->context, $this->cm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_navigation_panel($panelclass, $page) {
|
/**
|
||||||
$panel = new $panelclass($this, $this->get_review_options(), $page);
|
* Get the navigation panel object for this attempt.
|
||||||
|
*
|
||||||
|
* @param $panelclass The type of panel, quiz_attempt_nav_panel or quiz_review_nav_panel
|
||||||
|
* @param $page the current page number.
|
||||||
|
* @param $showall whether we are showing the whole quiz on one page. (Used by review.php)
|
||||||
|
* @return quiz_nav_panel_base the requested object.
|
||||||
|
*/
|
||||||
|
public function get_navigation_panel($panelclass, $page, $showall = false) {
|
||||||
|
$panel = new $panelclass($this, $this->get_review_options(), $page, $showall);
|
||||||
return $panel->get_contents();
|
return $panel->get_contents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List of all this user's attempts for people who can see reports.
|
/**
|
||||||
|
* Given a URL containing attempt={this attempt id}, return an array of variant URLs
|
||||||
|
* @param $url a URL.
|
||||||
|
* @return string HTML fragment. Comma-separated list of links to the other
|
||||||
|
* attempts with the attempt number as the link text. The curent attempt is
|
||||||
|
* included but is not a link.
|
||||||
|
*/
|
||||||
public function links_to_other_attempts($url) {
|
public function links_to_other_attempts($url) {
|
||||||
$search = '/\battempt=' . $this->attempt->id . '\b/';
|
$search = '/\battempt=' . $this->attempt->id . '\b/';
|
||||||
$attempts = quiz_get_user_attempts($this->quiz->id, $this->attempt->userid, 'all');
|
$attempts = quiz_get_user_attempts($this->quiz->id, $this->attempt->userid, 'all');
|
||||||
|
@ -732,10 +835,19 @@ class quiz_attempt extends quiz {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods for processing manual comments ==============================================
|
// Methods for processing manual comments ==============================================
|
||||||
// I am not sure it is a good idea to have update methods here - this class is only
|
/**
|
||||||
// about getting data out of the question engine, and helping to display it, apart from
|
* Process a manual comment for a question in this attempt.
|
||||||
// this.
|
* @param $questionid
|
||||||
|
* @param integer $questionid the question id
|
||||||
|
* @param string $comment the new comment from the teacher.
|
||||||
|
* @param mixed $grade the grade the teacher assigned, or '' to not change the grade.
|
||||||
|
* @return mixed true on success, a string error message if a problem is detected
|
||||||
|
* (for example score out of range).
|
||||||
|
*/
|
||||||
public function process_comment($questionid, $comment, $grade) {
|
public function process_comment($questionid, $comment, $grade) {
|
||||||
|
// I am not sure it is a good idea to have update methods here - this
|
||||||
|
// class is only about getting data out of the question engine, and
|
||||||
|
// helping to display it, apart from this.
|
||||||
$this->ensure_question_loaded($questionid);
|
$this->ensure_question_loaded($questionid);
|
||||||
$this->ensure_state_loaded($questionid);
|
$this->ensure_state_loaded($questionid);
|
||||||
$state = $this->states[$questionid];
|
$state = $this->states[$questionid];
|
||||||
|
@ -755,6 +867,11 @@ class quiz_attempt extends quiz {
|
||||||
return $error;
|
return $error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the fields of the comment form for questions in this attempt.
|
||||||
|
* @param $questionid a question id.
|
||||||
|
* @param $prefix Prefix to add to all field names.
|
||||||
|
*/
|
||||||
public function question_print_comment_fields($questionid, $prefix) {
|
public function question_print_comment_fields($questionid, $prefix) {
|
||||||
global $DB;
|
global $DB;
|
||||||
|
|
||||||
|
@ -772,7 +889,10 @@ class quiz_attempt extends quiz {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private methods =====================================================================
|
// Private methods =====================================================================
|
||||||
// Check that the state of a particular question is loaded, and if not throw an exception.
|
/**
|
||||||
|
* Check that the state of a particular question is loaded, and if not throw an exception.
|
||||||
|
* @param integer $id a question id.
|
||||||
|
*/
|
||||||
private function ensure_state_loaded($id) {
|
private function ensure_state_loaded($id) {
|
||||||
if (!array_key_exists($id, $this->states) || isset($this->states[$id]->_partiallyloaded)) {
|
if (!array_key_exists($id, $this->states) || isset($this->states[$id]->_partiallyloaded)) {
|
||||||
throw new moodle_quiz_exception($this, 'statenotloaded', $id);
|
throw new moodle_quiz_exception($this, 'statenotloaded', $id);
|
||||||
|
@ -788,16 +908,23 @@ class quiz_attempt extends quiz {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enter description here...
|
* Get a URL for a particular question on a particular page of the quiz.
|
||||||
|
* Used by {@link attempt_url()} and {@link review_url()}.
|
||||||
*
|
*
|
||||||
* @param unknown_type $questionid the id of a particular question on the page to jump to.
|
* @param string $script. Used in the URL like /mod/quiz/$script.php
|
||||||
* @param integer $page -1 to look up the page number from the questionid, otherwise the page number to use.
|
* @param integer $questionid the id of a particular question on the page to jump to. 0 to just use the $page parameter.
|
||||||
* @param boolean $showall
|
* @param integer $page -1 to look up the page number from the questionid, otherwise the page number to go to.
|
||||||
* @return string bit to add to the end of a URL.
|
* @param boolean $showall if true, return a URL with showall=1, and not page number
|
||||||
|
* @param integer $thispage the page we are currently on. Links to questoins on this
|
||||||
|
* page will just be a fragment #q123. -1 to disable this.
|
||||||
|
* @return The requested URL.
|
||||||
*/
|
*/
|
||||||
private function page_and_question_fragment($questionid, $page, $showall = false) {
|
protected function page_and_question_url($script, $questionid, $page, $showall, $thispage) {
|
||||||
|
global $CFG;
|
||||||
|
|
||||||
|
// Fix up $page
|
||||||
if ($page == -1) {
|
if ($page == -1) {
|
||||||
if ($questionid) {
|
if ($questionid && !$showall) {
|
||||||
$page = $this->questions[$questionid]->_page;
|
$page = $this->questions[$questionid]->_page;
|
||||||
} else {
|
} else {
|
||||||
$page = 0;
|
$page = 0;
|
||||||
|
@ -806,28 +933,40 @@ class quiz_attempt extends quiz {
|
||||||
if ($showall) {
|
if ($showall) {
|
||||||
$page = 0;
|
$page = 0;
|
||||||
}
|
}
|
||||||
$fragment = '';
|
|
||||||
|
// Work out the correct start to the URL.
|
||||||
|
if ($thispage == $page) {
|
||||||
|
$url = '';
|
||||||
|
} else {
|
||||||
|
$url = $CFG->wwwroot . '/mod/quiz/' . $script . '.php?attempt=' . $this->attempt->id;
|
||||||
|
if ($showall) {
|
||||||
|
$url .= '&showall=1';
|
||||||
|
} else if ($page > 0) {
|
||||||
|
$url .= '&page=' . $page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a fragment to scroll down ot the question.
|
||||||
if ($questionid) {
|
if ($questionid) {
|
||||||
if ($questionid == reset($this->pagequestionids[$page])) {
|
if ($questionid == reset($this->pagequestionids[$page])) {
|
||||||
// First question on page, go to top.
|
// First question on page, go to top.
|
||||||
$fragment = '#';
|
$url .= '#';
|
||||||
} else {
|
} else {
|
||||||
$fragment = '#q' . $questionid;
|
$url .= '#q' . $questionid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$param = '';
|
|
||||||
if ($showall) {
|
return $url;
|
||||||
$param = '&showall=1';
|
|
||||||
} else if ($page > 0) {
|
|
||||||
$param = '&page=' . $page;
|
|
||||||
}
|
|
||||||
return $param . $fragment;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A PHP Iterator for conviniently looping over the questions in a quiz. The keys are the question
|
* A PHP Iterator for conviniently looping over the questions in a quiz. The keys are the question
|
||||||
* numbers (with 'i' for descriptions) and the values are the question objects.
|
* numbers (with 'i' for descriptions) and the values are the question objects.
|
||||||
|
*
|
||||||
|
* @copyright 2008 Tim Hunt
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
* @since Moodle 2.0
|
||||||
*/
|
*/
|
||||||
class quiz_attempt_question_iterator implements Iterator {
|
class quiz_attempt_question_iterator implements Iterator {
|
||||||
private $attemptobj; // Reference to the quiz_attempt object we provide access to.
|
private $attemptobj; // Reference to the quiz_attempt object we provide access to.
|
||||||
|
@ -882,38 +1021,52 @@ class quiz_attempt_question_iterator implements Iterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the navigation panel, and builds a {@link block_contents} to allow
|
||||||
|
* it to be output.
|
||||||
|
*
|
||||||
|
* @copyright 2008 Tim Hunt
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
* @since Moodle 2.0
|
||||||
|
*/
|
||||||
abstract class quiz_nav_panel_base {
|
abstract class quiz_nav_panel_base {
|
||||||
protected $attemptobj;
|
protected $attemptobj;
|
||||||
protected $options;
|
protected $options;
|
||||||
protected $page;
|
protected $page;
|
||||||
|
protected $showall;
|
||||||
|
|
||||||
protected function __construct(quiz_attempt $attemptobj, $options, $page) {
|
public function __construct(quiz_attempt $attemptobj, $options, $page, $showall) {
|
||||||
$this->attemptobj = $attemptobj;
|
$this->attemptobj = $attemptobj;
|
||||||
$this->options = $options;
|
$this->options = $options;
|
||||||
$this->page = $page;
|
$this->page = $page;
|
||||||
|
$this->showall = $showall;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function get_question_buttons() {
|
protected function get_question_buttons() {
|
||||||
global $PAGE;
|
|
||||||
$html = '<div class="qn_buttons">' . "\n";
|
$html = '<div class="qn_buttons">' . "\n";
|
||||||
foreach ($this->attemptobj->get_question_iterator() as $number => $question) {
|
foreach ($this->attemptobj->get_question_iterator() as $number => $question) {
|
||||||
$html .= $this->get_question_button($number, $question) . "\n";
|
$html .= $this->get_question_button($number, $question) . "\n";
|
||||||
$PAGE->requires->js_function_call('quiz_init_nav_button',
|
|
||||||
array($this->get_button_id($question), $question->id));
|
|
||||||
}
|
}
|
||||||
$html .= "</div>\n";
|
$html .= "</div>\n";
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function get_button_id($question) {
|
protected function get_question_button($number, $question) {
|
||||||
// The id to put on the button element in the HTML.
|
$strstate = get_string($this->attemptobj->get_question_status($question->id), 'quiz');
|
||||||
return 'quiznavbutton' . $question->id;
|
return '<a href="' . $this->get_question_url($question) .
|
||||||
|
'" class="qnbutton ' . $this->get_question_state_classes($question) .
|
||||||
|
'" id="quiznavbutton' . $question->id . '" title="' . $strstate . '">' .
|
||||||
|
$number . ' <span class="accesshide"> (' . $strstate . ')</span></a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected function get_question_button($number, $question);
|
protected function get_before_button_bits() {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
abstract protected function get_end_bits();
|
abstract protected function get_end_bits();
|
||||||
|
|
||||||
|
abstract protected function get_question_url($question);
|
||||||
|
|
||||||
protected function get_user_picture() {
|
protected function get_user_picture() {
|
||||||
global $DB;
|
global $DB;
|
||||||
$user = $DB->get_record('user', array('id' => $this->attemptobj->get_userid()));
|
$user = $DB->get_record('user', array('id' => $this->attemptobj->get_userid()));
|
||||||
|
@ -930,7 +1083,7 @@ abstract class quiz_nav_panel_base {
|
||||||
$classes = $this->attemptobj->get_question_status($question->id);
|
$classes = $this->attemptobj->get_question_status($question->id);
|
||||||
|
|
||||||
// Plus a marker for the current page.
|
// Plus a marker for the current page.
|
||||||
if ($question->_page == $this->page) {
|
if ($this->showall || $question->_page == $this->page) {
|
||||||
$classes .= ' thispage';
|
$classes .= ' thispage';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,10 +1095,14 @@ abstract class quiz_nav_panel_base {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_contents() {
|
public function get_contents() {
|
||||||
|
global $PAGE;
|
||||||
|
$PAGE->requires->js_function_call('quiz_init_nav_flags');
|
||||||
|
|
||||||
$content = '';
|
$content = '';
|
||||||
if ($this->attemptobj->get_quiz()->showuserpicture) {
|
if ($this->attemptobj->get_quiz()->showuserpicture) {
|
||||||
$content .= $this->get_user_picture() . "\n";
|
$content .= $this->get_user_picture() . "\n";
|
||||||
}
|
}
|
||||||
|
$content .= $this->get_before_button_bits();
|
||||||
$content .= $this->get_question_buttons() . "\n";
|
$content .= $this->get_question_buttons() . "\n";
|
||||||
$content .= '<div class="othernav">' . "\n" . $this->get_end_bits() . "\n</div>\n";
|
$content .= '<div class="othernav">' . "\n" . $this->get_end_bits() . "\n</div>\n";
|
||||||
|
|
||||||
|
@ -957,49 +1114,54 @@ abstract class quiz_nav_panel_base {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialisation of {@link quiz_nav_panel_base} for the attempt quiz page.
|
||||||
|
*
|
||||||
|
* @copyright 2008 Tim Hunt
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
* @since Moodle 2.0
|
||||||
|
*/
|
||||||
class quiz_attempt_nav_panel extends quiz_nav_panel_base {
|
class quiz_attempt_nav_panel extends quiz_nav_panel_base {
|
||||||
public function __construct(quiz_attempt $attemptobj, $options, $page) {
|
protected function get_question_url($question) {
|
||||||
parent::__construct($attemptobj, $options, $page);
|
return $this->attemptobj->attempt_url($question->id, -1, $this->page);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function get_question_button($number, $question) {
|
protected function get_before_button_bits() {
|
||||||
$questionsonpage = $this->attemptobj->get_question_ids($question->_page);
|
return '<div id="quiznojswarning">' . get_string('navnojswarning', 'quiz') . "</div>\n";
|
||||||
$onclick = '';
|
|
||||||
if ($question->id != reset($questionsonpage)) {
|
|
||||||
$onclick = ' onclick="form.action = form.action + \'#q' . $question->id .
|
|
||||||
'\'; return true;"';
|
|
||||||
}
|
|
||||||
return '<input type="submit" name="gotopage' . $question->_page .
|
|
||||||
'" value="' . $number . '" class="qnbutton ' .
|
|
||||||
$this->get_question_state_classes($question) . '" id="' .
|
|
||||||
$this->get_button_id($question) . '" ' . $onclick . '/>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function get_end_bits() {
|
protected function get_end_bits() {
|
||||||
|
global $PAGE;
|
||||||
$output = '';
|
$output = '';
|
||||||
$output .= '<input type="submit" name="gotosummary" value="' .
|
$output .= '<a href="' . $this->attemptobj->summary_url() . '" class="endtestlink">' . get_string('endtest', 'quiz') . '</a>';
|
||||||
get_string('endtest', 'quiz') . '" class="endtestlink" />';
|
|
||||||
$output .= $this->attemptobj->get_timer_html();
|
$output .= $this->attemptobj->get_timer_html();
|
||||||
|
$output .= $PAGE->requires->js_function_call('quiz_init_attempt_nav')->now();
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialisation of {@link quiz_nav_panel_base} for the review quiz page.
|
||||||
|
*
|
||||||
|
* @copyright 2008 Tim Hunt
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
* @since Moodle 2.0
|
||||||
|
*/
|
||||||
class quiz_review_nav_panel extends quiz_nav_panel_base {
|
class quiz_review_nav_panel extends quiz_nav_panel_base {
|
||||||
public function __construct(quiz_attempt $attemptobj, $options, $page) {
|
protected function get_question_url($question) {
|
||||||
parent::__construct($attemptobj, $options, $page);
|
return $this->attemptobj->review_url($question->id, -1, $this->showall, $this->page);
|
||||||
}
|
|
||||||
|
|
||||||
protected function get_question_button($number, $question) {
|
|
||||||
$strstate = get_string($this->attemptobj->get_question_status($question->id), 'quiz');
|
|
||||||
return '<a href="' . $this->attemptobj->review_url($question->id) .
|
|
||||||
'" class="qnbutton ' . $this->get_question_state_classes($question) . '" id="' .
|
|
||||||
$this->get_button_id($question) . '" title="' . $strstate . '">' . $number . '<span class="accesshide">(' . $strstate . '</span></a>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function get_end_bits() {
|
protected function get_end_bits() {
|
||||||
|
$html = '';
|
||||||
|
if ($this->attemptobj->get_num_pages() > 1) {
|
||||||
|
if ($this->showall) {
|
||||||
|
$html = '<a href="' . $this->attemptobj->review_url(0, 0, false) . '">' . get_string('showeachpage', 'quiz') . '</a>';
|
||||||
|
} else {
|
||||||
|
$html = '<a href="' . $this->attemptobj->review_url(0, 0, true) . '">' . get_string('showall', 'quiz') . '</a>';
|
||||||
|
}
|
||||||
|
}
|
||||||
$accessmanager = $this->attemptobj->get_access_manager(time());
|
$accessmanager = $this->attemptobj->get_access_manager(time());
|
||||||
$html = '<a href="' . $this->attemptobj->review_url(0, 0, true) . '">' .
|
|
||||||
get_string('showall', 'quiz') . '</a>';
|
|
||||||
$html .= $accessmanager->print_finish_review_link($this->attemptobj->is_preview_user(), true);
|
$html .= $accessmanager->print_finish_review_link($this->attemptobj->is_preview_user(), true);
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,23 +29,6 @@ $timeup = optional_param('timeup', 0, PARAM_BOOL); // True if form was submitted
|
||||||
|
|
||||||
$attemptobj = new quiz_attempt($attemptid);
|
$attemptobj = new quiz_attempt($attemptid);
|
||||||
|
|
||||||
/// Because IE is buggy (see http://www.peterbe.com/plog/button-tag-in-IE) we cannot
|
|
||||||
/// do the quiz navigation buttons as <button type="submit" name="page" value="N">Caption</button>.
|
|
||||||
/// Instead we have to do them as <input type="submit" name="gotopageN" value="Caption"/> -
|
|
||||||
/// at lest that seemed like the least horrible work-around to me. Therefore, we need to
|
|
||||||
/// intercept gotopageN parameters here, and adjust $pgae accordingly.
|
|
||||||
if (optional_param('gotosummary', false, PARAM_BOOL)) {
|
|
||||||
$nextpage = -1;
|
|
||||||
} else {
|
|
||||||
$numpagesinquiz = $attemptobj->get_num_pages();
|
|
||||||
for ($i = 0; $i < $numpagesinquiz; $i++) {
|
|
||||||
if (optional_param('gotopage' . $i, false, PARAM_BOOL)) {
|
|
||||||
$nextpage = $i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set $nexturl now. It will be updated if a particular question was sumbitted in
|
/// Set $nexturl now. It will be updated if a particular question was sumbitted in
|
||||||
/// adaptive mode.
|
/// adaptive mode.
|
||||||
if ($nextpage == -1) {
|
if ($nextpage == -1) {
|
||||||
|
@ -163,8 +146,9 @@ if (!$finishattempt) {
|
||||||
|
|
||||||
/// We have been asked to finish attempt, so do that //////////////////////
|
/// We have been asked to finish attempt, so do that //////////////////////
|
||||||
|
|
||||||
/// Load the states of questions we have not done anything with, and reload the
|
/// Now load the state of every question, reloading the ones we messed around
|
||||||
/// ones we changed above.
|
/// with above.
|
||||||
|
$attemptobj->preload_question_states();
|
||||||
$attemptobj->load_question_states();
|
$attemptobj->load_question_states();
|
||||||
|
|
||||||
/// Move each question to the closed state.
|
/// Move each question to the closed state.
|
||||||
|
|
|
@ -148,11 +148,54 @@ quiz_timer = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialise a button on the navigation panel.
|
// Set up synchronisation between question flags and the corresponding button in the nav panel.
|
||||||
function quiz_init_nav_button(buttonid, questionid) {
|
function quiz_init_nav_flags() {
|
||||||
// Arrange to be notified if the flagged state changes.
|
var navblock = document.getElementById('quiznavigation');
|
||||||
var button = document.getElementById(buttonid);
|
var buttons = YAHOO.util.Dom.getElementsByClassName('qnbutton', 'a', navblock);
|
||||||
button.stateupdater = new quiz_nav_updater(button, questionid);
|
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) {
|
function quiz_nav_updater(element, questionid) {
|
||||||
|
|
|
@ -72,12 +72,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Arrange for the navigation to be displayed.
|
/// Arrange for the navigation to be displayed.
|
||||||
$navbc = $attemptobj->get_navigation_panel('quiz_review_nav_panel', $page);
|
$navbc = $attemptobj->get_navigation_panel('quiz_review_nav_panel', $page, $showall);
|
||||||
$firstregion = reset($PAGE->blocks->get_regions());
|
$firstregion = reset($PAGE->blocks->get_regions());
|
||||||
$PAGE->blocks->add_pretend_block($navbc, $firstregion);
|
$PAGE->blocks->add_pretend_block($navbc, $firstregion);
|
||||||
|
|
||||||
/// Print the page header
|
/// Print the page header
|
||||||
$PAGE->requires->js('mod/quiz/quiz.js');
|
|
||||||
$headtags = $attemptobj->get_html_head_contributions($page);
|
$headtags = $attemptobj->get_html_head_contributions($page);
|
||||||
if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
|
if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
|
||||||
$accessmanager->setup_secure_page($attemptobj->get_course()->shortname.': '.format_string($attemptobj->get_quiz_name()), $headtags);
|
$accessmanager->setup_secure_page($attemptobj->get_course()->shortname.': '.format_string($attemptobj->get_quiz_name()), $headtags);
|
||||||
|
@ -236,7 +235,7 @@
|
||||||
if ($lastpage) {
|
if ($lastpage) {
|
||||||
$accessmanager->print_finish_review_link($attemptobj->is_preview_user());
|
$accessmanager->print_finish_review_link($attemptobj->is_preview_user());
|
||||||
} else {
|
} else {
|
||||||
link_arrow_right(get_string('next'), s($attemptobj->review_url(0, $page + 1)));
|
echo link_arrow_right(get_string('next'), s($attemptobj->review_url(0, $page + 1)));
|
||||||
}
|
}
|
||||||
echo "</div>";
|
echo "</div>";
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ if ($attemptobj->is_preview_user()) {
|
||||||
print_heading($title);
|
print_heading($title);
|
||||||
|
|
||||||
/// Prepare the summary table header
|
/// Prepare the summary table header
|
||||||
$table->class = 'generaltable quizsummaryofattempt';
|
$table->class = 'generaltable quizsummaryofattempt boxaligncenter';
|
||||||
$table->head = array(get_string('question', 'quiz'), get_string('status', 'quiz'));
|
$table->head = array(get_string('question', 'quiz'), get_string('status', 'quiz'));
|
||||||
$table->align = array('left', 'left');
|
$table->align = array('left', 'left');
|
||||||
$table->size = array('', '');
|
$table->size = array('', '');
|
||||||
|
|
|
@ -1174,7 +1174,9 @@ table.quizreviewsummary td.cell {
|
||||||
#quiznavigation .qnbutton.incorrect {
|
#quiznavigation .qnbutton.incorrect {
|
||||||
background-color: #fcc;
|
background-color: #fcc;
|
||||||
}
|
}
|
||||||
|
#quiznojswarning {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
#mod-quiz-report .dubious{
|
#mod-quiz-report .dubious{
|
||||||
background-color: #fcc;
|
background-color: #fcc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4377,8 +4377,12 @@ body.jsenabled .jshidewhenenabled {
|
||||||
height: 16px;
|
height: 16px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
#mod-quiz-attempt #quiz-timer {
|
#mod-quiz-attempt #quiz-timer,
|
||||||
display: none;
|
#mod-quiz-summary #quiz-timer {
|
||||||
|
display: none; /* Revealed by JavaScript if applicable */
|
||||||
|
}
|
||||||
|
#mod-quiz-summary #quiz-timer {
|
||||||
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
#mod-quiz-attempt #quiz-time-left {
|
#mod-quiz-attempt #quiz-time-left {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -4612,13 +4616,20 @@ table.quizreviewsummary td.cell {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
#quiznavigation .othernav {
|
#quiznavigation .othernav {
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
#quiznavigation .othernav a,
|
#quiznavigation .othernav a,
|
||||||
#quiznavigation .othernav input {
|
#quiznavigation .othernav input {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0.5em 0;
|
margin: 0.5em 0;
|
||||||
}
|
}
|
||||||
|
#quiznojswarning {
|
||||||
|
font-size: 0.7em;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
.jsenabled #quiznojswarning {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.mod-quiz div.tabtree a span img.iconsmall {
|
.mod-quiz div.tabtree a span img.iconsmall {
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue