mirror of
https://github.com/moodle/moodle.git
synced 2025-03-23 17:10:20 +01:00
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:
parent
ca0a5210be
commit
072c95122b
@ -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');
|
||||
|
@ -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"/>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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';
|
||||
|
@ -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 !!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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');
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user