diff --git a/lang/en_utf8/quiz.php b/lang/en_utf8/quiz.php
index e3aefdec6c3..cb4c3f01d41 100644
--- a/lang/en_utf8/quiz.php
+++ b/lang/en_utf8/quiz.php
@@ -212,6 +212,7 @@ in course \'$a->coursename\'
You can review this attempt at $a->quizreviewurl.';
$string['emailnotifysubject'] = '$a->studentname has completed quiz $a->quizname';
+$string['endtest'] = 'End test ...';
$string['errorinquestion'] = 'Error in question';
$string['errormissingquestion'] = 'Error: The system is missing the question with id $a';
$string['errornotnumbers'] = 'Error - answers must be numeric';
@@ -467,6 +468,7 @@ $string['quiznotavailable'] = 'The quiz will not be available until $a';
$string['quizopen'] = 'Open the quiz';
$string['quizopens'] = 'Quiz opens';
$string['quizopenedon'] = 'This quiz opened at $a';
+$string['quiznavigation'] = 'Quiz navigation';
$string['quizsettings'] = 'Quiz settings';
$string['quiztimelimit'] = 'Time limit: $a';
$string['quiztimer'] = 'Quiz Timer';
diff --git a/mod/quiz/attempt.php b/mod/quiz/attempt.php
index 4508d5baccd..c521d62a697 100644
--- a/mod/quiz/attempt.php
+++ b/mod/quiz/attempt.php
@@ -36,6 +36,23 @@
$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 Caption .
+/// Instead we have to do them as -
+/// 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)) {
+ $page = -1;
+ } else {
+ $numpagesinquiz = $attemptobj->get_num_pages();
+ for ($i = 0; $i < $numpagesinquiz; $i++) {
+ if (optional_param('gotopage' . $i, false, PARAM_BOOL)) {
+ $page = $i;
+ break;
+ }
+ }
+ }
+
/// We treat automatically closed attempts just like normally closed attempts
if ($timeup) {
$finishattempt = 1;
@@ -275,9 +292,17 @@ if ($page == -1) {
}
echo '
';
-/// Print the navigation panel if required
- // TODO!!!
- quiz_print_navigation_panel($page, $attemptobj->get_num_pages());
+/// Print the navigation panel in a left column.
+ print_container_start();
+ echo '
';
+ $attemptobj->print_navigation_panel('quiz_attempt_nav_panel', $page);
+ echo '
';
+ print_container_end();
+
+/// Start the main column.
+ echo '
';
+ print_container_start();
+ echo skip_main_destination();
/// Print all the questions
foreach ($attemptobj->get_question_ids($page) as $id) {
@@ -285,13 +310,13 @@ if ($page == -1) {
}
/// Print a link to the next page.
- echo "
\n";
+ echo '
';
if ($attemptobj->is_last_page($page)) {
- $nextpage = -1;
+ $nextpage = 'gotosummary';
} else {
- $nextpage = $page + 1;
+ $nextpage = 'gotopage' . ($page + 1);
}
- echo link_arrow_right(get_string('next'), 'javascript:navigate(' . $nextpage . ')');
+ echo ' ';
echo "
";
// Finish the form
@@ -306,6 +331,13 @@ if ($page == -1) {
echo "\n";
+ // End middle column.
+ print_container_end();
+ echo '
';
+
+ echo '
';
+ echo '
';
+
// Finish the page
$accessmanager->show_attempt_timer_if_needed($attemptobj->get_attempt(), time());
if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
diff --git a/mod/quiz/attemptlib.php b/mod/quiz/attemptlib.php
index 490ceba3071..ac5d693f7ab 100644
--- a/mod/quiz/attemptlib.php
+++ b/mod/quiz/attemptlib.php
@@ -165,7 +165,6 @@ class quiz {
* @return object the question object with that id.
*/
public function get_question($id) {
- $this->ensure_question_loaded($id);
return $this->questions[$id];
}
@@ -254,7 +253,7 @@ class quiz {
*/
public function attempt_url($attemptid) {
global $CFG;
- return $CFG->wwwroot . '/mod/quiz/attempt.php?attempt=' . $attemptid . '&page=0';
+ return $CFG->wwwroot . '/mod/quiz/attempt.php?attempt=' . $attemptid;
}
/**
@@ -555,7 +554,7 @@ class quiz_attempt extends quiz {
*/
public function attempt_url($questionid = 0, $page = -1) {
global $CFG;
- return $CFG->wwwroot . '/mod/quiz/attempt.php?attempt=' . $this->attempt->id . '&' .
+ return $CFG->wwwroot . '/mod/quiz/attempt.php?attempt=' . $this->attempt->id .
$this->page_and_question_fragment($questionid, $page);
}
@@ -582,7 +581,7 @@ class quiz_attempt extends quiz {
if (is_null($otherattemptid)) {
$otherattemptid = $this->attempt->id;
}
- return $CFG->wwwroot . '/mod/quiz/review.php?attempt=' . $otherattemptid . '&' .
+ return $CFG->wwwroot . '/mod/quiz/review.php?attempt=' . $otherattemptid .
$this->page_and_question_fragment($questionid, $page, $showall);
}
@@ -614,7 +613,11 @@ class quiz_attempt extends quiz {
quiz_send_notification_emails($this->course, $this->quiz, $this->attempt,
$this->context, $this->cm);
}
-
+
+ public function print_navigation_panel($panelclass, $page) {
+ $panel = new quiz_attempt_nav_panel($this, $this->get_review_options(), $page);
+ $panel->display();
+ }
// Private methods =====================================================================
// Check that the state of a particular question is loaded, and if not throw an exception.
@@ -641,7 +644,7 @@ class quiz_attempt extends quiz {
* @return string bit to add to the end of a URL.
*/
private function page_and_question_fragment($questionid, $page, $showall = false) {
- if ($page = -1) {
+ if ($page == -1) {
if ($questionid) {
$page = $this->questions[$questionid]->_page;
} else {
@@ -657,10 +660,9 @@ class quiz_attempt extends quiz {
}
$param = '';
if ($showall) {
- $param = 'showall=1';
- } else if (/*$page > 1*/ true) {
- // TODO currently needed by the navigate JS, but clean this up later.
- $param = 'page=' . $page;
+ $param = '&showall=1';
+ } else if ($page > 0) {
+ $param = '&page=' . $page;
}
return $param . $fragment;
}
@@ -722,4 +724,86 @@ class quiz_attempt_question_iterator implements Iterator {
return $this->current() !== false;
}
}
+
+abstract class quiz_nav_panel_base {
+ protected $attemptobj;
+ protected $options;
+ protected $page;
+
+ protected function __construct(quiz_attempt $attemptobj, $options, $page) {
+ $this->attemptobj = $attemptobj;
+ $this->options = $options;
+ $this->page = $page;
+ }
+
+ protected function get_question_buttons() {
+ $html = '
';
+ foreach ($this->attemptobj->get_question_iterator() as $number => $question) {
+ $html .= $this->get_question_button($number, $question);
+ }
+ $html .= '
';
+ return $html;
+ }
+
+ abstract protected function get_question_button($number, $question);
+
+ abstract protected function get_end_bits();
+
+ protected function get_question_state($question) {
+ $state = 'todo'; // TODO
+ if ($question->_page == $this->page) {
+ $state .= ' thispage';
+ }
+ return $state;
+ }
+
+ public function display() {
+ $strquiznavigation = get_string('quiznavigation', 'quiz');
+ $content = $this->get_question_buttons() . $this->get_end_bits();
+ print_side_block($strquiznavigation, $content, NULL, NULL, '', array('id' => 'quiznavigation'), $strquiznavigation);
+ }
+}
+
+class quiz_attempt_nav_panel extends quiz_nav_panel_base {
+ public function __construct(quiz_attempt $attemptobj, $options, $page) {
+ parent::__construct($attemptobj, $options, $page);
+ }
+
+ protected function get_question_button($number, $question) {
+ $questionsonpage = $this->attemptobj->get_question_ids($question->_page);
+ $onclick = '';
+ if ($question->id != reset($questionsonpage)) {
+ $onclick = ' onclick="form.action = form.action + \'#q' . $question->id .
+ '\'; return true;"';
+ }
+ return '
';
+ }
+
+ protected function get_end_bits() {
+ return '
';
+ }
+}
+
+class quiz_review_nav_panel extends quiz_nav_panel_base {
+ public function __construct(quiz_attempt $attemptobj, $options, $page) {
+ parent::__construct($attemptobj, $options, $page);
+ }
+
+ protected function get_question_button($number, $question) {
+ return '
' . $number . ' ';
+ }
+
+ protected function get_end_bits() {
+ $html = '
' .
+ get_string('showall', 'quiz') . ' ';
+ $html .= '
' .
+ get_string('finishreview', 'quiz') . ' ';
+ return $html;
+ }
+}
?>
\ No newline at end of file
diff --git a/mod/quiz/quiz.js b/mod/quiz/quiz.js
index 2ced50fc1c9..6201bbffecd 100644
--- a/mod/quiz/quiz.js
+++ b/mod/quiz/quiz.js
@@ -6,16 +6,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
-/* Used by quiz navigation links to force a form submit, and hence save the user's data. */
-function navigate(page) {
- var ourForm = document.getElementById('responseform');
- ourForm.action = ourForm.action.replace(/page=.*/, 'page=' + page);
- if (ourForm.onsubmit) {
- ourForm.onsubmit();
- }
- ourForm.submit();
-}
-
/* 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) {
diff --git a/theme/standard/styles_layout.css b/theme/standard/styles_layout.css
index 6741f441983..5df23df9e05 100644
--- a/theme/standard/styles_layout.css
+++ b/theme/standard/styles_layout.css
@@ -2562,7 +2562,6 @@ body.notes .notesgroup {
text-align: left;
margin: 0 auto 1.8em auto;
border: 1px solid;
- clear: both;
}
.que .info {
float: left;
@@ -3818,14 +3817,21 @@ body#mod-forum-search .introcontent {
#passwordform {
margin: 1em 0;
}
-#mod-quiz-attempt #page {
+#mod-quiz-attempt #middle-column {
text-align: center;
}
#mod-quiz-attempt .pagingbar {
margin: 1.5em auto;
}
-#mod-quiz-attempt #page {
- text-align: center;
+#mod-quiz-attempt #middle-column {
+ margin: 0 0 0 12.5em;
+}
+#mod-quiz-attempt #left-column {
+ width: 11.5em;
+ float: left;
+}
+#mod-quiz-attempt .submitbtns {
+ text-align: left;
}
#mod-quiz-attempt #quiz-timer-outer {
@@ -4048,6 +4054,26 @@ table.quizreviewsummary td.cell {
text-align: center;
margin: 6px 0;
}
+
+#quiznavigation input.qnbutton {
+ border: 1px solid grey;
+ background: white;
+ font-weight: bold;
+ width: 1.5em;
+ height: 1.5em;
+ margin-right: 0.3em;
+ text-align: middle;
+}
+#quiznavigation input.qnbutton:hover {
+ background: silver;
+}
+#quiznavigation .qn_buttons {
+ margin: 0.2em;
+}
+#quiznavigation input.qnbutton.thispage {
+ background: #eee;
+}
+
/***
*** Modules: Resource
***/