mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 00:46:50 +02:00
MDL-16263 A way for students to flag/bookmark, particular questions during a quiz attempt for later review.
This is an initial implementation that is now at a working state, but with a few things left to do. It seemed like a good idea to commit it before leaving work on Friday night.
This commit is contained in:
parent
57f43d239a
commit
62e76c6766
18 changed files with 340 additions and 29 deletions
|
@ -68,10 +68,13 @@
|
|||
$quiz->review = $CFG->quiz_review;
|
||||
require_login($courseid, false);
|
||||
$quiz->course = $courseid;
|
||||
$context = get_context_instance(CONTEXT_COURSE, $courseid);
|
||||
} else if (!$quiz = $DB->get_record('quiz', array('id' => $quizid))) {
|
||||
print_error('invalidquizid', 'quiz', '', $quizid);
|
||||
} else {
|
||||
require_login($quiz->course, false, get_coursemodule_from_instance('quiz', $quizid, $quiz->course));
|
||||
$cm = get_coursemodule_from_instance('quiz', $quizid, $quiz->course);
|
||||
require_login($quiz->course, false, $cm);
|
||||
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -187,7 +190,7 @@
|
|||
}
|
||||
|
||||
// TODO: should not use quiz-specific function here
|
||||
$options = quiz_get_renderoptions($quiz->review, $curstate);
|
||||
$options = quiz_get_renderoptions($quiz, $attempt, $context, $curstate);
|
||||
|
||||
// Fill in the correct responses (unless the question is in readonly mode)
|
||||
if ($fillcorrect && !$options->readonly) {
|
||||
|
|
38
question/qengine.js
Normal file
38
question/qengine.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
// This script, and the YUI libraries that it needs, are inluded by
|
||||
// the require_js calls in get_html_head_contributions in lib/questionlib.php.
|
||||
|
||||
question_flag_changer = {
|
||||
init_flag: function(checkboxid, postdata) {
|
||||
var checkbox = document.getElementById(checkboxid);
|
||||
checkbox.ajaxpostdata = postdata;
|
||||
checkbox.className += ' jsworking';
|
||||
question_flag_changer.update_image(checkbox);
|
||||
YAHOO.util.Event.addListener(checkbox, 'change', this.checkbox_state_change);
|
||||
YAHOO.util.Event.addListener(checkbox, 'focus', 'blur()');
|
||||
},
|
||||
|
||||
checkbox_state_change: function(e) {
|
||||
var checkbox = e.target ? e.target : e.srcElement;
|
||||
question_flag_changer.update_image(checkbox);
|
||||
var postdata = checkbox.ajaxpostdata
|
||||
if (checkbox.checked) {
|
||||
postdata += '&newstate=1'
|
||||
} else {
|
||||
postdata += '&newstate=0'
|
||||
}
|
||||
YAHOO.util.Connect.asyncRequest('POST', qengine_config.wwwroot + '/question/toggleflag.php', null, postdata);
|
||||
},
|
||||
|
||||
update_image: function(checkbox) {
|
||||
var img = document.getElementById(checkbox.id + 'img');
|
||||
if (checkbox.checked) {
|
||||
img.src = qengine_config.pixpath + '/i/flagged.png';
|
||||
img.alt = qengine_config.flaggedalt;
|
||||
img.title = qengine_config.unflagtooltip;
|
||||
} else {
|
||||
img.src = qengine_config.pixpath + '/i/unflagged.png';
|
||||
img.alt = qengine_config.unflaggedalt;
|
||||
img.title = qengine_config.flagtooltip;
|
||||
}
|
||||
}
|
||||
};
|
48
question/toggleflag.php
Normal file
48
question/toggleflag.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php // $Id$
|
||||
/**
|
||||
* Used by ajax calls to toggle the flagged state of a question in an attempt.
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
* @package questionbank
|
||||
*/
|
||||
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/questionlib.php');
|
||||
|
||||
// Parameters
|
||||
$sessionid = required_param('qsid', PARAM_INT);
|
||||
$attemptid = required_param('aid', PARAM_INT);
|
||||
$questionid = required_param('qid', PARAM_INT);
|
||||
$newstate = required_param('newstate', PARAM_BOOL);
|
||||
$checksum = required_param('checksum', PARAM_ALPHANUM);
|
||||
|
||||
// Check user is logged in.
|
||||
require_login();
|
||||
|
||||
// Check the sesskey.
|
||||
if (!confirm_sesskey()) {
|
||||
echo 'sesskey failure';
|
||||
}
|
||||
|
||||
// Check the checksum - it is very hard to know who a question session belongs
|
||||
// to, so we require that checksum parameter is matches an md5 hash of the
|
||||
// three ids and the users username. Since we are only updating a flag, that
|
||||
// probably makes it sufficiently difficult for malicious users to toggle
|
||||
// other users flags.
|
||||
if ($checksum != md5($attemptid . "_" . $USER->secret . "_" . $questionid . "_" . $sessionid)) {
|
||||
echo 'checksum failure';
|
||||
}
|
||||
|
||||
// Check that the requested session really exists
|
||||
$questionsession = $DB->get_record('question_sessions', array('id' => $sessionid,
|
||||
'attemptid' => $attemptid, 'questionid' => $questionid));
|
||||
if (!$questionsession) {
|
||||
echo 'invalid ids';
|
||||
}
|
||||
|
||||
// Now change state
|
||||
if (!question_update_flag($sessionid, $newstate)) {
|
||||
echo 'update failed';
|
||||
}
|
||||
|
||||
echo 'OK';
|
||||
?>
|
|
@ -13,7 +13,8 @@
|
|||
<div class="grade">
|
||||
<?php echo get_string('marks', 'quiz').': '.$grade; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php }
|
||||
$this->print_question_flag($question, $state, $options->flags); ?>
|
||||
</div>
|
||||
<div class="content">
|
||||
<?php $this->print_question_formulation_and_controls($question, $state, $cmoptions, $options);
|
||||
|
|
|
@ -879,7 +879,69 @@ class default_questiontype {
|
|||
include "$CFG->dirroot/question/type/question.html";
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Render the question flag, assuming $flagsoption allows it. You will probably
|
||||
* never need to override this method.
|
||||
*
|
||||
* @param object $question the question
|
||||
* @param object $state its current state
|
||||
* @param integer $flagsoption the option that says whether flags should be displayed.
|
||||
*/
|
||||
protected function print_question_flag($question, $state, $flagsoption) {
|
||||
global $CFG;
|
||||
switch ($flagsoption) {
|
||||
case QUESTION_FLAGSSHOWN:
|
||||
$flagcontent = $this->get_question_flag_tag($state->flagged);
|
||||
break;
|
||||
case QUESTION_FLAGSEDITABLE:
|
||||
$id = $question->name_prefix . '_flagged';
|
||||
if ($state->flagged) {
|
||||
$checked = 'checked="checked" ';
|
||||
} else {
|
||||
$checked = '';
|
||||
}
|
||||
$qsid = $state->questionsessionid;
|
||||
$aid = $state->attempt;
|
||||
$qid = $state->question;
|
||||
$checksum = question_get_toggleflag_checksum($aid, $qid, $qsid);
|
||||
$postdata = "qsid=$qsid&aid=$aid&qid=$qid&checksum=$checksum&sesskey=" . sesskey();
|
||||
$flagcontent = '<input type="checkbox" id="' . $id . '" name="' . $id .
|
||||
'" value="1" ' . $checked . ' />' .
|
||||
'<label for="' . $id . '">' . $this->get_question_flag_tag(
|
||||
$state->flagged, $id . 'img') . '</label>' .
|
||||
"\n" . '<script type="text/javascript">question_flag_changer.init_flag(' .
|
||||
"'$id', '$postdata');</script>";
|
||||
break;
|
||||
default:
|
||||
$flagcontent = '';
|
||||
}
|
||||
if ($flagcontent) {
|
||||
echo '<div class="questionflag">' . $flagcontent . "</div>\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out the actual img tag needed for the flag
|
||||
*
|
||||
* @param boolean $flagged whether the question is currently flagged.
|
||||
* @param string $id an id to be added as an attribute to the img (optional).
|
||||
* @return string the img tag.
|
||||
*/
|
||||
protected function get_question_flag_tag($flagged, $id = '') {
|
||||
global $CFG;
|
||||
if ($id) {
|
||||
$id = 'id="' . $id . '" ';
|
||||
}
|
||||
if ($flagged) {
|
||||
$img = 'flagged.png';
|
||||
} else {
|
||||
$img = 'unflagged.png';
|
||||
}
|
||||
return '<img ' . $id . 'src="' . $CFG->pixpath . '/i/' . $img .
|
||||
'" alt="' . get_string('flagthisquestion', 'question') . '" />';
|
||||
}
|
||||
|
||||
/**
|
||||
* Print history of responses
|
||||
*
|
||||
* Used by print_question()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue