MDL-79863 qtype_ordering: qtype/ordering increase padding of draggable elements to allow easier dropping in first and last positions

This commit is contained in:
Gordon Bateson 2015-11-15 10:12:39 +09:00 committed by Mathew May
parent ca0a5210be
commit 072c95122b
10 changed files with 326 additions and 84 deletions

View File

@ -50,7 +50,7 @@ class backup_qtype_ordering_plugin extends backup_qtype_plugin {
$this->add_question_question_answers($pluginwrapper);
// Now create the qtype own structures
$fields = array('selecttype', 'selectcount',
$fields = array('layouttype', 'selecttype', 'selectcount',
'correctfeedback', 'correctfeedbackformat',
'incorrectfeedback', 'incorrectfeedbackformat',
'partiallycorrectfeedback', 'partiallycorrectfeedbackformat');

View File

@ -4,8 +4,9 @@
<TABLE NAME="qtype_ordering_options" COMMENT="Options for ordering questions">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="questionid"/>
<FIELD NAME="questionid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="selecttype"/>
<FIELD NAME="selecttype" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="questionid" NEXT="selectcount"/>
<FIELD NAME="questionid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="layouttype"/>
<FIELD NAME="layouttype" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="questionid" NEXT="selecttype"/>
<FIELD NAME="selecttype" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="layouttype" NEXT="selectcount"/>
<FIELD NAME="selectcount" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="selecttype" NEXT="correctfeedback"/>
<FIELD NAME="correctfeedback" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="selectcount" NEXT="correctfeedbackformat"/>
<FIELD NAME="correctfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="correctfeedback" NEXT="incorrectfeedback"/>

View File

@ -149,6 +149,23 @@ function xmldb_qtype_ordering_upgrade($oldversion) {
upgrade_plugin_savepoint(true, $newversion, 'qtype', 'ordering');
}
$newversion = 2015110725;
if ($oldversion < $newversion) {
$table = new xmldb_table('qtype_ordering_options');
$fields = array(
new xmldb_field('layouttype', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, 0, 'questionid'),
new xmldb_field('selecttype', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, 0, 'layouttype')
);
foreach ($fields as $field) {
if ($dbman->field_exists($table, $field)) {
$dbman->change_field_type($table, $field);
} else {
$dbman->add_field($table, $field);
}
}
upgrade_plugin_savepoint(true, $newversion, 'qtype', 'ordering');
}
return true;
}

View File

@ -41,6 +41,13 @@ class qtype_ordering_edit_form extends question_edit_form {
const NUM_ANS_START = 6;
const NUM_ANS_ADD = 2;
// this functionality is currently disabled
// because it is not fully functional
protected $use_editor_for_answers = false;
/**
* unique name for this question type
*/
public function qtype() {
return 'ordering';
}
@ -55,6 +62,17 @@ class qtype_ordering_edit_form extends question_edit_form {
// cache this plugins name
$plugin = 'qtype_ordering';
// layouttype
$name = 'layouttype';
$label = get_string($name, $plugin);
$options = array(
0 => get_string('vertical', $plugin),
1 => get_string('horizontal', $plugin)
);
$mform->addElement('select', $name, $label, $options);
$mform->addHelpButton($name, $name, $plugin);
$mform->setDefault($name, 0);
// selecttype
$name = 'selecttype';
$label = get_string($name, $plugin);
@ -80,16 +98,24 @@ class qtype_ordering_edit_form extends question_edit_form {
$mform->setDefault($name, 0);
// answers (=items)
// get_per_answer_fields()
// add_per_answer_fields()
$elements = array();
$options = array();
$name = 'answerheader';
$label = get_string($name, $plugin);
$elements[] =& $mform->createElement('header', $name, $label);
$elements[] = $mform->createElement('header', $name, $label);
$options[$name] = array('expanded' => true);
$name = 'answer';
$label = get_string($name, $plugin);
$options = array('rows' => self::NUM_ANS_ROWS, 'cols' => self::NUM_ANS_COLS);
$elements[] =& $mform->createElement('textarea', $name, $label, $options);
if ($this->use_editor_for_answers) {
$elements[] = $mform->createElement('editor', $name, $label, $this->get_editor_attributes(), $this->get_editor_options());
} else {
$elements[] = $mform->createElement('textarea', $name, $label, array('rows' => self::NUM_ANS_ROWS, 'cols' => self::NUM_ANS_COLS));
}
$options[$name] = array('type' => PARAM_RAW);
if (empty($this->question->options)){
$start = 0;
@ -99,14 +125,40 @@ class qtype_ordering_edit_form extends question_edit_form {
if ($start < self::NUM_ANS_START) {
$start = self::NUM_ANS_START;
}
$options = array('answerheader' => array('expanded' => true));
$buttontext = get_string('addmoreanswers', $plugin, self::NUM_ANS_ADD);
$this->repeat_elements($elements, $start, $options, 'countanswers', 'addanswers', self::NUM_ANS_ADD, $buttontext);
// feedback
$this->add_ordering_feedback_fields();
$this->add_ordering_feedback_fields(true);
// interactive
$this->add_ordering_interactive_settings(true, true);
}
/**
* get_editor_attributes
*/
protected function get_editor_attributes() {
return array(
'rows' => self::NUM_ANS_ROWS,
'cols' => self::NUM_ANS_COLS
);
}
/**
* get_editor_options
*/
protected function get_editor_options() {
return array(
'context' => $this->context,
'maxfiles' => EDITOR_UNLIMITED_FILES,
'noclean' => true
);
}
/**
* data_preprocessing
*/
public function data_preprocessing($question) {
$question = parent::data_preprocessing($question);
@ -118,17 +170,57 @@ class qtype_ordering_edit_form extends question_edit_form {
// answers and fractions
$question->answer = array();
$question->fraction = array();
if (isset($question->options->answers)) {
$i = 0;
foreach ($question->options->answers as $answer) {
if (trim($answer->answer)=='') {
continue; // skip empty answers
}
$question->answer[$i] = $answer->answer;
if ($this->use_editor_for_answers) {
$draftid = file_get_submitted_draft_itemid("answer[$i]");
if (isset($answer->id)) {
$itemid = $answer->id;
} else {
$itemid = null;
}
if (isset($answer->answer)) {
$text = $answer->answer;
} else {
$text = '';
}
if (isset($answer->answerformat)) {
$format = $answer->answerformat;
} else {
$format = FORMAT_MOODLE;
}
$text = file_prepare_draft_area($draftid, $this->context->id, 'qtype_ordering',
'answer', $itemid, $this->editoroptions, $text);
$question->answer[$i] = array('text' => $text,
'format' => $format,
'itemid' => $draftid);
} else {
$question->answer[$i]= $answer->answer;
}
$question->fraction[$i] = ($i + 1);
$i++;
}
}
// layouttype
if (isset($question->options->layouttype)) {
$question->layouttype = $question->options->layouttype;
} else {
$question->layouttype = 0;
}
// selecttype
@ -154,6 +246,9 @@ class qtype_ordering_edit_form extends question_edit_form {
$answercount = 0;
foreach ($data['answer'] as $answer){
if ($this->use_editor_for_answers) {
$answer = $answer['text'];
}
if (trim($answer)=='') {
continue; // skip empty answer
}
@ -168,11 +263,10 @@ class qtype_ordering_edit_form extends question_edit_form {
return $errors;
}
protected function add_ordering_feedback_fields($withshownumpartscorrect = false) {
protected function add_ordering_feedback_fields($shownumpartscorrect = false) {
if (method_exists($this, 'add_combined_feedback_fields')) {
// Moodle >= 2.1
$this->add_combined_feedback_fields($withshownumpartscorrect);
$this->add_combined_feedback_fields($shownumpartscorrect);
} else {
// Moodle 2.0
$mform = $this->_form;
@ -185,10 +279,17 @@ class qtype_ordering_edit_form extends question_edit_form {
}
}
protected function data_preprocessing_ordering_feedback($question, $withshownumcorrect = false) {
protected function add_ordering_interactive_settings($clearwrong=false, $shownumpartscorrect=false) {
if (method_exists($this, 'add_interactive_settings')) {
// Moodle >= 2.1
$this->add_interactive_settings($clearwrong, $shownumpartscorrect);
}
}
protected function data_preprocessing_ordering_feedback($question, $shownumcorrect=false) {
if (method_exists($this, 'data_preprocessing_combined_feedback')) {
// Moodle >= 2.1
$question = $this->data_preprocessing_combined_feedback($question, $withshownumcorrect);
$question = $this->data_preprocessing_combined_feedback($question, $shownumcorrect);
} else {
// Moodle 2.0
$names = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback');
@ -208,13 +309,13 @@ class qtype_ordering_edit_form extends question_edit_form {
}
$text = file_prepare_draft_area($draftid, $this->context->id, 'qtype_ordering',
$name, $itemid, $this->fileoptions, $text);
$name, $itemid, $this->editoroptions, $text);
$format = $name.'format';
if (isset($question->options->$format)) {
$format = $question->options->$format;
} else {
$format = 0;
$format = FORMAT_MOODLE;
}
$question->$name = array('text' => $text,

View File

@ -20,6 +20,9 @@ $string['answer'] = 'Item text';
$string['answerheader'] = 'Draggable item {no}';
$string['correctorder'] = 'The correct order for these items is as follows:';
$string['defaultquestionname'] = 'Drag the following items into the correct order.';
$string['horizontal'] = 'Horizontal';
$string['layouttype_help'] = 'Choose whether to display the items vertically or horizontally.';
$string['layouttype'] = 'Layout of items';
$string['noresponsedetails'] = 'Sorry, no details of the response to this question are available.';
$string['notenoughanswers'] = 'Ordering questions must have more than {$a} answers.';
$string['selectall'] = 'Select all items';
@ -29,6 +32,7 @@ $string['selectcount'] = 'Size of subset';
$string['selectrandom'] = 'Select a random subset of items';
$string['selecttype_help'] = 'Choose whether to display all the items or a subset of the items.';
$string['selecttype'] = 'Item selection type';
$string['vertical'] = 'Vertical';
// requred strings for Moodle 2.0
$string['ordering'] = 'Ordering';

View File

@ -54,18 +54,18 @@ class qtype_ordering_question extends question_graded_automatically {
public $currentresponse;
public function start_attempt(question_attempt_step $step, $variant) {
$this->answers = $this->get_ordering_answers();
$this->options = $this->get_ordering_options();
$answers = $this->get_ordering_answers();
$options = $this->get_ordering_options();
$countanswers = count($this->answers);
$countanswers = count($answers);
// sanitize "selecttype"
$selecttype = $this->options->selecttype;
$selecttype = $options->selecttype;
$selecttype = max(0, $selecttype);
$selecttype = min(2, $selecttype);
// sanitize "selectcount"
$selectcount = $this->options->selectcount;
$selectcount = $options->selectcount;
$selectcount = max(3, $selectcount);
$selectcount = min($countanswers, $selectcount);
@ -78,15 +78,15 @@ class qtype_ordering_question extends question_graded_automatically {
// extract answer ids
switch ($selecttype) {
case 0: // all
$answerids = array_keys($this->answers);
$answerids = array_keys($answers);
break;
case 1: // random subset
$answerids = array_rand($this->answers, $selectcount);
$answerids = array_rand($answers, $selectcount);
break;
case 2: // contiguous subset
$answerids = array_keys($this->answers);
$answerids = array_keys($answers);
$offset = mt_rand(0, $countanswers - $selectcount);
$answerids = array_slice($answerids, $offset, $selectcount, true);
break;
@ -101,8 +101,8 @@ class qtype_ordering_question extends question_graded_automatically {
}
public function apply_attempt_state(question_attempt_step $step) {
$this->answers = $this->get_ordering_answers();
$this->options = $this->get_ordering_options();
$answers = $this->get_ordering_answers();
$options = $this->get_ordering_options();
$this->currentresponse = array_filter(explode(',', $step->get_qt_var('_currentresponse')));
$this->correctresponse = array_filter(explode(',', $step->get_qt_var('_correctresponse')));
}
@ -198,6 +198,7 @@ class qtype_ordering_question extends question_graded_automatically {
if (empty($this->options)) {
$this->options = (object)array(
'questionid' => $this->id,
'layouttype' => 0, // vertical
'selecttype' => 0, // all answers
'selectcount' => 0,
'correctfeedback' => '',
@ -232,4 +233,13 @@ class qtype_ordering_question extends question_graded_automatically {
}
return $this->answers;
}
public function get_ordering_layoutclass() {
$options = $this->get_ordering_options();
switch ($options->layouttype) {
case 0: return 'vertical';
case 1: return 'horizontal';
default: return ''; // shouldn't happen !!
}
}
}

View File

@ -40,6 +40,9 @@ if (class_exists('question_type')) {
*/
class qtype_ordering extends question_type {
/** combined feedback fields */
public $feedback_fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback');
/**
* Utility method used by {@link qtype_renderer::head_code()}
* It looks for any of the files script.js or script.php that
@ -136,16 +139,15 @@ class qtype_ordering extends question_type {
// Insert all the new answers
foreach ($question->answer as $i => $text) {
foreach ($question->answer as $i => $answer) {
$answer = (object)array(
'question' => $question->id,
'fraction' => ($i + 1), // start at 1
'answer' => $text,
'answerformat' => FORMAT_MOODLE, // =0
'feedback' => '',
'feedbackformat' => FORMAT_MOODLE, // =0
'question' => $question->id,
'fraction' => ($i + 1), // start at 1
'answer' => (is_array($answer) ? $answer['text'] : $answer),
'answerformat' => (is_array($answer) ? $answer['format'] : FORMAT_MOODLE),
'feedback' => '',
'feedbackformat' => FORMAT_MOODLE,
);
if ($answer->id = array_shift($answerids)) {
if (! $DB->update_record('question_answers', $answer)) {
$result->error = get_string('cannotupdaterecord', 'error', 'question_answers (id='.$answer->id.')');
@ -163,6 +165,7 @@ class qtype_ordering extends question_type {
// create $options for this ordering question
$options = (object)array(
'questionid' => $question->id,
'layouttype' => $question->layouttype,
'selecttype' => $question->selecttype,
'selectcount' => $question->selectcount
);
@ -196,10 +199,9 @@ class qtype_ordering extends question_type {
$options = $this->initialise_combined_feedback($question, $questiondata, $shownumcorrect);
} else {
// Moodle 2.0
$names = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback');
foreach ($names as $name) {
$format = $name.'format';
$question->$name = $questiondata->options->$name;
foreach ($this->feedback_fields as $field) {
$format = $field.'format';
$question->$field = $questiondata->options->$field;
$question->$format = $questiondata->options->$format;
}
if ($shownumcorrect) {
@ -228,11 +230,10 @@ class qtype_ordering extends question_type {
$options = $this->save_combined_feedback_helper($options, $question, $context, $shownumcorrect);
} else {
// Moodle 2.0
$names = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback');
foreach ($names as $name) {
$text = $question->$name;
$format = $name.'format';
$options->$name = $this->import_or_save_files($text, $context, 'qtype_ordering', $name, $question->id);
foreach ($this->feedback_fields as $field) {
$text = $question->$field;
$format = $field.'format';
$options->$field = $this->import_or_save_files($text, $context, 'qtype_ordering', $field, $question->id);
$options->$format = $text['format'];
}
if ($shownumcorrect) {
@ -243,6 +244,9 @@ class qtype_ordering extends question_type {
}
public function is_not_blank($value) {
if (is_array($value)) {
$value = $value['text'];
}
$value = trim($value);
return ($value || $value==='0');
}
@ -281,17 +285,17 @@ class qtype_ordering extends question_type {
* @param string $extra (optional, default=null)
* @todo Finish documenting this function
*/
function import_from_gift($lines, $question, $format, $extra=null) {
public function import_from_gift($lines, $question, $format, $extra=null) {
// convert $lines to a single a string - for preg_match()
$lines = implode(PHP_EOL, $lines);
// extract question info from GIFT file $lines
$search = '/^([^{]*)\s*\{>\s*(\d+)\s*((?:ALL|EXACT|RANDOM|REL|CONTIGUOUS|CONTIG)?)\s*(.*?)\s*\}\s*$/s';
$search = '/^([^{]*)\s*\{>\s*(\d+)\s*((?:ALL|EXACT|RANDOM|REL|CONTIGUOUS|CONTIG)?)\s*((?:HORIZONTAL|HORI|H|1|VERTICAL|VERT|V|0)?)\s*(.*?)\s*\}\s*$/s';
// $1 the question name
// $2 the number of items to be shown
// $3 the extraction type
// $4 the lines of items to be ordered
// $4 the layout type
// $5 the lines of items to be ordered
if (empty($extra) || ! preg_match($search, $lines, $matches)) {
return false; // format not recognized
}
@ -299,7 +303,8 @@ class qtype_ordering extends question_type {
$questionname = trim($matches[1]);
$selectcount = trim($matches[2]);
$selecttype = trim($matches[3]);
$lines = explode(PHP_EOL, $matches[4]);
$layouttype = trim($matches[4]);
$lines = explode(PHP_EOL, $matches[5]);
unset($matches);
$question->qtype = 'ordering';
@ -314,7 +319,7 @@ class qtype_ordering extends question_type {
} else {
$selectcount = min(6, count($lines));
}
$this->set_count_and_type($question, $selectcount, $selecttype);
$this->set_layout_count_type($question, $layouttype, $selectcount, $selecttype);
// remove blank items
$lines = array_map('trim', $lines);
@ -339,16 +344,40 @@ class qtype_ordering extends question_type {
$question->feedbackformat[$i] = FORMAT_MOODLE; // =0
}
// check that the required feedback fields exist
$this->check_ordering_combined_feedback($question);
return $question;
}
/**
* extract_count_and_type
* check_ordering_combined_feedback
*
* @param stdClass $question
* @param stdClass $question (passed by reference)
* @todo Finish documenting this function
*/
function extract_count_and_type($question) {
protected function check_ordering_combined_feedback(&$question) {
foreach ($this->feedback_fields as $field) {
if (empty($question->$field)) {
$question->$field = array('text' => '', 'format' => 0, 'itemid' => 0, 'files' => null);
}
}
}
/**
* extract_layout_count_type
*
* @param stdClass $question
* @todo Finish documenting this function
*/
public function extract_layout_count_type($question) {
switch ($question->options->layouttype) {
case 0: $layout = 'VERTICAL'; break;
case 1: $layout = 'HORIZONTAL'; break;
default: $layout = ''; // shouldn't happen !!
}
switch ($question->options->selecttype) {
case 0: $type = 'ALL'; break; // all items
case 1: $type = 'RANDOM'; break; // random subset
@ -359,7 +388,7 @@ class qtype_ordering extends question_type {
// Note: this used to be (selectcount + 2)
$count = $question->options->selectcount;
return array($count, $type);
return array($layout, $count, $type);
}
/**
@ -370,16 +399,16 @@ class qtype_ordering extends question_type {
* @param string $extra (optional, default=null)
* @todo Finish documenting this function
*/
function export_to_gift($question, $format, $extra=null) {
list($count, $type) = $this->extract_count_and_type($question);
$expout = $question->questiontext.'{>'.$count.' '.$type.' '."\n";
public function export_to_gift($question, $format, $extra=null) {
list($layouttype, $selectcount, $selecttype) = $this->extract_layout_count_type($question);
$output = $question->questiontext.'{>'.$selectcount.' '.
$selecttype.' '.
$layouttype."\n";
foreach ($question->options->answers as $answer) {
$expout .= $answer->answer."\n";
$output .= $answer->answer."\n";
}
$expout .= '}';
return $expout;
$output .= '}';
return $output;
}
/**
@ -390,13 +419,14 @@ class qtype_ordering extends question_type {
* @param string $extra (optional, default=null)
* @todo Finish documenting this function
*/
function export_to_xml($question, qformat_xml $format, $extra=null) {
public function export_to_xml($question, qformat_xml $format, $extra=null) {
list($count, $type) = $this->extract_count_and_type($question);
list($layouttype, $selectcount, $selecttype) = $this->extract_layout_count_type($question);
$output = '';
$output .= " <selecttype>$type</selecttype>\n";
$output .= " <selectcount>$count</selectcount>\n";
$output .= " <layouttype>$layouttype</layouttype>\n";
$output .= " <selecttype>$selecttype</selecttype>\n";
$output .= " <selectcount>$selectcount</selectcount>\n";
foreach($question->options->answers as $answer) {
$output .= ' <answer fraction="'.$answer->fraction.'" '.$format->format($answer->answerformat).">\n";
@ -446,9 +476,10 @@ class qtype_ordering extends question_type {
$selecttype = 'logical';
$selectcount = 'studentsee';
}
$layouttype = $format->getpath($data, array('#', 'layouttype', 0, '#'), 'VERTICAL');
$selecttype = $format->getpath($data, array('#', $selecttype, 0, '#'), 'RANDOM');
$selectcount = $format->getpath($data, array('#', $selectcount, 0, '#'), 6);
$this->set_count_and_type($newquestion, $selectcount, $selecttype);
$this->set_layout_count_type($newquestion, $layouttype, $selectcount, $selecttype);
$newquestion->answer = array();
$newquestion->answerformat = array();
@ -470,6 +501,9 @@ class qtype_ordering extends question_type {
$i++;
}
// check that the required feedback fields exist
$this->check_ordering_combined_feedback($newquestion);
return $newquestion;
}
@ -499,18 +533,45 @@ class qtype_ordering extends question_type {
}
/*
* set_count_and_type
* set_layout_count_type
*
* @param object $question (passed by reference)
* @param integer $layout the layout type
* @param integer $count the number of items to display
* @param integer $type the extraction type
* @param integer $default_type (optional, default=1)
*/
function set_count_and_type(&$question, $count, $type, $default_type=1) {
public function set_layout_count_type(&$question, $layout, $count, $type) {
$default_layout = 0; // horizontal
$default_type = 1; // random
$default_count = 3;
switch (strtoupper($layout)) {
case 'HORIZONTAL':
case 'HORI':
case 'H':
case '1':
$question->layouttype = 1;
break;
case 'VERTICAL':
case 'VERT':
case 'V':
case '0':
$question->layouttype = 0;
break;
default:
$question->layouttype = $default_layout;
}
// set "selectcount" from $count
// this used to be ($count - 2)
$question->selectcount = $count;
if (is_numeric($count)) {
$question->selectcount = intval($count);
} else {
$question->selectcount = $default_count;
}
// set "selecttype" from $type
switch ($type) {

View File

@ -53,9 +53,16 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
// response_id : id_q27_1_response_319
// sortable_id : id_sortable_q27_1_response_319
$response_fieldname = $question->get_response_fieldname();
$response_name = $qa->get_qt_field_name($response_fieldname);
$response_id = 'id_'.preg_replace('/[^a-zA-Z0-9]+/', '_', $response_name);
$sortable_id = 'id_sortable_'.$question->id;
$response_name = $qa->get_qt_field_name($response_fieldname);
$response_id = 'id_'.preg_replace('/[^a-zA-Z0-9]+/', '_', $response_name);
$sortable_id = 'id_sortable_'.$question->id;
$ablock_id = 'id_ablock_'.$question->id;
switch ($question->options->layouttype) {
case 0 : $axis = 'y'; break; // vertical
case 1 : $axis = ''; break; // horizontal
default: $axis = ''; // unknown
}
$result = '';
@ -67,11 +74,13 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
$script .= "if (window.$) {\n"; // $ is an alias for jQuery
$script .= " $(function() {\n";
$script .= " $('#$sortable_id').sortable({\n";
$script .= " axis: '$axis',\n";
$script .= " containment: '#$ablock_id',\n";
$script .= " opacity: 0.6,\n";
$script .= " update: function(event, ui) {\n";
$script .= " var ItemsOrder = $(this).sortable('toArray').toString();\n";
$script .= " $('#$response_id').attr('value', ItemsOrder);\n";
$script .= " },\n";
$script .= " opacity: 0.6\n";
$script .= " }\n";
$script .= " });\n";
$script .= " $('#$sortable_id').disableSelection();\n";
$script .= " });\n";
@ -89,6 +98,9 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
$printeditems = false;
if (count($currentresponse)) {
// set layout class
$layoutclass = $question->get_ordering_layoutclass();
// generate ordering items
foreach ($currentresponse as $position => $answerid) {
if (! array_key_exists($answerid, $question->answers)) {
@ -100,8 +112,8 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
if ($printeditems==false) {
$printeditems = true;
$result .= html_writer::start_tag('div', array('class' => 'ablock'));
$result .= html_writer::start_tag('div', array('class' => 'answer'));
$result .= html_writer::start_tag('div', array('class' => 'ablock', 'id' => $ablock_id));
$result .= html_writer::start_tag('div', array('class' => 'answer ordering'));
$result .= html_writer::start_tag('ul', array('class' => 'sortablelist', 'id' => $sortable_id));
}
@ -118,6 +130,8 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
$class = 'sortableitem';
$img = '';
}
$class = "$class $layoutclass";
// the original "id" revealed the correct order of the answers
// because $answer->fraction holds the correct order number
// $id = 'ordering_item_'.$answerid.'_'.intval($question->answers[$answerid]->fraction);
@ -136,7 +150,8 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
'name' => $response_name,
'id' => $response_id,
'value' => ''));
$result .= html_writer::tag('div', '', array('style' => 'clear:both;'));
// the following DIV is not necessary if we use "overflow: auto;" on the "answer" DIV
//$result .= html_writer::tag('div', '', array('style' => 'clear:both;'));
}
return $result;
@ -165,12 +180,13 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
}
}
if ($showcorrect) {
$layoutclass = $question->get_ordering_layoutclass();
$output .= html_writer::tag('p', get_string('correctorder', 'qtype_ordering'));
$output .= html_writer::start_tag('ol');
$output .= html_writer::start_tag('ol', array('class' => 'correctorder'));
$correctresponse = $question->correctresponse;
foreach ($correctresponse as $position => $answerid) {
$answer = $question->answers[$answerid];
$output .= html_writer::tag('li', $answer->answer);
$output .= html_writer::tag('li', $answer->answer, array('class' => $layoutclass));
}
$output .= html_writer::end_tag('ol');
}

View File

@ -1,3 +1,6 @@
/* ensure container covers the draggable items */
.que.ordering div.answer.ordering { overflow: auto; }
.que.ordering ul.sortablelist {
border : 1px solid #ccc;
float : left;
@ -9,23 +12,37 @@
padding : 4px 4px 0 4px;
width : 80%;
}
.que.ordering ul.sortablelist,
.que.ordering ul.sortablelist li {
-webkit-border-radius: 6px; /* Safari and Chrome */
-moz-border-radius: 6px; /* Firefox */
-o-border-radius: 6px; /* Opera */
border-radius: 6px; /* CSS3 */
}
.que.ordering ul.sortablelist li {
background-color : #eeeeee;
border : 1px solid #cccccc;
border-image : initial;
list-style-type : none;
margin-bottom : 1px;
min-height : 20px;
padding : 8px 2px;
margin : 4px;
padding : 6px 12px;
}
.que.ordering ul.sortablelist li.sortableitem {
position : relative;
cursor : move;
}
.que.ordering ul.sortablelist li.horizontal {
float : left;
}
.que.ordering ul.sortablelist li.vertical {
min-height : 18px;
}
.que.ordering ul.sortablelist li.correctposition {
background-color : #dff0d8; /* light green */
border : 4px solid #99ff66; /* gentle green */
}
.que.ordering ul.sortablelist li.wrongposition {
background-color : #f2dede; /* light red */
border : 4px solid #ff7373; /* gentle red */
}
.que.ordering ul.sortablelist li.correctposition,
@ -33,3 +50,18 @@
margin-bottom : 4px;
margin-top : 4px;
}
.que.ordering div.rightanswer ol.correctorder {
overflow: auto; /* cover the floating LI elements */
}
.que.ordering div.rightanswer ol.correctorder li.horizontal {
float : left;
margin-left : 24px;
margin-right : 24px;
}
.que.ordering div.rightanswer ol.correctorder li.vertical {
}
/* the width restriction can be limited to editors for draggable items
by inserting "fieldset:nth-child(n+4)" before "div.feditor" */
#page-question-type-ordering form.mform fieldset:nth-child(n+4) div.feditor { max-width: 480px; }

View File

@ -30,6 +30,6 @@ defined('MOODLE_INTERNAL') || die();
$plugin->cron = 0;
$plugin->component = 'qtype_ordering';
$plugin->maturity = MATURITY_STABLE; // ALPHA=50, BETA=100, RC=150, STABLE=200
$plugin->release = '2015-07-31 (24)';
$plugin->version = 2015073124;
$plugin->release = '2015-11-15 (30)';
$plugin->version = 2015111530;
$plugin->requires = 2010112400; // Moodle 2.0