From a2bb148ae33b1ff47aed65d65f55e25f2a69c009 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 28 Jan 2011 19:07:33 +0000 Subject: [PATCH 001/208] MDL-47494 ddimageortext: work-in-progress converting the ddwtos and gapselect qtypes. --- question/type/ddimageortext/db/install.xml | 23 + question/type/ddimageortext/db/upgrade.php | 83 +++ .../type/ddimageortext/edit_ddwtos_form.php | 69 ++ question/type/ddimageortext/icon.gif | Bin 0 -> 867 bytes .../ddimageortext/lang/en/qtype_ddwtos.php | 13 + question/type/ddimageortext/question.php | 59 ++ question/type/ddimageortext/questiontype.php | 224 ++++++ question/type/ddimageortext/renderer.php | 181 +++++ question/type/ddimageortext/script.js | 562 +++++++++++++++ .../type/ddimageortext/simpletest/helper.php | 97 +++ .../ddimageortext/simpletest/testquestion.php | 246 +++++++ .../simpletest/testquestiontype.php | 470 ++++++++++++ .../simpletest/testwalkthrough.php | 680 ++++++++++++++++++ question/type/ddimageortext/styles.css | 67 ++ question/type/ddimageortext/version.php | 4 + 15 files changed, 2778 insertions(+) create mode 100755 question/type/ddimageortext/db/install.xml create mode 100755 question/type/ddimageortext/db/upgrade.php create mode 100755 question/type/ddimageortext/edit_ddwtos_form.php create mode 100755 question/type/ddimageortext/icon.gif create mode 100755 question/type/ddimageortext/lang/en/qtype_ddwtos.php create mode 100755 question/type/ddimageortext/question.php create mode 100755 question/type/ddimageortext/questiontype.php create mode 100755 question/type/ddimageortext/renderer.php create mode 100755 question/type/ddimageortext/script.js create mode 100755 question/type/ddimageortext/simpletest/helper.php create mode 100755 question/type/ddimageortext/simpletest/testquestion.php create mode 100755 question/type/ddimageortext/simpletest/testquestiontype.php create mode 100755 question/type/ddimageortext/simpletest/testwalkthrough.php create mode 100755 question/type/ddimageortext/styles.css create mode 100755 question/type/ddimageortext/version.php diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml new file mode 100755 index 00000000000..065853d37b1 --- /dev/null +++ b/question/type/ddimageortext/db/install.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/question/type/ddimageortext/db/upgrade.php b/question/type/ddimageortext/db/upgrade.php new file mode 100755 index 00000000000..91d665a1685 --- /dev/null +++ b/question/type/ddimageortext/db/upgrade.php @@ -0,0 +1,83 @@ +question = $ddanswer->questionid; + $answer->answer = addslashes($ddanswer->answer); + $answer->fraction = 1; + + $feedback = new stdClass; + $feedback->draggroup = $ddanswer->draggroup; + $feedback->infinite = $ddanswer->infinite; + $answer->feedback = serialize($feedback); + + if(!insert_record('question_answers', $answer)){ + notify('move_question_ddanswers_to_question_answers(): cannot insert row into question_answer table.'); + return false; + } + } + } + + // Drop table + $result = $result && drop_table($table); + } + + if ($result && $oldversion < 2010042800) { + + /// Rename field correctresponsesfeedback on table question_ddwtos to shownumcorrect + $table = new XMLDBTable('question_ddwtos'); + $field = new XMLDBField('correctresponsesfeedback'); + $field->setAttributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'incorrectfeedback'); + + /// Launch rename field correctresponsesfeedback + $result = $result && rename_field($table, $field, 'shownumcorrect'); + } + + return $result; +} diff --git a/question/type/ddimageortext/edit_ddwtos_form.php b/question/type/ddimageortext/edit_ddwtos_form.php new file mode 100755 index 00000000000..dec87f43e86 --- /dev/null +++ b/question/type/ddimageortext/edit_ddwtos_form.php @@ -0,0 +1,69 @@ +. + + +/** + * Defines the editing form for the drag-and-drop words into sentences question type. + * + * @package qtype_ddwtos + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->dirroot . '/question/type/sddl/edit_form_base.php'); + + +/** + * Drag-and-drop words into sentences editing form definition. + * + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { + + function qtype() { + return 'ddwtos'; + } + + protected function default_values_from_feedback_field($feedback, $key){ + $feedback = unserialize($feedback); + $draggroup = $feedback->draggroup; + $infinite = $feedback->infinite; + + $default_values = array(); + $default_values['choices['.$key.'][draggroup]'] = $draggroup; + $default_values['choices['.$key.'][infinite]'] = $infinite; + return $default_values; + } + + protected function repeated_options(){ + $repeatedoptions = array(); + $repeatedoptions['draggroup']['default'] = '1'; + $repeatedoptions['infinite']['default'] = 0; + return $repeatedoptions; + } + + protected function choice_group(&$mform, $grouparray){ + $options = array(); + for ($i = 1; $i <= 8; $i += 1) { + $options[$i] = $i; + } + $grouparray[] =& $mform->createElement('select', 'draggroup', get_string('group', 'qtype_ddwtos'), $options); + $grouparray[] =& $mform->createElement('checkbox', 'infinite', ' ', get_string('infinite', 'qtype_ddwtos'), null, array('size'=>1, 'class'=>'tweakcss')); + return $grouparray; + } +} diff --git a/question/type/ddimageortext/icon.gif b/question/type/ddimageortext/icon.gif new file mode 100755 index 0000000000000000000000000000000000000000..f900852b7c387ee8fdbd61f26d031376af7966ac GIT binary patch literal 867 zcmZ?wbhEHb6krfw_|Cxa_wV1|zkmPy`Sa`7ub)4E{`m3ZhYug#ym|Bb_3IZeUOa#P z{PE+*4<9~Uy?XV+g$pN7o?KE=Vr6AzW@ct+XsDr~p{}m3q@*M+E-oY_#K*_Sz`*eT z|9>Dk3PwX$HPm=1$P=VpEuqZW<8gNHhqm80(b xSm4OqE2-`F=Ep@v_ij1IFrOJl4^K?jjg9*f@oC|qel5YIniHFsH#IO=0{~))R22XK literal 0 HcmV?d00001 diff --git a/question/type/ddimageortext/lang/en/qtype_ddwtos.php b/question/type/ddimageortext/lang/en/qtype_ddwtos.php new file mode 100755 index 00000000000..34b17378121 --- /dev/null +++ b/question/type/ddimageortext/lang/en/qtype_ddwtos.php @@ -0,0 +1,13 @@ +. + + +/** + * Drag-and-drop words into sentences question definition class. + * + * @package qtype_ddwtos + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); + +/** + * Represents a drag-and-drop words into sentences question. + * + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddwtos_question extends qtype_gapselect_question_base { +//is actually exactly the same. +} + + +/** + * Represents one of the choices (draggable boxes). + * + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddwtos_choice { + public $text; + public $draggroup; + public $isinfinite; + + public function __construct($text, $draggroup = 1, $isinfinite = false) { + $this->text = $text; + $this->draggroup = $draggroup; + $this->isinfinite = $isinfinite; + } + public function choice_group(){ + return $this->draggroup; + } +} diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php new file mode 100755 index 00000000000..b72e89a2414 --- /dev/null +++ b/question/type/ddimageortext/questiontype.php @@ -0,0 +1,224 @@ +. + + +/** + * Question type class for the drag-and-drop words into sentences question type. + * + * @package qtype_ddwtos + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +require_once($CFG->libdir . '/questionlib.php'); +require_once($CFG->dirroot . '/question/engine/lib.php'); +require_once($CFG->dirroot . '/question/format/xml/format.php'); + +require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); + +/** + * The drag-and-drop words into sentences question type class. + * + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddwtos extends qtype_gapselect_base { + protected function feedback_serialization($choice){ + $output = new stdClass; + $output->draggroup = $choice['draggroup']; + $output->infinite = !empty($choice['infinite']); + return serialize($output); + } + + protected function feedback_unserialization($choicedata){ + $options = unserialize($choicedata->feedback); + return new qtype_ddwtos_choice($choicedata->answer, $options->draggroup, $options->infinite); + } + + + protected function feedback_unserialize_as_array($feedback){ + $feedbackobj = unserialize($feedback); + return array('draggroup'=> $feedbackobj->draggroup, 'infinite'=> $feedbackobj->infinite); + } + + protected function choice_group_key(){ + return 'draggroup'; + } + + public function requires_qtypes() { + return array('sddl'); + } + + public function import_from_xml($data, $question, $format, $extra=null) { + if (!isset($data['@']['type']) || $data['@']['type'] != 'ddwtos') { + return false; + } + + $question = $format->import_headers($data); + $question->qtype = 'ddwtos'; + + $question->shuffleanswers = $format->trans_single( + $format->getpath($data, array('#', 'shuffleanswers', 0, '#'), 1)); + + if (!empty($data['#']['dragbox'])) { + // Modern XML format. + $dragboxes = $data['#']['dragbox']; + $question->answer = array(); + $question->draggroup = array(); + $question->infinite = array(); + + foreach ($data['#']['dragbox'] as $dragboxxml) { + $question->choices[] = array( + 'answer' => $format->getpath($dragboxxml, array('#', 'text', 0, '#'), '', true), + 'draggroup' => $format->getpath($dragboxxml, array('#', 'group', 0, '#'), 1), + 'infinite' => array_key_exists('infinite', $dragboxxml['#']), + ); + } + + } else { + // Legacy format containing PHP serialisation. + foreach ($data['#']['answer'] as $answerxml) { + $ans = $format->import_answer($answerxml); + $options = unserialize(stripslashes($ans->feedback)); + $question->choices[] = array( + 'answer' => $ans->answer, + 'draggroup' => $options->draggroup, + 'infinite' => $options->infinite, + ); + } + } + + $format->import_combined_feedback($question, $data, true); + $format->import_hints($question, $data, true); + + return $question; + } + + function export_to_xml($question, $format, $extra = null) { + $output = ''; + + $output .= ' ' . $question->options->shuffleanswers . "\n"; + + $output .= $format->write_combined_feedback($question->options); + + foreach ($question->options->answers as $answer) { + $options = unserialize($answer->feedback); + + $output .= " \n"; + $output .= $format->writetext($answer->answer, 3); + $output .= " {$options->draggroup}\n"; + if ($options->infinite) { + $output .= " \n"; + } + $output .= " \n"; + } + + return $output; + } + + /* + * Backup the data in the question + * + * This is used in question/backuplib.php + */ + public function backup($bf, $preferences, $question, $level = 6) { + $status = true; + $ddwtos = get_records("question_ddwtos", "questionid", $question, "id"); + + //If there are ddwtos + if ($ddwtos) { + //Iterate over each ddwtos + foreach ($ddwtos as $ddws) { + $status = fwrite ($bf,start_tag("DDWORDSSENTENCES",$level,true)); + //Print oumultiresponse contents + fwrite ($bf,full_tag("SHUFFLEANSWERS",$level+1,false,$ddws->shuffleanswers)); + fwrite ($bf,full_tag("CORRECTFEEDBACK",$level+1,false,$ddws->correctfeedback)); + fwrite ($bf,full_tag("PARTIALLYCORRECTFEEDBACK",$level+1,false,$ddws->partiallycorrectfeedback)); + fwrite ($bf,full_tag("INCORRECTFEEDBACK",$level+1,false,$ddws->incorrectfeedback)); + fwrite ($bf,full_tag("SHOWNUMCORRECT",$level+1,false,$ddws->shownumcorrect)); + $status = fwrite ($bf,end_tag("DDWORDSSENTENCES",$level,true)); + } + + //Now print question_answers + $status = question_backup_answers($bf,$preferences,$question); + } + return $status; + } + + /** + * Restores the data in the question (This is used in question/restorelib.php) + * + */ + public function restore($old_question_id,$new_question_id,$info,$restore) { + $status = true; + + //Get the ddwtos array + $ddwtos = $info['#']['DDWORDSSENTENCES']; + + //Iterate over oumultiresponses + for($i = 0; $i < sizeof($ddwtos); $i++) { + $mul_info = $ddwtos[$i]; + + //Now, build the question_ddwtos record structure + $ddwtos = new stdClass; + $ddwtos->questionid = $new_question_id; + $ddwtos->shuffleanswers = isset($mul_info['#']['SHUFFLEANSWERS']['0']['#'])?backup_todb($mul_info['#']['SHUFFLEANSWERS']['0']['#']):''; + if (array_key_exists("CORRECTFEEDBACK", $mul_info['#'])) { + $ddwtos->correctfeedback = backup_todb($mul_info['#']['CORRECTFEEDBACK']['0']['#']); + } else { + $ddwtos->correctfeedback = ''; + } + if (array_key_exists("PARTIALLYCORRECTFEEDBACK", $mul_info['#'])) { + $ddwtos->partiallycorrectfeedback = backup_todb($mul_info['#']['PARTIALLYCORRECTFEEDBACK']['0']['#']); + } else { + $ddwtos->partiallycorrectfeedback = ''; + } + if (array_key_exists("INCORRECTFEEDBACK", $mul_info['#'])) { + $ddwtos->incorrectfeedback = backup_todb($mul_info['#']['INCORRECTFEEDBACK']['0']['#']); + } else { + $ddwtos->incorrectfeedback = ''; + } + if (array_key_exists('SHOWNUMCORRECT', $mul_info['#'])) { + $ddwtos->shownumcorrect = backup_todb($mul_info['#']['SHOWNUMCORRECT']['0']['#']); + } else if (array_key_exists('CORRECTRESPONSESFEEDBACK', $mul_info['#'])) { + $ddwtos->shownumcorrect = backup_todb($mul_info['#']['CORRECTRESPONSESFEEDBACK']['0']['#']); + } else { + $ddwtos->shownumcorrect = 0; + } + + $newid = insert_record ("question_ddwtos",$ddwtos); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + if (!$newid) { + $status = false; + } + } + return $status; + } + +} diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php new file mode 100755 index 00000000000..8f4362fed1b --- /dev/null +++ b/question/type/ddimageortext/renderer.php @@ -0,0 +1,181 @@ +. + + +/** + * Drag-and-drop words into sentences question renderer class. + * + * @package qtype_ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); + + +/** + * Generates the output for drag-and-drop words into sentences questions. + * + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddwtos_renderer extends qtype_elements_embedded_in_question_text_renderer { + + protected function qtext_classname(){ + return 'qtext ddwtos_questionid_for_javascript'; + } + + protected function post_qtext_elements(question_attempt $qa, question_display_options $options){ + $result = ''; + $question = $qa->get_question(); + $dragboxs = ''; + foreach ($question->choices as $group => $choices) { + $dragboxs .= $this->drag_boxes($qa, $group, + $question->get_ordered_choices($group), $options); + } + $result .= html_writer::tag('div', $dragboxs, + array('class' => 'answercontainer')); + // We abuse the clear_wrong method to output the hidden form fields we + // want irrespective of whether we are actually clearing the wrong + // bits of the response. + if (!$options->clearwrong) { + $result .= $this->clear_wrong($qa, false); + } + return $result; + } + + /** + * Modify the contents of a drag/drop box to fix some IE-related problem. + * Unfortunately I don't have more details than that. + * @param string $string the box contents. + * @return string the box contents modified. + */ + protected function dodgy_ie_fix($string) { + return ' ' . $string . ' '; + } + + protected function embedded_element(question_attempt $qa, $place, question_display_options $options) { + $question = $qa->get_question(); + $group = $question->places[$place]; + $boxcontents = $this->dodgy_ie_fix(' '); + + $value = $qa->get_last_qt_var($question->field($place)); + + $attributes = array( + 'id' => $this->box_id($qa, 'p' . $place, $group), + 'class' => 'slot group' . $group + ); + + if ($options->readonly) { + $attributes['class'] .= ' readonly'; + } else { + $attributes['tabindex'] = '0'; + } + + $feedbackimage = ''; + if ($options->correctness) { + $response = $qa->get_last_qt_data(); + $fieldname = $question->field($place); + if (array_key_exists($fieldname, $response)) { + $fraction = (int) ($response[$fieldname] == $question->get_right_choice_for($place)); + $attributes['class'] .= ' ' . $this->feedback_class($fraction); + $feedbackimage = $this->feedback_image($fraction); + } + } + + return html_writer::tag('span', $boxcontents, $attributes) . ' ' . $feedbackimage; + } + + protected function drag_boxes($qa, $group, $choices, question_display_options $options) { + $readonly = ''; + if ($options->readonly) { + $readonly = ' readonly'; + } + + $boxes = ''; + foreach ($choices as $key => $choice) { + //Bug 8632 - long text entry causes bug in drag and drop field in IE + $content = str_replace('-', '‑', $choice->text); + $content = $this->dodgy_ie_fix(str_replace(' ', ' ', $content)); + + $infinite = ''; + if ($choice->isinfinite) { + $infinite = ' infinite'; + } + + $boxes .= html_writer::tag('span', $content, array( + 'id' => $this->box_id($qa, $key, $choice->draggroup), + 'class' => 'player group' . $choice->draggroup . $infinite . $readonly)) . ' '; + } + + return html_writer::nonempty_tag('div', $boxes, array('class' => 'answertext')); + } + + + public function head_code(question_attempt $qa) { + require_js(array('yui_dom-event', 'yui_dragdrop')); + return parent::head_code($qa); + } + + /** + * Actually, this question type abuses this method to always ouptut the + * hidden fields it needs. + */ + public function clear_wrong(question_attempt $qa, $reallyclear = true) { + $question = $qa->get_question(); + $response = $qa->get_last_qt_data(); + + if (!empty($response) && $reallyclear) { + $cleanresponse = $question->clear_wrong_from_response($response); + } else { + $cleanresponse = $response; + } + + $output = ''; + foreach ($question->places as $place => $group) { + $fieldname = $question->field($place); + if (array_key_exists($fieldname, $response)) { + $value = $response[$fieldname]; + } else { + $value = '0'; + } + if (array_key_exists($fieldname, $cleanresponse)) { + $cleanvalue = $cleanresponse[$fieldname]; + } else { + $cleanvalue = '0'; + } + if ($cleanvalue != $value) { + $output .= html_writer::empty_tag('input', array( + 'type' => 'hidden', + 'id' => $this->box_id($qa, 'p' . $place, $group) . '_hidden', + 'value' => s($value))) . + html_writer::empty_tag('input', array( + 'type' => 'hidden', + 'name' => $qa->get_qt_field_name($fieldname), + 'value' => s($cleanvalue))); + } else { + $output .= html_writer::empty_tag('input', array( + 'type' => 'hidden', + 'id' => $this->box_id($qa, 'p' . $place, $group) . '_hidden', + 'name' => $qa->get_qt_field_name($fieldname), + 'value' => s($value))); + } + } + return $output; + } + +} diff --git a/question/type/ddimageortext/script.js b/question/type/ddimageortext/script.js new file mode 100755 index 00000000000..0f0a4807959 --- /dev/null +++ b/question/type/ddimageortext/script.js @@ -0,0 +1,562 @@ +/** + * JavaScript objects, functions as well as usage of some YUI library for + * enabling drag and drop interaction for dran-anddrop words into sentences + * (ddwtos) + * + * @package qtype_ddwtos + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +//global variables +var ddwtos_currentzindex = 10; + + +/* + * The way it seems to be, if there are more than one of this type of question + * in a quiz, then this file is shared between them. Therefore it has to cope + * with ALL the questions of this type on the page. + */ +(function() { + + // start of App object SHARED BY ALL QUESTIONS OF THIS TYPE IN THE QUIZ ///// + YAHOO.example.DDApp = { + init : function() { + var questionspans = YAHOO.util.Dom.getElementsByClassName("ddwtos_questionid_for_javascript"); + + // we need this loop in case of more than one of this qtype on one page + for (var i = 0; i < questionspans.length; i++) { + // The Questions object should now contain a QuestionDataObject + //object for each question of this type in the quiz. + Questions[questionspans[i].id] = new QuestionDataObject(questionspans[i].id); + } + + // populate the arrays "slots" and "players" for each question + var tempSlots = YAHOO.util.Dom.getElementsByClassName("slot", "span"); + var tempPlayers = YAHOO.util.Dom.getElementsByClassName("player", "span"); + + //ie7 zoom message + ie7_zoom_message(); + + for (var i = 0; i < tempSlots.length; i++) { + var name_prefix = tempSlots[i].id.split("_")[0] + "_"; + var q = Questions[name_prefix]; + var g = getGroupForThis(tempSlots[i].id); + + var ddtarget = new YAHOO.util.DDTarget(tempSlots[i].id, g); + q.tempSlots.push(tempSlots[i]); + q.slots.push(ddtarget); + } + + for (var i = 0; i < tempPlayers.length; i++) { + var name_prefix = tempPlayers[i].id.split("_")[0] + "_"; + var q = Questions[name_prefix]; + var g = getGroupForThis(tempPlayers[i].id); + var ddplayer = new YAHOO.example.DDPlayer(tempPlayers[i].id, g); + q.tempPlayers.push(tempPlayers[i]); + q.players.push(ddplayer); + } + + for (var i = 0; i < questionspans.length; i++) { + var q = Questions[questionspans[i].id]; + var groupwidth = getWidthForAllGroups(q.tempPlayers); + for (var j = 0; j < q.tempSlots.length; j++) { + var g = getGroupForThis(q.tempSlots[j].id); + setWidth(q.tempSlots[j], groupwidth[g]); + } + for (var j = 0; j < q.tempPlayers.length; j++) { + var g = getGroupForThis(q.tempPlayers[j].id); + setWidth(q.tempPlayers[j], groupwidth[g]); + } + + // set responses for all slots + setResponsesForAllSlots(q.tempSlots, q.tempPlayers); + } + } + }; + // end of App object //////////////////////////////////////////////////////// + + // beginning of Player object (the draggable item) ////////////////////////// + YAHOO.example.DDPlayer = function(id, sGroup, config) { + YAHOO.example.DDPlayer.superclass.constructor.apply(this, arguments); + this.initPlayer(id, sGroup, config); + }; + + YAHOO.extend(YAHOO.example.DDPlayer, YAHOO.util.DD, { + TYPE :"DDPlayer", + + initPlayer : function(id, sGroup, config) { + this.isTarget = false; + this.currentPos = YAHOO.util.Dom.getXY(this.getEl()); + + }, + + //Abstract method called after a drag/drop object is clicked and the drag or mousedown time thresholds have beeen met. + startDrag : function(x, y) { + YAHOO.util.Dom.setStyle(this.getEl(), "zIndex", ddwtos_currentzindex++); + YAHOO.util.Dom.removeClass(this.getEl(), 'placed'); + + if (is_infinite(this.getEl()) && !this.slot){ + var currentplayer = this.getEl().id.replace(/_clone[0-9]+$/, ''); + var ddplayer = YAHOO.util.DragDropMgr.getDDById(currentplayer); + clone_player(ddplayer); + } + + if (this.slot) { // dragging starts from a slot + var hiddenElement = document.getElementById(this.slot.getEl().id + '_hidden'); + hiddenElement.value = ''; + this.slot.player = null; + this.slot = null; + } + }, + + //Abstract method called when this item is dropped on another DragDrop obj + onDragDrop : function(e, id) { + // get the drag and drop object that was targeted + var target = YAHOO.util.DragDropMgr.getDDById(id); + var dragged = this.getEl(); + + //get the question-prefix of slot and player and check whether they belong to the same question + var slotprefix = target.id.split("_")[0] + "_"; + var playerprefix = dragged.id.split("_")[0] + "_"; + if (slotprefix != playerprefix){ + var p = YAHOO.util.DragDropMgr.getDDById(dragged.id); + p.startDrag(0,0); + p.onInvalidDrop(null); + return; + } + + show_element(this.getEl()); + + if (target.player) { // there's a player already there + var oldplayer = target.player; + oldplayer.startDrag(0,0); + oldplayer.onInvalidDrop(null); + } + + YAHOO.util.DragDropMgr.moveToEl(dragged, target.getEl()); + this.slot = target; + target.player = this; + YAHOO.util.Dom.setXY(target.player.getEl(), YAHOO.util.Dom.getXY(target.getEl())); + YAHOO.util.Dom.addClass(this.getEl(), 'placed'); + if (YAHOO.util.Dom.hasClass(target.getEl(), 'readonly')) { + if (YAHOO.util.Dom.hasClass(target.getEl(), 'correct')) { + YAHOO.util.Dom.addClass(this.getEl(), 'correct'); + } else if (YAHOO.util.Dom.hasClass(target.getEl(), 'incorrect')) { + YAHOO.util.Dom.addClass(this.getEl(), 'incorrect'); + } + } + + // set value + var hiddenElement = document.getElementById(id + '_hidden'); + hiddenElement.value = this.getEl().id.split("_")[1]; + }, + + //Abstract method called when this item is dropped on an area with no drop target + onInvalidDrop : function(e) { + YAHOO.util.Dom.setXY(this.getEl(), YAHOO.util.Dom.getXY(this.originalplayer.getEl())); + YAHOO.util.Dom.removeClass(this.getEl(), 'placed'); + } + }); + // end of Player object (the draggable item) //////////////////////////////// + + YAHOO.util.Event.onDOMReady(YAHOO.example.DDApp.init, YAHOO.example.DDApp, true); + + + // Objects/////////////////////////////////////////////////////////////////// + var Questions = new Object(); + + function QuestionDataObject(theid) { + this.id = theid; + this.tempSlots = []; + this.tempPlayers = []; + this.slots = []; + this.players = []; + } + + // template for the slot object + function SlotObject(id, group, currentvalue, values, callback) { + this.id = id; + this.group = group; + this.currentvalue = currentvalue; + this.values = values; + this.callback = callback; + } + // End of Objects /////////////////////////////////////////////////////////// + + // functions //////////////////////////////////////////////////////////////// + + function clone_player(p) { + var el = p.getEl(); + var newNode = document.createElement('div'); + newNode.className = el.className; + newNode.innerHTML = el.innerHTML; + + if (!p.clones) { + p.clones = []; + } + newNode.id = el.id + '_clone' + p.clones.length; // _clone0 for first + + newNode.style.position = 'absolute'; + + var region = YAHOO.util.Dom.getRegion(el); + var height = region.bottom - region.top; + var width = region.right - region.left; + + // -2 is becuase get_region includes the border, but style.width/height does not. + newNode.style.height = (height - 2) + "px"; + newNode.style.width = (width - 2) + "px"; + + el.parentNode.parentNode.appendChild(newNode); + YAHOO.util.Dom.setXY(newNode, YAHOO.util.Dom.getXY(el)); + + var g = getGroupForThis(el.id); + var p2 = new YAHOO.example.DDPlayer(newNode.id, g); + p2.originalplayer = p; + + hide_element(el); + show_element(newNode); + + if (is_readonly(newNode)) { + p2.lock(); + } + + p.clones[p.clones.length] = p2; + return p2; + } + + function clone_players(players){ + for (var i = 0; i < players.length; i++) { + var p = YAHOO.util.DragDropMgr.getDDById(players[i].id); + clone_player(p); + } + } + + function is_readonly(el){ + return YAHOO.util.Dom.hasClass(el, 'readonly'); + } + + function is_infinite(el){ + return YAHOO.util.Dom.hasClass(el, 'infinite'); + } + + function show_element(el){ + YAHOO.util.Dom.setStyle(el, 'visibility', 'visible'); + } + + function hide_element(el){ + YAHOO.util.Dom.setStyle(el, 'visibility', 'hidden'); + } + + function list_of_slots_and_players(slots, players) { + this.slots = slots; + this.players = players; + } + + function set_xy_after_resize(e, slotsandplayerobj){ + setTimeout(function() { + set_xy_after_resize_actual(e,slotsandplayerobj); + }, 0); + } + + function set_xy_after_resize_actual(e, slotsandplayerobj) { + var slots = slotsandplayerobj.slots; + var players = slotsandplayerobj.players; + for (var i = 0; i < players.length; i++) { + var original = YAHOO.util.DragDropMgr.getDDById(players[i].id); + for (var index in original.clones) { + var c = original.clones[index]; + if (c.slot) { + //player is in slot + YAHOO.util.Dom.setXY(c.getEl(), YAHOO.util.Dom.getXY(c.slot.getEl())); + } else { + //player is not in slot + YAHOO.util.Dom.setXY(c.getEl(), YAHOO.util.Dom.getXY(c.originalplayer.getEl())); + } + } + } + } + + function setResponsesForAllSlots(slots, players) { + clone_players(players); + + for (var i = 0; i < slots.length; i++) { + var slot = slots[i]; + + var hiddenElement = document.getElementById(slot.id + '_hidden'); + if (!hiddenElement) continue; + + // get group + var group = getGroupForThis(slot.id); + + // get array of values + var values = getValuesForThisSlot(slot.id, players); + + var currentvalue = parseInt(hiddenElement.value); + // if slot is occupied + if (currentvalue) { + // Find player + var idbits = hiddenElement.id.split('_'); + idbits[1] = currentvalue; + idbits.pop(); + var newid = idbits.join('_'); + var original = YAHOO.util.DragDropMgr.getDDById(newid); + var index = original.clones.length - 1; + original.clones[index].startDrag(0, 0); + original.clones[index].onDragDrop(null, slot.id); + } + YAHOO.util.Event.addListener(slot.id, "focus", setFocus); + YAHOO.util.Event.addListener(slot.id, "blur", setBlur); + + YAHOO.util.Event.addListener(slot.id, "mousedown", mouseDown); + + var myobj = new SlotObject(slot.id, group, currentvalue, values, funCallKeys); + + // event keydown + YAHOO.util.Event.addListener(slot.id, "keydown", funCallKeys, myobj); + } + + //resize + var listofslotsandplayers = new list_of_slots_and_players(slots, players); + YAHOO.util.Event.addListener(window, "resize", set_xy_after_resize, listofslotsandplayers); + YAHOO.util.Event.addListener(window, "load", set_xy_after_resize, listofslotsandplayers); + } + + function getValuesForThisSlot(slotid, players) { + var gslot = getGroupForThis(slotid); + var values = []; + var j = 0; + for (var i = 0; i < players.length; i++) { + var pElement = players[i]; + var gplayer = getGroupForThis(pElement.id); + + // from the same group + if (gslot == gplayer) { + values[j++] = pElement.id; + } + } + return values; + } + + function getWidthForAllGroups(allplayers) { + var widtharray = []; + for (var i = 0; i < allplayers.length; i++) { + var g = getGroupForThis(allplayers[i].id); + var width = getWidthForThisElement(allplayers[i]); + if (!widtharray[g] || width > widtharray[g]) { + widtharray[g] = width; + } + } + return widtharray; + } + + function getWidthForThisGroup(allplayers, group) { + var tempwidth = 0; + for (var i = 0; i < allplayers.length; i++) { + var g = getGroupForThis(allplayers[i].id); + if (group != g) { + continue; + } + var width = getWidthForThisElement(allplayers[i]); + if (width > tempwidth) { + tempwidth = width; + } + } + return tempwidth; + } + + function getWidthForThisElement(el) { + var region = YAHOO.util.Dom.getRegion(el); + return region.right - region.left; + } + + function setWidth(el, gwidth) { + var width = getWidthForThisElement(el); + var remainder = (gwidth - width) + 10; + + // IE8 does not rewrap lines when the padding changes, so this + // change uses different layout for that browser version only. + if (navigator.appVersion.indexOf('MSIE 8') != -1) { + var region = YAHOO.util.Dom.getRegion(el); + var height = region.bottom - region.top; + el.style.display = 'inline-block'; + el.style.width = gwidth + 'px'; + el.style.height = height + 'px'; + return; + } + + YAHOO.util.Dom.setStyle(el, 'padding-right', Math.floor((remainder + 1) / 2) + 'px'); + YAHOO.util.Dom.setStyle(el, 'padding-left', Math.floor(remainder / 2) + 'px'); + } + + function funCallKeys(e, slotobj) { + //disable the key access when readonly + if (is_readonly(document.getElementById(slotobj.values[0]))) { + return; + } + + var evt = e || window.event; + var key = evt.keyCode; + + switch (key) { + case 39: // arrow right (forwards) + case 40: // arrow down (forwards) + case 32: // space (forwards) + changeObject(slotobj, 1); + return false; //this has to return false because of IE + + case 37: // arrow left (backwards) + case 38: // arrow up (backwards) + changeObject(slotobj, -1); + return false; //this has to return false because of IE + + case 66: // B (backwards) + case 98: // b (backwards) + case 80: // P (previous) + case 112: // p (previous) + changeObject(slotobj, -1); + break; + + case 13: // cariage return (forwards) + case 70: // F (forwards) + case 102: // f (forwards) + case 78: // N (next) + case 110: // n (next) + changeObject(slotobj, 1); + break; + + case 27: // escape (empty the drop box) + changeObject(slotobj, 0); + default: + return true; + } + return true; + } + + function changeObject(slotobj, direction) { + // Prevent infinite loop if there are no values for this slot + if (slotobj.values.length == 0) { + return; + } + + if (direction == 0) { + call_YUI_startDrag_onInvalidDrop(slotobj); + return; + } + + var hiddenElement = document.getElementById(slotobj.id + '_hidden'); + + // Get current position in values list + var selectedIndex = -1; + for(var i = 0; i < slotobj.values.length; i++) { + if (slotobj.values[i].split("_")[1] == hiddenElement.value) { + selectedIndex = i; + break; + } + } + + var currentIndex = selectedIndex; + while (true) { + // Get new position in values list + selectedIndex += direction; + if (selectedIndex > slotobj.values.length) { + selectedIndex-= slotobj.values.length + 1; + } + if (selectedIndex < 0) { + selectedIndex += slotobj.values.length + 1; + } + + //empty the slot at the beginning or the end of the players list + if (selectedIndex == slotobj.values.length) { + call_YUI_startDrag_onInvalidDrop(slotobj); + return; + } + + // If we loop round back to the current one then there are + // no more options, so stop + if (selectedIndex == currentIndex) { + break; + } + + // Check the item at the new position is not used + var original = YAHOO.util.DragDropMgr.getDDById(slotobj.values[selectedIndex]); + var index = original.clones.length - 1; + if (!original.clones[index].slot) { + // This one is not in a slot so we can use it + original.clones[index].startDrag(0, 0); + original.clones[index].onDragDrop(null, slotobj.id); + break; + } + } + } + + function call_YUI_startDrag_onInvalidDrop(slotobj){ + var target = YAHOO.util.DragDropMgr.getDDById(slotobj.id); + if (!target.player) { + return; + } + var player = target.player; + + // Find player and call YUI methods + player.startDrag(0, 0); + player.onInvalidDrop(null); + } + + function getGroupForThis(str) { + var g = str.split("_")[2]; + return g; + } + + function mouseDown() { + } + + function setFocus() { + YAHOO.util.Dom.addClass(this, 'focussed'); + } + + function setBlur() { + YAHOO.util.Dom.removeClass(this, 'focussed'); + } + + function ie7_zoom_message (){ + var browser = navigator.appVersion; + if (browser.indexOf('MSIE 7') > -1){ + var b = document.body.getBoundingClientRect(); + var magnifactor = (b.right - b.left)/document.body.clientWidth; + if (magnifactor < 0.9 || magnifactor > 1.1){ + + var answers = YAHOO.util.Dom.getElementsByClassName("answercontainer", "div"); + for(var i=0; i. + + +/** + * Test helper class for the drag-and-drop words into sentences question type. + * + * @package qtype_ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddwtos_test_helper { + /** + * @return qtype_ddwtos_question + */ + public static function make_a_ddwtos_question() { + question_bank::load_question_definition_classes('ddwtos'); + $dd = new qtype_ddwtos_question(); + + test_question_maker::initialise_a_question($dd); + + $dd->name = 'Drag-and-drop words into sentences question'; + $dd->questiontext = 'The [[1]] brown [[2]] jumped over the [[3]] dog.'; + $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; + $dd->qtype = question_bank::get_qtype('ddwtos'); + + $dd->shufflechoices = true; + + test_question_maker::set_standard_combined_feedback_fields($dd); + + $dd->choices = array( + 1 => array( + 1 => new qtype_ddwtos_choice('quick', 1), + 2 => new qtype_ddwtos_choice('slow', 1)), + 2 => array( + 1 => new qtype_ddwtos_choice('fox', 2), + 2 => new qtype_ddwtos_choice('dog', 2)), + 3 => array( + 1 => new qtype_ddwtos_choice('lazy', 3), + 2 => new qtype_ddwtos_choice('assiduous', 3)), + ); + + $dd->places = array(1 => 1, 2 => 2, 3 => 3); + $dd->rightchoices = array(1 => 1, 2 => 1, 3 => 1); + $dd->textfragments = array('The ', ' brown ', ' jumped over the ', ' dog.'); + + return $dd; + } + + /** + * @return qtype_ddwtos_question + */ + public static function make_a_maths_ddwtos_question() { + question_bank::load_question_definition_classes('ddwtos'); + $dd = new qtype_ddwtos_question(); + + test_question_maker::initialise_a_question($dd); + + $dd->name = 'Drag-and-drop words into sentences question'; + $dd->questiontext = 'Fill in the operators to make this equation work: ' . + '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3'; + $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; + $dd->qtype = question_bank::get_qtype('ddwtos'); + + $dd->shufflechoices = true; + + test_question_maker::set_standard_combined_feedback_fields($dd); + + $dd->choices = array( + 1 => array( + 1 => new qtype_ddwtos_choice('+', 1, true), + 2 => new qtype_ddwtos_choice('-', 1, true), + 3 => new qtype_ddwtos_choice('*', 1, true), + 4 => new qtype_ddwtos_choice('/', 1, true), + )); + + $dd->places = array(1 => 1, 2 => 1, 3 => 1, 4 => 1); + $dd->rightchoices = array(1 => 1, 2 => 2, 3 => 1, 4 => 2); + $dd->textfragments = array('7 ', ' 11 ', ' 13 ', ' 17 ', ' 19 = 3'); + + return $dd; + } +} diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php new file mode 100755 index 00000000000..db8ae7c9166 --- /dev/null +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -0,0 +1,246 @@ +. + + +/** + * Unit tests for the drag-and-drop words into sentences question definition class. + * + * @package qtype_ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); +require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); + + +/** + * Unit tests for the matching question definition class. + * + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddwtos_question_test extends UnitTestCase { + + public function test_get_question_summary() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $this->assertEqual('The [[1]] brown [[2]] jumped over the [[3]] dog.; [[1]] -> {quick / slow}; [[2]] -> {fox / dog}; [[3]] -> {lazy / assiduous}', + $dd->get_question_summary()); + } + + public function test_get_question_summary_maths() { + $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $this->assertEqual('Fill in the operators to make this equation work: ' . + '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3; [[1]] -> {+ / - / * / /}', + $dd->get_question_summary()); + } + + public function test_summarise_response() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual('{quick} {fox} {lazy}', + $dd->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); + } + + public function test_summarise_response_maths() { + $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual('{+} {-} {+} {-}', + $dd->summarise_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); + } + + public function test_get_random_guess_score() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $this->assertEqual(0.5, $dd->get_random_guess_score()); + } + + public function test_get_random_guess_score_maths() { + $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $this->assertEqual(0.25, $dd->get_random_guess_score()); + } + + public function test_get_right_choice_for() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(1, $dd->get_right_choice_for(1)); + $this->assertEqual(1, $dd->get_right_choice_for(2)); + } + + public function test_get_right_choice_for_maths() { + $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(1, $dd->get_right_choice_for(1)); + $this->assertEqual(2, $dd->get_right_choice_for(2)); + } + + public function test_clear_wrong_from_response() { + $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $initialresponse = array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'); + $this->assertEqual(array('p1' => '1', 'p2' => '0', 'p3' => '1', 'p4' => '0'), + $dd->clear_wrong_from_response($initialresponse)); + } + + public function test_get_num_parts_right() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(array(2, 3), + $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '2'))); + $this->assertEqual(array(3, 3), + $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); + } + + public function test_get_num_parts_right_maths() { + $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(array(2, 4), + $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); + } + + public function test_get_expected_data() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT), + $dd->get_expected_data()); + } + + public function test_get_correct_response() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(array('p1' => '1', 'p2' => '1', 'p3' => '1'), + $dd->get_correct_response()); + } + + public function test_get_correct_response_maths() { + $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'), + $dd->get_correct_response()); + } + + public function test_is_same_response() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->init_first_step(new question_attempt_step()); + + $this->assertTrue($dd->is_same_response( + array(), + array('p1' => '0', 'p2' => '0', 'p3' => '0'))); + + $this->assertFalse($dd->is_same_response( + array(), + array('p1' => '1', 'p2' => '0', 'p3' => '0'))); + + $this->assertFalse($dd->is_same_response( + array('p1' => '0', 'p2' => '0', 'p3' => '0'), + array('p1' => '1', 'p2' => '0', 'p3' => '0'))); + + $this->assertTrue($dd->is_same_response( + array('p1' => '1', 'p2' => '2', 'p3' => '3'), + array('p1' => '1', 'p2' => '2', 'p3' => '3'))); + + $this->assertFalse($dd->is_same_response( + array('p1' => '1', 'p2' => '2', 'p3' => '3'), + array('p1' => '1', 'p2' => '2', 'p3' => '2'))); + } + public function test_is_complete_response() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->init_first_step(new question_attempt_step()); + + $this->assertFalse($dd->is_complete_response(array())); + $this->assertFalse($dd->is_complete_response( + array('p1' => '1', 'p2' => '1', 'p3' => '0'))); + $this->assertFalse($dd->is_complete_response(array('p1' => '1'))); + $this->assertTrue($dd->is_complete_response( + array('p1' => '1', 'p2' => '1', 'p3' => '1'))); + } + + public function test_is_gradable_response() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->init_first_step(new question_attempt_step()); + + $this->assertFalse($dd->is_gradable_response(array())); + $this->assertFalse($dd->is_gradable_response( + array('p1' => '0', 'p2' => '0', 'p3' => '0'))); + $this->assertTrue($dd->is_gradable_response( + array('p1' => '1', 'p2' => '1', 'p3' => '0'))); + $this->assertTrue($dd->is_gradable_response(array('p1' => '1'))); + $this->assertTrue($dd->is_gradable_response( + array('p1' => '1', 'p2' => '1', 'p3' => '1'))); + } + + public function test_grading() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(array(1, question_state::$gradedright), + $dd->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); + $this->assertEqual(array(1/3, question_state::$gradedpartial), + $dd->grade_response(array('p1' => '1'))); + $this->assertEqual(array(0, question_state::$gradedwrong), + $dd->grade_response(array('p1' => '2', 'p2' => '2', 'p3' => '2'))); + } + + public function test_grading_maths() { + $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(array(1, question_state::$gradedright), + $dd->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); + $this->assertEqual(array(0.5, question_state::$gradedpartial), + $dd->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); + $this->assertEqual(array(0, question_state::$gradedwrong), + $dd->grade_response(array('p1' => '0', 'p2' => '1', 'p3' => '2', 'p4' => '1'))); + } + + public function test_classify_response() { + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->shufflechoices = false; + $dd->init_first_step(new question_attempt_step()); + + $this->assertEqual(array( + 1 => new question_classified_response(1, 'quick', 1), + 2 => new question_classified_response(2, 'dog', 0), + 3 => new question_classified_response(1, 'lazy', 1), + ), $dd->classify_response(array('p1' => '1', 'p2' => '2', 'p3' => '1'))); + $this->assertEqual(array( + 1 => question_classified_response::no_response(), + 2 => new question_classified_response(1, 'fox', 1), + 3 => new question_classified_response(2, 'assiduous', 0), + ), $dd->classify_response(array('p1' => '0', 'p2' => '1', 'p3' => '2'))); + } +} diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php new file mode 100755 index 00000000000..0acfa17b174 --- /dev/null +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -0,0 +1,470 @@ +. + + +/** + * Unit tests for the drag-and-drop words into sentences question definition class. + * + * @package qtype_ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); +require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); + + +/** + * Unit tests for the drag-and-drop words into sentences question definition class. + * + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddwtos_test extends UnitTestCase { + /** @var qtype_ddwtos instance of the question type class to test. */ + protected $qtype; + + public function setUp() { + $this->qtype = question_bank::get_qtype('ddwtos');; + } + + public function tearDown() { + $this->qtype = null; + } + + public function assert_same_xml($expectedxml, $xml) { + $this->assertEqual(str_replace("\r\n", "\n", $expectedxml), + str_replace("\r\n", "\n", $xml)); + } + + /** + * @return object the data to construct a question like + * {@link qtype_ddwtos_test_helper::make_a_ddwtos_question()}. + */ + protected function get_test_question_data() { + global $USER; + + $dd = new stdClass; + $dd->id = 0; + $dd->category = 0; + $dd->parent = 0; + $dd->questiontextformat = FORMAT_HTML; + $dd->defaultmark = 1; + $dd->penalty = 0.3333333; + $dd->length = 1; + $dd->stamp = make_unique_id_code(); + $dd->version = make_unique_id_code(); + $dd->hidden = 0; + $dd->timecreated = time(); + $dd->timemodified = time(); + $dd->createdby = $USER->id; + $dd->modifiedby = $USER->id; + + $dd->name = 'Drag-and-drop words into sentences question'; + $dd->questiontext = 'The [[1]] brown [[2]] jumped over the [[3]] dog.'; + $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; + $dd->qtype = 'ddwtos'; + + $dd->options->shuffleanswers = true; + + test_question_maker::set_standard_combined_feedback_fields($dd->options); + + $dd->options->answers = array( + (object) array('answer' => 'quick', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), + (object) array('answer' => 'fox', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), + (object) array('answer' => 'lazy', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), + (object) array('answer' => 'assiduous', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), + (object) array('answer' => 'dog', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), + (object) array('answer' => 'slow', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), + ); + + return $dd; + } + + public function test_name() { + $this->assertEqual($this->qtype->name(), 'ddwtos'); + } + + public function test_can_analyse_responses() { + $this->assertTrue($this->qtype->can_analyse_responses()); + } + + public function test_initialise_question_instance() { + $qdata = $this->get_test_question_data(); + + $expected = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $expected->stamp = $qdata->stamp; + $expected->version = $qdata->version; + + $q = $this->qtype->make_question($qdata); + + $this->assertEqual($expected, $q); + } + + public function test_get_random_guess_score() { + $q = $this->get_test_question_data(); + $this->assertWithinMargin(0.5, $this->qtype->get_random_guess_score($q), 0.0000001); + } + + public function test_get_possible_responses() { + $q = $this->get_test_question_data(); + + $this->assertEqual(array( + 1 => array( + 1 => new question_possible_response('quick', 1), + 2 => new question_possible_response('slow', 0), + null => question_possible_response::no_response()), + 2 => array( + 1 => new question_possible_response('fox', 1), + 2 => new question_possible_response('dog', 0), + null => question_possible_response::no_response()), + 3 => array( + 1 => new question_possible_response('lazy', 1), + 2 => new question_possible_response('assiduous', 0), + null => question_possible_response::no_response()), + ), $this->qtype->get_possible_responses($q)); + } + + public function test_xml_import() { + $xml = ' + + A drag-and-drop question + + + Put these in order: [[1]], [[2]], [[3]]. + + + The answer is Alpha, Beta, Gamma. + + 3 + 0.3333333 + 0 + 1 + + Your answer is correct.

]]>
+
+ + Your answer is partially correct.

]]>
+
+ + Your answer is incorrect.

]]>
+
+ + + Alpha + 1 + + + Beta + 1 + + + Gamma + 1 + + + + Try again. + + + + These are the first three letters of the Greek alphabet. + + + +
'; + $xmldata = xmlize($xml); + + $importer = new qformat_xml(); + $q = $importer->try_importing_using_qtypes( + $xmldata['question'], null, null, 'ddwtos'); + + $expectedq = new stdClass; + $expectedq->qtype = 'ddwtos'; + $expectedq->name = 'A drag-and-drop question'; + $expectedq->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; + $expectedq->questiontextformat = FORMAT_MOODLE; + $expectedq->generalfeedback = 'The answer is Alpha, Beta, Gamma.'; + $expectedq->defaultmark = 3; + $expectedq->length = 1; + $expectedq->penalty = 0.3333333; + + $expectedq->shuffleanswers = 1; + $expectedq->correctfeedback = '

Your answer is correct.

'; + $expectedq->partiallycorrectfeedback = '

Your answer is partially correct.

'; + $expectedq->shownumcorrect = true; + $expectedq->incorrectfeedback = '

Your answer is incorrect.

'; + + $expectedq->choices = array( + array('answer' => 'Alpha', 'draggroup' => 1, 'infinite' => false), + array('answer' => 'Beta', 'draggroup' => 1, 'infinite' => false), + array('answer' => 'Gamma', 'draggroup' => 1, 'infinite' => true), + ); + + $expectedq->hint = array('Try again.', 'These are the first three letters of the Greek alphabet.'); + $expectedq->hintshownumcorrect = array(true, true); + $expectedq->hintclearwrong = array(false, true); + + $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q); + } + + public function test_xml_import_legacy() { + $xml = ' + + QDandD1 Base definition + + + <p>Drag and drop the words from the list below to fill the blank spaces and correctly complete the sentence.</p> <p>At 25°C all aqueous basic solutions have [[1]] ion concentrations less than [[8]]<br />mol litre<sup>-1</sup> and pH values [[9]] than [[6]].</p> <!--DONOTCLEAN--> + + + + <p>At 25 &#xB0;C all aqueous basic solutions have hydrogen ion concentrations less than 10<sup>&#x2212;7</sup> mol litre<sup>&#x2212;1</sup> and pH values greater than 7.</p> <p>See Section 9 of S103 <em class="italic">Discovering Science</em> Block 8.</p> + + 1 + 0.33 + 0 + 0 + false + + 1 + hydrogen + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;} + + + + 0 + positive + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;} + + + + 0 + hydroxide + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;} + + + + 0 + negative + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;} + + + + 0 + 10<sup>7</sup> + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;} + + + + 1 + 7 + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;} + + + + 0 + 1 + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;} + + + + 1 + 10<sup>-7</sup> + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;} + + + + 1 + greater + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;} + + + + 0 + less + + O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;} + + + + Your answer is correct. + + 1 + + Your answer is partially correct. + + + Your answer is incorrect. + + 0 + 0.33 + + 1 + 0 + + You may wish to read Section 9 of <em class="italic">Discovering Science</em> Block 8. + + + + 1 + 1 + + Any incorrect choices will be removed before your final try. + + + '; + $xmldata = xmlize($xml); + + $importer = new qformat_xml(); + $q = $importer->try_importing_using_qtypes( + $xmldata['question'], null, null, 'ddwtos'); + + $expectedq = new stdClass; + $expectedq->qtype = 'ddwtos'; + $expectedq->name = 'QDandD1 Base definition'; + $expectedq->questiontext = '

Drag and drop the words from the list below to fill the blank spaces and correctly complete the sentence.

At 25°C all aqueous basic solutions have [[1]] ion concentrations less than [[8]]
mol litre-1 and pH values [[9]] than [[6]].

'; + $expectedq->questiontextformat = FORMAT_HTML; + $expectedq->generalfeedback = '

At 25 °C all aqueous basic solutions have hydrogen ion concentrations less than 10−7 mol litre−1 and pH values greater than 7.

See Section 9 of S103 Discovering Science Block 8.

'; + $expectedq->defaultmark = 1; + $expectedq->length = 1; + $expectedq->penalty = 0.3333333; + + $expectedq->shuffleanswers = 0; + $expectedq->correctfeedback = 'Your answer is correct.'; + $expectedq->partiallycorrectfeedback = 'Your answer is partially correct.'; + $expectedq->shownumcorrect = true; + $expectedq->incorrectfeedback = 'Your answer is incorrect.'; + + $expectedq->choices = array( + array('answer' => 'hydrogen', 'draggroup' => 1, 'infinite' => false), + array('answer' => 'positive', 'draggroup' => 1, 'infinite' => false), + array('answer' => 'hydroxide', 'draggroup' => 1, 'infinite' => false), + array('answer' => 'negative', 'draggroup' => 1, 'infinite' => false), + array('answer' => '107', 'draggroup' => 2, 'infinite' => false), + array('answer' => '7', 'draggroup' => 2, 'infinite' => false), + array('answer' => '1', 'draggroup' => 2, 'infinite' => false), + array('answer' => '10-7', 'draggroup' => 2, 'infinite' => false), + array('answer' => 'greater', 'draggroup' => 3, 'infinite' => false), + array('answer' => 'less', 'draggroup' => 3, 'infinite' => false), + ); + + $expectedq->hint = array( + 'You may wish to read Section 9 of Discovering Science Block 8.', + 'Any incorrect choices will be removed before your final try.' + ); + $expectedq->hintshownumcorrect = array(true, true); + $expectedq->hintclearwrong = array(false, true); + + $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q); + } + + public function test_xml_export() { + $qdata = new stdClass; + $qdata->id = 123; + $qdata->qtype = 'ddwtos'; + $qdata->name = 'A drag-and-drop question'; + $qdata->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; + $qdata->questiontextformat = FORMAT_MOODLE; + $qdata->generalfeedback = 'The answer is Alpha, Beta, Gamma.'; + $qdata->defaultmark = 3; + $qdata->length = 1; + $qdata->penalty = 0.3333333; + $qdata->hidden = 0; + + $qdata->options->shuffleanswers = 1; + $qdata->options->correctfeedback = '

Your answer is correct.

'; + $qdata->options->partiallycorrectfeedback = '

Your answer is partially correct.

'; + $qdata->options->shownumcorrect = true; + $qdata->options->incorrectfeedback = '

Your answer is incorrect.

'; + + $qdata->options->answers = array( + new question_answer('Alpha', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}'), + new question_answer('Beta', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}'), + new question_answer('Gamma', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:1;}'), + ); + + $qdata->hints = array( + new question_hint_with_parts('Try again.', true, false), + new question_hint_with_parts('These are the first three letters of the Greek alphabet.', true, true), + ); + + $exporter = new qformat_xml(); + $xml = $exporter->writequestion($qdata); + + $expectedxml = ' + + + A drag-and-drop question + + + Put these in order: [[1]], [[2]], [[3]]. + + + The answer is Alpha, Beta, Gamma. + + 3 + 0.3333333 + 0 + 1 + + Your answer is correct.

]]>
+
+ + Your answer is partially correct.

]]>
+
+ + Your answer is incorrect.

]]>
+
+ + + Alpha + 1 + + + Beta + 1 + + + Gamma + 1 + + + + Try again. + + + + These are the first three letters of the Greek alphabet. + + + +
+'; + + $this->assert_same_xml($expectedxml, $xml); + } +} diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php new file mode 100755 index 00000000000..4a0f2820fc9 --- /dev/null +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -0,0 +1,680 @@ +. + + +/** + * This file contains tests that walks a question through the interactive + * behaviour. + * + * @package qtype_ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); +require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); + + +class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { + + protected function get_contains_drop_box_expectation($place, $group, $readonly, $stateclass = '0') { + $qa = $this->quba->get_question_attempt($this->slot); + + $expectedattrs = array( + 'id' => $qa->get_qt_field_name($place . '_' . $group), + ); + $class = 'slot group' . $group; + if ($readonly) { + $class .= ' readonly'; + } else { + $expectedattrs['tabindex'] = 0; + } + if ($stateclass) { + $class .= ' ' . $stateclass; + } + $expectedattrs['class'] = $class; + + return new ContainsTagWithAttributes('span', $expectedattrs); + } + + public function test_interactive_behaviour() { + + // Create a drag-and-drop question. + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->hints = array( + new question_hint_with_parts('This is the first hint.', false, false), + new question_hint_with_parts('This is the second hint.', true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + + // Save the wrong answer. + $this->process_submission(array('p1' => '2', 'p2' => '2', 'p3' => '2')); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '2'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '2'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + + // Submit the wrong answer. + $this->process_submission(array('p1' => '2', 'p2' => '2', 'p3' => '2', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true), + $this->get_contains_drop_box_expectation('p2', 2, true), + $this->get_contains_drop_box_expectation('p3', 3, true), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_try_again_button_expectation(true), + $this->get_does_not_contain_correctness_expectation(), + new PatternExpectation('/' . preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + $this->get_contains_hint_expectation('This is the first hint')); + + // Do try again. + $this->process_submission(array('-tryagain' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '2'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '2'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(2), + $this->get_no_hint_visible_expectation()); + + // Submit the right answer. + $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '1', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(2); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), + $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), + $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_correct_expectation(), + $this->get_no_hint_visible_expectation()); + + // Check regrading does not mess anything up. + $this->quba->regrade_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(2); + } + + public function test_deferred_feedback() { + + // Create a drag-and-drop question. + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'deferredfeedback', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_does_not_contain_feedback_expectation()); + + // Save a partial answer. + $this->process_submission(array('p1' => '1', 'p2' => '2')); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + + // Save the right answer. + $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '1')); + + // Verify. + $this->check_current_state(question_state::$complete); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '1'), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + + // Finish the attempt. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(3); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), + $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), + $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), + $this->get_contains_correct_expectation()); + + // Change the right answer a bit. + $dd->rightchoices[2] = 2; + + // Check regrading does not mess anything up. + $this->quba->regrade_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedpartial); + $this->check_current_mark(2); + } + + public function test_deferred_feedback_unanswered() { + + // Create a drag-and-drop question. + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'deferredfeedback', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + $this->check_step_count(1); + + // Save a blank response. + $this->process_submission(array('p1' => '0', 'p2' => '0', 'p3' => '0')); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + $this->check_step_count(1); + + // Finish the attempt. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gaveup); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true), + $this->get_contains_drop_box_expectation('p2', 2, true), + $this->get_contains_drop_box_expectation('p3', 3, true)); + } + + public function test_deferred_feedback_partial_answer() { + + // Create a drag-and-drop question. + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'deferredfeedback', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + + // Save a partial response. + $this->process_submission(array('p1' => '1', 'p2' => '0', 'p3' => '0')); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + + // Finish the attempt. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedpartial); + $this->check_current_mark(1); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), + $this->get_contains_drop_box_expectation('p2', 2, true, 'incorrect'), + $this->get_contains_drop_box_expectation('p3', 3, true, 'incorrect'), + $this->get_contains_partcorrect_expectation()); + } + + public function test_interactive_grading() { + + // Create a drag-and-drop question. + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->hints = array( + new question_hint_with_parts('This is the first hint.', true, true), + new question_hint_with_parts('This is the second hint.', true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 9); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->assertEqual('interactivecountback', + $this->quba->get_question_attempt($this->slot)->get_behaviour_name()); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_does_not_contain_num_parts_correct(), + $this->get_no_hint_visible_expectation()); + + // Submit an response with the first two parts right. + $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '2', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true), + $this->get_contains_drop_box_expectation('p2', 2, true), + $this->get_contains_drop_box_expectation('p3', 3, true), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_try_again_button_expectation(true), + $this->get_does_not_contain_correctness_expectation(), + new PatternExpectation('/' . preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + $this->get_contains_hint_expectation('This is the first hint'), + $this->get_contains_num_parts_correct(2), + $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0')); + + // Check that extract responses will return the reset data. + $prefix = $this->quba->get_field_prefix($this->slot); + $this->assertEqual(array('p1' => '1', 'p2' => '1'), + $this->quba->extract_responses($this->slot, array($prefix . 'p1' => '1', $prefix . 'p2' => '1', '-tryagain' => 1))); + + // Do try again. + $this->process_submission(array('p1' => '1', 'p2' => '1', '-tryagain' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_try_again_button_expectation(), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(2), + $this->get_no_hint_visible_expectation()); + + // Submit an response with the first and last parts right. + $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '1', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true), + $this->get_contains_drop_box_expectation('p2', 2, true), + $this->get_contains_drop_box_expectation('p3', 3, true), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_try_again_button_expectation(true), + $this->get_does_not_contain_correctness_expectation(), + new PatternExpectation('/' . preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + $this->get_contains_hint_expectation('This is the second hint'), + $this->get_contains_num_parts_correct(2), + $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '1')); + + // Do try again. + $this->process_submission(array('p1' => '1', 'p3' => '1', '-tryagain' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '1'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_try_again_button_expectation(), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(1), + $this->get_no_hint_visible_expectation()); + + // Submit the right answer. + $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '1', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(6); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), + $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), + $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), + $this->get_contains_submit_button_expectation(false), + $this->get_does_not_contain_try_again_button_expectation(), + $this->get_contains_correct_expectation(), + $this->get_no_hint_visible_expectation(), + $this->get_does_not_contain_num_parts_correct(), + $this->get_contains_standard_correct_combined_feedback_expectation(), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '1')); + } + + public function test_interactive_correct_no_submit() { + + // Create a drag-and-drop question. + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->hints = array( + new question_hint_with_parts('This is the first hint.', false, false), + new question_hint_with_parts('This is the second hint.', true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + + // Save the right answer. + $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '1')); + + // Finish the attempt without clicking check. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(3); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), + $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), + $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_correct_expectation(), + $this->get_no_hint_visible_expectation()); + + // Check regrading does not mess anything up. + $this->quba->regrade_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(3); + } + + public function test_interactive_partial_no_submit() { + + // Create a drag-and-drop question. + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->hints = array( + new question_hint_with_parts('This is the first hint.', false, false), + new question_hint_with_parts('This is the second hint.', true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + + // Save the a partially right answer. + $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '2')); + + // Finish the attempt without clicking check. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedpartial); + $this->check_current_mark(1); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), + $this->get_contains_drop_box_expectation('p2', 2, true, 'incorrect'), + $this->get_contains_drop_box_expectation('p3', 3, true, 'incorrect'), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_partcorrect_expectation(), + $this->get_no_hint_visible_expectation()); + + // Check regrading does not mess anything up. + $this->quba->regrade_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedpartial); + $this->check_current_mark(1); + } + + public function test_interactive_no_right_clears() { + + // Create a drag-and-drop question. + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd->hints = array( + new question_hint_with_parts('This is the first hint.', false, true), + new question_hint_with_parts('This is the second hint.', true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_marked_out_of_summary(), + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + + // Save the a completely wrong answer. + $this->process_submission(array('p1' => '2', 'p2' => '2', 'p3' => '2', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_marked_out_of_summary(), + $this->get_contains_drop_box_expectation('p1', 1, true), + $this->get_contains_drop_box_expectation('p2', 2, true), + $this->get_contains_drop_box_expectation('p3', 3, true), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_hint_expectation('This is the first hint')); + + // Do try again. + $this->process_submission(array('p1' => '0', 'p2' => '0', 'p3' => '0', '-tryagain' => 1)); + + // Check that all the wrong answers have been cleared. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_marked_out_of_summary(), + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(2), + $this->get_no_hint_visible_expectation()); + } + + public function test_display_of_right_answer_when_shuffled() { + + // Create a drag-and-drop question. + $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $this->start_attempt_at_question($dd, 'deferredfeedback', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_does_not_contain_feedback_expectation()); + + // Save a partial answer. + $this->process_submission($dd->get_correct_response()); + + // Verify. + $this->check_current_state(question_state::$complete); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, false), + $this->get_contains_drop_box_expectation('p2', 2, false), + $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', $dd->get_right_choice_for(1)), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', $dd->get_right_choice_for(2)), + $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', $dd->get_right_choice_for(3)), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + + // Finish the attempt. + $this->quba->finish_all_questions(); + + // Verify. + $this->displayoptions->rightanswer = question_display_options::VISIBLE; + $this->assertEqual('{quick} {fox} {lazy}', $dd->get_right_answer_summary()); + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(3); + $this->check_current_output( + $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), + $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), + $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), + $this->get_contains_correct_expectation(), + new PatternExpectation('/' . preg_quote('The [quick] brown [fox] jumped over the [lazy] dog.') . '/')); + + } +} diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css new file mode 100755 index 00000000000..991b59e5788 --- /dev/null +++ b/question/type/ddimageortext/styles.css @@ -0,0 +1,67 @@ +.que.ddwtos .qtext { + line-height:2em; + margin-top: 1px; + margin-bottom: 0.5em; + display: block; +} + +.que.ddwtos .answercontainer { + line-height: 2em; + margin-bottom:1em; + display: block; +} + +.que.ddwtos .answertext { + padding-bottom: 0.5em; +} + +.que.ddwtos .slot { + display: inline-block; + text-align: center; + border: 1px solid #000000; +} +.que.ddwtos .player { + display: inline-block; + text-align: center; + cursor: move; + border: 1px solid #000000; +} +.que.ddwtos .player.placed { /* Lets the focus rectangle be visible in IE. */ + background: transparent; +} + +.que.ddwtos .readonly { + cursor: default; +} + +.que.ddwtos span.incorrect { + background-color: #faa; +} +.que.ddwtos span.correct { + background-color: #afa; +} + +.que.ddwtos .group1 { + background-color: #FFFFFF; +} +.que.ddwtos .group2 { + background-color: #DCDCDC; +} +.que.ddwtos .group3 { + background-color: #B0C4DE; +} +.que.ddwtos .group4 { + background-color: #D8BFD8; +} +.que.ddwtos .group5 { + background-color: #87CEFA; +} +.que.ddwtos .group6 { + background-color: #DAA520; +} +.que.ddwtos .group7 { + background-color: #FFD700; +} +.que.ddwtos .group8 { + background-color: #F0E68C; +} diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php new file mode 100755 index 00000000000..243100003cd --- /dev/null +++ b/question/type/ddimageortext/version.php @@ -0,0 +1,4 @@ +version = 2010042800; +$plugin->requires = 2007101000; From 77e268e1e9d20eda6bc19e8370a675ab8418ae19 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 31 Jan 2011 18:07:38 +0000 Subject: [PATCH 002/208] MDL-47494 ddimageortext: More work on the ddwtos and gapselect qtypes. Now there are no longer fatal errors that break other qtypes, but these two qtypes still not work completely. More to come. --- .../type/ddimageortext/edit_ddwtos_form.php | 2 +- question/type/ddimageortext/questiontype.php | 29 ++++---- .../simpletest/testquestiontype.php | 66 ++++++++++--------- .../simpletest/testwalkthrough.php | 4 +- 4 files changed, 53 insertions(+), 48 deletions(-) diff --git a/question/type/ddimageortext/edit_ddwtos_form.php b/question/type/ddimageortext/edit_ddwtos_form.php index dec87f43e86..e04351c8e14 100755 --- a/question/type/ddimageortext/edit_ddwtos_form.php +++ b/question/type/ddimageortext/edit_ddwtos_form.php @@ -24,7 +24,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once($CFG->dirroot . '/question/type/sddl/edit_form_base.php'); +require_once($CFG->dirroot . '/question/type/gapselect/edit_form_base.php'); /** diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index b72e89a2414..94d121a634b 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -38,30 +38,29 @@ require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos extends qtype_gapselect_base { - protected function feedback_serialization($choice){ + protected function choice_group_key(){ + return 'draggroup'; + } + + public function requires_qtypes() { + return array('gapselect'); + } + + protected function choice_options_to_feedback($choice){ $output = new stdClass; $output->draggroup = $choice['draggroup']; $output->infinite = !empty($choice['infinite']); return serialize($output); } - protected function feedback_unserialization($choicedata){ - $options = unserialize($choicedata->feedback); - return new qtype_ddwtos_choice($choicedata->answer, $options->draggroup, $options->infinite); - } - - - protected function feedback_unserialize_as_array($feedback){ + protected function feedback_to_choice_options($feedback){ $feedbackobj = unserialize($feedback); return array('draggroup'=> $feedbackobj->draggroup, 'infinite'=> $feedbackobj->infinite); } - protected function choice_group_key(){ - return 'draggroup'; - } - - public function requires_qtypes() { - return array('sddl'); + protected function make_choice($choicedata){ + $options = unserialize($choicedata->feedback); + return new qtype_ddwtos_choice($choicedata->answer, $options->draggroup, $options->infinite); } public function import_from_xml($data, $question, $format, $extra=null) { @@ -94,7 +93,7 @@ class qtype_ddwtos extends qtype_gapselect_base { // Legacy format containing PHP serialisation. foreach ($data['#']['answer'] as $answerxml) { $ans = $format->import_answer($answerxml); - $options = unserialize(stripslashes($ans->feedback)); + $options = unserialize(stripslashes($ans->feedback['text'])); $question->choices[] = array( 'answer' => $ans->answer, 'draggroup' => $options->draggroup, diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index 0acfa17b174..f8bfa87e9c6 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -64,6 +64,7 @@ class qtype_ddwtos_test extends UnitTestCase { $dd->category = 0; $dd->parent = 0; $dd->questiontextformat = FORMAT_HTML; + $dd->generalfeedbackformat = FORMAT_HTML; $dd->defaultmark = 1; $dd->penalty = 0.3333333; $dd->length = 1; @@ -205,10 +206,10 @@ class qtype_ddwtos_test extends UnitTestCase { $expectedq->penalty = 0.3333333; $expectedq->shuffleanswers = 1; - $expectedq->correctfeedback = '

Your answer is correct.

'; - $expectedq->partiallycorrectfeedback = '

Your answer is partially correct.

'; + $expectedq->correctfeedback = array('text' => '

Your answer is correct.

', 'format' => FORMAT_MOODLE, 'files' => array()); + $expectedq->partiallycorrectfeedback = array('text' => '

Your answer is partially correct.

', 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->shownumcorrect = true; - $expectedq->incorrectfeedback = '

Your answer is incorrect.

'; + $expectedq->incorrectfeedback = array('text' => '

Your answer is incorrect.

', 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->choices = array( array('answer' => 'Alpha', 'draggroup' => 1, 'infinite' => false), @@ -348,32 +349,32 @@ class qtype_ddwtos_test extends UnitTestCase { $expectedq->name = 'QDandD1 Base definition'; $expectedq->questiontext = '

Drag and drop the words from the list below to fill the blank spaces and correctly complete the sentence.

At 25°C all aqueous basic solutions have [[1]] ion concentrations less than [[8]]
mol litre-1 and pH values [[9]] than [[6]].

'; $expectedq->questiontextformat = FORMAT_HTML; - $expectedq->generalfeedback = '

At 25 °C all aqueous basic solutions have hydrogen ion concentrations less than 10−7 mol litre−1 and pH values greater than 7.

See Section 9 of S103 Discovering Science Block 8.

'; + $expectedq->generalfeedback = '

At 25 °C all aqueous basic solutions have hydrogen ion concentrations less than 10−7 mol litre−1 and pH values greater than 7.

See Section 9 of S103 Discovering Science Block 8.

'; $expectedq->defaultmark = 1; $expectedq->length = 1; $expectedq->penalty = 0.3333333; $expectedq->shuffleanswers = 0; - $expectedq->correctfeedback = 'Your answer is correct.'; - $expectedq->partiallycorrectfeedback = 'Your answer is partially correct.'; + $expectedq->correctfeedback = array('text' => 'Your answer is correct.', 'format' => FORMAT_MOODLE, 'files' => array()); + $expectedq->partiallycorrectfeedback = array('text' => 'Your answer is partially correct.', 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->shownumcorrect = true; - $expectedq->incorrectfeedback = 'Your answer is incorrect.'; + $expectedq->incorrectfeedback = array('text' => 'Your answer is incorrect.', 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->choices = array( - array('answer' => 'hydrogen', 'draggroup' => 1, 'infinite' => false), - array('answer' => 'positive', 'draggroup' => 1, 'infinite' => false), - array('answer' => 'hydroxide', 'draggroup' => 1, 'infinite' => false), - array('answer' => 'negative', 'draggroup' => 1, 'infinite' => false), - array('answer' => '107', 'draggroup' => 2, 'infinite' => false), - array('answer' => '7', 'draggroup' => 2, 'infinite' => false), - array('answer' => '1', 'draggroup' => 2, 'infinite' => false), - array('answer' => '10-7', 'draggroup' => 2, 'infinite' => false), - array('answer' => 'greater', 'draggroup' => 3, 'infinite' => false), - array('answer' => 'less', 'draggroup' => 3, 'infinite' => false), + array('answer' => array('text' => 'hydrogen', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 1, 'infinite' => false), + array('answer' => array('text' => 'positive', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 1, 'infinite' => false), + array('answer' => array('text' => 'hydroxide', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 1, 'infinite' => false), + array('answer' => array('text' => 'negative', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 1, 'infinite' => false), + array('answer' => array('text' => '107', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 2, 'infinite' => false), + array('answer' => array('text' => '7', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 2, 'infinite' => false), + array('answer' => array('text' => '1', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 2, 'infinite' => false), + array('answer' => array('text' => '10-7', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 2, 'infinite' => false), + array('answer' => array('text' => 'greater', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 3, 'infinite' => false), + array('answer' => array('text' => 'less', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 3, 'infinite' => false), ); $expectedq->hint = array( - 'You may wish to read Section 9 of Discovering Science Block 8.', + 'You may wish to read Section 9 of Discovering Science Block 8.', 'Any incorrect choices will be removed before your final try.' ); $expectedq->hintshownumcorrect = array(true, true); @@ -385,11 +386,13 @@ class qtype_ddwtos_test extends UnitTestCase { public function test_xml_export() { $qdata = new stdClass; $qdata->id = 123; + $qdata->contextid = 0; $qdata->qtype = 'ddwtos'; $qdata->name = 'A drag-and-drop question'; $qdata->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; $qdata->questiontextformat = FORMAT_MOODLE; $qdata->generalfeedback = 'The answer is Alpha, Beta, Gamma.'; + $qdata->generalfeedbackformat = FORMAT_MOODLE; $qdata->defaultmark = 3; $qdata->length = 1; $qdata->penalty = 0.3333333; @@ -397,19 +400,22 @@ class qtype_ddwtos_test extends UnitTestCase { $qdata->options->shuffleanswers = 1; $qdata->options->correctfeedback = '

Your answer is correct.

'; + $qdata->options->correctfeedbackformat = FORMAT_MOODLE; $qdata->options->partiallycorrectfeedback = '

Your answer is partially correct.

'; - $qdata->options->shownumcorrect = true; + $qdata->options->partiallycorrectfeedbackformat = FORMAT_MOODLE; + $qdata->options->shownumcorrect = 1; $qdata->options->incorrectfeedback = '

Your answer is incorrect.

'; + $qdata->options->incorrectfeedbackformat = FORMAT_MOODLE; $qdata->options->answers = array( - new question_answer('Alpha', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}'), - new question_answer('Beta', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}'), - new question_answer('Gamma', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:1;}'), + 13 => new question_answer(13, 'Alpha', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', FORMAT_MOODLE), + 14 => new question_answer(14, 'Beta', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', FORMAT_MOODLE), + 15 => new question_answer(15, 'Gamma', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:1;}', FORMAT_MOODLE), ); $qdata->hints = array( - new question_hint_with_parts('Try again.', true, false), - new question_hint_with_parts('These are the first three letters of the Greek alphabet.', true, true), + 1 => new question_hint_with_parts(1, 'Try again.', FORMAT_MOODLE, true, false), + 2 => new question_hint_with_parts(2, 'These are the first three letters of the Greek alphabet.', FORMAT_MOODLE, true, true), ); $exporter = new qformat_xml(); @@ -423,20 +429,20 @@ class qtype_ddwtos_test extends UnitTestCase { Put these in order: [[1]], [[2]], [[3]]. - + The answer is Alpha, Beta, Gamma. 3 0.3333333 0 1 - + Your answer is correct.

]]>
- + Your answer is partially correct.

]]>
- + Your answer is incorrect.

]]>
@@ -453,11 +459,11 @@ class qtype_ddwtos_test extends UnitTestCase { 1 - + Try again. - + These are the first three letters of the Greek alphabet. diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index 4a0f2820fc9..9b6f42549f7 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -57,8 +57,8 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { // Create a drag-and-drop question. $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->hints = array( - new question_hint_with_parts('This is the first hint.', false, false), - new question_hint_with_parts('This is the second hint.', true, true), + 13 => new question_hint_with_parts(13, 'This is the first hint.', FORMAT_HTML, false, false), + 14 => new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true), ); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'interactive', 3); From 08c1d356eb4248e375c17f97b5b1e1f39e4a1172 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 1 Feb 2011 11:40:29 +0000 Subject: [PATCH 003/208] MDL-47494 ddimageortext: Now all the unit tests for the the ddwtos and gapselect qtypes pass. --- .../ddimageortext/lang/en/qtype_ddwtos.php | 27 ++++++++++++++++++- .../simpletest/testwalkthrough.php | 21 +++++++-------- question/type/ddimageortext/version.php | 4 +-- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddwtos.php b/question/type/ddimageortext/lang/en/qtype_ddwtos.php index 34b17378121..aabe3852384 100755 --- a/question/type/ddimageortext/lang/en/qtype_ddwtos.php +++ b/question/type/ddimageortext/lang/en/qtype_ddwtos.php @@ -1,10 +1,35 @@ . + + +/** + * Language strings for the select missing words question type. + * + * @package qtype + * @subpackage gapselect + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + $string['addingddwtos'] = 'Adding drag and drop: words in text'; $string['addmorechoiceblanks'] = 'Blanks for {no} More Choices'; $string['answer'] = 'Answer'; -$string['correctansweris'] = 'The correct answer is: $a'; +$string['correctansweris'] = 'The correct answer is: {$a}'; $string['ddwtos'] = 'Drag and drop: words in text'; $string['ddwtos_help'] = 'Type in some question text like "The [[1]] jumped over the [[2]]", then enter the possible words to go in gaps 1 and 2 underneath.'; $string['ddwtossummary'] = 'Missing words in some text are filled in using drag-and-drop.'; diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index 9b6f42549f7..4b613e70160 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -57,8 +57,8 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { // Create a drag-and-drop question. $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->hints = array( - 13 => new question_hint_with_parts(13, 'This is the first hint.', FORMAT_HTML, false, false), - 14 => new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true), + new question_hint_with_parts(13, 'This is the first hint.', FORMAT_HTML, false, false), + new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true), ); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'interactive', 3); @@ -332,8 +332,8 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { // Create a drag-and-drop question. $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->hints = array( - new question_hint_with_parts('This is the first hint.', true, true), - new question_hint_with_parts('This is the second hint.', true, true), + new question_hint_with_parts(1, 'This is the first hint.', FORMAT_MOODLE, true, true), + new question_hint_with_parts(2, 'This is the second hint.', FORMAT_MOODLE, true, true), ); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'interactive', 9); @@ -469,8 +469,8 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { // Create a drag-and-drop question. $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->hints = array( - new question_hint_with_parts('This is the first hint.', false, false), - new question_hint_with_parts('This is the second hint.', true, true), + new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), + new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), ); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'interactive', 3); @@ -520,8 +520,8 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { // Create a drag-and-drop question. $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->hints = array( - new question_hint_with_parts('This is the first hint.', false, false), - new question_hint_with_parts('This is the second hint.', true, true), + new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), + new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), ); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'interactive', 3); @@ -571,8 +571,8 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { // Create a drag-and-drop question. $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->hints = array( - new question_hint_with_parts('This is the first hint.', false, true), - new question_hint_with_parts('This is the second hint.', true, true), + new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, true), + new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), ); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'interactive', 3); @@ -675,6 +675,5 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), $this->get_contains_correct_expectation(), new PatternExpectation('/' . preg_quote('The [quick] brown [fox] jumped over the [lazy] dog.') . '/')); - } } diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 243100003cd..ad42b28bb9e 100755 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -1,4 +1,4 @@ version = 2010042800; -$plugin->requires = 2007101000; +$plugin->version = 2011020100; +$plugin->requires = 2011011200; From 428b36687dd19a721ae2d95650272db7f23d5710 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 1 Feb 2011 23:44:40 +0000 Subject: [PATCH 004/208] MDL-47494 ddimageortext: ddwtos and gapselect qtypes now very nearly work. Todo rendering questions with files, and ddwtos javascript. --- question/type/ddimageortext/db/install.xml | 11 ++- question/type/ddimageortext/db/upgrade.php | 83 ------------------ .../type/ddimageortext/edit_ddwtos_form.php | 33 ++----- .../type/ddimageortext/{ => pix}/icon.gif | Bin question/type/ddimageortext/questiontype.php | 2 +- 5 files changed, 17 insertions(+), 112 deletions(-) delete mode 100755 question/type/ddimageortext/db/upgrade.php rename question/type/ddimageortext/{ => pix}/icon.gif (100%) diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml index 065853d37b1..50dbefe8a09 100755 --- a/question/type/ddimageortext/db/install.xml +++ b/question/type/ddimageortext/db/install.xml @@ -9,10 +9,13 @@ - - - - + + + + + + + diff --git a/question/type/ddimageortext/db/upgrade.php b/question/type/ddimageortext/db/upgrade.php deleted file mode 100755 index 91d665a1685..00000000000 --- a/question/type/ddimageortext/db/upgrade.php +++ /dev/null @@ -1,83 +0,0 @@ -question = $ddanswer->questionid; - $answer->answer = addslashes($ddanswer->answer); - $answer->fraction = 1; - - $feedback = new stdClass; - $feedback->draggroup = $ddanswer->draggroup; - $feedback->infinite = $ddanswer->infinite; - $answer->feedback = serialize($feedback); - - if(!insert_record('question_answers', $answer)){ - notify('move_question_ddanswers_to_question_answers(): cannot insert row into question_answer table.'); - return false; - } - } - } - - // Drop table - $result = $result && drop_table($table); - } - - if ($result && $oldversion < 2010042800) { - - /// Rename field correctresponsesfeedback on table question_ddwtos to shownumcorrect - $table = new XMLDBTable('question_ddwtos'); - $field = new XMLDBField('correctresponsesfeedback'); - $field->setAttributes(XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'incorrectfeedback'); - - /// Launch rename field correctresponsesfeedback - $result = $result && rename_field($table, $field, 'shownumcorrect'); - } - - return $result; -} diff --git a/question/type/ddimageortext/edit_ddwtos_form.php b/question/type/ddimageortext/edit_ddwtos_form.php index e04351c8e14..222aaf08fcd 100755 --- a/question/type/ddimageortext/edit_ddwtos_form.php +++ b/question/type/ddimageortext/edit_ddwtos_form.php @@ -34,36 +34,21 @@ require_once($CFG->dirroot . '/question/type/gapselect/edit_form_base.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { - function qtype() { return 'ddwtos'; } - protected function default_values_from_feedback_field($feedback, $key){ - $feedback = unserialize($feedback); - $draggroup = $feedback->draggroup; - $infinite = $feedback->infinite; - - $default_values = array(); - $default_values['choices['.$key.'][draggroup]'] = $draggroup; - $default_values['choices['.$key.'][infinite]'] = $infinite; - return $default_values; + protected function data_preprocessing_choice($question, $answer, $key) { + $question = parent::data_preprocessing_choice($question, $answer, $key); + $options = unserialize($answer->feedback); + $question->choices[$key]['choicegroup'] = $options->draggroup; + $question->choices[$key]['infinite'] = $options->infinite; + return $question; } - protected function repeated_options(){ - $repeatedoptions = array(); - $repeatedoptions['draggroup']['default'] = '1'; - $repeatedoptions['infinite']['default'] = 0; - return $repeatedoptions; - } - - protected function choice_group(&$mform, $grouparray){ - $options = array(); - for ($i = 1; $i <= 8; $i += 1) { - $options[$i] = $i; - } - $grouparray[] =& $mform->createElement('select', 'draggroup', get_string('group', 'qtype_ddwtos'), $options); - $grouparray[] =& $mform->createElement('checkbox', 'infinite', ' ', get_string('infinite', 'qtype_ddwtos'), null, array('size'=>1, 'class'=>'tweakcss')); + protected function choice_group($mform) { + $grouparray = parent::choice_group($mform); + $grouparray[] = $mform->createElement('checkbox', 'infinite', ' ', get_string('infinite', 'qtype_ddwtos'), null, array('size'=>1, 'class'=>'tweakcss')); return $grouparray; } } diff --git a/question/type/ddimageortext/icon.gif b/question/type/ddimageortext/pix/icon.gif similarity index 100% rename from question/type/ddimageortext/icon.gif rename to question/type/ddimageortext/pix/icon.gif diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 94d121a634b..e360fcc15fb 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -48,7 +48,7 @@ class qtype_ddwtos extends qtype_gapselect_base { protected function choice_options_to_feedback($choice){ $output = new stdClass; - $output->draggroup = $choice['draggroup']; + $output->draggroup = $choice['choicegroup']; $output->infinite = !empty($choice['infinite']); return serialize($output); } From 303bf0190248fdc18e0382ab1fe64512da21cf93 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 2 Feb 2011 19:03:38 +0000 Subject: [PATCH 005/208] MDL-47494 ddimageortext: Finish making ddwtos work, mostly. Also various other JS fixes. This JavaScript really needs to be rewritten to use YUI3. --- question/type/ddimageortext/renderer.php | 4 +++- question/type/ddimageortext/styles.css | 9 ++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 8f4362fed1b..8be3eeaef5a 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -127,7 +127,9 @@ class qtype_ddwtos_renderer extends qtype_elements_embedded_in_question_text_ren public function head_code(question_attempt $qa) { - require_js(array('yui_dom-event', 'yui_dragdrop')); + $this->page->requires->yui2_lib('dom'); + $this->page->requires->yui2_lib('event'); + $this->page->requires->yui2_lib('dragdrop'); return parent::head_code($qa); } diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 991b59e5788..8a84a09b149 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -1,13 +1,16 @@ .que.ddwtos .qtext { - line-height:2em; - margin-top: 1px; + line-height: 2em; margin-bottom: 0.5em; display: block; } +.que.ddwtos .qtext * { + line-height: 2em; +} + .que.ddwtos .answercontainer { line-height: 2em; - margin-bottom:1em; + margin-bottom: 1em; display: block; } From 7368987a5f7d3c5b3b1c4ef6c61266646f105370 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 9 Feb 2011 20:33:51 +0000 Subject: [PATCH 006/208] MDL-47494 ddimageortext: Images in questions now work in quiz attempts. --- question/type/ddimageortext/simpletest/testquestiontype.php | 1 + 1 file changed, 1 insertion(+) diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index f8bfa87e9c6..4ef6567c5b5 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -62,6 +62,7 @@ class qtype_ddwtos_test extends UnitTestCase { $dd = new stdClass; $dd->id = 0; $dd->category = 0; + $dd->contextid = 0; $dd->parent = 0; $dd->questiontextformat = FORMAT_HTML; $dd->generalfeedbackformat = FORMAT_HTML; From 3919f482a72d73d40d4814338afe864d9a32a020 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 21 Feb 2011 18:10:19 +0000 Subject: [PATCH 007/208] MDL-47494 ddimageortext: Fix new stdClass -> stdClass(), and trailing whitespace. --- question/type/ddimageortext/questiontype.php | 4 ++-- .../type/ddimageortext/simpletest/testquestiontype.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index e360fcc15fb..e5078dd6be0 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -47,7 +47,7 @@ class qtype_ddwtos extends qtype_gapselect_base { } protected function choice_options_to_feedback($choice){ - $output = new stdClass; + $output = new stdClass(); $output->draggroup = $choice['choicegroup']; $output->infinite = !empty($choice['infinite']); return serialize($output); @@ -174,7 +174,7 @@ class qtype_ddwtos extends qtype_gapselect_base { $mul_info = $ddwtos[$i]; //Now, build the question_ddwtos record structure - $ddwtos = new stdClass; + $ddwtos = new stdClass(); $ddwtos->questionid = $new_question_id; $ddwtos->shuffleanswers = isset($mul_info['#']['SHUFFLEANSWERS']['0']['#'])?backup_todb($mul_info['#']['SHUFFLEANSWERS']['0']['#']):''; if (array_key_exists("CORRECTFEEDBACK", $mul_info['#'])) { diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index 4ef6567c5b5..dca047ed47a 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -59,7 +59,7 @@ class qtype_ddwtos_test extends UnitTestCase { protected function get_test_question_data() { global $USER; - $dd = new stdClass; + $dd = new stdClass(); $dd->id = 0; $dd->category = 0; $dd->contextid = 0; @@ -196,7 +196,7 @@ class qtype_ddwtos_test extends UnitTestCase { $q = $importer->try_importing_using_qtypes( $xmldata['question'], null, null, 'ddwtos'); - $expectedq = new stdClass; + $expectedq = new stdClass(); $expectedq->qtype = 'ddwtos'; $expectedq->name = 'A drag-and-drop question'; $expectedq->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; @@ -345,7 +345,7 @@ class qtype_ddwtos_test extends UnitTestCase { $q = $importer->try_importing_using_qtypes( $xmldata['question'], null, null, 'ddwtos'); - $expectedq = new stdClass; + $expectedq = new stdClass(); $expectedq->qtype = 'ddwtos'; $expectedq->name = 'QDandD1 Base definition'; $expectedq->questiontext = '

Drag and drop the words from the list below to fill the blank spaces and correctly complete the sentence.

At 25°C all aqueous basic solutions have [[1]] ion concentrations less than [[8]]
mol litre-1 and pH values [[9]] than [[6]].

'; @@ -385,7 +385,7 @@ class qtype_ddwtos_test extends UnitTestCase { } public function test_xml_export() { - $qdata = new stdClass; + $qdata = new stdClass(); $qdata->id = 123; $qdata->contextid = 0; $qdata->qtype = 'ddwtos'; From c205413ad932b4316200674219f78780e20542eb Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 22 Feb 2011 19:59:12 +0000 Subject: [PATCH 008/208] MDL-47494 ddimageortext: Add @package and GPL boiler-plate to files in /question. --- question/type/ddimageortext/script.js | 22 +++++++++++++++++++--- question/type/ddimageortext/version.php | 24 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/script.js b/question/type/ddimageortext/script.js index 0f0a4807959..f2c47e5a48c 100755 --- a/question/type/ddimageortext/script.js +++ b/question/type/ddimageortext/script.js @@ -1,11 +1,27 @@ +// This file is part of Moodle - http://moodle.org/ +// +// 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 . + /** * JavaScript objects, functions as well as usage of some YUI library for * enabling drag and drop interaction for dran-anddrop words into sentences * (ddwtos) * - * @package qtype_ddwtos - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype + * @subpackage ddwtos + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ //global variables diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index ad42b28bb9e..19bbecdec14 100755 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -1,4 +1,28 @@ . + +/** + * Version information for the drag-and-drop words into sentences question type. + * + * @package qtype + * @subpackage ddwtos + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + $plugin->version = 2011020100; $plugin->requires = 2011011200; From 5b4602d26750b97c4302941b73c3dbf5fb66e61a Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 23 Feb 2011 13:38:16 +0000 Subject: [PATCH 009/208] MDL-47494 ddimageortext: Fix @package names and PHPdoc layout. --- .../type/ddimageortext/edit_ddwtos_form.php | 13 +++++++------ .../type/ddimageortext/lang/en/qtype_ddwtos.php | 11 ++++------- question/type/ddimageortext/question.php | 17 +++++++++-------- question/type/ddimageortext/questiontype.php | 14 +++++++------- question/type/ddimageortext/renderer.php | 13 +++++++------ .../type/ddimageortext/simpletest/helper.php | 14 +++++++++++--- .../ddimageortext/simpletest/testquestion.php | 13 +++++++------ .../simpletest/testquestiontype.php | 12 ++++++------ .../simpletest/testwalkthrough.php | 17 +++++++++++------ 9 files changed, 69 insertions(+), 55 deletions(-) diff --git a/question/type/ddimageortext/edit_ddwtos_form.php b/question/type/ddimageortext/edit_ddwtos_form.php index 222aaf08fcd..9be4ef36df4 100755 --- a/question/type/ddimageortext/edit_ddwtos_form.php +++ b/question/type/ddimageortext/edit_ddwtos_form.php @@ -15,23 +15,24 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** * Defines the editing form for the drag-and-drop words into sentences question type. * - * @package qtype_ddwtos - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype + * @subpackage ddwtos + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once($CFG->dirroot . '/question/type/gapselect/edit_form_base.php'); /** * Drag-and-drop words into sentences editing form definition. * - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { function qtype() { diff --git a/question/type/ddimageortext/lang/en/qtype_ddwtos.php b/question/type/ddimageortext/lang/en/qtype_ddwtos.php index aabe3852384..9ea3e7d918f 100755 --- a/question/type/ddimageortext/lang/en/qtype_ddwtos.php +++ b/question/type/ddimageortext/lang/en/qtype_ddwtos.php @@ -15,17 +15,14 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** - * Language strings for the select missing words question type. * - * @package qtype - * @subpackage gapselect - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype + * @subpackage ddwtos + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - $string['addingddwtos'] = 'Adding drag and drop: words in text'; $string['addmorechoiceblanks'] = 'Blanks for {no} More Choices'; $string['answer'] = 'Answer'; diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 18a9911cc0b..191c04e3832 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -19,9 +19,10 @@ /** * Drag-and-drop words into sentences question definition class. * - * @package qtype_ddwtos - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype + * @subpackage ddwtos + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); @@ -29,19 +30,19 @@ require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); /** * Represents a drag-and-drop words into sentences question. * - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_question extends qtype_gapselect_question_base { -//is actually exactly the same. + // Is actually exactly the same. } /** * Represents one of the choices (draggable boxes). * - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_choice { public $text; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index e5078dd6be0..fcbc0d6a2f8 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -15,27 +15,27 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** * Question type class for the drag-and-drop words into sentences question type. * - * @package qtype_ddwtos - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype + * @subpackage ddwtos + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once($CFG->libdir . '/questionlib.php'); require_once($CFG->dirroot . '/question/engine/lib.php'); require_once($CFG->dirroot . '/question/format/xml/format.php'); - require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); + /** * The drag-and-drop words into sentences question type class. * - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos extends qtype_gapselect_base { protected function choice_group_key(){ diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 8be3eeaef5a..fc1a5b2a9b7 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -15,23 +15,24 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** * Drag-and-drop words into sentences question renderer class. * - * @package qtype_ddwtos - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype + * @subpackage ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); /** * Generates the output for drag-and-drop words into sentences questions. * - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_renderer extends qtype_elements_embedded_in_question_text_renderer { diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/simpletest/helper.php index 7b814808bb5..2ee3d142df0 100755 --- a/question/type/ddimageortext/simpletest/helper.php +++ b/question/type/ddimageortext/simpletest/helper.php @@ -15,13 +15,21 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * Test helpers for the drag-and-drop words into sentences question type. + * + * @package qtype + * @subpackage ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + /** * Test helper class for the drag-and-drop words into sentences question type. * - * @package qtype_ddwtos - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_test_helper { /** diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index db8ae7c9166..2cc02432c34 100755 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -15,15 +15,16 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** * Unit tests for the drag-and-drop words into sentences question definition class. * - * @package qtype_ddwtos - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype + * @subpackage ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); @@ -31,8 +32,8 @@ require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); /** * Unit tests for the matching question definition class. * - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_question_test extends UnitTestCase { diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index dca047ed47a..3311e12ebff 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -15,13 +15,13 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** * Unit tests for the drag-and-drop words into sentences question definition class. * - * @package qtype_ddwtos - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype + * @subpackage ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -32,8 +32,8 @@ require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); /** * Unit tests for the drag-and-drop words into sentences question definition class. * - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_test extends UnitTestCase { /** @var qtype_ddwtos instance of the question type class to test. */ diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index 4b613e70160..4b7ec380458 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -15,14 +15,13 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** - * This file contains tests that walks a question through the interactive - * behaviour. + * Unit tests for the drag-and-drop words into sentences question type. * - * @package qtype_ddwtos - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype + * @subpackage ddwtos + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -30,6 +29,12 @@ require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); +/** + * Unit tests for the drag-and-drop words into sentences question type. + * + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { protected function get_contains_drop_box_expectation($place, $group, $readonly, $stateclass = '0') { From 425362802e55077a4c2fbc18039cc39e3bfb41ae Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 23 Feb 2011 15:03:35 +0000 Subject: [PATCH 010/208] MDL-47494 ddimageortext: Add missing defined('MOODLE_INTERNAL') || die(); --- question/type/ddimageortext/edit_ddwtos_form.php | 2 ++ question/type/ddimageortext/question.php | 5 ++++- question/type/ddimageortext/questiontype.php | 2 ++ question/type/ddimageortext/renderer.php | 2 ++ question/type/ddimageortext/simpletest/helper.php | 3 +++ question/type/ddimageortext/simpletest/testquestion.php | 2 ++ question/type/ddimageortext/simpletest/testquestiontype.php | 2 ++ question/type/ddimageortext/simpletest/testwalkthrough.php | 2 ++ question/type/ddimageortext/version.php | 2 ++ 9 files changed, 21 insertions(+), 1 deletion(-) diff --git a/question/type/ddimageortext/edit_ddwtos_form.php b/question/type/ddimageortext/edit_ddwtos_form.php index 9be4ef36df4..f840a6ef919 100755 --- a/question/type/ddimageortext/edit_ddwtos_form.php +++ b/question/type/ddimageortext/edit_ddwtos_form.php @@ -25,6 +25,8 @@ */ +defined('MOODLE_INTERNAL') || die(); + require_once($CFG->dirroot . '/question/type/gapselect/edit_form_base.php'); diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 191c04e3832..6861858bbf3 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -15,7 +15,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . - /** * Drag-and-drop words into sentences question definition class. * @@ -25,8 +24,12 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + +defined('MOODLE_INTERNAL') || die(); + require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); + /** * Represents a drag-and-drop words into sentences question. * diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index fcbc0d6a2f8..aa03abee0f5 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -25,6 +25,8 @@ */ +defined('MOODLE_INTERNAL') || die(); + require_once($CFG->libdir . '/questionlib.php'); require_once($CFG->dirroot . '/question/engine/lib.php'); require_once($CFG->dirroot . '/question/format/xml/format.php'); diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index fc1a5b2a9b7..9c127b6fc27 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -25,6 +25,8 @@ */ +defined('MOODLE_INTERNAL') || die(); + require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/simpletest/helper.php index 2ee3d142df0..37f28439bc6 100755 --- a/question/type/ddimageortext/simpletest/helper.php +++ b/question/type/ddimageortext/simpletest/helper.php @@ -25,6 +25,9 @@ */ +defined('MOODLE_INTERNAL') || die(); + + /** * Test helper class for the drag-and-drop words into sentences question type. * diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index 2cc02432c34..00329ff3c6c 100755 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -25,6 +25,8 @@ */ +defined('MOODLE_INTERNAL') || die(); + require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index 3311e12ebff..1fe729aa416 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -25,6 +25,8 @@ */ +defined('MOODLE_INTERNAL') || die(); + require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index 4b7ec380458..38ead171d94 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -25,6 +25,8 @@ */ +defined('MOODLE_INTERNAL') || die(); + require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 19bbecdec14..94b1fbeabdf 100755 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -24,5 +24,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die(); + $plugin->version = 2011020100; $plugin->requires = 2011011200; From 453aded6c2e95e121a742c38043102472759cf1e Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 23 Feb 2011 18:53:50 +0000 Subject: [PATCH 011/208] MDL-47494 ddimageortext: Massively reduce the number of references to quiz in the question code. This mostly involves moving lang strings around, but I don't have time to do an AMOS script now. --- question/type/ddimageortext/script.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/script.js b/question/type/ddimageortext/script.js index f2c47e5a48c..bf84942f3a7 100755 --- a/question/type/ddimageortext/script.js +++ b/question/type/ddimageortext/script.js @@ -30,12 +30,12 @@ var ddwtos_currentzindex = 10; /* * The way it seems to be, if there are more than one of this type of question - * in a quiz, then this file is shared between them. Therefore it has to cope + * on a page, then this file is shared between them. Therefore it has to cope * with ALL the questions of this type on the page. */ (function() { - // start of App object SHARED BY ALL QUESTIONS OF THIS TYPE IN THE QUIZ ///// + // start of App object by all questions of this type on a page. YAHOO.example.DDApp = { init : function() { var questionspans = YAHOO.util.Dom.getElementsByClassName("ddwtos_questionid_for_javascript"); @@ -43,7 +43,7 @@ var ddwtos_currentzindex = 10; // we need this loop in case of more than one of this qtype on one page for (var i = 0; i < questionspans.length; i++) { // The Questions object should now contain a QuestionDataObject - //object for each question of this type in the quiz. + // object for each question of this type on the page. Questions[questionspans[i].id] = new QuestionDataObject(questionspans[i].id); } From 81f5dc53f132976531bc5e151c765f98c36eb572 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 24 Feb 2011 19:12:42 +0000 Subject: [PATCH 012/208] MDL-47494 ddimageortext: Split question_definition::init_first_step into start_attempt and apply_attempt_state. --- .../ddimageortext/simpletest/testquestion.php | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index 00329ff3c6c..9bce14087fa 100755 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -55,7 +55,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_summarise_response() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual('{quick} {fox} {lazy}', $dd->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); @@ -64,7 +64,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_summarise_response_maths() { $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual('{+} {-} {+} {-}', $dd->summarise_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); @@ -83,7 +83,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_right_choice_for() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(1, $dd->get_right_choice_for(1)); $this->assertEqual(1, $dd->get_right_choice_for(2)); @@ -92,7 +92,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_right_choice_for_maths() { $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(1, $dd->get_right_choice_for(1)); $this->assertEqual(2, $dd->get_right_choice_for(2)); @@ -101,7 +101,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_clear_wrong_from_response() { $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $initialresponse = array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'); $this->assertEqual(array('p1' => '1', 'p2' => '0', 'p3' => '1', 'p4' => '0'), @@ -111,7 +111,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_num_parts_right() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array(2, 3), $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '2'))); @@ -122,7 +122,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_num_parts_right_maths() { $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array(2, 4), $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); @@ -130,7 +130,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_expected_data() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT), $dd->get_expected_data()); @@ -139,7 +139,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_correct_response() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array('p1' => '1', 'p2' => '1', 'p3' => '1'), $dd->get_correct_response()); @@ -148,7 +148,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_correct_response_maths() { $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'), $dd->get_correct_response()); @@ -156,7 +156,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_is_same_response() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertTrue($dd->is_same_response( array(), @@ -180,7 +180,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_is_complete_response() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertFalse($dd->is_complete_response(array())); $this->assertFalse($dd->is_complete_response( @@ -192,7 +192,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_is_gradable_response() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertFalse($dd->is_gradable_response(array())); $this->assertFalse($dd->is_gradable_response( @@ -207,7 +207,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_grading() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array(1, question_state::$gradedright), $dd->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); @@ -220,7 +220,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_grading_maths() { $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array(1, question_state::$gradedright), $dd->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); @@ -233,7 +233,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_classify_response() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->shufflechoices = false; - $dd->init_first_step(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array( 1 => new question_classified_response(1, 'quick', 1), From 01bac81a41f679fab02b70adeeee459ee7948ab6 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 28 Feb 2011 10:49:20 +0000 Subject: [PATCH 013/208] MDL-47494 ddimageortext: Update quiz and questions backup and restore. This does not include user data yet, and it needs more testing. --- .../backup_qtype_ddwtos_plugin.class.php | 84 +++++++++++ .../restore_qtype_ddwtos_plugin.class.php | 136 ++++++++++++++++++ 2 files changed, 220 insertions(+) create mode 100755 question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php create mode 100755 question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php new file mode 100755 index 00000000000..a86b6b33655 --- /dev/null +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php @@ -0,0 +1,84 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + + +/** + * Provides the information to backup ddwtos questions + * + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class backup_qtype_ddwtos_plugin extends backup_qtype_plugin { + + /** + * Returns the qtype information to attach to question element + */ + protected function define_question_plugin_structure() { + + // Define the virtual plugin element with the condition to fulfill + $plugin = $this->get_plugin_element(null, '../../qtype', 'ddwtos'); + + // Create one standard named plugin element (the visible container) + $pluginwrapper = new backup_nested_element($this->get_recommended_name()); + + // connect the visible container ASAP + $plugin->add_child($pluginwrapper); + + // This qtype uses standard question_answers, add them here + // to the tree before any other information that will use them + $this->add_question_question_answers($pluginwrapper); + + // Now create the qtype own structures + $ddwtos = new backup_nested_element('ddwtos', array('id'), array( + 'shuffleanswers', 'correctfeedback', 'correctfeedbackformat', + 'partiallycorrectfeedback', 'partiallycorrectfeedbackformat', + 'incorrectfeedback', 'incorrectfeedbackformat', 'shownumcorrect')); + + // Now the own qtype tree + $pluginwrapper->add_child($ddwtos); + + // set source to populate the data + $ddwtos->set_source_table('question_ddwtos', array('questionid' => backup::VAR_PARENTID)); + + // don't need to annotate ids nor files + + return $plugin; + } + + /** + * Returns one array with filearea => mappingname elements for the qtype + * + * Used by {@link get_components_and_fileareas} to know about all the qtype + * files to be processed both in backup and restore. + */ + public static function get_qtype_fileareas() { + return array( + 'correctfeedback' => 'question_created', + 'partiallycorrectfeedback' => 'question_created', + 'incorrectfeedback' => 'question_created'); + } +} diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php new file mode 100755 index 00000000000..786ec45e5cd --- /dev/null +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php @@ -0,0 +1,136 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + + +/** + * restore plugin class that provides the necessary information + * needed to restore one ddwtos qtype plugin + * + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_qtype_ddwtos_plugin extends restore_qtype_plugin { + + /** + * Returns the paths to be handled by the plugin at question level + */ + protected function define_question_plugin_structure() { + + $paths = array(); + + // This qtype uses question_answers, add them + $this->add_question_question_answers($paths); + + // Add own qtype stuff + $elename = 'ddwtos'; + $elepath = $this->get_pathfor('/ddwtos'); // we used get_recommended_name() so this works + $paths[] = new restore_path_element($elename, $elepath); + + + return $paths; // And we return the interesting paths + } + + /** + * Process the qtype/ddwtos element + */ + public function process_ddwtos($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + // Detect if the question is created or mapped + $oldquestionid = $this->get_old_parentid('question'); + $newquestionid = $this->get_new_parentid('question'); + $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; + + // If the question has been created by restore, we need to create its question_ddwtos too + if ($questioncreated) { + // Adjust some columns + $data->questionid = $newquestionid; + // Insert record + $newitemid = $DB->insert_record('question_ddwtos', $data); + // Create mapping (needed for decoding links) + $this->set_mapping('question_ddwtos', $oldid, $newitemid); + } else { + // Nothing to remap if the question already existed + } + } + + /** + * Given one question_states record, return the answer + * recoded pointing to all the restored stuff for ddwtos questions + * + * answer are two (hypen speparated) lists of comma separated question_answers + * the first to specify the order of the answers and the second to specify the + * responses. Note the order list (the first one) can be optional + */ + public function recode_state_answer($state) { + $answer = $state->answer; + $orderarr = array(); + $responsesarr = array(); + $lists = explode(':', $answer); + // if only 1 list, answer is missing the order list, adjust + if (count($lists) == 1) { + $lists[1] = $lists[0]; // here we have the responses + $lists[0] = ''; // here we have the order + } + // Map order + foreach (explode(',', $lists[0]) as $id) { + if (!empty($id) && $newid = $this->get_mappingid('question_answer', $id)) { + $orderarr[] = $newid; + } + } + // Map responses + foreach (explode(',', $lists[1]) as $id) { + if (!empty($id) && $newid = $this->get_mappingid('question_answer', $id)) { + $responsesarr[] = $newid; + } + } + // Build the final answer, if not order, only responses + $result = ''; + if (empty($orderarr)) { + $result = implode(',', $responsesarr); + } else { + $result = implode(',', $orderarr) . ':' . implode(',', $responsesarr); + } + return $result; + } + + /** + * Return the contents of this qtype to be processed by the links decoder + */ + static public function define_decode_contents() { + + $contents = array(); + + $fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'); + $contents[] = new restore_decode_content('question_ddwtos', $fields, 'question_ddwtos'); + + return $contents; + } +} From c9826b0a304b87d9b4276fa0fa9403192001c9b8 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 23 Mar 2011 14:27:22 +0000 Subject: [PATCH 014/208] MDL-47494 ddimageortext: Question import, support for files in hints. Also fix some minor bugs and unit tests. --- question/type/ddimageortext/questiontype.php | 4 +- .../simpletest/testquestiontype.php | 37 +++++++++++-------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index aa03abee0f5..3bda33afea6 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -86,7 +86,7 @@ class qtype_ddwtos extends qtype_gapselect_base { foreach ($data['#']['dragbox'] as $dragboxxml) { $question->choices[] = array( 'answer' => $format->getpath($dragboxxml, array('#', 'text', 0, '#'), '', true), - 'draggroup' => $format->getpath($dragboxxml, array('#', 'group', 0, '#'), 1), + 'choicegroup' => $format->getpath($dragboxxml, array('#', 'group', 0, '#'), 1), 'infinite' => array_key_exists('infinite', $dragboxxml['#']), ); } @@ -98,7 +98,7 @@ class qtype_ddwtos extends qtype_gapselect_base { $options = unserialize(stripslashes($ans->feedback['text'])); $question->choices[] = array( 'answer' => $ans->answer, - 'draggroup' => $options->draggroup, + 'choicegroup' => $options->draggroup, 'infinite' => $options->infinite, ); } diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index 1fe729aa416..ee8dc7883fc 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -215,12 +215,14 @@ class qtype_ddwtos_test extends UnitTestCase { $expectedq->incorrectfeedback = array('text' => '

Your answer is incorrect.

', 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->choices = array( - array('answer' => 'Alpha', 'draggroup' => 1, 'infinite' => false), - array('answer' => 'Beta', 'draggroup' => 1, 'infinite' => false), - array('answer' => 'Gamma', 'draggroup' => 1, 'infinite' => true), + array('answer' => 'Alpha', 'choicegroup' => 1, 'infinite' => false), + array('answer' => 'Beta', 'choicegroup' => 1, 'infinite' => false), + array('answer' => 'Gamma', 'choicegroup' => 1, 'infinite' => true), ); - $expectedq->hint = array('Try again.', 'These are the first three letters of the Greek alphabet.'); + $expectedq->hint = array( + array('text' => 'Try again.', 'format' => FORMAT_MOODLE, 'files' => array()), + array('text' => 'These are the first three letters of the Greek alphabet.', 'format' => FORMAT_MOODLE, 'files' => array())); $expectedq->hintshownumcorrect = array(true, true); $expectedq->hintclearwrong = array(false, true); @@ -364,26 +366,29 @@ class qtype_ddwtos_test extends UnitTestCase { $expectedq->incorrectfeedback = array('text' => 'Your answer is incorrect.', 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->choices = array( - array('answer' => array('text' => 'hydrogen', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 1, 'infinite' => false), - array('answer' => array('text' => 'positive', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 1, 'infinite' => false), - array('answer' => array('text' => 'hydroxide', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 1, 'infinite' => false), - array('answer' => array('text' => 'negative', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 1, 'infinite' => false), - array('answer' => array('text' => '107', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 2, 'infinite' => false), - array('answer' => array('text' => '7', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 2, 'infinite' => false), - array('answer' => array('text' => '1', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 2, 'infinite' => false), - array('answer' => array('text' => '10-7', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 2, 'infinite' => false), - array('answer' => array('text' => 'greater', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 3, 'infinite' => false), - array('answer' => array('text' => 'less', 'format' => FORMAT_MOODLE, 'files' => array()), 'draggroup' => 3, 'infinite' => false), + array('answer' => array('text' => 'hydrogen', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 1, 'infinite' => false), + array('answer' => array('text' => 'positive', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 1, 'infinite' => false), + array('answer' => array('text' => 'hydroxide', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 1, 'infinite' => false), + array('answer' => array('text' => 'negative', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 1, 'infinite' => false), + array('answer' => array('text' => '107', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 2, 'infinite' => false), + array('answer' => array('text' => '7', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 2, 'infinite' => false), + array('answer' => array('text' => '1', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 2, 'infinite' => false), + array('answer' => array('text' => '10-7', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 2, 'infinite' => false), + array('answer' => array('text' => 'greater', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 3, 'infinite' => false), + array('answer' => array('text' => 'less', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 3, 'infinite' => false), ); $expectedq->hint = array( - 'You may wish to read Section 9 of Discovering Science Block 8.', - 'Any incorrect choices will be removed before your final try.' + array('text' => 'You may wish to read Section 9 of Discovering Science Block 8.', + 'format' => FORMAT_HTML, 'files' => array()), + array('text' => 'Any incorrect choices will be removed before your final try.', + 'format' => FORMAT_HTML, 'files' => array()), ); $expectedq->hintshownumcorrect = array(true, true); $expectedq->hintclearwrong = array(false, true); $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q); + $this->assertEqual($expectedq->hint, $q->hint); } public function test_xml_export() { From adebc4e51dfd374b133acdbea1569baa092abcc9 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 23 Mar 2011 16:22:25 +0000 Subject: [PATCH 015/208] MDL-47494 ddimageortext: Add lots of missing public/protected/private. --- .../backup/moodle2/restore_qtype_ddwtos_plugin.class.php | 2 +- question/type/ddimageortext/edit_ddwtos_form.php | 2 +- question/type/ddimageortext/questiontype.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php index 786ec45e5cd..1676ddbb227 100755 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php @@ -124,7 +124,7 @@ class restore_qtype_ddwtos_plugin extends restore_qtype_plugin { /** * Return the contents of this qtype to be processed by the links decoder */ - static public function define_decode_contents() { + public static function define_decode_contents() { $contents = array(); diff --git a/question/type/ddimageortext/edit_ddwtos_form.php b/question/type/ddimageortext/edit_ddwtos_form.php index f840a6ef919..fd2273b71b1 100755 --- a/question/type/ddimageortext/edit_ddwtos_form.php +++ b/question/type/ddimageortext/edit_ddwtos_form.php @@ -37,7 +37,7 @@ require_once($CFG->dirroot . '/question/type/gapselect/edit_form_base.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { - function qtype() { + public function qtype() { return 'ddwtos'; } diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 3bda33afea6..c990afab802 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -110,7 +110,7 @@ class qtype_ddwtos extends qtype_gapselect_base { return $question; } - function export_to_xml($question, $format, $extra = null) { + public function export_to_xml($question, $format, $extra = null) { $output = ''; $output .= ' ' . $question->options->shuffleanswers . "\n"; From 944829e93094ec0ca97494e6cd145c0674089b39 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 5 Apr 2011 17:54:39 +0100 Subject: [PATCH 016/208] MDL-47494 ddimageortext: Fix codechecker problems in match, description and ddwtos qtypes. --- .../restore_qtype_ddwtos_plugin.class.php | 3 - .../type/ddimageortext/edit_ddwtos_form.php | 4 +- question/type/ddimageortext/question.php | 2 +- question/type/ddimageortext/questiontype.php | 107 +------- question/type/ddimageortext/renderer.php | 11 +- question/type/ddimageortext/script.js | 6 +- .../ddimageortext/simpletest/testquestion.php | 6 +- .../simpletest/testquestiontype.php | 119 ++++++--- .../simpletest/testwalkthrough.php | 237 ++++++++++++------ 9 files changed, 270 insertions(+), 225 deletions(-) diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php index 1676ddbb227..ddf034ff12b 100755 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php @@ -50,7 +50,6 @@ class restore_qtype_ddwtos_plugin extends restore_qtype_plugin { $elepath = $this->get_pathfor('/ddwtos'); // we used get_recommended_name() so this works $paths[] = new restore_path_element($elename, $elepath); - return $paths; // And we return the interesting paths } @@ -76,8 +75,6 @@ class restore_qtype_ddwtos_plugin extends restore_qtype_plugin { $newitemid = $DB->insert_record('question_ddwtos', $data); // Create mapping (needed for decoding links) $this->set_mapping('question_ddwtos', $oldid, $newitemid); - } else { - // Nothing to remap if the question already existed } } diff --git a/question/type/ddimageortext/edit_ddwtos_form.php b/question/type/ddimageortext/edit_ddwtos_form.php index fd2273b71b1..d9840386f1d 100755 --- a/question/type/ddimageortext/edit_ddwtos_form.php +++ b/question/type/ddimageortext/edit_ddwtos_form.php @@ -51,7 +51,9 @@ class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { protected function choice_group($mform) { $grouparray = parent::choice_group($mform); - $grouparray[] = $mform->createElement('checkbox', 'infinite', ' ', get_string('infinite', 'qtype_ddwtos'), null, array('size'=>1, 'class'=>'tweakcss')); + $grouparray[] = $mform->createElement('checkbox', 'infinite', ' ', + get_string('infinite', 'qtype_ddwtos'), null, + array('size' => 1, 'class' => 'tweakcss')); return $grouparray; } } diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 6861858bbf3..6894248d242 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -57,7 +57,7 @@ class qtype_ddwtos_choice { $this->draggroup = $draggroup; $this->isinfinite = $isinfinite; } - public function choice_group(){ + public function choice_group() { return $this->draggroup; } } diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index c990afab802..aeff6ec3185 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -40,7 +40,7 @@ require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddwtos extends qtype_gapselect_base { - protected function choice_group_key(){ + protected function choice_group_key() { return 'draggroup'; } @@ -48,21 +48,22 @@ class qtype_ddwtos extends qtype_gapselect_base { return array('gapselect'); } - protected function choice_options_to_feedback($choice){ + protected function choice_options_to_feedback($choice) { $output = new stdClass(); $output->draggroup = $choice['choicegroup']; $output->infinite = !empty($choice['infinite']); return serialize($output); } - protected function feedback_to_choice_options($feedback){ + protected function feedback_to_choice_options($feedback) { $feedbackobj = unserialize($feedback); - return array('draggroup'=> $feedbackobj->draggroup, 'infinite'=> $feedbackobj->infinite); + return array('draggroup' => $feedbackobj->draggroup, 'infinite' => $feedbackobj->infinite); } - protected function make_choice($choicedata){ + protected function make_choice($choicedata) { $options = unserialize($choicedata->feedback); - return new qtype_ddwtos_choice($choicedata->answer, $options->draggroup, $options->infinite); + return new qtype_ddwtos_choice( + $choicedata->answer, $options->draggroup, $options->infinite); } public function import_from_xml($data, $question, $format, $extra=null) { @@ -113,7 +114,8 @@ class qtype_ddwtos extends qtype_gapselect_base { public function export_to_xml($question, $format, $extra = null) { $output = ''; - $output .= ' ' . $question->options->shuffleanswers . "\n"; + $output .= ' ' . $question->options->shuffleanswers . + "\n"; $output .= $format->write_combined_feedback($question->options); @@ -131,95 +133,4 @@ class qtype_ddwtos extends qtype_gapselect_base { return $output; } - - /* - * Backup the data in the question - * - * This is used in question/backuplib.php - */ - public function backup($bf, $preferences, $question, $level = 6) { - $status = true; - $ddwtos = get_records("question_ddwtos", "questionid", $question, "id"); - - //If there are ddwtos - if ($ddwtos) { - //Iterate over each ddwtos - foreach ($ddwtos as $ddws) { - $status = fwrite ($bf,start_tag("DDWORDSSENTENCES",$level,true)); - //Print oumultiresponse contents - fwrite ($bf,full_tag("SHUFFLEANSWERS",$level+1,false,$ddws->shuffleanswers)); - fwrite ($bf,full_tag("CORRECTFEEDBACK",$level+1,false,$ddws->correctfeedback)); - fwrite ($bf,full_tag("PARTIALLYCORRECTFEEDBACK",$level+1,false,$ddws->partiallycorrectfeedback)); - fwrite ($bf,full_tag("INCORRECTFEEDBACK",$level+1,false,$ddws->incorrectfeedback)); - fwrite ($bf,full_tag("SHOWNUMCORRECT",$level+1,false,$ddws->shownumcorrect)); - $status = fwrite ($bf,end_tag("DDWORDSSENTENCES",$level,true)); - } - - //Now print question_answers - $status = question_backup_answers($bf,$preferences,$question); - } - return $status; - } - - /** - * Restores the data in the question (This is used in question/restorelib.php) - * - */ - public function restore($old_question_id,$new_question_id,$info,$restore) { - $status = true; - - //Get the ddwtos array - $ddwtos = $info['#']['DDWORDSSENTENCES']; - - //Iterate over oumultiresponses - for($i = 0; $i < sizeof($ddwtos); $i++) { - $mul_info = $ddwtos[$i]; - - //Now, build the question_ddwtos record structure - $ddwtos = new stdClass(); - $ddwtos->questionid = $new_question_id; - $ddwtos->shuffleanswers = isset($mul_info['#']['SHUFFLEANSWERS']['0']['#'])?backup_todb($mul_info['#']['SHUFFLEANSWERS']['0']['#']):''; - if (array_key_exists("CORRECTFEEDBACK", $mul_info['#'])) { - $ddwtos->correctfeedback = backup_todb($mul_info['#']['CORRECTFEEDBACK']['0']['#']); - } else { - $ddwtos->correctfeedback = ''; - } - if (array_key_exists("PARTIALLYCORRECTFEEDBACK", $mul_info['#'])) { - $ddwtos->partiallycorrectfeedback = backup_todb($mul_info['#']['PARTIALLYCORRECTFEEDBACK']['0']['#']); - } else { - $ddwtos->partiallycorrectfeedback = ''; - } - if (array_key_exists("INCORRECTFEEDBACK", $mul_info['#'])) { - $ddwtos->incorrectfeedback = backup_todb($mul_info['#']['INCORRECTFEEDBACK']['0']['#']); - } else { - $ddwtos->incorrectfeedback = ''; - } - if (array_key_exists('SHOWNUMCORRECT', $mul_info['#'])) { - $ddwtos->shownumcorrect = backup_todb($mul_info['#']['SHOWNUMCORRECT']['0']['#']); - } else if (array_key_exists('CORRECTRESPONSESFEEDBACK', $mul_info['#'])) { - $ddwtos->shownumcorrect = backup_todb($mul_info['#']['CORRECTRESPONSESFEEDBACK']['0']['#']); - } else { - $ddwtos->shownumcorrect = 0; - } - - $newid = insert_record ("question_ddwtos",$ddwtos); - - //Do some output - if (($i+1) % 50 == 0) { - if (!defined('RESTORE_SILENTLY')) { - echo "."; - if (($i+1) % 1000 == 0) { - echo "
"; - } - } - backup_flush(300); - } - - if (!$newid) { - $status = false; - } - } - return $status; - } - } diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 9c127b6fc27..5e4b772784e 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -38,11 +38,12 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); */ class qtype_ddwtos_renderer extends qtype_elements_embedded_in_question_text_renderer { - protected function qtext_classname(){ + protected function qtext_classname() { return 'qtext ddwtos_questionid_for_javascript'; } - protected function post_qtext_elements(question_attempt $qa, question_display_options $options){ + protected function post_qtext_elements(question_attempt $qa, + question_display_options $options) { $result = ''; $question = $qa->get_question(); $dragboxs = ''; @@ -71,7 +72,8 @@ class qtype_ddwtos_renderer extends qtype_elements_embedded_in_question_text_ren return ' ' . $string . ' '; } - protected function embedded_element(question_attempt $qa, $place, question_display_options $options) { + protected function embedded_element(question_attempt $qa, $place, + question_display_options $options) { $question = $qa->get_question(); $group = $question->places[$place]; $boxcontents = $this->dodgy_ie_fix(' '); @@ -94,7 +96,8 @@ class qtype_ddwtos_renderer extends qtype_elements_embedded_in_question_text_ren $response = $qa->get_last_qt_data(); $fieldname = $question->field($place); if (array_key_exists($fieldname, $response)) { - $fraction = (int) ($response[$fieldname] == $question->get_right_choice_for($place)); + $fraction = (int) ($response[$fieldname] == + $question->get_right_choice_for($place)); $attributes['class'] .= ' ' . $this->feedback_class($fraction); $feedbackimage = $this->feedback_image($fraction); } diff --git a/question/type/ddimageortext/script.js b/question/type/ddimageortext/script.js index bf84942f3a7..8e5f2d38980 100755 --- a/question/type/ddimageortext/script.js +++ b/question/type/ddimageortext/script.js @@ -104,7 +104,6 @@ var ddwtos_currentzindex = 10; initPlayer : function(id, sGroup, config) { this.isTarget = false; this.currentPos = YAHOO.util.Dom.getXY(this.getEl()); - }, //Abstract method called after a drag/drop object is clicked and the drag or mousedown time thresholds have beeen met. @@ -178,7 +177,6 @@ var ddwtos_currentzindex = 10; YAHOO.util.Event.onDOMReady(YAHOO.example.DDApp.init, YAHOO.example.DDApp, true); - // Objects/////////////////////////////////////////////////////////////////// var Questions = new Object(); @@ -300,7 +298,9 @@ var ddwtos_currentzindex = 10; var slot = slots[i]; var hiddenElement = document.getElementById(slot.id + '_hidden'); - if (!hiddenElement) continue; + if (!hiddenElement) { + continue; + } // get group var group = getGroupForThis(slot.id); diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index 9bce14087fa..a32cfda3375 100755 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -41,7 +41,8 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_question_summary() { $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); - $this->assertEqual('The [[1]] brown [[2]] jumped over the [[3]] dog.; [[1]] -> {quick / slow}; [[2]] -> {fox / dog}; [[3]] -> {lazy / assiduous}', + $this->assertEqual('The [[1]] brown [[2]] jumped over the [[3]] dog.; ' . + '[[1]] -> {quick / slow}; [[2]] -> {fox / dog}; [[3]] -> {lazy / assiduous}', $dd->get_question_summary()); } @@ -125,7 +126,8 @@ class qtype_ddwtos_question_test extends UnitTestCase { $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array(2, 4), - $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); + $dd->get_num_parts_right(array( + 'p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); } public function test_get_expected_data() { diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index ee8dc7883fc..e87315c6e70 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -89,12 +89,18 @@ class qtype_ddwtos_test extends UnitTestCase { test_question_maker::set_standard_combined_feedback_fields($dd->options); $dd->options->answers = array( - (object) array('answer' => 'quick', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), - (object) array('answer' => 'fox', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), - (object) array('answer' => 'lazy', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), - (object) array('answer' => 'assiduous', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), - (object) array('answer' => 'dog', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), - (object) array('answer' => 'slow', 'feedback' => 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), + (object) array('answer' => 'quick', 'feedback' => + 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), + (object) array('answer' => 'fox', 'feedback' => + 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), + (object) array('answer' => 'lazy', 'feedback' => + 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), + (object) array('answer' => 'assiduous', 'feedback' => + 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), + (object) array('answer' => 'dog', 'feedback' => + 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), + (object) array('answer' => 'slow', 'feedback' => + 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), ); return $dd; @@ -209,10 +215,14 @@ class qtype_ddwtos_test extends UnitTestCase { $expectedq->penalty = 0.3333333; $expectedq->shuffleanswers = 1; - $expectedq->correctfeedback = array('text' => '

Your answer is correct.

', 'format' => FORMAT_MOODLE, 'files' => array()); - $expectedq->partiallycorrectfeedback = array('text' => '

Your answer is partially correct.

', 'format' => FORMAT_MOODLE, 'files' => array()); + $expectedq->correctfeedback = array('text' => '

Your answer is correct.

', + 'format' => FORMAT_MOODLE, 'files' => array()); + $expectedq->partiallycorrectfeedback = array( + 'text' => '

Your answer is partially correct.

', + 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->shownumcorrect = true; - $expectedq->incorrectfeedback = array('text' => '

Your answer is incorrect.

', 'format' => FORMAT_MOODLE, 'files' => array()); + $expectedq->incorrectfeedback = array('text' => '

Your answer is incorrect.

', + 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->choices = array( array('answer' => 'Alpha', 'choicegroup' => 1, 'infinite' => false), @@ -222,7 +232,8 @@ class qtype_ddwtos_test extends UnitTestCase { $expectedq->hint = array( array('text' => 'Try again.', 'format' => FORMAT_MOODLE, 'files' => array()), - array('text' => 'These are the first three letters of the Greek alphabet.', 'format' => FORMAT_MOODLE, 'files' => array())); + array('text' => 'These are the first three letters of the Greek alphabet.', + 'format' => FORMAT_MOODLE, 'files' => array())); $expectedq->hintshownumcorrect = array(true, true); $expectedq->hintclearwrong = array(false, true); @@ -235,11 +246,19 @@ class qtype_ddwtos_test extends UnitTestCase { QDandD1 Base definition - <p>Drag and drop the words from the list below to fill the blank spaces and correctly complete the sentence.</p> <p>At 25°C all aqueous basic solutions have [[1]] ion concentrations less than [[8]]<br />mol litre<sup>-1</sup> and pH values [[9]] than [[6]].</p> <!--DONOTCLEAN--> + <p>Drag and drop the words from the list below to fill the blank spaces ' . + 'and correctly complete the sentence.</p> <p>At 25°C all aqueous basic ' . + 'solutions have [[1]] ion concentrations less than [[8]]<br />mol ' . + 'litre<sup>-1</sup> and pH values [[9]] than [[6]].</p> ' . + '<!--DONOTCLEAN--> - <p>At 25 &#xB0;C all aqueous basic solutions have hydrogen ion concentrations less than 10<sup>&#x2212;7</sup> mol litre<sup>&#x2212;1</sup> and pH values greater than 7.</p> <p>See Section 9 of S103 <em class="italic">Discovering Science</em> Block 8.</p> + <p>At 25 &#xB0;C all aqueous basic solutions have hydrogen ion ' . + 'concentrations less than 10<sup>&#x2212;7</sup> mol ' . + 'litre<sup>&#x2212;1</sup> and pH values greater than 7.</p> ' . + '<p>See Section 9 of S103 <em class="italic">Discovering ' . + 'Science</em> Block 8.</p> 1 0.33 @@ -332,7 +351,8 @@ class qtype_ddwtos_test extends UnitTestCase { 1 0 - You may wish to read Section 9 of <em class="italic">Discovering Science</em> Block 8. + You may wish to read Section 9 of <em ' . + 'class="italic">Discovering Science</em> Block 8.
@@ -352,36 +372,57 @@ class qtype_ddwtos_test extends UnitTestCase { $expectedq = new stdClass(); $expectedq->qtype = 'ddwtos'; $expectedq->name = 'QDandD1 Base definition'; - $expectedq->questiontext = '

Drag and drop the words from the list below to fill the blank spaces and correctly complete the sentence.

At 25°C all aqueous basic solutions have [[1]] ion concentrations less than [[8]]
mol litre-1 and pH values [[9]] than [[6]].

'; + $expectedq->questiontext = '

Drag and drop the words from the list below ' . + 'to fill the blank spaces and correctly complete the sentence.

' . + '

At 25°C all aqueous basic solutions have [[1]] ion concentrations ' . + 'less than [[8]]
mol litre-1 and pH values [[9]] than [[6]].

' . + ''; $expectedq->questiontextformat = FORMAT_HTML; - $expectedq->generalfeedback = '

At 25 °C all aqueous basic solutions have hydrogen ion concentrations less than 10−7 mol litre−1 and pH values greater than 7.

See Section 9 of S103 Discovering Science Block 8.

'; + $expectedq->generalfeedback = '

At 25 °C all aqueous basic solutions ' . + 'have hydrogen ion concentrations less than 10−7 ' . + 'mol litre−1 and pH values greater than 7.

See ' . + 'Section 9 of S103 Discovering Science Block 8.

'; $expectedq->defaultmark = 1; $expectedq->length = 1; $expectedq->penalty = 0.3333333; $expectedq->shuffleanswers = 0; - $expectedq->correctfeedback = array('text' => 'Your answer is correct.', 'format' => FORMAT_MOODLE, 'files' => array()); - $expectedq->partiallycorrectfeedback = array('text' => 'Your answer is partially correct.', 'format' => FORMAT_MOODLE, 'files' => array()); + $expectedq->correctfeedback = array('text' => 'Your answer is correct.', + 'format' => FORMAT_MOODLE, 'files' => array()); + $expectedq->partiallycorrectfeedback = array( + 'text' => 'Your answer is partially correct.', + 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->shownumcorrect = true; - $expectedq->incorrectfeedback = array('text' => 'Your answer is incorrect.', 'format' => FORMAT_MOODLE, 'files' => array()); + $expectedq->incorrectfeedback = array('text' => 'Your answer is incorrect.', + 'format' => FORMAT_MOODLE, 'files' => array()); $expectedq->choices = array( - array('answer' => array('text' => 'hydrogen', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 1, 'infinite' => false), - array('answer' => array('text' => 'positive', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 1, 'infinite' => false), - array('answer' => array('text' => 'hydroxide', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 1, 'infinite' => false), - array('answer' => array('text' => 'negative', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 1, 'infinite' => false), - array('answer' => array('text' => '107', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 2, 'infinite' => false), - array('answer' => array('text' => '7', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 2, 'infinite' => false), - array('answer' => array('text' => '1', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 2, 'infinite' => false), - array('answer' => array('text' => '10-7', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 2, 'infinite' => false), - array('answer' => array('text' => 'greater', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 3, 'infinite' => false), - array('answer' => array('text' => 'less', 'format' => FORMAT_MOODLE, 'files' => array()), 'choicegroup' => 3, 'infinite' => false), + array('answer' => array('text' => 'hydrogen', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 1, 'infinite' => false), + array('answer' => array('text' => 'positive', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 1, 'infinite' => false), + array('answer' => array('text' => 'hydroxide', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 1, 'infinite' => false), + array('answer' => array('text' => 'negative', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 1, 'infinite' => false), + array('answer' => array('text' => '107', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 2, 'infinite' => false), + array('answer' => array('text' => '7', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 2, 'infinite' => false), + array('answer' => array('text' => '1', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 2, 'infinite' => false), + array('answer' => array('text' => '10-7', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 2, 'infinite' => false), + array('answer' => array('text' => 'greater', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 3, 'infinite' => false), + array('answer' => array('text' => 'less', 'format' => FORMAT_MOODLE, + 'files' => array()), 'choicegroup' => 3, 'infinite' => false), ); - $expectedq->hint = array( - array('text' => 'You may wish to read Section 9 of Discovering Science Block 8.', + $expectedq->hint = array(array('text' => 'You may wish to read Section 9 of ' . + 'Discovering Science Block 8.', 'format' => FORMAT_HTML, 'files' => array()), - array('text' => 'Any incorrect choices will be removed before your final try.', + array('text' => 'Any incorrect choices will be removed before your final try.', 'format' => FORMAT_HTML, 'files' => array()), ); $expectedq->hintshownumcorrect = array(true, true); @@ -416,14 +457,22 @@ class qtype_ddwtos_test extends UnitTestCase { $qdata->options->incorrectfeedbackformat = FORMAT_MOODLE; $qdata->options->answers = array( - 13 => new question_answer(13, 'Alpha', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', FORMAT_MOODLE), - 14 => new question_answer(14, 'Beta', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', FORMAT_MOODLE), - 15 => new question_answer(15, 'Gamma', 0, 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:1;}', FORMAT_MOODLE), + 13 => new question_answer(13, 'Alpha', 0, + 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', + FORMAT_MOODLE), + 14 => new question_answer(14, 'Beta', 0, + 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', + FORMAT_MOODLE), + 15 => new question_answer(15, 'Gamma', 0, + 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:1;}', + FORMAT_MOODLE), ); $qdata->hints = array( 1 => new question_hint_with_parts(1, 'Try again.', FORMAT_MOODLE, true, false), - 2 => new question_hint_with_parts(2, 'These are the first three letters of the Greek alphabet.', FORMAT_MOODLE, true, true), + 2 => new question_hint_with_parts(2, + 'These are the first three letters of the Greek alphabet.', + FORMAT_MOODLE, true, true), ); $exporter = new qformat_xml(); diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index 38ead171d94..79421f3d88d 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -39,7 +39,8 @@ require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); */ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { - protected function get_contains_drop_box_expectation($place, $group, $readonly, $stateclass = '0') { + protected function get_contains_drop_box_expectation($place, $group, $readonly, + $stateclass = '0') { $qa = $this->quba->get_question_attempt($this->slot); $expectedattrs = array( @@ -77,9 +78,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), @@ -95,9 +99,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '2'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '2'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '2'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation(), @@ -117,7 +124,8 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_submit_button_expectation(false), $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), - new PatternExpectation('/' . preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + new PatternExpectation('/' . + preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), $this->get_contains_hint_expectation('This is the first hint')); // Do try again. @@ -130,9 +138,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '2'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '2'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '2'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation(), @@ -175,9 +186,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_does_not_contain_feedback_expectation()); // Save a partial answer. @@ -190,9 +204,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '2'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); @@ -206,9 +223,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '1'), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); @@ -249,9 +269,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); $this->check_step_count(1); @@ -266,9 +289,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); $this->check_step_count(1); @@ -299,9 +325,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); @@ -315,9 +344,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); @@ -339,8 +371,10 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { // Create a drag-and-drop question. $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->hints = array( - new question_hint_with_parts(1, 'This is the first hint.', FORMAT_MOODLE, true, true), - new question_hint_with_parts(2, 'This is the second hint.', FORMAT_MOODLE, true, true), + new question_hint_with_parts(1, 'This is the first hint.', + FORMAT_MOODLE, true, true), + new question_hint_with_parts(2, 'This is the second hint.', + FORMAT_MOODLE, true, true), ); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'interactive', 9); @@ -354,9 +388,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), @@ -376,18 +413,23 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_submit_button_expectation(false), $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), - new PatternExpectation('/' . preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + new PatternExpectation('/' . + preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), $this->get_contains_hint_expectation('This is the first hint'), $this->get_contains_num_parts_correct(2), $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0')); + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0')); // Check that extract responses will return the reset data. $prefix = $this->quba->get_field_prefix($this->slot); $this->assertEqual(array('p1' => '1', 'p2' => '1'), - $this->quba->extract_responses($this->slot, array($prefix . 'p1' => '1', $prefix . 'p2' => '1', '-tryagain' => 1))); + $this->quba->extract_responses($this->slot, + array($prefix . 'p1' => '1', $prefix . 'p2' => '1', '-tryagain' => 1))); // Do try again. $this->process_submission(array('p1' => '1', 'p2' => '1', '-tryagain' => 1)); @@ -399,9 +441,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_try_again_button_expectation(), $this->get_does_not_contain_correctness_expectation(), @@ -422,13 +467,17 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_submit_button_expectation(false), $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), - new PatternExpectation('/' . preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + new PatternExpectation('/' . + preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), $this->get_contains_hint_expectation('This is the second hint'), $this->get_contains_num_parts_correct(2), $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '1')); + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '1')); // Do try again. $this->process_submission(array('p1' => '1', 'p3' => '1', '-tryagain' => 1)); @@ -440,9 +489,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '1'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_try_again_button_expectation(), $this->get_does_not_contain_correctness_expectation(), @@ -466,9 +518,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_no_hint_visible_expectation(), $this->get_does_not_contain_num_parts_correct(), $this->get_contains_standard_correct_combined_feedback_expectation(), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '1'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '1')); + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '1')); } public function test_interactive_correct_no_submit() { @@ -476,8 +531,10 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { // Create a drag-and-drop question. $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->hints = array( - new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), - new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), + new question_hint_with_parts(23, 'This is the first hint.', + FORMAT_MOODLE, false, false), + new question_hint_with_parts(24, 'This is the second hint.', + FORMAT_MOODLE, true, true), ); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'interactive', 3); @@ -489,9 +546,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), @@ -527,8 +587,10 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { // Create a drag-and-drop question. $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); $dd->hints = array( - new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), - new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), + new question_hint_with_parts(23, 'This is the first hint.', + FORMAT_MOODLE, false, false), + new question_hint_with_parts(24, 'This is the second hint.', + FORMAT_MOODLE, true, true), ); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'interactive', 3); @@ -540,9 +602,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), @@ -592,9 +657,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), @@ -625,9 +693,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(2), @@ -647,9 +718,12 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', '0'), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '0'), $this->get_does_not_contain_feedback_expectation()); // Save a partial answer. @@ -662,9 +736,15 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), $this->get_contains_drop_box_expectation('p3', 3, false), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p1', $dd->get_right_choice_for(1)), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p2', $dd->get_right_choice_for(2)), - $this->get_contains_hidden_expectation($this->quba->get_field_prefix($this->slot) . 'p3', $dd->get_right_choice_for(3)), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', + $dd->get_right_choice_for(1)), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', + $dd->get_right_choice_for(2)), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', + $dd->get_right_choice_for(3)), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); @@ -681,6 +761,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), $this->get_contains_correct_expectation(), - new PatternExpectation('/' . preg_quote('The [quick] brown [fox] jumped over the [lazy] dog.') . '/')); + new PatternExpectation('/' . + preg_quote('The [quick] brown [fox] jumped over the [lazy] dog.') . '/')); } } From 46b0a9735c5cd2d6ff33b8f5f23af8293cabce55 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 29 Mar 2011 16:29:54 +0100 Subject: [PATCH 017/208] MDL-47494 ddimageortext: Better way of handling the creation of test questions for different question types. --- .../type/ddimageortext/simpletest/helper.php | 10 +++-- .../ddimageortext/simpletest/testquestion.php | 40 +++++++++---------- .../simpletest/testquestiontype.php | 4 +- .../simpletest/testwalkthrough.php | 18 ++++----- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/simpletest/helper.php index 37f28439bc6..d988693ac72 100755 --- a/question/type/ddimageortext/simpletest/helper.php +++ b/question/type/ddimageortext/simpletest/helper.php @@ -34,11 +34,15 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos_test_helper { +class qtype_ddwtos_test_helper extends question_test_helper { + public function get_test_questions() { + return array('fox', 'maths'); + } + /** * @return qtype_ddwtos_question */ - public static function make_a_ddwtos_question() { + public function make_ddwtos_question_fox() { question_bank::load_question_definition_classes('ddwtos'); $dd = new qtype_ddwtos_question(); @@ -75,7 +79,7 @@ class qtype_ddwtos_test_helper { /** * @return qtype_ddwtos_question */ - public static function make_a_maths_ddwtos_question() { + public function make_ddwtos_question_maths() { question_bank::load_question_definition_classes('ddwtos'); $dd = new qtype_ddwtos_question(); diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index a32cfda3375..2a5103024a0 100755 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -40,21 +40,21 @@ require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_question_summary() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $this->assertEqual('The [[1]] brown [[2]] jumped over the [[3]] dog.; ' . '[[1]] -> {quick / slow}; [[2]] -> {fox / dog}; [[3]] -> {lazy / assiduous}', $dd->get_question_summary()); } public function test_get_question_summary_maths() { - $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos', 'maths'); $this->assertEqual('Fill in the operators to make this equation work: ' . '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3; [[1]] -> {+ / - / * / /}', $dd->get_question_summary()); } public function test_summarise_response() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -63,7 +63,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_summarise_response_maths() { - $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -72,17 +72,17 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_random_guess_score() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $this->assertEqual(0.5, $dd->get_random_guess_score()); } public function test_get_random_guess_score_maths() { - $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos', 'maths'); $this->assertEqual(0.25, $dd->get_random_guess_score()); } public function test_get_right_choice_for() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -91,7 +91,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_right_choice_for_maths() { - $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -100,7 +100,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_clear_wrong_from_response() { - $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -110,7 +110,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_num_parts_right() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -121,7 +121,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_num_parts_right_maths() { - $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -131,7 +131,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_expected_data() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->start_attempt(new question_attempt_step()); $this->assertEqual(array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT), @@ -139,7 +139,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_correct_response() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -148,7 +148,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_correct_response_maths() { - $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -157,7 +157,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_is_same_response() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->start_attempt(new question_attempt_step()); $this->assertTrue($dd->is_same_response( @@ -181,7 +181,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { array('p1' => '1', 'p2' => '2', 'p3' => '2'))); } public function test_is_complete_response() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->start_attempt(new question_attempt_step()); $this->assertFalse($dd->is_complete_response(array())); @@ -193,7 +193,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_is_gradable_response() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->start_attempt(new question_attempt_step()); $this->assertFalse($dd->is_gradable_response(array())); @@ -207,7 +207,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_grading() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -220,7 +220,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_grading_maths() { - $dd = qtype_ddwtos_test_helper::make_a_maths_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); @@ -233,7 +233,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_classify_response() { - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step()); diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index e87315c6e70..42e4d17ec77 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -56,7 +56,7 @@ class qtype_ddwtos_test extends UnitTestCase { /** * @return object the data to construct a question like - * {@link qtype_ddwtos_test_helper::make_a_ddwtos_question()}. + * {@link qtype_ddwtos_test_helper::make_ddwtos_question_fox()}. */ protected function get_test_question_data() { global $USER; @@ -117,7 +117,7 @@ class qtype_ddwtos_test extends UnitTestCase { public function test_initialise_question_instance() { $qdata = $this->get_test_question_data(); - $expected = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $expected = test_question_maker::make_question('ddwtos'); $expected->stamp = $qdata->stamp; $expected->version = $qdata->version; diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index 79421f3d88d..11adf6388b0 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -63,7 +63,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_behaviour() { // Create a drag-and-drop question. - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->hints = array( new question_hint_with_parts(13, 'This is the first hint.', FORMAT_HTML, false, false), new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true), @@ -175,7 +175,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_deferred_feedback() { // Create a drag-and-drop question. - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'deferredfeedback', 3); @@ -258,7 +258,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_deferred_feedback_unanswered() { // Create a drag-and-drop question. - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'deferredfeedback', 3); @@ -314,7 +314,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_deferred_feedback_partial_answer() { // Create a drag-and-drop question. - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'deferredfeedback', 3); @@ -369,7 +369,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_grading() { // Create a drag-and-drop question. - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->hints = array( new question_hint_with_parts(1, 'This is the first hint.', FORMAT_MOODLE, true, true), @@ -529,7 +529,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_correct_no_submit() { // Create a drag-and-drop question. - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->hints = array( new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), @@ -585,7 +585,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_partial_no_submit() { // Create a drag-and-drop question. - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->hints = array( new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), @@ -641,7 +641,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_no_right_clears() { // Create a drag-and-drop question. - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $dd->hints = array( new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, true), new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), @@ -708,7 +708,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_display_of_right_answer_when_shuffled() { // Create a drag-and-drop question. - $dd = qtype_ddwtos_test_helper::make_a_ddwtos_question(); + $dd = test_question_maker::make_question('ddwtos'); $this->start_attempt_at_question($dd, 'deferredfeedback', 3); // Check the initial state. From 332641ac7243ae67ab9b7dd7a0afb852a8651e25 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 27 Apr 2011 18:00:14 +0100 Subject: [PATCH 018/208] MDL-47494 ddimageortext: numerical qtype: assorted changes 1. database upgrade to merge instructions into the questiontext field, and remove the UNITDISPLAY option. 2. Changes to the validation in deferred feedback mode, so students are warned about incomplete answers. 3. Using this to wark students if they enter an answer that is not recognised as a number. --- question/type/ddimageortext/simpletest/testwalkthrough.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index 11adf6388b0..1435dd1e0f5 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -198,7 +198,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->process_submission(array('p1' => '1', 'p2' => '2')); // Verify. - $this->check_current_state(question_state::$todo); + $this->check_current_state(question_state::$invalid); $this->check_current_mark(null); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), @@ -338,7 +338,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { $this->process_submission(array('p1' => '1', 'p2' => '0', 'p3' => '0')); // Verify. - $this->check_current_state(question_state::$todo); + $this->check_current_state(question_state::$invalid); $this->check_current_mark(null); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), From f32281ebf6e41e10b0183f1f49b27166911ac896 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 5 May 2011 21:26:25 +0100 Subject: [PATCH 019/208] MDL-47494 ddimageortext: Finished backup and restore of attempt data. Yay --- .../restore_qtype_ddwtos_plugin.class.php | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php index ddf034ff12b..51981fa96f1 100755 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php @@ -78,46 +78,6 @@ class restore_qtype_ddwtos_plugin extends restore_qtype_plugin { } } - /** - * Given one question_states record, return the answer - * recoded pointing to all the restored stuff for ddwtos questions - * - * answer are two (hypen speparated) lists of comma separated question_answers - * the first to specify the order of the answers and the second to specify the - * responses. Note the order list (the first one) can be optional - */ - public function recode_state_answer($state) { - $answer = $state->answer; - $orderarr = array(); - $responsesarr = array(); - $lists = explode(':', $answer); - // if only 1 list, answer is missing the order list, adjust - if (count($lists) == 1) { - $lists[1] = $lists[0]; // here we have the responses - $lists[0] = ''; // here we have the order - } - // Map order - foreach (explode(',', $lists[0]) as $id) { - if (!empty($id) && $newid = $this->get_mappingid('question_answer', $id)) { - $orderarr[] = $newid; - } - } - // Map responses - foreach (explode(',', $lists[1]) as $id) { - if (!empty($id) && $newid = $this->get_mappingid('question_answer', $id)) { - $responsesarr[] = $newid; - } - } - // Build the final answer, if not order, only responses - $result = ''; - if (empty($orderarr)) { - $result = implode(',', $responsesarr); - } else { - $result = implode(',', $orderarr) . ':' . implode(',', $responsesarr); - } - return $result; - } - /** * Return the contents of this qtype to be processed by the links decoder */ From bc4f8bcb79e2b07e34c5034af8b01b4ba3ec784b Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 12 May 2011 23:18:47 +0100 Subject: [PATCH 020/208] MDL-47494 ddimageortext: MDL-27408 update all question and quiz plugin version.php files. --- question/type/ddimageortext/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 94b1fbeabdf..3b9e628090c 100755 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -26,5 +26,5 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2011020100; -$plugin->requires = 2011011200; +$plugin->version = 2011051200; +$plugin->requires = 2011051212; From fa4a86a3e5d446c1cedeb78101c7bbad64f1ebeb Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Sat, 14 May 2011 22:53:25 +0100 Subject: [PATCH 021/208] MDL-47494 ddimageortext: Fix some more codechecker issues. --- .../backup/moodle2/backup_qtype_ddwtos_plugin.class.php | 1 - .../backup/moodle2/restore_qtype_ddwtos_plugin.class.php | 1 - question/type/ddimageortext/edit_ddwtos_form.php | 1 - question/type/ddimageortext/lang/en/qtype_ddwtos.php | 1 - question/type/ddimageortext/question.php | 1 - question/type/ddimageortext/questiontype.php | 1 - question/type/ddimageortext/renderer.php | 1 - question/type/ddimageortext/simpletest/helper.php | 1 - question/type/ddimageortext/simpletest/testquestion.php | 1 - question/type/ddimageortext/simpletest/testquestiontype.php | 1 - question/type/ddimageortext/simpletest/testwalkthrough.php | 1 - question/type/ddimageortext/version.php | 1 - 12 files changed, 12 deletions(-) diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php index a86b6b33655..89cb186f836 100755 --- a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php @@ -1,5 +1,4 @@ Date: Sun, 15 May 2011 23:07:56 +0100 Subject: [PATCH 022/208] MDL-47494 ddimageortext: Add a readme file. --- question/type/ddimageortext/README.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 question/type/ddimageortext/README.txt diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt new file mode 100644 index 00000000000..5a8629c0845 --- /dev/null +++ b/question/type/ddimageortext/README.txt @@ -0,0 +1,11 @@ +Drag-and-drop, words to sentences question type + +This question type requires that gapselect question type +https://github.com/timhunt/moodle-qtype_gapselect/ +to be installed in order to work. + +This question type was originally the work of Mahmoud Kassaei at +the Open University (http://www.open.ac.uk/). +It was updated to work with the Moodle 2.1 question engine by Tim Hunt. +It was then refactored extenstively by Jamie Pratt (http://jamiep.org/) +as part of creating the gapselect question type. From 47b5deb6aed2e1aac1112a040db37e23d8a449d0 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 16 May 2011 05:01:14 -0700 Subject: [PATCH 023/208] MDL-47494 ddimageortext: Updated the readme file to add install instructions. --- question/type/ddimageortext/README.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index 5a8629c0845..dc15e0fe630 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -9,3 +9,15 @@ the Open University (http://www.open.ac.uk/). It was updated to work with the Moodle 2.1 question engine by Tim Hunt. It was then refactored extenstively by Jamie Pratt (http://jamiep.org/) as part of creating the gapselect question type. + + +This question type is compatible with Moodle 2.1+. + +To install using git, type this command in the root of your Moodle install + git clone git://github.com/timhunt/moodle-qtype_ddwtos.git question/type/ddwtos +Then add question/type/ddwtosto your git ignore. + +Alternatively, download the zip from + https://github.com/timhunt/moodle-qtype_ddwtos/zipball/master +unzip it into the question/type folder, and then rename the new folder to +ddwtos. From a8448b3f797b3fd4d1b6467e85862756bdba2aa4 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 26 May 2011 22:08:03 +0100 Subject: [PATCH 024/208] MDL-47494 ddimageortext: Implement the new variants handling. --- .../ddimageortext/simpletest/testquestion.php | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index c7f27d76db6..58fea4279cf 100755 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -55,7 +55,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_summarise_response() { $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual('{quick} {fox} {lazy}', $dd->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); @@ -64,7 +64,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_summarise_response_maths() { $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual('{+} {-} {+} {-}', $dd->summarise_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); @@ -83,7 +83,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_right_choice_for() { $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(1, $dd->get_right_choice_for(1)); $this->assertEqual(1, $dd->get_right_choice_for(2)); @@ -92,7 +92,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_right_choice_for_maths() { $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(1, $dd->get_right_choice_for(1)); $this->assertEqual(2, $dd->get_right_choice_for(2)); @@ -101,7 +101,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_clear_wrong_from_response() { $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $initialresponse = array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'); $this->assertEqual(array('p1' => '1', 'p2' => '0', 'p3' => '1', 'p4' => '0'), @@ -111,7 +111,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_num_parts_right() { $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array(2, 3), $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '2'))); @@ -122,7 +122,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_num_parts_right_maths() { $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array(2, 4), $dd->get_num_parts_right(array( @@ -131,7 +131,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_expected_data() { $dd = test_question_maker::make_question('ddwtos'); - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT), $dd->get_expected_data()); @@ -140,7 +140,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_correct_response() { $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array('p1' => '1', 'p2' => '1', 'p3' => '1'), $dd->get_correct_response()); @@ -149,7 +149,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_get_correct_response_maths() { $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'), $dd->get_correct_response()); @@ -157,7 +157,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_is_same_response() { $dd = test_question_maker::make_question('ddwtos'); - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertTrue($dd->is_same_response( array(), @@ -181,7 +181,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_is_complete_response() { $dd = test_question_maker::make_question('ddwtos'); - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertFalse($dd->is_complete_response(array())); $this->assertFalse($dd->is_complete_response( @@ -193,7 +193,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_is_gradable_response() { $dd = test_question_maker::make_question('ddwtos'); - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertFalse($dd->is_gradable_response(array())); $this->assertFalse($dd->is_gradable_response( @@ -208,7 +208,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_grading() { $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array(1, question_state::$gradedright), $dd->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); @@ -221,7 +221,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_grading_maths() { $dd = test_question_maker::make_question('ddwtos', 'maths'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array(1, question_state::$gradedright), $dd->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); @@ -234,7 +234,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { public function test_classify_response() { $dd = test_question_maker::make_question('ddwtos'); $dd->shufflechoices = false; - $dd->start_attempt(new question_attempt_step()); + $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array( 1 => new question_classified_response(1, 'quick', 1), From 339481f106da4414bd130de4d16572a2240c6d88 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 21 Jun 2011 19:37:24 +0700 Subject: [PATCH 025/208] MDL-47494 ddimageortext: NOBUG new README.txt for new question type ddimagetoimage - Darg and Drop Image to Image. I forked the existing ddwtos question type which has a lot in common with this new question type to give me a quick start setting up the needed infrastructure for a Moodle question type plug in. --- question/type/ddimageortext/README.txt | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index dc15e0fe630..def8b611eb4 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -1,23 +1,18 @@ -Drag-and-drop, words to sentences question type +A drag-and-drop, images to images question type This question type requires that gapselect question type https://github.com/timhunt/moodle-qtype_gapselect/ to be installed in order to work. -This question type was originally the work of Mahmoud Kassaei at -the Open University (http://www.open.ac.uk/). -It was updated to work with the Moodle 2.1 question engine by Tim Hunt. -It was then refactored extenstively by Jamie Pratt (http://jamiep.org/) -as part of creating the gapselect question type. - +This question type was written by Jamie Pratt (http://jamiep.org/). This question type is compatible with Moodle 2.1+. To install using git, type this command in the root of your Moodle install - git clone git://github.com/timhunt/moodle-qtype_ddwtos.git question/type/ddwtos -Then add question/type/ddwtosto your git ignore. + git clone git://github.com/jamiepratt/moodle-qtype_ddimagetoimage.git question/type/ddimagetoimage +Then add question/type/ddimagetoimage to your git ignore. Alternatively, download the zip from - https://github.com/timhunt/moodle-qtype_ddwtos/zipball/master + https://github.com/jamiepratt/moodle-qtype_ddimagetoimage/zipball/master unzip it into the question/type folder, and then rename the new folder to -ddwtos. +ddimagetoimage. From a70985115572cc20966ec716bab059188d85d146 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 21 Jun 2011 19:45:14 +0700 Subject: [PATCH 026/208] MDL-47494 ddimageortext: NOBUG search and replace for ddwtos, replaced with ddimagetoimage --- .../backup_qtype_ddwtos_plugin.class.php | 12 ++--- .../restore_qtype_ddwtos_plugin.class.php | 20 ++++---- question/type/ddimageortext/db/install.xml | 4 +- .../type/ddimageortext/edit_ddwtos_form.php | 8 ++-- .../ddimageortext/lang/en/qtype_ddwtos.php | 12 ++--- question/type/ddimageortext/question.php | 6 +-- question/type/ddimageortext/questiontype.php | 10 ++-- question/type/ddimageortext/renderer.php | 6 +-- question/type/ddimageortext/script.js | 10 ++-- .../type/ddimageortext/simpletest/helper.php | 44 +++++++++--------- .../ddimageortext/simpletest/testquestion.php | 46 +++++++++---------- .../simpletest/testquestiontype.php | 34 +++++++------- .../simpletest/testwalkthrough.php | 24 +++++----- question/type/ddimageortext/styles.css | 36 +++++++-------- question/type/ddimageortext/version.php | 2 +- 15 files changed, 137 insertions(+), 137 deletions(-) diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php index 89cb186f836..95dbc936292 100755 --- a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php @@ -26,12 +26,12 @@ defined('MOODLE_INTERNAL') || die(); /** - * Provides the information to backup ddwtos questions + * Provides the information to backup ddimagetoimage questions * * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class backup_qtype_ddwtos_plugin extends backup_qtype_plugin { +class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { /** * Returns the qtype information to attach to question element @@ -39,7 +39,7 @@ class backup_qtype_ddwtos_plugin extends backup_qtype_plugin { protected function define_question_plugin_structure() { // Define the virtual plugin element with the condition to fulfill - $plugin = $this->get_plugin_element(null, '../../qtype', 'ddwtos'); + $plugin = $this->get_plugin_element(null, '../../qtype', 'ddimagetoimage'); // Create one standard named plugin element (the visible container) $pluginwrapper = new backup_nested_element($this->get_recommended_name()); @@ -52,16 +52,16 @@ class backup_qtype_ddwtos_plugin extends backup_qtype_plugin { $this->add_question_question_answers($pluginwrapper); // Now create the qtype own structures - $ddwtos = new backup_nested_element('ddwtos', array('id'), array( + $ddimagetoimage = new backup_nested_element('ddimagetoimage', array('id'), array( 'shuffleanswers', 'correctfeedback', 'correctfeedbackformat', 'partiallycorrectfeedback', 'partiallycorrectfeedbackformat', 'incorrectfeedback', 'incorrectfeedbackformat', 'shownumcorrect')); // Now the own qtype tree - $pluginwrapper->add_child($ddwtos); + $pluginwrapper->add_child($ddimagetoimage); // set source to populate the data - $ddwtos->set_source_table('question_ddwtos', array('questionid' => backup::VAR_PARENTID)); + $ddimagetoimage->set_source_table('question_ddimagetoimage', array('questionid' => backup::VAR_PARENTID)); // don't need to annotate ids nor files diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php index 48fd9695bef..361c06da75a 100755 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php @@ -27,12 +27,12 @@ defined('MOODLE_INTERNAL') || die(); /** * restore plugin class that provides the necessary information - * needed to restore one ddwtos qtype plugin + * needed to restore one ddimagetoimage qtype plugin * * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class restore_qtype_ddwtos_plugin extends restore_qtype_plugin { +class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { /** * Returns the paths to be handled by the plugin at question level @@ -45,17 +45,17 @@ class restore_qtype_ddwtos_plugin extends restore_qtype_plugin { $this->add_question_question_answers($paths); // Add own qtype stuff - $elename = 'ddwtos'; - $elepath = $this->get_pathfor('/ddwtos'); // we used get_recommended_name() so this works + $elename = 'ddimagetoimage'; + $elepath = $this->get_pathfor('/ddimagetoimage'); // we used get_recommended_name() so this works $paths[] = new restore_path_element($elename, $elepath); return $paths; // And we return the interesting paths } /** - * Process the qtype/ddwtos element + * Process the qtype/ddimagetoimage element */ - public function process_ddwtos($data) { + public function process_ddimagetoimage($data) { global $DB; $data = (object)$data; @@ -66,14 +66,14 @@ class restore_qtype_ddwtos_plugin extends restore_qtype_plugin { $newquestionid = $this->get_new_parentid('question'); $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; - // If the question has been created by restore, we need to create its question_ddwtos too + // If the question has been created by restore, we need to create its question_ddimagetoimage too if ($questioncreated) { // Adjust some columns $data->questionid = $newquestionid; // Insert record - $newitemid = $DB->insert_record('question_ddwtos', $data); + $newitemid = $DB->insert_record('question_ddimagetoimage', $data); // Create mapping (needed for decoding links) - $this->set_mapping('question_ddwtos', $oldid, $newitemid); + $this->set_mapping('question_ddimagetoimage', $oldid, $newitemid); } } @@ -85,7 +85,7 @@ class restore_qtype_ddwtos_plugin extends restore_qtype_plugin { $contents = array(); $fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'); - $contents[] = new restore_decode_content('question_ddwtos', $fields, 'question_ddwtos'); + $contents[] = new restore_decode_content('question_ddimagetoimage', $fields, 'question_ddimagetoimage'); return $contents; } diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml index 50dbefe8a09..2b1a00faa37 100755 --- a/question/type/ddimageortext/db/install.xml +++ b/question/type/ddimageortext/db/install.xml @@ -1,10 +1,10 @@ - - +
diff --git a/question/type/ddimageortext/edit_ddwtos_form.php b/question/type/ddimageortext/edit_ddwtos_form.php index 5f30792e4a9..5d79f618782 100755 --- a/question/type/ddimageortext/edit_ddwtos_form.php +++ b/question/type/ddimageortext/edit_ddwtos_form.php @@ -18,7 +18,7 @@ * Defines the editing form for the drag-and-drop words into sentences question type. * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -35,9 +35,9 @@ require_once($CFG->dirroot . '/question/type/gapselect/edit_form_base.php'); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { +class qtype_ddimagetoimage_edit_form extends qtype_gapselect_edit_form_base { public function qtype() { - return 'ddwtos'; + return 'ddimagetoimage'; } protected function data_preprocessing_choice($question, $answer, $key) { @@ -51,7 +51,7 @@ class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { protected function choice_group($mform) { $grouparray = parent::choice_group($mform); $grouparray[] = $mform->createElement('checkbox', 'infinite', ' ', - get_string('infinite', 'qtype_ddwtos'), null, + get_string('infinite', 'qtype_ddimagetoimage'), null, array('size' => 1, 'class' => 'tweakcss')); return $grouparray; } diff --git a/question/type/ddimageortext/lang/en/qtype_ddwtos.php b/question/type/ddimageortext/lang/en/qtype_ddwtos.php index 44759253472..c7c55dd9e1a 100755 --- a/question/type/ddimageortext/lang/en/qtype_ddwtos.php +++ b/question/type/ddimageortext/lang/en/qtype_ddwtos.php @@ -17,18 +17,18 @@ /** * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['addingddwtos'] = 'Adding drag and drop: words in text'; +$string['addingddimagetoimage'] = 'Adding drag and drop: words in text'; $string['addmorechoiceblanks'] = 'Blanks for {no} More Choices'; $string['answer'] = 'Answer'; $string['correctansweris'] = 'The correct answer is: {$a}'; -$string['ddwtos'] = 'Drag and drop: words in text'; -$string['ddwtos_help'] = 'Type in some question text like "The [[1]] jumped over the [[2]]", then enter the possible words to go in gaps 1 and 2 underneath.'; -$string['ddwtossummary'] = 'Missing words in some text are filled in using drag-and-drop.'; -$string['editingddwtos'] = 'Editing drag and drop: words in text'; +$string['ddimagetoimage'] = 'Drag and drop: words in text'; +$string['ddimagetoimage_help'] = 'Type in some question text like "The [[1]] jumped over the [[2]]", then enter the possible words to go in gaps 1 and 2 underneath.'; +$string['ddimagetoimagesummary'] = 'Missing words in some text are filled in using drag-and-drop.'; +$string['editingddimagetoimage'] = 'Editing drag and drop: words in text'; $string['infinite'] = 'Infinite'; $string['pleaseputananswerineachbox'] = 'Please put an answer in each box.'; diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 25e3fe4d9a9..9476ab94a0b 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -18,7 +18,7 @@ * Drag-and-drop words into sentences question definition class. * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -35,7 +35,7 @@ require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos_question extends qtype_gapselect_question_base { +class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { // Is actually exactly the same. } @@ -46,7 +46,7 @@ class qtype_ddwtos_question extends qtype_gapselect_question_base { * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos_choice { +class qtype_ddimagetoimage_choice { public $text; public $draggroup; public $isinfinite; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 8b46966a759..8c67a4ca821 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -18,7 +18,7 @@ * Question type class for the drag-and-drop words into sentences question type. * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -38,7 +38,7 @@ require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos extends qtype_gapselect_base { +class qtype_ddimagetoimage extends qtype_gapselect_base { protected function choice_group_key() { return 'draggroup'; } @@ -61,17 +61,17 @@ class qtype_ddwtos extends qtype_gapselect_base { protected function make_choice($choicedata) { $options = unserialize($choicedata->feedback); - return new qtype_ddwtos_choice( + return new qtype_ddimagetoimage_choice( $choicedata->answer, $options->draggroup, $options->infinite); } public function import_from_xml($data, $question, $format, $extra=null) { - if (!isset($data['@']['type']) || $data['@']['type'] != 'ddwtos') { + if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimagetoimage') { return false; } $question = $format->import_headers($data); - $question->qtype = 'ddwtos'; + $question->qtype = 'ddimagetoimage'; $question->shuffleanswers = $format->trans_single( $format->getpath($data, array('#', 'shuffleanswers', 0, '#'), 1)); diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index e04716366fc..74750609547 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -18,7 +18,7 @@ * Drag-and-drop words into sentences question renderer class. * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -35,10 +35,10 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos_renderer extends qtype_elements_embedded_in_question_text_renderer { +class qtype_ddimagetoimage_renderer extends qtype_elements_embedded_in_question_text_renderer { protected function qtext_classname() { - return 'qtext ddwtos_questionid_for_javascript'; + return 'qtext ddimagetoimage_questionid_for_javascript'; } protected function post_qtext_elements(question_attempt $qa, diff --git a/question/type/ddimageortext/script.js b/question/type/ddimageortext/script.js index 8e5f2d38980..542e7ac2f4e 100755 --- a/question/type/ddimageortext/script.js +++ b/question/type/ddimageortext/script.js @@ -16,16 +16,16 @@ /** * JavaScript objects, functions as well as usage of some YUI library for * enabling drag and drop interaction for dran-anddrop words into sentences - * (ddwtos) + * (ddimagetoimage) * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ //global variables -var ddwtos_currentzindex = 10; +var ddimagetoimage_currentzindex = 10; /* @@ -38,7 +38,7 @@ var ddwtos_currentzindex = 10; // start of App object by all questions of this type on a page. YAHOO.example.DDApp = { init : function() { - var questionspans = YAHOO.util.Dom.getElementsByClassName("ddwtos_questionid_for_javascript"); + var questionspans = YAHOO.util.Dom.getElementsByClassName("ddimagetoimage_questionid_for_javascript"); // we need this loop in case of more than one of this qtype on one page for (var i = 0; i < questionspans.length; i++) { @@ -108,7 +108,7 @@ var ddwtos_currentzindex = 10; //Abstract method called after a drag/drop object is clicked and the drag or mousedown time thresholds have beeen met. startDrag : function(x, y) { - YAHOO.util.Dom.setStyle(this.getEl(), "zIndex", ddwtos_currentzindex++); + YAHOO.util.Dom.setStyle(this.getEl(), "zIndex", ddimagetoimage_currentzindex++); YAHOO.util.Dom.removeClass(this.getEl(), 'placed'); if (is_infinite(this.getEl()) && !this.slot){ diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/simpletest/helper.php index 50e244f4157..317a217fc8c 100755 --- a/question/type/ddimageortext/simpletest/helper.php +++ b/question/type/ddimageortext/simpletest/helper.php @@ -18,7 +18,7 @@ * Test helpers for the drag-and-drop words into sentences question type. * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -33,24 +33,24 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos_test_helper extends question_test_helper { +class qtype_ddimagetoimage_test_helper extends question_test_helper { public function get_test_questions() { return array('fox', 'maths'); } /** - * @return qtype_ddwtos_question + * @return qtype_ddimagetoimage_question */ - public function make_ddwtos_question_fox() { - question_bank::load_question_definition_classes('ddwtos'); - $dd = new qtype_ddwtos_question(); + public function make_ddimagetoimage_question_fox() { + question_bank::load_question_definition_classes('ddimagetoimage'); + $dd = new qtype_ddimagetoimage_question(); test_question_maker::initialise_a_question($dd); $dd->name = 'Drag-and-drop words into sentences question'; $dd->questiontext = 'The [[1]] brown [[2]] jumped over the [[3]] dog.'; $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; - $dd->qtype = question_bank::get_qtype('ddwtos'); + $dd->qtype = question_bank::get_qtype('ddimagetoimage'); $dd->shufflechoices = true; @@ -58,14 +58,14 @@ class qtype_ddwtos_test_helper extends question_test_helper { $dd->choices = array( 1 => array( - 1 => new qtype_ddwtos_choice('quick', 1), - 2 => new qtype_ddwtos_choice('slow', 1)), + 1 => new qtype_ddimagetoimage_choice('quick', 1), + 2 => new qtype_ddimagetoimage_choice('slow', 1)), 2 => array( - 1 => new qtype_ddwtos_choice('fox', 2), - 2 => new qtype_ddwtos_choice('dog', 2)), + 1 => new qtype_ddimagetoimage_choice('fox', 2), + 2 => new qtype_ddimagetoimage_choice('dog', 2)), 3 => array( - 1 => new qtype_ddwtos_choice('lazy', 3), - 2 => new qtype_ddwtos_choice('assiduous', 3)), + 1 => new qtype_ddimagetoimage_choice('lazy', 3), + 2 => new qtype_ddimagetoimage_choice('assiduous', 3)), ); $dd->places = array(1 => 1, 2 => 2, 3 => 3); @@ -76,11 +76,11 @@ class qtype_ddwtos_test_helper extends question_test_helper { } /** - * @return qtype_ddwtos_question + * @return qtype_ddimagetoimage_question */ - public function make_ddwtos_question_maths() { - question_bank::load_question_definition_classes('ddwtos'); - $dd = new qtype_ddwtos_question(); + public function make_ddimagetoimage_question_maths() { + question_bank::load_question_definition_classes('ddimagetoimage'); + $dd = new qtype_ddimagetoimage_question(); test_question_maker::initialise_a_question($dd); @@ -88,7 +88,7 @@ class qtype_ddwtos_test_helper extends question_test_helper { $dd->questiontext = 'Fill in the operators to make this equation work: ' . '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3'; $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; - $dd->qtype = question_bank::get_qtype('ddwtos'); + $dd->qtype = question_bank::get_qtype('ddimagetoimage'); $dd->shufflechoices = true; @@ -96,10 +96,10 @@ class qtype_ddwtos_test_helper extends question_test_helper { $dd->choices = array( 1 => array( - 1 => new qtype_ddwtos_choice('+', 1, true), - 2 => new qtype_ddwtos_choice('-', 1, true), - 3 => new qtype_ddwtos_choice('*', 1, true), - 4 => new qtype_ddwtos_choice('/', 1, true), + 1 => new qtype_ddimagetoimage_choice('+', 1, true), + 2 => new qtype_ddimagetoimage_choice('-', 1, true), + 3 => new qtype_ddimagetoimage_choice('*', 1, true), + 4 => new qtype_ddimagetoimage_choice('/', 1, true), )); $dd->places = array(1 => 1, 2 => 1, 3 => 1, 4 => 1); diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index 58fea4279cf..bdee7b892e3 100755 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -18,7 +18,7 @@ * Unit tests for the drag-and-drop words into sentences question definition class. * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); -require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); +require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.php'); /** @@ -36,24 +36,24 @@ require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos_question_test extends UnitTestCase { +class qtype_ddimagetoimage_question_test extends UnitTestCase { public function test_get_question_summary() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $this->assertEqual('The [[1]] brown [[2]] jumped over the [[3]] dog.; ' . '[[1]] -> {quick / slow}; [[2]] -> {fox / dog}; [[3]] -> {lazy / assiduous}', $dd->get_question_summary()); } public function test_get_question_summary_maths() { - $dd = test_question_maker::make_question('ddwtos', 'maths'); + $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); $this->assertEqual('Fill in the operators to make this equation work: ' . '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3; [[1]] -> {+ / - / * / /}', $dd->get_question_summary()); } public function test_summarise_response() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -62,7 +62,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_summarise_response_maths() { - $dd = test_question_maker::make_question('ddwtos', 'maths'); + $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -71,17 +71,17 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_random_guess_score() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $this->assertEqual(0.5, $dd->get_random_guess_score()); } public function test_get_random_guess_score_maths() { - $dd = test_question_maker::make_question('ddwtos', 'maths'); + $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); $this->assertEqual(0.25, $dd->get_random_guess_score()); } public function test_get_right_choice_for() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -90,7 +90,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_right_choice_for_maths() { - $dd = test_question_maker::make_question('ddwtos', 'maths'); + $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -99,7 +99,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_clear_wrong_from_response() { - $dd = test_question_maker::make_question('ddwtos', 'maths'); + $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -109,7 +109,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_num_parts_right() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -120,7 +120,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_num_parts_right_maths() { - $dd = test_question_maker::make_question('ddwtos', 'maths'); + $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -130,7 +130,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_expected_data() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT), @@ -138,7 +138,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_correct_response() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -147,7 +147,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_get_correct_response_maths() { - $dd = test_question_maker::make_question('ddwtos', 'maths'); + $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -156,7 +156,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_is_same_response() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->start_attempt(new question_attempt_step(), 1); $this->assertTrue($dd->is_same_response( @@ -180,7 +180,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { array('p1' => '1', 'p2' => '2', 'p3' => '2'))); } public function test_is_complete_response() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->start_attempt(new question_attempt_step(), 1); $this->assertFalse($dd->is_complete_response(array())); @@ -192,7 +192,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_is_gradable_response() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->start_attempt(new question_attempt_step(), 1); $this->assertFalse($dd->is_gradable_response(array())); @@ -206,7 +206,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_grading() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -219,7 +219,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_grading_maths() { - $dd = test_question_maker::make_question('ddwtos', 'maths'); + $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -232,7 +232,7 @@ class qtype_ddwtos_question_test extends UnitTestCase { } public function test_classify_response() { - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index 34c41f87889..78c42a87582 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -18,7 +18,7 @@ * Unit tests for the drag-and-drop words into sentences question definition class. * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); -require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); +require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.php'); /** @@ -36,12 +36,12 @@ require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos_test extends UnitTestCase { - /** @var qtype_ddwtos instance of the question type class to test. */ +class qtype_ddimagetoimage_test extends UnitTestCase { + /** @var qtype_ddimagetoimage instance of the question type class to test. */ protected $qtype; public function setUp() { - $this->qtype = question_bank::get_qtype('ddwtos');; + $this->qtype = question_bank::get_qtype('ddimagetoimage');; } public function tearDown() { @@ -55,7 +55,7 @@ class qtype_ddwtos_test extends UnitTestCase { /** * @return object the data to construct a question like - * {@link qtype_ddwtos_test_helper::make_ddwtos_question_fox()}. + * {@link qtype_ddimagetoimage_test_helper::make_ddimagetoimage_question_fox()}. */ protected function get_test_question_data() { global $USER; @@ -81,7 +81,7 @@ class qtype_ddwtos_test extends UnitTestCase { $dd->name = 'Drag-and-drop words into sentences question'; $dd->questiontext = 'The [[1]] brown [[2]] jumped over the [[3]] dog.'; $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; - $dd->qtype = 'ddwtos'; + $dd->qtype = 'ddimagetoimage'; $dd->options->shuffleanswers = true; @@ -106,7 +106,7 @@ class qtype_ddwtos_test extends UnitTestCase { } public function test_name() { - $this->assertEqual($this->qtype->name(), 'ddwtos'); + $this->assertEqual($this->qtype->name(), 'ddimagetoimage'); } public function test_can_analyse_responses() { @@ -116,7 +116,7 @@ class qtype_ddwtos_test extends UnitTestCase { public function test_initialise_question_instance() { $qdata = $this->get_test_question_data(); - $expected = test_question_maker::make_question('ddwtos'); + $expected = test_question_maker::make_question('ddimagetoimage'); $expected->stamp = $qdata->stamp; $expected->version = $qdata->version; @@ -150,7 +150,7 @@ class qtype_ddwtos_test extends UnitTestCase { } public function test_xml_import() { - $xml = ' + $xml = ' A drag-and-drop question @@ -201,10 +201,10 @@ class qtype_ddwtos_test extends UnitTestCase { $importer = new qformat_xml(); $q = $importer->try_importing_using_qtypes( - $xmldata['question'], null, null, 'ddwtos'); + $xmldata['question'], null, null, 'ddimagetoimage'); $expectedq = new stdClass(); - $expectedq->qtype = 'ddwtos'; + $expectedq->qtype = 'ddimagetoimage'; $expectedq->name = 'A drag-and-drop question'; $expectedq->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; $expectedq->questiontextformat = FORMAT_MOODLE; @@ -240,7 +240,7 @@ class qtype_ddwtos_test extends UnitTestCase { } public function test_xml_import_legacy() { - $xml = ' + $xml = ' QDandD1 Base definition @@ -366,10 +366,10 @@ class qtype_ddwtos_test extends UnitTestCase { $importer = new qformat_xml(); $q = $importer->try_importing_using_qtypes( - $xmldata['question'], null, null, 'ddwtos'); + $xmldata['question'], null, null, 'ddimagetoimage'); $expectedq = new stdClass(); - $expectedq->qtype = 'ddwtos'; + $expectedq->qtype = 'ddimagetoimage'; $expectedq->name = 'QDandD1 Base definition'; $expectedq->questiontext = '

Drag and drop the words from the list below ' . 'to fill the blank spaces and correctly complete the sentence.

' . @@ -435,7 +435,7 @@ class qtype_ddwtos_test extends UnitTestCase { $qdata = new stdClass(); $qdata->id = 123; $qdata->contextid = 0; - $qdata->qtype = 'ddwtos'; + $qdata->qtype = 'ddimagetoimage'; $qdata->name = 'A drag-and-drop question'; $qdata->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; $qdata->questiontextformat = FORMAT_MOODLE; @@ -478,7 +478,7 @@ class qtype_ddwtos_test extends UnitTestCase { $xml = $exporter->writequestion($qdata); $expectedxml = ' - + A drag-and-drop question diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index a296640bace..bbbdf4118eb 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -18,7 +18,7 @@ * Unit tests for the drag-and-drop words into sentences question type. * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); -require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); +require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.php'); /** @@ -36,7 +36,7 @@ require_once($CFG->dirroot . '/question/type/ddwtos/simpletest/helper.php'); * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { +class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_base { protected function get_contains_drop_box_expectation($place, $group, $readonly, $stateclass = '0') { @@ -62,7 +62,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_behaviour() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->hints = array( new question_hint_with_parts(13, 'This is the first hint.', FORMAT_HTML, false, false), new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true), @@ -174,7 +174,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_deferred_feedback() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'deferredfeedback', 3); @@ -257,7 +257,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_deferred_feedback_unanswered() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'deferredfeedback', 3); @@ -313,7 +313,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_deferred_feedback_partial_answer() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'deferredfeedback', 3); @@ -368,7 +368,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_grading() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->hints = array( new question_hint_with_parts(1, 'This is the first hint.', FORMAT_MOODLE, true, true), @@ -528,7 +528,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_correct_no_submit() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->hints = array( new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), @@ -584,7 +584,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_partial_no_submit() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->hints = array( new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), @@ -640,7 +640,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_interactive_no_right_clears() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $dd->hints = array( new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, true), new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), @@ -707,7 +707,7 @@ class qtype_ddwtos_walkthrough_test extends qbehaviour_walkthrough_test_base { public function test_display_of_right_answer_when_shuffled() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddwtos'); + $dd = test_question_maker::make_question('ddimagetoimage'); $this->start_attempt_at_question($dd, 'deferredfeedback', 3); // Check the initial state. diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 8a84a09b149..4b26ec74d81 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -1,70 +1,70 @@ -.que.ddwtos .qtext { +.que.ddimagetoimage .qtext { line-height: 2em; margin-bottom: 0.5em; display: block; } -.que.ddwtos .qtext * { +.que.ddimagetoimage .qtext * { line-height: 2em; } -.que.ddwtos .answercontainer { +.que.ddimagetoimage .answercontainer { line-height: 2em; margin-bottom: 1em; display: block; } -.que.ddwtos .answertext { +.que.ddimagetoimage .answertext { padding-bottom: 0.5em; } -.que.ddwtos .slot { +.que.ddimagetoimage .slot { display: inline-block; text-align: center; border: 1px solid #000000; } -.que.ddwtos .player { +.que.ddimagetoimage .player { display: inline-block; text-align: center; cursor: move; border: 1px solid #000000; } -.que.ddwtos .player.placed { /* Lets the focus rectangle be visible in IE. */ +.que.ddimagetoimage .player.placed { /* Lets the focus rectangle be visible in IE. */ background: transparent; } -.que.ddwtos .readonly { +.que.ddimagetoimage .readonly { cursor: default; } -.que.ddwtos span.incorrect { +.que.ddimagetoimage span.incorrect { background-color: #faa; } -.que.ddwtos span.correct { +.que.ddimagetoimage span.correct { background-color: #afa; } -.que.ddwtos .group1 { +.que.ddimagetoimage .group1 { background-color: #FFFFFF; } -.que.ddwtos .group2 { +.que.ddimagetoimage .group2 { background-color: #DCDCDC; } -.que.ddwtos .group3 { +.que.ddimagetoimage .group3 { background-color: #B0C4DE; } -.que.ddwtos .group4 { +.que.ddimagetoimage .group4 { background-color: #D8BFD8; } -.que.ddwtos .group5 { +.que.ddimagetoimage .group5 { background-color: #87CEFA; } -.que.ddwtos .group6 { +.que.ddimagetoimage .group6 { background-color: #DAA520; } -.que.ddwtos .group7 { +.que.ddimagetoimage .group7 { background-color: #FFD700; } -.que.ddwtos .group8 { +.que.ddimagetoimage .group8 { background-color: #F0E68C; } diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 036d05ab489..a15d0944567 100755 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -18,7 +18,7 @@ * Version information for the drag-and-drop words into sentences question type. * * @package qtype - * @subpackage ddwtos + * @subpackage ddimagetoimage * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ From 1d41020572be17bf07e66cc7976d9c2dd65096ff Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 23 Jun 2011 14:57:35 +0700 Subject: [PATCH 027/208] MDL-47494 ddimageortext: NOBUG db structure for this question type. --- question/type/ddimageortext/db/install.xml | 33 ++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml index 2b1a00faa37..dd603bf532b 100755 --- a/question/type/ddimageortext/db/install.xml +++ b/question/type/ddimageortext/db/install.xml @@ -1,14 +1,14 @@ - -
+
- - - + + + @@ -22,5 +22,28 @@
+ + + + + + + + + + + +
+ + + + + + + + + + +
\ No newline at end of file From b0a8a7ebbd8164d68b62ef5a17840b31a3f55a9f Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 23 Jun 2011 14:58:20 +0700 Subject: [PATCH 028/208] MDL-47494 ddimageortext: NOBUG adding a TODO.txt to track tasks. --- question/type/ddimageortext/TODO.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 question/type/ddimageortext/TODO.txt diff --git a/question/type/ddimageortext/TODO.txt b/question/type/ddimageortext/TODO.txt new file mode 100644 index 00000000000..7c6564c25a1 --- /dev/null +++ b/question/type/ddimageortext/TODO.txt @@ -0,0 +1,16 @@ +Question authoring form fields 2 hours +Display Image in authoring form +Calculation of size of drop zones +Calculate size of images, server side and save the sizes upon image upload +Display of drop zones on authoring form 4 hours +Question instance saving 2 hours +Question instance loading 2 hours +Question rendering code 6 hours +- correctly position images +- make images draggable +- react to drop of images +- write position that images where dropped to in hidden fields +- grade question parts based on where images dragged to +- have position of images at start respond to saved state + +Testing and debugging for cross browser compatibility 4 hours From 943b33da7e83cc6911bfead1815602278fa4a0eb Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 23 Jun 2011 15:06:56 +0700 Subject: [PATCH 029/208] MDL-47494 ddimageortext: NOBUG changing file names to qtype name --- .../{edit_ddwtos_form.php => edit_ddimagetoimage_form.php} | 0 .../lang/en/{qtype_ddwtos.php => qtype_ddimagetoimage.php} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename question/type/ddimageortext/{edit_ddwtos_form.php => edit_ddimagetoimage_form.php} (100%) mode change 100755 => 100644 rename question/type/ddimageortext/lang/en/{qtype_ddwtos.php => qtype_ddimagetoimage.php} (100%) mode change 100755 => 100644 diff --git a/question/type/ddimageortext/edit_ddwtos_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php old mode 100755 new mode 100644 similarity index 100% rename from question/type/ddimageortext/edit_ddwtos_form.php rename to question/type/ddimageortext/edit_ddimagetoimage_form.php diff --git a/question/type/ddimageortext/lang/en/qtype_ddwtos.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php old mode 100755 new mode 100644 similarity index 100% rename from question/type/ddimageortext/lang/en/qtype_ddwtos.php rename to question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php From e79dad73e185357ab473a2630fc6d15708f5469a Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 30 Jun 2011 16:43:33 +0700 Subject: [PATCH 030/208] MDL-47494 ddimageortext: NOBUG completed most of the basics of the question editing form and saving of data in database. --- question/type/ddimageortext/README.txt | 3 + question/type/ddimageortext/db/install.xml | 20 +- .../edit_ddimagetoimage_form.php | 234 ++++++++++++++++-- .../lang/en/qtype_ddimagetoimage.php | 23 +- question/type/ddimageortext/questiontype.php | 132 +++++----- 5 files changed, 309 insertions(+), 103 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index def8b611eb4..5fbeb377a09 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -8,6 +8,9 @@ This question type was written by Jamie Pratt (http://jamiep.org/). This question type is compatible with Moodle 2.1+. +Requires this fix : MDL-28099 +filepicker form element does not work with element names with an index such as image[0] + To install using git, type this command in the root of your Moodle install git clone git://github.com/jamiepratt/moodle-qtype_ddimagetoimage.git question/type/ddimagetoimage Then add question/type/ddimagetoimage to your git ignore. diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml index dd603bf532b..6ab689a2b2e 100755 --- a/question/type/ddimageortext/db/install.xml +++ b/question/type/ddimageortext/db/install.xml @@ -1,5 +1,5 @@ - @@ -24,25 +24,31 @@ - - + + + + - + +
- - + + + + - + +
diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 5d79f618782..0c43a7ed611 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * Defines the editing form for the drag-and-drop words into sentences question type. + * Defines the editing form for the drag-and-drop images onto images question type. * * @package qtype * @subpackage ddimagetoimage @@ -23,36 +23,238 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - defined('MOODLE_INTERNAL') || die(); -require_once($CFG->dirroot . '/question/type/gapselect/edit_form_base.php'); - - /** - * Drag-and-drop words into sentences editing form definition. + * Drag-and-drop images onto images editing form definition. * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_edit_form extends qtype_gapselect_edit_form_base { +class qtype_ddimagetoimage_edit_form extends question_edit_form { + const MAX_GROUPS = 8; + const START_NUM_IMAGES = 6; + const ADD_NUM_IMAGES = 3; + public function qtype() { return 'ddimagetoimage'; } - protected function data_preprocessing_choice($question, $answer, $key) { - $question = parent::data_preprocessing_choice($question, $answer, $key); - $options = unserialize($answer->feedback); - $question->choices[$key]['choicegroup'] = $options->draggroup; - $question->choices[$key]['infinite'] = $options->infinite; - return $question; + /** + * + * Options shared by all file pickers in the form. + */ + public static function file_picker_options() { + $filepickeroptions = array(); + $filepickeroptions['accepted_types'] = array('web_image'); + $filepickeroptions['maxbytes'] = 0; + $filepickeroptions['maxfiles'] = 1; + $filepickeroptions['subdirs'] = 0; + return $filepickeroptions; } - protected function choice_group($mform) { - $grouparray = parent::choice_group($mform); + protected function get_drag_image_repeats() { + $countimages = 0; + if (isset($this->question->id)) { + foreach ($this->question->options->drags as $drag) { + $countimages = max($countimages, $drag->no); + } + } + if ($this->question->formoptions->repeatelements) { + $imagerepeatsatstart = max(self::START_NUM_IMAGES, $countimages + self::ADD_NUM_IMAGES); + } else { + $imagerepeatsatstart = $countimages; + } + $imagerepeats = optional_param('noimages', $imagerepeatsatstart, PARAM_INT); + $addfields = optional_param('addimages', '', PARAM_TEXT); + if (!empty($addfields)){ + $imagerepeats += self::ADD_NUM_IMAGES; + } + return array($imagerepeatsatstart, $imagerepeats); + } + + /** + * definition_inner adds all specific fields to the form. + * @param object $mform (the form being built). + */ + protected function definition_inner($mform) { + $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimagetoimage'), + null, self::file_picker_options()); + + list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); + $this->definition_drop_zones($mform, $imagerepeats); + $mform->addElement('checkbox', 'shuffleanswers', ' ', + get_string('shuffleimages', 'qtype_ddimagetoimage')); + $mform->setDefault('shuffleanswers', 0); + $mform->closeHeaderBefore('shuffleanswers'); + //add the draggable image fields to the form + $this->definition_draggable_images($mform, $imagerepeatsatstart); + + $this->add_combined_feedback_fields(true); + $this->add_interactive_settings(true, true); + } + + protected function definition_drop_zones($mform, $imagerepeats) { + $mform->addElement('header', 'dropzoneheader', + get_string('dropzoneheader', 'qtype_ddimagetoimage')); + + $countdropzones = 0; + if (isset($this->question->id)) { + foreach ($this->question->options->drops as $drop) { + $countdropzones = max($countdropzones, $drop->no); + } + } + if ($this->question->formoptions->repeatelements) { + $dropzonerepeatsatstart = max(self::START_NUM_IMAGES, + $countdropzones + self::ADD_NUM_IMAGES); + } else { + $dropzonerepeatsatstart = $countdropzones; + } + + $this->repeat_elements($this->drop_zone($mform, $imagerepeats), $dropzonerepeatsatstart, + $this->drop_zones_repeated_options(), + 'nodropzone', 'adddropzone', self::ADD_NUM_IMAGES, + get_string('addmoredropzones', 'qtype_ddimagetoimage')); + } + + protected function drop_zone($mform, $imagerepeats) { + $dropzoneitem = array(); + + + $grouparray = array(); + $grouparray[] = $mform->createElement('static', 'xleftlabel', '', + ' '.get_string('xleft', 'qtype_ddimagetoimage').' '); + $grouparray[] = $mform->createElement('text', 'xleft', + get_string('xleft', 'qtype_ddimagetoimage'), + array('size'=>5, 'class'=>'tweakcss')); + $mform->setType('xleft', PARAM_NOTAGS); + $grouparray[] = $mform->createElement('static', 'ytoplabel', '', + ' '.get_string('ytop', 'qtype_ddimagetoimage').' '); + $grouparray[] = $mform->createElement('text', 'ytop', + get_string('ytop', 'qtype_ddimagetoimage'), + array('size'=>5, 'class'=>'tweakcss')); + $mform->setType('ytop', PARAM_NOTAGS); + $options = array(); + + for ($i = 1; $i <= $imagerepeats; $i += 1) { + $options[$i] = $i; + } + $grouparray[] = $mform->createElement('static', '', '', ' ' . + get_string('draggableimage', 'qtype_ddimagetoimage').' '); + $grouparray[] = $mform->createElement('select', 'choice', + get_string('draggableimage', 'qtype_ddimagetoimage'), $options); + $grouparray[] = $mform->createElement('static', '', '', ' ' . + get_string('label', 'qtype_ddimagetoimage').' '); + $grouparray[] = $mform->createElement('text', 'droplabel', + get_string('label', 'qtype_ddimagetoimage'), + array('size'=>10, 'class'=>'tweakcss')); + $mform->setType('droplabel', PARAM_NOTAGS); + $dropzone = $mform->createElement('group', 'drops', + get_string('dropzone', 'qtype_ddimagetoimage', '{no}'), $grouparray); + return array($dropzone); + } + + protected function drop_zones_repeated_options() { + $repeatedoptions = array(); + $repeatedoptions['choicegroup']['default'] = '1'; + return $repeatedoptions; + } + + protected function definition_draggable_images($mform, $imagerepeatsatstart) { + + $this->repeat_elements($this->draggable_image($mform), $imagerepeatsatstart, + $this->draggable_images_repeated_options(), + 'noimages', 'addimages', self::ADD_NUM_IMAGES, + get_string('addmoreimages', 'qtype_ddimagetoimage')); + } + + protected function draggable_image($mform) { + $draggableimageitem = array(); + + $draggableimageitem[] = $mform->createElement('header', 'draggableimageheader', + get_string('draggableimageheader', 'qtype_ddimagetoimage', '{no}')); + $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null, + self::file_picker_options()); + + $grouparray = array(); + $grouparray[] = $mform->createElement('text', 'draglabel', + get_string('label', 'qtype_ddimagetoimage'), + array('size'=>30, 'class'=>'tweakcss')); + $mform->setType('draglabel', PARAM_NOTAGS); + $options = array(); + for ($i = 1; $i <= self::MAX_GROUPS; $i += 1) { + $options[$i] = $i; + } + $grouparray[] = $mform->createElement('static', '', '', ' ' . + get_string('group', 'qtype_gapselect').' '); + $grouparray[] = $mform->createElement('select', 'draggroup', + get_string('group', 'qtype_gapselect'), $options); $grouparray[] = $mform->createElement('checkbox', 'infinite', ' ', get_string('infinite', 'qtype_ddimagetoimage'), null, array('size' => 1, 'class' => 'tweakcss')); - return $grouparray; + $draggableimageitem[] = $mform->createElement('group', 'drags', + get_string('label', 'qtype_ddimagetoimage'), $grouparray); + return $draggableimageitem; } + + protected function draggable_images_repeated_options() { + $repeatedoptions = array(); + $repeatedoptions['draggroup']['default'] = '1'; + return $repeatedoptions; + } + + public function data_preprocessing($question) { + + $question = parent::data_preprocessing($question); + $question = $this->data_preprocessing_combined_feedback($question, true); + $question = $this->data_preprocessing_hints($question, true, true); + + if (!empty($question->options)) { + $question->shuffleanswers = $question->options->shuffleanswers; + $question->drags = array(); + foreach ($question->options->drags as $drag) { + $dragindex = $drag->no -1; + $question->drags[$dragindex] = array(); + $question->drags[$dragindex]['draglabel'] = $drag->label; + $question->drags[$dragindex]['infinite'] = $drag->infinite; + $question->drags[$dragindex]['draggroup'] = $drag->draggroup; + } + list(, $imagerepeats) = $this->get_drag_image_repeats(); + for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { + $draftitemid = file_get_submitted_draft_itemid("dragitem[$imageindex]"); + //numbers not allowed in filearea name + $filearea = str_replace(range('0', '9'), range('a', 'j'), "drag_$imageindex"); + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', + $filearea, !empty($question->id) ? (int) $question->id : null, + self::file_picker_options()); + $question->dragitem[$imageindex] = $draftitemid; + } + $question->drops = array(); + foreach ($question->options->drops as $drop) { + $question->drops[$drop->no -1] = array(); + $question->drops[$drop->no -1]['choice'] = $drop->choice; + $question->drops[$drop->no -1]['droplabel'] = $drop->label; + $question->drops[$drop->no -1]['xleft'] = $drop->xleft; + $question->drops[$drop->no -1]['ytop'] = $drop->ytop; + } + } + + $draftitemid = file_get_submitted_draft_itemid('bgimage'); + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', + 'bgimage', !empty($question->id) ? (int) $question->id : null, + self::file_picker_options()); + $question->bgimage = $draftitemid; + error_log(print_r(array('mform' => $this), true)); + error_log(print_r(compact('question'), true)); + return $question; + } + + public function validation($data, $files) { + $errors = parent::validation($data, $files); + + return $errors; + } + + + } diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index c7c55dd9e1a..d836df9f9c2 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -22,13 +22,22 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['addingddimagetoimage'] = 'Adding drag and drop: words in text'; -$string['addmorechoiceblanks'] = 'Blanks for {no} More Choices'; +$string['addingddimagetoimage'] = 'Adding drag and drop: images onto images'; +$string['addmoredropzones'] = 'Blanks for {no} More Drop Zones'; +$string['addmoreimages'] = 'Blanks for {no} More Draggable Images'; $string['answer'] = 'Answer'; +$string['bgimage'] = 'Background Image'; $string['correctansweris'] = 'The correct answer is: {$a}'; -$string['ddimagetoimage'] = 'Drag and drop: words in text'; -$string['ddimagetoimage_help'] = 'Type in some question text like "The [[1]] jumped over the [[2]]", then enter the possible words to go in gaps 1 and 2 underneath.'; -$string['ddimagetoimagesummary'] = 'Missing words in some text are filled in using drag-and-drop.'; -$string['editingddimagetoimage'] = 'Editing drag and drop: words in text'; +$string['ddimagetoimage'] = 'Drag and drop: images onto images'; +$string['ddimagetoimage_help'] = 'Select a background image file, select a number of draggable images and define the drop zones on the background image to which they must be dragged.'; +$string['ddimagetoimagesummary'] = 'Images are dragged and dropped into drop zones on a background image.'; +$string['draggableimage'] = 'Draggable image'; +$string['draggableimageheader'] = 'Draggable image {$a}'; +$string['dropzone'] = 'Drop zone {$a}'; +$string['dropzoneheader'] = 'Drop zones'; +$string['editingddimagetoimage'] = 'Editing drag and drop: images onto images'; $string['infinite'] = 'Infinite'; -$string['pleaseputananswerineachbox'] = 'Please put an answer in each box.'; +$string['label'] = 'Label'; +$string['shuffleimages'] = 'Shuffle Draggable Images'; +$string['xleft'] = 'Left'; +$string['ytop'] = 'Top'; \ No newline at end of file diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 8c67a4ca821..889a92a105d 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -38,7 +38,7 @@ require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage extends qtype_gapselect_base { +class qtype_ddimagetoimage extends question_type { protected function choice_group_key() { return 'draggroup'; } @@ -47,89 +47,75 @@ class qtype_ddimagetoimage extends qtype_gapselect_base { return array('gapselect'); } - protected function choice_options_to_feedback($choice) { - $output = new stdClass(); - $output->draggroup = $choice['choicegroup']; - $output->infinite = !empty($choice['infinite']); - return serialize($output); + public function get_question_options($question) { + global $DB; + $question->options = $DB->get_record('qtype_ddimagetoimage', + array('questionid' => $question->id), '*', MUST_EXIST); + $question->options->drags = $DB->get_records('qtype_ddimagetoimage_drags', + array('questionid' => $question->id), 'no ASC', '*'); + $question->options->drops = $DB->get_records('qtype_ddimagetoimage_drops', + array('questionid' => $question->id), 'no ASC', '*'); + parent::get_question_options($question); } - protected function feedback_to_choice_options($feedback) { - $feedbackobj = unserialize($feedback); - return array('draggroup' => $feedbackobj->draggroup, 'infinite' => $feedbackobj->infinite); - } + public function save_question_options($formdata) { + global $DB; + $context = $formdata->context; - protected function make_choice($choicedata) { - $options = unserialize($choicedata->feedback); - return new qtype_ddimagetoimage_choice( - $choicedata->answer, $options->draggroup, $options->infinite); - } - - public function import_from_xml($data, $question, $format, $extra=null) { - if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimagetoimage') { - return false; + $options = $DB->get_record('qtype_ddimagetoimage', array('questionid' => $formdata->id)); + if (!$options) { + $options = new stdClass(); + $options->questionid = $formdata->id; + $options->correctfeedback = ''; + $options->partiallycorrectfeedback = ''; + $options->incorrectfeedback = ''; + $options->id = $DB->insert_record('qtype_ddimagetoimage', $options); } - $question = $format->import_headers($data); - $question->qtype = 'ddimagetoimage'; - - $question->shuffleanswers = $format->trans_single( - $format->getpath($data, array('#', 'shuffleanswers', 0, '#'), 1)); - - if (!empty($data['#']['dragbox'])) { - // Modern XML format. - $dragboxes = $data['#']['dragbox']; - $question->answer = array(); - $question->draggroup = array(); - $question->infinite = array(); - - foreach ($data['#']['dragbox'] as $dragboxxml) { - $question->choices[] = array( - 'answer' => $format->getpath($dragboxxml, array('#', 'text', 0, '#'), '', true), - 'choicegroup' => $format->getpath($dragboxxml, array('#', 'group', 0, '#'), 1), - 'infinite' => array_key_exists('infinite', $dragboxxml['#']), - ); + $options->shuffleanswers = !empty($formdata->shuffleanswers); + $options = $this->save_combined_feedback_helper($options, $formdata, $context, true); + $this->save_hints($formdata, true); + $DB->update_record('qtype_ddimagetoimage', $options); + $DB->delete_records('qtype_ddimagetoimage_drops', array('questionid' => $formdata->id)); + foreach (array_keys($formdata->drops) as $dropno){ + if ($formdata->drops[$dropno]['xleft'] == ''){ + continue; } + $drop = new stdClass(); + $drop->questionid = $formdata->id; + $drop->no = $dropno + 1; + $drop->xleft = $formdata->drops[$dropno]['xleft']; + $drop->ytop = $formdata->drops[$dropno]['ytop']; + $drop->choice = $formdata->drops[$dropno]['choice']; + $drop->label = $formdata->drops[$dropno]['droplabel']; - } else { - // Legacy format containing PHP serialisation. - foreach ($data['#']['answer'] as $answerxml) { - $ans = $format->import_answer($answerxml); - $options = unserialize(stripslashes($ans->feedback['text'])); - $question->choices[] = array( - 'answer' => $ans->answer, - 'choicegroup' => $options->draggroup, - 'infinite' => $options->infinite, - ); + $DB->insert_record('qtype_ddimagetoimage_drops', $drop); + } + + $DB->delete_records('qtype_ddimagetoimage_drags', array('questionid' => $formdata->id)); + foreach (array_keys($formdata->drags) as $dragno){ + $info = file_get_draft_area_info($formdata->dragitem[$dragno]); + if ($info['filecount'] > 0) { + //numbers not allowed in filearea name + $filearea = str_replace(range('0', '9'), range('a', 'j'), "drag_$dragno"); + file_save_draft_area_files($formdata->dragitem[$dragno], $formdata->context->id, + 'qtype_ddimagetoimage', $filearea, $formdata->id, + array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); + $drag = new stdClass(); + $drag->questionid = $formdata->id; + $drag->no = $dragno + 1; + $drag->draggroup = $formdata->drags[$dragno]['draggroup']; + $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; + $drag->label = $formdata->drags[$dragno]['draglabel']; + + $DB->insert_record('qtype_ddimagetoimage_drags', $drag); } } - $format->import_combined_feedback($question, $data, true); - $format->import_hints($question, $data, true); - - return $question; + file_save_draft_area_files($formdata->bgimage, $formdata->context->id, + 'qtype_ddimagetoimage', 'bgimage', $formdata->id, + array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); } - public function export_to_xml($question, $format, $extra = null) { - $output = ''; - $output .= ' ' . $question->options->shuffleanswers . - "\n"; - - $output .= $format->write_combined_feedback($question->options); - - foreach ($question->options->answers as $answer) { - $options = unserialize($answer->feedback); - - $output .= " \n"; - $output .= $format->writetext($answer->answer, 3); - $output .= " {$options->draggroup}\n"; - if ($options->infinite) { - $output .= " \n"; - } - $output .= " \n"; - } - - return $output; - } } From 0fe992a97dc71a47b3e84cb4260dce1c1dbdd580 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 22 Jul 2011 16:25:14 +0700 Subject: [PATCH 031/208] MDL-47494 ddimageortext: NOBUG made a lot of progress with javascript necessary for question editing form and question attempt UI. --- .../edit_ddimagetoimage_form.php | 56 ++++++++++++++----- .../lang/en/qtype_ddimagetoimage.php | 3 + question/type/ddimageortext/renderer.php | 15 +---- question/type/ddimageortext/styles.css | 31 ++++++++++ 4 files changed, 78 insertions(+), 27 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 0c43a7ed611..bf34edb813d 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -46,7 +46,8 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { */ public static function file_picker_options() { $filepickeroptions = array(); - $filepickeroptions['accepted_types'] = array('web_image'); + //$filepickeroptions['accepted_types'] = array('web_image'); + $filepickeroptions['accepted_types'] = array('*'); $filepickeroptions['maxbytes'] = 0; $filepickeroptions['maxfiles'] = 1; $filepickeroptions['subdirs'] = 0; @@ -78,8 +79,15 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { * @param object $mform (the form being built). */ protected function definition_inner($mform) { - $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimagetoimage'), - null, self::file_picker_options()); + + $previewareaheaderelement = $mform->createElement('header', 'previewareaheader', + get_string('previewareaheader', 'qtype_ddimagetoimage')); + $mform->insertElementBefore($previewareaheaderelement, 'generalheader'); + $previewareaelement = $mform->createElement('static', 'previewarea', + get_string('previewarea', 'qtype_ddimagetoimage'), + get_string('previewareamessage', 'qtype_ddimagetoimage')); + $mform->insertElementBefore($previewareaelement, 'generalheader'); + list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); $this->definition_drop_zones($mform, $imagerepeats); @@ -98,6 +106,10 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $mform->addElement('header', 'dropzoneheader', get_string('dropzoneheader', 'qtype_ddimagetoimage')); + $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimagetoimage'), + null, self::file_picker_options()); + + $countdropzones = 0; if (isset($this->question->id)) { foreach ($this->question->options->drops as $drop) { @@ -136,6 +148,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $mform->setType('ytop', PARAM_NOTAGS); $options = array(); + $options[0] = ''; for ($i = 1; $i <= $imagerepeats; $i += 1) { $options[$i] = $i; } @@ -156,7 +169,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { protected function drop_zones_repeated_options() { $repeatedoptions = array(); - $repeatedoptions['choicegroup']['default'] = '1'; + $repeatedoptions['choice']['default'] = '0'; return $repeatedoptions; } @@ -204,6 +217,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { } public function data_preprocessing($question) { + global $PAGE; $question = parent::data_preprocessing($question); $question = $this->data_preprocessing_combined_feedback($question, true); @@ -225,8 +239,8 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { //numbers not allowed in filearea name $filearea = str_replace(range('0', '9'), range('a', 'j'), "drag_$imageindex"); file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', - $filearea, !empty($question->id) ? (int) $question->id : null, - self::file_picker_options()); + $filearea, !empty($question->id) ? (int) $question->id : null, + self::file_picker_options()); $question->dragitem[$imageindex] = $draftitemid; } $question->drops = array(); @@ -237,18 +251,34 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $question->drops[$drop->no -1]['xleft'] = $drop->xleft; $question->drops[$drop->no -1]['ytop'] = $drop->ytop; } + $draftitemid = file_get_submitted_draft_itemid('bgimage'); + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', + 'bgimage', !empty($question->id) ? (int) $question->id : null, + self::file_picker_options()); + $question->bgimage = $draftitemid; } - $draftitemid = file_get_submitted_draft_itemid('bgimage'); - file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', - 'bgimage', !empty($question->id) ? (int) $question->id : null, - self::file_picker_options()); - $question->bgimage = $draftitemid; - error_log(print_r(array('mform' => $this), true)); - error_log(print_r(compact('question'), true)); + $jsmodule = array( + 'name' => 'qtype_ddimagetoimage', + 'fullpath' => '/question/type/ddimagetoimage/module.js', + 'requires' => array('node', 'dd-drop', 'dd-constrain', 'form_filepicker') + ); + $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_form', + null, true, $jsmodule); + return $question; } + public static function file_get_draft_area_files($draftitemid) { + $toreturn = new stdClass(); + $toreturn->draftitemid = $draftitemid; + $draftareafiles = file_get_drafarea_files($draftitemid); + $draftareafile = reset($draftareafiles->list); + $toreturn->url = $draftareafile->url; + return $toreturn; + } + + public function validation($data, $files) { $errors = parent::validation($data, $files); diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index d836df9f9c2..6796aa9898a 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -38,6 +38,9 @@ $string['dropzoneheader'] = 'Drop zones'; $string['editingddimagetoimage'] = 'Editing drag and drop: images onto images'; $string['infinite'] = 'Infinite'; $string['label'] = 'Label'; +$string['previewarea'] = 'Preview area -'; +$string['previewareaheader'] = 'Preview'; +$string['previewareamessage'] = 'Choose a background image and draggable images and designate drop zones and they will be previewed here.'; $string['shuffleimages'] = 'Shuffle Draggable Images'; $string['xleft'] = 'Left'; $string['ytop'] = 'Top'; \ No newline at end of file diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 74750609547..ba760b4d5ed 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -44,20 +44,7 @@ class qtype_ddimagetoimage_renderer extends qtype_elements_embedded_in_question_ protected function post_qtext_elements(question_attempt $qa, question_display_options $options) { $result = ''; - $question = $qa->get_question(); - $dragboxs = ''; - foreach ($question->choices as $group => $choices) { - $dragboxs .= $this->drag_boxes($qa, $group, - $question->get_ordered_choices($group), $options); - } - $result .= html_writer::tag('div', $dragboxs, - array('class' => 'answercontainer')); - // We abuse the clear_wrong method to output the hidden form fields we - // want irrespective of whether we are actually clearing the wrong - // bits of the response. - if (!$options->clearwrong) { - $result .= $this->clear_wrong($qa, false); - } + return $result; } diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 4b26ec74d81..ccc0cf63947 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -68,3 +68,34 @@ .que.ddimagetoimage .group8 { background-color: #F0E68C; } + +form.mform fieldset#previewareaheader .drag { + border: 1px solid black; + background-color: #004C6D; + cursor: move; + margin: 5px; + z-index: 3; +} +form.mform fieldset#previewareaheader .dragitems { + clear:left; +} + + +form.mform fieldset#previewareaheader { + text-align : center; +} +form.mform fieldset#previewareaheader .dropbackground { + margin:0 auto; + background-color: #8DD5E7; + z-index: 1; +} +form.mform fieldset#previewareaheader .droptarget { + border: 1px solid black; + position: absolute; + background-color: #FFA928; + z-index: 2; +} + +form.mform fieldset#previewareaheader .droptarget.yui3-dd-drop-over { + background-color: #FFA928; +} From 649e58e904970bacad86cc0f1c89047993d0a771 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 1 Aug 2011 20:42:18 +0700 Subject: [PATCH 032/208] MDL-47494 ddimageortext: NOBUG implemented resizing of images,validity checks on form data, different sizes for margins so all items in a group take up the same screen real estate. --- question/type/ddimageortext/TODO.txt | 16 ++-- .../edit_ddimagetoimage_form.php | 86 +++++++++++++++---- .../lang/en/qtype_ddimagetoimage.php | 13 ++- question/type/ddimageortext/questiontype.php | 2 +- question/type/ddimageortext/styles.css | 40 +++++++-- 5 files changed, 120 insertions(+), 37 deletions(-) diff --git a/question/type/ddimageortext/TODO.txt b/question/type/ddimageortext/TODO.txt index 7c6564c25a1..aceaf24f456 100644 --- a/question/type/ddimageortext/TODO.txt +++ b/question/type/ddimageortext/TODO.txt @@ -1,16 +1,12 @@ -Question authoring form fields 2 hours -Display Image in authoring form -Calculation of size of drop zones -Calculate size of images, server side and save the sizes upon image upload -Display of drop zones on authoring form 4 hours +Question authoring form fields +* correct sizing of borders and margins + Question instance saving 2 hours Question instance loading 2 hours Question rendering code 6 hours -- correctly position images -- make images draggable -- react to drop of images -- write position that images where dropped to in hidden fields +- repurpose and extend authoring form code for question rendering +- make sure code works with multiple questions on the page +- get position that images where dropped to from hidden fields - grade question parts based on where images dragged to -- have position of images at start respond to saved state Testing and debugging for cross browser compatibility 4 hours diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index bf34edb813d..909fc2e479c 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -80,18 +80,16 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { */ protected function definition_inner($mform) { - $previewareaheaderelement = $mform->createElement('header', 'previewareaheader', + $mform->addElement('header', 'previewareaheader', get_string('previewareaheader', 'qtype_ddimagetoimage')); - $mform->insertElementBefore($previewareaheaderelement, 'generalheader'); - $previewareaelement = $mform->createElement('static', 'previewarea', + $mform->addElement('static', 'previewarea', get_string('previewarea', 'qtype_ddimagetoimage'), get_string('previewareamessage', 'qtype_ddimagetoimage')); - $mform->insertElementBefore($previewareaelement, 'generalheader'); list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); $this->definition_drop_zones($mform, $imagerepeats); - $mform->addElement('checkbox', 'shuffleanswers', ' ', + $mform->addElement('advcheckbox', 'shuffleanswers', ' ', get_string('shuffleimages', 'qtype_ddimagetoimage')); $mform->setDefault('shuffleanswers', 0); $mform->closeHeaderBefore('shuffleanswers'); @@ -202,9 +200,8 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { get_string('group', 'qtype_gapselect').' '); $grouparray[] = $mform->createElement('select', 'draggroup', get_string('group', 'qtype_gapselect'), $options); - $grouparray[] = $mform->createElement('checkbox', 'infinite', ' ', - get_string('infinite', 'qtype_ddimagetoimage'), null, - array('size' => 1, 'class' => 'tweakcss')); + $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ', + get_string('infinite', 'qtype_ddimagetoimage')); $draggableimageitem[] = $mform->createElement('group', 'drags', get_string('label', 'qtype_ddimagetoimage'), $grouparray); return $draggableimageitem; @@ -261,7 +258,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $jsmodule = array( 'name' => 'qtype_ddimagetoimage', 'fullpath' => '/question/type/ddimagetoimage/module.js', - 'requires' => array('node', 'dd-drop', 'dd-constrain', 'form_filepicker') + 'requires' => array('node', 'dd', 'dd-drop', 'dd-constrain', 'form_filepicker') ); $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_form', null, true, $jsmodule); @@ -269,19 +266,78 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { return $question; } - public static function file_get_draft_area_files($draftitemid) { - $toreturn = new stdClass(); - $toreturn->draftitemid = $draftitemid; + + public static function file_uploaded($draftitemid) { $draftareafiles = file_get_drafarea_files($draftitemid); - $draftareafile = reset($draftareafiles->list); - $toreturn->url = $draftareafile->url; - return $toreturn; + do { + $draftareafile = array_shift($draftareafiles->list); + } while ($draftareafile !== null && $draftareafile->filename == '.'); + if ($draftareafile === null) { + return false; + } + return true; } public function validation($data, $files) { $errors = parent::validation($data, $files); + if (!self::file_uploaded($data['bgimage'])){ + $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddimagetoimage'); + } + $allchoices = array(); + for ($i=0; $i < $data['nodropzone']; $i++) { + $ytoppresent = (trim($data['drops'][$i]['ytop']) !== ''); + $xleftpresent = (trim($data['drops'][$i]['ytop']) !== ''); + $labelpresent = (trim($data['drops'][$i]['droplabel']) !== ''); + $choice = $data['drops'][$i]['choice']; + $imagechoicepresent = ($choice !== '0'); + + if ($imagechoicepresent) { + if (!$ytoppresent) { + $errors["drops[$i]"] = + get_string('formerror_noytop', 'qtype_ddimagetoimage'); + } + if (!$xleftpresent) { + $errors["drops[$i]"] = + get_string('formerror_noxleft', 'qtype_ddimagetoimage'); + } + if (!self::file_uploaded($data['dragitem'][$choice - 1])) { + $errors["drops[$i]"] = + get_string('formerror_nofile', 'qtype_ddimagetoimage', $choice); + $errors['dragitem['.($choice - 1).']'] = + get_string('formerror_nofile2', 'qtype_ddimagetoimage', $i); + } + if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { + $errors["drops[$i]"] = + get_string('formerror_multipledraginstance', 'qtype_ddimagetoimage', $choice); + $errors['drops['.($allchoices[$choice]).']'] = + get_string('formerror_multipledraginstance', 'qtype_ddimagetoimage', $choice); + $errors['drags['.($choice-1).']'] = + get_string('formerror_multipledraginstance2', 'qtype_ddimagetoimage', $choice); + } + $allchoices[$choice] = $i; + } else { + if ($ytoppresent || $xleftpresent || $labelpresent) { + echo '
';
+                    var_dump(compact('ytoppresent', 'xleftpresent', 'labelpresent', 'choice'));
+                    echo '
'; + $errors["drops[$i]"] = + get_string('formerror_noimageselected', 'qtype_ddimagetoimage'); + } + } + + } + for ($i=0; $i < $data['noimages']; $i++) { + $labelpresent = (trim($data['drags'][$i]['draglabel']) !== ''); + $infinitechecked = (trim($data['drags'][$i]['infinite']) === '1'); + if (!self::file_uploaded($data['dragitem'][$i])) { + if ($infinitechecked || $labelpresent) { + $errors['dragitem['.($i).']'] = + get_string('formerror_nofile3', 'qtype_ddimagetoimage'); + } + } + } return $errors; } diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 6796aa9898a..6e0424cffe9 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -29,18 +29,27 @@ $string['answer'] = 'Answer'; $string['bgimage'] = 'Background Image'; $string['correctansweris'] = 'The correct answer is: {$a}'; $string['ddimagetoimage'] = 'Drag and drop: images onto images'; -$string['ddimagetoimage_help'] = 'Select a background image file, select a number of draggable images and define the drop zones on the background image to which they must be dragged.'; +$string['ddimagetoimage_help'] = 'Select a background image file, select draggable images and define the drop zones on the background image to which they must be dragged.'; $string['ddimagetoimagesummary'] = 'Images are dragged and dropped into drop zones on a background image.'; $string['draggableimage'] = 'Draggable image'; $string['draggableimageheader'] = 'Draggable image {$a}'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; $string['editingddimagetoimage'] = 'Editing drag and drop: images onto images'; +$string['formerror_noytop'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; +$string['formerror_noxleft'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; +$string['formerror_nofile'] = 'Although you selected drag image {$a} as the correct choice for this drop zone you have not selected an image for drag image {$a}.'; +$string['formerror_nofile2'] = 'You need to select an image file here, this drag item is referred to as the correct answer for drop zone {$a}.'; +$string['formerror_nofile3'] = 'You need to select an image file here, or delete the associated label and uncheck the infinite checkbox.'; +$string['formerror_multipledraginstance'] = 'You have selected this image {$a} more than once as the correct choice for a drop zone but it is not marked as being an infinite drag item.'; +$string['formerror_multipledraginstance2'] = 'You have selected this image more than once as the correct choice for a drop zone but it is not marked as being an infinite drag item.'; +$string['formerror_noimageselected'] = 'You need to select a drag item to be the correct choice for this drop zone.'; +$string['formerror_nobgimage'] = 'You need to select an image to use as the background for the drag and drop area.'; $string['infinite'] = 'Infinite'; $string['label'] = 'Label'; $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; -$string['previewareamessage'] = 'Choose a background image and draggable images and designate drop zones and they will be previewed here.'; +$string['previewareamessage'] = '
  • Select a background image file.
  • Select draggable images.
  • And define drop zones by selecting an image that the student must drag to the drop zone and drag it to where the student should drag it too.
'; $string['shuffleimages'] = 'Shuffle Draggable Images'; $string['xleft'] = 'Left'; $string['ytop'] = 'Top'; \ No newline at end of file diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 889a92a105d..b06c5641ca9 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -78,7 +78,7 @@ class qtype_ddimagetoimage extends question_type { $DB->update_record('qtype_ddimagetoimage', $options); $DB->delete_records('qtype_ddimagetoimage_drops', array('questionid' => $formdata->id)); foreach (array_keys($formdata->drops) as $dropno){ - if ($formdata->drops[$dropno]['xleft'] == ''){ + if ($formdata->drops[$dropno]['choice'] == 0){ continue; } $drop = new stdClass(); diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index ccc0cf63947..25216e5abf1 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -68,32 +68,54 @@ .que.ddimagetoimage .group8 { background-color: #F0E68C; } - +form.mform fieldset#previewareaheader .group1 { + background-color: #FFFFFF; +} +form.mform fieldset#previewareaheader .group2 { + background-color: #DCDCDC; +} +form.mform fieldset#previewareaheader .group3 { + background-color: #B0C4DE; +} +form.mform fieldset#previewareaheader .group4 { + background-color: #D8BFD8; +} +form.mform fieldset#previewareaheader .group5 { + background-color: #87CEFA; +} +form.mform fieldset#previewareaheader .group6 { + background-color: #DAA520; +} +form.mform fieldset#previewareaheader .group7 { + background-color: #FFD700; +} +form.mform fieldset#previewareaheader .group8 { + background-color: #F0E68C; +} +form.mform fieldset#previewareaheader img.draghome { + margin: 5px; + visibility : hidden; +} form.mform fieldset#previewareaheader .drag { border: 1px solid black; - background-color: #004C6D; cursor: move; - margin: 5px; - z-index: 3; + z-index: 2; } form.mform fieldset#previewareaheader .dragitems { clear:left; } -form.mform fieldset#previewareaheader { +form.mform fieldset#previewareaheader div.ddarea { text-align : center; } form.mform fieldset#previewareaheader .dropbackground { margin:0 auto; - background-color: #8DD5E7; - z-index: 1; } form.mform fieldset#previewareaheader .droptarget { border: 1px solid black; position: absolute; - background-color: #FFA928; - z-index: 2; + z-index: 1; } form.mform fieldset#previewareaheader .droptarget.yui3-dd-drop-over { From a61b274b69ab6f80e87b1b4255b46ead6deb30db Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 1 Aug 2011 21:12:45 +0700 Subject: [PATCH 033/208] MDL-47494 ddimageortext: NOBUG passing values of max heights and widths into js from PHP constants. --- .../type/ddimageortext/edit_ddimagetoimage_form.php | 12 ++++++++++-- question/type/ddimageortext/questiontype.php | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 909fc2e479c..b9ec560a4e8 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -260,8 +260,16 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { 'fullpath' => '/question/type/ddimagetoimage/module.js', 'requires' => array('node', 'dd', 'dd-drop', 'dd-constrain', 'form_filepicker') ); - $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_form', - null, true, $jsmodule); + $maxsizes =new stdClass(); + $maxsizes->bg_image = new stdClass(); + $maxsizes->bg_image->width = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH; + $maxsizes->bg_image->height = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXHEIGHT; + $maxsizes->drag_image = new stdClass(); + $maxsizes->drag_image->width = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH; + $maxsizes->drag_image->height = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT; + + $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_form', $maxsizes, + true, $jsmodule); return $question; } diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index b06c5641ca9..b9d882d06f5 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -31,6 +31,10 @@ require_once($CFG->dirroot . '/question/engine/lib.php'); require_once($CFG->dirroot . '/question/format/xml/format.php'); require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); +define('QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH', 600); +define('QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXHEIGHT', 400); +define('QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH', 150); +define('QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT', 100); /** * The drag-and-drop words into sentences question type class. From 8262ace5d07803bd2f612cf2c6e6385b5a4ad431 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 2 Aug 2011 09:18:32 +0700 Subject: [PATCH 034/208] MDL-47494 ddimageortext: NOBUG added server side resizing of oversize images. --- .../edit_ddimagetoimage_form.php | 2 +- question/type/ddimageortext/questiontype.php | 56 ++++++++++++++++++- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index b9ec560a4e8..430b7f99a03 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -268,7 +268,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $maxsizes->drag_image->width = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH; $maxsizes->drag_image->height = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT; - $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_form', $maxsizes, + $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_form', array($maxsizes), true, $jsmodule); return $question; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index b9d882d06f5..955866d930a 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -63,7 +63,7 @@ class qtype_ddimagetoimage extends question_type { } public function save_question_options($formdata) { - global $DB; + global $DB, $USER; $context = $formdata->context; $options = $DB->get_record('qtype_ddimagetoimage', array('questionid' => $formdata->id)); @@ -100,9 +100,14 @@ class qtype_ddimagetoimage extends question_type { foreach (array_keys($formdata->drags) as $dragno){ $info = file_get_draft_area_info($formdata->dragitem[$dragno]); if ($info['filecount'] > 0) { + $draftitemid = $formdata->dragitem[$dragno]; + //numbers not allowed in filearea name $filearea = str_replace(range('0', '9'), range('a', 'j'), "drag_$dragno"); - file_save_draft_area_files($formdata->dragitem[$dragno], $formdata->context->id, + self::constrain_image_size_in_draft_area($draftitemid, + QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH, + QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT); + file_save_draft_area_files($draftitemid, $formdata->context->id, 'qtype_ddimagetoimage', $filearea, $formdata->id, array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); $drag = new stdClass(); @@ -116,10 +121,57 @@ class qtype_ddimagetoimage extends question_type { } } + self::constrain_image_size_in_draft_area($formdata->bgimage, + QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH, + QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXHEIGHT); file_save_draft_area_files($formdata->bgimage, $formdata->context->id, 'qtype_ddimagetoimage', 'bgimage', $formdata->id, array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); } + public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) { + global $USER; + $usercontext = get_context_instance(CONTEXT_USER, $USER->id); + $fs = get_file_storage(); + $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id'); + if ($draftfiles) { + foreach ($draftfiles as $file) { + if ($file->is_directory()) { + continue; + } + $imageinfo = $file->get_imageinfo(); + $width = $imageinfo['width']; + $height = $imageinfo['height']; + $mimetype = $imageinfo['mimetype']; + switch ($mimetype) { + case 'image/jpeg' : + $quality = 80; + break; + case 'image/png' : + $quality = 8; + break; + default : + $quality = NULL; + } + $newwidth = min($maxwidth, $width); + $newheight = min($maxheight, $height); + if ($newwidth != $width || $newheight != $height) { + $newimagefilename = $file->get_filename(); + $newimagefilename = + preg_replace('!\.!', "_{$newwidth}x{$newheight}.", $newimagefilename, 1); + $newrecord = new stdClass(); + $newrecord->contextid = $usercontext->id; + $newrecord->component = 'user'; + $newrecord->filearea = 'draft'; + $newrecord->itemid = $draftitemid; + $newrecord->filepath = '/'; + $newrecord->filename = $newimagefilename; + $fs->convert_image($newrecord, $file, $newwidth, $newheight, true, $quality); + $file->delete(); + } + } + } + } + } From 3fbd84d956d9d98d30b474c634a3a732e218cb1d Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 8 Aug 2011 15:38:07 +0700 Subject: [PATCH 035/208] MDL-47494 ddimageortext: NOBUG new icon for question type --- question/type/ddimageortext/pix/icon.gif | Bin 867 -> 361 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/question/type/ddimageortext/pix/icon.gif b/question/type/ddimageortext/pix/icon.gif index f900852b7c387ee8fdbd61f26d031376af7966ac..f5705c637b7bd1003995fef64a48e51ae378b29e 100755 GIT binary patch literal 361 zcmV-v0hazpNk%w1VGsZi0M!5hBQ{wtLSi#VYBWe{H%DSPK~XzRY&}qMKT&T(RB}aB zZb(;iNm+AIQBhKKqgQyQU3{rwf2(7Gu4i?RXoRY1hOuplvvG~5a*eiikhge}xq60} zeTkicikg9qqJx^fhLNL)iiL=t!HuHAkEXAarpA@1$CjzcnXAd1r@5W4$DXLVp|iuH zv(BWrsiwBjsJGFmxYD%4w8YV`#nG|R+_Bu{x#H`-?(@s`_V)Ms-~9dV{r&v_00000 z00000A^8Le002DzEC2ui01yBW000Jtz>siAEDCwZq*8g@5T4NJCU-Ertp!prI)Z4IPFA2C1n50Hg({2?+-V0|KO^rydi#yu5}^QNdG3ImO1u#XLsK HL_q*M7u=r% literal 867 zcmZ?wbhEHb6krfw_|Cxa_wV1|zkmPy`Sa`7ub)4E{`m3ZhYug#ym|Bb_3IZeUOa#P z{PE+*4<9~Uy?XV+g$pN7o?KE=Vr6AzW@ct+XsDr~p{}m3q@*M+E-oY_#K*_Sz`*eT z|9>Dk3PwX$HPm=1$P=VpEuqZW<8gNHhqm80(b xSm4OqE2-`F=Ep@v_ij1IFrOJl4^K?jjg9*f@oC|qel5YIniHFsH#IO=0{~))R22XK From b59900489ac700b5ac2ea5a87d9d21ce045a9144 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 11 Aug 2011 14:17:43 +0700 Subject: [PATCH 036/208] MDL-47494 ddimageortext: NOBUG js for form and question pretty much finished. Some debugging still necessary. --- .../edit_ddimagetoimage_form.php | 3 - question/type/ddimageortext/question.php | 78 +++++- question/type/ddimageortext/questiontype.php | 58 ++++- question/type/ddimageortext/renderer.php | 228 +++++++++--------- question/type/ddimageortext/styles.css | 50 ++-- 5 files changed, 259 insertions(+), 158 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 430b7f99a03..4a44913ca3d 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -327,9 +327,6 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $allchoices[$choice] = $i; } else { if ($ytoppresent || $xleftpresent || $labelpresent) { - echo '
';
-                    var_dump(compact('ytoppresent', 'xleftpresent', 'labelpresent', 'choice'));
-                    echo '
'; $errors["drops[$i]"] = get_string('formerror_noimageselected', 'qtype_ddimagetoimage'); } diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 9476ab94a0b..342bbd79fa6 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -36,27 +36,87 @@ require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { - // Is actually exactly the same. + public function get_right_choice_for($placeno) { + $place = $this->places[$placeno]; + foreach ($this->choiceorder[$place->group] as $choicekey => $choiceid) { + if ($this->rightchoices[$placeno] == $choiceid) { + return $choicekey; + } + } + } + public function summarise_response(array $response) { + $matches = array(); + $allblank = true; + foreach ($this->places as $placeno => $place) { + if (array_key_exists($this->field($placeno), $response) && + $response[$this->field($placeno)]) { + $choices[] = '{' . html_to_text($this->get_selected_choice( + $place->group, $response[$this->field($placeno)])->text, 0, false) . '}'; + $allblank = false; + } else { + $choices[] = '{}'; + } + } + if ($allblank) { + return null; + } + return implode(' ', $choices); + } + + public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) { + if ($filearea == 'bgimage' || preg_match('!drag\_[a-j]+$!A', $filearea)) { + $validfilearea = true; + } else { + $validfilearea = false; + } + if ($component == 'qtype_ddimagetoimage' && $validfilearea) { + $question = $qa->get_question(); + $questionid = reset($args); // itemid is answer id. + return $questionid == $question->id; + } else { + return parent::check_file_access($qa, $options, $component, + $filearea, $args, $forcedownload); + } + } } /** - * Represents one of the choices (draggable boxes). + * Represents one of the choices (draggable images). * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_choice { - public $text; - public $draggroup; +class qtype_ddimagetoimage_drag_item { + public $alttextlabel; + public $no; + public $group; public $isinfinite; - public function __construct($text, $draggroup = 1, $isinfinite = false) { - $this->text = $text; - $this->draggroup = $draggroup; + public function __construct($alttextlabel, $no, $group = 1, $isinfinite = false) { + $this->text = $alttextlabel; + $this->no = $no; + $this->group = $group; $this->isinfinite = $isinfinite; } public function choice_group() { - return $this->draggroup; + return $this->group; } } +/** + * Represents one of the places (drop zones). + * + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddimagetoimage_drop_zone { + public $alttextlabel; + public $group; + public $xy; + + public function __construct($alttextlabel, $group = 1, $x = '', $y = '') { + $this->text = $alttextlabel; + $this->group = $group; + $this->xy = array($x, $y); + } +} \ No newline at end of file diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 955866d930a..5f455d5ede6 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -62,6 +62,55 @@ class qtype_ddimagetoimage extends question_type { parent::get_question_options($question); } + protected function make_choice($dragdata) { + return new qtype_ddimagetoimage_drag_item($dragdata->label, $dragdata->no, + $dragdata->draggroup, $dragdata->infinite); + } + + protected function make_place($dropzonedata) { + return new qtype_ddimagetoimage_drop_zone($dropzonedata->label, $dropzonedata->group, + $dropzonedata->xleft, $dropzonedata->ytop); + } + + protected function initialise_question_instance(question_definition $question, $questiondata) { + parent::initialise_question_instance($question, $questiondata); + $question->shufflechoices = $questiondata->options->shuffleanswers; + + $this->initialise_combined_feedback($question, $questiondata, true); + + $question->choices = array(); + $choiceindexmap= array(); + + // Store the choices in arrays by group. + foreach ($questiondata->options->drags as $dragdata) { + $filearea = self::drag_image_file_area($dragdata->no - 1); + + $choice = $this->make_choice($dragdata); + + if (array_key_exists($choice->choice_group(), $question->choices)) { + $question->choices[$choice->choice_group()][$dragdata->no] = $choice; + } else { + $question->choices[$choice->choice_group()][1] = $choice; + } + + end($question->choices[$choice->choice_group()]); + $choiceindexmap[$dragdata->no] = array($choice->choice_group(), + key($question->choices[$choice->choice_group()])); + } + + $question->places = array(); + $question->rightchoices = array(); + + $i = 1; + + foreach ($questiondata->options->drops as $dropdata) { + list($group, $choiceindex) = $choiceindexmap[$dropdata->choice]; + $dropdata->group = $group; + $question->places[$dropdata->no] = $this->make_place($dropdata); + $question->rightchoices[$dropdata->no] = $choiceindex; + } + } + public function save_question_options($formdata) { global $DB, $USER; $context = $formdata->context; @@ -102,8 +151,7 @@ class qtype_ddimagetoimage extends question_type { if ($info['filecount'] > 0) { $draftitemid = $formdata->dragitem[$dragno]; - //numbers not allowed in filearea name - $filearea = str_replace(range('0', '9'), range('a', 'j'), "drag_$dragno"); + $filearea = self::drag_image_file_area($dragno); self::constrain_image_size_in_draft_area($draftitemid, QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH, QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT); @@ -129,6 +177,12 @@ class qtype_ddimagetoimage extends question_type { array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); } + public static function drag_image_file_area($dragno) { + //numbers not allowed in filearea name + return str_replace(range('0', '9'), range('a', 'j'), "drag_$dragno"); + } + + public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) { global $USER; $usercontext = get_context_instance(CONTEXT_USER, $USER->id); diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index ba760b4d5ed..ef980b3293b 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -35,100 +35,9 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_renderer extends qtype_elements_embedded_in_question_text_renderer { - - protected function qtext_classname() { - return 'qtext ddimagetoimage_questionid_for_javascript'; - } - - protected function post_qtext_elements(question_attempt $qa, - question_display_options $options) { - $result = ''; - - return $result; - } - - /** - * Modify the contents of a drag/drop box to fix some IE-related problem. - * Unfortunately I don't have more details than that. - * @param string $string the box contents. - * @return string the box contents modified. - */ - protected function dodgy_ie_fix($string) { - return ' ' . $string . ' '; - } - - protected function embedded_element(question_attempt $qa, $place, - question_display_options $options) { - $question = $qa->get_question(); - $group = $question->places[$place]; - $boxcontents = $this->dodgy_ie_fix(' '); - - $value = $qa->get_last_qt_var($question->field($place)); - - $attributes = array( - 'id' => $this->box_id($qa, 'p' . $place, $group), - 'class' => 'slot group' . $group - ); - - if ($options->readonly) { - $attributes['class'] .= ' readonly'; - } else { - $attributes['tabindex'] = '0'; - } - - $feedbackimage = ''; - if ($options->correctness) { - $response = $qa->get_last_qt_data(); - $fieldname = $question->field($place); - if (array_key_exists($fieldname, $response)) { - $fraction = (int) ($response[$fieldname] == - $question->get_right_choice_for($place)); - $attributes['class'] .= ' ' . $this->feedback_class($fraction); - $feedbackimage = $this->feedback_image($fraction); - } - } - - return html_writer::tag('span', $boxcontents, $attributes) . ' ' . $feedbackimage; - } - - protected function drag_boxes($qa, $group, $choices, question_display_options $options) { - $readonly = ''; - if ($options->readonly) { - $readonly = ' readonly'; - } - - $boxes = ''; - foreach ($choices as $key => $choice) { - //Bug 8632 - long text entry causes bug in drag and drop field in IE - $content = str_replace('-', '‑', $choice->text); - $content = $this->dodgy_ie_fix(str_replace(' ', ' ', $content)); - - $infinite = ''; - if ($choice->isinfinite) { - $infinite = ' infinite'; - } - - $boxes .= html_writer::tag('span', $content, array( - 'id' => $this->box_id($qa, $key, $choice->draggroup), - 'class' => 'player group' . $choice->draggroup . $infinite . $readonly)) . ' '; - } - - return html_writer::nonempty_tag('div', $boxes, array('class' => 'answertext')); - } +class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_renderer { - public function head_code(question_attempt $qa) { - $this->page->requires->yui2_lib('dom'); - $this->page->requires->yui2_lib('event'); - $this->page->requires->yui2_lib('dragdrop'); - return parent::head_code($qa); - } - - /** - * Actually, this question type abuses this method to always ouptut the - * hidden fields it needs. - */ public function clear_wrong(question_attempt $qa, $reallyclear = true) { $question = $qa->get_question(); $response = $qa->get_last_qt_data(); @@ -138,38 +47,119 @@ class qtype_ddimagetoimage_renderer extends qtype_elements_embedded_in_question_ } else { $cleanresponse = $response; } + } + + public function formulation_and_controls(question_attempt $qa, + question_display_options $options) { + global $PAGE; + + $question = $qa->get_question(); + $response = $qa->get_last_qt_data(); $output = ''; - foreach ($question->places as $place => $group) { - $fieldname = $question->field($place); - if (array_key_exists($fieldname, $response)) { - $value = $response[$fieldname]; - } else { - $value = '0'; - } - if (array_key_exists($fieldname, $cleanresponse)) { - $cleanvalue = $cleanresponse[$fieldname]; - } else { - $cleanvalue = '0'; - } - if ($cleanvalue != $value) { - $output .= html_writer::empty_tag('input', array( - 'type' => 'hidden', - 'id' => $this->box_id($qa, 'p' . $place, $group) . '_hidden', - 'value' => s($value))) . - html_writer::empty_tag('input', array( - 'type' => 'hidden', - 'name' => $qa->get_qt_field_name($fieldname), - 'value' => s($cleanvalue))); - } else { - $output .= html_writer::empty_tag('input', array( - 'type' => 'hidden', - 'id' => $this->box_id($qa, 'p' . $place, $group) . '_hidden', - 'name' => $qa->get_qt_field_name($fieldname), - 'value' => s($value))); + $bgimage = self::get_url_for_image($qa, 'bgimage'); + + $img = html_writer::empty_tag('img', array('src'=>$bgimage, 'class'=>'dropbackground')); + $droparea = html_writer::tag('div', $img, array('class'=>'droparea')); + + $dragimagehomes = ''; + foreach ($question->choices as $groupno => $group) { + $dragimagehomesgroup = ''; + foreach ($group as $choiceno => $dragimage) { + $filearea = qtype_ddimagetoimage::drag_image_file_area($dragimage->no - 1); + $dragimageurl = self::get_url_for_image($qa, $filearea); + $classes = array("group{$groupno}", + 'draghome', + "dragimagehomes{$dragimage->no}", + "choice{$choiceno}"); + if ($dragimage->isinfinite) { + $classes[] = 'infinite'; + } + $dragimagehomesgroup .= html_writer::empty_tag('img', + array('src'=>$dragimageurl, + 'class'=>join(' ', $classes))); } + $dragimagehomes .= html_writer::tag('div', $dragimagehomesgroup, + array('class'=>'dragitemgroup'.$groupno)); } + + $dragitems = html_writer::tag('div', $dragimagehomes, array('class'=>'dragitems')); + $dropzones = html_writer::empty_tag('div', array('class'=>'dropzones')); + $output .= html_writer::tag('div', $droparea.$dragitems.$dropzones, + array('class'=>'ddarea')); + foreach ($question->places as $placeno => $place){ + $varname = $question->field($placeno); + list($fieldname, $html) = $this->hidden_field_for_qt_var($qa, $varname); + $output .= $html; + $question->places[$placeno]->fieldname = $fieldname; + } + $jsmodule = array( + 'name' => 'qtype_ddimagetoimage', + 'fullpath' => '/question/type/ddimagetoimage/module.js', + 'requires' => array('node', 'dd', 'dd-drop', 'dd-constrain') + ); + + $topnode = 'div#q'.$qa->get_slot().' div.ddarea'; + $sendtojs = array($question->places, $topnode, $options->readonly); + + $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_question', + $sendtojs, + true, + $jsmodule); return $output; } + protected static function get_url_for_image(question_attempt $qa, $filearea) { + $question = $qa->get_question(); + $qubaid = $qa->get_usage_id(); + $slot = $qa->get_slot(); + $fs = get_file_storage(); + $draftfiles = $fs->get_area_files($question->contextid, 'qtype_ddimagetoimage', + $filearea, $question->id, 'id'); + if ($draftfiles) { + foreach ($draftfiles as $file) { + if ($file->is_directory()) { + continue; + } + $url = moodle_url::make_pluginfile_url($question->contextid, 'qtype_ddimagetoimage', + $filearea, "$qubaid/$slot/{$question->id}", '/', + $file->get_filename()); + return $url->out(); + } + } + throw new coding_exception('File not found in filearea '.$filearea); + } + + protected function hidden_field_for_qt_var(question_attempt $qa, $varname) { + $value = $qa->get_last_qt_var($varname); + $fieldname = $qa->get_qt_field_name($varname); + $attributes = array('type'=>'text', + 'id' => str_replace(':', '_', $fieldname), + 'name'=> $fieldname, + 'value'=> $value); + return array($fieldname, html_writer::empty_tag('input', $attributes)."\n"); + } + + public function specific_feedback(question_attempt $qa) { + return $this->combined_feedback($qa); + } + + public function correct_response(question_attempt $qa) { + $question = $qa->get_question(); + + $correctanswer = ''; + foreach ($question->textfragments as $i => $fragment) { + if ($i > 0) { + $group = $question->places[$i]; + $choice = $question->choices[$group][$question->rightchoices[$i]]; + $correctanswer .= '[' . str_replace('-', '‑', + $choice->text) . ']'; + } + $correctanswer .= $fragment; + } + + if (!empty($correctanswer)) { + return get_string('correctansweris', 'qtype_gapselect', $correctanswer); + } + } } diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 25216e5abf1..807dbc95468 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -8,35 +8,14 @@ line-height: 2em; } -.que.ddimagetoimage .answercontainer { - line-height: 2em; - margin-bottom: 1em; - display: block; -} - -.que.ddimagetoimage .answertext { - padding-bottom: 0.5em; -} - -.que.ddimagetoimage .slot { - display: inline-block; - text-align: center; +.que.ddimagetoimage div.droparea img { border: 1px solid #000000; } -.que.ddimagetoimage .player { - display: inline-block; - text-align: center; - cursor: move; - border: 1px solid #000000; -} -.que.ddimagetoimage .player.placed { /* Lets the focus rectangle be visible in IE. */ - background: transparent; -} -.que.ddimagetoimage .readonly { - cursor: default; +.que.ddimagetoimage img.draghome { + margin: 5px; + visibility : hidden; } - .que.ddimagetoimage span.incorrect { background-color: #faa; } @@ -68,6 +47,27 @@ .que.ddimagetoimage .group8 { background-color: #F0E68C; } +.que.ddimagetoimage .drag { + border: 1px solid black; + cursor: move; + z-index: 2; +} +.que.ddimagetoimage div.ddarea { + text-align : center; +} +.que.ddimagetoimage .dropbackground { + margin:0 auto; +} +.que.ddimagetoimage .dropzone { + border: 1px solid black; + position: absolute; + z-index: 1; +} + +.que.ddimagetoimage .droptarget.yui3-dd-drop-over { + background-color: #FFA928; +} + form.mform fieldset#previewareaheader .group1 { background-color: #FFFFFF; } From b79b7fb6d5b313f84ffc57cac07817509e06c74f Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 11 Aug 2011 14:56:38 +0700 Subject: [PATCH 037/208] MDL-47494 ddimageortext: NOBUG small fix to ignore invalid values in hidden fields. --- question/type/ddimageortext/module.js | 516 ++++++++++++++++++++++++++ 1 file changed, 516 insertions(+) create mode 100644 question/type/ddimageortext/module.js diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js new file mode 100644 index 00000000000..98e5ce122a8 --- /dev/null +++ b/question/type/ddimageortext/module.js @@ -0,0 +1,516 @@ +M.qtype_ddimagetoimage={ + Y : null, + doc : null, + fp : null, + /** + * Entry point when called from question editing form + */ + init_form : function(Y, maxsizes) { + this.Y = Y; + this.fp = this.file_pickers(); + topnode = Y.one('fieldset#previewareaheader'); + topnode.append('
'+ + '
'+ + '
'); + this.doc = this.doc_structure(Y, topnode, this, maxsizes); + this.init_dd_area(); + }, + /** + * Entry point when called from question renderer + */ + init_question : function(Y, drops, topnodestr, readonly) { + this.Y = Y; + this.doc = this.doc_structure(Y, Y.one(topnodestr), this, null); + this.init_drops(drops); + var i = 0; + this.doc.drag_item_homes().each(function(dragitemhome){ + var dragimageno = + +this.doc.get_classname_numeric_suffix(dragitemhome, 'dragimagehomes'); + var choice = +this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); + var group = +this.doc.get_classname_numeric_suffix(dragitemhome, 'group') + var groupsize = this.doc.drop_zone_group(group).size(); + var dragnode = this.doc.clone_new_drag_item(i, dragimageno); + i++; + if (!readonly) { + this.doc.draggable_for_question(dragnode, group, choice); + } + if (dragnode.hasClass('infinite')) { + var dragstocreate = groupsize - 1; + while (dragstocreate > 0) { + dragnode = this.doc.clone_new_drag_item(i, dragimageno); + i++; + if (!readonly) { + this.doc.draggable_for_question(dragnode, group, choice); + } + dragstocreate--; + } + } + //put these here for easy refernece later + }, this); + this.doc.bg_img().on('load', this.delayed_redraw, this); + this.doc.drag_item_homes().on('load', this.delayed_redraw, this); + Y.on('windowresize', this.redraw, this); + }, + delayed_redraw : function (e) { + this.redraw(); + this.Y.later(2000, this, this.redraw); + }, + redraw : function(e) { + this.doc.drag_items().removeClass('placed'); + this.doc.drop_zones().each(function(dropzone) { + var relativexy = dropzone.getData('xy'); + dropzone.setXY(this.convert_to_window_xy(relativexy)); + var inputcss = 'input#' + dropzone.getData('inputid'); + var input = this.doc.top_node().one(inputcss); + var choice = input.get('value'); + if (choice !== "") { + var group = dropzone.getData('group'); + var dragitem = this.doc.top_node() + .one('div.dragitemgroup'+group+' img.choice'+choice+'.drag:not(.placed)'); + if (dragitem !== null) { + dragitem.setXY(dropzone.getXY()); + dragitem.addClass('placed'); + } + } + }, this); + this.doc.drag_items().each(function(dragitem) { + if (!dragitem.hasClass('placed')) { + var dragitemhome = this.doc.get_drag_image_home(dragitem.getData('dragimageno')); + dragitem.setXY(dragitemhome.getXY()); + } + }, this); + this.update_padding_sizes_all(); + }, + init_drops : function (drops) { + var dropareas = this.doc.top_node().one('div.dropzones'); + var groupnodes = {}; + for (var groupno =1; groupno <= 8; groupno++) { + var groupnode = this.Y.Node.create('
'); + dropareas.append(groupnode); + groupnodes[groupno] = groupnode; + } + for (var dropno in drops){ + var nodeclass = 'dropzone group'+drops[dropno].group+' place'+dropno; + var title = drops[dropno].text.replace('"', '\"'); + var dropnodehtml = '
 
'; + var dropnode = this.Y.Node.create(dropnodehtml); + groupnodes[drops[dropno].group].append(dropnode); + dropnode.setStyles({'opacity': 0.5}); + dropnode.setData('xy', drops[dropno].xy); + dropnode.setData('inputid', drops[dropno].fieldname.replace(':', '_')); + dropnode.setData('group', drops[dropno].group); + var dropdd = new this.Y.DD.Drop({ + node: dropnode}); + dropdd.on('drop:hit', function(e) { + var drag = e.drag.get('node'); + var drop = e.drop.get('node'); + if (+drop.getData('group') === drag.getData('group')){ + var inputid = drop.getData('inputid'); + var inputnode = this.Y.one('input#'+inputid); + inputnode.set('value', drag.getData('choice')); + } + }, this); + }; + }, + /** + * Object to encapsulate operations on dd area. + */ + doc_structure : function (Y, topnode, mainobj, maxsizes) { + var dragitemsarea = topnode.one('div.dragitems'); + var dropbgarea = topnode.one('div.droparea'); + return { + top_node : function() { + return topnode; + }, + drag_items : function() { + return dragitemsarea.all('img.drag'); + }, + drop_zones : function() { + return topnode.all('div.dropzones div.dropzone'); + }, + drop_zone_group : function(groupno) { + return topnode.all('div.dropzones div.group' + groupno); + }, + drag_items_cloned_from : function(dragimageno) { + return dragitemsarea.all('img.dragimages'+dragimageno); + }, + drag_item : function(draginstanceno) { + return dragitemsarea.one('img.draginstance' + draginstanceno); + }, + drag_item_homes : function() { + return dragitemsarea.all('img.draghome'); + }, + bg_img : function() { + return topnode.one('img.dropbackground'); + }, + load_bg_img : function (url) { + dropbgarea.setContent(''); + this.bg_img().on('load', this.on_image_load, this, 'bg_image'); + }, + add_or_update_drag_item_home : function (dragimageno, url, alt, group) { + var oldhome = dragitemsarea.one('img.dragimagehomes'+dragimageno); + var classes = 'draghome dragimagehomes'+dragimageno+' group'+group; + var imghtml = ''+alt+''; + if (oldhome === null) { + if (url) { + dragitemsarea.append(imghtml); + } + } else { + if (url) { + dragitemsarea.insert(imghtml, oldhome); + } + oldhome.remove(true); + } + var newlycreated = dragitemsarea.one('img.dragimagehomes'+dragimageno); + if (newlycreated !== null) { + newlycreated.setData('groupno', group); + newlycreated.setData('dragimageno', dragimageno); + newlycreated.on('load', this.on_image_load, this, 'drag_image'); + } + }, + on_image_load : function (e, imagetype) { + if (maxsizes !== null) { + var maxsize = maxsizes[imagetype]; + var reduceby = Math.max(e.target.get('width') / maxsize.width, + e.target.get('height') / maxsize.height); + if (reduceby > 1) { + e.target.set('width', Math.floor(e.target.get('width') / reduceby)); + } + } + }, + get_drag_image_home : function (dragimageno) { + return dragitemsarea.one('img.dragimagehomes' + dragimageno); + }, + get_classname_numeric_suffix : function(node, prefix) { + var classes = node.getAttribute('class'); + if (classes !== '') { + var classesarr = classes.split(' '); + for (index in classesarr) { + var patt1 = new RegExp('^'+prefix+'([0-9])+$'); + if (patt1.test(classesarr[index])) { + var patt2 = new RegExp('([0-9])+$'); + var match = patt2.exec(classesarr[index]); + return +match[0]; + } + } + } + throw 'Prefix "'+prefix+'" not found in class names.'; + }, + clone_new_drag_item : function (draginstanceno, dragimageno) { + var draghome = this.get_drag_image_home(dragimageno); + if (draghome === null) { + return null; + } + var drag = draghome.cloneNode(true); + drag.removeClass('dragimagehomes' + dragimageno); + drag.addClass('dragimages' + dragimageno); + drag.addClass('draginstance' + draginstanceno); + drag.removeClass('draghome'); + drag.addClass('drag'); + drag.setStyles({'visibility': 'visible', 'position' : 'absolute'}); + drag.setData('draginstanceno', draginstanceno); + drag.setData('dragimageno', dragimageno); + draghome.get('parentNode').appendChild(drag); + return drag; + }, + draggable_for_question : function (drag, group, choice) { + var dd = new Y.DD.Drag({ + node: drag, + dragMode: 'intersect' + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + dd.on('drag:end', function(e) { + mainobj.redraw(); + }, this); + drag.setData('group', group); + drag.setData('choice', choice); + + }, + draggable_for_form : function (drag) { + var dd = new Y.DD.Drag({ + node: drag, + dragMode: 'intersect' + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + dd.on('drag:end', function(e) { + var dragnode = e.target.get('node'); + var draginstanceno = dragnode.getData('draginstanceno'); + var gooddrop = dragnode.getData('gooddrop'); + var endxy; + + if (!gooddrop) { + mainobj.reset_drag_xy(draginstanceno); + } else { + endxy = [Math.round(e.pageX), Math.round(e.pageY)]; + mainobj.set_drag_xy(draginstanceno, endxy); + } + }, this); + dd.on('drag:start', function(e) { + var drag = e.target; + drag.get('node').setData('gooddrop', false); + }, this); + + } + + } + }, + + file_pickers : function () { + var draftitemidstoname; + var nametoparentnode; + if (draftitemidstoname === undefined) { + draftitemidstoname = {}; + nametoparentnode = {}; + var filepickers = this.Y.all('form.mform input.filepickerhidden'); + filepickers.each(function(filepicker, k, items) { + draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); + nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); + }, this); + } + var toreturn = { + file : function (name) { + var parentnode = nametoparentnode[name]; + var fileanchor = parentnode.one('div.filepicker-filelist a'); + if (fileanchor) { + return fileanchor.get('href'); + } else { + return null; + } + }, + name : function (draftitemid) { + return draftitemidstoname[draftitemid]; + } + } + return toreturn; + }, + /** + * Low level operations on form. + */ + form : { + to_name_with_index : function(name, indexes) { + indexes = indexes || []; + var indexstring = name; + for (var i=0; i < indexes.length; i++) { + indexstring = indexstring + '[' + indexes[i] + ']'; + } + return indexstring; + }, + get_form_value : function(name, indexes) { + var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; + if (el.type === 'checkbox') { + return el.checked; + } else { + return el.value; + } + }, + set_form_value : function(name, indexes, value) { + var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; + if (el.type === 'checkbox') { + el.checked = value; + } else { + el.value = value; + } + }, + from_name_with_index : function(name) { + var toreturn = {}; + toreturn.indexes = []; + var bracket = name.indexOf('['); + toreturn.name = name.substring(0, bracket); + while (bracket !== -1) { + var end = name.indexOf(']', bracket + 1); + toreturn.indexes.push(name.substring(bracket + 1, end)); + bracket = name.indexOf('[', end + 1); + } + return toreturn; + } + }, + + init_dd_area : function() { + //set up drag items homes + for (var i=0; i < this.form.get_form_value('noimages'); i++) { + var url = this.fp.file(this.form.to_name_with_index('dragitem', [i])); + this.doc.add_or_update_drag_item_home(i, url, + this.form.get_form_value('drags', [i, 'draglabel']), + this.form.get_form_value('drags', [i, 'draggroup'])); + } + + //set up drop zones + for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { + var dragimageno = this.form.get_form_value('drops', [i, 'choice']); + if (dragimageno !== '0') { + var drag = this.doc.clone_new_drag_item(i, dragimageno - 1); + if (drag !== null) { + this.doc.draggable_for_form(drag); + } + } + } + + this.setup_form_events(); + + this.doc.load_bg_img(this.fp.file(this.form.to_name_with_index('bgimage'))); + + var drop = new this.Y.DD.Drop({ + node: this.doc.bg_img() + }); + //Listen for a drop:hit on this target + drop.on('drop:hit', function(e) { + e.drag.get('node').setData('gooddrop', true); + }); + + this.Y.on('windowresize', this.reposition_drags, this); + + this.doc.bg_img().after('load', function(e) { + this.Y.later(3000, this, function (e) { + this.reposition_drags(); + this.update_padding_sizes_all(); + }, this); + }, this); + + }, + setup_form_events : function () { + //events triggered by changes to form data + this.Y.all('fieldset#dropzoneheader input').on('blur', function (e){ + var name = e.target.getAttribute('name'); + var nameparts = this.form.from_name_with_index(name); + this.reposition_drag(nameparts.indexes[0]); + }, this); + + this.Y.all('fieldset#dropzoneheader select').on('change', function (e){ + var name = e.target.getAttribute('name'); + var nameparts = this.form.from_name_with_index(name); + var draginstanceno = nameparts.indexes[0]; + this.update_drag_instance(draginstanceno); + }, this); + + this.Y.all('fieldset#dropzoneheader select').on('change', function (e){ + var name = e.target.getAttribute('name'); + var nameparts = this.form.from_name_with_index(name); + var draginstanceno = nameparts.indexes[0]; + this.update_drag_instance(draginstanceno); + }, this); + + for (var i=0; i < this.form.get_form_value('noimages'); i++) { + this.Y.all('fieldset#draggableimageheader_'+i+' select') + .on('change', this.on_drag_group_change, this); + } + + this.Y.after(this.after_image_upload, M.form_filepicker, 'callback', this); + + }, + on_drag_group_change : function (e){ + var name = e.target.getAttribute('name'); + var nameparts = this.form.from_name_with_index(name); + var dragimageno = nameparts.indexes[0]; + this.update_drag_image_home(dragimageno); + }, + after_image_upload : function (params) { + var url = params['url']; + var itemname = this.fp.name(params.id); + var itemnameparts = this.form.from_name_with_index(itemname); + if (itemnameparts.name === 'dragitem') { + var dragimageno = itemnameparts.indexes[0]; + this.update_drag_image_home(dragimageno); + } else { + this.doc.load_bg_img(url); + this.doc.bg_img().after('load', this.reposition_drags, this); + } + }, + update_padding_sizes_all : function () { + for (var groupno = 1; groupno <= 8; groupno++) { + this.update_padding_size_for_group(groupno); + } + }, + update_padding_size_for_group : function (groupno) { + var groupimages = this.doc.top_node().all('img.group'+groupno); + var maxwidth = 0; + var maxheight = 0; + groupimages.each(function(image){ + maxwidth = Math.max(maxwidth, image.get('width')); + maxheight = Math.max(maxheight, image.get('height')); + }, this); + groupimages.each(function(image) { + var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); + var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); + image.setStyle('padding', margintopbottom+'px '+marginleftright+'px'); + }, this); + this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, + 'height': maxheight + 10}); + }, + update_drag_image_home : function (dragimageno) { + dragimageno = +dragimageno; + var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])); + this.doc.add_or_update_drag_item_home(dragimageno, url, + this.form.get_form_value('drags', [dragimageno, 'draglabel']), + this.form.get_form_value('drags', [dragimageno, 'draggroup'])); + for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { + var dropdragimageno = this.form.get_form_value('drops', [i, 'choice']) - 1; + if (dropdragimageno === dragimageno) { + this.update_drag_instance(i); + } + } + }, + update_drag_instance : function(draginstanceno) { + var drag = this.doc.drag_item(draginstanceno); + var dragimageno = this.form.get_form_value('drops', [draginstanceno, 'choice']) - 1; + if (drag !== null) { + drag.remove(true); + } + drag = this.doc.clone_new_drag_item(draginstanceno, dragimageno); + this.doc.draggable_for_form(drag); + if (drag !== null) { + drag.on('load', function(e){ + this.reposition_drag(draginstanceno); + }, this); + } + }, + reposition_drags : function() { + this.doc.drag_items().each(function (drag) { + var draginstanceno = drag.getData('draginstanceno'); + this.reposition_drag(draginstanceno); + }, this); + }, + reposition_drag : function (draginstanceno) { + this.update_padding_sizes_all(); + var drag = this.doc.drag_item(draginstanceno); + if (null !== drag) { + var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), + this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; + if (fromform[0] == '' && fromform[1] == '') { + var dragimageno = drag.getData('dragimageno'); + drag.setXY(this.doc.get_drag_image_home(dragimageno).getXY()); + } else { + drag.setXY(this.convert_to_window_xy(this.constrain_xy(draginstanceno, fromform))); + } + } + }, + set_drag_xy : function (draginstanceno, xy) { + xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.round(xy[0])); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.round(xy[1])); + this.reposition_drag(draginstanceno); + }, + reset_drag_xy : function (draginstanceno) { + this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); + this.reposition_drag(draginstanceno); + }, + + //make sure xy value is not out of bounds of bg image + constrain_xy : function (draginstanceno, bgimgxy) { + var drag = this.doc.drag_item(draginstanceno); + var xleftconstrained = + Math.min(bgimgxy[0], this.doc.bg_img().get('width') - drag.get('offsetWidth')); + var ytopconstrained = + Math.min(bgimgxy[1], this.doc.bg_img().get('height') - drag.get('offsetHeight')); + xleftconstrained = Math.max(xleftconstrained, 0); + ytopconstrained = Math.max(ytopconstrained, 0); + return [xleftconstrained, ytopconstrained]; + }, + convert_to_bg_img_xy : function (windowxy) { + return [windowxy[0] - this.doc.bg_img().getX(), + windowxy[1] - this.doc.bg_img().getY()]; + }, + convert_to_window_xy : function (bgimgxy) { + return [+bgimgxy[0] + this.doc.bg_img().getX() + 1, + +bgimgxy[1] + this.doc.bg_img().getY() + 1]; + } + +} \ No newline at end of file From 5c951453e04faa17acd3cc7156bb42223a1d24d3 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 11 Aug 2011 16:13:30 +0700 Subject: [PATCH 038/208] MDL-47494 ddimageortext: NOBUG fixed problems with hint options 'show number correct' and 'clear wrong answers'. --- .../lang/en/qtype_ddimagetoimage.php | 1 + question/type/ddimageortext/question.php | 12 +- question/type/ddimageortext/questiontype.php | 4 + question/type/ddimageortext/renderer.php | 32 +- question/type/ddimageortext/script.js | 578 ------------------ 5 files changed, 36 insertions(+), 591 deletions(-) delete mode 100755 question/type/ddimageortext/script.js diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 6e0424cffe9..1f744a6e232 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -47,6 +47,7 @@ $string['formerror_noimageselected'] = 'You need to select a drag item to be the $string['formerror_nobgimage'] = 'You need to select an image to use as the background for the drag and drop area.'; $string['infinite'] = 'Infinite'; $string['label'] = 'Label'; +$string['nolabel'] = 'No label text'; $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = '
  • Select a background image file.
  • Select draggable images.
  • And define drop zones by selecting an image that the student must drag to the drop zone and drag it to where the student should drag it too.
'; diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 342bbd79fa6..f3571b71b58 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -30,12 +30,22 @@ require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); /** - * Represents a drag-and-drop words into sentences question. + * Represents a drag-and-drop images to image question. * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { + public function clear_wrong_from_response(array $response) { + foreach ($this->places as $place => $notused) { + if (array_key_exists($this->field($place), $response) && + $response[$this->field($place)] != $this->get_right_choice_for($place)) { + $response[$this->field($place)] = '0'; + } + } + return $response; + } + public function get_right_choice_for($placeno) { $place = $this->places[$placeno]; foreach ($this->choiceorder[$place->group] as $choicekey => $choiceid) { diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 5f455d5ede6..30a8e6f754a 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -72,6 +72,10 @@ class qtype_ddimagetoimage extends question_type { $dropzonedata->xleft, $dropzonedata->ytop); } + protected function make_hint($hint) { + return question_hint_with_parts::load_from_record($hint); + } + protected function initialise_question_instance(question_definition $question, $questiondata) { parent::initialise_question_instance($question, $questiondata); $question->shufflechoices = $questiondata->options->shuffleanswers; diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index ef980b3293b..ba8579b950f 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -38,15 +38,21 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_renderer { - public function clear_wrong(question_attempt $qa, $reallyclear = true) { + public function clear_wrong(question_attempt $qa) { $question = $qa->get_question(); $response = $qa->get_last_qt_data(); - if (!empty($response) && $reallyclear) { + if (!empty($response)) { $cleanresponse = $question->clear_wrong_from_response($response); } else { $cleanresponse = $response; } + $cleanresponsehtml = ''; + foreach ($cleanresponse as $fieldname => $value) { + list (, $html) = $this->hidden_field_for_qt_var($qa, $fieldname, $value); + $cleanresponsehtml .= $html; + } + return $cleanresponsehtml; } public function formulation_and_controls(question_attempt $qa, @@ -130,10 +136,12 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere throw new coding_exception('File not found in filearea '.$filearea); } - protected function hidden_field_for_qt_var(question_attempt $qa, $varname) { - $value = $qa->get_last_qt_var($varname); + protected function hidden_field_for_qt_var(question_attempt $qa, $varname, $value = null) { + if ($value === null) { + $value = $qa->get_last_qt_var($varname); + } $fieldname = $qa->get_qt_field_name($varname); - $attributes = array('type'=>'text', + $attributes = array('type'=>'hidden', 'id' => str_replace(':', '_', $fieldname), 'name'=> $fieldname, 'value'=> $value); @@ -148,14 +156,14 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $question = $qa->get_question(); $correctanswer = ''; - foreach ($question->textfragments as $i => $fragment) { - if ($i > 0) { - $group = $question->places[$i]; - $choice = $question->choices[$group][$question->rightchoices[$i]]; - $correctanswer .= '[' . str_replace('-', '‑', - $choice->text) . ']'; + foreach ($question->places as $i => $place) { + $choice = $question->choices[$place->group][$question->rightchoices[$i]]; + if ($choice->text != '') { + $text = $choice->text; + } else { + $text = get_string('nolabel', 'qtype_ddimagetoimage'); } - $correctanswer .= $fragment; + $correctanswer .= '[' . str_replace('-', '‑', $text) . ']'; } if (!empty($correctanswer)) { diff --git a/question/type/ddimageortext/script.js b/question/type/ddimageortext/script.js deleted file mode 100755 index 542e7ac2f4e..00000000000 --- a/question/type/ddimageortext/script.js +++ /dev/null @@ -1,578 +0,0 @@ -// This file is part of Moodle - http://moodle.org/ -// -// 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 . - -/** - * JavaScript objects, functions as well as usage of some YUI library for - * enabling drag and drop interaction for dran-anddrop words into sentences - * (ddimagetoimage) - * - * @package qtype - * @subpackage ddimagetoimage - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -//global variables -var ddimagetoimage_currentzindex = 10; - - -/* - * The way it seems to be, if there are more than one of this type of question - * on a page, then this file is shared between them. Therefore it has to cope - * with ALL the questions of this type on the page. - */ -(function() { - - // start of App object by all questions of this type on a page. - YAHOO.example.DDApp = { - init : function() { - var questionspans = YAHOO.util.Dom.getElementsByClassName("ddimagetoimage_questionid_for_javascript"); - - // we need this loop in case of more than one of this qtype on one page - for (var i = 0; i < questionspans.length; i++) { - // The Questions object should now contain a QuestionDataObject - // object for each question of this type on the page. - Questions[questionspans[i].id] = new QuestionDataObject(questionspans[i].id); - } - - // populate the arrays "slots" and "players" for each question - var tempSlots = YAHOO.util.Dom.getElementsByClassName("slot", "span"); - var tempPlayers = YAHOO.util.Dom.getElementsByClassName("player", "span"); - - //ie7 zoom message - ie7_zoom_message(); - - for (var i = 0; i < tempSlots.length; i++) { - var name_prefix = tempSlots[i].id.split("_")[0] + "_"; - var q = Questions[name_prefix]; - var g = getGroupForThis(tempSlots[i].id); - - var ddtarget = new YAHOO.util.DDTarget(tempSlots[i].id, g); - q.tempSlots.push(tempSlots[i]); - q.slots.push(ddtarget); - } - - for (var i = 0; i < tempPlayers.length; i++) { - var name_prefix = tempPlayers[i].id.split("_")[0] + "_"; - var q = Questions[name_prefix]; - var g = getGroupForThis(tempPlayers[i].id); - var ddplayer = new YAHOO.example.DDPlayer(tempPlayers[i].id, g); - q.tempPlayers.push(tempPlayers[i]); - q.players.push(ddplayer); - } - - for (var i = 0; i < questionspans.length; i++) { - var q = Questions[questionspans[i].id]; - var groupwidth = getWidthForAllGroups(q.tempPlayers); - for (var j = 0; j < q.tempSlots.length; j++) { - var g = getGroupForThis(q.tempSlots[j].id); - setWidth(q.tempSlots[j], groupwidth[g]); - } - for (var j = 0; j < q.tempPlayers.length; j++) { - var g = getGroupForThis(q.tempPlayers[j].id); - setWidth(q.tempPlayers[j], groupwidth[g]); - } - - // set responses for all slots - setResponsesForAllSlots(q.tempSlots, q.tempPlayers); - } - } - }; - // end of App object //////////////////////////////////////////////////////// - - // beginning of Player object (the draggable item) ////////////////////////// - YAHOO.example.DDPlayer = function(id, sGroup, config) { - YAHOO.example.DDPlayer.superclass.constructor.apply(this, arguments); - this.initPlayer(id, sGroup, config); - }; - - YAHOO.extend(YAHOO.example.DDPlayer, YAHOO.util.DD, { - TYPE :"DDPlayer", - - initPlayer : function(id, sGroup, config) { - this.isTarget = false; - this.currentPos = YAHOO.util.Dom.getXY(this.getEl()); - }, - - //Abstract method called after a drag/drop object is clicked and the drag or mousedown time thresholds have beeen met. - startDrag : function(x, y) { - YAHOO.util.Dom.setStyle(this.getEl(), "zIndex", ddimagetoimage_currentzindex++); - YAHOO.util.Dom.removeClass(this.getEl(), 'placed'); - - if (is_infinite(this.getEl()) && !this.slot){ - var currentplayer = this.getEl().id.replace(/_clone[0-9]+$/, ''); - var ddplayer = YAHOO.util.DragDropMgr.getDDById(currentplayer); - clone_player(ddplayer); - } - - if (this.slot) { // dragging starts from a slot - var hiddenElement = document.getElementById(this.slot.getEl().id + '_hidden'); - hiddenElement.value = ''; - this.slot.player = null; - this.slot = null; - } - }, - - //Abstract method called when this item is dropped on another DragDrop obj - onDragDrop : function(e, id) { - // get the drag and drop object that was targeted - var target = YAHOO.util.DragDropMgr.getDDById(id); - var dragged = this.getEl(); - - //get the question-prefix of slot and player and check whether they belong to the same question - var slotprefix = target.id.split("_")[0] + "_"; - var playerprefix = dragged.id.split("_")[0] + "_"; - if (slotprefix != playerprefix){ - var p = YAHOO.util.DragDropMgr.getDDById(dragged.id); - p.startDrag(0,0); - p.onInvalidDrop(null); - return; - } - - show_element(this.getEl()); - - if (target.player) { // there's a player already there - var oldplayer = target.player; - oldplayer.startDrag(0,0); - oldplayer.onInvalidDrop(null); - } - - YAHOO.util.DragDropMgr.moveToEl(dragged, target.getEl()); - this.slot = target; - target.player = this; - YAHOO.util.Dom.setXY(target.player.getEl(), YAHOO.util.Dom.getXY(target.getEl())); - YAHOO.util.Dom.addClass(this.getEl(), 'placed'); - if (YAHOO.util.Dom.hasClass(target.getEl(), 'readonly')) { - if (YAHOO.util.Dom.hasClass(target.getEl(), 'correct')) { - YAHOO.util.Dom.addClass(this.getEl(), 'correct'); - } else if (YAHOO.util.Dom.hasClass(target.getEl(), 'incorrect')) { - YAHOO.util.Dom.addClass(this.getEl(), 'incorrect'); - } - } - - // set value - var hiddenElement = document.getElementById(id + '_hidden'); - hiddenElement.value = this.getEl().id.split("_")[1]; - }, - - //Abstract method called when this item is dropped on an area with no drop target - onInvalidDrop : function(e) { - YAHOO.util.Dom.setXY(this.getEl(), YAHOO.util.Dom.getXY(this.originalplayer.getEl())); - YAHOO.util.Dom.removeClass(this.getEl(), 'placed'); - } - }); - // end of Player object (the draggable item) //////////////////////////////// - - YAHOO.util.Event.onDOMReady(YAHOO.example.DDApp.init, YAHOO.example.DDApp, true); - - // Objects/////////////////////////////////////////////////////////////////// - var Questions = new Object(); - - function QuestionDataObject(theid) { - this.id = theid; - this.tempSlots = []; - this.tempPlayers = []; - this.slots = []; - this.players = []; - } - - // template for the slot object - function SlotObject(id, group, currentvalue, values, callback) { - this.id = id; - this.group = group; - this.currentvalue = currentvalue; - this.values = values; - this.callback = callback; - } - // End of Objects /////////////////////////////////////////////////////////// - - // functions //////////////////////////////////////////////////////////////// - - function clone_player(p) { - var el = p.getEl(); - var newNode = document.createElement('div'); - newNode.className = el.className; - newNode.innerHTML = el.innerHTML; - - if (!p.clones) { - p.clones = []; - } - newNode.id = el.id + '_clone' + p.clones.length; // _clone0 for first - - newNode.style.position = 'absolute'; - - var region = YAHOO.util.Dom.getRegion(el); - var height = region.bottom - region.top; - var width = region.right - region.left; - - // -2 is becuase get_region includes the border, but style.width/height does not. - newNode.style.height = (height - 2) + "px"; - newNode.style.width = (width - 2) + "px"; - - el.parentNode.parentNode.appendChild(newNode); - YAHOO.util.Dom.setXY(newNode, YAHOO.util.Dom.getXY(el)); - - var g = getGroupForThis(el.id); - var p2 = new YAHOO.example.DDPlayer(newNode.id, g); - p2.originalplayer = p; - - hide_element(el); - show_element(newNode); - - if (is_readonly(newNode)) { - p2.lock(); - } - - p.clones[p.clones.length] = p2; - return p2; - } - - function clone_players(players){ - for (var i = 0; i < players.length; i++) { - var p = YAHOO.util.DragDropMgr.getDDById(players[i].id); - clone_player(p); - } - } - - function is_readonly(el){ - return YAHOO.util.Dom.hasClass(el, 'readonly'); - } - - function is_infinite(el){ - return YAHOO.util.Dom.hasClass(el, 'infinite'); - } - - function show_element(el){ - YAHOO.util.Dom.setStyle(el, 'visibility', 'visible'); - } - - function hide_element(el){ - YAHOO.util.Dom.setStyle(el, 'visibility', 'hidden'); - } - - function list_of_slots_and_players(slots, players) { - this.slots = slots; - this.players = players; - } - - function set_xy_after_resize(e, slotsandplayerobj){ - setTimeout(function() { - set_xy_after_resize_actual(e,slotsandplayerobj); - }, 0); - } - - function set_xy_after_resize_actual(e, slotsandplayerobj) { - var slots = slotsandplayerobj.slots; - var players = slotsandplayerobj.players; - for (var i = 0; i < players.length; i++) { - var original = YAHOO.util.DragDropMgr.getDDById(players[i].id); - for (var index in original.clones) { - var c = original.clones[index]; - if (c.slot) { - //player is in slot - YAHOO.util.Dom.setXY(c.getEl(), YAHOO.util.Dom.getXY(c.slot.getEl())); - } else { - //player is not in slot - YAHOO.util.Dom.setXY(c.getEl(), YAHOO.util.Dom.getXY(c.originalplayer.getEl())); - } - } - } - } - - function setResponsesForAllSlots(slots, players) { - clone_players(players); - - for (var i = 0; i < slots.length; i++) { - var slot = slots[i]; - - var hiddenElement = document.getElementById(slot.id + '_hidden'); - if (!hiddenElement) { - continue; - } - - // get group - var group = getGroupForThis(slot.id); - - // get array of values - var values = getValuesForThisSlot(slot.id, players); - - var currentvalue = parseInt(hiddenElement.value); - // if slot is occupied - if (currentvalue) { - // Find player - var idbits = hiddenElement.id.split('_'); - idbits[1] = currentvalue; - idbits.pop(); - var newid = idbits.join('_'); - var original = YAHOO.util.DragDropMgr.getDDById(newid); - var index = original.clones.length - 1; - original.clones[index].startDrag(0, 0); - original.clones[index].onDragDrop(null, slot.id); - } - YAHOO.util.Event.addListener(slot.id, "focus", setFocus); - YAHOO.util.Event.addListener(slot.id, "blur", setBlur); - - YAHOO.util.Event.addListener(slot.id, "mousedown", mouseDown); - - var myobj = new SlotObject(slot.id, group, currentvalue, values, funCallKeys); - - // event keydown - YAHOO.util.Event.addListener(slot.id, "keydown", funCallKeys, myobj); - } - - //resize - var listofslotsandplayers = new list_of_slots_and_players(slots, players); - YAHOO.util.Event.addListener(window, "resize", set_xy_after_resize, listofslotsandplayers); - YAHOO.util.Event.addListener(window, "load", set_xy_after_resize, listofslotsandplayers); - } - - function getValuesForThisSlot(slotid, players) { - var gslot = getGroupForThis(slotid); - var values = []; - var j = 0; - for (var i = 0; i < players.length; i++) { - var pElement = players[i]; - var gplayer = getGroupForThis(pElement.id); - - // from the same group - if (gslot == gplayer) { - values[j++] = pElement.id; - } - } - return values; - } - - function getWidthForAllGroups(allplayers) { - var widtharray = []; - for (var i = 0; i < allplayers.length; i++) { - var g = getGroupForThis(allplayers[i].id); - var width = getWidthForThisElement(allplayers[i]); - if (!widtharray[g] || width > widtharray[g]) { - widtharray[g] = width; - } - } - return widtharray; - } - - function getWidthForThisGroup(allplayers, group) { - var tempwidth = 0; - for (var i = 0; i < allplayers.length; i++) { - var g = getGroupForThis(allplayers[i].id); - if (group != g) { - continue; - } - var width = getWidthForThisElement(allplayers[i]); - if (width > tempwidth) { - tempwidth = width; - } - } - return tempwidth; - } - - function getWidthForThisElement(el) { - var region = YAHOO.util.Dom.getRegion(el); - return region.right - region.left; - } - - function setWidth(el, gwidth) { - var width = getWidthForThisElement(el); - var remainder = (gwidth - width) + 10; - - // IE8 does not rewrap lines when the padding changes, so this - // change uses different layout for that browser version only. - if (navigator.appVersion.indexOf('MSIE 8') != -1) { - var region = YAHOO.util.Dom.getRegion(el); - var height = region.bottom - region.top; - el.style.display = 'inline-block'; - el.style.width = gwidth + 'px'; - el.style.height = height + 'px'; - return; - } - - YAHOO.util.Dom.setStyle(el, 'padding-right', Math.floor((remainder + 1) / 2) + 'px'); - YAHOO.util.Dom.setStyle(el, 'padding-left', Math.floor(remainder / 2) + 'px'); - } - - function funCallKeys(e, slotobj) { - //disable the key access when readonly - if (is_readonly(document.getElementById(slotobj.values[0]))) { - return; - } - - var evt = e || window.event; - var key = evt.keyCode; - - switch (key) { - case 39: // arrow right (forwards) - case 40: // arrow down (forwards) - case 32: // space (forwards) - changeObject(slotobj, 1); - return false; //this has to return false because of IE - - case 37: // arrow left (backwards) - case 38: // arrow up (backwards) - changeObject(slotobj, -1); - return false; //this has to return false because of IE - - case 66: // B (backwards) - case 98: // b (backwards) - case 80: // P (previous) - case 112: // p (previous) - changeObject(slotobj, -1); - break; - - case 13: // cariage return (forwards) - case 70: // F (forwards) - case 102: // f (forwards) - case 78: // N (next) - case 110: // n (next) - changeObject(slotobj, 1); - break; - - case 27: // escape (empty the drop box) - changeObject(slotobj, 0); - default: - return true; - } - return true; - } - - function changeObject(slotobj, direction) { - // Prevent infinite loop if there are no values for this slot - if (slotobj.values.length == 0) { - return; - } - - if (direction == 0) { - call_YUI_startDrag_onInvalidDrop(slotobj); - return; - } - - var hiddenElement = document.getElementById(slotobj.id + '_hidden'); - - // Get current position in values list - var selectedIndex = -1; - for(var i = 0; i < slotobj.values.length; i++) { - if (slotobj.values[i].split("_")[1] == hiddenElement.value) { - selectedIndex = i; - break; - } - } - - var currentIndex = selectedIndex; - while (true) { - // Get new position in values list - selectedIndex += direction; - if (selectedIndex > slotobj.values.length) { - selectedIndex-= slotobj.values.length + 1; - } - if (selectedIndex < 0) { - selectedIndex += slotobj.values.length + 1; - } - - //empty the slot at the beginning or the end of the players list - if (selectedIndex == slotobj.values.length) { - call_YUI_startDrag_onInvalidDrop(slotobj); - return; - } - - // If we loop round back to the current one then there are - // no more options, so stop - if (selectedIndex == currentIndex) { - break; - } - - // Check the item at the new position is not used - var original = YAHOO.util.DragDropMgr.getDDById(slotobj.values[selectedIndex]); - var index = original.clones.length - 1; - if (!original.clones[index].slot) { - // This one is not in a slot so we can use it - original.clones[index].startDrag(0, 0); - original.clones[index].onDragDrop(null, slotobj.id); - break; - } - } - } - - function call_YUI_startDrag_onInvalidDrop(slotobj){ - var target = YAHOO.util.DragDropMgr.getDDById(slotobj.id); - if (!target.player) { - return; - } - var player = target.player; - - // Find player and call YUI methods - player.startDrag(0, 0); - player.onInvalidDrop(null); - } - - function getGroupForThis(str) { - var g = str.split("_")[2]; - return g; - } - - function mouseDown() { - } - - function setFocus() { - YAHOO.util.Dom.addClass(this, 'focussed'); - } - - function setBlur() { - YAHOO.util.Dom.removeClass(this, 'focussed'); - } - - function ie7_zoom_message (){ - var browser = navigator.appVersion; - if (browser.indexOf('MSIE 7') > -1){ - var b = document.body.getBoundingClientRect(); - var magnifactor = (b.right - b.left)/document.body.clientWidth; - if (magnifactor < 0.9 || magnifactor > 1.1){ - - var answers = YAHOO.util.Dom.getElementsByClassName("answercontainer", "div"); - for(var i=0; i Date: Thu, 11 Aug 2011 17:39:11 +0700 Subject: [PATCH 039/208] MDL-47494 ddimageortext: NOBUG make the cursor not change to the move cursor over drag objects when in readonly mode. --- question/type/ddimageortext/renderer.php | 6 +++++- question/type/ddimageortext/styles.css | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index ba8579b950f..1236fad7e22 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -89,7 +89,11 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere array('class'=>'dragitemgroup'.$groupno)); } - $dragitems = html_writer::tag('div', $dragimagehomes, array('class'=>'dragitems')); + $dragitemsclass = 'dragitems'; + if ($options->readonly) { + $dragitemsclass .= ' readonly'; + } + $dragitems = html_writer::tag('div', $dragimagehomes, array('class'=> $dragitemsclass)); $dropzones = html_writer::empty_tag('div', array('class'=>'dropzones')); $output .= html_writer::tag('div', $droparea.$dragitems.$dropzones, array('class'=>'ddarea')); diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 807dbc95468..d1e5bfc97c3 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -52,6 +52,9 @@ cursor: move; z-index: 2; } +.que.ddimagetoimage .dragitems.readonly .drag { + cursor: auto; +} .que.ddimagetoimage div.ddarea { text-align : center; } From 9ba6e055cc53c6aa02397cb4a5419bf5f45131b3 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 11 Aug 2011 17:40:02 +0700 Subject: [PATCH 040/208] MDL-47494 ddimageortext: NOBUG file access function that I forgot to add and commit earlier. --- question/type/ddimageortext/lib.php | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 question/type/ddimageortext/lib.php diff --git a/question/type/ddimageortext/lib.php b/question/type/ddimageortext/lib.php new file mode 100644 index 00000000000..542f7c46dbc --- /dev/null +++ b/question/type/ddimageortext/lib.php @@ -0,0 +1,39 @@ +. + +/** + * Serve question type files + * + * @since 2.0 + * @package qtype + * @subpackage essay + * @copyright Dongsheng Cai + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + + +/** + * Checks file access for essay questions. + */ +function qtype_ddimagetoimage_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { + global $CFG; + require_once($CFG->libdir . '/questionlib.php'); + question_pluginfile($course, $context, 'qtype_ddimagetoimage', + $filearea, $args, $forcedownload); +} From 1d5ba964234bd6da9b071c88f875f539a522ff96 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 11 Aug 2011 18:22:27 +0700 Subject: [PATCH 041/208] MDL-47494 ddimageortext: NOBUG ironed out a few bugs with drag item choice nos. --- question/type/ddimageortext/module.js | 24 ++++++++++++++++++++++++ question/type/ddimageortext/question.php | 2 +- question/type/ddimageortext/renderer.php | 10 ++++++---- question/type/ddimageortext/styles.css | 8 ++++---- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index 98e5ce122a8..394b649104c 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -57,6 +57,11 @@ M.qtype_ddimagetoimage={ }, redraw : function(e) { this.doc.drag_items().removeClass('placed'); + this.doc.drag_items().each (function (dragitem) { + if (dragitem.dd !== undefined) { + dragitem.dd.detachAll('drag:start'); + } + }, this); this.doc.drop_zones().each(function(dropzone) { var relativexy = dropzone.getData('xy'); dropzone.setXY(this.convert_to_window_xy(relativexy)); @@ -70,6 +75,12 @@ M.qtype_ddimagetoimage={ if (dragitem !== null) { dragitem.setXY(dropzone.getXY()); dragitem.addClass('placed'); + if (dragitem.dd !== undefined) { + dragitem.dd.once('drag:start', function (e, input) { + input.set('value', ''); + e.target.get('node').removeClass('placed'); + },this, input); + } } } }, this); @@ -97,6 +108,7 @@ M.qtype_ddimagetoimage={ groupnodes[drops[dropno].group].append(dropnode); dropnode.setStyles({'opacity': 0.5}); dropnode.setData('xy', drops[dropno].xy); + dropnode.setData('place', dropno); dropnode.setData('inputid', drops[dropno].fieldname.replace(':', '_')); dropnode.setData('group', drops[dropno].group); var dropdd = new this.Y.DD.Drop({ @@ -218,6 +230,18 @@ M.qtype_ddimagetoimage={ node: drag, dragMode: 'intersect' }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + +// dd.on('drag:start', function(e) { +// var drag = e.target.get('node'); +// var inputid = drag.getData('placedonid'); +// if (inputid !== undefined || inputid !== null) { +// var inputnode = this.Y.one('input#'+inputid); +// if (inputnode !== null) { +// inputnode.set('value', ''); +// } +// } +// drag.setData('placedonid', ''); +// }, this); dd.on('drag:end', function(e) { mainobj.redraw(); }, this); diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index f3571b71b58..186dfdfbc4b 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -40,7 +40,7 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { foreach ($this->places as $place => $notused) { if (array_key_exists($this->field($place), $response) && $response[$this->field($place)] != $this->get_right_choice_for($place)) { - $response[$this->field($place)] = '0'; + $response[$this->field($place)] = ''; } } return $response; diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 1236fad7e22..76e5154a123 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -69,9 +69,11 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $droparea = html_writer::tag('div', $img, array('class'=>'droparea')); $dragimagehomes = ''; + dbg($question); foreach ($question->choices as $groupno => $group) { $dragimagehomesgroup = ''; - foreach ($group as $choiceno => $dragimage) { + $orderedgroup = $question->get_ordered_choices($groupno); + foreach ($orderedgroup as $choiceno => $dragimage) { $filearea = qtype_ddimagetoimage::drag_image_file_area($dragimage->no - 1); $dragimageurl = self::get_url_for_image($qa, $filearea); $classes = array("group{$groupno}", @@ -145,10 +147,10 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $value = $qa->get_last_qt_var($varname); } $fieldname = $qa->get_qt_field_name($varname); - $attributes = array('type'=>'hidden', + $attributes = array('type' => 'hidden', 'id' => str_replace(':', '_', $fieldname), - 'name'=> $fieldname, - 'value'=> $value); + 'name' => $fieldname, + 'value' => $value); return array($fieldname, html_writer::empty_tag('input', $attributes)."\n"); } diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index d1e5bfc97c3..14550510814 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -27,10 +27,10 @@ background-color: #FFFFFF; } .que.ddimagetoimage .group2 { - background-color: #DCDCDC; + background-color: #B0C4DE; } .que.ddimagetoimage .group3 { - background-color: #B0C4DE; + background-color: #DCDCDC; } .que.ddimagetoimage .group4 { background-color: #D8BFD8; @@ -75,10 +75,10 @@ form.mform fieldset#previewareaheader .group1 { background-color: #FFFFFF; } form.mform fieldset#previewareaheader .group2 { - background-color: #DCDCDC; + background-color: #B0C4DE; } form.mform fieldset#previewareaheader .group3 { - background-color: #B0C4DE; + background-color: #DCDCDC; } form.mform fieldset#previewareaheader .group4 { background-color: #D8BFD8; From 9e5f72e1163436f943b84dc9b616740cc6ceba7b Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 11 Aug 2011 18:44:24 +0700 Subject: [PATCH 042/208] MDL-47494 ddimageortext: NOBUG adding output of question text. --- question/type/ddimageortext/renderer.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 76e5154a123..4709718c8fb 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -62,14 +62,16 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $question = $qa->get_question(); $response = $qa->get_last_qt_data(); - $output = ''; + $questiontext = $question->format_questiontext($qa); + + $output = html_writer::tag('div', $questiontext, array('class' => 'qtext')); + $bgimage = self::get_url_for_image($qa, 'bgimage'); $img = html_writer::empty_tag('img', array('src'=>$bgimage, 'class'=>'dropbackground')); $droparea = html_writer::tag('div', $img, array('class'=>'droparea')); $dragimagehomes = ''; - dbg($question); foreach ($question->choices as $groupno => $group) { $dragimagehomesgroup = ''; $orderedgroup = $question->get_ordered_choices($groupno); From 8f1c40332fc464c47948ad6c216c1d664044fab8 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 14 Aug 2011 15:55:17 +0700 Subject: [PATCH 043/208] MDL-47494 ddimageortext: NOBUG javascript almost done but needs refactoring hopefully to simplify it. --- question/type/ddimageortext/module.js | 264 ++++++++++++++------------ 1 file changed, 143 insertions(+), 121 deletions(-) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index 394b649104c..ac74e83219b 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -1,20 +1,6 @@ M.qtype_ddimagetoimage={ Y : null, doc : null, - fp : null, - /** - * Entry point when called from question editing form - */ - init_form : function(Y, maxsizes) { - this.Y = Y; - this.fp = this.file_pickers(); - topnode = Y.one('fieldset#previewareaheader'); - topnode.append('
'+ - '
'+ - '
'); - this.doc = this.doc_structure(Y, topnode, this, maxsizes); - this.init_dd_area(); - }, /** * Entry point when called from question renderer */ @@ -231,17 +217,6 @@ M.qtype_ddimagetoimage={ dragMode: 'intersect' }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); -// dd.on('drag:start', function(e) { -// var drag = e.target.get('node'); -// var inputid = drag.getData('placedonid'); -// if (inputid !== undefined || inputid !== null) { -// var inputnode = this.Y.one('input#'+inputid); -// if (inputnode !== null) { -// inputnode.set('value', ''); -// } -// } -// drag.setData('placedonid', ''); -// }, this); dd.on('drag:end', function(e) { mainobj.redraw(); }, this); @@ -276,88 +251,73 @@ M.qtype_ddimagetoimage={ } }, - - file_pickers : function () { - var draftitemidstoname; - var nametoparentnode; - if (draftitemidstoname === undefined) { - draftitemidstoname = {}; - nametoparentnode = {}; - var filepickers = this.Y.all('form.mform input.filepickerhidden'); - filepickers.each(function(filepicker, k, items) { - draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); - nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); - }, this); + + update_padding_sizes_all : function () { + for (var groupno = 1; groupno <= 8; groupno++) { + this.update_padding_size_for_group(groupno); } - var toreturn = { - file : function (name) { - var parentnode = nametoparentnode[name]; - var fileanchor = parentnode.one('div.filepicker-filelist a'); - if (fileanchor) { - return fileanchor.get('href'); - } else { - return null; - } - }, - name : function (draftitemid) { - return draftitemidstoname[draftitemid]; - } - } - return toreturn; }, + update_padding_size_for_group : function (groupno) { + var groupimages = this.doc.top_node().all('img.group'+groupno); + var maxwidth = 0; + var maxheight = 0; + groupimages.each(function(image){ + maxwidth = Math.max(maxwidth, image.get('width')); + maxheight = Math.max(maxheight, image.get('height')); + }, this); + groupimages.each(function(image) { + var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); + var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); + image.setStyle('padding', margintopbottom+'px '+marginleftright+'px'); + }, this); + this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, + 'height': maxheight + 10}); + }, + convert_to_window_xy : function (bgimgxy) { + return [+bgimgxy[0] + this.doc.bg_img().getX() + 1, + +bgimgxy[1] + this.doc.bg_img().getY() + 1]; + }, + + //---------- stuff below this line only used in question editing form --------------- + + fp : null, /** - * Low level operations on form. + * Entry point when called from question editing form */ - form : { - to_name_with_index : function(name, indexes) { - indexes = indexes || []; - var indexstring = name; - for (var i=0; i < indexes.length; i++) { - indexstring = indexstring + '[' + indexes[i] + ']'; - } - return indexstring; - }, - get_form_value : function(name, indexes) { - var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; - if (el.type === 'checkbox') { - return el.checked; - } else { - return el.value; - } - }, - set_form_value : function(name, indexes, value) { - var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; - if (el.type === 'checkbox') { - el.checked = value; - } else { - el.value = value; - } - }, - from_name_with_index : function(name) { - var toreturn = {}; - toreturn.indexes = []; - var bracket = name.indexOf('['); - toreturn.name = name.substring(0, bracket); - while (bracket !== -1) { - var end = name.indexOf(']', bracket + 1); - toreturn.indexes.push(name.substring(bracket + 1, end)); - bracket = name.indexOf('[', end + 1); - } - return toreturn; - } + init_form : function(Y, maxsizes) { + this.Y = Y; + this.fp = this.file_pickers(); + topnode = Y.one('fieldset#previewareaheader'); + topnode.append('
'+ + '
'+ + '
'); + this.doc = this.doc_structure(Y, topnode, this, maxsizes); + this.init_dd_area(); }, init_dd_area : function() { //set up drag items homes + var dragimagesoptions = {0: ''}; for (var i=0; i < this.form.get_form_value('noimages'); i++) { - var url = this.fp.file(this.form.to_name_with_index('dragitem', [i])); - this.doc.add_or_update_drag_item_home(i, url, + var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); + if (file.name !== null) { + dragimagesoptions[i+1] = (i+1)+'. '+file.name; + } + this.doc.add_or_update_drag_item_home(i, file.href, this.form.get_form_value('drags', [i, 'draglabel']), this.form.get_form_value('drags', [i, 'draggroup'])); } //set up drop zones for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { + var options = this.Y.one('#id_drops_'+i+'_choice').get('options'); + options.each(function (option, k, options) { + if (dragimagesoptions[option.get('value')] === undefined) { + option.remove(true); + } else { + option.set('text', dragimagesoptions[option.get('value')]); + } + }, this); var dragimageno = this.form.get_form_value('drops', [i, 'choice']); if (dragimageno !== '0') { var drag = this.doc.clone_new_drag_item(i, dragimageno - 1); @@ -369,7 +329,7 @@ M.qtype_ddimagetoimage={ this.setup_form_events(); - this.doc.load_bg_img(this.fp.file(this.form.to_name_with_index('bgimage'))); + this.doc.load_bg_img(this.fp.file(this.form.to_name_with_index('bgimage')).href); var drop = new this.Y.DD.Drop({ node: this.doc.bg_img() @@ -431,39 +391,34 @@ M.qtype_ddimagetoimage={ var itemnameparts = this.form.from_name_with_index(itemname); if (itemnameparts.name === 'dragitem') { var dragimageno = itemnameparts.indexes[0]; - this.update_drag_image_home(dragimageno); + this.load_drag_item_home(dragimageno, url); + this.doc.drag_items_cloned_from(dragimageno).remove(true); + this.Y.all('fieldset#dropzoneheader option[value="'+(+dragimageno+1)+'"]') + .remove(true); + var selects = this.Y.all('fieldset#dropzoneheader select'); + selects.each(function (select, k, selects){ + var name = + this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).name; + select.append(''); + }, this); + this.doc.get_drag_image_home(dragimageno).after('load', function (e, dragimageno) { + this.update_drag_image_home(dragimageno); + }, this, dragimageno); } else { this.doc.load_bg_img(url); this.doc.bg_img().after('load', this.reposition_drags, this); } }, - update_padding_sizes_all : function () { - for (var groupno = 1; groupno <= 8; groupno++) { - this.update_padding_size_for_group(groupno); - } - }, - update_padding_size_for_group : function (groupno) { - var groupimages = this.doc.top_node().all('img.group'+groupno); - var maxwidth = 0; - var maxheight = 0; - groupimages.each(function(image){ - maxwidth = Math.max(maxwidth, image.get('width')); - maxheight = Math.max(maxheight, image.get('height')); - }, this); - groupimages.each(function(image) { - var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); - var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); - image.setStyle('padding', margintopbottom+'px '+marginleftright+'px'); - }, this); - this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, - 'height': maxheight + 10}); - }, - update_drag_image_home : function (dragimageno) { - dragimageno = +dragimageno; - var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])); + load_drag_item_home : function (dragimageno, url) { this.doc.add_or_update_drag_item_home(dragimageno, url, this.form.get_form_value('drags', [dragimageno, 'draglabel']), this.form.get_form_value('drags', [dragimageno, 'draggroup'])); + }, + update_drag_image_home : function (dragimageno) { + dragimageno = +dragimageno; + var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).href; + this.load_drag_item_home(dragimageno, url); for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { var dropdragimageno = this.form.get_form_value('drops', [i, 'choice']) - 1; if (dropdragimageno === dragimageno) { @@ -532,9 +487,76 @@ M.qtype_ddimagetoimage={ return [windowxy[0] - this.doc.bg_img().getX(), windowxy[1] - this.doc.bg_img().getY()]; }, - convert_to_window_xy : function (bgimgxy) { - return [+bgimgxy[0] + this.doc.bg_img().getX() + 1, - +bgimgxy[1] + this.doc.bg_img().getY() + 1]; + + /** + * Low level operations on form. + */ + form : { + to_name_with_index : function(name, indexes) { + indexes = indexes || []; + var indexstring = name; + for (var i=0; i < indexes.length; i++) { + indexstring = indexstring + '[' + indexes[i] + ']'; + } + return indexstring; + }, + get_form_value : function(name, indexes) { + var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; + if (el.type === 'checkbox') { + return el.checked; + } else { + return el.value; + } + }, + set_form_value : function(name, indexes, value) { + var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; + if (el.type === 'checkbox') { + el.checked = value; + } else { + el.value = value; + } + }, + from_name_with_index : function(name) { + var toreturn = {}; + toreturn.indexes = []; + var bracket = name.indexOf('['); + toreturn.name = name.substring(0, bracket); + while (bracket !== -1) { + var end = name.indexOf(']', bracket + 1); + toreturn.indexes.push(name.substring(bracket + 1, end)); + bracket = name.indexOf('[', end + 1); + } + return toreturn; + } + }, + + file_pickers : function () { + var draftitemidstoname; + var nametoparentnode; + if (draftitemidstoname === undefined) { + draftitemidstoname = {}; + nametoparentnode = {}; + var filepickers = this.Y.all('form.mform input.filepickerhidden'); + filepickers.each(function(filepicker, k, items) { + draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); + nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); + }, this); + } + var toreturn = { + file : function (name) { + var parentnode = nametoparentnode[name]; + var fileanchor = parentnode.one('div.filepicker-filelist a'); + if (fileanchor) { + return {href : fileanchor.get('href'), name : fileanchor.get('innerHTML')}; + } else { + return {href : null, name : null}; + } + }, + name : function (draftitemid) { + return draftitemidstoname[draftitemid]; + } + } + return toreturn; } } \ No newline at end of file From f20ac87f234b4feef03449996d5681ed1bcfc7ad Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 15 Aug 2011 21:55:24 +0700 Subject: [PATCH 044/208] MDL-47494 ddimageortext: NOBUG refactored js and added disabling of options in select boxes dependent of whether the image is 'infinite' or not and whether it is selected elsewhere. --- .../edit_ddimagetoimage_form.php | 12 +- question/type/ddimageortext/module.js | 343 +++++++++--------- 2 files changed, 175 insertions(+), 180 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 4a44913ca3d..d5cf5f70fa9 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -261,12 +261,12 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { 'requires' => array('node', 'dd', 'dd-drop', 'dd-constrain', 'form_filepicker') ); $maxsizes =new stdClass(); - $maxsizes->bg_image = new stdClass(); - $maxsizes->bg_image->width = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH; - $maxsizes->bg_image->height = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXHEIGHT; - $maxsizes->drag_image = new stdClass(); - $maxsizes->drag_image->width = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH; - $maxsizes->drag_image->height = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT; + $maxsizes->bgimage = new stdClass(); + $maxsizes->bgimage->width = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH; + $maxsizes->bgimage->height = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXHEIGHT; + $maxsizes->dragimage = new stdClass(); + $maxsizes->dragimage->width = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH; + $maxsizes->dragimage->height = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT; $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_form', array($maxsizes), true, $jsmodule); diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index ac74e83219b..a3378a8f390 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -9,13 +9,13 @@ M.qtype_ddimagetoimage={ this.doc = this.doc_structure(Y, Y.one(topnodestr), this, null); this.init_drops(drops); var i = 0; - this.doc.drag_item_homes().each(function(dragitemhome){ + this.doc.drag_image_homes().each(function(dragimagehome){ var dragimageno = - +this.doc.get_classname_numeric_suffix(dragitemhome, 'dragimagehomes'); - var choice = +this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); - var group = +this.doc.get_classname_numeric_suffix(dragitemhome, 'group') + +this.doc.get_classname_numeric_suffix(dragimagehome, 'dragimagehomes'); + var choice = +this.doc.get_classname_numeric_suffix(dragimagehome, 'choice'); + var group = +this.doc.get_classname_numeric_suffix(dragimagehome, 'group') var groupsize = this.doc.drop_zone_group(group).size(); - var dragnode = this.doc.clone_new_drag_item(i, dragimageno); + var dragnode = this.doc.clone_new_drag_image(i, dragimageno); i++; if (!readonly) { this.doc.draggable_for_question(dragnode, group, choice); @@ -23,7 +23,7 @@ M.qtype_ddimagetoimage={ if (dragnode.hasClass('infinite')) { var dragstocreate = groupsize - 1; while (dragstocreate > 0) { - dragnode = this.doc.clone_new_drag_item(i, dragimageno); + dragnode = this.doc.clone_new_drag_image(i, dragimageno); i++; if (!readonly) { this.doc.draggable_for_question(dragnode, group, choice); @@ -34,7 +34,7 @@ M.qtype_ddimagetoimage={ //put these here for easy refernece later }, this); this.doc.bg_img().on('load', this.delayed_redraw, this); - this.doc.drag_item_homes().on('load', this.delayed_redraw, this); + this.doc.drag_image_homes().on('load', this.delayed_redraw, this); Y.on('windowresize', this.redraw, this); }, delayed_redraw : function (e) { @@ -42,10 +42,10 @@ M.qtype_ddimagetoimage={ this.Y.later(2000, this, this.redraw); }, redraw : function(e) { - this.doc.drag_items().removeClass('placed'); - this.doc.drag_items().each (function (dragitem) { - if (dragitem.dd !== undefined) { - dragitem.dd.detachAll('drag:start'); + this.doc.drag_images().removeClass('placed'); + this.doc.drag_images().each (function (dragimage) { + if (dragimage.dd !== undefined) { + dragimage.dd.detachAll('drag:start'); } }, this); this.doc.drop_zones().each(function(dropzone) { @@ -56,13 +56,13 @@ M.qtype_ddimagetoimage={ var choice = input.get('value'); if (choice !== "") { var group = dropzone.getData('group'); - var dragitem = this.doc.top_node() + var dragimage = this.doc.top_node() .one('div.dragitemgroup'+group+' img.choice'+choice+'.drag:not(.placed)'); - if (dragitem !== null) { - dragitem.setXY(dropzone.getXY()); - dragitem.addClass('placed'); - if (dragitem.dd !== undefined) { - dragitem.dd.once('drag:start', function (e, input) { + if (dragimage !== null) { + dragimage.setXY(dropzone.getXY()); + dragimage.addClass('placed'); + if (dragimage.dd !== undefined) { + dragimage.dd.once('drag:start', function (e, input) { input.set('value', ''); e.target.get('node').removeClass('placed'); },this, input); @@ -70,10 +70,10 @@ M.qtype_ddimagetoimage={ } } }, this); - this.doc.drag_items().each(function(dragitem) { - if (!dragitem.hasClass('placed')) { - var dragitemhome = this.doc.get_drag_image_home(dragitem.getData('dragimageno')); - dragitem.setXY(dragitemhome.getXY()); + this.doc.drag_images().each(function(dragimage) { + if (!dragimage.hasClass('placed')) { + var dragimagehome = this.doc.drag_image_home(dragimage.getData('dragimageno')); + dragimage.setXY(dragimagehome.getXY()); } }, this); this.update_padding_sizes_all(); @@ -114,14 +114,14 @@ M.qtype_ddimagetoimage={ * Object to encapsulate operations on dd area. */ doc_structure : function (Y, topnode, mainobj, maxsizes) { - var dragitemsarea = topnode.one('div.dragitems'); + var dragimagesarea = topnode.one('div.dragitems'); var dropbgarea = topnode.one('div.droparea'); return { top_node : function() { return topnode; }, - drag_items : function() { - return dragitemsarea.all('img.drag'); + drag_images : function() { + return dragimagesarea.all('img.drag'); }, drop_zones : function() { return topnode.all('div.dropzones div.dropzone'); @@ -129,14 +129,14 @@ M.qtype_ddimagetoimage={ drop_zone_group : function(groupno) { return topnode.all('div.dropzones div.group' + groupno); }, - drag_items_cloned_from : function(dragimageno) { - return dragitemsarea.all('img.dragimages'+dragimageno); + drag_images_cloned_from : function(dragimageno) { + return dragimagesarea.all('img.dragimages'+dragimageno); }, - drag_item : function(draginstanceno) { - return dragitemsarea.one('img.draginstance' + draginstanceno); + drag_image : function(draginstanceno) { + return dragimagesarea.one('img.draginstance' + draginstanceno); }, - drag_item_homes : function() { - return dragitemsarea.all('img.draghome'); + drag_image_homes : function() { + return dragimagesarea.all('img.draghome'); }, bg_img : function() { return topnode.one('img.dropbackground'); @@ -145,39 +145,28 @@ M.qtype_ddimagetoimage={ dropbgarea.setContent(''); this.bg_img().on('load', this.on_image_load, this, 'bg_image'); }, - add_or_update_drag_item_home : function (dragimageno, url, alt, group) { - var oldhome = dragitemsarea.one('img.dragimagehomes'+dragimageno); + add_or_update_drag_image_home : function (dragimageno, url, alt, group) { + var oldhome = this.drag_image_home(dragimageno); var classes = 'draghome dragimagehomes'+dragimageno+' group'+group; var imghtml = ''+alt+''; if (oldhome === null) { if (url) { - dragitemsarea.append(imghtml); + dragimagesarea.append(imghtml); } } else { if (url) { - dragitemsarea.insert(imghtml, oldhome); + dragimagesarea.insert(imghtml, oldhome); } oldhome.remove(true); } - var newlycreated = dragitemsarea.one('img.dragimagehomes'+dragimageno); + var newlycreated = dragimagesarea.one('img.dragimagehomes'+dragimageno); if (newlycreated !== null) { newlycreated.setData('groupno', group); newlycreated.setData('dragimageno', dragimageno); - newlycreated.on('load', this.on_image_load, this, 'drag_image'); } }, - on_image_load : function (e, imagetype) { - if (maxsizes !== null) { - var maxsize = maxsizes[imagetype]; - var reduceby = Math.max(e.target.get('width') / maxsize.width, - e.target.get('height') / maxsize.height); - if (reduceby > 1) { - e.target.set('width', Math.floor(e.target.get('width') / reduceby)); - } - } - }, - get_drag_image_home : function (dragimageno) { - return dragitemsarea.one('img.dragimagehomes' + dragimageno); + drag_image_home : function (dragimageno) { + return dragimagesarea.one('img.dragimagehomes' + dragimageno); }, get_classname_numeric_suffix : function(node, prefix) { var classes = node.getAttribute('class'); @@ -194,8 +183,8 @@ M.qtype_ddimagetoimage={ } throw 'Prefix "'+prefix+'" not found in class names.'; }, - clone_new_drag_item : function (draginstanceno, dragimageno) { - var draghome = this.get_drag_image_home(dragimageno); + clone_new_drag_image : function (draginstanceno, dragimageno) { + var draghome = this.drag_image_home(dragimageno); if (draghome === null) { return null; } @@ -281,6 +270,7 @@ M.qtype_ddimagetoimage={ //---------- stuff below this line only used in question editing form --------------- fp : null, + maxsizes : null, /** * Entry point when called from question editing form */ @@ -291,64 +281,139 @@ M.qtype_ddimagetoimage={ topnode.append('
'+ '
'+ '
'); - this.doc = this.doc_structure(Y, topnode, this, maxsizes); - this.init_dd_area(); + this.doc = this.doc_structure(Y, topnode, this); + this.maxsizes = maxsizes; + this.draw_dd_area(); }, - init_dd_area : function() { + draw_dd_area : function() { + var bgimageurl = this.fp.file(this.form.to_name_with_index('bgimage')).href + if (bgimageurl !== null) { + this.doc.load_bg_img(bgimageurl); + this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage') + this.load_drag_homes(); + this.setup_form_events(); + + var drop = new this.Y.DD.Drop({ + node: this.doc.bg_img() + }); + //Listen for a drop:hit on the background image + drop.on('drop:hit', function(e) { + e.drag.get('node').setData('gooddrop', true); + }); + + this.Y.on('windowresize', this.reposition_drags, this); + + this.doc.bg_img().after('load', this.wait_for_all_images, this); + this.doc.drag_image_homes().after('load', this.wait_for_all_images, this); + this.doc.drag_image_homes().on('load', this.constrain_image_size, this, 'dragimage'); + } + }, + wait_for_all_images : function (wait) { + if (wait === undefined) { + wait = 0; + } + var allimgsloaded; + if (allimgsloaded === true) { + return; + } + if (!this.doc.bg_img().get('complete')){ + return; + } else { + var allimgsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ + //search for one node which is not 'complete' + return !dragimagehome.get('complete'); + }, this); + if (allimgsloaded) { + this.doc.drag_image_homes().detach('load', this.wait_for_all_images); + this.doc.bg_img().detach('load', this.wait_for_all_images); + if (wait === 0) { + this.after_all_images_loaded(); + } else { + this.Y.later(wait, this, function (e) { + this.after_all_images_loaded(); + }, this); + } + } + } + }, + + after_all_images_loaded : function () { + this.doc.drag_images().remove(true); + this.copy_drag_instances(); + this.update_padding_sizes_all(); + this.reposition_drags(); + this.set_options_for_drag_image_selectors(); + }, + + constrain_image_size : function (e, imagetype) { + var maxsize = this.maxsizes[imagetype]; + var reduceby = Math.max(e.target.get('width') / maxsize.width, + e.target.get('height') / maxsize.height); + if (reduceby > 1) { + e.target.set('width', Math.floor(e.target.get('width') / reduceby)); + } + }, + + load_drag_homes : function () { //set up drag items homes + var dragimagesoptions = {0: ''}; + for (var i=0; i < this.form.get_form_value('noimages'); i++) { + this.load_drag_image_home(i); + } + }, + + load_drag_image_home : function (dragimageno) { + var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).href; + this.doc.add_or_update_drag_image_home(dragimageno, url, + this.form.get_form_value('drags', [dragimageno, 'draglabel']), + this.form.get_form_value('drags', [dragimageno, 'draggroup'])); + }, + + copy_drag_instances : function () { + //set up drop zones + for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { + var dragimageno = this.form.get_form_value('drops', [i, 'choice']); + if (dragimageno !== '0') { + var drag = this.doc.clone_new_drag_image(i, dragimageno - 1); + if (drag !== null) { + this.doc.draggable_for_form(drag); + } + } + } + }, + set_options_for_drag_image_selectors : function () { var dragimagesoptions = {0: ''}; for (var i=0; i < this.form.get_form_value('noimages'); i++) { var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); if (file.name !== null) { dragimagesoptions[i+1] = (i+1)+'. '+file.name; } - this.doc.add_or_update_drag_item_home(i, file.href, - this.form.get_form_value('drags', [i, 'draglabel']), - this.form.get_form_value('drags', [i, 'draggroup'])); } - - //set up drop zones for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { - var options = this.Y.one('#id_drops_'+i+'_choice').get('options'); - options.each(function (option, k, options) { - if (dragimagesoptions[option.get('value')] === undefined) { - option.remove(true); + var selector = this.Y.one('#id_drops_'+i+'_choice'); + var selectedvalue = selector.get('value'); + var options = selector.get('options'); + options.remove(true); + for (var value in dragimagesoptions) { + if (value === selectedvalue) { + var option = new Option(dragimagesoptions[value], value, true, true); } else { - option.set('text', dragimagesoptions[option.get('value')]); - } - }, this); - var dragimageno = this.form.get_form_value('drops', [i, 'choice']); - if (dragimageno !== '0') { - var drag = this.doc.clone_new_drag_item(i, dragimageno - 1); - if (drag !== null) { - this.doc.draggable_for_form(drag); + var option = new Option(dragimagesoptions[value], value, false, false); + if (+value !== 0) { // no image option is always selectable + var cbsel = 'fieldset#draggableimageheader_'+(+value-1)+' input[type="checkbox"]'; + var cbel = this.Y.one(cbsel); + var infinite = cbel.get('checked'); + if (!infinite && (this.doc.drag_images_cloned_from(+value).size !== 0)) { + option.disabled = true; + } + } } + selector.append(option); } } - - this.setup_form_events(); - - this.doc.load_bg_img(this.fp.file(this.form.to_name_with_index('bgimage')).href); - - var drop = new this.Y.DD.Drop({ - node: this.doc.bg_img() - }); - //Listen for a drop:hit on this target - drop.on('drop:hit', function(e) { - e.drag.get('node').setData('gooddrop', true); - }); - - this.Y.on('windowresize', this.reposition_drags, this); - - this.doc.bg_img().after('load', function(e) { - this.Y.later(3000, this, function (e) { - this.reposition_drags(); - this.update_padding_sizes_all(); - }, this); - }, this); - }, + setup_form_events : function () { //events triggered by changes to form data this.Y.all('fieldset#dropzoneheader input').on('blur', function (e){ @@ -357,104 +422,34 @@ M.qtype_ddimagetoimage={ this.reposition_drag(nameparts.indexes[0]); }, this); - this.Y.all('fieldset#dropzoneheader select').on('change', function (e){ - var name = e.target.getAttribute('name'); - var nameparts = this.form.from_name_with_index(name); - var draginstanceno = nameparts.indexes[0]; - this.update_drag_instance(draginstanceno); - }, this); - - this.Y.all('fieldset#dropzoneheader select').on('change', function (e){ - var name = e.target.getAttribute('name'); - var nameparts = this.form.from_name_with_index(name); - var draginstanceno = nameparts.indexes[0]; - this.update_drag_instance(draginstanceno); - }, this); + this.Y.all('fieldset#dropzoneheader select').on('change', this.draw_dd_area, this); for (var i=0; i < this.form.get_form_value('noimages'); i++) { this.Y.all('fieldset#draggableimageheader_'+i+' select') - .on('change', this.on_drag_group_change, this); + .on('change', this.draw_dd_area, this); + this.Y.all('fieldset#draggableimageheader_'+i+' input[type="checkbox"]') + .on('change', this.set_options_for_drag_image_selectors, this); } - - this.Y.after(this.after_image_upload, M.form_filepicker, 'callback', this); + //event on file picker new file selection + this.Y.after(this.draw_dd_area, M.form_filepicker, 'callback', this); + }, + - }, - on_drag_group_change : function (e){ - var name = e.target.getAttribute('name'); - var nameparts = this.form.from_name_with_index(name); - var dragimageno = nameparts.indexes[0]; - this.update_drag_image_home(dragimageno); - }, - after_image_upload : function (params) { - var url = params['url']; - var itemname = this.fp.name(params.id); - var itemnameparts = this.form.from_name_with_index(itemname); - if (itemnameparts.name === 'dragitem') { - var dragimageno = itemnameparts.indexes[0]; - this.load_drag_item_home(dragimageno, url); - this.doc.drag_items_cloned_from(dragimageno).remove(true); - this.Y.all('fieldset#dropzoneheader option[value="'+(+dragimageno+1)+'"]') - .remove(true); - var selects = this.Y.all('fieldset#dropzoneheader select'); - selects.each(function (select, k, selects){ - var name = - this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).name; - select.append(''); - }, this); - this.doc.get_drag_image_home(dragimageno).after('load', function (e, dragimageno) { - this.update_drag_image_home(dragimageno); - }, this, dragimageno); - } else { - this.doc.load_bg_img(url); - this.doc.bg_img().after('load', this.reposition_drags, this); - } - }, - load_drag_item_home : function (dragimageno, url) { - this.doc.add_or_update_drag_item_home(dragimageno, url, - this.form.get_form_value('drags', [dragimageno, 'draglabel']), - this.form.get_form_value('drags', [dragimageno, 'draggroup'])); - }, - update_drag_image_home : function (dragimageno) { - dragimageno = +dragimageno; - var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).href; - this.load_drag_item_home(dragimageno, url); - for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { - var dropdragimageno = this.form.get_form_value('drops', [i, 'choice']) - 1; - if (dropdragimageno === dragimageno) { - this.update_drag_instance(i); - } - } - }, - update_drag_instance : function(draginstanceno) { - var drag = this.doc.drag_item(draginstanceno); - var dragimageno = this.form.get_form_value('drops', [draginstanceno, 'choice']) - 1; - if (drag !== null) { - drag.remove(true); - } - drag = this.doc.clone_new_drag_item(draginstanceno, dragimageno); - this.doc.draggable_for_form(drag); - if (drag !== null) { - drag.on('load', function(e){ - this.reposition_drag(draginstanceno); - }, this); - } - }, reposition_drags : function() { - this.doc.drag_items().each(function (drag) { + this.doc.drag_images().each(function (drag) { var draginstanceno = drag.getData('draginstanceno'); this.reposition_drag(draginstanceno); }, this); }, reposition_drag : function (draginstanceno) { this.update_padding_sizes_all(); - var drag = this.doc.drag_item(draginstanceno); + var drag = this.doc.drag_image(draginstanceno); if (null !== drag) { var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; if (fromform[0] == '' && fromform[1] == '') { var dragimageno = drag.getData('dragimageno'); - drag.setXY(this.doc.get_drag_image_home(dragimageno).getXY()); + drag.setXY(this.doc.drag_image_home(dragimageno).getXY()); } else { drag.setXY(this.convert_to_window_xy(this.constrain_xy(draginstanceno, fromform))); } @@ -474,7 +469,7 @@ M.qtype_ddimagetoimage={ //make sure xy value is not out of bounds of bg image constrain_xy : function (draginstanceno, bgimgxy) { - var drag = this.doc.drag_item(draginstanceno); + var drag = this.doc.drag_image(draginstanceno); var xleftconstrained = Math.min(bgimgxy[0], this.doc.bg_img().get('width') - drag.get('offsetWidth')); var ytopconstrained = From a135d087d67f4513ec42ed67bcdf4b9c56b01ca9 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 16 Aug 2011 18:47:27 +0700 Subject: [PATCH 045/208] MDL-47494 ddimageortext: NOBUG further refactoring and changes to make the code work in IE too. --- question/type/ddimageortext/module.js | 166 +++++++++++++++-------- question/type/ddimageortext/renderer.php | 2 +- 2 files changed, 110 insertions(+), 58 deletions(-) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index a3378a8f390..845e107d797 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -1,13 +1,49 @@ M.qtype_ddimagetoimage={ Y : null, doc : null, + drops : null, + readonly : null, /** * Entry point when called from question renderer */ init_question : function(Y, drops, topnodestr, readonly) { this.Y = Y; + this.drops = drops; + this.readonly = readonly; this.doc = this.doc_structure(Y, Y.one(topnodestr), this, null); - this.init_drops(drops); + this.update_padding_sizes_all(); + this.poll_for_image_load(null, 1000, this.create_all_drag_and_drops); + this.doc.bg_img() + .after('load', this.poll_for_image_load, this, 1000, this.create_all_drag_and_drops); + this.doc.drag_image_homes() + .after('load', this.poll_for_image_load, this, 1000, this.create_all_drag_and_drops); + this.Y.on('windowresize', this.redraw, this); + }, + polltimer : null, + poll_for_image_load : function (e, pause, doafterwords) { + if (this.doc.bg_img().get('complete')) { + var notalldragsloaded = this.doc.drag_image_homes().some(function(dragimagehome){ + !dragimagehome.get('complete'); + }); + if (!notalldragsloaded) { + if (this.polltimer !== null) { + this.polltimer.cancel(); + this.polltimer = null; + } + this.doc.drag_image_homes().detach('load', this.poll_for_image_load); + this.doc.bg_img().detach('load', this.poll_for_image_load); + if (pause !== 0) { + this.Y.later(pause, this, doafterwords); + } else { + doafterwords.call(this); + } + } else if (this.polltimer === null) { + this.polltimer = this.Y.later(500, this.poll_for_image_load, this, true); + } + } + }, + create_all_drag_and_drops : function () { + this.init_drops(); var i = 0; this.doc.drag_image_homes().each(function(dragimagehome){ var dragimageno = @@ -17,7 +53,7 @@ M.qtype_ddimagetoimage={ var groupsize = this.doc.drop_zone_group(group).size(); var dragnode = this.doc.clone_new_drag_image(i, dragimageno); i++; - if (!readonly) { + if (!this.readonly) { this.doc.draggable_for_question(dragnode, group, choice); } if (dragnode.hasClass('infinite')) { @@ -25,23 +61,17 @@ M.qtype_ddimagetoimage={ while (dragstocreate > 0) { dragnode = this.doc.clone_new_drag_image(i, dragimageno); i++; - if (!readonly) { + if (!this.readonly) { this.doc.draggable_for_question(dragnode, group, choice); } dragstocreate--; } } - //put these here for easy refernece later }, this); - this.doc.bg_img().on('load', this.delayed_redraw, this); - this.doc.drag_image_homes().on('load', this.delayed_redraw, this); - Y.on('windowresize', this.redraw, this); - }, - delayed_redraw : function (e) { + this.update_padding_sizes_all(); this.redraw(); - this.Y.later(2000, this, this.redraw); }, - redraw : function(e) { + redraw : function() { this.doc.drag_images().removeClass('placed'); this.doc.drag_images().each (function (dragimage) { if (dragimage.dd !== undefined) { @@ -56,8 +86,17 @@ M.qtype_ddimagetoimage={ var choice = input.get('value'); if (choice !== "") { var group = dropzone.getData('group'); - var dragimage = this.doc.top_node() - .one('div.dragitemgroup'+group+' img.choice'+choice+'.drag:not(.placed)'); + var dragimage = null; + var dragimages = this.doc.top_node() + .all('div.dragitemgroup'+group+' img.choice'+choice+'.drag'); + dragimages.some(function (d) { + if (!d.hasClass('placed')) { + dragimage = d; + return true; + } else { + return false; + } + }); if (dragimage !== null) { dragimage.setXY(dropzone.getXY()); dragimage.addClass('placed'); @@ -76,9 +115,8 @@ M.qtype_ddimagetoimage={ dragimage.setXY(dragimagehome.getXY()); } }, this); - this.update_padding_sizes_all(); }, - init_drops : function (drops) { + init_drops : function () { var dropareas = this.doc.top_node().one('div.dropzones'); var groupnodes = {}; for (var groupno =1; groupno <= 8; groupno++) { @@ -86,17 +124,17 @@ M.qtype_ddimagetoimage={ dropareas.append(groupnode); groupnodes[groupno] = groupnode; } - for (var dropno in drops){ - var nodeclass = 'dropzone group'+drops[dropno].group+' place'+dropno; - var title = drops[dropno].text.replace('"', '\"'); + for (var dropno in this.drops){ + var nodeclass = 'dropzone group'+this.drops[dropno].group+' place'+dropno; + var title = this.drops[dropno].text.replace('"', '\"'); var dropnodehtml = '
 
'; var dropnode = this.Y.Node.create(dropnodehtml); - groupnodes[drops[dropno].group].append(dropnode); + groupnodes[this.drops[dropno].group].append(dropnode); dropnode.setStyles({'opacity': 0.5}); - dropnode.setData('xy', drops[dropno].xy); + dropnode.setData('xy', this.drops[dropno].xy); dropnode.setData('place', dropno); - dropnode.setData('inputid', drops[dropno].fieldname.replace(':', '_')); - dropnode.setData('group', drops[dropno].group); + dropnode.setData('inputid', this.drops[dropno].fieldname.replace(':', '_')); + dropnode.setData('group', this.drops[dropno].group); var dropdd = new this.Y.DD.Drop({ node: dropnode}); dropdd.on('drop:hit', function(e) { @@ -287,11 +325,12 @@ M.qtype_ddimagetoimage={ }, draw_dd_area : function() { - var bgimageurl = this.fp.file(this.form.to_name_with_index('bgimage')).href + var bgimageurl = this.fp.file(this.form.to_name_with_index('bgimage')).href; if (bgimageurl !== null) { this.doc.load_bg_img(bgimageurl); - this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage') + this.doc.bg_img().addClass('loading'); this.load_drag_homes(); + this.doc.drag_image_homes().addClass('loading'); this.setup_form_events(); var drop = new this.Y.DD.Drop({ @@ -304,44 +343,44 @@ M.qtype_ddimagetoimage={ this.Y.on('windowresize', this.reposition_drags, this); - this.doc.bg_img().after('load', this.wait_for_all_images, this); - this.doc.drag_image_homes().after('load', this.wait_for_all_images, this); + this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage') this.doc.drag_image_homes().on('load', this.constrain_image_size, this, 'dragimage'); + this.doc.bg_img() + .after('load', this.wait_for_all_images, this, this.after_all_images_loaded, 1000); + this.doc.drag_image_homes() + .after('load', this.wait_for_all_images, this, this.after_all_images_loaded, 1000); } }, - wait_for_all_images : function (wait) { + wait_for_all_images : function (e, doafterwards, wait) { if (wait === undefined) { wait = 0; } - var allimgsloaded; - if (allimgsloaded === true) { + e.target.removeClass('loading'); + if (this.doc.bg_img().hasClass('loading')){ return; } - if (!this.doc.bg_img().get('complete')){ + var dragimagesstillloading = this.doc.drag_image_homes().filter('.loading'); + if (dragimagesstillloading.size() !== 0){ return; + } + + //if we get here everything has loaded + this.doc.drag_image_homes().detach('load', this.wait_for_all_images); + this.doc.bg_img().detach('load', this.wait_for_all_images); + + if (wait === 0) { + doafterwards.call(this); } else { - var allimgsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ - //search for one node which is not 'complete' - return !dragimagehome.get('complete'); + this.Y.later(wait, this, function (e) { + doafterwards.call(this); }, this); - if (allimgsloaded) { - this.doc.drag_image_homes().detach('load', this.wait_for_all_images); - this.doc.bg_img().detach('load', this.wait_for_all_images); - if (wait === 0) { - this.after_all_images_loaded(); - } else { - this.Y.later(wait, this, function (e) { - this.after_all_images_loaded(); - }, this); - } - } } }, after_all_images_loaded : function () { this.doc.drag_images().remove(true); - this.copy_drag_instances(); this.update_padding_sizes_all(); + this.copy_drag_instances(); this.reposition_drags(); this.set_options_for_drag_image_selectors(); }, @@ -393,40 +432,50 @@ M.qtype_ddimagetoimage={ for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { var selector = this.Y.one('#id_drops_'+i+'_choice'); var selectedvalue = selector.get('value'); - var options = selector.get('options'); - options.remove(true); + selector.all('option').remove(true); for (var value in dragimagesoptions) { - if (value === selectedvalue) { - var option = new Option(dragimagesoptions[value], value, true, true); + value = +value; + var option = ''; + selector.append(option); + var optionnode = selector.one('option[value="' + value + '"]') + if (value === +selectedvalue) { + optionnode.set('selected', true); } else { - var option = new Option(dragimagesoptions[value], value, false, false); - if (+value !== 0) { // no image option is always selectable - var cbsel = 'fieldset#draggableimageheader_'+(+value-1)+' input[type="checkbox"]'; - var cbel = this.Y.one(cbsel); + if (value !== 0) { // no image option is always selectable + var cbselector = 'fieldset#draggableimageheader_'+(value-1) + +' input[type="checkbox"]'; + var cbel = this.Y.one(cbselector); var infinite = cbel.get('checked'); - if (!infinite && (this.doc.drag_images_cloned_from(+value).size !== 0)) { - option.disabled = true; + if ((!infinite) && + (this.doc.drag_images_cloned_from(value - 1).size() !== 0)) { + optionnode.set('disabled', true); } } } - selector.append(option); } } }, setup_form_events : function () { //events triggered by changes to form data + + //x and y coordinates this.Y.all('fieldset#dropzoneheader input').on('blur', function (e){ var name = e.target.getAttribute('name'); var nameparts = this.form.from_name_with_index(name); this.reposition_drag(nameparts.indexes[0]); }, this); + //change in selected image this.Y.all('fieldset#dropzoneheader select').on('change', this.draw_dd_area, this); for (var i=0; i < this.form.get_form_value('noimages'); i++) { + //change to group selector this.Y.all('fieldset#draggableimageheader_'+i+' select') .on('change', this.draw_dd_area, this); + //change to infinite checkbox this.Y.all('fieldset#draggableimageheader_'+i+' input[type="checkbox"]') .on('change', this.set_options_for_drag_image_selectors, this); } @@ -441,8 +490,8 @@ M.qtype_ddimagetoimage={ this.reposition_drag(draginstanceno); }, this); }, + reposition_drag : function (draginstanceno) { - this.update_padding_sizes_all(); var drag = this.doc.drag_image(draginstanceno); if (null !== drag) { var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), @@ -452,6 +501,9 @@ M.qtype_ddimagetoimage={ drag.setXY(this.doc.drag_image_home(dragimageno).getXY()); } else { drag.setXY(this.convert_to_window_xy(this.constrain_xy(draginstanceno, fromform))); + var dragxy = this.convert_to_bg_img_xy(drag.getXY()); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], dragxy[0]); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], dragxy[1]) } } }, diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 4709718c8fb..dc5b99ad166 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -149,7 +149,7 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $value = $qa->get_last_qt_var($varname); } $fieldname = $qa->get_qt_field_name($varname); - $attributes = array('type' => 'hidden', + $attributes = array('type' => 'text', 'id' => str_replace(':', '_', $fieldname), 'name' => $fieldname, 'value' => $value); From aa854a768a90ab72388f130ac74aaa562f1a7d18 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 17 Aug 2011 10:08:51 +0700 Subject: [PATCH 046/208] MDL-47494 ddimageortext: NOBUG some polishing of code. --- question/type/ddimageortext/module.js | 17 ++++++++++------- question/type/ddimageortext/renderer.php | 2 +- question/type/ddimageortext/styles.css | 6 +++--- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index 845e107d797..9f06134aa68 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -295,7 +295,8 @@ M.qtype_ddimagetoimage={ groupimages.each(function(image) { var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); - image.setStyle('padding', margintopbottom+'px '+marginleftright+'px'); + image.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' + +margintopbottom+'px '+marginleftright+'px'); }, this); this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, 'height': maxheight + 10}); @@ -500,17 +501,19 @@ M.qtype_ddimagetoimage={ var dragimageno = drag.getData('dragimageno'); drag.setXY(this.doc.drag_image_home(dragimageno).getXY()); } else { - drag.setXY(this.convert_to_window_xy(this.constrain_xy(draginstanceno, fromform))); - var dragxy = this.convert_to_bg_img_xy(drag.getXY()); - this.form.set_form_value('drops', [draginstanceno, 'xleft'], dragxy[0]); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], dragxy[1]) + var constrainedxy = this.constrain_xy(draginstanceno, fromform); + drag.setXY(this.convert_to_window_xy(constrainedxy)); + if (constrainedxy[0] !== +fromform[0] || constrainedxy[1] !== +fromform[1]){ + this.form.set_form_value('drops', [draginstanceno, 'xleft'], constrainedxy[0]); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); + } } } }, set_drag_xy : function (draginstanceno, xy) { xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); - this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.round(xy[0])); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.round(xy[1])); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.floor(xy[0])); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.floor(xy[1])); this.reposition_drag(draginstanceno); }, reset_drag_xy : function (draginstanceno) { diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index dc5b99ad166..4709718c8fb 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -149,7 +149,7 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $value = $qa->get_last_qt_var($varname); } $fieldname = $qa->get_qt_field_name($varname); - $attributes = array('type' => 'text', + $attributes = array('type' => 'hidden', 'id' => str_replace(':', '_', $fieldname), 'name' => $fieldname, 'value' => $value); diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 14550510814..9453d9273e5 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -120,7 +120,7 @@ form.mform fieldset#previewareaheader .droptarget { position: absolute; z-index: 1; } - -form.mform fieldset#previewareaheader .droptarget.yui3-dd-drop-over { - background-color: #FFA928; +form.mform fieldset#previewareaheader div.droparea img { + border: 1px solid #000000; } + From 152045b3311e932582dc69467ffdaed9843abe91 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 18 Aug 2011 16:31:46 +0700 Subject: [PATCH 047/208] MDL-47494 ddimageortext: NOBUG trying to get padding to work correctly in IE7. --- question/type/ddimageortext/module.js | 38 ++++++++++++++++----------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index 9f06134aa68..b284e3c82b2 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -11,7 +11,6 @@ M.qtype_ddimagetoimage={ this.drops = drops; this.readonly = readonly; this.doc = this.doc_structure(Y, Y.one(topnodestr), this, null); - this.update_padding_sizes_all(); this.poll_for_image_load(null, 1000, this.create_all_drag_and_drops); this.doc.bg_img() .after('load', this.poll_for_image_load, this, 1000, this.create_all_drag_and_drops); @@ -286,20 +285,27 @@ M.qtype_ddimagetoimage={ }, update_padding_size_for_group : function (groupno) { var groupimages = this.doc.top_node().all('img.group'+groupno); - var maxwidth = 0; - var maxheight = 0; - groupimages.each(function(image){ - maxwidth = Math.max(maxwidth, image.get('width')); - maxheight = Math.max(maxheight, image.get('height')); - }, this); - groupimages.each(function(image) { - var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); - var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); - image.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' - +margintopbottom+'px '+marginleftright+'px'); - }, this); - this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, - 'height': maxheight + 10}); + if (groupimages.size() !== 0) { + var maxwidth = 0; + var maxheight = 0; + groupimages.each(function(image){ + maxwidth = Math.max(maxwidth, image.get('width')); + maxheight = Math.max(maxheight, image.get('height')); + }, this); + console.log('groupno : '+groupno); + console.log('maxwidth : '+maxwidth); + console.log('maxheight : '+maxheight); + groupimages.each(function(image) { + var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); + var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); + image.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' + +margintopbottom+'px '+marginleftright+'px'); + console.log(margintopbottom+'px '+marginleftright+'px ' + +margintopbottom+'px '+marginleftright+'px'); + }, this); + this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, + 'height': maxheight + 10}); + } }, convert_to_window_xy : function (bgimgxy) { return [+bgimgxy[0] + this.doc.bg_img().getX() + 1, @@ -380,8 +386,8 @@ M.qtype_ddimagetoimage={ after_all_images_loaded : function () { this.doc.drag_images().remove(true); - this.update_padding_sizes_all(); this.copy_drag_instances(); + this.update_padding_sizes_all(); this.reposition_drags(); this.set_options_for_drag_image_selectors(); }, From dbe2635db67da9d853ff6eeb4726bd2280df88ee Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 18 Aug 2011 16:46:45 +0700 Subject: [PATCH 048/208] MDL-47494 ddimageortext: NOBUG using polling of complete js property to test for image loading, seems to be more reliable. --- question/type/ddimageortext/module.js | 36 ++++----------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index b284e3c82b2..8703ceb559b 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -335,9 +335,7 @@ M.qtype_ddimagetoimage={ var bgimageurl = this.fp.file(this.form.to_name_with_index('bgimage')).href; if (bgimageurl !== null) { this.doc.load_bg_img(bgimageurl); - this.doc.bg_img().addClass('loading'); this.load_drag_homes(); - this.doc.drag_image_homes().addClass('loading'); this.setup_form_events(); var drop = new this.Y.DD.Drop({ @@ -352,35 +350,11 @@ M.qtype_ddimagetoimage={ this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage') this.doc.drag_image_homes().on('load', this.constrain_image_size, this, 'dragimage'); + this.poll_for_image_load(null, 1000, this.after_all_images_loaded); this.doc.bg_img() - .after('load', this.wait_for_all_images, this, this.after_all_images_loaded, 1000); + .after('load', this.poll_for_image_load, this, 1000, this.after_all_images_loaded); this.doc.drag_image_homes() - .after('load', this.wait_for_all_images, this, this.after_all_images_loaded, 1000); - } - }, - wait_for_all_images : function (e, doafterwards, wait) { - if (wait === undefined) { - wait = 0; - } - e.target.removeClass('loading'); - if (this.doc.bg_img().hasClass('loading')){ - return; - } - var dragimagesstillloading = this.doc.drag_image_homes().filter('.loading'); - if (dragimagesstillloading.size() !== 0){ - return; - } - - //if we get here everything has loaded - this.doc.drag_image_homes().detach('load', this.wait_for_all_images); - this.doc.bg_img().detach('load', this.wait_for_all_images); - - if (wait === 0) { - doafterwards.call(this); - } else { - this.Y.later(wait, this, function (e) { - doafterwards.call(this); - }, this); + .after('load', this.poll_for_image_load, this, 1000, this.after_all_images_loaded); } }, @@ -405,11 +379,11 @@ M.qtype_ddimagetoimage={ //set up drag items homes var dragimagesoptions = {0: ''}; for (var i=0; i < this.form.get_form_value('noimages'); i++) { - this.load_drag_image_home(i); + this.load_drag_home(i); } }, - load_drag_image_home : function (dragimageno) { + load_drag_home : function (dragimageno) { var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).href; this.doc.add_or_update_drag_image_home(dragimageno, url, this.form.get_form_value('drags', [dragimageno, 'draglabel']), From a8be2699a99d7c4afb2d6d3f16d44c572217cd4a Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 18 Aug 2011 18:44:40 +0700 Subject: [PATCH 049/208] MDL-47494 ddimageortext: NOBUG more work to make JS more reliable across browsers. --- question/type/ddimageortext/module.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index 8703ceb559b..79f0c0198a2 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -292,16 +292,11 @@ M.qtype_ddimagetoimage={ maxwidth = Math.max(maxwidth, image.get('width')); maxheight = Math.max(maxheight, image.get('height')); }, this); - console.log('groupno : '+groupno); - console.log('maxwidth : '+maxwidth); - console.log('maxheight : '+maxheight); groupimages.each(function(image) { var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); image.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' +margintopbottom+'px '+marginleftright+'px'); - console.log(margintopbottom+'px '+marginleftright+'px ' - +margintopbottom+'px '+marginleftright+'px'); }, this); this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, 'height': maxheight + 10}); @@ -373,6 +368,7 @@ M.qtype_ddimagetoimage={ if (reduceby > 1) { e.target.set('width', Math.floor(e.target.get('width') / reduceby)); } + e.target.detach('load', this.constrain_image_size); }, load_drag_homes : function () { From 09a9329a5ac96f2e37e5dd5137b8cc38412e2e89 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 18 Aug 2011 22:28:15 +0700 Subject: [PATCH 050/208] MDL-47494 ddimageortext: NOBUG removing some of the redundant node clones. --- question/type/ddimageortext/module.js | 46 ++++++++++++++++++++------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index 79f0c0198a2..1edc62d1be7 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -328,10 +328,11 @@ M.qtype_ddimagetoimage={ draw_dd_area : function() { var bgimageurl = this.fp.file(this.form.to_name_with_index('bgimage')).href; + this.stop_selector_events(); + this.set_options_for_drag_image_selectors(); if (bgimageurl !== null) { this.doc.load_bg_img(bgimageurl); this.load_drag_homes(); - this.setup_form_events(); var drop = new this.Y.DD.Drop({ node: this.doc.bg_img() @@ -350,15 +351,17 @@ M.qtype_ddimagetoimage={ .after('load', this.poll_for_image_load, this, 1000, this.after_all_images_loaded); this.doc.drag_image_homes() .after('load', this.poll_for_image_load, this, 1000, this.after_all_images_loaded); + } else { + this.setup_form_events(); } }, after_all_images_loaded : function () { - this.doc.drag_images().remove(true); - this.copy_drag_instances(); + this.update_drag_instances(); this.update_padding_sizes_all(); this.reposition_drags(); this.set_options_for_drag_image_selectors(); + this.setup_form_events(); }, constrain_image_size : function (e, imagetype) { @@ -386,11 +389,11 @@ M.qtype_ddimagetoimage={ this.form.get_form_value('drags', [dragimageno, 'draggroup'])); }, - copy_drag_instances : function () { + update_drag_instances : function () { //set up drop zones for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { var dragimageno = this.form.get_form_value('drops', [i, 'choice']); - if (dragimageno !== '0') { + if (dragimageno !== '0' && (this.doc.drag_image(i) === null)) { var drag = this.doc.clone_new_drag_image(i, dragimageno - 1); if (drag !== null) { this.doc.draggable_for_form(drag); @@ -434,6 +437,10 @@ M.qtype_ddimagetoimage={ } } }, + + stop_selector_events : function () { + this.Y.all('fieldset#dropzoneheader select').detachAll(); + }, setup_form_events : function () { //events triggered by changes to form data @@ -441,23 +448,40 @@ M.qtype_ddimagetoimage={ //x and y coordinates this.Y.all('fieldset#dropzoneheader input').on('blur', function (e){ var name = e.target.getAttribute('name'); - var nameparts = this.form.from_name_with_index(name); - this.reposition_drag(nameparts.indexes[0]); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + this.reposition_drag(draginstanceno); }, this); //change in selected image - this.Y.all('fieldset#dropzoneheader select').on('change', this.draw_dd_area, this); + this.Y.all('fieldset#dropzoneheader select').on('change', function (e){ + var name = e.target.getAttribute('name'); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + var old = this.doc.drag_image(draginstanceno); + if (old !== null) { + old.remove(true); + } + this.draw_dd_area(); + }, this); for (var i=0; i < this.form.get_form_value('noimages'); i++) { //change to group selector - this.Y.all('fieldset#draggableimageheader_'+i+' select') - .on('change', this.draw_dd_area, this); + this.Y.all('fieldset#draggableimageheader_'+i+' select').on('change', function (e, i){ + this.doc.drag_images_cloned_from(i).remove(true); + this.draw_dd_area(); + }, this, i); //change to infinite checkbox this.Y.all('fieldset#draggableimageheader_'+i+' input[type="checkbox"]') .on('change', this.set_options_for_drag_image_selectors, this); } //event on file picker new file selection - this.Y.after(this.draw_dd_area, M.form_filepicker, 'callback', this); + this.Y.after(function (e){ + var name = this.fp.name(e.id); + if (name !== 'bgimage') { + var dragimageeno = this.form.from_name_with_index(name).indexes[0]; + this.doc.drag_images_cloned_from(dragimageeno).remove(true); + } + this.draw_dd_area(); + }, M.form_filepicker, 'callback', this); }, From 1f6d7f5f2646a27f3ac0dcfdde42e3df7d4e8a3a Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 19 Aug 2011 12:59:30 +0700 Subject: [PATCH 051/208] MDL-47494 ddimageortext: NOBUG further hardening of JS. Fixed bugs in poll_for_image_load and fixed error in IE7 about undefined parameters. --- question/type/ddimageortext/module.js | 71 ++++++++++++++++----------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/module.js index 1edc62d1be7..b9e9a4908e8 100644 --- a/question/type/ddimageortext/module.js +++ b/question/type/ddimageortext/module.js @@ -13,18 +13,28 @@ M.qtype_ddimagetoimage={ this.doc = this.doc_structure(Y, Y.one(topnodestr), this, null); this.poll_for_image_load(null, 1000, this.create_all_drag_and_drops); this.doc.bg_img() - .after('load', this.poll_for_image_load, this, 1000, this.create_all_drag_and_drops); + .after('load', this.poll_for_image_load, this, false, 1000, this.create_all_drag_and_drops); this.doc.drag_image_homes() - .after('load', this.poll_for_image_load, this, 1000, this.create_all_drag_and_drops); - this.Y.on('windowresize', this.redraw, this); + .after('load', this.poll_for_image_load, this, false, 1000, this.create_all_drag_and_drops); + this.Y.on('windowresize', this.reposition_drags_for_question, this); }, polltimer : null, - poll_for_image_load : function (e, pause, doafterwords) { - if (this.doc.bg_img().get('complete')) { - var notalldragsloaded = this.doc.drag_image_homes().some(function(dragimagehome){ - !dragimagehome.get('complete'); + poll_for_image_load : function (e, waitforimageconstrain, pause, doafterwords) { + var bgdone = this.doc.bg_img().get('complete'); + if (waitforimageconstrain) { + bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); + } + if (bgdone) { + var alldragsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ + //in 'some' loop returning true breaks the loop and is passed as return value from + //'some' else returns false. Can be though of as equivalent to ||. + var done = (dragimagehome.get('complete')); + if (waitforimageconstrain) { + done = done && dragimagehome.hasClass('constrained'); + } + return !done; }); - if (!notalldragsloaded) { + if (alldragsloaded) { if (this.polltimer !== null) { this.polltimer.cancel(); this.polltimer = null; @@ -37,7 +47,9 @@ M.qtype_ddimagetoimage={ doafterwords.call(this); } } else if (this.polltimer === null) { - this.polltimer = this.Y.later(500, this.poll_for_image_load, this, true); + var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; + this.polltimer = + this.Y.later(500, this, this.poll_for_image_load, pollarguments, true); } } }, @@ -68,9 +80,9 @@ M.qtype_ddimagetoimage={ } }, this); this.update_padding_sizes_all(); - this.redraw(); + this.reposition_drags_for_question(); }, - redraw : function() { + reposition_drags_for_question : function() { this.doc.drag_images().removeClass('placed'); this.doc.drag_images().each (function (dragimage) { if (dragimage.dd !== undefined) { @@ -244,7 +256,7 @@ M.qtype_ddimagetoimage={ }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); dd.on('drag:end', function(e) { - mainobj.redraw(); + mainobj.reposition_drags_for_question(); }, this); drag.setData('group', group); drag.setData('choice', choice); @@ -327,7 +339,7 @@ M.qtype_ddimagetoimage={ }, draw_dd_area : function() { - var bgimageurl = this.fp.file(this.form.to_name_with_index('bgimage')).href; + var bgimageurl = this.fp.file('bgimage').href; this.stop_selector_events(); this.set_options_for_drag_image_selectors(); if (bgimageurl !== null) { @@ -342,15 +354,14 @@ M.qtype_ddimagetoimage={ e.drag.get('node').setData('gooddrop', true); }); - this.Y.on('windowresize', this.reposition_drags, this); + this.Y.on('windowresize', this.reposition_drags_for_form, this); this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage') this.doc.drag_image_homes().on('load', this.constrain_image_size, this, 'dragimage'); - this.poll_for_image_load(null, 1000, this.after_all_images_loaded); this.doc.bg_img() - .after('load', this.poll_for_image_load, this, 1000, this.after_all_images_loaded); + .after('load', this.poll_for_image_load, this, true, 1000, this.after_all_images_loaded); this.doc.drag_image_homes() - .after('load', this.poll_for_image_load, this, 1000, this.after_all_images_loaded); + .after('load', this.poll_for_image_load, this, true, 1000, this.after_all_images_loaded); } else { this.setup_form_events(); } @@ -359,7 +370,7 @@ M.qtype_ddimagetoimage={ after_all_images_loaded : function () { this.update_drag_instances(); this.update_padding_sizes_all(); - this.reposition_drags(); + this.reposition_drags_for_form(); this.set_options_for_drag_image_selectors(); this.setup_form_events(); }, @@ -371,13 +382,14 @@ M.qtype_ddimagetoimage={ if (reduceby > 1) { e.target.set('width', Math.floor(e.target.get('width') / reduceby)); } + e.target.addClass('constrained'); e.target.detach('load', this.constrain_image_size); }, load_drag_homes : function () { //set up drag items homes var dragimagesoptions = {0: ''}; - for (var i=0; i < this.form.get_form_value('noimages'); i++) { + for (var i=0; i < this.form.get_form_value('noimages', []); i++) { this.load_drag_home(i); } }, @@ -391,7 +403,7 @@ M.qtype_ddimagetoimage={ update_drag_instances : function () { //set up drop zones - for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { + for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { var dragimageno = this.form.get_form_value('drops', [i, 'choice']); if (dragimageno !== '0' && (this.doc.drag_image(i) === null)) { var drag = this.doc.clone_new_drag_image(i, dragimageno - 1); @@ -403,13 +415,13 @@ M.qtype_ddimagetoimage={ }, set_options_for_drag_image_selectors : function () { var dragimagesoptions = {0: ''}; - for (var i=0; i < this.form.get_form_value('noimages'); i++) { + for (var i=0; i < this.form.get_form_value('noimages', []); i++) { var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); if (file.name !== null) { dragimagesoptions[i+1] = (i+1)+'. '+file.name; } } - for (var i=0; i < this.form.get_form_value('nodropzone'); i++) { + for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { var selector = this.Y.one('#id_drops_'+i+'_choice'); var selectedvalue = selector.get('value'); selector.all('option').remove(true); @@ -449,7 +461,7 @@ M.qtype_ddimagetoimage={ this.Y.all('fieldset#dropzoneheader input').on('blur', function (e){ var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; - this.reposition_drag(draginstanceno); + this.reposition_drag_for_form(draginstanceno); }, this); //change in selected image @@ -463,7 +475,7 @@ M.qtype_ddimagetoimage={ this.draw_dd_area(); }, this); - for (var i=0; i < this.form.get_form_value('noimages'); i++) { + for (var i=0; i < this.form.get_form_value('noimages', []); i++) { //change to group selector this.Y.all('fieldset#draggableimageheader_'+i+' select').on('change', function (e, i){ this.doc.drag_images_cloned_from(i).remove(true); @@ -485,14 +497,14 @@ M.qtype_ddimagetoimage={ }, - reposition_drags : function() { + reposition_drags_for_form : function() { this.doc.drag_images().each(function (drag) { var draginstanceno = drag.getData('draginstanceno'); - this.reposition_drag(draginstanceno); + this.reposition_drag_for_form(draginstanceno); }, this); }, - reposition_drag : function (draginstanceno) { + reposition_drag_for_form : function (draginstanceno) { var drag = this.doc.drag_image(draginstanceno); if (null !== drag) { var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), @@ -514,12 +526,12 @@ M.qtype_ddimagetoimage={ xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.floor(xy[0])); this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.floor(xy[1])); - this.reposition_drag(draginstanceno); + this.reposition_drag_for_form(draginstanceno); }, reset_drag_xy : function (draginstanceno) { this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); - this.reposition_drag(draginstanceno); + this.reposition_drag_for_form(draginstanceno); }, //make sure xy value is not out of bounds of bg image @@ -543,7 +555,6 @@ M.qtype_ddimagetoimage={ */ form : { to_name_with_index : function(name, indexes) { - indexes = indexes || []; var indexstring = name; for (var i=0; i < indexes.length; i++) { indexstring = indexstring + '[' + indexes[i] + ']'; From 23f1e8f539977869095cfb64b7e11fec66985828 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 19 Aug 2011 13:05:34 +0700 Subject: [PATCH 052/208] MDL-47494 ddimageortext: NOBUG renamed module.js to dd.js to make it easier to find in list of js files in js debugger, makes sense to have a more descriptive name I think. --- question/type/ddimageortext/{module.js => dd.js} | 0 question/type/ddimageortext/edit_ddimagetoimage_form.php | 3 ++- question/type/ddimageortext/renderer.php | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename question/type/ddimageortext/{module.js => dd.js} (100%) diff --git a/question/type/ddimageortext/module.js b/question/type/ddimageortext/dd.js similarity index 100% rename from question/type/ddimageortext/module.js rename to question/type/ddimageortext/dd.js diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index d5cf5f70fa9..35fa35ad93c 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -257,7 +257,8 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $jsmodule = array( 'name' => 'qtype_ddimagetoimage', - 'fullpath' => '/question/type/ddimagetoimage/module.js', + 'fullpath' => '/question/type/ddimagetoimage/dd.js', + //we can make sure that file picker is loaded first by including it here 'requires' => array('node', 'dd', 'dd-drop', 'dd-constrain', 'form_filepicker') ); $maxsizes =new stdClass(); diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 4709718c8fb..488bbe1c090 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -109,7 +109,7 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere } $jsmodule = array( 'name' => 'qtype_ddimagetoimage', - 'fullpath' => '/question/type/ddimagetoimage/module.js', + 'fullpath' => '/question/type/ddimagetoimage/dd.js', 'requires' => array('node', 'dd', 'dd-drop', 'dd-constrain') ); From 14178839d93e34676754ba862eaecc99aab769b0 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 19 Aug 2011 14:41:45 +0700 Subject: [PATCH 053/208] MDL-47494 ddimageortext: NOBUG fixed bug seen in IE7 with poll_image_load and with padding sizes. --- question/type/ddimageortext/dd.js | 54 +++++++++++++++---------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/question/type/ddimageortext/dd.js b/question/type/ddimageortext/dd.js index b9e9a4908e8..767901851c4 100644 --- a/question/type/ddimageortext/dd.js +++ b/question/type/ddimageortext/dd.js @@ -24,33 +24,31 @@ M.qtype_ddimagetoimage={ if (waitforimageconstrain) { bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); } - if (bgdone) { - var alldragsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ - //in 'some' loop returning true breaks the loop and is passed as return value from - //'some' else returns false. Can be though of as equivalent to ||. - var done = (dragimagehome.get('complete')); - if (waitforimageconstrain) { - done = done && dragimagehome.hasClass('constrained'); - } - return !done; - }); - if (alldragsloaded) { - if (this.polltimer !== null) { - this.polltimer.cancel(); - this.polltimer = null; - } - this.doc.drag_image_homes().detach('load', this.poll_for_image_load); - this.doc.bg_img().detach('load', this.poll_for_image_load); - if (pause !== 0) { - this.Y.later(pause, this, doafterwords); - } else { - doafterwords.call(this); - } - } else if (this.polltimer === null) { - var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; - this.polltimer = - this.Y.later(500, this, this.poll_for_image_load, pollarguments, true); + var alldragsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ + //in 'some' loop returning true breaks the loop and is passed as return value from + //'some' else returns false. Can be though of as equivalent to ||. + var done = (dragimagehome.get('complete')); + if (waitforimageconstrain) { + done = done && dragimagehome.hasClass('constrained'); } + return !done; + }); + if (alldragsloaded && alldragsloaded) { + if (this.polltimer !== null) { + this.polltimer.cancel(); + this.polltimer = null; + } + this.doc.drag_image_homes().detach('load', this.poll_for_image_load); + this.doc.bg_img().detach('load', this.poll_for_image_load); + if (pause !== 0) { + this.Y.later(pause, this, doafterwords); + } else { + doafterwords.call(this); + } + } else if (this.polltimer === null) { + var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; + this.polltimer = + this.Y.later(500, this, this.poll_for_image_load, pollarguments, true); } }, create_all_drag_and_drops : function () { @@ -296,7 +294,7 @@ M.qtype_ddimagetoimage={ } }, update_padding_size_for_group : function (groupno) { - var groupimages = this.doc.top_node().all('img.group'+groupno); + var groupimages = this.doc.top_node().all('img.draghome.group'+groupno); if (groupimages.size() !== 0) { var maxwidth = 0; var maxheight = 0; @@ -368,8 +366,8 @@ M.qtype_ddimagetoimage={ }, after_all_images_loaded : function () { - this.update_drag_instances(); this.update_padding_sizes_all(); + this.update_drag_instances(); this.reposition_drags_for_form(); this.set_options_for_drag_image_selectors(); this.setup_form_events(); From 950ce139615870f8b7e98de9c478a95dae5b4a86 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 19 Aug 2011 15:07:20 +0700 Subject: [PATCH 054/208] MDL-47494 ddimageortext: NOBUG fixed (non)updating of padding size when group is changed. --- question/type/ddimageortext/dd.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/dd.js b/question/type/ddimageortext/dd.js index 767901851c4..bd214a6c8b1 100644 --- a/question/type/ddimageortext/dd.js +++ b/question/type/ddimageortext/dd.js @@ -476,7 +476,7 @@ M.qtype_ddimagetoimage={ for (var i=0; i < this.form.get_form_value('noimages', []); i++) { //change to group selector this.Y.all('fieldset#draggableimageheader_'+i+' select').on('change', function (e, i){ - this.doc.drag_images_cloned_from(i).remove(true); + this.doc.drag_images().remove(true); this.draw_dd_area(); }, this, i); //change to infinite checkbox From 61c6aed4c888abd65eb91354f03c3ec557bb0b15 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 19 Aug 2011 15:27:13 +0700 Subject: [PATCH 055/208] MDL-47494 ddimageortext: NOBUG previous commit which changed the way padding update worked broke padding setting in preview mode. Fixed now. --- question/type/ddimageortext/dd.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/dd.js b/question/type/ddimageortext/dd.js index bd214a6c8b1..98bd969adb5 100644 --- a/question/type/ddimageortext/dd.js +++ b/question/type/ddimageortext/dd.js @@ -53,6 +53,7 @@ M.qtype_ddimagetoimage={ }, create_all_drag_and_drops : function () { this.init_drops(); + this.update_padding_sizes_all(); var i = 0; this.doc.drag_image_homes().each(function(dragimagehome){ var dragimageno = @@ -77,7 +78,6 @@ M.qtype_ddimagetoimage={ } } }, this); - this.update_padding_sizes_all(); this.reposition_drags_for_question(); }, reposition_drags_for_question : function() { From 372aad7a966c96988d457b4607afc1240153cd8a Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 19 Aug 2011 18:18:18 +0700 Subject: [PATCH 056/208] MDL-47494 ddimageortext: NOBUG needed to switch to using drag id as item id for drag image fileareas. --- .../edit_ddimagetoimage_form.php | 9 +++-- question/type/ddimageortext/questiontype.php | 36 +++++++++++++------ 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 35fa35ad93c..d8af5d203ce 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -46,8 +46,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { */ public static function file_picker_options() { $filepickeroptions = array(); - //$filepickeroptions['accepted_types'] = array('web_image'); - $filepickeroptions['accepted_types'] = array('*'); + $filepickeroptions['accepted_types'] = array('web_image'); $filepickeroptions['maxbytes'] = 0; $filepickeroptions['maxfiles'] = 1; $filepickeroptions['subdirs'] = 0; @@ -234,10 +233,10 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { $draftitemid = file_get_submitted_draft_itemid("dragitem[$imageindex]"); //numbers not allowed in filearea name - $filearea = str_replace(range('0', '9'), range('a', 'j'), "drag_$imageindex"); + $itemid = !empty($question->drags[$imageindex]['id']) ? + (int) $question->options->drags['id'] : null; file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', - $filearea, !empty($question->id) ? (int) $question->id : null, - self::file_picker_options()); + 'dragimage', $itemid, self::file_picker_options()); $question->dragitem[$imageindex] = $draftitemid; } $question->drops = array(); diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 30a8e6f754a..9dc9f628533 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -87,7 +87,6 @@ class qtype_ddimagetoimage extends question_type { // Store the choices in arrays by group. foreach ($questiondata->options->drags as $dragdata) { - $filearea = self::drag_image_file_area($dragdata->no - 1); $choice = $this->make_choice($dragdata); @@ -149,19 +148,15 @@ class qtype_ddimagetoimage extends question_type { $DB->insert_record('qtype_ddimagetoimage_drops', $drop); } - $DB->delete_records('qtype_ddimagetoimage_drags', array('questionid' => $formdata->id)); + //an array of drag no -> drag id + $olddragids = $DB->get_records_menu('qtype_ddimagetoimage_drags', + array('questionid' => $formdata->id), + '', 'no, id'); foreach (array_keys($formdata->drags) as $dragno){ $info = file_get_draft_area_info($formdata->dragitem[$dragno]); if ($info['filecount'] > 0) { - $draftitemid = $formdata->dragitem[$dragno]; + $draftitemid = file_get_submitted_draft_itemid("dragitem[$dragno]"); - $filearea = self::drag_image_file_area($dragno); - self::constrain_image_size_in_draft_area($draftitemid, - QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH, - QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT); - file_save_draft_area_files($draftitemid, $formdata->context->id, - 'qtype_ddimagetoimage', $filearea, $formdata->id, - array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); $drag = new stdClass(); $drag->questionid = $formdata->id; $drag->no = $dragno + 1; @@ -169,9 +164,28 @@ class qtype_ddimagetoimage extends question_type { $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; $drag->label = $formdata->drags[$dragno]['draglabel']; - $DB->insert_record('qtype_ddimagetoimage_drags', $drag); + if (isset($olddragids[$dragno +1])) { + $drag->id = $olddragids[$dragno +1]; + unset($olddragids[$dragno +1]); + $DB->update_record('qtype_ddimagetoimage_drags', $drag); + } else { + $drag->id = $DB->insert_record('qtype_ddimagetoimage_drags', $drag); + } + + + + self::constrain_image_size_in_draft_area($draftitemid, + QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH, + QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT); + file_save_draft_area_files($draftitemid, $formdata->context->id, + 'qtype_ddimagetoimage', 'dragimage', $drag->id, + array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); } } + if (!empty($olddragids)) { + list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); + $DB->delete_records_select('qtype_ddimagetoimage_drags', "id $sql", $params); + } self::constrain_image_size_in_draft_area($formdata->bgimage, QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH, From 7cac27f4e1c3484a9f5a5feb80f82c9fdb161815 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 19 Aug 2011 19:31:44 +0700 Subject: [PATCH 057/208] MDL-47494 ddimageortext: NOBUG issue with padding updating when uploading a new image in the same group. --- question/type/ddimageortext/dd.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/question/type/ddimageortext/dd.js b/question/type/ddimageortext/dd.js index 98bd969adb5..88a0dac7241 100644 --- a/question/type/ddimageortext/dd.js +++ b/question/type/ddimageortext/dd.js @@ -475,10 +475,10 @@ M.qtype_ddimagetoimage={ for (var i=0; i < this.form.get_form_value('noimages', []); i++) { //change to group selector - this.Y.all('fieldset#draggableimageheader_'+i+' select').on('change', function (e, i){ + this.Y.all('fieldset#draggableimageheader_'+i+' select').on('change', function (e){ this.doc.drag_images().remove(true); this.draw_dd_area(); - }, this, i); + }, this); //change to infinite checkbox this.Y.all('fieldset#draggableimageheader_'+i+' input[type="checkbox"]') .on('change', this.set_options_for_drag_image_selectors, this); @@ -487,8 +487,7 @@ M.qtype_ddimagetoimage={ this.Y.after(function (e){ var name = this.fp.name(e.id); if (name !== 'bgimage') { - var dragimageeno = this.form.from_name_with_index(name).indexes[0]; - this.doc.drag_images_cloned_from(dragimageeno).remove(true); + this.doc.drag_images().remove(true); } this.draw_dd_area(); }, M.form_filepicker, 'callback', this); From 3c2b258d19278c26eab0d5ea1d885175662d4044 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 20 Aug 2011 10:36:50 +0700 Subject: [PATCH 058/208] MDL-47494 ddimageortext: NOBUG changed to using dragimage as filearea for dragimages and using drag id as item id instead of using file area dragimage_[a-j] etc. --- .../backup_qtype_ddwtos_plugin.class.php | 83 ----------------- .../restore_qtype_ddwtos_plugin.class.php | 92 ------------------- .../edit_ddimagetoimage_form.php | 33 ++++--- question/type/ddimageortext/question.php | 21 ++++- question/type/ddimageortext/questiontype.php | 10 +- question/type/ddimageortext/renderer.php | 12 ++- 6 files changed, 45 insertions(+), 206 deletions(-) delete mode 100755 question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php delete mode 100755 question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php deleted file mode 100755 index 95dbc936292..00000000000 --- a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddwtos_plugin.class.php +++ /dev/null @@ -1,83 +0,0 @@ -. - -/** - * @package moodlecore - * @subpackage backup-moodle2 - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - - -defined('MOODLE_INTERNAL') || die(); - - -/** - * Provides the information to backup ddimagetoimage questions - * - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { - - /** - * Returns the qtype information to attach to question element - */ - protected function define_question_plugin_structure() { - - // Define the virtual plugin element with the condition to fulfill - $plugin = $this->get_plugin_element(null, '../../qtype', 'ddimagetoimage'); - - // Create one standard named plugin element (the visible container) - $pluginwrapper = new backup_nested_element($this->get_recommended_name()); - - // connect the visible container ASAP - $plugin->add_child($pluginwrapper); - - // This qtype uses standard question_answers, add them here - // to the tree before any other information that will use them - $this->add_question_question_answers($pluginwrapper); - - // Now create the qtype own structures - $ddimagetoimage = new backup_nested_element('ddimagetoimage', array('id'), array( - 'shuffleanswers', 'correctfeedback', 'correctfeedbackformat', - 'partiallycorrectfeedback', 'partiallycorrectfeedbackformat', - 'incorrectfeedback', 'incorrectfeedbackformat', 'shownumcorrect')); - - // Now the own qtype tree - $pluginwrapper->add_child($ddimagetoimage); - - // set source to populate the data - $ddimagetoimage->set_source_table('question_ddimagetoimage', array('questionid' => backup::VAR_PARENTID)); - - // don't need to annotate ids nor files - - return $plugin; - } - - /** - * Returns one array with filearea => mappingname elements for the qtype - * - * Used by {@link get_components_and_fileareas} to know about all the qtype - * files to be processed both in backup and restore. - */ - public static function get_qtype_fileareas() { - return array( - 'correctfeedback' => 'question_created', - 'partiallycorrectfeedback' => 'question_created', - 'incorrectfeedback' => 'question_created'); - } -} diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php deleted file mode 100755 index 361c06da75a..00000000000 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddwtos_plugin.class.php +++ /dev/null @@ -1,92 +0,0 @@ -. - -/** - * @package moodlecore - * @subpackage backup-moodle2 - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - - -defined('MOODLE_INTERNAL') || die(); - - -/** - * restore plugin class that provides the necessary information - * needed to restore one ddimagetoimage qtype plugin - * - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { - - /** - * Returns the paths to be handled by the plugin at question level - */ - protected function define_question_plugin_structure() { - - $paths = array(); - - // This qtype uses question_answers, add them - $this->add_question_question_answers($paths); - - // Add own qtype stuff - $elename = 'ddimagetoimage'; - $elepath = $this->get_pathfor('/ddimagetoimage'); // we used get_recommended_name() so this works - $paths[] = new restore_path_element($elename, $elepath); - - return $paths; // And we return the interesting paths - } - - /** - * Process the qtype/ddimagetoimage element - */ - public function process_ddimagetoimage($data) { - global $DB; - - $data = (object)$data; - $oldid = $data->id; - - // Detect if the question is created or mapped - $oldquestionid = $this->get_old_parentid('question'); - $newquestionid = $this->get_new_parentid('question'); - $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; - - // If the question has been created by restore, we need to create its question_ddimagetoimage too - if ($questioncreated) { - // Adjust some columns - $data->questionid = $newquestionid; - // Insert record - $newitemid = $DB->insert_record('question_ddimagetoimage', $data); - // Create mapping (needed for decoding links) - $this->set_mapping('question_ddimagetoimage', $oldid, $newitemid); - } - } - - /** - * Return the contents of this qtype to be processed by the links decoder - */ - public static function define_decode_contents() { - - $contents = array(); - - $fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'); - $contents[] = new restore_decode_content('question_ddimagetoimage', $fields, 'question_ddimagetoimage'); - - return $contents; - } -} diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index d8af5d203ce..548e6a01213 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -219,6 +219,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $question = $this->data_preprocessing_combined_feedback($question, true); $question = $this->data_preprocessing_hints($question, true, true); + $dragids = array(); // drag no -> dragid if (!empty($question->options)) { $question->shuffleanswers = $question->options->shuffleanswers; $question->drags = array(); @@ -228,16 +229,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $question->drags[$dragindex]['draglabel'] = $drag->label; $question->drags[$dragindex]['infinite'] = $drag->infinite; $question->drags[$dragindex]['draggroup'] = $drag->draggroup; - } - list(, $imagerepeats) = $this->get_drag_image_repeats(); - for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { - $draftitemid = file_get_submitted_draft_itemid("dragitem[$imageindex]"); - //numbers not allowed in filearea name - $itemid = !empty($question->drags[$imageindex]['id']) ? - (int) $question->options->drags['id'] : null; - file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', - 'dragimage', $itemid, self::file_picker_options()); - $question->dragitem[$imageindex] = $draftitemid; + $dragids[$dragindex] = $drag->id; } $question->drops = array(); foreach ($question->options->drops as $drop) { @@ -247,11 +239,24 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $question->drops[$drop->no -1]['xleft'] = $drop->xleft; $question->drops[$drop->no -1]['ytop'] = $drop->ytop; } - $draftitemid = file_get_submitted_draft_itemid('bgimage'); + } + //initialise file picker for bgimage + $draftitemid = file_get_submitted_draft_itemid('bgimage'); + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', + 'bgimage', !empty($question->id) ? (int) $question->id : null, + self::file_picker_options()); + $question->bgimage = $draftitemid; + + //initialise file picker for dragimages + list(, $imagerepeats) = $this->get_drag_image_repeats(); + $draftitemids = optional_param('dragitem', array(), PARAM_INT); + for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { + $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; + //numbers not allowed in filearea name + $itemid = isset($dragids[$imageindex]) ? $dragids[$imageindex] : null; file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', - 'bgimage', !empty($question->id) ? (int) $question->id : null, - self::file_picker_options()); - $question->bgimage = $draftitemid; + 'dragimage', $itemid, self::file_picker_options()); + $question->dragitem[$imageindex] = $draftitemid; } $jsmodule = array( diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 186dfdfbc4b..9e76dcf5068 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -74,15 +74,26 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { } public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) { - if ($filearea == 'bgimage' || preg_match('!drag\_[a-j]+$!A', $filearea)) { + if ($filearea == 'bgimage' || $filearea == 'dragimage') { $validfilearea = true; } else { $validfilearea = false; } if ($component == 'qtype_ddimagetoimage' && $validfilearea) { $question = $qa->get_question(); - $questionid = reset($args); // itemid is answer id. - return $questionid == $question->id; + $itemid = reset($args); + if ($filearea == 'bgimage') { + return $itemid == $question->id; + } else if ($filearea == 'dragimage') { + foreach ($question->choices as $group) { + foreach ($group as $drag) { + if ($drag->id == $itemid) { + return true; + } + } + } + return false; + } } else { return parent::check_file_access($qa, $options, $component, $filearea, $args, $forcedownload); @@ -98,12 +109,14 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddimagetoimage_drag_item { + public $id; public $alttextlabel; public $no; public $group; public $isinfinite; - public function __construct($alttextlabel, $no, $group = 1, $isinfinite = false) { + public function __construct($alttextlabel, $no, $group = 1, $isinfinite = false, $id = 0) { + $this->id = $id; $this->text = $alttextlabel; $this->no = $no; $this->group = $group; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 9dc9f628533..258abdf7442 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -64,7 +64,7 @@ class qtype_ddimagetoimage extends question_type { protected function make_choice($dragdata) { return new qtype_ddimagetoimage_drag_item($dragdata->label, $dragdata->no, - $dragdata->draggroup, $dragdata->infinite); + $dragdata->draggroup, $dragdata->infinite, $dragdata->id); } protected function make_place($dropzonedata) { @@ -155,7 +155,7 @@ class qtype_ddimagetoimage extends question_type { foreach (array_keys($formdata->drags) as $dragno){ $info = file_get_draft_area_info($formdata->dragitem[$dragno]); if ($info['filecount'] > 0) { - $draftitemid = file_get_submitted_draft_itemid("dragitem[$dragno]"); + $draftitemid = $formdata->dragitem[$dragno]; $drag = new stdClass(); $drag->questionid = $formdata->id; @@ -195,12 +195,6 @@ class qtype_ddimagetoimage extends question_type { array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); } - public static function drag_image_file_area($dragno) { - //numbers not allowed in filearea name - return str_replace(range('0', '9'), range('a', 'j'), "drag_$dragno"); - } - - public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) { global $USER; $usercontext = get_context_instance(CONTEXT_USER, $USER->id); diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 488bbe1c090..4b28e5e8731 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -76,8 +76,7 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $dragimagehomesgroup = ''; $orderedgroup = $question->get_ordered_choices($groupno); foreach ($orderedgroup as $choiceno => $dragimage) { - $filearea = qtype_ddimagetoimage::drag_image_file_area($dragimage->no - 1); - $dragimageurl = self::get_url_for_image($qa, $filearea); + $dragimageurl = self::get_url_for_image($qa, 'dragimage', $dragimage->id); $classes = array("group{$groupno}", 'draghome', "dragimagehomes{$dragimage->no}", @@ -123,20 +122,23 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere return $output; } - protected static function get_url_for_image(question_attempt $qa, $filearea) { + protected static function get_url_for_image(question_attempt $qa, $filearea, $itemid = 0) { $question = $qa->get_question(); $qubaid = $qa->get_usage_id(); $slot = $qa->get_slot(); $fs = get_file_storage(); + if ($filearea == 'bgimage') { + $itemid = $question->id; + } $draftfiles = $fs->get_area_files($question->contextid, 'qtype_ddimagetoimage', - $filearea, $question->id, 'id'); + $filearea, $itemid, 'id'); if ($draftfiles) { foreach ($draftfiles as $file) { if ($file->is_directory()) { continue; } $url = moodle_url::make_pluginfile_url($question->contextid, 'qtype_ddimagetoimage', - $filearea, "$qubaid/$slot/{$question->id}", '/', + $filearea, "$qubaid/$slot/{$itemid}", '/', $file->get_filename()); return $url->out(); } From f8db3110620e7339e7a443f071732b85b7435582 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 20 Aug 2011 11:16:36 +0700 Subject: [PATCH 059/208] MDL-47494 ddimageortext: NOBUG implemented moving and deleting files associated with question when question is moved or deleted. --- question/type/ddimageortext/questiontype.php | 35 ++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 258abdf7442..108c7283a09 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -238,6 +238,41 @@ class qtype_ddimagetoimage extends question_type { } } } + public function move_files($questionid, $oldcontextid, $newcontextid) { + global $DB; + $fs = get_file_storage(); + parent::move_files($questionid, $oldcontextid, $newcontextid); + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'qtype_ddimagetoimage', 'bgimage', $questionid); + $dragids = $DB->get_records_menu('qtype_ddimagetoimage_drags', + array('questionid' => $questionid), 'id', 'id,1'); + foreach ($dragids as $dragid => $notused) { + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'qtype_ddimagetoimage', 'dragimage', $dragid); + } + $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); + } + + /** + * Delete all the files belonging to this question. + * @param int $questionid the question being deleted. + * @param int $contextid the context the question is in. + */ + + protected function delete_files($questionid, $contextid) { + global $DB; + $fs = get_file_storage(); + + parent::delete_files($questionid, $contextid); + + $dragids = $DB->get_records_menu('qtype_ddimagetoimage_drags', + array('questionid' => $questionid), 'id', 'id,1'); + foreach ($dragids as $dragid => $notused) { + $fs->delete_area_files($contextid, 'qtype_ddimagetoimage', 'dragimage', $dragid); + } + + $this->delete_files_in_combined_feedback($questionid, $contextid); + } } From de1291955f408e45e137be469a3cd5d9daeb32df Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 20 Aug 2011 12:55:47 +0700 Subject: [PATCH 060/208] MDL-47494 ddimageortext: NOBUG implementing question back up and restore. --- ...ckup_qtype_ddimagetoimage_plugin.class.php | 94 ++++++++++++ ...tore_qtype_ddimagetoimage_plugin.class.php | 144 ++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php create mode 100644 question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php new file mode 100644 index 00000000000..4aeef438677 --- /dev/null +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php @@ -0,0 +1,94 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +defined('MOODLE_INTERNAL') || die(); + + +/** + * Provides the information to backup ddimagetoimage questions + * + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { + + /** + * Returns the qtype information to attach to question element + */ + protected function define_question_plugin_structure() { + + $plugin = $this->get_plugin_element(null, '../../qtype', 'ddimagetoimage'); + + $pluginwrapper = new backup_nested_element($this->get_recommended_name()); + + $plugin->add_child($pluginwrapper); + + $ddimagetoimages = new backup_nested_element('ddimagetoimage', array('id'), array( + 'shuffleanswers', 'correctfeedback', 'correctfeedbackformat', + 'partiallycorrectfeedback', 'partiallycorrectfeedbackformat', + 'incorrectfeedback', 'incorrectfeedbackformat', 'shownumcorrect')); + + $pluginwrapper->add_child($ddimagetoimages); + $drags = new backup_nested_element('drags'); + + $drag = new backup_nested_element('drag', array('id'), + array('no', 'draggroup', 'infinite', 'label')); + $drops = new backup_nested_element('drops'); + + $drop = new backup_nested_element('drop', array('id'), + array('no', 'xleft', 'ytop', 'choice', 'label')); + + + $ddimagetoimages->set_source_table('qtype_ddimagetoimage', + array('questionid' => backup::VAR_PARENTID)); + + $pluginwrapper->add_child($drags); + $drags->add_child($drag); + $pluginwrapper->add_child($drops); + $drops->add_child($drop); + + $drag->set_source_table('qtype_ddimagetoimage_drags', + array('questionid' => backup::VAR_PARENTID)); + + + $drop->set_source_table('qtype_ddimagetoimage_drops', + array('questionid' => backup::VAR_PARENTID)); + + return $plugin; + } + + /** + * Returns one array with filearea => mappingname elements for the qtype + * + * Used by {@link get_components_and_fileareas} to know about all the qtype + * files to be processed both in backup and restore. + */ + public static function get_qtype_fileareas() { + return array( + 'correctfeedback' => 'question_created', + 'partiallycorrectfeedback' => 'question_created', + 'incorrectfeedback' => 'question_created', + + 'bgimage' => 'question_created', + 'dragimage' => 'qtype_ddimagetoimage_drags'); + } +} diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php new file mode 100644 index 00000000000..eeb4ac1f289 --- /dev/null +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php @@ -0,0 +1,144 @@ +. + +/** + * @package moodlecore + * @subpackage backup-moodle2 + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + + +/** + * restore plugin class that provides the necessary information + * needed to restore one ddimagetoimage qtype plugin + * + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { + + /** + * Returns the paths to be handled by the plugin at question level + */ + protected function define_question_plugin_structure() { + + $paths = array(); + + // Add own qtype stuff + $elename = 'ddimagetoimage'; + $elepath = $this->get_pathfor('/ddimagetoimage'); + $paths[] = new restore_path_element($elename, $elepath); + + $elename = 'drag'; + $elepath = $this->get_pathfor('/drags/drag'); + $paths[] = new restore_path_element($elename, $elepath); + + $elename = 'drop'; + $elepath = $this->get_pathfor('/drops/drop'); + $paths[] = new restore_path_element($elename, $elepath); + + return $paths; // And we return the interesting paths + } + + /** + * Process the qtype/ddimagetoimage element + */ + public function process_ddimagetoimage($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + // Detect if the question is created or mapped + $oldquestionid = $this->get_old_parentid('question'); + $newquestionid = $this->get_new_parentid('question'); + $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; + + // If the question has been created by restore, we need to create its qtype_ddimagetoimage too + if ($questioncreated) { + // Adjust some columns + $data->questionid = $newquestionid; + // Insert record + $newitemid = $DB->insert_record('qtype_ddimagetoimage', $data); + // Create mapping (needed for decoding links) + $this->set_mapping('qtype_ddimagetoimage', $oldid, $newitemid); + } + } + + /** + * Process the qtype/drags/drag element + */ + public function process_drag($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + // Detect if the question is created or mapped + $oldquestionid = $this->get_old_parentid('question'); + $newquestionid = $this->get_new_parentid('question'); + $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; + + if ($questioncreated) { + $data->questionid = $newquestionid; + // Insert record + $newitemid = $DB->insert_record('qtype_ddimagetoimage_drags', $data); + // Create mapping (there are files and states based on this) + $this->set_mapping('qtype_ddimagetoimage_drags', $oldid, $newitemid); + + } + } + + /** + * Process the qtype/drags/drag element + */ + public function process_drop($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + + // Detect if the question is created or mapped + $oldquestionid = $this->get_old_parentid('question'); + $newquestionid = $this->get_new_parentid('question'); + $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; + + if ($questioncreated) { + $data->questionid = $newquestionid; + // Insert record + $newitemid = $DB->insert_record('qtype_ddimagetoimage_drops', $data); + // Create mapping (there are files and states based on this) + $this->set_mapping('qtype_ddimagetoimage_drops', $oldid, $newitemid); + + } + } + /** + * Return the contents of this qtype to be processed by the links decoder + */ + public static function define_decode_contents() { + + $contents = array(); + + $fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'); + $contents[] = new restore_decode_content('qtype_ddimagetoimage', $fields, 'question_ddimagetoimage'); + + return $contents; + } +} From cc5a1217e6698fd8c47df81466a1a9b02f65a244 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 20 Aug 2011 18:13:20 +0700 Subject: [PATCH 061/208] MDL-47494 ddimageortext: NOBUG implemented import and export to Moodle XML format. --- .../edit_ddimagetoimage_form.php | 1 + question/type/ddimageortext/questiontype.php | 143 +++++++++++++++++- 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 548e6a01213..f5864a2a864 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -242,6 +242,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { } //initialise file picker for bgimage $draftitemid = file_get_submitted_draft_itemid('bgimage'); + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', 'bgimage', !empty($question->id) ? (int) $question->id : null, self::file_picker_options()); diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 108c7283a09..807f3748e1a 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * Question type class for the drag-and-drop words into sentences question type. + * Question type class for the drag-and-drop images onto images question type. * * @package qtype * @subpackage ddimagetoimage @@ -275,4 +275,145 @@ class qtype_ddimagetoimage extends question_type { $this->delete_files_in_combined_feedback($questionid, $contextid); } + + public function export_to_xml($question, $format, $extra = null) { + $fs = get_file_storage(); + $contextid = $question->contextid; + $output = ''; + + $output .= ' ' . $question->options->shuffleanswers . + "\n"; + + $output .= $format->write_combined_feedback($question->options); + $output .= $format->write_hints($question); + $files = $fs->get_area_files($contextid, 'qtype_ddimagetoimage', 'bgimage', $question->id); + $output .= " ".$this->write_files($files, 2)."\n";; + + foreach ($question->options->drags as $drag) { + $files = $fs->get_area_files($contextid, 'qtype_ddimagetoimage', 'dragimage', $drag->id); + $output .= " \n"; + $output .= " {$drag->no}\n"; + $output .= $format->writetext($drag->label, 3)."\n"; + $output .= " {$drag->draggroup}\n"; + if ($drag->infinite) { + $output .= " \n"; + } + $output .= $this->write_files($files, 3); + $output .= " \n"; + } + foreach ($question->options->drops as $drop) { + $output .= " \n"; + $output .= $format->writetext($drop->label, 3); + $output .= " {$drop->no}\n"; + $output .= " {$drop->choice}\n"; + $output .= " {$drop->xleft}\n"; + $output .= " {$drop->ytop}\n"; + $output .= " \n"; + } + + return $output; + } + + public function import_from_xml($data, $question, $format, $extra=null) { + if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimagetoimage') { + return false; + } + + $question = $format->import_headers($data); + $question->qtype = 'ddimagetoimage'; + + $question->shuffleanswers = $format->trans_single( + $format->getpath($data, array('#', 'shuffleanswers', 0, '#'), 1)); + $filexml = $format->getpath($data, array('#', 'file'), array()); + $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml); + $drags = $data['#']['drag']; + $question->drags = array(); + + foreach ($drags as $dragxml) { + $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0); + $dragindex = $dragno -1; + $question->drags[$dragindex] = array(); + $question->drags[$dragindex]['draglabel'] = + $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); + $question->drags[$dragindex]['infinite'] = + $format->getpath($dragxml, array('#', 'infinite', 0, '#'), 0); + $question->drags[$dragindex]['draggroup'] = + $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1); + $filexml = $format->getpath($dragxml, array('#', 'file'), array()); + $question->dragitem[$dragindex] = + $this->import_files_to_draft_file_area($format, $filexml); + } + + $drops = $data['#']['drop']; + $question->drops = array(); + foreach ($drops as $dropxml) { + $dropno = $format->getpath($dropxml, array('#', 'no', 0, '#'), 0); + $dropindex = $dropno -1; + $question->drops[$dropindex] = array(); + $question->drops[$dropindex]['choice'] = + $format->getpath($dropxml, array('#', 'choice', 0, '#'), 0); + $question->drops[$dropindex]['droplabel'] = + $format->getpath($dropxml, array('#', 'text', 0, '#'), '', true); + $question->drops[$dropindex]['xleft'] = + $format->getpath($dropxml, array('#', 'xleft', 0, '#'), ''); + $question->drops[$dropindex]['ytop'] = + $format->getpath($dropxml, array('#', 'ytop', 0, '#'), ''); + } + + $format->import_combined_feedback($question, $data, true); + $format->import_hints($question, $data, true); + + return $question; + } + + + /** + * Create a draft files area, import files into it and return the draft item id. + * @param qformat_xml $format + * @param array $xml an array of nodes from the the parsed XML. + * @return integer draftitemid + */ + public function import_files_to_draft_file_area($format, $xml) { + global $USER; + $fs = get_file_storage(); + $files = $format->import_files($xml); + $usercontext = get_context_instance(CONTEXT_USER, $USER->id); + $draftitemid = file_get_unused_draft_itemid(); + foreach ($files as $file) { + $record = new stdClass(); + $record->contextid = $usercontext->id; + $record->component = 'user'; + $record->filearea = 'draft'; + $record->itemid = $draftitemid; + $record->filename = $file->name; + $record->filepath = '/'; + $fs->create_file_from_string($record, $this->decode_file($file)); + } + return $draftitemid; + } + + /** + * Convert files into text output in the given format. + * This method is copied from qformat_default as a quick fix, as the method there is + * protected. + * @param array + * @param string encoding method + * @return string $string + */ + public function write_files($files, $indent) { + if (empty($files)) { + return ''; + } + $string = ''; + foreach ($files as $file) { + if ($file->is_directory()) { + continue; + } + $string .= str_repeat(' ', $indent); + $string .= ''; + $string .= base64_encode($file->get_content()); + $string .= ''; + } + return $string; + } } From f65546366dde11b1916b65419216cf4a647908ad Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 20 Aug 2011 20:36:05 +0700 Subject: [PATCH 062/208] MDL-47494 ddimageortext: NOBUG fixed shuffle choices value not being imported. --- question/type/ddimageortext/questiontype.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 807f3748e1a..22a6813a83c 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -281,9 +281,9 @@ class qtype_ddimagetoimage extends question_type { $contextid = $question->contextid; $output = ''; - $output .= ' ' . $question->options->shuffleanswers . - "\n"; - + if ($question->options->shuffleanswers) { + $output .= " \n"; + } $output .= $format->write_combined_feedback($question->options); $output .= $format->write_hints($question); $files = $fs->get_area_files($contextid, 'qtype_ddimagetoimage', 'bgimage', $question->id); @@ -322,8 +322,9 @@ class qtype_ddimagetoimage extends question_type { $question = $format->import_headers($data); $question->qtype = 'ddimagetoimage'; - $question->shuffleanswers = $format->trans_single( - $format->getpath($data, array('#', 'shuffleanswers', 0, '#'), 1)); + $question->shuffleanswers = array_key_exists('shuffleanswers', + $format->getpath($data, array('#'), array())); + $filexml = $format->getpath($data, array('#', 'file'), array()); $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml); $drags = $data['#']['drag']; @@ -335,8 +336,7 @@ class qtype_ddimagetoimage extends question_type { $question->drags[$dragindex] = array(); $question->drags[$dragindex]['draglabel'] = $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); - $question->drags[$dragindex]['infinite'] = - $format->getpath($dragxml, array('#', 'infinite', 0, '#'), 0); + $question->drags[$dragindex]['infinite'] = array_key_exists('infinite', $dragxml['#']); $question->drags[$dragindex]['draggroup'] = $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1); $filexml = $format->getpath($dragxml, array('#', 'file'), array()); @@ -412,7 +412,7 @@ class qtype_ddimagetoimage extends question_type { $string .= str_repeat(' ', $indent); $string .= ''; $string .= base64_encode($file->get_content()); - $string .= ''; + $string .= "\n"; } return $string; } From 9b2ccabae80e8ed8106a0deba2cd6bcce462909f Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 20 Aug 2011 20:52:38 +0700 Subject: [PATCH 063/208] MDL-47494 ddimageortext: NOBUG added feedback for student when they have not dragged an image to each drop zone. --- .../type/ddimageortext/lang/en/qtype_ddimagetoimage.php | 1 + question/type/ddimageortext/question.php | 6 ++++++ question/type/ddimageortext/renderer.php | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 1f744a6e232..e065751d67b 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -48,6 +48,7 @@ $string['formerror_nobgimage'] = 'You need to select an image to use as the back $string['infinite'] = 'Infinite'; $string['label'] = 'Label'; $string['nolabel'] = 'No label text'; +$string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, please drag an image to each drop region.'; $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = '
  • Select a background image file.
  • Select draggable images.
  • And define drop zones by selecting an image that the student must drag to the drop zone and drag it to where the student should drag it too.
'; diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 9e76dcf5068..42439880685 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -99,6 +99,12 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { $filearea, $args, $forcedownload); } } + public function get_validation_error(array $response) { + if ($this->is_complete_response($response)) { + return ''; + } + return get_string('pleasedraganimagetoeachdropregion', 'qtype_ddimagetoimage'); + } } diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 4b28e5e8731..8805b2d9ea5 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -119,6 +119,11 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $sendtojs, true, $jsmodule); + if ($qa->get_state() == question_state::$invalid) { + $output .= html_writer::nonempty_tag('div', + $question->get_validation_error($qa->get_last_qt_data()), + array('class' => 'validationerror')); + } return $output; } From 26295e67a954c5339eb0e4b9a81d64dd1aeca9eb Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 21 Aug 2011 16:13:31 +0700 Subject: [PATCH 064/208] MDL-47494 ddimageortext: NOBUG converted js from static code to modular code. As well as making code clearer this also made it so we use different instances of the same code for the several questions on the same page. --- question/type/ddimageortext/dd.js | 620 ------------------ .../edit_ddimagetoimage_form.php | 14 +- question/type/ddimageortext/renderer.php | 19 +- question/type/ddimageortext/yui/dd/dd.js | 213 ++++++ question/type/ddimageortext/yui/form/form.js | 306 +++++++++ .../ddimageortext/yui/question/question.js | 130 ++++ 6 files changed, 663 insertions(+), 639 deletions(-) delete mode 100644 question/type/ddimageortext/dd.js create mode 100644 question/type/ddimageortext/yui/dd/dd.js create mode 100644 question/type/ddimageortext/yui/form/form.js create mode 100644 question/type/ddimageortext/yui/question/question.js diff --git a/question/type/ddimageortext/dd.js b/question/type/ddimageortext/dd.js deleted file mode 100644 index 88a0dac7241..00000000000 --- a/question/type/ddimageortext/dd.js +++ /dev/null @@ -1,620 +0,0 @@ -M.qtype_ddimagetoimage={ - Y : null, - doc : null, - drops : null, - readonly : null, - /** - * Entry point when called from question renderer - */ - init_question : function(Y, drops, topnodestr, readonly) { - this.Y = Y; - this.drops = drops; - this.readonly = readonly; - this.doc = this.doc_structure(Y, Y.one(topnodestr), this, null); - this.poll_for_image_load(null, 1000, this.create_all_drag_and_drops); - this.doc.bg_img() - .after('load', this.poll_for_image_load, this, false, 1000, this.create_all_drag_and_drops); - this.doc.drag_image_homes() - .after('load', this.poll_for_image_load, this, false, 1000, this.create_all_drag_and_drops); - this.Y.on('windowresize', this.reposition_drags_for_question, this); - }, - polltimer : null, - poll_for_image_load : function (e, waitforimageconstrain, pause, doafterwords) { - var bgdone = this.doc.bg_img().get('complete'); - if (waitforimageconstrain) { - bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); - } - var alldragsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ - //in 'some' loop returning true breaks the loop and is passed as return value from - //'some' else returns false. Can be though of as equivalent to ||. - var done = (dragimagehome.get('complete')); - if (waitforimageconstrain) { - done = done && dragimagehome.hasClass('constrained'); - } - return !done; - }); - if (alldragsloaded && alldragsloaded) { - if (this.polltimer !== null) { - this.polltimer.cancel(); - this.polltimer = null; - } - this.doc.drag_image_homes().detach('load', this.poll_for_image_load); - this.doc.bg_img().detach('load', this.poll_for_image_load); - if (pause !== 0) { - this.Y.later(pause, this, doafterwords); - } else { - doafterwords.call(this); - } - } else if (this.polltimer === null) { - var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; - this.polltimer = - this.Y.later(500, this, this.poll_for_image_load, pollarguments, true); - } - }, - create_all_drag_and_drops : function () { - this.init_drops(); - this.update_padding_sizes_all(); - var i = 0; - this.doc.drag_image_homes().each(function(dragimagehome){ - var dragimageno = - +this.doc.get_classname_numeric_suffix(dragimagehome, 'dragimagehomes'); - var choice = +this.doc.get_classname_numeric_suffix(dragimagehome, 'choice'); - var group = +this.doc.get_classname_numeric_suffix(dragimagehome, 'group') - var groupsize = this.doc.drop_zone_group(group).size(); - var dragnode = this.doc.clone_new_drag_image(i, dragimageno); - i++; - if (!this.readonly) { - this.doc.draggable_for_question(dragnode, group, choice); - } - if (dragnode.hasClass('infinite')) { - var dragstocreate = groupsize - 1; - while (dragstocreate > 0) { - dragnode = this.doc.clone_new_drag_image(i, dragimageno); - i++; - if (!this.readonly) { - this.doc.draggable_for_question(dragnode, group, choice); - } - dragstocreate--; - } - } - }, this); - this.reposition_drags_for_question(); - }, - reposition_drags_for_question : function() { - this.doc.drag_images().removeClass('placed'); - this.doc.drag_images().each (function (dragimage) { - if (dragimage.dd !== undefined) { - dragimage.dd.detachAll('drag:start'); - } - }, this); - this.doc.drop_zones().each(function(dropzone) { - var relativexy = dropzone.getData('xy'); - dropzone.setXY(this.convert_to_window_xy(relativexy)); - var inputcss = 'input#' + dropzone.getData('inputid'); - var input = this.doc.top_node().one(inputcss); - var choice = input.get('value'); - if (choice !== "") { - var group = dropzone.getData('group'); - var dragimage = null; - var dragimages = this.doc.top_node() - .all('div.dragitemgroup'+group+' img.choice'+choice+'.drag'); - dragimages.some(function (d) { - if (!d.hasClass('placed')) { - dragimage = d; - return true; - } else { - return false; - } - }); - if (dragimage !== null) { - dragimage.setXY(dropzone.getXY()); - dragimage.addClass('placed'); - if (dragimage.dd !== undefined) { - dragimage.dd.once('drag:start', function (e, input) { - input.set('value', ''); - e.target.get('node').removeClass('placed'); - },this, input); - } - } - } - }, this); - this.doc.drag_images().each(function(dragimage) { - if (!dragimage.hasClass('placed')) { - var dragimagehome = this.doc.drag_image_home(dragimage.getData('dragimageno')); - dragimage.setXY(dragimagehome.getXY()); - } - }, this); - }, - init_drops : function () { - var dropareas = this.doc.top_node().one('div.dropzones'); - var groupnodes = {}; - for (var groupno =1; groupno <= 8; groupno++) { - var groupnode = this.Y.Node.create('
'); - dropareas.append(groupnode); - groupnodes[groupno] = groupnode; - } - for (var dropno in this.drops){ - var nodeclass = 'dropzone group'+this.drops[dropno].group+' place'+dropno; - var title = this.drops[dropno].text.replace('"', '\"'); - var dropnodehtml = '
 
'; - var dropnode = this.Y.Node.create(dropnodehtml); - groupnodes[this.drops[dropno].group].append(dropnode); - dropnode.setStyles({'opacity': 0.5}); - dropnode.setData('xy', this.drops[dropno].xy); - dropnode.setData('place', dropno); - dropnode.setData('inputid', this.drops[dropno].fieldname.replace(':', '_')); - dropnode.setData('group', this.drops[dropno].group); - var dropdd = new this.Y.DD.Drop({ - node: dropnode}); - dropdd.on('drop:hit', function(e) { - var drag = e.drag.get('node'); - var drop = e.drop.get('node'); - if (+drop.getData('group') === drag.getData('group')){ - var inputid = drop.getData('inputid'); - var inputnode = this.Y.one('input#'+inputid); - inputnode.set('value', drag.getData('choice')); - } - }, this); - }; - }, - /** - * Object to encapsulate operations on dd area. - */ - doc_structure : function (Y, topnode, mainobj, maxsizes) { - var dragimagesarea = topnode.one('div.dragitems'); - var dropbgarea = topnode.one('div.droparea'); - return { - top_node : function() { - return topnode; - }, - drag_images : function() { - return dragimagesarea.all('img.drag'); - }, - drop_zones : function() { - return topnode.all('div.dropzones div.dropzone'); - }, - drop_zone_group : function(groupno) { - return topnode.all('div.dropzones div.group' + groupno); - }, - drag_images_cloned_from : function(dragimageno) { - return dragimagesarea.all('img.dragimages'+dragimageno); - }, - drag_image : function(draginstanceno) { - return dragimagesarea.one('img.draginstance' + draginstanceno); - }, - drag_image_homes : function() { - return dragimagesarea.all('img.draghome'); - }, - bg_img : function() { - return topnode.one('img.dropbackground'); - }, - load_bg_img : function (url) { - dropbgarea.setContent(''); - this.bg_img().on('load', this.on_image_load, this, 'bg_image'); - }, - add_or_update_drag_image_home : function (dragimageno, url, alt, group) { - var oldhome = this.drag_image_home(dragimageno); - var classes = 'draghome dragimagehomes'+dragimageno+' group'+group; - var imghtml = ''+alt+''; - if (oldhome === null) { - if (url) { - dragimagesarea.append(imghtml); - } - } else { - if (url) { - dragimagesarea.insert(imghtml, oldhome); - } - oldhome.remove(true); - } - var newlycreated = dragimagesarea.one('img.dragimagehomes'+dragimageno); - if (newlycreated !== null) { - newlycreated.setData('groupno', group); - newlycreated.setData('dragimageno', dragimageno); - } - }, - drag_image_home : function (dragimageno) { - return dragimagesarea.one('img.dragimagehomes' + dragimageno); - }, - get_classname_numeric_suffix : function(node, prefix) { - var classes = node.getAttribute('class'); - if (classes !== '') { - var classesarr = classes.split(' '); - for (index in classesarr) { - var patt1 = new RegExp('^'+prefix+'([0-9])+$'); - if (patt1.test(classesarr[index])) { - var patt2 = new RegExp('([0-9])+$'); - var match = patt2.exec(classesarr[index]); - return +match[0]; - } - } - } - throw 'Prefix "'+prefix+'" not found in class names.'; - }, - clone_new_drag_image : function (draginstanceno, dragimageno) { - var draghome = this.drag_image_home(dragimageno); - if (draghome === null) { - return null; - } - var drag = draghome.cloneNode(true); - drag.removeClass('dragimagehomes' + dragimageno); - drag.addClass('dragimages' + dragimageno); - drag.addClass('draginstance' + draginstanceno); - drag.removeClass('draghome'); - drag.addClass('drag'); - drag.setStyles({'visibility': 'visible', 'position' : 'absolute'}); - drag.setData('draginstanceno', draginstanceno); - drag.setData('dragimageno', dragimageno); - draghome.get('parentNode').appendChild(drag); - return drag; - }, - draggable_for_question : function (drag, group, choice) { - var dd = new Y.DD.Drag({ - node: drag, - dragMode: 'intersect' - }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); - - dd.on('drag:end', function(e) { - mainobj.reposition_drags_for_question(); - }, this); - drag.setData('group', group); - drag.setData('choice', choice); - - }, - draggable_for_form : function (drag) { - var dd = new Y.DD.Drag({ - node: drag, - dragMode: 'intersect' - }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); - dd.on('drag:end', function(e) { - var dragnode = e.target.get('node'); - var draginstanceno = dragnode.getData('draginstanceno'); - var gooddrop = dragnode.getData('gooddrop'); - var endxy; - - if (!gooddrop) { - mainobj.reset_drag_xy(draginstanceno); - } else { - endxy = [Math.round(e.pageX), Math.round(e.pageY)]; - mainobj.set_drag_xy(draginstanceno, endxy); - } - }, this); - dd.on('drag:start', function(e) { - var drag = e.target; - drag.get('node').setData('gooddrop', false); - }, this); - - } - - } - }, - - update_padding_sizes_all : function () { - for (var groupno = 1; groupno <= 8; groupno++) { - this.update_padding_size_for_group(groupno); - } - }, - update_padding_size_for_group : function (groupno) { - var groupimages = this.doc.top_node().all('img.draghome.group'+groupno); - if (groupimages.size() !== 0) { - var maxwidth = 0; - var maxheight = 0; - groupimages.each(function(image){ - maxwidth = Math.max(maxwidth, image.get('width')); - maxheight = Math.max(maxheight, image.get('height')); - }, this); - groupimages.each(function(image) { - var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); - var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); - image.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' - +margintopbottom+'px '+marginleftright+'px'); - }, this); - this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, - 'height': maxheight + 10}); - } - }, - convert_to_window_xy : function (bgimgxy) { - return [+bgimgxy[0] + this.doc.bg_img().getX() + 1, - +bgimgxy[1] + this.doc.bg_img().getY() + 1]; - }, - - //---------- stuff below this line only used in question editing form --------------- - - fp : null, - maxsizes : null, - /** - * Entry point when called from question editing form - */ - init_form : function(Y, maxsizes) { - this.Y = Y; - this.fp = this.file_pickers(); - topnode = Y.one('fieldset#previewareaheader'); - topnode.append('
'+ - '
'+ - '
'); - this.doc = this.doc_structure(Y, topnode, this); - this.maxsizes = maxsizes; - this.draw_dd_area(); - }, - - draw_dd_area : function() { - var bgimageurl = this.fp.file('bgimage').href; - this.stop_selector_events(); - this.set_options_for_drag_image_selectors(); - if (bgimageurl !== null) { - this.doc.load_bg_img(bgimageurl); - this.load_drag_homes(); - - var drop = new this.Y.DD.Drop({ - node: this.doc.bg_img() - }); - //Listen for a drop:hit on the background image - drop.on('drop:hit', function(e) { - e.drag.get('node').setData('gooddrop', true); - }); - - this.Y.on('windowresize', this.reposition_drags_for_form, this); - - this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage') - this.doc.drag_image_homes().on('load', this.constrain_image_size, this, 'dragimage'); - this.doc.bg_img() - .after('load', this.poll_for_image_load, this, true, 1000, this.after_all_images_loaded); - this.doc.drag_image_homes() - .after('load', this.poll_for_image_load, this, true, 1000, this.after_all_images_loaded); - } else { - this.setup_form_events(); - } - }, - - after_all_images_loaded : function () { - this.update_padding_sizes_all(); - this.update_drag_instances(); - this.reposition_drags_for_form(); - this.set_options_for_drag_image_selectors(); - this.setup_form_events(); - }, - - constrain_image_size : function (e, imagetype) { - var maxsize = this.maxsizes[imagetype]; - var reduceby = Math.max(e.target.get('width') / maxsize.width, - e.target.get('height') / maxsize.height); - if (reduceby > 1) { - e.target.set('width', Math.floor(e.target.get('width') / reduceby)); - } - e.target.addClass('constrained'); - e.target.detach('load', this.constrain_image_size); - }, - - load_drag_homes : function () { - //set up drag items homes - var dragimagesoptions = {0: ''}; - for (var i=0; i < this.form.get_form_value('noimages', []); i++) { - this.load_drag_home(i); - } - }, - - load_drag_home : function (dragimageno) { - var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).href; - this.doc.add_or_update_drag_image_home(dragimageno, url, - this.form.get_form_value('drags', [dragimageno, 'draglabel']), - this.form.get_form_value('drags', [dragimageno, 'draggroup'])); - }, - - update_drag_instances : function () { - //set up drop zones - for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { - var dragimageno = this.form.get_form_value('drops', [i, 'choice']); - if (dragimageno !== '0' && (this.doc.drag_image(i) === null)) { - var drag = this.doc.clone_new_drag_image(i, dragimageno - 1); - if (drag !== null) { - this.doc.draggable_for_form(drag); - } - } - } - }, - set_options_for_drag_image_selectors : function () { - var dragimagesoptions = {0: ''}; - for (var i=0; i < this.form.get_form_value('noimages', []); i++) { - var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); - if (file.name !== null) { - dragimagesoptions[i+1] = (i+1)+'. '+file.name; - } - } - for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { - var selector = this.Y.one('#id_drops_'+i+'_choice'); - var selectedvalue = selector.get('value'); - selector.all('option').remove(true); - for (var value in dragimagesoptions) { - value = +value; - var option = ''; - selector.append(option); - var optionnode = selector.one('option[value="' + value + '"]') - if (value === +selectedvalue) { - optionnode.set('selected', true); - } else { - if (value !== 0) { // no image option is always selectable - var cbselector = 'fieldset#draggableimageheader_'+(value-1) - +' input[type="checkbox"]'; - var cbel = this.Y.one(cbselector); - var infinite = cbel.get('checked'); - if ((!infinite) && - (this.doc.drag_images_cloned_from(value - 1).size() !== 0)) { - optionnode.set('disabled', true); - } - } - } - } - } - }, - - stop_selector_events : function () { - this.Y.all('fieldset#dropzoneheader select').detachAll(); - }, - - setup_form_events : function () { - //events triggered by changes to form data - - //x and y coordinates - this.Y.all('fieldset#dropzoneheader input').on('blur', function (e){ - var name = e.target.getAttribute('name'); - var draginstanceno = this.form.from_name_with_index(name).indexes[0]; - this.reposition_drag_for_form(draginstanceno); - }, this); - - //change in selected image - this.Y.all('fieldset#dropzoneheader select').on('change', function (e){ - var name = e.target.getAttribute('name'); - var draginstanceno = this.form.from_name_with_index(name).indexes[0]; - var old = this.doc.drag_image(draginstanceno); - if (old !== null) { - old.remove(true); - } - this.draw_dd_area(); - }, this); - - for (var i=0; i < this.form.get_form_value('noimages', []); i++) { - //change to group selector - this.Y.all('fieldset#draggableimageheader_'+i+' select').on('change', function (e){ - this.doc.drag_images().remove(true); - this.draw_dd_area(); - }, this); - //change to infinite checkbox - this.Y.all('fieldset#draggableimageheader_'+i+' input[type="checkbox"]') - .on('change', this.set_options_for_drag_image_selectors, this); - } - //event on file picker new file selection - this.Y.after(function (e){ - var name = this.fp.name(e.id); - if (name !== 'bgimage') { - this.doc.drag_images().remove(true); - } - this.draw_dd_area(); - }, M.form_filepicker, 'callback', this); - }, - - - reposition_drags_for_form : function() { - this.doc.drag_images().each(function (drag) { - var draginstanceno = drag.getData('draginstanceno'); - this.reposition_drag_for_form(draginstanceno); - }, this); - }, - - reposition_drag_for_form : function (draginstanceno) { - var drag = this.doc.drag_image(draginstanceno); - if (null !== drag) { - var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), - this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; - if (fromform[0] == '' && fromform[1] == '') { - var dragimageno = drag.getData('dragimageno'); - drag.setXY(this.doc.drag_image_home(dragimageno).getXY()); - } else { - var constrainedxy = this.constrain_xy(draginstanceno, fromform); - drag.setXY(this.convert_to_window_xy(constrainedxy)); - if (constrainedxy[0] !== +fromform[0] || constrainedxy[1] !== +fromform[1]){ - this.form.set_form_value('drops', [draginstanceno, 'xleft'], constrainedxy[0]); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); - } - } - } - }, - set_drag_xy : function (draginstanceno, xy) { - xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); - this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.floor(xy[0])); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.floor(xy[1])); - this.reposition_drag_for_form(draginstanceno); - }, - reset_drag_xy : function (draginstanceno) { - this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); - this.reposition_drag_for_form(draginstanceno); - }, - - //make sure xy value is not out of bounds of bg image - constrain_xy : function (draginstanceno, bgimgxy) { - var drag = this.doc.drag_image(draginstanceno); - var xleftconstrained = - Math.min(bgimgxy[0], this.doc.bg_img().get('width') - drag.get('offsetWidth')); - var ytopconstrained = - Math.min(bgimgxy[1], this.doc.bg_img().get('height') - drag.get('offsetHeight')); - xleftconstrained = Math.max(xleftconstrained, 0); - ytopconstrained = Math.max(ytopconstrained, 0); - return [xleftconstrained, ytopconstrained]; - }, - convert_to_bg_img_xy : function (windowxy) { - return [windowxy[0] - this.doc.bg_img().getX(), - windowxy[1] - this.doc.bg_img().getY()]; - }, - - /** - * Low level operations on form. - */ - form : { - to_name_with_index : function(name, indexes) { - var indexstring = name; - for (var i=0; i < indexes.length; i++) { - indexstring = indexstring + '[' + indexes[i] + ']'; - } - return indexstring; - }, - get_form_value : function(name, indexes) { - var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; - if (el.type === 'checkbox') { - return el.checked; - } else { - return el.value; - } - }, - set_form_value : function(name, indexes, value) { - var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; - if (el.type === 'checkbox') { - el.checked = value; - } else { - el.value = value; - } - }, - from_name_with_index : function(name) { - var toreturn = {}; - toreturn.indexes = []; - var bracket = name.indexOf('['); - toreturn.name = name.substring(0, bracket); - while (bracket !== -1) { - var end = name.indexOf(']', bracket + 1); - toreturn.indexes.push(name.substring(bracket + 1, end)); - bracket = name.indexOf('[', end + 1); - } - return toreturn; - } - }, - - file_pickers : function () { - var draftitemidstoname; - var nametoparentnode; - if (draftitemidstoname === undefined) { - draftitemidstoname = {}; - nametoparentnode = {}; - var filepickers = this.Y.all('form.mform input.filepickerhidden'); - filepickers.each(function(filepicker, k, items) { - draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); - nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); - }, this); - } - var toreturn = { - file : function (name) { - var parentnode = nametoparentnode[name]; - var fileanchor = parentnode.one('div.filepicker-filelist a'); - if (fileanchor) { - return {href : fileanchor.get('href'), name : fileanchor.get('innerHTML')}; - } else { - return {href : null, name : null}; - } - }, - name : function (draftitemid) { - return draftitemidstoname[draftitemid]; - } - } - return toreturn; - } - -} \ No newline at end of file diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index f5864a2a864..d47bff8ed0f 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -260,12 +260,6 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $question->dragitem[$imageindex] = $draftitemid; } - $jsmodule = array( - 'name' => 'qtype_ddimagetoimage', - 'fullpath' => '/question/type/ddimagetoimage/dd.js', - //we can make sure that file picker is loaded first by including it here - 'requires' => array('node', 'dd', 'dd-drop', 'dd-constrain', 'form_filepicker') - ); $maxsizes =new stdClass(); $maxsizes->bgimage = new stdClass(); $maxsizes->bgimage->width = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH; @@ -274,8 +268,12 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $maxsizes->dragimage->width = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH; $maxsizes->dragimage->height = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT; - $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_form', array($maxsizes), - true, $jsmodule); + $params = array('maxsizes' => $maxsizes, + 'topnode' => 'fieldset#previewareaheader'); + + $PAGE->requires->yui_module('moodle-qtype_ddimagetoimage-form', + 'M.qtype_ddimagetoimage.init_form', + array($params)); return $question; } diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 8805b2d9ea5..b949238551d 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -106,19 +106,16 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $output .= $html; $question->places[$placeno]->fieldname = $fieldname; } - $jsmodule = array( - 'name' => 'qtype_ddimagetoimage', - 'fullpath' => '/question/type/ddimagetoimage/dd.js', - 'requires' => array('node', 'dd', 'dd-drop', 'dd-constrain') - ); - $topnode = 'div#q'.$qa->get_slot().' div.ddarea'; - $sendtojs = array($question->places, $topnode, $options->readonly); + $params = array('drops' => $question->places, + 'topnode' => $topnode, + 'readonly' => $options->readonly); + + $PAGE->requires->yui_module('moodle-qtype_ddimagetoimage-question', + 'M.qtype_ddimagetoimage.init_question', + array($params)); + - $PAGE->requires->js_init_call('M.qtype_ddimagetoimage.init_question', - $sendtojs, - true, - $jsmodule); if ($qa->get_state() == question_state::$invalid) { $output .= html_writer::nonempty_tag('div', $question->get_validation_error($qa->get_last_qt_data()), diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js new file mode 100644 index 00000000000..86b78064a7c --- /dev/null +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -0,0 +1,213 @@ +YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { + var DDIMAGETOIMAGEDDNAME = 'ddimagetoimage_dd'; + var DDIMAGETOIMAGE_DD = function() { + DDIMAGETOIMAGE_DD.superclass.constructor.apply(this, arguments); + } + Y.extend(DDIMAGETOIMAGE_DD, Y.Base, { + doc : null, + polltimer : null, + poll_for_image_load : function (e, waitforimageconstrain, pause, doafterwords) { + var bgdone = this.doc.bg_img().get('complete'); + if (waitforimageconstrain) { + bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); + } + var alldragsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ + //in 'some' loop returning true breaks the loop and is passed as return value from + //'some' else returns false. Can be though of as equivalent to ||. + var done = (dragimagehome.get('complete')); + if (waitforimageconstrain) { + done = done && dragimagehome.hasClass('constrained'); + } + return !done; + }); + if (alldragsloaded && alldragsloaded) { + if (this.polltimer !== null) { + this.polltimer.cancel(); + this.polltimer = null; + } + this.doc.drag_image_homes().detach('load', this.poll_for_image_load); + this.doc.bg_img().detach('load', this.poll_for_image_load); + if (pause !== 0) { + Y.later(pause, this, doafterwords); + } else { + doafterwords.call(this); + } + } else if (this.polltimer === null) { + var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; + this.polltimer = + Y.later(500, this, this.poll_for_image_load, pollarguments, true); + } + }, + /** + * Object to encapsulate operations on dd area. + */ + doc_structure : function (mainobj) { + var topnode = Y.one(this.get('topnode')); + var dragimagesarea = topnode.one('div.dragitems'); + var dropbgarea = topnode.one('div.droparea'); + return { + top_node : function() { + return topnode; + }, + drag_images : function() { + return dragimagesarea.all('img.drag'); + }, + drop_zones : function() { + return topnode.all('div.dropzones div.dropzone'); + }, + drop_zone_group : function(groupno) { + return topnode.all('div.dropzones div.group' + groupno); + }, + drag_images_cloned_from : function(dragimageno) { + return dragimagesarea.all('img.dragimages'+dragimageno); + }, + drag_image : function(draginstanceno) { + return dragimagesarea.one('img.draginstance' + draginstanceno); + }, + drag_image_homes : function() { + return dragimagesarea.all('img.draghome'); + }, + bg_img : function() { + return topnode.one('img.dropbackground'); + }, + load_bg_img : function (url) { + dropbgarea.setContent(''); + this.bg_img().on('load', this.on_image_load, this, 'bg_image'); + }, + add_or_update_drag_image_home : function (dragimageno, url, alt, group) { + var oldhome = this.drag_image_home(dragimageno); + var classes = 'draghome dragimagehomes'+dragimageno+' group'+group; + var imghtml = ''+alt+''; + if (oldhome === null) { + if (url) { + dragimagesarea.append(imghtml); + } + } else { + if (url) { + dragimagesarea.insert(imghtml, oldhome); + } + oldhome.remove(true); + } + var newlycreated = dragimagesarea.one('img.dragimagehomes'+dragimageno); + if (newlycreated !== null) { + newlycreated.setData('groupno', group); + newlycreated.setData('dragimageno', dragimageno); + } + }, + drag_image_home : function (dragimageno) { + return dragimagesarea.one('img.dragimagehomes' + dragimageno); + }, + get_classname_numeric_suffix : function(node, prefix) { + var classes = node.getAttribute('class'); + if (classes !== '') { + var classesarr = classes.split(' '); + for (index in classesarr) { + var patt1 = new RegExp('^'+prefix+'([0-9])+$'); + if (patt1.test(classesarr[index])) { + var patt2 = new RegExp('([0-9])+$'); + var match = patt2.exec(classesarr[index]); + return +match[0]; + } + } + } + throw 'Prefix "'+prefix+'" not found in class names.'; + }, + clone_new_drag_image : function (draginstanceno, dragimageno) { + var draghome = this.drag_image_home(dragimageno); + if (draghome === null) { + return null; + } + var drag = draghome.cloneNode(true); + drag.removeClass('dragimagehomes' + dragimageno); + drag.addClass('dragimages' + dragimageno); + drag.addClass('draginstance' + draginstanceno); + drag.removeClass('draghome'); + drag.addClass('drag'); + drag.setStyles({'visibility': 'visible', 'position' : 'absolute'}); + drag.setData('draginstanceno', draginstanceno); + drag.setData('dragimageno', dragimageno); + draghome.get('parentNode').appendChild(drag); + return drag; + }, + draggable_for_question : function (drag, group, choice) { + var dd = new Y.DD.Drag({ + node: drag, + dragMode: 'intersect' + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + + dd.on('drag:end', function(e) { + mainobj.reposition_drags_for_question(); + }, this); + drag.setData('group', group); + drag.setData('choice', choice); + + }, + draggable_for_form : function (drag) { + var dd = new Y.DD.Drag({ + node: drag, + dragMode: 'intersect' + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + dd.on('drag:end', function(e) { + var dragnode = e.target.get('node'); + var draginstanceno = dragnode.getData('draginstanceno'); + var gooddrop = dragnode.getData('gooddrop'); + var endxy; + + if (!gooddrop) { + mainobj.reset_drag_xy(draginstanceno); + } else { + endxy = [Math.round(e.pageX), Math.round(e.pageY)]; + mainobj.set_drag_xy(draginstanceno, endxy); + } + }, this); + dd.on('drag:start', function(e) { + var drag = e.target; + drag.get('node').setData('gooddrop', false); + }, this); + + } + + } + }, + + update_padding_sizes_all : function () { + for (var groupno = 1; groupno <= 8; groupno++) { + this.update_padding_size_for_group(groupno); + } + }, + update_padding_size_for_group : function (groupno) { + var groupimages = this.doc.top_node().all('img.draghome.group'+groupno); + if (groupimages.size() !== 0) { + var maxwidth = 0; + var maxheight = 0; + groupimages.each(function(image){ + maxwidth = Math.max(maxwidth, image.get('width')); + maxheight = Math.max(maxheight, image.get('height')); + }, this); + groupimages.each(function(image) { + var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); + var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); + image.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' + +margintopbottom+'px '+marginleftright+'px'); + }, this); + this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, + 'height': maxheight + 10}); + } + }, + convert_to_window_xy : function (bgimgxy) { + return [+bgimgxy[0] + this.doc.bg_img().getX() + 1, + +bgimgxy[1] + this.doc.bg_img().getY() + 1]; + } + }, { + NAME : DDIMAGETOIMAGEDDNAME, + ATTRS : { + drops : {value : null}, + readonly : {value : false}, + topnode : {value : null} + } + }); + M.qtype_ddimagetoimage = M.qtype_ddimagetoimage || {}; + M.qtype_ddimagetoimage.dd_base_class = DDIMAGETOIMAGE_DD; + }, '@VERSION@', { + requires:['node', 'dd', 'dd-drop', 'dd-constrain'] + }); diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js new file mode 100644 index 00000000000..8d7d4064cdb --- /dev/null +++ b/question/type/ddimageortext/yui/form/form.js @@ -0,0 +1,306 @@ +YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { + var DDIMAGETOIMAGEFORMNAME = 'ddimagetoimage_form'; + var DDIMAGETOIMAGE_FORM = function() { + DDIMAGETOIMAGE_FORM.superclass.constructor.apply(this, arguments); + }; + Y.extend(DDIMAGETOIMAGE_FORM, M.qtype_ddimagetoimage.dd_base_class, { + fp : null, + + initializer : function(params) { + this.fp = this.file_pickers(); + Y.one(this.get('topnode')).append('
'+ + '
'+ + '
'); + this.doc = this.doc_structure(this); + this.draw_dd_area(); + }, + + draw_dd_area : function() { + var bgimageurl = this.fp.file('bgimage').href; + this.stop_selector_events(); + this.set_options_for_drag_image_selectors(); + if (bgimageurl !== null) { + this.doc.load_bg_img(bgimageurl); + this.load_drag_homes(); + + var drop = new Y.DD.Drop({ + node: this.doc.bg_img() + }); + //Listen for a drop:hit on the background image + drop.on('drop:hit', function(e) { + e.drag.get('node').setData('gooddrop', true); + }); + + Y.on('windowresize', this.reposition_drags_for_form, this); + + this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); + this.doc.drag_image_homes() + .on('load', this.constrain_image_size, this, 'dragimage'); + this.doc.bg_img().after('load', this.poll_for_image_load, this, + true, 1000, this.after_all_images_loaded); + this.doc.drag_image_homes() .after('load', this.poll_for_image_load, this, + true, 1000, this.after_all_images_loaded); + } else { + this.setup_form_events(); + } + }, + + after_all_images_loaded : function () { + this.update_padding_sizes_all(); + this.update_drag_instances(); + this.reposition_drags_for_form(); + this.set_options_for_drag_image_selectors(); + this.setup_form_events(); + }, + + constrain_image_size : function (e, imagetype) { + var maxsize = this.get('maxsizes')[imagetype]; + var reduceby = Math.max(e.target.get('width') / maxsize.width, + e.target.get('height') / maxsize.height); + if (reduceby > 1) { + e.target.set('width', Math.floor(e.target.get('width') / reduceby)); + } + e.target.addClass('constrained'); + e.target.detach('load', this.constrain_image_size); + }, + + load_drag_homes : function () { + //set up drag items homes + var dragimagesoptions = {0: ''}; + for (var i=0; i < this.form.get_form_value('noimages', []); i++) { + this.load_drag_home(i); + } + }, + + load_drag_home : function (dragimageno) { + var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).href; + this.doc.add_or_update_drag_image_home(dragimageno, url, + this.form.get_form_value('drags', [dragimageno, 'draglabel']), + this.form.get_form_value('drags', [dragimageno, 'draggroup'])); + }, + + update_drag_instances : function () { + //set up drop zones + for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { + var dragimageno = this.form.get_form_value('drops', [i, 'choice']); + if (dragimageno !== '0' && (this.doc.drag_image(i) === null)) { + var drag = this.doc.clone_new_drag_image(i, dragimageno - 1); + if (drag !== null) { + this.doc.draggable_for_form(drag); + } + } + } + }, + set_options_for_drag_image_selectors : function () { + var dragimagesoptions = {0: ''}; + for (var i=0; i < this.form.get_form_value('noimages', []); i++) { + var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); + if (file.name !== null) { + dragimagesoptions[i+1] = (i+1)+'. '+file.name; + } + } + for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { + var selector = Y.one('#id_drops_'+i+'_choice'); + var selectedvalue = selector.get('value'); + selector.all('option').remove(true); + for (var value in dragimagesoptions) { + value = +value; + var option = ''; + selector.append(option); + var optionnode = selector.one('option[value="' + value + '"]') + if (value === +selectedvalue) { + optionnode.set('selected', true); + } else { + if (value !== 0) { // no image option is always selectable + var cbselector = 'fieldset#draggableimageheader_'+(value-1) + +' input[type="checkbox"]'; + var cbel = Y.one(cbselector); + var infinite = cbel.get('checked'); + if ((!infinite) && + (this.doc.drag_images_cloned_from(value - 1).size() !== 0)) { + optionnode.set('disabled', true); + } + } + } + } + } + }, + + stop_selector_events : function () { + Y.all('fieldset#dropzoneheader select').detachAll(); + }, + + setup_form_events : function () { + //events triggered by changes to form data + + //x and y coordinates + Y.all('fieldset#dropzoneheader input').on('blur', function (e){ + var name = e.target.getAttribute('name'); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + this.reposition_drag_for_form(draginstanceno); + }, this); + + //change in selected image + Y.all('fieldset#dropzoneheader select').on('change', function (e){ + var name = e.target.getAttribute('name'); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + var old = this.doc.drag_image(draginstanceno); + if (old !== null) { + old.remove(true); + } + this.draw_dd_area(); + }, this); + + for (var i=0; i < this.form.get_form_value('noimages', []); i++) { + //change to group selector + Y.all('fieldset#draggableimageheader_'+i+' select').on('change', function (e){ + this.doc.drag_images().remove(true); + this.draw_dd_area(); + }, this); + //change to infinite checkbox + Y.all('fieldset#draggableimageheader_'+i+' input[type="checkbox"]') + .on('change', this.set_options_for_drag_image_selectors, this); + } + //event on file picker new file selection + Y.after(function (e){ + var name = this.fp.name(e.id); + if (name !== 'bgimage') { + this.doc.drag_images().remove(true); + } + this.draw_dd_area(); + }, M.form_filepicker, 'callback', this); + }, + + + reposition_drags_for_form : function() { + this.doc.drag_images().each(function (drag) { + var draginstanceno = drag.getData('draginstanceno'); + this.reposition_drag_for_form(draginstanceno); + }, this); + }, + + reposition_drag_for_form : function (draginstanceno) { + var drag = this.doc.drag_image(draginstanceno); + if (null !== drag) { + var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), + this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; + if (fromform[0] == '' && fromform[1] == '') { + var dragimageno = drag.getData('dragimageno'); + drag.setXY(this.doc.drag_image_home(dragimageno).getXY()); + } else { + var constrainedxy = this.constrain_xy(draginstanceno, fromform); + drag.setXY(this.convert_to_window_xy(constrainedxy)); + if (constrainedxy[0] !== +fromform[0] || constrainedxy[1] !== +fromform[1]){ + this.form.set_form_value('drops', [draginstanceno, 'xleft'], constrainedxy[0]); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); + } + } + } + }, + set_drag_xy : function (draginstanceno, xy) { + xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.floor(xy[0])); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.floor(xy[1])); + this.reposition_drag_for_form(draginstanceno); + }, + reset_drag_xy : function (draginstanceno) { + this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); + this.reposition_drag_for_form(draginstanceno); + }, + + //make sure xy value is not out of bounds of bg image + constrain_xy : function (draginstanceno, bgimgxy) { + var drag = this.doc.drag_image(draginstanceno); + var xleftconstrained = + Math.min(bgimgxy[0], this.doc.bg_img().get('width') - drag.get('offsetWidth')); + var ytopconstrained = + Math.min(bgimgxy[1], this.doc.bg_img().get('height') - drag.get('offsetHeight')); + xleftconstrained = Math.max(xleftconstrained, 0); + ytopconstrained = Math.max(ytopconstrained, 0); + return [xleftconstrained, ytopconstrained]; + }, + convert_to_bg_img_xy : function (windowxy) { + return [windowxy[0] - this.doc.bg_img().getX(), + windowxy[1] - this.doc.bg_img().getY()]; + }, + + /** + * Low level operations on form. + */ + form : { + to_name_with_index : function(name, indexes) { + var indexstring = name; + for (var i=0; i < indexes.length; i++) { + indexstring = indexstring + '[' + indexes[i] + ']'; + } + return indexstring; + }, + get_form_value : function(name, indexes) { + var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; + if (el.type === 'checkbox') { + return el.checked; + } else { + return el.value; + } + }, + set_form_value : function(name, indexes, value) { + var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; + if (el.type === 'checkbox') { + el.checked = value; + } else { + el.value = value; + } + }, + from_name_with_index : function(name) { + var toreturn = {}; + toreturn.indexes = []; + var bracket = name.indexOf('['); + toreturn.name = name.substring(0, bracket); + while (bracket !== -1) { + var end = name.indexOf(']', bracket + 1); + toreturn.indexes.push(name.substring(bracket + 1, end)); + bracket = name.indexOf('[', end + 1); + } + return toreturn; + } + }, + + file_pickers : function () { + var draftitemidstoname; + var nametoparentnode; + if (draftitemidstoname === undefined) { + draftitemidstoname = {}; + nametoparentnode = {}; + var filepickers = Y.all('form.mform input.filepickerhidden'); + filepickers.each(function(filepicker, k, items) { + draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); + nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); + }, this); + } + var toreturn = { + file : function (name) { + var parentnode = nametoparentnode[name]; + var fileanchor = parentnode.one('div.filepicker-filelist a'); + if (fileanchor) { + return {href : fileanchor.get('href'), name : fileanchor.get('innerHTML')}; + } else { + return {href : null, name : null}; + } + }, + name : function (draftitemid) { + return draftitemidstoname[draftitemid]; + } + } + return toreturn; + } + }, {NAME : DDIMAGETOIMAGEFORMNAME, ATTRS : {maxsizes:{value:null}}}); + M.qtype_ddimagetoimage = M.qtype_ddimagetoimage || {}; + M.qtype_ddimagetoimage.init_form = function(config) { + return new DDIMAGETOIMAGE_FORM(config); + } +}, '@VERSION@', { + requires:['moodle-qtype_ddimagetoimage-dd', 'form_filepicker'] +}); \ No newline at end of file diff --git a/question/type/ddimageortext/yui/question/question.js b/question/type/ddimageortext/yui/question/question.js new file mode 100644 index 00000000000..aad3287a04f --- /dev/null +++ b/question/type/ddimageortext/yui/question/question.js @@ -0,0 +1,130 @@ +YUI.add('moodle-qtype_ddimagetoimage-question', function(Y) { + var DDIMAGETOIMAGEQUESTIONNAME = 'ddimagetoimage_question'; + var DDIMAGETOIMAGE_QUESTION = function() { + DDIMAGETOIMAGE_QUESTION.superclass.constructor.apply(this, arguments); + }; + Y.extend(DDIMAGETOIMAGE_QUESTION, M.qtype_ddimagetoimage.dd_base_class, { + initializer : function(params) { + this.doc = this.doc_structure(this); + this.poll_for_image_load(null, 1000, this.create_all_drag_and_drops); + this.doc.bg_img().after('load', this.poll_for_image_load, this, + false, 1000, this.create_all_drag_and_drops); + this.doc.drag_image_homes().after('load', this.poll_for_image_load, this, + false, 1000, this.create_all_drag_and_drops); + Y.on('windowresize', this.reposition_drags_for_question, this); + }, + create_all_drag_and_drops : function () { + this.init_drops(); + this.update_padding_sizes_all(); + var i = 0; + this.doc.drag_image_homes().each(function(dragimagehome){ + var dragimageno = + +this.doc.get_classname_numeric_suffix(dragimagehome, 'dragimagehomes'); + var choice = +this.doc.get_classname_numeric_suffix(dragimagehome, 'choice'); + var group = +this.doc.get_classname_numeric_suffix(dragimagehome, 'group') + var groupsize = this.doc.drop_zone_group(group).size(); + var dragnode = this.doc.clone_new_drag_image(i, dragimageno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + if (dragnode.hasClass('infinite')) { + var dragstocreate = groupsize - 1; + while (dragstocreate > 0) { + dragnode = this.doc.clone_new_drag_image(i, dragimageno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + dragstocreate--; + } + } + }, this); + this.reposition_drags_for_question(); + }, + reposition_drags_for_question : function() { + this.doc.drag_images().removeClass('placed'); + this.doc.drag_images().each (function (dragimage) { + if (dragimage.dd !== undefined) { + dragimage.dd.detachAll('drag:start'); + } + }, this); + this.doc.drop_zones().each(function(dropzone) { + var relativexy = dropzone.getData('xy'); + dropzone.setXY(this.convert_to_window_xy(relativexy)); + var inputcss = 'input#' + dropzone.getData('inputid'); + var input = this.doc.top_node().one(inputcss); + var choice = input.get('value'); + if (choice !== "") { + var group = dropzone.getData('group'); + var dragimage = null; + var dragimages = this.doc.top_node() + .all('div.dragitemgroup'+group+' img.choice'+choice+'.drag'); + dragimages.some(function (d) { + if (!d.hasClass('placed')) { + dragimage = d; + return true; + } else { + return false; + } + }); + if (dragimage !== null) { + dragimage.setXY(dropzone.getXY()); + dragimage.addClass('placed'); + if (dragimage.dd !== undefined) { + dragimage.dd.once('drag:start', function (e, input) { + input.set('value', ''); + e.target.get('node').removeClass('placed'); + },this, input); + } + } + } + }, this); + this.doc.drag_images().each(function(dragimage) { + if (!dragimage.hasClass('placed')) { + var dragimagehome = this.doc.drag_image_home(dragimage.getData('dragimageno')); + dragimage.setXY(dragimagehome.getXY()); + } + }, this); + }, + init_drops : function () { + var dropareas = this.doc.top_node().one('div.dropzones'); + var groupnodes = {}; + for (var groupno =1; groupno <= 8; groupno++) { + var groupnode = Y.Node.create('
'); + dropareas.append(groupnode); + groupnodes[groupno] = groupnode; + } + for (var dropno in this.get('drops')){ + var drop = this.get('drops')[dropno]; + var nodeclass = 'dropzone group'+drop.group+' place'+dropno; + var title = drop.text.replace('"', '\"'); + var dropnodehtml = '
 
'; + var dropnode = Y.Node.create(dropnodehtml); + groupnodes[drop.group].append(dropnode); + dropnode.setStyles({'opacity': 0.5}); + dropnode.setData('xy', drop.xy); + dropnode.setData('place', dropno); + dropnode.setData('inputid', drop.fieldname.replace(':', '_')); + dropnode.setData('group', drop.group); + var dropdd = new Y.DD.Drop({ + node: dropnode}); + dropdd.on('drop:hit', function(e) { + var drag = e.drag.get('node'); + var drop = e.drop.get('node'); + if (+drop.getData('group') === drag.getData('group')){ + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#'+inputid); + inputnode.set('value', drag.getData('choice')); + } + }, this); + }; + } + }, {NAME : DDIMAGETOIMAGEQUESTIONNAME, ATTRS : {}}); + M.qtype_ddimagetoimage = M.qtype_ddimagetoimage || {}; + M.qtype_ddimagetoimage.init_question = function(config) { + return new DDIMAGETOIMAGE_QUESTION(config); + } +}, '@VERSION@', { + requires:['moodle-qtype_ddimagetoimage-dd'] +}); \ No newline at end of file From 59a4937f0ad2612643de7cee63410844fefab83b Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 21 Aug 2011 16:18:17 +0700 Subject: [PATCH 065/208] MDL-47494 ddimageortext: NOBUG fixed typo that was causing intermittent problems with poll_image_loading. --- question/type/ddimageortext/yui/question/question.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/yui/question/question.js b/question/type/ddimageortext/yui/question/question.js index aad3287a04f..84460732b3e 100644 --- a/question/type/ddimageortext/yui/question/question.js +++ b/question/type/ddimageortext/yui/question/question.js @@ -6,7 +6,7 @@ YUI.add('moodle-qtype_ddimagetoimage-question', function(Y) { Y.extend(DDIMAGETOIMAGE_QUESTION, M.qtype_ddimagetoimage.dd_base_class, { initializer : function(params) { this.doc = this.doc_structure(this); - this.poll_for_image_load(null, 1000, this.create_all_drag_and_drops); + this.poll_for_image_load(null, false, 1000, this.create_all_drag_and_drops); this.doc.bg_img().after('load', this.poll_for_image_load, this, false, 1000, this.create_all_drag_and_drops); this.doc.drag_image_homes().after('load', this.poll_for_image_load, this, From da102a7fe4ebf71f2530fe10dc25bc01f44cdc1b Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 21 Aug 2011 17:16:13 +0700 Subject: [PATCH 066/208] MDL-47494 ddimageortext: NOBUG moved student attempt code into same module as base class in order to reduce the ammount of files that must be loaded. Teacher editing form code is still separate. --- question/type/ddimageortext/renderer.php | 2 +- question/type/ddimageortext/yui/dd/dd.js | 131 +++++++++++++++++- .../ddimageortext/yui/question/question.js | 130 ----------------- 3 files changed, 130 insertions(+), 133 deletions(-) delete mode 100644 question/type/ddimageortext/yui/question/question.js diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index b949238551d..0100e758623 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -111,7 +111,7 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere 'topnode' => $topnode, 'readonly' => $options->readonly); - $PAGE->requires->yui_module('moodle-qtype_ddimagetoimage-question', + $PAGE->requires->yui_module('moodle-qtype_ddimagetoimage-dd', 'M.qtype_ddimagetoimage.init_question', array($params)); diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 86b78064a7c..fcaf6bb75bf 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -208,6 +208,133 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { }); M.qtype_ddimagetoimage = M.qtype_ddimagetoimage || {}; M.qtype_ddimagetoimage.dd_base_class = DDIMAGETOIMAGE_DD; - }, '@VERSION@', { + + var DDIMAGETOIMAGEQUESTIONNAME = 'ddimagetoimage_question'; + var DDIMAGETOIMAGE_QUESTION = function() { + DDIMAGETOIMAGE_QUESTION.superclass.constructor.apply(this, arguments); + }; + Y.extend(DDIMAGETOIMAGE_QUESTION, M.qtype_ddimagetoimage.dd_base_class, { + initializer : function(params) { + this.doc = this.doc_structure(this); + this.poll_for_image_load(null, false, 1000, this.create_all_drag_and_drops); + this.doc.bg_img().after('load', this.poll_for_image_load, this, + false, 1000, this.create_all_drag_and_drops); + this.doc.drag_image_homes().after('load', this.poll_for_image_load, this, + false, 1000, this.create_all_drag_and_drops); + Y.on('windowresize', this.reposition_drags_for_question, this); + }, + create_all_drag_and_drops : function () { + this.init_drops(); + this.update_padding_sizes_all(); + var i = 0; + this.doc.drag_image_homes().each(function(dragimagehome){ + var dragimageno = + +this.doc.get_classname_numeric_suffix(dragimagehome, 'dragimagehomes'); + var choice = +this.doc.get_classname_numeric_suffix(dragimagehome, 'choice'); + var group = +this.doc.get_classname_numeric_suffix(dragimagehome, 'group') + var groupsize = this.doc.drop_zone_group(group).size(); + var dragnode = this.doc.clone_new_drag_image(i, dragimageno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + if (dragnode.hasClass('infinite')) { + var dragstocreate = groupsize - 1; + while (dragstocreate > 0) { + dragnode = this.doc.clone_new_drag_image(i, dragimageno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + dragstocreate--; + } + } + }, this); + this.reposition_drags_for_question(); + }, + reposition_drags_for_question : function() { + this.doc.drag_images().removeClass('placed'); + this.doc.drag_images().each (function (dragimage) { + if (dragimage.dd !== undefined) { + dragimage.dd.detachAll('drag:start'); + } + }, this); + this.doc.drop_zones().each(function(dropzone) { + var relativexy = dropzone.getData('xy'); + dropzone.setXY(this.convert_to_window_xy(relativexy)); + var inputcss = 'input#' + dropzone.getData('inputid'); + var input = this.doc.top_node().one(inputcss); + var choice = input.get('value'); + if (choice !== "") { + var group = dropzone.getData('group'); + var dragimage = null; + var dragimages = this.doc.top_node() + .all('div.dragitemgroup'+group+' img.choice'+choice+'.drag'); + dragimages.some(function (d) { + if (!d.hasClass('placed')) { + dragimage = d; + return true; + } else { + return false; + } + }); + if (dragimage !== null) { + dragimage.setXY(dropzone.getXY()); + dragimage.addClass('placed'); + if (dragimage.dd !== undefined) { + dragimage.dd.once('drag:start', function (e, input) { + input.set('value', ''); + e.target.get('node').removeClass('placed'); + },this, input); + } + } + } + }, this); + this.doc.drag_images().each(function(dragimage) { + if (!dragimage.hasClass('placed')) { + var dragimagehome = this.doc.drag_image_home(dragimage.getData('dragimageno')); + dragimage.setXY(dragimagehome.getXY()); + } + }, this); + }, + init_drops : function () { + var dropareas = this.doc.top_node().one('div.dropzones'); + var groupnodes = {}; + for (var groupno =1; groupno <= 8; groupno++) { + var groupnode = Y.Node.create('
'); + dropareas.append(groupnode); + groupnodes[groupno] = groupnode; + } + for (var dropno in this.get('drops')){ + var drop = this.get('drops')[dropno]; + var nodeclass = 'dropzone group'+drop.group+' place'+dropno; + var title = drop.text.replace('"', '\"'); + var dropnodehtml = '
 
'; + var dropnode = Y.Node.create(dropnodehtml); + groupnodes[drop.group].append(dropnode); + dropnode.setStyles({'opacity': 0.5}); + dropnode.setData('xy', drop.xy); + dropnode.setData('place', dropno); + dropnode.setData('inputid', drop.fieldname.replace(':', '_')); + dropnode.setData('group', drop.group); + var dropdd = new Y.DD.Drop({ + node: dropnode}); + dropdd.on('drop:hit', function(e) { + var drag = e.drag.get('node'); + var drop = e.drop.get('node'); + if (+drop.getData('group') === drag.getData('group')){ + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#'+inputid); + inputnode.set('value', drag.getData('choice')); + } + }, this); + }; + } + }, {NAME : DDIMAGETOIMAGEQUESTIONNAME, ATTRS : {}}); + + M.qtype_ddimagetoimage.init_question = function(config) { + return new DDIMAGETOIMAGE_QUESTION(config); + } +}, '@VERSION@', { requires:['node', 'dd', 'dd-drop', 'dd-constrain'] - }); +}); diff --git a/question/type/ddimageortext/yui/question/question.js b/question/type/ddimageortext/yui/question/question.js deleted file mode 100644 index 84460732b3e..00000000000 --- a/question/type/ddimageortext/yui/question/question.js +++ /dev/null @@ -1,130 +0,0 @@ -YUI.add('moodle-qtype_ddimagetoimage-question', function(Y) { - var DDIMAGETOIMAGEQUESTIONNAME = 'ddimagetoimage_question'; - var DDIMAGETOIMAGE_QUESTION = function() { - DDIMAGETOIMAGE_QUESTION.superclass.constructor.apply(this, arguments); - }; - Y.extend(DDIMAGETOIMAGE_QUESTION, M.qtype_ddimagetoimage.dd_base_class, { - initializer : function(params) { - this.doc = this.doc_structure(this); - this.poll_for_image_load(null, false, 1000, this.create_all_drag_and_drops); - this.doc.bg_img().after('load', this.poll_for_image_load, this, - false, 1000, this.create_all_drag_and_drops); - this.doc.drag_image_homes().after('load', this.poll_for_image_load, this, - false, 1000, this.create_all_drag_and_drops); - Y.on('windowresize', this.reposition_drags_for_question, this); - }, - create_all_drag_and_drops : function () { - this.init_drops(); - this.update_padding_sizes_all(); - var i = 0; - this.doc.drag_image_homes().each(function(dragimagehome){ - var dragimageno = - +this.doc.get_classname_numeric_suffix(dragimagehome, 'dragimagehomes'); - var choice = +this.doc.get_classname_numeric_suffix(dragimagehome, 'choice'); - var group = +this.doc.get_classname_numeric_suffix(dragimagehome, 'group') - var groupsize = this.doc.drop_zone_group(group).size(); - var dragnode = this.doc.clone_new_drag_image(i, dragimageno); - i++; - if (!this.get('readonly')) { - this.doc.draggable_for_question(dragnode, group, choice); - } - if (dragnode.hasClass('infinite')) { - var dragstocreate = groupsize - 1; - while (dragstocreate > 0) { - dragnode = this.doc.clone_new_drag_image(i, dragimageno); - i++; - if (!this.get('readonly')) { - this.doc.draggable_for_question(dragnode, group, choice); - } - dragstocreate--; - } - } - }, this); - this.reposition_drags_for_question(); - }, - reposition_drags_for_question : function() { - this.doc.drag_images().removeClass('placed'); - this.doc.drag_images().each (function (dragimage) { - if (dragimage.dd !== undefined) { - dragimage.dd.detachAll('drag:start'); - } - }, this); - this.doc.drop_zones().each(function(dropzone) { - var relativexy = dropzone.getData('xy'); - dropzone.setXY(this.convert_to_window_xy(relativexy)); - var inputcss = 'input#' + dropzone.getData('inputid'); - var input = this.doc.top_node().one(inputcss); - var choice = input.get('value'); - if (choice !== "") { - var group = dropzone.getData('group'); - var dragimage = null; - var dragimages = this.doc.top_node() - .all('div.dragitemgroup'+group+' img.choice'+choice+'.drag'); - dragimages.some(function (d) { - if (!d.hasClass('placed')) { - dragimage = d; - return true; - } else { - return false; - } - }); - if (dragimage !== null) { - dragimage.setXY(dropzone.getXY()); - dragimage.addClass('placed'); - if (dragimage.dd !== undefined) { - dragimage.dd.once('drag:start', function (e, input) { - input.set('value', ''); - e.target.get('node').removeClass('placed'); - },this, input); - } - } - } - }, this); - this.doc.drag_images().each(function(dragimage) { - if (!dragimage.hasClass('placed')) { - var dragimagehome = this.doc.drag_image_home(dragimage.getData('dragimageno')); - dragimage.setXY(dragimagehome.getXY()); - } - }, this); - }, - init_drops : function () { - var dropareas = this.doc.top_node().one('div.dropzones'); - var groupnodes = {}; - for (var groupno =1; groupno <= 8; groupno++) { - var groupnode = Y.Node.create('
'); - dropareas.append(groupnode); - groupnodes[groupno] = groupnode; - } - for (var dropno in this.get('drops')){ - var drop = this.get('drops')[dropno]; - var nodeclass = 'dropzone group'+drop.group+' place'+dropno; - var title = drop.text.replace('"', '\"'); - var dropnodehtml = '
 
'; - var dropnode = Y.Node.create(dropnodehtml); - groupnodes[drop.group].append(dropnode); - dropnode.setStyles({'opacity': 0.5}); - dropnode.setData('xy', drop.xy); - dropnode.setData('place', dropno); - dropnode.setData('inputid', drop.fieldname.replace(':', '_')); - dropnode.setData('group', drop.group); - var dropdd = new Y.DD.Drop({ - node: dropnode}); - dropdd.on('drop:hit', function(e) { - var drag = e.drag.get('node'); - var drop = e.drop.get('node'); - if (+drop.getData('group') === drag.getData('group')){ - var inputid = drop.getData('inputid'); - var inputnode = Y.one('input#'+inputid); - inputnode.set('value', drag.getData('choice')); - } - }, this); - }; - } - }, {NAME : DDIMAGETOIMAGEQUESTIONNAME, ATTRS : {}}); - M.qtype_ddimagetoimage = M.qtype_ddimagetoimage || {}; - M.qtype_ddimagetoimage.init_question = function(config) { - return new DDIMAGETOIMAGE_QUESTION(config); - } -}, '@VERSION@', { - requires:['moodle-qtype_ddimagetoimage-dd'] -}); \ No newline at end of file From 8bfaad3b5bf1f987c64d46ff958c765d55c5bcbe Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 21 Aug 2011 20:55:55 +0700 Subject: [PATCH 067/208] MDL-47494 ddimageortext: NOBUG removing 'correct answer is' textual feedback to student as it is unintelligible and improving summarising of response. Fixed random guess score in statistics that was showing zero. Fixed statistics for question parts. --- .../lang/en/qtype_ddimagetoimage.php | 4 ++ question/type/ddimageortext/question.php | 61 +++++++++++++++++-- question/type/ddimageortext/questiontype.php | 35 +++++++++++ question/type/ddimageortext/renderer.php | 17 +----- 4 files changed, 97 insertions(+), 20 deletions(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index e065751d67b..75ef985e90e 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -53,5 +53,9 @@ $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = '
  • Select a background image file.
  • Select draggable images.
  • And define drop zones by selecting an image that the student must drag to the drop zone and drag it to where the student should drag it too.
'; $string['shuffleimages'] = 'Shuffle Draggable Images'; +$string['summarisechoice'] = '{$a->no}. {$a->text}'; +$string['summariseplace'] = '{$a->no}. {$a->text}'; +$string['summarisechoiceno'] = 'Image {$a}'; +$string['summariseplaceno'] = 'Drop zone {$a}'; $string['xleft'] = 'Left'; $string['ytop'] = 'Top'; \ No newline at end of file diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 42439880685..45a308a0233 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -59,9 +59,25 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { $allblank = true; foreach ($this->places as $placeno => $place) { if (array_key_exists($this->field($placeno), $response) && - $response[$this->field($placeno)]) { - $choices[] = '{' . html_to_text($this->get_selected_choice( - $place->group, $response[$this->field($placeno)])->text, 0, false) . '}'; + $response[$this->field($placeno)]) { + $selected = $this->get_selected_choice($place->group, + $response[$this->field($placeno)]); + if (trim($selected->text) !='') { + $summarisechoice = + get_string('summarisechoice', 'qtype_ddimagetoimage', $selected); + } else { + $summarisechoice = + get_string('summarisechoiceno', 'qtype_ddimagetoimage', $selected->no); + } + $place->no = $placeno; + if (trim($place->text) !='') { + $summariseplace = + get_string('summariseplace', 'qtype_ddimagetoimage', $place); + } else { + $summariseplace = + get_string('summariseplaceno', 'qtype_ddimagetoimage', $place->no); + } + $choices[] = "$summariseplace -> {{$summarisechoice}}"; $allblank = false; } else { $choices[] = '{}'; @@ -105,6 +121,43 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { } return get_string('pleasedraganimagetoeachdropregion', 'qtype_ddimagetoimage'); } + + public function classify_response(array $response) { + $parts = array(); + foreach ($this->places as $placeno => $place) { + $group = $place->group; + if (!array_key_exists($this->field($placeno), $response) || + !$response[$this->field($placeno)]) { + $parts[$placeno] = question_classified_response::no_response(); + continue; + } + + $fieldname = $this->field($placeno); + $choiceno = $this->choiceorder[$group][$response[$fieldname]]; + $choice = $this->choices[$group][$choiceno]; + if (trim($choice->text) !='') { + $summarisechoice = + get_string('summarisechoice', 'qtype_ddimagetoimage', $choice); + } else { + $summarisechoice = + get_string('summarisechoiceno', 'qtype_ddimagetoimage', $choice->no); + } + $correct = $this->get_right_choice_for($placeno) == $response[$fieldname]; + $parts[$placeno] = new question_classified_response( + $choiceno, $summarisechoice, $correct?1:0); + } + return $parts; + } + + public function get_random_guess_score() { + $accum = 0; + + foreach ($this->places as $place) { + $accum += 1 / count($this->choices[$place->group]); + } + + return $accum / count($this->places); + } } @@ -116,7 +169,7 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { */ class qtype_ddimagetoimage_drag_item { public $id; - public $alttextlabel; + public $text; public $no; public $group; public $isinfinite; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 22a6813a83c..be37c6b6666 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -416,4 +416,39 @@ class qtype_ddimagetoimage extends question_type { } return $string; } + + public function get_possible_responses($questiondata) { + $question = $this->make_question($questiondata); + + $parts = array(); + foreach ($question->places as $placeno => $place) { + $group = $place->group; + $choices = array(); + + foreach ($question->choices[$group] as $i => $choice) { + if (trim($choice->text) !='') { + $summarisechoice = + get_string('summarisechoice', 'qtype_ddimagetoimage', $choice); + } else { + $summarisechoice = + get_string('summarisechoiceno', 'qtype_ddimagetoimage', $choice->no); + } + $correct = $question->rightchoices[$placeno] == $i; + $choices[$choice->no] = new question_possible_response( + $summarisechoice, + $correct?1:0); + } + $choices[null] = question_possible_response::no_response(); + + $parts[$placeno] = $choices; + } + + return $parts; + } + + public function get_random_guess_score($questiondata) { + $question = $this->make_question($questiondata); + return $question->get_random_guess_score(); + } + } diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 0100e758623..18a3c238a04 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -165,21 +165,6 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere } public function correct_response(question_attempt $qa) { - $question = $qa->get_question(); - - $correctanswer = ''; - foreach ($question->places as $i => $place) { - $choice = $question->choices[$place->group][$question->rightchoices[$i]]; - if ($choice->text != '') { - $text = $choice->text; - } else { - $text = get_string('nolabel', 'qtype_ddimagetoimage'); - } - $correctanswer .= '[' . str_replace('-', '‑', $text) . ']'; - } - - if (!empty($correctanswer)) { - return get_string('correctansweris', 'qtype_gapselect', $correctanswer); - } + return ''; } } From dbf87f16be6602b004c4c615bc3f4a9fc0918587 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 22 Aug 2011 14:51:18 +0700 Subject: [PATCH 068/208] MDL-47494 ddimageortext: NOBUG a few comments for js classes. --- question/type/ddimageortext/yui/dd/dd.js | 7 +++++++ question/type/ddimageortext/yui/form/form.js | 3 +++ 2 files changed, 10 insertions(+) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index fcaf6bb75bf..8d6125400d0 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -1,8 +1,12 @@ + YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var DDIMAGETOIMAGEDDNAME = 'ddimagetoimage_dd'; var DDIMAGETOIMAGE_DD = function() { DDIMAGETOIMAGE_DD.superclass.constructor.apply(this, arguments); } + /** + * This is the base class for the question rendering and question editing form code. + */ Y.extend(DDIMAGETOIMAGE_DD, Y.Base, { doc : null, polltimer : null, @@ -213,6 +217,9 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var DDIMAGETOIMAGE_QUESTION = function() { DDIMAGETOIMAGE_QUESTION.superclass.constructor.apply(this, arguments); }; + /** + * This is the code for question rendering. + */ Y.extend(DDIMAGETOIMAGE_QUESTION, M.qtype_ddimagetoimage.dd_base_class, { initializer : function(params) { this.doc = this.doc_structure(this); diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 8d7d4064cdb..2189d75bfe9 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -1,3 +1,6 @@ +/** + * This is the question editing form code. + */ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { var DDIMAGETOIMAGEFORMNAME = 'ddimagetoimage_form'; var DDIMAGETOIMAGE_FORM = function() { From 5fd925aaa9e0cd6ca77ce4ed91eb42b629cba840 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 22 Aug 2011 22:23:35 +0700 Subject: [PATCH 069/208] MDL-47494 ddimageortext: NOBUG added key handlers for arrow keys, space key and escape key to select drags for drop zones. --- question/type/ddimageortext/yui/dd/dd.js | 144 ++++++++++++++++++++--- 1 file changed, 129 insertions(+), 15 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 8d6125400d0..2f024e7c0bc 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -68,6 +68,9 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { drag_image : function(draginstanceno) { return dragimagesarea.one('img.draginstance' + draginstanceno); }, + drag_images_in_group : function(groupno) { + return dragimagesarea.all('img.drag.group' + groupno); + }, drag_image_homes : function() { return dragimagesarea.all('img.draghome'); }, @@ -258,6 +261,80 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } }, this); this.reposition_drags_for_question(); + if (!this.get('readonly')) { + this.doc.drop_zones().set('tabIndex', 0); + this.doc.drop_zones().each( + function(v){ + v.on('dragchange', this.drop_zone_key_press, this); + } + , this); + } + }, + drop_zone_key_press : function (e) { + switch (e.direction) { + case 'next' : + this.place_next_drag_in(e.target); + break; + case 'previous' : + this.place_previous_drag_in(e.target); + break; + case 'remove' : + this.remove_drag_from_drop(e.target); + break; + } + e.preventDefault(); + this.reposition_drags_for_question(); + }, + place_next_drag_in : function (drop) { + this.search_for_unplaced_drop_choice(drop, 1); + }, + place_previous_drag_in : function (drop) { + this.search_for_unplaced_drop_choice(drop, -1); + }, + search_for_unplaced_drop_choice : function (drop, direction) { + var next; + var current = this.current_drag_in_drop(drop); + if ('' === current) { + if (direction == 1) { + next = 1; + } else { + next = 1; + var groupno = drop.getData('group'); + this.doc.drag_images_in_group(groupno).each(function(drag) { + next = Math.max(next, drag.getData('choice')); + }, this); + } + } else { + next = + current + direction; + } + var drag; + do { + if (this.get_choices_for_drop(next, drop).size() === 0){ + this.remove_drag_from_drop(drop); + return; + } else { + drag = this.get_unplaced_choice_for_drop(next, drop); + } + next = next + direction; + } while (drag === null); + this.place_drag_in_drop(drag, drop); + }, + current_drag_in_drop : function (drop) { + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#'+inputid); + return inputnode.get('value'); + }, + remove_drag_from_drop : function (drop) { + this.place_drag_in_drop(null, drop); + }, + place_drag_in_drop : function (drag, drop) { + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#'+inputid); + if (drag !== null) { + inputnode.set('value', drag.getData('choice')); + } else { + inputnode.set('value', ''); + } }, reposition_drags_for_question : function() { this.doc.drag_images().removeClass('placed'); @@ -273,18 +350,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var input = this.doc.top_node().one(inputcss); var choice = input.get('value'); if (choice !== "") { - var group = dropzone.getData('group'); - var dragimage = null; - var dragimages = this.doc.top_node() - .all('div.dragitemgroup'+group+' img.choice'+choice+'.drag'); - dragimages.some(function (d) { - if (!d.hasClass('placed')) { - dragimage = d; - return true; - } else { - return false; - } - }); + var dragimage = this.get_unplaced_choice_for_drop(choice, dropzone); if (dragimage !== null) { dragimage.setXY(dropzone.getXY()); dragimage.addClass('placed'); @@ -304,6 +370,28 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } }, this); }, + get_choices_for_drop : function(choice, drop) { + var group = drop.getData('group'); + var dragimage = null; + var dragimages = this.doc.top_node() + .all('div.dragitemgroup'+group+' img.choice'+choice+'.drag'); + return dragimages; + }, + get_unplaced_choice_for_drop : function(choice, drop) { + var dragimages = this.get_choices_for_drop(choice, drop); + if (dragimages.some(function (d) { + if (!d.hasClass('placed')) { + dragimage = d; + return true; + } else { + return false; + } + })) { + return dragimage; + } else { + return null; + } + }, init_drops : function () { var dropareas = this.doc.top_node().one('div.dropzones'); var groupnodes = {}; @@ -330,15 +418,41 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var drag = e.drag.get('node'); var drop = e.drop.get('node'); if (+drop.getData('group') === drag.getData('group')){ - var inputid = drop.getData('inputid'); - var inputnode = Y.one('input#'+inputid); - inputnode.set('value', drag.getData('choice')); + this.place_drag_in_drop(drag, drop); } }, this); }; } }, {NAME : DDIMAGETOIMAGEQUESTIONNAME, ATTRS : {}}); + Y.Event.define('dragchange', { + // Webkit and IE repeat keydown when you hold down arrow keys. + // Opera links keypress to page scroll; others keydown. + // Firefox prevents page scroll via preventDefault() on either + // keydown or keypress. + _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', + + _keys: { + '32': 'next', + '37': 'previous', + '38': 'previous', + '39': 'next', + '40': 'next', + '27': 'remove' + }, + + _keyHandler: function (e, notifier) { + if (this._keys[e.keyCode]) { + e.direction = this._keys[e.keyCode]; + notifier.fire(e); + } + }, + + on: function (node, sub, notifier) { + sub._detacher = node.on(this._event, this._keyHandler, + this, notifier); + } + }); M.qtype_ddimagetoimage.init_question = function(config) { return new DDIMAGETOIMAGE_QUESTION(config); } From 104059b34224e901444fdd5de52f8dd91c627b07 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 23 Aug 2011 13:19:35 +0700 Subject: [PATCH 070/208] MDL-47494 ddimageortext: NOBUG little bit of rejigging of question and response summarising. --- question/type/ddimageortext/question.php | 76 ++++++++++++-------- question/type/ddimageortext/questiontype.php | 12 ++-- 2 files changed, 52 insertions(+), 36 deletions(-) diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 45a308a0233..352e6cd2a1d 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -55,33 +55,19 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { } } public function summarise_response(array $response) { - $matches = array(); $allblank = true; foreach ($this->places as $placeno => $place) { + $summariseplace = $place->summarise(); if (array_key_exists($this->field($placeno), $response) && $response[$this->field($placeno)]) { $selected = $this->get_selected_choice($place->group, $response[$this->field($placeno)]); - if (trim($selected->text) !='') { - $summarisechoice = - get_string('summarisechoice', 'qtype_ddimagetoimage', $selected); - } else { - $summarisechoice = - get_string('summarisechoiceno', 'qtype_ddimagetoimage', $selected->no); - } - $place->no = $placeno; - if (trim($place->text) !='') { - $summariseplace = - get_string('summariseplace', 'qtype_ddimagetoimage', $place); - } else { - $summariseplace = - get_string('summariseplaceno', 'qtype_ddimagetoimage', $place->no); - } - $choices[] = "$summariseplace -> {{$summarisechoice}}"; + $summarisechoice = $selected->summarise(); $allblank = false; } else { - $choices[] = '{}'; + $summarisechoice = ''; } + $choices[] = "$summariseplace -> {{$summarisechoice}}"; } if ($allblank) { return null; @@ -135,16 +121,10 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { $fieldname = $this->field($placeno); $choiceno = $this->choiceorder[$group][$response[$fieldname]]; $choice = $this->choices[$group][$choiceno]; - if (trim($choice->text) !='') { - $summarisechoice = - get_string('summarisechoice', 'qtype_ddimagetoimage', $choice); - } else { - $summarisechoice = - get_string('summarisechoiceno', 'qtype_ddimagetoimage', $choice->no); - } + $correct = $this->get_right_choice_for($placeno) == $response[$fieldname]; $parts[$placeno] = new question_classified_response( - $choiceno, $summarisechoice, $correct?1:0); + $choiceno, $choice->summarise(), $correct?1:0); } return $parts; } @@ -158,6 +138,25 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { return $accum / count($this->places); } + + + public function get_question_summary() { + $summary = ''; + if (!html_is_blank($this->questiontext)) { + $question = $this->html_to_text($this->questiontext, $this->questiontextformat); + $summary .= $question . '; '; + } + $places = array(); + foreach ($this->places as $place) { + $cs = array(); + foreach ($this->choices[$place->group] as $choice) { + $cs[] = $choice->summarise(); + } + $places[] = '[[' . $place->summarise() . ']] -> {' . implode(' / ', $cs) . '}'; + } + $summary .= implode('; ', $places); + return $summary; + } } @@ -184,6 +183,14 @@ class qtype_ddimagetoimage_drag_item { public function choice_group() { return $this->group; } + + public function summarise() { + if (trim($this->text) != '') { + return get_string('summarisechoice', 'qtype_ddimagetoimage', $this); + } else { + return get_string('summarisechoiceno', 'qtype_ddimagetoimage', $this->no); + } + } } /** * Represents one of the places (drop zones). @@ -192,13 +199,26 @@ class qtype_ddimagetoimage_drag_item { * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddimagetoimage_drop_zone { - public $alttextlabel; + public $no; + public $text; public $group; public $xy; - public function __construct($alttextlabel, $group = 1, $x = '', $y = '') { + public function __construct($alttextlabel, $no, $group = 1, $x = '', $y = '') { + $this->no = $no; $this->text = $alttextlabel; $this->group = $group; $this->xy = array($x, $y); } + + public function summarise() { + if (trim($this->text) != '') { + $summariseplace = + get_string('summariseplace', 'qtype_ddimagetoimage', $this); + } else { + $summariseplace = + get_string('summariseplaceno', 'qtype_ddimagetoimage', $this->no); + } + return $summariseplace; + } } \ No newline at end of file diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index be37c6b6666..ead9773eb8b 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -68,7 +68,8 @@ class qtype_ddimagetoimage extends question_type { } protected function make_place($dropzonedata) { - return new qtype_ddimagetoimage_drop_zone($dropzonedata->label, $dropzonedata->group, + return new qtype_ddimagetoimage_drop_zone($dropzonedata->label, $dropzonedata->no, + $dropzonedata->group, $dropzonedata->xleft, $dropzonedata->ytop); } @@ -426,13 +427,8 @@ class qtype_ddimagetoimage extends question_type { $choices = array(); foreach ($question->choices[$group] as $i => $choice) { - if (trim($choice->text) !='') { - $summarisechoice = - get_string('summarisechoice', 'qtype_ddimagetoimage', $choice); - } else { - $summarisechoice = - get_string('summarisechoiceno', 'qtype_ddimagetoimage', $choice->no); - } + $summarisechoice = $choice->summarise(); + $correct = $question->rightchoices[$placeno] == $i; $choices[$choice->no] = new question_possible_response( $summarisechoice, From bfe791348d897f00bac0cb9bd65c5a6546d76b00 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 24 Aug 2011 17:48:28 +0700 Subject: [PATCH 071/208] MDL-47494 ddimageortext: NOBUG made changes to Tim's ddwtos unit tests so that they can be used with this question type. --- .../type/ddimageortext/simpletest/helper.php | 68 ++- .../ddimageortext/simpletest/testquestion.php | 103 ++-- .../simpletest/testquestiontype.php | 474 ------------------ .../simpletest/testwalkthrough.php | 28 ++ 4 files changed, 133 insertions(+), 540 deletions(-) diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/simpletest/helper.php index 317a217fc8c..cde426a8105 100755 --- a/question/type/ddimageortext/simpletest/helper.php +++ b/question/type/ddimageortext/simpletest/helper.php @@ -48,7 +48,7 @@ class qtype_ddimagetoimage_test_helper extends question_test_helper { test_question_maker::initialise_a_question($dd); $dd->name = 'Drag-and-drop words into sentences question'; - $dd->questiontext = 'The [[1]] brown [[2]] jumped over the [[3]] dog.'; + $dd->questiontext = 'The quick brown fox jumped over the lazy dog.'; $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; $dd->qtype = question_bank::get_qtype('ddimagetoimage'); @@ -56,25 +56,44 @@ class qtype_ddimagetoimage_test_helper extends question_test_helper { test_question_maker::set_standard_combined_feedback_fields($dd); - $dd->choices = array( - 1 => array( - 1 => new qtype_ddimagetoimage_choice('quick', 1), - 2 => new qtype_ddimagetoimage_choice('slow', 1)), - 2 => array( - 1 => new qtype_ddimagetoimage_choice('fox', 2), - 2 => new qtype_ddimagetoimage_choice('dog', 2)), - 3 => array( - 1 => new qtype_ddimagetoimage_choice('lazy', 3), - 2 => new qtype_ddimagetoimage_choice('assiduous', 3)), - ); + $dd->choices = $this->make_choice_structure(array( + new qtype_ddimagetoimage_drag_item('quick', 1, 1), + new qtype_ddimagetoimage_drag_item('fox', 2, 1), + new qtype_ddimagetoimage_drag_item('lazy', 1, 2), + new qtype_ddimagetoimage_drag_item('dog', 2, 2) - $dd->places = array(1 => 1, 2 => 2, 3 => 3); - $dd->rightchoices = array(1 => 1, 2 => 1, 3 => 1); - $dd->textfragments = array('The ', ' brown ', ' jumped over the ', ' dog.'); + )); + + $dd->places = $this->make_place_structure(array( + new qtype_ddimagetoimage_drop_zone('', 1, 1), + new qtype_ddimagetoimage_drop_zone('', 2, 1), + new qtype_ddimagetoimage_drop_zone('', 3, 2), + new qtype_ddimagetoimage_drop_zone('', 4, 2) + )); + $dd->rightchoices = array(1 => 1, 2 => 2, 3 => 1, 4 => 2); return $dd; } + protected function make_choice_structure($choices) { + $choicestructure = array(); + foreach ($choices as $choice) { + if (!isset($choicestructure[$choice->group])) { + $choicestructure[$choice->group] = array(); + } + $choicestructure[$choice->group][$choice->no] = $choice; + } + return $choicestructure; + } + + protected function make_place_structure($places) { + $placestructure = array(); + foreach ($places as $place) { + $placestructure[$place->no] = $place; + } + return $placestructure; + } + /** * @return qtype_ddimagetoimage_question */ @@ -94,17 +113,18 @@ class qtype_ddimagetoimage_test_helper extends question_test_helper { test_question_maker::set_standard_combined_feedback_fields($dd); - $dd->choices = array( - 1 => array( - 1 => new qtype_ddimagetoimage_choice('+', 1, true), - 2 => new qtype_ddimagetoimage_choice('-', 1, true), - 3 => new qtype_ddimagetoimage_choice('*', 1, true), - 4 => new qtype_ddimagetoimage_choice('/', 1, true), - )); + $dd->choices = $this->make_choice_structure(array( + new qtype_ddimagetoimage_drag_item('+', 1, 1), + new qtype_ddimagetoimage_drag_item('-', 2, 1) + )); - $dd->places = array(1 => 1, 2 => 1, 3 => 1, 4 => 1); + $dd->places = $this->make_place_structure(array( + new qtype_ddimagetoimage_drop_zone('', 1, 1), + new qtype_ddimagetoimage_drop_zone('', 2, 1), + new qtype_ddimagetoimage_drop_zone('', 3, 1), + new qtype_ddimagetoimage_drop_zone('', 4, 1) + )); $dd->rightchoices = array(1 => 1, 2 => 2, 3 => 1, 4 => 2); - $dd->textfragments = array('7 ', ' 11 ', ' 13 ', ' 17 ', ' 19 = 3'); return $dd; } diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index bdee7b892e3..6ddd54b12ab 100755 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -40,16 +40,23 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { public function test_get_question_summary() { $dd = test_question_maker::make_question('ddimagetoimage'); - $this->assertEqual('The [[1]] brown [[2]] jumped over the [[3]] dog.; ' . - '[[1]] -> {quick / slow}; [[2]] -> {fox / dog}; [[3]] -> {lazy / assiduous}', - $dd->get_question_summary()); + $this->assertEqual('The quick brown fox jumped over the lazy dog.; '. + '[[Drop zone 1]] -> {1. quick / 2. fox}; '. + '[[Drop zone 2]] -> {1. quick / 2. fox}; '. + '[[Drop zone 3]] -> {1. lazy / 2. dog}; '. + '[[Drop zone 4]] -> {1. lazy / 2. dog}', + $dd->get_question_summary()); } public function test_get_question_summary_maths() { $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); - $this->assertEqual('Fill in the operators to make this equation work: ' . - '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3; [[1]] -> {+ / - / * / /}', - $dd->get_question_summary()); + $this->assertEqual('Fill in the operators to make this equation work: '. + '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3; '. + '[[Drop zone 1]] -> {1. + / 2. -}; '. + '[[Drop zone 2]] -> {1. + / 2. -}; '. + '[[Drop zone 3]] -> {1. + / 2. -}; '. + '[[Drop zone 4]] -> {1. + / 2. -}', + $dd->get_question_summary()); } public function test_summarise_response() { @@ -57,8 +64,11 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual('{quick} {fox} {lazy}', - $dd->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); + $this->assertEqual('Drop zone 1 -> {1. quick} '. + 'Drop zone 2 -> {1. quick} '. + 'Drop zone 3 -> {1. lazy} '. + 'Drop zone 4 -> {1. lazy}', + $dd->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); } public function test_summarise_response_maths() { @@ -66,7 +76,10 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual('{+} {-} {+} {-}', + $this->assertEqual('Drop zone 1 -> {1. +} '. + 'Drop zone 2 -> {2. -} '. + 'Drop zone 3 -> {1. +} '. + 'Drop zone 4 -> {2. -}', $dd->summarise_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); } @@ -77,7 +90,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { public function test_get_random_guess_score_maths() { $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); - $this->assertEqual(0.25, $dd->get_random_guess_score()); + $this->assertEqual(0.5, $dd->get_random_guess_score()); } public function test_get_right_choice_for() { @@ -86,7 +99,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(1, $dd->get_right_choice_for(1)); - $this->assertEqual(1, $dd->get_right_choice_for(2)); + $this->assertEqual(2, $dd->get_right_choice_for(2)); } public function test_get_right_choice_for_maths() { @@ -96,6 +109,8 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $this->assertEqual(1, $dd->get_right_choice_for(1)); $this->assertEqual(2, $dd->get_right_choice_for(2)); + $this->assertEqual(1, $dd->get_right_choice_for(3)); + $this->assertEqual(2, $dd->get_right_choice_for(4)); } public function test_clear_wrong_from_response() { @@ -104,7 +119,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $dd->start_attempt(new question_attempt_step(), 1); $initialresponse = array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'); - $this->assertEqual(array('p1' => '1', 'p2' => '0', 'p3' => '1', 'p4' => '0'), + $this->assertEqual(array('p1' => '1', 'p2' => '', 'p3' => '1', 'p4' => ''), $dd->clear_wrong_from_response($initialresponse)); } @@ -113,10 +128,10 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array(2, 3), - $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '2'))); - $this->assertEqual(array(3, 3), - $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); + $this->assertEqual(array(2, 4), + $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '2'))); + $this->assertEqual(array(4, 4), + $dd->get_num_parts_right(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); } public function test_get_num_parts_right_maths() { @@ -133,8 +148,10 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $dd = test_question_maker::make_question('ddimagetoimage'); $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT), - $dd->get_expected_data()); + $this->assertEqual( + array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT, 'p4' => PARAM_INT), + $dd->get_expected_data() + ); } public function test_get_correct_response() { @@ -142,7 +159,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array('p1' => '1', 'p2' => '1', 'p3' => '1'), + $this->assertEqual(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'), $dd->get_correct_response()); } @@ -161,23 +178,23 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $this->assertTrue($dd->is_same_response( array(), - array('p1' => '0', 'p2' => '0', 'p3' => '0'))); + array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => ''))); $this->assertFalse($dd->is_same_response( array(), - array('p1' => '1', 'p2' => '0', 'p3' => '0'))); + array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => ''))); $this->assertFalse($dd->is_same_response( - array('p1' => '0', 'p2' => '0', 'p3' => '0'), - array('p1' => '1', 'p2' => '0', 'p3' => '0'))); + array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => ''), + array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => ''))); $this->assertTrue($dd->is_same_response( - array('p1' => '1', 'p2' => '2', 'p3' => '3'), - array('p1' => '1', 'p2' => '2', 'p3' => '3'))); + array('p1' => '1', 'p2' => '2', 'p3' => '3', 'p4' => '4'), + array('p1' => '1', 'p2' => '2', 'p3' => '3', 'p4' => '4'))); $this->assertFalse($dd->is_same_response( - array('p1' => '1', 'p2' => '2', 'p3' => '3'), - array('p1' => '1', 'p2' => '2', 'p3' => '2'))); + array('p1' => '1', 'p2' => '2', 'p3' => '3', 'p4' => '4'), + array('p1' => '1', 'p2' => '2', 'p3' => '2', 'p4' => '4'))); } public function test_is_complete_response() { $dd = test_question_maker::make_question('ddimagetoimage'); @@ -185,10 +202,10 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $this->assertFalse($dd->is_complete_response(array())); $this->assertFalse($dd->is_complete_response( - array('p1' => '1', 'p2' => '1', 'p3' => '0'))); + array('p1' => '1', 'p2' => '1', 'p3' => '', 'p4' => ''))); $this->assertFalse($dd->is_complete_response(array('p1' => '1'))); $this->assertTrue($dd->is_complete_response( - array('p1' => '1', 'p2' => '1', 'p3' => '1'))); + array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); } public function test_is_gradable_response() { @@ -197,9 +214,9 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $this->assertFalse($dd->is_gradable_response(array())); $this->assertFalse($dd->is_gradable_response( - array('p1' => '0', 'p2' => '0', 'p3' => '0'))); + array('p1' => '', 'p2' => '', 'p3' => '', 'p3' => ''))); $this->assertTrue($dd->is_gradable_response( - array('p1' => '1', 'p2' => '1', 'p3' => '0'))); + array('p1' => '1', 'p2' => '1', 'p3' => ''))); $this->assertTrue($dd->is_gradable_response(array('p1' => '1'))); $this->assertTrue($dd->is_gradable_response( array('p1' => '1', 'p2' => '1', 'p3' => '1'))); @@ -211,11 +228,11 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array(1, question_state::$gradedright), - $dd->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1'))); - $this->assertEqual(array(1/3, question_state::$gradedpartial), + $dd->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); + $this->assertEqual(array(0.25, question_state::$gradedpartial), $dd->grade_response(array('p1' => '1'))); $this->assertEqual(array(0, question_state::$gradedwrong), - $dd->grade_response(array('p1' => '2', 'p2' => '2', 'p3' => '2'))); + $dd->grade_response(array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1'))); } public function test_grading_maths() { @@ -228,7 +245,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $this->assertEqual(array(0.5, question_state::$gradedpartial), $dd->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); $this->assertEqual(array(0, question_state::$gradedwrong), - $dd->grade_response(array('p1' => '0', 'p2' => '1', 'p3' => '2', 'p4' => '1'))); + $dd->grade_response(array('p1' => '', 'p2' => '1', 'p3' => '2', 'p4' => '1'))); } public function test_classify_response() { @@ -237,14 +254,16 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual(array( - 1 => new question_classified_response(1, 'quick', 1), - 2 => new question_classified_response(2, 'dog', 0), - 3 => new question_classified_response(1, 'lazy', 1), - ), $dd->classify_response(array('p1' => '1', 'p2' => '2', 'p3' => '1'))); + 1 => new question_classified_response(1, '1. quick', 1), + 2 => new question_classified_response(2, '2. fox', 1), + 3 => new question_classified_response(1, '1. lazy', 1), + 4 => new question_classified_response(2, '2. dog', 1) + ), $dd->classify_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); $this->assertEqual(array( 1 => question_classified_response::no_response(), - 2 => new question_classified_response(1, 'fox', 1), - 3 => new question_classified_response(2, 'assiduous', 0), - ), $dd->classify_response(array('p1' => '0', 'p2' => '1', 'p3' => '2'))); + 2 => new question_classified_response(1, '1. quick', 0), + 3 => new question_classified_response(2, '2. dog', 0), + 4 => new question_classified_response(2, '2. dog', 1) + ), $dd->classify_response(array('p1' => '', 'p2' => '1', 'p3' => '2', 'p4' => '2'))); } } diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index 78c42a87582..72d7a387b34 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -48,63 +48,6 @@ class qtype_ddimagetoimage_test extends UnitTestCase { $this->qtype = null; } - public function assert_same_xml($expectedxml, $xml) { - $this->assertEqual(str_replace("\r\n", "\n", $expectedxml), - str_replace("\r\n", "\n", $xml)); - } - - /** - * @return object the data to construct a question like - * {@link qtype_ddimagetoimage_test_helper::make_ddimagetoimage_question_fox()}. - */ - protected function get_test_question_data() { - global $USER; - - $dd = new stdClass(); - $dd->id = 0; - $dd->category = 0; - $dd->contextid = 0; - $dd->parent = 0; - $dd->questiontextformat = FORMAT_HTML; - $dd->generalfeedbackformat = FORMAT_HTML; - $dd->defaultmark = 1; - $dd->penalty = 0.3333333; - $dd->length = 1; - $dd->stamp = make_unique_id_code(); - $dd->version = make_unique_id_code(); - $dd->hidden = 0; - $dd->timecreated = time(); - $dd->timemodified = time(); - $dd->createdby = $USER->id; - $dd->modifiedby = $USER->id; - - $dd->name = 'Drag-and-drop words into sentences question'; - $dd->questiontext = 'The [[1]] brown [[2]] jumped over the [[3]] dog.'; - $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; - $dd->qtype = 'ddimagetoimage'; - - $dd->options->shuffleanswers = true; - - test_question_maker::set_standard_combined_feedback_fields($dd->options); - - $dd->options->answers = array( - (object) array('answer' => 'quick', 'feedback' => - 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), - (object) array('answer' => 'fox', 'feedback' => - 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), - (object) array('answer' => 'lazy', 'feedback' => - 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), - (object) array('answer' => 'assiduous', 'feedback' => - 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), - (object) array('answer' => 'dog', 'feedback' => - 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), - (object) array('answer' => 'slow', 'feedback' => - 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), - ); - - return $dd; - } - public function test_name() { $this->assertEqual($this->qtype->name(), 'ddimagetoimage'); } @@ -112,421 +55,4 @@ class qtype_ddimagetoimage_test extends UnitTestCase { public function test_can_analyse_responses() { $this->assertTrue($this->qtype->can_analyse_responses()); } - - public function test_initialise_question_instance() { - $qdata = $this->get_test_question_data(); - - $expected = test_question_maker::make_question('ddimagetoimage'); - $expected->stamp = $qdata->stamp; - $expected->version = $qdata->version; - - $q = $this->qtype->make_question($qdata); - - $this->assertEqual($expected, $q); - } - - public function test_get_random_guess_score() { - $q = $this->get_test_question_data(); - $this->assertWithinMargin(0.5, $this->qtype->get_random_guess_score($q), 0.0000001); - } - - public function test_get_possible_responses() { - $q = $this->get_test_question_data(); - - $this->assertEqual(array( - 1 => array( - 1 => new question_possible_response('quick', 1), - 2 => new question_possible_response('slow', 0), - null => question_possible_response::no_response()), - 2 => array( - 1 => new question_possible_response('fox', 1), - 2 => new question_possible_response('dog', 0), - null => question_possible_response::no_response()), - 3 => array( - 1 => new question_possible_response('lazy', 1), - 2 => new question_possible_response('assiduous', 0), - null => question_possible_response::no_response()), - ), $this->qtype->get_possible_responses($q)); - } - - public function test_xml_import() { - $xml = ' - - A drag-and-drop question - - - Put these in order: [[1]], [[2]], [[3]]. - - - The answer is Alpha, Beta, Gamma. - - 3 - 0.3333333 - 0 - 1 - - Your answer is correct.

]]>
-
- - Your answer is partially correct.

]]>
-
- - Your answer is incorrect.

]]>
-
- - - Alpha - 1 - - - Beta - 1 - - - Gamma - 1 - - - - Try again. - - - - These are the first three letters of the Greek alphabet. - - - -
'; - $xmldata = xmlize($xml); - - $importer = new qformat_xml(); - $q = $importer->try_importing_using_qtypes( - $xmldata['question'], null, null, 'ddimagetoimage'); - - $expectedq = new stdClass(); - $expectedq->qtype = 'ddimagetoimage'; - $expectedq->name = 'A drag-and-drop question'; - $expectedq->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; - $expectedq->questiontextformat = FORMAT_MOODLE; - $expectedq->generalfeedback = 'The answer is Alpha, Beta, Gamma.'; - $expectedq->defaultmark = 3; - $expectedq->length = 1; - $expectedq->penalty = 0.3333333; - - $expectedq->shuffleanswers = 1; - $expectedq->correctfeedback = array('text' => '

Your answer is correct.

', - 'format' => FORMAT_MOODLE, 'files' => array()); - $expectedq->partiallycorrectfeedback = array( - 'text' => '

Your answer is partially correct.

', - 'format' => FORMAT_MOODLE, 'files' => array()); - $expectedq->shownumcorrect = true; - $expectedq->incorrectfeedback = array('text' => '

Your answer is incorrect.

', - 'format' => FORMAT_MOODLE, 'files' => array()); - - $expectedq->choices = array( - array('answer' => 'Alpha', 'choicegroup' => 1, 'infinite' => false), - array('answer' => 'Beta', 'choicegroup' => 1, 'infinite' => false), - array('answer' => 'Gamma', 'choicegroup' => 1, 'infinite' => true), - ); - - $expectedq->hint = array( - array('text' => 'Try again.', 'format' => FORMAT_MOODLE, 'files' => array()), - array('text' => 'These are the first three letters of the Greek alphabet.', - 'format' => FORMAT_MOODLE, 'files' => array())); - $expectedq->hintshownumcorrect = array(true, true); - $expectedq->hintclearwrong = array(false, true); - - $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q); - } - - public function test_xml_import_legacy() { - $xml = ' - - QDandD1 Base definition - - - <p>Drag and drop the words from the list below to fill the blank spaces ' . - 'and correctly complete the sentence.</p> <p>At 25°C all aqueous basic ' . - 'solutions have [[1]] ion concentrations less than [[8]]<br />mol ' . - 'litre<sup>-1</sup> and pH values [[9]] than [[6]].</p> ' . - '<!--DONOTCLEAN--> - - - - <p>At 25 &#xB0;C all aqueous basic solutions have hydrogen ion ' . - 'concentrations less than 10<sup>&#x2212;7</sup> mol ' . - 'litre<sup>&#x2212;1</sup> and pH values greater than 7.</p> ' . - '<p>See Section 9 of S103 <em class="italic">Discovering ' . - 'Science</em> Block 8.</p> - - 1 - 0.33 - 0 - 0 - false - - 1 - hydrogen - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;} - - - - 0 - positive - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;} - - - - 0 - hydroxide - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;} - - - - 0 - negative - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;} - - - - 0 - 10<sup>7</sup> - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;} - - - - 1 - 7 - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;} - - - - 0 - 1 - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;} - - - - 1 - 10<sup>-7</sup> - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;} - - - - 1 - greater - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;} - - - - 0 - less - - O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;} - - - - Your answer is correct. - - 1 - - Your answer is partially correct. - - - Your answer is incorrect. - - 0 - 0.33 - - 1 - 0 - - You may wish to read Section 9 of <em ' . - 'class="italic">Discovering Science</em> Block 8. - - - - 1 - 1 - - Any incorrect choices will be removed before your final try. - - - '; - $xmldata = xmlize($xml); - - $importer = new qformat_xml(); - $q = $importer->try_importing_using_qtypes( - $xmldata['question'], null, null, 'ddimagetoimage'); - - $expectedq = new stdClass(); - $expectedq->qtype = 'ddimagetoimage'; - $expectedq->name = 'QDandD1 Base definition'; - $expectedq->questiontext = '

Drag and drop the words from the list below ' . - 'to fill the blank spaces and correctly complete the sentence.

' . - '

At 25°C all aqueous basic solutions have [[1]] ion concentrations ' . - 'less than [[8]]
mol litre-1 and pH values [[9]] than [[6]].

' . - ''; - $expectedq->questiontextformat = FORMAT_HTML; - $expectedq->generalfeedback = '

At 25 °C all aqueous basic solutions ' . - 'have hydrogen ion concentrations less than 10−7 ' . - 'mol litre−1 and pH values greater than 7.

See ' . - 'Section 9 of S103 Discovering Science Block 8.

'; - $expectedq->defaultmark = 1; - $expectedq->length = 1; - $expectedq->penalty = 0.3333333; - - $expectedq->shuffleanswers = 0; - $expectedq->correctfeedback = array('text' => 'Your answer is correct.', - 'format' => FORMAT_MOODLE, 'files' => array()); - $expectedq->partiallycorrectfeedback = array( - 'text' => 'Your answer is partially correct.', - 'format' => FORMAT_MOODLE, 'files' => array()); - $expectedq->shownumcorrect = true; - $expectedq->incorrectfeedback = array('text' => 'Your answer is incorrect.', - 'format' => FORMAT_MOODLE, 'files' => array()); - - $expectedq->choices = array( - array('answer' => array('text' => 'hydrogen', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 1, 'infinite' => false), - array('answer' => array('text' => 'positive', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 1, 'infinite' => false), - array('answer' => array('text' => 'hydroxide', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 1, 'infinite' => false), - array('answer' => array('text' => 'negative', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 1, 'infinite' => false), - array('answer' => array('text' => '107', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 2, 'infinite' => false), - array('answer' => array('text' => '7', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 2, 'infinite' => false), - array('answer' => array('text' => '1', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 2, 'infinite' => false), - array('answer' => array('text' => '10-7', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 2, 'infinite' => false), - array('answer' => array('text' => 'greater', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 3, 'infinite' => false), - array('answer' => array('text' => 'less', 'format' => FORMAT_MOODLE, - 'files' => array()), 'choicegroup' => 3, 'infinite' => false), - ); - - $expectedq->hint = array(array('text' => 'You may wish to read Section 9 of ' . - 'Discovering Science Block 8.', - 'format' => FORMAT_HTML, 'files' => array()), - array('text' => 'Any incorrect choices will be removed before your final try.', - 'format' => FORMAT_HTML, 'files' => array()), - ); - $expectedq->hintshownumcorrect = array(true, true); - $expectedq->hintclearwrong = array(false, true); - - $this->assert(new CheckSpecifiedFieldsExpectation($expectedq), $q); - $this->assertEqual($expectedq->hint, $q->hint); - } - - public function test_xml_export() { - $qdata = new stdClass(); - $qdata->id = 123; - $qdata->contextid = 0; - $qdata->qtype = 'ddimagetoimage'; - $qdata->name = 'A drag-and-drop question'; - $qdata->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; - $qdata->questiontextformat = FORMAT_MOODLE; - $qdata->generalfeedback = 'The answer is Alpha, Beta, Gamma.'; - $qdata->generalfeedbackformat = FORMAT_MOODLE; - $qdata->defaultmark = 3; - $qdata->length = 1; - $qdata->penalty = 0.3333333; - $qdata->hidden = 0; - - $qdata->options->shuffleanswers = 1; - $qdata->options->correctfeedback = '

Your answer is correct.

'; - $qdata->options->correctfeedbackformat = FORMAT_MOODLE; - $qdata->options->partiallycorrectfeedback = '

Your answer is partially correct.

'; - $qdata->options->partiallycorrectfeedbackformat = FORMAT_MOODLE; - $qdata->options->shownumcorrect = 1; - $qdata->options->incorrectfeedback = '

Your answer is incorrect.

'; - $qdata->options->incorrectfeedbackformat = FORMAT_MOODLE; - - $qdata->options->answers = array( - 13 => new question_answer(13, 'Alpha', 0, - 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', - FORMAT_MOODLE), - 14 => new question_answer(14, 'Beta', 0, - 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', - FORMAT_MOODLE), - 15 => new question_answer(15, 'Gamma', 0, - 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:1;}', - FORMAT_MOODLE), - ); - - $qdata->hints = array( - 1 => new question_hint_with_parts(1, 'Try again.', FORMAT_MOODLE, true, false), - 2 => new question_hint_with_parts(2, - 'These are the first three letters of the Greek alphabet.', - FORMAT_MOODLE, true, true), - ); - - $exporter = new qformat_xml(); - $xml = $exporter->writequestion($qdata); - - $expectedxml = ' - - - A drag-and-drop question - - - Put these in order: [[1]], [[2]], [[3]]. - - - The answer is Alpha, Beta, Gamma. - - 3 - 0.3333333 - 0 - 1 - - Your answer is correct.

]]>
-
- - Your answer is partially correct.

]]>
-
- - Your answer is incorrect.

]]>
-
- - - Alpha - 1 - - - Beta - 1 - - - Gamma - 1 - - - - Try again. - - - - These are the first three letters of the Greek alphabet. - - - -
-'; - - $this->assert_same_xml($expectedxml, $xml); - } } diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index bbbdf4118eb..e2e15c2516b 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -73,6 +73,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -83,6 +84,8 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->quba->get_field_prefix($this->slot) . 'p2', '0'), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', '0'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), @@ -94,6 +97,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -116,6 +120,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, true), $this->get_contains_drop_box_expectation('p2', 2, true), @@ -133,6 +138,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -155,6 +161,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedright); $this->check_current_mark(2); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), @@ -181,6 +188,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -199,6 +207,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$invalid); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -218,6 +227,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$complete); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -264,6 +274,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -284,6 +295,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -304,6 +316,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gaveup); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, true), $this->get_contains_drop_box_expectation('p2', 2, true), @@ -320,6 +333,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -339,6 +353,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$invalid); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -358,6 +373,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedpartial); $this->check_current_mark(1); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), $this->get_contains_drop_box_expectation('p2', 2, true, 'incorrect'), @@ -383,6 +399,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->check_current_mark(null); $this->assertEqual('interactivecountback', $this->quba->get_question_attempt($this->slot)->get_behaviour_name()); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -405,6 +422,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, true), $this->get_contains_drop_box_expectation('p2', 2, true), @@ -436,6 +454,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -459,6 +478,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, true), $this->get_contains_drop_box_expectation('p2', 2, true), @@ -484,6 +504,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -507,6 +528,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedright); $this->check_current_mark(6); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), @@ -541,6 +563,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -565,6 +588,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedright); $this->check_current_mark(3); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), @@ -597,6 +621,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), @@ -621,6 +646,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedpartial); $this->check_current_mark(1); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), $this->get_contains_drop_box_expectation('p2', 2, true, 'incorrect'), @@ -651,6 +677,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_marked_out_of_summary(), $this->get_contains_drop_box_expectation('p1', 1, false), @@ -713,6 +740,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); + $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( $this->get_contains_drop_box_expectation('p1', 1, false), $this->get_contains_drop_box_expectation('p2', 2, false), From e074cd91ea2171a2b4e795d28d2170d9500ee31e Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 24 Aug 2011 17:52:53 +0700 Subject: [PATCH 072/208] MDL-47494 ddimageortext: NOBUG "Typo in DDWtoS foreign key definition #874" applying a small fix for a typo from a fix to the ddwtos code that this code is based on. --- question/type/ddimageortext/db/install.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml index 6ab689a2b2e..07a40be9766 100755 --- a/question/type/ddimageortext/db/install.xml +++ b/question/type/ddimageortext/db/install.xml @@ -19,7 +19,7 @@ - + From 87c64021c2dc001a38648bbb5293168abc4e2fa6 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 24 Aug 2011 18:25:53 +0700 Subject: [PATCH 073/208] MDL-47494 ddimageortext: NOBUG mainly white space changes to fix code formatting issues highlighted by code checker. --- question/type/ddimageortext/README.txt | 6 ++- question/type/ddimageortext/TODO.txt | 12 ----- ...ckup_qtype_ddimagetoimage_plugin.class.php | 2 - ...tore_qtype_ddimagetoimage_plugin.class.php | 8 +-- question/type/ddimageortext/db/install.xml | 2 +- .../edit_ddimagetoimage_form.php | 7 +-- question/type/ddimageortext/questiontype.php | 13 +++-- question/type/ddimageortext/renderer.php | 3 +- question/type/ddimageortext/styles.css | 1 - question/type/ddimageortext/yui/dd/dd.js | 33 ++++++------ question/type/ddimageortext/yui/form/form.js | 51 +++++++++---------- 11 files changed, 58 insertions(+), 80 deletions(-) delete mode 100644 question/type/ddimageortext/TODO.txt diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index 5fbeb377a09..6c4605afe54 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -11,8 +11,10 @@ This question type is compatible with Moodle 2.1+. Requires this fix : MDL-28099 filepicker form element does not work with element names with an index such as image[0] -To install using git, type this command in the root of your Moodle install - git clone git://github.com/jamiepratt/moodle-qtype_ddimagetoimage.git question/type/ddimagetoimage +To install using git, type this command in the root of your Moodle install : + +git clone git://github.com/jamiepratt/moodle-qtype_ddimagetoimage.git question/type/ddimagetoimage + Then add question/type/ddimagetoimage to your git ignore. Alternatively, download the zip from diff --git a/question/type/ddimageortext/TODO.txt b/question/type/ddimageortext/TODO.txt deleted file mode 100644 index aceaf24f456..00000000000 --- a/question/type/ddimageortext/TODO.txt +++ /dev/null @@ -1,12 +0,0 @@ -Question authoring form fields -* correct sizing of borders and margins - -Question instance saving 2 hours -Question instance loading 2 hours -Question rendering code 6 hours -- repurpose and extend authoring form code for question rendering -- make sure code works with multiple questions on the page -- get position that images where dropped to from hidden fields -- grade question parts based on where images dragged to - -Testing and debugging for cross browser compatibility 4 hours diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php index 4aeef438677..de8d93da728 100644 --- a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php @@ -57,7 +57,6 @@ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { $drop = new backup_nested_element('drop', array('id'), array('no', 'xleft', 'ytop', 'choice', 'label')); - $ddimagetoimages->set_source_table('qtype_ddimagetoimage', array('questionid' => backup::VAR_PARENTID)); @@ -69,7 +68,6 @@ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { $drag->set_source_table('qtype_ddimagetoimage_drags', array('questionid' => backup::VAR_PARENTID)); - $drop->set_source_table('qtype_ddimagetoimage_drops', array('questionid' => backup::VAR_PARENTID)); diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php index eeb4ac1f289..7d54ed41861 100644 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php @@ -21,10 +21,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - defined('MOODLE_INTERNAL') || die(); - /** * restore plugin class that provides the necessary information * needed to restore one ddimagetoimage qtype plugin @@ -71,7 +69,8 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { $newquestionid = $this->get_new_parentid('question'); $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; - // If the question has been created by restore, we need to create its qtype_ddimagetoimage too + // If the question has been created by restore, + // we need to create its qtype_ddimagetoimage too if ($questioncreated) { // Adjust some columns $data->questionid = $newquestionid; @@ -137,7 +136,8 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { $contents = array(); $fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'); - $contents[] = new restore_decode_content('qtype_ddimagetoimage', $fields, 'question_ddimagetoimage'); + $contents[] = + new restore_decode_content('qtype_ddimagetoimage', $fields, 'question_ddimagetoimage'); return $contents; } diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml index 07a40be9766..209aa0a2a08 100755 --- a/question/type/ddimageortext/db/install.xml +++ b/question/type/ddimageortext/db/install.xml @@ -52,4 +52,4 @@
-
\ No newline at end of file + diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index d47bff8ed0f..f21e4d9b114 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -67,7 +67,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { } $imagerepeats = optional_param('noimages', $imagerepeatsatstart, PARAM_INT); $addfields = optional_param('addimages', '', PARAM_TEXT); - if (!empty($addfields)){ + if (!empty($addfields)) { $imagerepeats += self::ADD_NUM_IMAGES; } return array($imagerepeatsatstart, $imagerepeats); @@ -85,7 +85,6 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { get_string('previewarea', 'qtype_ddimagetoimage'), get_string('previewareamessage', 'qtype_ddimagetoimage')); - list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); $this->definition_drop_zones($mform, $imagerepeats); $mform->addElement('advcheckbox', 'shuffleanswers', ' ', @@ -106,7 +105,6 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimagetoimage'), null, self::file_picker_options()); - $countdropzones = 0; if (isset($this->question->id)) { foreach ($this->question->options->drops as $drop) { @@ -129,7 +127,6 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { protected function drop_zone($mform, $imagerepeats) { $dropzoneitem = array(); - $grouparray = array(); $grouparray[] = $mform->createElement('static', 'xleftlabel', '', ' '.get_string('xleft', 'qtype_ddimagetoimage').' '); @@ -293,7 +290,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { public function validation($data, $files) { $errors = parent::validation($data, $files); - if (!self::file_uploaded($data['bgimage'])){ + if (!self::file_uploaded($data['bgimage'])) { $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddimagetoimage'); } diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index ead9773eb8b..e3d7cea2180 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -134,8 +134,8 @@ class qtype_ddimagetoimage extends question_type { $this->save_hints($formdata, true); $DB->update_record('qtype_ddimagetoimage', $options); $DB->delete_records('qtype_ddimagetoimage_drops', array('questionid' => $formdata->id)); - foreach (array_keys($formdata->drops) as $dropno){ - if ($formdata->drops[$dropno]['choice'] == 0){ + foreach (array_keys($formdata->drops) as $dropno) { + if ($formdata->drops[$dropno]['choice'] == 0) { continue; } $drop = new stdClass(); @@ -153,7 +153,7 @@ class qtype_ddimagetoimage extends question_type { $olddragids = $DB->get_records_menu('qtype_ddimagetoimage_drags', array('questionid' => $formdata->id), '', 'no, id'); - foreach (array_keys($formdata->drags) as $dragno){ + foreach (array_keys($formdata->drags) as $dragno) { $info = file_get_draft_area_info($formdata->dragitem[$dragno]); if ($info['filecount'] > 0) { $draftitemid = $formdata->dragitem[$dragno]; @@ -173,8 +173,6 @@ class qtype_ddimagetoimage extends question_type { $drag->id = $DB->insert_record('qtype_ddimagetoimage_drags', $drag); } - - self::constrain_image_size_in_draft_area($draftitemid, QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH, QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT); @@ -218,7 +216,7 @@ class qtype_ddimagetoimage extends question_type { $quality = 8; break; default : - $quality = NULL; + $quality = null; } $newwidth = min($maxwidth, $width); $newheight = min($maxheight, $height); @@ -291,7 +289,8 @@ class qtype_ddimagetoimage extends question_type { $output .= " ".$this->write_files($files, 2)."\n";; foreach ($question->options->drags as $drag) { - $files = $fs->get_area_files($contextid, 'qtype_ddimagetoimage', 'dragimage', $drag->id); + $files = + $fs->get_area_files($contextid, 'qtype_ddimagetoimage', 'dragimage', $drag->id); $output .= " \n"; $output .= " {$drag->no}\n"; $output .= $format->writetext($drag->label, 3)."\n"; diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 18a3c238a04..fb5fe30679c 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -100,7 +100,7 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $dropzones = html_writer::empty_tag('div', array('class'=>'dropzones')); $output .= html_writer::tag('div', $droparea.$dragitems.$dropzones, array('class'=>'ddarea')); - foreach ($question->places as $placeno => $place){ + foreach ($question->places as $placeno => $place) { $varname = $question->field($placeno); list($fieldname, $html) = $this->hidden_field_for_qt_var($qa, $varname); $output .= $html; @@ -115,7 +115,6 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere 'M.qtype_ddimagetoimage.init_question', array($params)); - if ($qa->get_state() == question_state::$invalid) { $output .= html_writer::nonempty_tag('div', $question->get_validation_error($qa->get_last_qt_data()), diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 9453d9273e5..77038e98293 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -123,4 +123,3 @@ form.mform fieldset#previewareaheader .droptarget { form.mform fieldset#previewareaheader div.droparea img { border: 1px solid #000000; } - diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 2f024e7c0bc..32c199795ef 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -1,4 +1,3 @@ - YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var DDIMAGETOIMAGEDDNAME = 'ddimagetoimage_dd'; var DDIMAGETOIMAGE_DD = function() { @@ -16,7 +15,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); } var alldragsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ - //in 'some' loop returning true breaks the loop and is passed as return value from + //in 'some' loop returning true breaks the loop and is passed as return value from //'some' else returns false. Can be though of as equivalent to ||. var done = (dragimagehome.get('complete')); if (waitforimageconstrain) { @@ -141,13 +140,13 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { node: drag, dragMode: 'intersect' }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); - + dd.on('drag:end', function(e) { mainobj.reposition_drags_for_question(); }, this); drag.setData('group', group); drag.setData('choice', choice); - + }, draggable_for_form : function (drag) { var dd = new Y.DD.Drag({ @@ -159,7 +158,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var draginstanceno = dragnode.getData('draginstanceno'); var gooddrop = dragnode.getData('gooddrop'); var endxy; - + if (!gooddrop) { mainobj.reset_drag_xy(draginstanceno); } else { @@ -171,12 +170,12 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var drag = e.target; drag.get('node').setData('gooddrop', false); }, this); - + } - + } }, - + update_padding_sizes_all : function () { for (var groupno = 1; groupno <= 8; groupno++) { this.update_padding_size_for_group(groupno); @@ -238,7 +237,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { this.update_padding_sizes_all(); var i = 0; this.doc.drag_image_homes().each(function(dragimagehome){ - var dragimageno = + var dragimageno = +this.doc.get_classname_numeric_suffix(dragimagehome, 'dragimagehomes'); var choice = +this.doc.get_classname_numeric_suffix(dragimagehome, 'choice'); var group = +this.doc.get_classname_numeric_suffix(dragimagehome, 'group') @@ -272,7 +271,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { }, drop_zone_key_press : function (e) { switch (e.direction) { - case 'next' : + case 'next' : this.place_next_drag_in(e.target); break; case 'previous' : @@ -370,7 +369,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } }, this); }, - get_choices_for_drop : function(choice, drop) { + get_choices_for_drop : function(choice, drop) { var group = drop.getData('group'); var dragimage = null; var dragimages = this.doc.top_node() @@ -379,6 +378,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { }, get_unplaced_choice_for_drop : function(choice, drop) { var dragimages = this.get_choices_for_drop(choice, drop); + var dragimage = null; if (dragimages.some(function (d) { if (!d.hasClass('placed')) { dragimage = d; @@ -386,11 +386,8 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } else { return false; } - })) { - return dragimage; - } else { - return null; - } + })); + return dragimage; }, init_drops : function () { var dropareas = this.doc.top_node().one('div.dropzones'); @@ -424,7 +421,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { }; } }, {NAME : DDIMAGETOIMAGEQUESTIONNAME, ATTRS : {}}); - + Y.Event.define('dragchange', { // Webkit and IE repeat keydown when you hold down arrow keys. // Opera links keypress to page scroll; others keydown. @@ -453,7 +450,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { this, notifier); } }); - M.qtype_ddimagetoimage.init_question = function(config) { + M.qtype_ddimagetoimage.init_question = function(config) { return new DDIMAGETOIMAGE_QUESTION(config); } }, '@VERSION@', { diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 2189d75bfe9..e8b0436bf76 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -17,7 +17,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { this.doc = this.doc_structure(this); this.draw_dd_area(); }, - + draw_dd_area : function() { var bgimageurl = this.fp.file('bgimage').href; this.stop_selector_events(); @@ -25,7 +25,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { if (bgimageurl !== null) { this.doc.load_bg_img(bgimageurl); this.load_drag_homes(); - + var drop = new Y.DD.Drop({ node: this.doc.bg_img() }); @@ -33,9 +33,9 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { drop.on('drop:hit', function(e) { e.drag.get('node').setData('gooddrop', true); }); - + Y.on('windowresize', this.reposition_drags_for_form, this); - + this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); this.doc.drag_image_homes() .on('load', this.constrain_image_size, this, 'dragimage'); @@ -47,7 +47,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { this.setup_form_events(); } }, - + after_all_images_loaded : function () { this.update_padding_sizes_all(); this.update_drag_instances(); @@ -55,7 +55,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { this.set_options_for_drag_image_selectors(); this.setup_form_events(); }, - + constrain_image_size : function (e, imagetype) { var maxsize = this.get('maxsizes')[imagetype]; var reduceby = Math.max(e.target.get('width') / maxsize.width, @@ -66,22 +66,22 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { e.target.addClass('constrained'); e.target.detach('load', this.constrain_image_size); }, - + load_drag_homes : function () { //set up drag items homes - var dragimagesoptions = {0: ''}; + var dragimagesoptions = {0: ''}; for (var i=0; i < this.form.get_form_value('noimages', []); i++) { this.load_drag_home(i); } }, - + load_drag_home : function (dragimageno) { var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).href; - this.doc.add_or_update_drag_image_home(dragimageno, url, + this.doc.add_or_update_drag_image_home(dragimageno, url, this.form.get_form_value('drags', [dragimageno, 'draglabel']), this.form.get_form_value('drags', [dragimageno, 'draggroup'])); }, - + update_drag_instances : function () { //set up drop zones for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { @@ -95,7 +95,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { } }, set_options_for_drag_image_selectors : function () { - var dragimagesoptions = {0: ''}; + var dragimagesoptions = {0: ''}; for (var i=0; i < this.form.get_form_value('noimages', []); i++) { var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); if (file.name !== null) { @@ -130,21 +130,21 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { } } }, - + stop_selector_events : function () { Y.all('fieldset#dropzoneheader select').detachAll(); }, - + setup_form_events : function () { //events triggered by changes to form data - + //x and y coordinates Y.all('fieldset#dropzoneheader input').on('blur', function (e){ var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; this.reposition_drag_for_form(draginstanceno); }, this); - + //change in selected image Y.all('fieldset#dropzoneheader select').on('change', function (e){ var name = e.target.getAttribute('name'); @@ -155,7 +155,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { } this.draw_dd_area(); }, this); - + for (var i=0; i < this.form.get_form_value('noimages', []); i++) { //change to group selector Y.all('fieldset#draggableimageheader_'+i+' select').on('change', function (e){ @@ -171,26 +171,25 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { var name = this.fp.name(e.id); if (name !== 'bgimage') { this.doc.drag_images().remove(true); - } + } this.draw_dd_area(); }, M.form_filepicker, 'callback', this); }, - - + reposition_drags_for_form : function() { this.doc.drag_images().each(function (drag) { var draginstanceno = drag.getData('draginstanceno'); this.reposition_drag_for_form(draginstanceno); }, this); }, - + reposition_drag_for_form : function (draginstanceno) { var drag = this.doc.drag_image(draginstanceno); if (null !== drag) { var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; if (fromform[0] == '' && fromform[1] == '') { - var dragimageno = drag.getData('dragimageno'); + var dragimageno = drag.getData('dragimageno'); drag.setXY(this.doc.drag_image_home(dragimageno).getXY()); } else { var constrainedxy = this.constrain_xy(draginstanceno, fromform); @@ -213,7 +212,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); this.reposition_drag_for_form(draginstanceno); }, - + //make sure xy value is not out of bounds of bg image constrain_xy : function (draginstanceno, bgimgxy) { var drag = this.doc.drag_image(draginstanceno); @@ -229,7 +228,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { return [windowxy[0] - this.doc.bg_img().getX(), windowxy[1] - this.doc.bg_img().getY()]; }, - + /** * Low level operations on form. */ @@ -270,7 +269,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { return toreturn; } }, - + file_pickers : function () { var draftitemidstoname; var nametoparentnode; @@ -301,7 +300,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { } }, {NAME : DDIMAGETOIMAGEFORMNAME, ATTRS : {maxsizes:{value:null}}}); M.qtype_ddimagetoimage = M.qtype_ddimagetoimage || {}; - M.qtype_ddimagetoimage.init_form = function(config) { + M.qtype_ddimagetoimage.init_form = function(config) { return new DDIMAGETOIMAGE_FORM(config); } }, '@VERSION@', { From c1844f5be82e23bf98467a97386465a8bd0e0f98 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 24 Aug 2011 18:30:12 +0700 Subject: [PATCH 074/208] MDL-47494 ddimageortext: NOBUG updating README file with up to date installation instructions. --- question/type/ddimageortext/README.txt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index 6c4605afe54..8812e8a8152 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -6,10 +6,7 @@ to be installed in order to work. This question type was written by Jamie Pratt (http://jamiep.org/). -This question type is compatible with Moodle 2.1+. - -Requires this fix : MDL-28099 -filepicker form element does not work with element names with an index such as image[0] +This question type is compatible with Moodle 2.1. To install using git, type this command in the root of your Moodle install : @@ -19,5 +16,4 @@ Then add question/type/ddimagetoimage to your git ignore. Alternatively, download the zip from https://github.com/jamiepratt/moodle-qtype_ddimagetoimage/zipball/master -unzip it into the question/type folder, and then rename the new folder to -ddimagetoimage. +unzip it into the question/type folder, and then rename the new folder to ddimagetoimage. From dfd89ae5a21cda9a253a33f33e1f0df5890f3527 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 24 Aug 2011 19:48:46 +0700 Subject: [PATCH 075/208] MDL-47494 ddimageortext: NOBUG removed exception as it messes up unit tests where files do not exist and are not needed. --- question/type/ddimageortext/renderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index fb5fe30679c..6f8d585c3c6 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -144,7 +144,7 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere return $url->out(); } } - throw new coding_exception('File not found in filearea '.$filearea); + return null; } protected function hidden_field_for_qt_var(question_attempt $qa, $varname, $value = null) { From 3637ee16866fc6002a968ac543fc20dcbd3ad9f3 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 25 Aug 2011 13:37:38 +0700 Subject: [PATCH 076/208] MDL-47494 ddimageortext: NOBUG implemented question walkthrough unit tests. --- .../simpletest/testwalkthrough.php | 549 ++++++++++-------- 1 file changed, 306 insertions(+), 243 deletions(-) diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index e2e15c2516b..bb6dae2140d 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -38,25 +38,14 @@ require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.ph */ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_base { - protected function get_contains_drop_box_expectation($place, $group, $readonly, - $stateclass = '0') { - $qa = $this->quba->get_question_attempt($this->slot); + protected function get_contains_drag_image_home_expectation($dragimageno, $choice, $group) { + $class = 'group' . $group; + $class .= ' draghome dragimagehomes' . $dragimageno. ' choice'.$choice; - $expectedattrs = array( - 'id' => $qa->get_qt_field_name($place . '_' . $group), - ); - $class = 'slot group' . $group; - if ($readonly) { - $class .= ' readonly'; - } else { - $expectedattrs['tabindex'] = 0; - } - if ($stateclass) { - $class .= ' ' . $stateclass; - } + $expectedattrs = array(); $expectedattrs['class'] = $class; - return new ContainsTagWithAttributes('span', $expectedattrs); + return new ContainsTagWithAttributes('img', $expectedattrs); } public function test_interactive_behaviour() { @@ -68,66 +57,74 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true), ); $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'interactive', 3); + $this->start_attempt_at_question($dd, 'interactive', 12); // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', '0'), + $this->quba->get_field_prefix($this->slot) . 'p4'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), $this->get_no_hint_visible_expectation()); // Save the wrong answer. - $this->process_submission(array('p1' => '2', 'p2' => '2', 'p3' => '2')); - + $this->process_submission(array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1')); // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '2'), + $this->quba->get_field_prefix($this->slot) . 'p1', 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->quba->get_field_prefix($this->slot) . 'p2', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '2'), + $this->quba->get_field_prefix($this->slot) . 'p3', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 1), $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), $this->get_no_hint_visible_expectation()); - // Submit the wrong answer. - $this->process_submission(array('p1' => '2', 'p2' => '2', 'p3' => '2', '-submit' => 1)); + $this->process_submission( + array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1', '-submit' => 1)); // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true), - $this->get_contains_drop_box_expectation('p2', 2, true), - $this->get_contains_drop_box_expectation('p3', 3, true), - $this->get_contains_submit_button_expectation(false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 1), $this->get_contains_try_again_button_expectation(true), - $this->get_does_not_contain_correctness_expectation(), new PatternExpectation('/' . preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), $this->get_contains_hint_expectation('This is the first hint')); @@ -138,17 +135,20 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', '2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->quba->get_field_prefix($this->slot) . 'p2', '1'), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p3', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', '1'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation(), @@ -156,16 +156,25 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->get_no_hint_visible_expectation()); // Submit the right answer. - $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '1', '-submit' => 1)); + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1)); // Verify. $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(2); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_mark(8); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), - $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), - $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', '2'), $this->get_contains_submit_button_expectation(false), $this->get_contains_correct_expectation(), $this->get_no_hint_visible_expectation()); @@ -175,7 +184,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(2); + $this->check_current_mark(8); } public function test_deferred_feedback() { @@ -183,61 +192,68 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Create a drag-and-drop question. $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'deferredfeedback', 3); + $this->start_attempt_at_question($dd, 'deferredfeedback', 12); // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), $this->get_does_not_contain_feedback_expectation()); // Save a partial answer. - $this->process_submission(array('p1' => '1', 'p2' => '2')); - + $this->process_submission(array('p1' => '2', 'p2' => '1')); // Verify. $this->check_current_state(question_state::$invalid); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->quba->get_field_prefix($this->slot) . 'p1', 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->quba->get_field_prefix($this->slot) . 'p2', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); - // Save the right answer. - $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '1')); + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')); // Verify. $this->check_current_state(question_state::$complete); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->quba->get_field_prefix($this->slot) . 'p2', 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '1'), + $this->quba->get_field_prefix($this->slot) . 'p3', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); @@ -246,22 +262,32 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(3); + $this->check_current_mark(12); + $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), - $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), - $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2), $this->get_contains_correct_expectation()); // Change the right answer a bit. - $dd->rightchoices[2] = 2; + $dd->rightchoices[2] = 1; // Check regrading does not mess anything up. $this->quba->regrade_all_questions(); // Verify. $this->check_current_state(question_state::$gradedpartial); - $this->check_current_mark(2); + $this->check_current_mark(9); } public function test_deferred_feedback_unanswered() { @@ -269,43 +295,47 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Create a drag-and-drop question. $dd = test_question_maker::make_question('ddimagetoimage'); $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'deferredfeedback', 3); + $this->start_attempt_at_question($dd, 'deferredfeedback', 12); // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); $this->check_step_count(1); // Save a blank response. - $this->process_submission(array('p1' => '0', 'p2' => '0', 'p3' => '0')); + $this->process_submission(array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => '')); // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1', ''), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2', ''), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); $this->check_step_count(1); @@ -316,11 +346,11 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gaveup); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true), - $this->get_contains_drop_box_expectation('p2', 2, true), - $this->get_contains_drop_box_expectation('p3', 3, true)); + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2)); } public function test_deferred_feedback_partial_answer() { @@ -333,37 +363,41 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); // Save a partial response. - $this->process_submission(array('p1' => '1', 'p2' => '0', 'p3' => '0')); + $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => '')); // Verify. $this->check_current_state(question_state::$invalid); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2', 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); @@ -372,12 +406,12 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedpartial); - $this->check_current_mark(1); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_mark(1.5); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), - $this->get_contains_drop_box_expectation('p2', 2, true, 'incorrect'), - $this->get_contains_drop_box_expectation('p3', 3, true, 'incorrect'), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_partcorrect_expectation()); } @@ -392,24 +426,26 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ FORMAT_MOODLE, true, true), ); $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'interactive', 9); + $this->start_attempt_at_question($dd, 'interactive', 12); // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); $this->assertEqual('interactivecountback', $this->quba->get_question_attempt($this->slot)->get_behaviour_name()); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), @@ -417,16 +453,17 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->get_no_hint_visible_expectation()); // Submit an response with the first two parts right. - $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '2', '-submit' => 1)); + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '2', 'p4' => '1', '-submit' => 1)); // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true), - $this->get_contains_drop_box_expectation('p2', 2, true), - $this->get_contains_drop_box_expectation('p3', 3, true), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), @@ -436,35 +473,41 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->get_contains_num_parts_correct(2), $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->quba->get_field_prefix($this->slot) . 'p2', 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0')); + $this->quba->get_field_prefix($this->slot) . 'p3', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 1)); // Check that extract responses will return the reset data. $prefix = $this->quba->get_field_prefix($this->slot); - $this->assertEqual(array('p1' => '1', 'p2' => '1'), + $this->assertEqual(array('p1' => '1', 'p2' => '2'), $this->quba->extract_responses($this->slot, - array($prefix . 'p1' => '1', $prefix . 'p2' => '1', '-tryagain' => 1))); + array($prefix . 'p1' => '1', $prefix . 'p2' => '2', '-tryagain' => 1))); // Do try again. - $this->process_submission(array('p1' => '1', 'p2' => '1', '-tryagain' => 1)); + // keys p3 and p4 are extra hidden fields to clear data. + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => '', '-tryagain' => 1)); // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->quba->get_field_prefix($this->slot) . 'p2', 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_try_again_button_expectation(), $this->get_does_not_contain_correctness_expectation(), @@ -473,16 +516,17 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->get_no_hint_visible_expectation()); // Submit an response with the first and last parts right. - $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '1', '-submit' => 1)); + $this->process_submission( + array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '2', '-submit' => 1)); // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true), - $this->get_contains_drop_box_expectation('p2', 2, true), - $this->get_contains_drop_box_expectation('p3', 3, true), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), @@ -492,29 +536,34 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->get_contains_num_parts_correct(2), $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '1')); + $this->quba->get_field_prefix($this->slot) . 'p3', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2)); // Do try again. - $this->process_submission(array('p1' => '1', 'p3' => '1', '-tryagain' => 1)); + $this->process_submission( + array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => '2', '-tryagain' => 1)); // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2', ''), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '1'), + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_try_again_button_expectation(), $this->get_does_not_contain_correctness_expectation(), @@ -523,28 +572,31 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->get_no_hint_visible_expectation()); // Submit the right answer. - $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '1', '-submit' => 1)); + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1)); // Verify. $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(6); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_mark(7); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), - $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), - $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2), $this->get_contains_submit_button_expectation(false), $this->get_does_not_contain_try_again_button_expectation(), $this->get_contains_correct_expectation(), $this->get_no_hint_visible_expectation(), $this->get_does_not_contain_num_parts_correct(), - $this->get_contains_standard_correct_combined_feedback_expectation(), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '1')); + $this->get_contains_standard_correct_combined_feedback_expectation()); } public function test_interactive_correct_no_submit() { @@ -563,24 +615,26 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), $this->get_no_hint_visible_expectation()); // Save the right answer. - $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '1')); + $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')); // Finish the attempt without clicking check. $this->quba->finish_all_questions(); @@ -588,11 +642,11 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedright); $this->check_current_mark(3); - $this->expectException(new coding_exception('File not found in filearea bgimage')); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), - $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), - $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_correct_expectation(), $this->get_no_hint_visible_expectation()); @@ -616,29 +670,32 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ FORMAT_MOODLE, true, true), ); $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'interactive', 3); + $this->start_attempt_at_question($dd, 'interactive', 4); // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), $this->get_no_hint_visible_expectation()); // Save the a partially right answer. - $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '2')); + $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '1')); // Finish the attempt without clicking check. $this->quba->finish_all_questions(); @@ -646,11 +703,12 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->check_current_state(question_state::$gradedpartial); $this->check_current_mark(1); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), - $this->get_contains_drop_box_expectation('p2', 2, true, 'incorrect'), - $this->get_contains_drop_box_expectation('p3', 3, true, 'incorrect'), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_partcorrect_expectation(), $this->get_no_hint_visible_expectation()); @@ -677,54 +735,63 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_output( $this->get_contains_marked_out_of_summary(), - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(3), $this->get_no_hint_visible_expectation()); // Save the a completely wrong answer. - $this->process_submission(array('p1' => '2', 'p2' => '2', 'p3' => '2', '-submit' => 1)); + $this->process_submission( + array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1', '-submit' => 1)); // Verify. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); $this->check_current_output( $this->get_contains_marked_out_of_summary(), - $this->get_contains_drop_box_expectation('p1', 1, true), - $this->get_contains_drop_box_expectation('p2', 2, true), - $this->get_contains_drop_box_expectation('p3', 3, true), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_hint_expectation('This is the first hint')); // Do try again. - $this->process_submission(array('p1' => '0', 'p2' => '0', 'p3' => '0', '-tryagain' => 1)); + $this->process_submission( + array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => '', '-tryagain' => 1)); // Check that all the wrong answers have been cleared. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); $this->check_current_output( $this->get_contains_marked_out_of_summary(), - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1', ''), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2', ''), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(2), @@ -740,17 +807,16 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Check the initial state. $this->check_current_state(question_state::$todo); $this->check_current_mark(null); - $this->expectException(new coding_exception('File not found in filearea bgimage')); + $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '0'), + $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '0'), + $this->quba->get_field_prefix($this->slot) . 'p2'), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '0'), + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), $this->get_does_not_contain_feedback_expectation()); // Save a partial answer. @@ -760,9 +826,6 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->check_current_state(question_state::$complete); $this->check_current_mark(null); $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, false), - $this->get_contains_drop_box_expectation('p2', 2, false), - $this->get_contains_drop_box_expectation('p3', 3, false), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', $dd->get_right_choice_for(1)), @@ -772,6 +835,9 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p3', $dd->get_right_choice_for(3)), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', + $dd->get_right_choice_for(4)), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); @@ -780,15 +846,12 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ // Verify. $this->displayoptions->rightanswer = question_display_options::VISIBLE; - $this->assertEqual('{quick} {fox} {lazy}', $dd->get_right_answer_summary()); + $this->assertEqual('Drop zone 1 -> {1. quick} '. + 'Drop zone 2 -> {2. fox} '. + 'Drop zone 3 -> {1. lazy} '. + 'Drop zone 4 -> {2. dog}', + $dd->get_right_answer_summary()); $this->check_current_state(question_state::$gradedright); $this->check_current_mark(3); - $this->check_current_output( - $this->get_contains_drop_box_expectation('p1', 1, true, 'correct'), - $this->get_contains_drop_box_expectation('p2', 2, true, 'correct'), - $this->get_contains_drop_box_expectation('p3', 3, true, 'correct'), - $this->get_contains_correct_expectation(), - new PatternExpectation('/' . - preg_quote('The [quick] brown [fox] jumped over the [lazy] dog.') . '/')); } } From 5a641fe31e533f69ccf184fa7e8aa68231c55d96 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 25 Aug 2011 18:17:13 +0700 Subject: [PATCH 077/208] MDL-47494 ddimageortext: NOBUG change to use id to find form in a way that works with IE7. --- question/type/ddimageortext/yui/form/form.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index e8b0436bf76..28b1ac814f1 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -240,8 +240,12 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { } return indexstring; }, + get_el : function (name, indexes) { + var form = document.getElementById('mform1'); + return form.elements[this.to_name_with_index(name, indexes)] + }, get_form_value : function(name, indexes) { - var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; + var el = this.get_el(name, indexes); if (el.type === 'checkbox') { return el.checked; } else { @@ -249,7 +253,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { } }, set_form_value : function(name, indexes, value) { - var el = document.forms[0].elements[this.to_name_with_index(name, indexes)]; + var el = this.get_el(name, indexes); if (el.type === 'checkbox') { el.checked = value; } else { From 8c2bf1f0d74109e7e7ded1706821f4e6903084bd Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 1 Sep 2011 17:19:24 +0700 Subject: [PATCH 078/208] MDL-47494 ddimageortext: NOBUG wait a little longer for page to settle down after images loaded. This seems to be necessary because after the tinymce editor loads xy coords all change. --- question/type/ddimageortext/yui/dd/dd.js | 2 +- question/type/ddimageortext/yui/form/form.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 32c199795ef..0d21ec45d81 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -38,7 +38,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } else if (this.polltimer === null) { var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; this.polltimer = - Y.later(500, this, this.poll_for_image_load, pollarguments, true); + Y.later(1000, this, this.poll_for_image_load, pollarguments, true); } }, /** diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 28b1ac814f1..039bd633622 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -40,9 +40,9 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { this.doc.drag_image_homes() .on('load', this.constrain_image_size, this, 'dragimage'); this.doc.bg_img().after('load', this.poll_for_image_load, this, - true, 1000, this.after_all_images_loaded); + true, 3000, this.after_all_images_loaded); this.doc.drag_image_homes() .after('load', this.poll_for_image_load, this, - true, 1000, this.after_all_images_loaded); + true, 3000, this.after_all_images_loaded); } else { this.setup_form_events(); } From dd6550e23b3802621e823e0e684b0d3538403751 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 1 Sep 2011 18:07:32 +0700 Subject: [PATCH 079/208] MDL-47494 ddimageortext: NOBUG should say drag images to image not images to images. --- .../type/ddimageortext/lang/en/qtype_ddimagetoimage.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 75ef985e90e..6e85e3aafbb 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -22,20 +22,20 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['addingddimagetoimage'] = 'Adding drag and drop: images onto images'; +$string['addingddimagetoimage'] = 'Adding drag and drop: images onto image'; $string['addmoredropzones'] = 'Blanks for {no} More Drop Zones'; $string['addmoreimages'] = 'Blanks for {no} More Draggable Images'; $string['answer'] = 'Answer'; $string['bgimage'] = 'Background Image'; $string['correctansweris'] = 'The correct answer is: {$a}'; -$string['ddimagetoimage'] = 'Drag and drop: images onto images'; +$string['ddimagetoimage'] = 'Drag and drop: images onto image'; $string['ddimagetoimage_help'] = 'Select a background image file, select draggable images and define the drop zones on the background image to which they must be dragged.'; $string['ddimagetoimagesummary'] = 'Images are dragged and dropped into drop zones on a background image.'; $string['draggableimage'] = 'Draggable image'; $string['draggableimageheader'] = 'Draggable image {$a}'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; -$string['editingddimagetoimage'] = 'Editing drag and drop: images onto images'; +$string['editingddimagetoimage'] = 'Editing drag and drop: images onto image'; $string['formerror_noytop'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; $string['formerror_noxleft'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; $string['formerror_nofile'] = 'Although you selected drag image {$a} as the correct choice for this drop zone you have not selected an image for drag image {$a}.'; From a116cdfa3de63617b44a61e2fea7b311fc65d5ec Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 1 Sep 2011 18:08:21 +0700 Subject: [PATCH 080/208] MDL-47494 ddimageortext: NOBUG refactored backup and restore code so it can be reused by ddwordtoimage --- ...ckup_qtype_ddimagetoimage_plugin.class.php | 16 ++++++------ ...tore_qtype_ddimagetoimage_plugin.class.php | 25 ++++++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php index de8d93da728..1c6a0944db9 100644 --- a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php @@ -31,23 +31,25 @@ defined('MOODLE_INTERNAL') || die(); */ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { + protected $qtype = "ddimagetoimage"; + /** * Returns the qtype information to attach to question element */ protected function define_question_plugin_structure() { - $plugin = $this->get_plugin_element(null, '../../qtype', 'ddimagetoimage'); + $plugin = $this->get_plugin_element(null, '../../qtype', $this->qtype); $pluginwrapper = new backup_nested_element($this->get_recommended_name()); $plugin->add_child($pluginwrapper); - $ddimagetoimages = new backup_nested_element('ddimagetoimage', array('id'), array( + $dds = new backup_nested_element($this->qtype, array('id'), array( 'shuffleanswers', 'correctfeedback', 'correctfeedbackformat', 'partiallycorrectfeedback', 'partiallycorrectfeedbackformat', 'incorrectfeedback', 'incorrectfeedbackformat', 'shownumcorrect')); - $pluginwrapper->add_child($ddimagetoimages); + $pluginwrapper->add_child($dds); $drags = new backup_nested_element('drags'); $drag = new backup_nested_element('drag', array('id'), @@ -57,7 +59,7 @@ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { $drop = new backup_nested_element('drop', array('id'), array('no', 'xleft', 'ytop', 'choice', 'label')); - $ddimagetoimages->set_source_table('qtype_ddimagetoimage', + $dds->set_source_table("qtype_{$this->qtype}", array('questionid' => backup::VAR_PARENTID)); $pluginwrapper->add_child($drags); @@ -65,10 +67,10 @@ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { $pluginwrapper->add_child($drops); $drops->add_child($drop); - $drag->set_source_table('qtype_ddimagetoimage_drags', + $drag->set_source_table("qtype_{$this->qtype}_drags", array('questionid' => backup::VAR_PARENTID)); - $drop->set_source_table('qtype_ddimagetoimage_drops', + $drop->set_source_table("qtype_{$this->qtype}_drops", array('questionid' => backup::VAR_PARENTID)); return $plugin; @@ -87,6 +89,6 @@ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { 'incorrectfeedback' => 'question_created', 'bgimage' => 'question_created', - 'dragimage' => 'qtype_ddimagetoimage_drags'); + 'dragimage' => "qtype_{$this->qtype}_drags"); } } diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php index 7d54ed41861..27433c399ba 100644 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php @@ -32,6 +32,8 @@ defined('MOODLE_INTERNAL') || die(); */ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { + protected $qtype = "ddimagetoimage"; + /** * Returns the paths to be handled by the plugin at question level */ @@ -40,8 +42,8 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { $paths = array(); // Add own qtype stuff - $elename = 'ddimagetoimage'; - $elepath = $this->get_pathfor('/ddimagetoimage'); + $elename = dds; + $elepath = $this->get_pathfor('/'.$this->qtype); $paths[] = new restore_path_element($elename, $elepath); $elename = 'drag'; @@ -56,9 +58,9 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { } /** - * Process the qtype/ddimagetoimage element + * Process the qtype/{qtypename} element */ - public function process_ddimagetoimage($data) { + public function process_dds($data) { global $DB; $data = (object)$data; @@ -75,9 +77,9 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { // Adjust some columns $data->questionid = $newquestionid; // Insert record - $newitemid = $DB->insert_record('qtype_ddimagetoimage', $data); + $newitemid = $DB->insert_record('qtype_'.$this->qtype, $data); // Create mapping (needed for decoding links) - $this->set_mapping('qtype_ddimagetoimage', $oldid, $newitemid); + $this->set_mapping('qtype_'.$this->qtype, $oldid, $newitemid); } } @@ -98,9 +100,9 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { if ($questioncreated) { $data->questionid = $newquestionid; // Insert record - $newitemid = $DB->insert_record('qtype_ddimagetoimage_drags', $data); + $newitemid = $DB->insert_record("qtype_{$this->qtype}_drags", $data); // Create mapping (there are files and states based on this) - $this->set_mapping('qtype_ddimagetoimage_drags', $oldid, $newitemid); + $this->set_mapping("qtype_{$this->qtype}_drags", $oldid, $newitemid); } } @@ -122,10 +124,9 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { if ($questioncreated) { $data->questionid = $newquestionid; // Insert record - $newitemid = $DB->insert_record('qtype_ddimagetoimage_drops', $data); + $newitemid = $DB->insert_record("qtype_{$this->qtype}_drops", $data); // Create mapping (there are files and states based on this) - $this->set_mapping('qtype_ddimagetoimage_drops', $oldid, $newitemid); - + $this->set_mapping("qtype_{$this->qtype}_drops", $oldid, $newitemid); } } /** @@ -137,7 +138,7 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { $fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'); $contents[] = - new restore_decode_content('qtype_ddimagetoimage', $fields, 'question_ddimagetoimage'); + new restore_decode_content('qtype_'.$this->qtype, $fields, 'qtype_'.$this->qtype); return $contents; } From 5445febbc8b4714c9fae832631a9b8ce38732319 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 2 Sep 2011 18:38:08 +0700 Subject: [PATCH 081/208] MDL-47494 ddimageortext: NOBUG fixing an issue with refactoring. --- ...ckup_qtype_ddimagetoimage_plugin.class.php | 19 +++++++------ ...tore_qtype_ddimagetoimage_plugin.class.php | 28 +++++++++++++------ 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php index 1c6a0944db9..dedd031afa0 100644 --- a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php @@ -31,20 +31,22 @@ defined('MOODLE_INTERNAL') || die(); */ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { - protected $qtype = "ddimagetoimage"; + protected static function qtype_name() { + return 'ddimagetoimage'; + } /** * Returns the qtype information to attach to question element */ protected function define_question_plugin_structure() { - - $plugin = $this->get_plugin_element(null, '../../qtype', $this->qtype); + $qtype = self::qtype_name(); + $plugin = $this->get_plugin_element(null, '../../qtype', $qtype); $pluginwrapper = new backup_nested_element($this->get_recommended_name()); $plugin->add_child($pluginwrapper); - $dds = new backup_nested_element($this->qtype, array('id'), array( + $dds = new backup_nested_element($qtype, array('id'), array( 'shuffleanswers', 'correctfeedback', 'correctfeedbackformat', 'partiallycorrectfeedback', 'partiallycorrectfeedbackformat', 'incorrectfeedback', 'incorrectfeedbackformat', 'shownumcorrect')); @@ -59,7 +61,7 @@ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { $drop = new backup_nested_element('drop', array('id'), array('no', 'xleft', 'ytop', 'choice', 'label')); - $dds->set_source_table("qtype_{$this->qtype}", + $dds->set_source_table("qtype_{$qtype}", array('questionid' => backup::VAR_PARENTID)); $pluginwrapper->add_child($drags); @@ -67,10 +69,10 @@ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { $pluginwrapper->add_child($drops); $drops->add_child($drop); - $drag->set_source_table("qtype_{$this->qtype}_drags", + $drag->set_source_table("qtype_{$qtype}_drags", array('questionid' => backup::VAR_PARENTID)); - $drop->set_source_table("qtype_{$this->qtype}_drops", + $drop->set_source_table("qtype_{$qtype}_drops", array('questionid' => backup::VAR_PARENTID)); return $plugin; @@ -83,12 +85,13 @@ class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { * files to be processed both in backup and restore. */ public static function get_qtype_fileareas() { + $qtype = self::qtype_name(); return array( 'correctfeedback' => 'question_created', 'partiallycorrectfeedback' => 'question_created', 'incorrectfeedback' => 'question_created', 'bgimage' => 'question_created', - 'dragimage' => "qtype_{$this->qtype}_drags"); + 'dragimage' => "qtype_{$qtype}_drags"); } } diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php index 27433c399ba..977f4754019 100644 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php @@ -32,7 +32,9 @@ defined('MOODLE_INTERNAL') || die(); */ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { - protected $qtype = "ddimagetoimage"; + protected static function qtype_name() { + return 'ddimagetoimage'; + } /** * Returns the paths to be handled by the plugin at question level @@ -43,7 +45,7 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { // Add own qtype stuff $elename = dds; - $elepath = $this->get_pathfor('/'.$this->qtype); + $elepath = $this->get_pathfor('/'.self::qtype_name()); $paths[] = new restore_path_element($elename, $elepath); $elename = 'drag'; @@ -63,6 +65,8 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { public function process_dds($data) { global $DB; + $prefix = 'qtype_'.self::qtype_name(); + $data = (object)$data; $oldid = $data->id; @@ -77,9 +81,9 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { // Adjust some columns $data->questionid = $newquestionid; // Insert record - $newitemid = $DB->insert_record('qtype_'.$this->qtype, $data); + $newitemid = $DB->insert_record($prefix, $data); // Create mapping (needed for decoding links) - $this->set_mapping('qtype_'.$this->qtype, $oldid, $newitemid); + $this->set_mapping($prefix, $oldid, $newitemid); } } @@ -89,6 +93,8 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { public function process_drag($data) { global $DB; + $prefix = 'qtype_'.self::qtype_name(); + $data = (object)$data; $oldid = $data->id; @@ -100,9 +106,9 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { if ($questioncreated) { $data->questionid = $newquestionid; // Insert record - $newitemid = $DB->insert_record("qtype_{$this->qtype}_drags", $data); + $newitemid = $DB->insert_record("{$prefix}_drags", $data); // Create mapping (there are files and states based on this) - $this->set_mapping("qtype_{$this->qtype}_drags", $oldid, $newitemid); + $this->set_mapping("{$prefix}_drags", $oldid, $newitemid); } } @@ -113,6 +119,8 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { public function process_drop($data) { global $DB; + $prefix = 'qtype_'.self::qtype_name(); + $data = (object)$data; $oldid = $data->id; @@ -124,9 +132,9 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { if ($questioncreated) { $data->questionid = $newquestionid; // Insert record - $newitemid = $DB->insert_record("qtype_{$this->qtype}_drops", $data); + $newitemid = $DB->insert_record("{$prefix}_drops", $data); // Create mapping (there are files and states based on this) - $this->set_mapping("qtype_{$this->qtype}_drops", $oldid, $newitemid); + $this->set_mapping("{$prefix}_drops", $oldid, $newitemid); } } /** @@ -134,11 +142,13 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { */ public static function define_decode_contents() { + $prefix = 'qtype_'.self::qtype_name(); + $contents = array(); $fields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'); $contents[] = - new restore_decode_content('qtype_'.$this->qtype, $fields, 'qtype_'.$this->qtype); + new restore_decode_content($prefix, $fields, $prefix); return $contents; } From 79594d6018f03c22538735c39d061a4eb713870f Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 2 Sep 2011 18:51:32 +0700 Subject: [PATCH 082/208] MDL-47494 ddimageortext: OU-1430 changing from repositioning drags when needed to repositioning every 1/2 second. This solves the problem of being able to detect when html editor has upset the x y coords on a page. --- question/type/ddimageortext/yui/form/form.js | 21 +++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 039bd633622..86ad78e700e 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -10,6 +10,11 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { fp : null, initializer : function(params) { + /*Y.before(function(Y, editorid, options) { + console.log('editor id' + editorid); + options['oninit'] = + return Y.Do.AlterArgs(message, [Y, editorid, options]) + }, M.editor_tinymce, 'init_editor', this);*/ this.fp = this.file_pickers(); Y.one(this.get('topnode')).append('
'+ '
'+ @@ -34,15 +39,16 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { e.drag.get('node').setData('gooddrop', true); }); - Y.on('windowresize', this.reposition_drags_for_form, this); + //Y.on('windowresize', this.reposition_drags_for_form, this); + Y.later(500, this, this.reposition_drags_for_form, [], true); this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); this.doc.drag_image_homes() .on('load', this.constrain_image_size, this, 'dragimage'); this.doc.bg_img().after('load', this.poll_for_image_load, this, - true, 3000, this.after_all_images_loaded); + true, 0, this.after_all_images_loaded); this.doc.drag_image_homes() .after('load', this.poll_for_image_load, this, - true, 3000, this.after_all_images_loaded); + true, 0, this.after_all_images_loaded); } else { this.setup_form_events(); } @@ -142,7 +148,6 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { Y.all('fieldset#dropzoneheader input').on('blur', function (e){ var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; - this.reposition_drag_for_form(draginstanceno); }, this); //change in selected image @@ -164,7 +169,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { }, this); //change to infinite checkbox Y.all('fieldset#draggableimageheader_'+i+' input[type="checkbox"]') - .on('change', this.set_options_for_drag_image_selectors, this); + .on('change', this.set_options_for_drag_image_selectors, this); } //event on file picker new file selection Y.after(function (e){ @@ -185,7 +190,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { reposition_drag_for_form : function (draginstanceno) { var drag = this.doc.drag_image(draginstanceno); - if (null !== drag) { + if (null !== drag && !drag.hasClass('yui3-dd-dragging')) { var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; if (fromform[0] == '' && fromform[1] == '') { @@ -205,12 +210,10 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.floor(xy[0])); this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.floor(xy[1])); - this.reposition_drag_for_form(draginstanceno); }, reset_drag_xy : function (draginstanceno) { this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); - this.reposition_drag_for_form(draginstanceno); }, //make sure xy value is not out of bounds of bg image @@ -308,5 +311,5 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { return new DDIMAGETOIMAGE_FORM(config); } }, '@VERSION@', { - requires:['moodle-qtype_ddimagetoimage-dd', 'form_filepicker'] + requires:['moodle-qtype_ddimagetoimage-dd', 'form_filepicker', 'editor_tinymce'] }); \ No newline at end of file From 1025d075c836d3b8329d32851d8554f34592ba93 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 2 Sep 2011 20:13:05 +0700 Subject: [PATCH 083/208] MDL-47494 ddimageortext: NOBUG noticed that when dragging and dropping drag item was off by 1 pixel in both x and y axis. --- question/type/ddimageortext/yui/dd/dd.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 0d21ec45d81..91d2f2d724c 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -201,8 +201,8 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } }, convert_to_window_xy : function (bgimgxy) { - return [+bgimgxy[0] + this.doc.bg_img().getX() + 1, - +bgimgxy[1] + this.doc.bg_img().getY() + 1]; + return [+bgimgxy[0] + this.doc.bg_img().getX(), + +bgimgxy[1] + this.doc.bg_img().getY()]; } }, { NAME : DDIMAGETOIMAGEDDNAME, From 8d24c8c6f8108ad917c9d29f59171344dc0e7499 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 2 Sep 2011 20:33:52 +0700 Subject: [PATCH 084/208] MDL-47494 ddimageortext: NOBUG removing some commented out code. --- question/type/ddimageortext/yui/form/form.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 86ad78e700e..e0d261bd25b 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -10,11 +10,6 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { fp : null, initializer : function(params) { - /*Y.before(function(Y, editorid, options) { - console.log('editor id' + editorid); - options['oninit'] = - return Y.Do.AlterArgs(message, [Y, editorid, options]) - }, M.editor_tinymce, 'init_editor', this);*/ this.fp = this.file_pickers(); Y.one(this.get('topnode')).append('
'+ '
'+ @@ -39,7 +34,6 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { e.drag.get('node').setData('gooddrop', true); }); - //Y.on('windowresize', this.reposition_drags_for_form, this); Y.later(500, this, this.reposition_drags_for_form, [], true); this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); From 1f82adbe9c067fb77201aa2cc55e478bc205a0cc Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 2 Sep 2011 21:00:42 +0700 Subject: [PATCH 085/208] MDL-47494 ddimageortext: NOBUG using same concept as used in question editing form to reduce delays in repositioning drags. --- question/type/ddimageortext/yui/dd/dd.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 91d2f2d724c..3b5a968a5e2 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -141,9 +141,6 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { dragMode: 'intersect' }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); - dd.on('drag:end', function(e) { - mainobj.reposition_drags_for_question(); - }, this); drag.setData('group', group); drag.setData('choice', choice); @@ -225,12 +222,12 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { Y.extend(DDIMAGETOIMAGE_QUESTION, M.qtype_ddimagetoimage.dd_base_class, { initializer : function(params) { this.doc = this.doc_structure(this); - this.poll_for_image_load(null, false, 1000, this.create_all_drag_and_drops); + this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); this.doc.bg_img().after('load', this.poll_for_image_load, this, - false, 1000, this.create_all_drag_and_drops); + false, 0, this.create_all_drag_and_drops); this.doc.drag_image_homes().after('load', this.poll_for_image_load, this, - false, 1000, this.create_all_drag_and_drops); - Y.on('windowresize', this.reposition_drags_for_question, this); + false, 0, this.create_all_drag_and_drops); + Y.later(500, this, this.reposition_drags_for_question, [], true); }, create_all_drag_and_drops : function () { this.init_drops(); @@ -363,7 +360,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } }, this); this.doc.drag_images().each(function(dragimage) { - if (!dragimage.hasClass('placed')) { + if (!dragimage.hasClass('placed') && !dragimage.hasClass('yui3-dd-dragging')) { var dragimagehome = this.doc.drag_image_home(dragimage.getData('dragimageno')); dragimage.setXY(dragimagehome.getXY()); } @@ -380,7 +377,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var dragimages = this.get_choices_for_drop(choice, drop); var dragimage = null; if (dragimages.some(function (d) { - if (!d.hasClass('placed')) { + if (!d.hasClass('placed') && !d.hasClass('yui3-dd-dragging')) { dragimage = d; return true; } else { From 6ff680a7ad0859ca3c6b0976eadce403b859b8c3 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 2 Sep 2011 21:04:30 +0700 Subject: [PATCH 086/208] MDL-47494 ddimageortext: OU-1443 Correcting spelling mistake. --- question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 6e85e3aafbb..1a938461eec 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -51,7 +51,7 @@ $string['nolabel'] = 'No label text'; $string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, please drag an image to each drop region.'; $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; -$string['previewareamessage'] = '
  • Select a background image file.
  • Select draggable images.
  • And define drop zones by selecting an image that the student must drag to the drop zone and drag it to where the student should drag it too.
'; +$string['previewareamessage'] = '
  • Select a background image file.
  • Select draggable images.
  • And define drop zones by selecting an image that the student must drag to the drop zone and drag it to where the student should drag it to.
'; $string['shuffleimages'] = 'Shuffle Draggable Images'; $string['summarisechoice'] = '{$a->no}. {$a->text}'; $string['summariseplace'] = '{$a->no}. {$a->text}'; From f15a56df11900c556604fd34c8f4c4b052aff2fc Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 2 Sep 2011 21:28:51 +0700 Subject: [PATCH 087/208] MDL-47494 ddimageortext: OU-1441 added a refresh button to reload page and especially preview area. --- question/type/ddimageortext/edit_ddimagetoimage_form.php | 5 +++++ question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php | 2 ++ 2 files changed, 7 insertions(+) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index f21e4d9b114..ef6b3bfed65 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -85,6 +85,11 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { get_string('previewarea', 'qtype_ddimagetoimage'), get_string('previewareamessage', 'qtype_ddimagetoimage')); + $mform->registerNoSubmitButton('refresh'); + $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_ddimagetoimage')); + $mform->addHelpButton('refresh', 'refresh', 'qtype_ddimagetoimage'); + $mform->closeHeaderBefore('refresh'); + list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); $this->definition_drop_zones($mform, $imagerepeats); $mform->addElement('advcheckbox', 'shuffleanswers', ' ', diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 1a938461eec..86cac62e890 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -52,6 +52,8 @@ $string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, ple $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = '
  • Select a background image file.
  • Select draggable images.
  • And define drop zones by selecting an image that the student must drag to the drop zone and drag it to where the student should drag it to.
'; +$string['refresh'] = 'Refresh Preview'; +$string['refresh_help'] = 'You may need to refresh the preview display if you upload a file with the same name as an existing file and choose to overwrite the existing file.'; $string['shuffleimages'] = 'Shuffle Draggable Images'; $string['summarisechoice'] = '{$a->no}. {$a->text}'; $string['summariseplace'] = '{$a->no}. {$a->text}'; From d22736bfe52c751ef0476f0d7127b66a7206b942 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 3 Sep 2011 15:01:29 +0700 Subject: [PATCH 088/208] MDL-47494 ddimageortext: NOBUG problems with IE 9 mean I had to remove this code that checks that coords in the form places drag image on bg image. --- question/type/ddimageortext/yui/form/form.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index e0d261bd25b..f41769fb848 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -34,8 +34,6 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { e.drag.get('node').setData('gooddrop', true); }); - Y.later(500, this, this.reposition_drags_for_form, [], true); - this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); this.doc.drag_image_homes() .on('load', this.constrain_image_size, this, 'dragimage'); @@ -54,6 +52,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { this.reposition_drags_for_form(); this.set_options_for_drag_image_selectors(); this.setup_form_events(); + Y.later(500, this, this.reposition_drags_for_form, [], true); }, constrain_image_size : function (e, imagetype) { @@ -193,10 +192,6 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { } else { var constrainedxy = this.constrain_xy(draginstanceno, fromform); drag.setXY(this.convert_to_window_xy(constrainedxy)); - if (constrainedxy[0] !== +fromform[0] || constrainedxy[1] !== +fromform[1]){ - this.form.set_form_value('drops', [draginstanceno, 'xleft'], constrainedxy[0]); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); - } } } }, From 7643f065d9943aa16856c910b55e99fcd431e612 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 3 Sep 2011 15:21:14 +0700 Subject: [PATCH 089/208] MDL-47494 ddimageortext: OU-1442 unordered lists will not work in many themes / browser combinations inside a form. --- question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 86cac62e890..4c1b54c7311 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -51,7 +51,7 @@ $string['nolabel'] = 'No label text'; $string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, please drag an image to each drop region.'; $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; -$string['previewareamessage'] = '
  • Select a background image file.
  • Select draggable images.
  • And define drop zones by selecting an image that the student must drag to the drop zone and drag it to where the student should drag it to.
'; +$string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable.
Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; $string['refresh'] = 'Refresh Preview'; $string['refresh_help'] = 'You may need to refresh the preview display if you upload a file with the same name as an existing file and choose to overwrite the existing file.'; $string['shuffleimages'] = 'Shuffle Draggable Images'; From 43281f4b2875ced84516ed733c284183f953e8ad Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 6 Sep 2011 17:50:42 +0700 Subject: [PATCH 090/208] MDL-47494 ddimageortext: OU-1442
does not work well in a form field label across browsers and themes. --- question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 4c1b54c7311..3820f4192a1 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -51,7 +51,7 @@ $string['nolabel'] = 'No label text'; $string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, please drag an image to each drop region.'; $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; -$string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable.
Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; +$string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; $string['refresh'] = 'Refresh Preview'; $string['refresh_help'] = 'You may need to refresh the preview display if you upload a file with the same name as an existing file and choose to overwrite the existing file.'; $string['shuffleimages'] = 'Shuffle Draggable Images'; From 50000b74d80433c585549968c6cb453847d4ab79 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 8 Sep 2011 10:35:32 +0700 Subject: [PATCH 091/208] MDL-47494 ddimageortext: NOBUG added and amended code to allow a teacher to create questions with draggable text mixed with images. --- .../edit_ddimagetoimage_form.php | 11 --- question/type/ddimageortext/questiontype.php | 2 +- question/type/ddimageortext/styles.css | 99 +++++-------------- question/type/ddimageortext/yui/dd/dd.js | 36 ++++--- question/type/ddimageortext/yui/form/form.js | 13 ++- 5 files changed, 58 insertions(+), 103 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index ef6b3bfed65..1f9e41e5874 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -337,17 +337,6 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { get_string('formerror_noimageselected', 'qtype_ddimagetoimage'); } } - - } - for ($i=0; $i < $data['noimages']; $i++) { - $labelpresent = (trim($data['drags'][$i]['draglabel']) !== ''); - $infinitechecked = (trim($data['drags'][$i]['infinite']) === '1'); - if (!self::file_uploaded($data['dragitem'][$i])) { - if ($infinitechecked || $labelpresent) { - $errors['dragitem['.($i).']'] = - get_string('formerror_nofile3', 'qtype_ddimagetoimage'); - } - } } return $errors; } diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index e3d7cea2180..b6228424d58 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -155,7 +155,7 @@ class qtype_ddimagetoimage extends question_type { '', 'no, id'); foreach (array_keys($formdata->drags) as $dragno) { $info = file_get_draft_area_info($formdata->dragitem[$dragno]); - if ($info['filecount'] > 0) { + if ($info['filecount'] > 0 || !empty($formdata->drags[$dragno]['draglabel'])) { $draftitemid = $formdata->dragitem[$dragno]; $drag = new stdClass(); diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 77038e98293..d893eef47c6 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -8,46 +8,53 @@ line-height: 2em; } -.que.ddimagetoimage div.droparea img { +.que.ddimagetoimage div.droparea img, form.mform fieldset#previewareaheader div.droparea img { border: 1px solid #000000; } -.que.ddimagetoimage img.draghome { +.que.ddimagetoimage .draghome, form.mform fieldset#previewareaheader .draghome { + vertical-align: top; margin: 5px; visibility : hidden; } -.que.ddimagetoimage span.incorrect { - background-color: #faa; -} -.que.ddimagetoimage span.correct { - background-color: #afa; + +.que.ddimagetoimage div.draghome, form.mform fieldset#previewareaheader div.draghome { + border: 1px solid black; + cursor: move; + background-color: #B0C4DE; + display: -moz-inline-stack; + display:inline-block; + height: auto; + width: auto; + zoom: 1; + *display: inline; } -.que.ddimagetoimage .group1 { +.que.ddimagetoimage .group1, form.mform fieldset#previewareaheader .group1 { background-color: #FFFFFF; } -.que.ddimagetoimage .group2 { +.que.ddimagetoimage .group2, form.mform fieldset#previewareaheader .group2 { background-color: #B0C4DE; } -.que.ddimagetoimage .group3 { +.que.ddimagetoimage .group3, form.mform fieldset#previewareaheader .group3 { background-color: #DCDCDC; } -.que.ddimagetoimage .group4 { +.que.ddimagetoimage .group4, form.mform fieldset#previewareaheader .group4 { background-color: #D8BFD8; } -.que.ddimagetoimage .group5 { +.que.ddimagetoimage .group5, form.mform fieldset#previewareaheader .group5 { background-color: #87CEFA; } -.que.ddimagetoimage .group6 { +.que.ddimagetoimage .group6, form.mform fieldset#previewareaheader .group6 { background-color: #DAA520; } -.que.ddimagetoimage .group7 { +.que.ddimagetoimage .group7, form.mform fieldset#previewareaheader .group7 { background-color: #FFD700; } -.que.ddimagetoimage .group8 { +.que.ddimagetoimage .group8, form.mform fieldset#previewareaheader .group8 { background-color: #F0E68C; } -.que.ddimagetoimage .drag { +.que.ddimagetoimage .drag, form.mform fieldset#previewareaheader .drag { border: 1px solid black; cursor: move; z-index: 2; @@ -55,10 +62,10 @@ .que.ddimagetoimage .dragitems.readonly .drag { cursor: auto; } -.que.ddimagetoimage div.ddarea { +.que.ddimagetoimage div.ddarea, form.mform fieldset#previewareaheader div.ddarea { text-align : center; } -.que.ddimagetoimage .dropbackground { +.que.ddimagetoimage .dropbackground, form.mform fieldset#previewareaheader .dropbackground { margin:0 auto; } .que.ddimagetoimage .dropzone { @@ -67,59 +74,3 @@ z-index: 1; } -.que.ddimagetoimage .droptarget.yui3-dd-drop-over { - background-color: #FFA928; -} - -form.mform fieldset#previewareaheader .group1 { - background-color: #FFFFFF; -} -form.mform fieldset#previewareaheader .group2 { - background-color: #B0C4DE; -} -form.mform fieldset#previewareaheader .group3 { - background-color: #DCDCDC; -} -form.mform fieldset#previewareaheader .group4 { - background-color: #D8BFD8; -} -form.mform fieldset#previewareaheader .group5 { - background-color: #87CEFA; -} -form.mform fieldset#previewareaheader .group6 { - background-color: #DAA520; -} -form.mform fieldset#previewareaheader .group7 { - background-color: #FFD700; -} -form.mform fieldset#previewareaheader .group8 { - background-color: #F0E68C; -} -form.mform fieldset#previewareaheader img.draghome { - margin: 5px; - visibility : hidden; -} -form.mform fieldset#previewareaheader .drag { - border: 1px solid black; - cursor: move; - z-index: 2; -} -form.mform fieldset#previewareaheader .dragitems { - clear:left; -} - - -form.mform fieldset#previewareaheader div.ddarea { - text-align : center; -} -form.mform fieldset#previewareaheader .dropbackground { - margin:0 auto; -} -form.mform fieldset#previewareaheader .droptarget { - border: 1px solid black; - position: absolute; - z-index: 1; -} -form.mform fieldset#previewareaheader div.droparea img { - border: 1px solid #000000; -} diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 3b5a968a5e2..622db858bc7 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -17,6 +17,9 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var alldragsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ //in 'some' loop returning true breaks the loop and is passed as return value from //'some' else returns false. Can be though of as equivalent to ||. + if (dragimagehome.get('tagName') !== 'IMG'){ + return false; + } var done = (dragimagehome.get('complete')); if (waitforimageconstrain) { done = done && dragimagehome.hasClass('constrained'); @@ -53,7 +56,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { return topnode; }, drag_images : function() { - return dragimagesarea.all('img.drag'); + return dragimagesarea.all('.drag'); }, drop_zones : function() { return topnode.all('div.dropzones div.dropzone'); @@ -62,19 +65,19 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { return topnode.all('div.dropzones div.group' + groupno); }, drag_images_cloned_from : function(dragimageno) { - return dragimagesarea.all('img.dragimages'+dragimageno); + return dragimagesarea.all('.dragimages'+dragimageno); }, drag_image : function(draginstanceno) { - return dragimagesarea.one('img.draginstance' + draginstanceno); + return dragimagesarea.one('.draginstance' + draginstanceno); }, drag_images_in_group : function(groupno) { - return dragimagesarea.all('img.drag.group' + groupno); + return dragimagesarea.all('.drag.group' + groupno); }, drag_image_homes : function() { - return dragimagesarea.all('img.draghome'); + return dragimagesarea.all('.draghome'); }, bg_img : function() { - return topnode.one('img.dropbackground'); + return topnode.one('.dropbackground'); }, load_bg_img : function (url) { dropbgarea.setContent(''); @@ -84,24 +87,29 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var oldhome = this.drag_image_home(dragimageno); var classes = 'draghome dragimagehomes'+dragimageno+' group'+group; var imghtml = ''+alt+''; + var divhtml = '
'+alt+'
'; if (oldhome === null) { if (url) { dragimagesarea.append(imghtml); + } else if (alt !== '') { + dragimagesarea.append(divhtml); } } else { if (url) { dragimagesarea.insert(imghtml, oldhome); + } else if (alt !== '') { + dragimagesarea.insert(divhtml, oldhome); } oldhome.remove(true); } - var newlycreated = dragimagesarea.one('img.dragimagehomes'+dragimageno); + var newlycreated = dragimagesarea.one('.dragimagehomes'+dragimageno); if (newlycreated !== null) { newlycreated.setData('groupno', group); newlycreated.setData('dragimageno', dragimageno); } }, drag_image_home : function (dragimageno) { - return dragimagesarea.one('img.dragimagehomes' + dragimageno); + return dragimagesarea.one('.dragimagehomes' + dragimageno); }, get_classname_numeric_suffix : function(node, prefix) { var classes = node.getAttribute('class'); @@ -179,17 +187,17 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } }, update_padding_size_for_group : function (groupno) { - var groupimages = this.doc.top_node().all('img.draghome.group'+groupno); + var groupimages = this.doc.top_node().all('.draghome.group'+groupno); if (groupimages.size() !== 0) { var maxwidth = 0; var maxheight = 0; groupimages.each(function(image){ - maxwidth = Math.max(maxwidth, image.get('width')); - maxheight = Math.max(maxheight, image.get('height')); + maxwidth = Math.max(maxwidth, image.get('clientWidth')); + maxheight = Math.max(maxheight, image.get('clientHeight')); }, this); groupimages.each(function(image) { - var margintopbottom = Math.round((10 + maxheight - image.get('height')) / 2); - var marginleftright = Math.round((10 + maxwidth - image.get('width')) / 2); + var margintopbottom = Math.round((10 + maxheight - image.get('clientHeight')) / 2); + var marginleftright = Math.round((10 + maxwidth - image.get('clientWidth')) / 2); image.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' +margintopbottom+'px '+marginleftright+'px'); }, this); @@ -370,7 +378,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var group = drop.getData('group'); var dragimage = null; var dragimages = this.doc.top_node() - .all('div.dragitemgroup'+group+' img.choice'+choice+'.drag'); + .all('div.dragitemgroup'+group+' .choice'+choice+'.drag'); return dragimages; }, get_unplaced_choice_for_drop : function(choice, drop) { diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index f41769fb848..ce84daf032b 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -68,7 +68,6 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { load_drag_homes : function () { //set up drag items homes - var dragimagesoptions = {0: ''}; for (var i=0; i < this.form.get_form_value('noimages', []); i++) { this.load_drag_home(i); } @@ -97,8 +96,11 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { var dragimagesoptions = {0: ''}; for (var i=0; i < this.form.get_form_value('noimages', []); i++) { var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); + var label = this.form.get_form_value('drags', [i, 'draglabel']); if (file.name !== null) { - dragimagesoptions[i+1] = (i+1)+'. '+file.name; + dragimagesoptions[i+1] = (i+1)+'. '+label+' ('+file.name+')'; + } else if (label != '') { + dragimagesoptions[i+1] = (i+1)+'. '+label; } } for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { @@ -160,6 +162,11 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { this.doc.drag_images().remove(true); this.draw_dd_area(); }, this); + Y.all('fieldset#draggableimageheader_'+i+' input[type="text"]') + .on('blur', function (e){ + this.doc.drag_images().remove(true); + this.draw_dd_area(); + }, this); //change to infinite checkbox Y.all('fieldset#draggableimageheader_'+i+' input[type="checkbox"]') .on('change', this.set_options_for_drag_image_selectors, this); @@ -300,5 +307,5 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { return new DDIMAGETOIMAGE_FORM(config); } }, '@VERSION@', { - requires:['moodle-qtype_ddimagetoimage-dd', 'form_filepicker', 'editor_tinymce'] + requires:['moodle-qtype_ddimagetoimage-dd', 'form_filepicker'] }); \ No newline at end of file From a3be6d9da12cd8a45fb975c5835eb9398da488b4 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 8 Sep 2011 19:22:46 +0700 Subject: [PATCH 092/208] MDL-47494 ddimageortext: NOBUG started making this a mixed question type with draggable text as welll as draggable images. --- .../edit_ddimagetoimage_form.php | 8 ++----- question/type/ddimageortext/renderer.php | 22 +++++++++++++++---- question/type/ddimageortext/yui/dd/dd.js | 2 +- question/type/ddimageortext/yui/form/form.js | 4 ++-- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 1f9e41e5874..7b255359d54 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -276,6 +276,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $PAGE->requires->yui_module('moodle-qtype_ddimagetoimage-form', 'M.qtype_ddimagetoimage.init_form', array($params)); + //$PAGE->requires->css('/lib/yui/3.4.0/build/csscssfonts/fonts-context-min.css'); return $question; } @@ -316,12 +317,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $errors["drops[$i]"] = get_string('formerror_noxleft', 'qtype_ddimagetoimage'); } - if (!self::file_uploaded($data['dragitem'][$choice - 1])) { - $errors["drops[$i]"] = - get_string('formerror_nofile', 'qtype_ddimagetoimage', $choice); - $errors['dragitem['.($choice - 1).']'] = - get_string('formerror_nofile2', 'qtype_ddimagetoimage', $i); - } + if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { $errors["drops[$i]"] = get_string('formerror_multipledraginstance', 'qtype_ddimagetoimage', $choice); diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 6f8d585c3c6..7b23f86a11b 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -37,7 +37,12 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); */ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_renderer { - + public function head_code(question_attempt $qa) { + $this->page->requires->css('/lib/yui/3.4.0/build/csscssfonts/fonts-context-min.css'); + $this->page->requires->yui2_lib('event'); + $this->page->requires->yui2_lib('dragdrop'); + return parent::head_code($qa); + } public function clear_wrong(question_attempt $qa) { $question = $qa->get_question(); $response = $qa->get_last_qt_data(); @@ -84,9 +89,18 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere if ($dragimage->isinfinite) { $classes[] = 'infinite'; } - $dragimagehomesgroup .= html_writer::empty_tag('img', - array('src'=>$dragimageurl, - 'class'=>join(' ', $classes))); + if ($dragimageurl === null) { + $classes[] = 'yui3-cssfonts'; + $dragimagehomesgroup .= html_writer::tag('div', + $dragimage->text, + array('src'=>$dragimageurl, + 'class'=>join(' ', $classes))); + } else { + $dragimagehomesgroup .= html_writer::empty_tag('img', + array('src'=>$dragimageurl, + 'alt' => $dragimage->text, + 'class'=>join(' ', $classes))); + } } $dragimagehomes .= html_writer::tag('div', $dragimagehomesgroup, array('class'=>'dragitemgroup'.$groupno)); diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 622db858bc7..1f45d634df5 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -87,7 +87,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var oldhome = this.drag_image_home(dragimageno); var classes = 'draghome dragimagehomes'+dragimageno+' group'+group; var imghtml = ''+alt+''; - var divhtml = '
'+alt+'
'; + var divhtml = '
'+alt+'
'; if (oldhome === null) { if (url) { dragimagesarea.append(imghtml); diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index ce84daf032b..f68362ec790 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -14,8 +14,8 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { Y.one(this.get('topnode')).append('
'+ '
'+ '
'); - this.doc = this.doc_structure(this); - this.draw_dd_area(); + //this.doc = this.doc_structure(this); + //this.draw_dd_area(); }, draw_dd_area : function() { From 97bb83259f9cce078d66b4bfe4d52d2e8933ff28 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 9 Sep 2011 12:37:03 +0700 Subject: [PATCH 093/208] MDL-47494 ddimageortext: NOBUG hardened code that waits for images loaded before going on. --- .../type/ddimageortext/lang/en/qtype_ddimagetoimage.php | 4 ++-- question/type/ddimageortext/yui/dd/dd.js | 7 ++++++- question/type/ddimageortext/yui/form/form.js | 5 +++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 3820f4192a1..80bb152f8ba 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -31,8 +31,8 @@ $string['correctansweris'] = 'The correct answer is: {$a}'; $string['ddimagetoimage'] = 'Drag and drop: images onto image'; $string['ddimagetoimage_help'] = 'Select a background image file, select draggable images and define the drop zones on the background image to which they must be dragged.'; $string['ddimagetoimagesummary'] = 'Images are dragged and dropped into drop zones on a background image.'; -$string['draggableimage'] = 'Draggable image'; -$string['draggableimageheader'] = 'Draggable image {$a}'; +$string['draggableimage'] = 'Draggable item'; +$string['draggableimageheader'] = 'Draggable item {$a}'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; $string['editingddimagetoimage'] = 'Editing drag and drop: images onto image'; diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 1f45d634df5..56694b92803 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -9,7 +9,11 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { Y.extend(DDIMAGETOIMAGE_DD, Y.Base, { doc : null, polltimer : null, + afterimageloaddone : false, poll_for_image_load : function (e, waitforimageconstrain, pause, doafterwords) { + if (this.afterimageloaddone) { + return; + } var bgdone = this.doc.bg_img().get('complete'); if (waitforimageconstrain) { bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); @@ -26,7 +30,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } return !done; }); - if (alldragsloaded && alldragsloaded) { + if (bgdone && alldragsloaded) { if (this.polltimer !== null) { this.polltimer.cancel(); this.polltimer = null; @@ -38,6 +42,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } else { doafterwords.call(this); } + this.afterimageloaddone = true; } else if (this.polltimer === null) { var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; this.polltimer = diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index f68362ec790..3caeb3503e3 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -14,8 +14,8 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { Y.one(this.get('topnode')).append('
'+ '
'+ '
'); - //this.doc = this.doc_structure(this); - //this.draw_dd_area(); + this.doc = this.doc_structure(this); + this.draw_dd_area(); }, draw_dd_area : function() { @@ -34,6 +34,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { e.drag.get('node').setData('gooddrop', true); }); + this.afterimageloaddone = false; this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); this.doc.drag_image_homes() .on('load', this.constrain_image_size, this, 'dragimage'); From 1a17df84deeff3dceee17f41839bccbf085b9d07 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 9 Sep 2011 15:23:57 +0700 Subject: [PATCH 094/208] MDL-47494 ddimageortext: NOBUG removed help button as it does not work on a submit button anyway. --- question/type/ddimageortext/edit_ddimagetoimage_form.php | 1 - question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php | 1 - 2 files changed, 2 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 7b255359d54..6e47ca905b9 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -87,7 +87,6 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $mform->registerNoSubmitButton('refresh'); $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_ddimagetoimage')); - $mform->addHelpButton('refresh', 'refresh', 'qtype_ddimagetoimage'); $mform->closeHeaderBefore('refresh'); list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 80bb152f8ba..b511a895629 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -53,7 +53,6 @@ $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; $string['refresh'] = 'Refresh Preview'; -$string['refresh_help'] = 'You may need to refresh the preview display if you upload a file with the same name as an existing file and choose to overwrite the existing file.'; $string['shuffleimages'] = 'Shuffle Draggable Images'; $string['summarisechoice'] = '{$a->no}. {$a->text}'; $string['summariseplace'] = '{$a->no}. {$a->text}'; From 42167fc49365540e1ac3003f7d567835d24873ac Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 9 Sep 2011 18:51:50 +0700 Subject: [PATCH 095/208] MDL-47494 ddimageortext: NOBUG added select drag item type selector and js code to hide the filepicker. --- .../edit_ddimagetoimage_form.php | 39 +++++++++++++++---- .../lang/en/qtype_ddimagetoimage.php | 7 +++- question/type/ddimageortext/yui/form/form.js | 26 +++++++++++-- 3 files changed, 58 insertions(+), 14 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index 6e47ca905b9..c6c31ece6f7 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -151,9 +151,9 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $options[$i] = $i; } $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('draggableimage', 'qtype_ddimagetoimage').' '); + get_string('draggableitem', 'qtype_ddimagetoimage').' '); $grouparray[] = $mform->createElement('select', 'choice', - get_string('draggableimage', 'qtype_ddimagetoimage'), $options); + get_string('draggableitem', 'qtype_ddimagetoimage'), $options); $grouparray[] = $mform->createElement('static', '', '', ' ' . get_string('label', 'qtype_ddimagetoimage').' '); $grouparray[] = $mform->createElement('text', 'droplabel', @@ -182,10 +182,16 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { protected function draggable_image($mform) { $draggableimageitem = array(); - $draggableimageitem[] = $mform->createElement('header', 'draggableimageheader', - get_string('draggableimageheader', 'qtype_ddimagetoimage', '{no}')); + $draggableimageitem[] = $mform->createElement('header', 'draggableitemheader', + get_string('draggableitemheader', 'qtype_ddimagetoimage', '{no}')); + $dragitemtypes = array(0 => get_string('draggableimage', 'qtype_ddimagetoimage'), + 1 => get_string('draggableword', 'qtype_ddimagetoimage')); + $draggableimageitem[] = $mform->createElement('select', 'dragitemtype', + get_string('draggableitemtype', 'qtype_ddimagetoimage'), + $dragitemtypes, + array('class' => 'dragitemtype')); $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null, - self::file_picker_options()); + self::file_picker_options()); $grouparray = array(); $grouparray[] = $mform->createElement('text', 'draglabel', @@ -199,7 +205,9 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $grouparray[] = $mform->createElement('static', '', '', ' ' . get_string('group', 'qtype_gapselect').' '); $grouparray[] = $mform->createElement('select', 'draggroup', - get_string('group', 'qtype_gapselect'), $options); + get_string('group', 'qtype_gapselect'), + $options, + array('class' => 'draggroup')); $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ', get_string('infinite', 'qtype_ddimagetoimage')); $draggableimageitem[] = $mform->createElement('group', 'drags', @@ -260,7 +268,22 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { 'dragimage', $itemid, self::file_picker_options()); $question->dragitem[$imageindex] = $draftitemid; } - + if (!empty($question->options)) { + foreach ($question->options->drags as $drag) { + $dragindex = $drag->no -1; + if (!isset($draftitemids[$dragindex])) { + $fileexists = false; + } else { + $fileexists = self::file_uploaded($draftitemids[$dragindex]); + } + $labelexists = $question->drags[$dragindex]['draglabel']; + if ($labelexists && !$fileexists) { + $question->dragitemtype[$dragindex] = 1; + } else { + $question->dragitemtype[$dragindex] = 0; + } + } + } $maxsizes =new stdClass(); $maxsizes->bgimage = new stdClass(); $maxsizes->bgimage->width = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH; @@ -275,7 +298,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $PAGE->requires->yui_module('moodle-qtype_ddimagetoimage-form', 'M.qtype_ddimagetoimage.init_form', array($params)); - //$PAGE->requires->css('/lib/yui/3.4.0/build/csscssfonts/fonts-context-min.css'); + $PAGE->requires->css('/lib/yui/3.2.0/build/cssfonts/fonts-context-min.css'); return $question; } diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index b511a895629..20a0a6882cf 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -31,8 +31,11 @@ $string['correctansweris'] = 'The correct answer is: {$a}'; $string['ddimagetoimage'] = 'Drag and drop: images onto image'; $string['ddimagetoimage_help'] = 'Select a background image file, select draggable images and define the drop zones on the background image to which they must be dragged.'; $string['ddimagetoimagesummary'] = 'Images are dragged and dropped into drop zones on a background image.'; -$string['draggableimage'] = 'Draggable item'; -$string['draggableimageheader'] = 'Draggable item {$a}'; +$string['draggableimage'] = 'Draggable image'; +$string['draggableitem'] = 'Draggable item'; +$string['draggableitemheader'] = 'Draggable item {$a}'; +$string['draggableitemtype'] = 'Type'; +$string['draggableword'] = 'Draggable word'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; $string['editingddimagetoimage'] = 'Editing drag and drop: images onto image'; diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 3caeb3503e3..21a301e6fc7 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -45,6 +45,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { } else { this.setup_form_events(); } + this.update_visibility_of_file_pickers(); }, after_all_images_loaded : function () { @@ -119,7 +120,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { optionnode.set('selected', true); } else { if (value !== 0) { // no image option is always selectable - var cbselector = 'fieldset#draggableimageheader_'+(value-1) + var cbselector = 'fieldset#draggableitemheader_'+(value-1) +' input[type="checkbox"]'; var cbel = Y.one(cbselector); var infinite = cbel.get('checked'); @@ -159,17 +160,22 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { for (var i=0; i < this.form.get_form_value('noimages', []); i++) { //change to group selector - Y.all('fieldset#draggableimageheader_'+i+' select').on('change', function (e){ + Y.all('fieldset#draggableitemheader_'+i+' select.draggroup') + .on('change', function (e){ this.doc.drag_images().remove(true); this.draw_dd_area(); }, this); - Y.all('fieldset#draggableimageheader_'+i+' input[type="text"]') + Y.all('fieldset#draggableitemheader_'+i+' select.dragitemtype') + .on('change', function (e){ + this.update_visibility_of_file_pickers(); + }, this); + Y.all('fieldset#draggableitemheader_'+i+' input[type="text"]') .on('blur', function (e){ this.doc.drag_images().remove(true); this.draw_dd_area(); }, this); //change to infinite checkbox - Y.all('fieldset#draggableimageheader_'+i+' input[type="checkbox"]') + Y.all('fieldset#draggableitemheader_'+i+' input[type="checkbox"]') .on('change', this.set_options_for_drag_image_selectors, this); } //event on file picker new file selection @@ -182,6 +188,18 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { }, M.form_filepicker, 'callback', this); }, + update_visibility_of_file_pickers : function() { + for (var i=0; i < this.form.get_form_value('noimages', []); i++) { + if ('0' === this.form.get_form_value('dragitemtype', [i])) { + Y.one('input#id_dragitem_'+i).get('parentNode').get('parentNode') + .setStyle('display', 'block'); + } else { + Y.one('input#id_dragitem_'+i).get('parentNode').get('parentNode') + .setStyle('display', 'none'); + } + } + }, + reposition_drags_for_form : function() { this.doc.drag_images().each(function (drag) { var draginstanceno = drag.getData('draginstanceno'); From c4d8ad0eda509d7b34c02d3bfed986fc430689c8 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 12 Sep 2011 17:35:39 +0700 Subject: [PATCH 096/208] MDL-47494 ddimageortext: NOBUG continued converting functionality of question type so it can be used with either image or text drag items. --- .../edit_ddimagetoimage_form.php | 50 ++++-- .../lang/en/qtype_ddimagetoimage.php | 9 +- question/type/ddimageortext/questiontype.php | 16 +- question/type/ddimageortext/renderer.php | 2 +- question/type/ddimageortext/yui/dd/dd.js | 144 +++++++++--------- question/type/ddimageortext/yui/form/form.js | 87 ++++++----- 6 files changed, 173 insertions(+), 135 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimagetoimage_form.php index c6c31ece6f7..d42ddf06ed5 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimagetoimage_form.php @@ -33,8 +33,8 @@ defined('MOODLE_INTERNAL') || die(); */ class qtype_ddimagetoimage_edit_form extends question_edit_form { const MAX_GROUPS = 8; - const START_NUM_IMAGES = 6; - const ADD_NUM_IMAGES = 3; + const START_NUM_ITEMS = 6; + const ADD_NUM_ITEMS = 3; public function qtype() { return 'ddimagetoimage'; @@ -61,14 +61,14 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { } } if ($this->question->formoptions->repeatelements) { - $imagerepeatsatstart = max(self::START_NUM_IMAGES, $countimages + self::ADD_NUM_IMAGES); + $imagerepeatsatstart = max(self::START_NUM_ITEMS, $countimages + self::ADD_NUM_ITEMS); } else { $imagerepeatsatstart = $countimages; } $imagerepeats = optional_param('noimages', $imagerepeatsatstart, PARAM_INT); $addfields = optional_param('addimages', '', PARAM_TEXT); if (!empty($addfields)) { - $imagerepeats += self::ADD_NUM_IMAGES; + $imagerepeats += self::ADD_NUM_ITEMS; } return array($imagerepeatsatstart, $imagerepeats); } @@ -116,15 +116,15 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { } } if ($this->question->formoptions->repeatelements) { - $dropzonerepeatsatstart = max(self::START_NUM_IMAGES, - $countdropzones + self::ADD_NUM_IMAGES); + $dropzonerepeatsatstart = max(self::START_NUM_ITEMS, + $countdropzones + self::ADD_NUM_ITEMS); } else { $dropzonerepeatsatstart = $countdropzones; } $this->repeat_elements($this->drop_zone($mform, $imagerepeats), $dropzonerepeatsatstart, $this->drop_zones_repeated_options(), - 'nodropzone', 'adddropzone', self::ADD_NUM_IMAGES, + 'nodropzone', 'adddropzone', self::ADD_NUM_ITEMS, get_string('addmoredropzones', 'qtype_ddimagetoimage')); } @@ -175,7 +175,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $this->repeat_elements($this->draggable_image($mform), $imagerepeatsatstart, $this->draggable_images_repeated_options(), - 'noimages', 'addimages', self::ADD_NUM_IMAGES, + 'noitems', 'additems', self::ADD_NUM_ITEMS, get_string('addmoreimages', 'qtype_ddimagetoimage')); } @@ -184,8 +184,8 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $draggableimageitem[] = $mform->createElement('header', 'draggableitemheader', get_string('draggableitemheader', 'qtype_ddimagetoimage', '{no}')); - $dragitemtypes = array(0 => get_string('draggableimage', 'qtype_ddimagetoimage'), - 1 => get_string('draggableword', 'qtype_ddimagetoimage')); + $dragitemtypes = array('image' => get_string('draggableimage', 'qtype_ddimagetoimage'), + 'word' => get_string('draggableword', 'qtype_ddimagetoimage')); $draggableimageitem[] = $mform->createElement('select', 'dragitemtype', get_string('draggableitemtype', 'qtype_ddimagetoimage'), $dragitemtypes, @@ -271,16 +271,16 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { if (!empty($question->options)) { foreach ($question->options->drags as $drag) { $dragindex = $drag->no -1; - if (!isset($draftitemids[$dragindex])) { + if (!isset($question->dragitem[$dragindex])) { $fileexists = false; } else { - $fileexists = self::file_uploaded($draftitemids[$dragindex]); + $fileexists = self::file_uploaded($question->dragitem[$dragindex]); } $labelexists = $question->drags[$dragindex]['draglabel']; if ($labelexists && !$fileexists) { - $question->dragitemtype[$dragindex] = 1; + $question->dragitemtype[$dragindex] = 'word'; } else { - $question->dragitemtype[$dragindex] = 0; + $question->dragitemtype[$dragindex] = 'image'; } } } @@ -315,7 +315,6 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { return true; } - public function validation($data, $files) { $errors = parent::validation($data, $files); if (!self::file_uploaded($data['bgimage'])) { @@ -340,6 +339,13 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { get_string('formerror_noxleft', 'qtype_ddimagetoimage'); } + if ($data['dragitemtype'][$choice - 1] != 'word' && + !self::file_uploaded($data['dragitem'][$choice - 1])) { + $errors['dragitem['.($choice - 1).']'] = + get_string('formerror_nofile', 'qtype_ddimagetoimage', $i); + } + + if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { $errors["drops[$i]"] = get_string('formerror_multipledraginstance', 'qtype_ddimagetoimage', $choice); @@ -356,6 +362,20 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { } } } + for ($dragindex=0; $dragindex < $data['noitems']; $dragindex++) { + $label = $data['drags'][$dragindex]['draglabel']; + if ($data['dragitemtype'][$dragindex] == 'word') { + $allowedtags = '
'; + $errormessage = get_string('formerror_disallowedtags', 'qtype_ddimagetoimage'); + } else { + $allowedtags = ''; + $errormessage = get_string('formerror_noallowedtags', 'qtype_ddimagetoimage'); + } + if ($label != strip_tags($label, $allowedtags)){ + $errors["drags[{$dragindex}]"] = $errormessage; + } + + } return $errors; } diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php index 20a0a6882cf..94b4b22c350 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php @@ -35,21 +35,22 @@ $string['draggableimage'] = 'Draggable image'; $string['draggableitem'] = 'Draggable item'; $string['draggableitemheader'] = 'Draggable item {$a}'; $string['draggableitemtype'] = 'Type'; -$string['draggableword'] = 'Draggable word'; +$string['draggableword'] = 'Draggable text'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; $string['editingddimagetoimage'] = 'Editing drag and drop: images onto image'; +$string['formerror_disallowedtags'] = 'You have used html tags here that are not allowed in a draggable text drag item type.'; +$string['formerror_noallowedtags'] = 'No html tags are allowed in this text which is the alt text for a draggable image'; $string['formerror_noytop'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; $string['formerror_noxleft'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; -$string['formerror_nofile'] = 'Although you selected drag image {$a} as the correct choice for this drop zone you have not selected an image for drag image {$a}.'; -$string['formerror_nofile2'] = 'You need to select an image file here, this drag item is referred to as the correct answer for drop zone {$a}.'; +$string['formerror_nofile'] = 'You need to upload or select a file to use here.'; $string['formerror_nofile3'] = 'You need to select an image file here, or delete the associated label and uncheck the infinite checkbox.'; $string['formerror_multipledraginstance'] = 'You have selected this image {$a} more than once as the correct choice for a drop zone but it is not marked as being an infinite drag item.'; $string['formerror_multipledraginstance2'] = 'You have selected this image more than once as the correct choice for a drop zone but it is not marked as being an infinite drag item.'; $string['formerror_noimageselected'] = 'You need to select a drag item to be the correct choice for this drop zone.'; $string['formerror_nobgimage'] = 'You need to select an image to use as the background for the drag and drop area.'; $string['infinite'] = 'Infinite'; -$string['label'] = 'Label'; +$string['label'] = 'Text'; $string['nolabel'] = 'No label text'; $string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, please drag an image to each drop region.'; $string['previewarea'] = 'Preview area -'; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index b6228424d58..0da5138b064 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -155,7 +155,7 @@ class qtype_ddimagetoimage extends question_type { '', 'no, id'); foreach (array_keys($formdata->drags) as $dragno) { $info = file_get_draft_area_info($formdata->dragitem[$dragno]); - if ($info['filecount'] > 0 || !empty($formdata->drags[$dragno]['draglabel'])) { + if ($info['filecount'] > 1 || !empty($formdata->drags[$dragno]['draglabel'])) { $draftitemid = $formdata->dragitem[$dragno]; $drag = new stdClass(); @@ -173,13 +173,22 @@ class qtype_ddimagetoimage extends question_type { $drag->id = $DB->insert_record('qtype_ddimagetoimage_drags', $drag); } - self::constrain_image_size_in_draft_area($draftitemid, + if ($formdata->dragitemtype[$dragno] == 'image') { + self::constrain_image_size_in_draft_area($draftitemid, QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH, QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT); - file_save_draft_area_files($draftitemid, $formdata->context->id, + file_save_draft_area_files($draftitemid, $formdata->context->id, 'qtype_ddimagetoimage', 'dragimage', $drag->id, array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); + } else { + //delete any existing files for draggable text item type + $fs = get_file_storage(); + $fs->delete_area_files($formdata->context->id, 'qtype_ddimagetoimage', + 'dragimage', $drag->id); + } + } + } if (!empty($olddragids)) { list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); @@ -194,6 +203,7 @@ class qtype_ddimagetoimage extends question_type { array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); } + public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) { global $USER; $usercontext = get_context_instance(CONTEXT_USER, $USER->id); diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 7b23f86a11b..cebc025988a 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -84,7 +84,7 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere $dragimageurl = self::get_url_for_image($qa, 'dragimage', $dragimage->id); $classes = array("group{$groupno}", 'draghome', - "dragimagehomes{$dragimage->no}", + "dragitemhomes{$dragimage->no}", "choice{$choiceno}"); if ($dragimage->isinfinite) { $classes[] = 'infinite'; diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 56694b92803..caf8fe66c9e 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -18,15 +18,15 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { if (waitforimageconstrain) { bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); } - var alldragsloaded = !this.doc.drag_image_homes().some(function(dragimagehome){ + var alldragsloaded = !this.doc.drag_item_homes().some(function(dragitemhome){ //in 'some' loop returning true breaks the loop and is passed as return value from //'some' else returns false. Can be though of as equivalent to ||. - if (dragimagehome.get('tagName') !== 'IMG'){ + if (dragitemhome.get('tagName') !== 'IMG'){ return false; } - var done = (dragimagehome.get('complete')); + var done = (dragitemhome.get('complete')); if (waitforimageconstrain) { - done = done && dragimagehome.hasClass('constrained'); + done = done && dragitemhome.hasClass('constrained'); } return !done; }); @@ -35,7 +35,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { this.polltimer.cancel(); this.polltimer = null; } - this.doc.drag_image_homes().detach('load', this.poll_for_image_load); + this.doc.drag_item_homes().detach('load', this.poll_for_image_load); this.doc.bg_img().detach('load', this.poll_for_image_load); if (pause !== 0) { Y.later(pause, this, doafterwords); @@ -54,14 +54,14 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { */ doc_structure : function (mainobj) { var topnode = Y.one(this.get('topnode')); - var dragimagesarea = topnode.one('div.dragitems'); + var dragitemsarea = topnode.one('div.dragitems'); var dropbgarea = topnode.one('div.droparea'); return { top_node : function() { return topnode; }, - drag_images : function() { - return dragimagesarea.all('.drag'); + drag_items : function() { + return dragitemsarea.all('.drag'); }, drop_zones : function() { return topnode.all('div.dropzones div.dropzone'); @@ -69,17 +69,17 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { drop_zone_group : function(groupno) { return topnode.all('div.dropzones div.group' + groupno); }, - drag_images_cloned_from : function(dragimageno) { - return dragimagesarea.all('.dragimages'+dragimageno); + drag_items_cloned_from : function(dragitemno) { + return dragitemsarea.all('.dragitems'+dragitemno); }, - drag_image : function(draginstanceno) { - return dragimagesarea.one('.draginstance' + draginstanceno); + drag_item : function(draginstanceno) { + return dragitemsarea.one('.draginstance' + draginstanceno); }, - drag_images_in_group : function(groupno) { - return dragimagesarea.all('.drag.group' + groupno); + drag_items_in_group : function(groupno) { + return dragitemsarea.all('.drag.group' + groupno); }, - drag_image_homes : function() { - return dragimagesarea.all('.draghome'); + drag_item_homes : function() { + return dragitemsarea.all('.draghome'); }, bg_img : function() { return topnode.one('.dropbackground'); @@ -88,33 +88,33 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { dropbgarea.setContent(''); this.bg_img().on('load', this.on_image_load, this, 'bg_image'); }, - add_or_update_drag_image_home : function (dragimageno, url, alt, group) { - var oldhome = this.drag_image_home(dragimageno); - var classes = 'draghome dragimagehomes'+dragimageno+' group'+group; + add_or_update_drag_item_home : function (dragitemno, url, alt, group) { + var oldhome = this.drag_item_home(dragitemno); + var classes = 'draghome dragitemhomes'+dragitemno+' group'+group; var imghtml = ''+alt+''; var divhtml = '
'+alt+'
'; if (oldhome === null) { if (url) { - dragimagesarea.append(imghtml); + dragitemsarea.append(imghtml); } else if (alt !== '') { - dragimagesarea.append(divhtml); + dragitemsarea.append(divhtml); } } else { if (url) { - dragimagesarea.insert(imghtml, oldhome); + dragitemsarea.insert(imghtml, oldhome); } else if (alt !== '') { - dragimagesarea.insert(divhtml, oldhome); + dragitemsarea.insert(divhtml, oldhome); } oldhome.remove(true); } - var newlycreated = dragimagesarea.one('.dragimagehomes'+dragimageno); + var newlycreated = dragitemsarea.one('.dragitemhomes'+dragitemno); if (newlycreated !== null) { newlycreated.setData('groupno', group); - newlycreated.setData('dragimageno', dragimageno); + newlycreated.setData('dragitemno', dragitemno); } }, - drag_image_home : function (dragimageno) { - return dragimagesarea.one('.dragimagehomes' + dragimageno); + drag_item_home : function (dragitemno) { + return dragitemsarea.one('.dragitemhomes' + dragitemno); }, get_classname_numeric_suffix : function(node, prefix) { var classes = node.getAttribute('class'); @@ -131,20 +131,20 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } throw 'Prefix "'+prefix+'" not found in class names.'; }, - clone_new_drag_image : function (draginstanceno, dragimageno) { - var draghome = this.drag_image_home(dragimageno); + clone_new_drag_item : function (draginstanceno, dragitemno) { + var draghome = this.drag_item_home(dragitemno); if (draghome === null) { return null; } var drag = draghome.cloneNode(true); - drag.removeClass('dragimagehomes' + dragimageno); - drag.addClass('dragimages' + dragimageno); + drag.removeClass('dragitemhomes' + dragitemno); + drag.addClass('dragitems' + dragitemno); drag.addClass('draginstance' + draginstanceno); drag.removeClass('draghome'); drag.addClass('drag'); drag.setStyles({'visibility': 'visible', 'position' : 'absolute'}); drag.setData('draginstanceno', draginstanceno); - drag.setData('dragimageno', dragimageno); + drag.setData('dragitemno', dragitemno); draghome.get('parentNode').appendChild(drag); return drag; }, @@ -192,18 +192,18 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } }, update_padding_size_for_group : function (groupno) { - var groupimages = this.doc.top_node().all('.draghome.group'+groupno); - if (groupimages.size() !== 0) { + var groupitems = this.doc.top_node().all('.draghome.group'+groupno); + if (groupitems.size() !== 0) { var maxwidth = 0; var maxheight = 0; - groupimages.each(function(image){ - maxwidth = Math.max(maxwidth, image.get('clientWidth')); - maxheight = Math.max(maxheight, image.get('clientHeight')); + groupitems.each(function(item){ + maxwidth = Math.max(maxwidth, item.get('clientWidth')); + maxheight = Math.max(maxheight, item.get('clientHeight')); }, this); - groupimages.each(function(image) { - var margintopbottom = Math.round((10 + maxheight - image.get('clientHeight')) / 2); - var marginleftright = Math.round((10 + maxwidth - image.get('clientWidth')) / 2); - image.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' + groupitems.each(function(item) { + var margintopbottom = Math.round((10 + maxheight - item.get('clientHeight')) / 2); + var marginleftright = Math.round((10 + maxwidth - item.get('clientWidth')) / 2); + item.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' +margintopbottom+'px '+marginleftright+'px'); }, this); this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, @@ -238,7 +238,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); this.doc.bg_img().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); - this.doc.drag_image_homes().after('load', this.poll_for_image_load, this, + this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); Y.later(500, this, this.reposition_drags_for_question, [], true); }, @@ -246,13 +246,13 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { this.init_drops(); this.update_padding_sizes_all(); var i = 0; - this.doc.drag_image_homes().each(function(dragimagehome){ - var dragimageno = - +this.doc.get_classname_numeric_suffix(dragimagehome, 'dragimagehomes'); - var choice = +this.doc.get_classname_numeric_suffix(dragimagehome, 'choice'); - var group = +this.doc.get_classname_numeric_suffix(dragimagehome, 'group') + this.doc.drag_item_homes().each(function(dragitemhome){ + var dragitemno = + +this.doc.get_classname_numeric_suffix(dragitemhome, 'dragitemhomes'); + var choice = +this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); + var group = +this.doc.get_classname_numeric_suffix(dragitemhome, 'group') var groupsize = this.doc.drop_zone_group(group).size(); - var dragnode = this.doc.clone_new_drag_image(i, dragimageno); + var dragnode = this.doc.clone_new_drag_item(i, dragitemno); i++; if (!this.get('readonly')) { this.doc.draggable_for_question(dragnode, group, choice); @@ -260,7 +260,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { if (dragnode.hasClass('infinite')) { var dragstocreate = groupsize - 1; while (dragstocreate > 0) { - dragnode = this.doc.clone_new_drag_image(i, dragimageno); + dragnode = this.doc.clone_new_drag_item(i, dragitemno); i++; if (!this.get('readonly')) { this.doc.draggable_for_question(dragnode, group, choice); @@ -309,7 +309,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } else { next = 1; var groupno = drop.getData('group'); - this.doc.drag_images_in_group(groupno).each(function(drag) { + this.doc.drag_items_in_group(groupno).each(function(drag) { next = Math.max(next, drag.getData('choice')); }, this); } @@ -346,10 +346,10 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } }, reposition_drags_for_question : function() { - this.doc.drag_images().removeClass('placed'); - this.doc.drag_images().each (function (dragimage) { - if (dragimage.dd !== undefined) { - dragimage.dd.detachAll('drag:start'); + this.doc.drag_items().removeClass('placed'); + this.doc.drag_items().each (function (dragitem) { + if (dragitem.dd !== undefined) { + dragitem.dd.detachAll('drag:start'); } }, this); this.doc.drop_zones().each(function(dropzone) { @@ -359,12 +359,12 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { var input = this.doc.top_node().one(inputcss); var choice = input.get('value'); if (choice !== "") { - var dragimage = this.get_unplaced_choice_for_drop(choice, dropzone); - if (dragimage !== null) { - dragimage.setXY(dropzone.getXY()); - dragimage.addClass('placed'); - if (dragimage.dd !== undefined) { - dragimage.dd.once('drag:start', function (e, input) { + var dragitem = this.get_unplaced_choice_for_drop(choice, dropzone); + if (dragitem !== null) { + dragitem.setXY(dropzone.getXY()); + dragitem.addClass('placed'); + if (dragitem.dd !== undefined) { + dragitem.dd.once('drag:start', function (e, input) { input.set('value', ''); e.target.get('node').removeClass('placed'); },this, input); @@ -372,32 +372,32 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { } } }, this); - this.doc.drag_images().each(function(dragimage) { - if (!dragimage.hasClass('placed') && !dragimage.hasClass('yui3-dd-dragging')) { - var dragimagehome = this.doc.drag_image_home(dragimage.getData('dragimageno')); - dragimage.setXY(dragimagehome.getXY()); + this.doc.drag_items().each(function(dragitem) { + if (!dragitem.hasClass('placed') && !dragitem.hasClass('yui3-dd-dragging')) { + var dragitemhome = this.doc.drag_item_home(dragitem.getData('dragitemno')); + dragitem.setXY(dragitemhome.getXY()); } }, this); }, get_choices_for_drop : function(choice, drop) { var group = drop.getData('group'); - var dragimage = null; - var dragimages = this.doc.top_node() + var dragitem = null; + var dragitems = this.doc.top_node() .all('div.dragitemgroup'+group+' .choice'+choice+'.drag'); - return dragimages; + return dragitems; }, get_unplaced_choice_for_drop : function(choice, drop) { - var dragimages = this.get_choices_for_drop(choice, drop); - var dragimage = null; - if (dragimages.some(function (d) { + var dragitems = this.get_choices_for_drop(choice, drop); + var dragitem = null; + if (dragitems.some(function (d) { if (!d.hasClass('placed') && !d.hasClass('yui3-dd-dragging')) { - dragimage = d; + dragitem = d; return true; } else { return false; } })); - return dragimage; + return dragitem; }, init_drops : function () { var dropareas = this.doc.top_node().one('div.dropzones'); diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 21a301e6fc7..5590e4f4b02 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -21,7 +21,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { draw_dd_area : function() { var bgimageurl = this.fp.file('bgimage').href; this.stop_selector_events(); - this.set_options_for_drag_image_selectors(); + this.set_options_for_drag_item_selectors(); if (bgimageurl !== null) { this.doc.load_bg_img(bgimageurl); this.load_drag_homes(); @@ -36,11 +36,11 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { this.afterimageloaddone = false; this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); - this.doc.drag_image_homes() + this.doc.drag_item_homes() .on('load', this.constrain_image_size, this, 'dragimage'); this.doc.bg_img().after('load', this.poll_for_image_load, this, true, 0, this.after_all_images_loaded); - this.doc.drag_image_homes() .after('load', this.poll_for_image_load, this, + this.doc.drag_item_homes() .after('load', this.poll_for_image_load, this, true, 0, this.after_all_images_loaded); } else { this.setup_form_events(); @@ -52,7 +52,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { this.update_padding_sizes_all(); this.update_drag_instances(); this.reposition_drags_for_form(); - this.set_options_for_drag_image_selectors(); + this.set_options_for_drag_item_selectors(); this.setup_form_events(); Y.later(500, this, this.reposition_drags_for_form, [], true); }, @@ -70,62 +70,68 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { load_drag_homes : function () { //set up drag items homes - for (var i=0; i < this.form.get_form_value('noimages', []); i++) { + for (var i=0; i < this.form.get_form_value('noitems', []); i++) { this.load_drag_home(i); } }, - load_drag_home : function (dragimageno) { - var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragimageno])).href; - this.doc.add_or_update_drag_image_home(dragimageno, url, - this.form.get_form_value('drags', [dragimageno, 'draglabel']), - this.form.get_form_value('drags', [dragimageno, 'draggroup'])); + load_drag_home : function (dragitemno) { + if ('image' === this.form.get_form_value('dragitemtype', [dragitemno])) { + var url = + this.fp.file(this.form.to_name_with_index('dragitem', [dragitemno])).href; + } else { + var url = null; + } + this.doc.add_or_update_drag_item_home(dragitemno, url, + this.form.get_form_value('drags', [dragitemno, 'draglabel']), + this.form.get_form_value('drags', [dragitemno, 'draggroup'])); }, update_drag_instances : function () { //set up drop zones for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { - var dragimageno = this.form.get_form_value('drops', [i, 'choice']); - if (dragimageno !== '0' && (this.doc.drag_image(i) === null)) { - var drag = this.doc.clone_new_drag_image(i, dragimageno - 1); + var dragitemno = this.form.get_form_value('drops', [i, 'choice']); + if (dragitemno !== '0' && (this.doc.drag_item(i) === null)) { + var drag = this.doc.clone_new_drag_item(i, dragitemno - 1); if (drag !== null) { this.doc.draggable_for_form(drag); } } } }, - set_options_for_drag_image_selectors : function () { - var dragimagesoptions = {0: ''}; - for (var i=0; i < this.form.get_form_value('noimages', []); i++) { - var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); + set_options_for_drag_item_selectors : function () { + var dragitemsoptions = {0: ''}; + for (var i=0; i < this.form.get_form_value('noitems', []); i++) { var label = this.form.get_form_value('drags', [i, 'draglabel']); - if (file.name !== null) { - dragimagesoptions[i+1] = (i+1)+'. '+label+' ('+file.name+')'; + var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); + if ('image' === this.form.get_form_value('dragitemtype', [i]) + && file.name !== null) { + dragitemsoptions[i+1] = (i+1)+'. '+label+' ('+file.name+')'; } else if (label != '') { - dragimagesoptions[i+1] = (i+1)+'. '+label; + dragitemsoptions[i+1] = (i+1)+'. '+label; } } for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { var selector = Y.one('#id_drops_'+i+'_choice'); var selectedvalue = selector.get('value'); selector.all('option').remove(true); - for (var value in dragimagesoptions) { + for (var value in dragitemsoptions) { value = +value; var option = ''; selector.append(option); var optionnode = selector.one('option[value="' + value + '"]') if (value === +selectedvalue) { optionnode.set('selected', true); } else { - if (value !== 0) { // no image option is always selectable + if (value !== 0) { // no item option is always selectable var cbselector = 'fieldset#draggableitemheader_'+(value-1) +' input[type="checkbox"]'; var cbel = Y.one(cbselector); var infinite = cbel.get('checked'); if ((!infinite) && - (this.doc.drag_images_cloned_from(value - 1).size() !== 0)) { + (this.doc.drag_items_cloned_from(value - 1).size() !== 0)) { optionnode.set('disabled', true); } } @@ -147,50 +153,51 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { var draginstanceno = this.form.from_name_with_index(name).indexes[0]; }, this); - //change in selected image + //change in selected item Y.all('fieldset#dropzoneheader select').on('change', function (e){ var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; - var old = this.doc.drag_image(draginstanceno); + var old = this.doc.drag_item(draginstanceno); if (old !== null) { old.remove(true); } this.draw_dd_area(); }, this); - for (var i=0; i < this.form.get_form_value('noimages', []); i++) { + for (var i=0; i < this.form.get_form_value('noitems', []); i++) { //change to group selector Y.all('fieldset#draggableitemheader_'+i+' select.draggroup') .on('change', function (e){ - this.doc.drag_images().remove(true); + this.doc.drag_items().remove(true); this.draw_dd_area(); }, this); Y.all('fieldset#draggableitemheader_'+i+' select.dragitemtype') .on('change', function (e){ - this.update_visibility_of_file_pickers(); + this.doc.drag_items().remove(true); + this.draw_dd_area(); }, this); Y.all('fieldset#draggableitemheader_'+i+' input[type="text"]') .on('blur', function (e){ - this.doc.drag_images().remove(true); + this.doc.drag_items().remove(true); this.draw_dd_area(); }, this); //change to infinite checkbox Y.all('fieldset#draggableitemheader_'+i+' input[type="checkbox"]') - .on('change', this.set_options_for_drag_image_selectors, this); + .on('change', this.set_options_for_drag_item_selectors, this); } //event on file picker new file selection Y.after(function (e){ var name = this.fp.name(e.id); if (name !== 'bgimage') { - this.doc.drag_images().remove(true); + this.doc.drag_items().remove(true); } this.draw_dd_area(); }, M.form_filepicker, 'callback', this); }, update_visibility_of_file_pickers : function() { - for (var i=0; i < this.form.get_form_value('noimages', []); i++) { - if ('0' === this.form.get_form_value('dragitemtype', [i])) { + for (var i=0; i < this.form.get_form_value('noitems', []); i++) { + if ('image' === this.form.get_form_value('dragitemtype', [i])) { Y.one('input#id_dragitem_'+i).get('parentNode').get('parentNode') .setStyle('display', 'block'); } else { @@ -201,20 +208,20 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { }, reposition_drags_for_form : function() { - this.doc.drag_images().each(function (drag) { + this.doc.drag_items().each(function (drag) { var draginstanceno = drag.getData('draginstanceno'); this.reposition_drag_for_form(draginstanceno); }, this); }, reposition_drag_for_form : function (draginstanceno) { - var drag = this.doc.drag_image(draginstanceno); + var drag = this.doc.drag_item(draginstanceno); if (null !== drag && !drag.hasClass('yui3-dd-dragging')) { var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; if (fromform[0] == '' && fromform[1] == '') { - var dragimageno = drag.getData('dragimageno'); - drag.setXY(this.doc.drag_image_home(dragimageno).getXY()); + var dragitemno = drag.getData('dragitemno'); + drag.setXY(this.doc.drag_item_home(dragitemno).getXY()); } else { var constrainedxy = this.constrain_xy(draginstanceno, fromform); drag.setXY(this.convert_to_window_xy(constrainedxy)); @@ -233,7 +240,7 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { //make sure xy value is not out of bounds of bg image constrain_xy : function (draginstanceno, bgimgxy) { - var drag = this.doc.drag_image(draginstanceno); + var drag = this.doc.drag_item(draginstanceno); var xleftconstrained = Math.min(bgimgxy[0], this.doc.bg_img().get('width') - drag.get('offsetWidth')); var ytopconstrained = @@ -326,5 +333,5 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { return new DDIMAGETOIMAGE_FORM(config); } }, '@VERSION@', { - requires:['moodle-qtype_ddimagetoimage-dd', 'form_filepicker'] + requires:['node', 'dd', 'dd-drop', 'dd-constrain', 'moodle-qtype_ddimagetoimage-dd', 'form_filepicker'] }); \ No newline at end of file From 31077627c3bce67a93fc719b97b78e5edbb45378 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 12 Sep 2011 18:57:02 +0700 Subject: [PATCH 097/208] MDL-47494 ddimageortext: NOBUG renaming of files and string replacement to change name of question type. --- question/type/ddimageortext/README.txt | 11 ++- ...ckup_qtype_ddimageortext_plugin.class.php} | 6 +- ...tore_qtype_ddimageortext_plugin.class.php} | 8 +- question/type/ddimageortext/db/install.xml | 8 +- ...e_form.php => edit_ddimageortext_form.php} | 92 +++++++++---------- ...agetoimage.php => qtype_ddimageortext.php} | 20 ++-- question/type/ddimageortext/lib.php | 4 +- question/type/ddimageortext/question.php | 20 ++-- question/type/ddimageortext/questiontype.php | 72 +++++++-------- question/type/ddimageortext/renderer.php | 12 +-- .../type/ddimageortext/simpletest/helper.php | 52 +++++------ .../ddimageortext/simpletest/testquestion.php | 46 +++++----- .../simpletest/testquestiontype.php | 12 +-- .../simpletest/testwalkthrough.php | 24 ++--- question/type/ddimageortext/styles.css | 36 ++++---- question/type/ddimageortext/version.php | 2 +- question/type/ddimageortext/yui/dd/dd.js | 30 +++--- question/type/ddimageortext/yui/form/form.js | 20 ++-- 18 files changed, 238 insertions(+), 237 deletions(-) rename question/type/ddimageortext/backup/moodle2/{backup_qtype_ddimagetoimage_plugin.class.php => backup_qtype_ddimageortext_plugin.class.php} (95%) rename question/type/ddimageortext/backup/moodle2/{restore_qtype_ddimagetoimage_plugin.class.php => restore_qtype_ddimageortext_plugin.class.php} (95%) rename question/type/ddimageortext/{edit_ddimagetoimage_form.php => edit_ddimageortext_form.php} (88%) rename question/type/ddimageortext/lang/en/{qtype_ddimagetoimage.php => qtype_ddimageortext.php} (81%) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index 8812e8a8152..b14ea17b18b 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -1,4 +1,5 @@ -A drag-and-drop, images to images question type +A drag-and-drop question type. +You can use text and / or images as drag items onto defined drop zones on a background image. This question type requires that gapselect question type https://github.com/timhunt/moodle-qtype_gapselect/ @@ -10,10 +11,10 @@ This question type is compatible with Moodle 2.1. To install using git, type this command in the root of your Moodle install : -git clone git://github.com/jamiepratt/moodle-qtype_ddimagetoimage.git question/type/ddimagetoimage +git clone git://github.com/jamiepratt/moodle-qtype_ddimageortext.git question/type/ddimageortext -Then add question/type/ddimagetoimage to your git ignore. +Then add question/type/ddimageortext to your git ignore. Alternatively, download the zip from - https://github.com/jamiepratt/moodle-qtype_ddimagetoimage/zipball/master -unzip it into the question/type folder, and then rename the new folder to ddimagetoimage. + https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/master +unzip it into the question/type folder, and then rename the new folder to ddimageortext. diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php similarity index 95% rename from question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php rename to question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php index dedd031afa0..929a2269aa9 100644 --- a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimagetoimage_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php @@ -24,15 +24,15 @@ defined('MOODLE_INTERNAL') || die(); /** - * Provides the information to backup ddimagetoimage questions + * Provides the information to backup ddimageortext questions * * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class backup_qtype_ddimagetoimage_plugin extends backup_qtype_plugin { +class backup_qtype_ddimageortext_plugin extends backup_qtype_plugin { protected static function qtype_name() { - return 'ddimagetoimage'; + return 'ddimageortext'; } /** diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php similarity index 95% rename from question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php rename to question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php index 977f4754019..104a3202b0b 100644 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimagetoimage_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php @@ -25,15 +25,15 @@ defined('MOODLE_INTERNAL') || die(); /** * restore plugin class that provides the necessary information - * needed to restore one ddimagetoimage qtype plugin + * needed to restore one ddimageortext qtype plugin * * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { +class restore_qtype_ddimageortext_plugin extends restore_qtype_plugin { protected static function qtype_name() { - return 'ddimagetoimage'; + return 'ddimageortext'; } /** @@ -76,7 +76,7 @@ class restore_qtype_ddimagetoimage_plugin extends restore_qtype_plugin { $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; // If the question has been created by restore, - // we need to create its qtype_ddimagetoimage too + // we need to create its qtype_ddimageortext too if ($questioncreated) { // Adjust some columns $data->questionid = $newquestionid; diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml index 209aa0a2a08..0f02b0f7fd0 100755 --- a/question/type/ddimageortext/db/install.xml +++ b/question/type/ddimageortext/db/install.xml @@ -1,10 +1,10 @@ - - +
@@ -22,7 +22,7 @@
- +
@@ -37,7 +37,7 @@
- +
diff --git a/question/type/ddimageortext/edit_ddimagetoimage_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php similarity index 88% rename from question/type/ddimageortext/edit_ddimagetoimage_form.php rename to question/type/ddimageortext/edit_ddimageortext_form.php index d42ddf06ed5..dde51bbabe9 100644 --- a/question/type/ddimageortext/edit_ddimagetoimage_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -18,7 +18,7 @@ * Defines the editing form for the drag-and-drop images onto images question type. * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -31,13 +31,13 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_edit_form extends question_edit_form { +class qtype_ddimageortext_edit_form extends question_edit_form { const MAX_GROUPS = 8; const START_NUM_ITEMS = 6; const ADD_NUM_ITEMS = 3; public function qtype() { - return 'ddimagetoimage'; + return 'ddimageortext'; } /** @@ -80,19 +80,19 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { protected function definition_inner($mform) { $mform->addElement('header', 'previewareaheader', - get_string('previewareaheader', 'qtype_ddimagetoimage')); + get_string('previewareaheader', 'qtype_ddimageortext')); $mform->addElement('static', 'previewarea', - get_string('previewarea', 'qtype_ddimagetoimage'), - get_string('previewareamessage', 'qtype_ddimagetoimage')); + get_string('previewarea', 'qtype_ddimageortext'), + get_string('previewareamessage', 'qtype_ddimageortext')); $mform->registerNoSubmitButton('refresh'); - $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_ddimagetoimage')); + $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_ddimageortext')); $mform->closeHeaderBefore('refresh'); list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); $this->definition_drop_zones($mform, $imagerepeats); $mform->addElement('advcheckbox', 'shuffleanswers', ' ', - get_string('shuffleimages', 'qtype_ddimagetoimage')); + get_string('shuffleimages', 'qtype_ddimageortext')); $mform->setDefault('shuffleanswers', 0); $mform->closeHeaderBefore('shuffleanswers'); //add the draggable image fields to the form @@ -104,9 +104,9 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { protected function definition_drop_zones($mform, $imagerepeats) { $mform->addElement('header', 'dropzoneheader', - get_string('dropzoneheader', 'qtype_ddimagetoimage')); + get_string('dropzoneheader', 'qtype_ddimageortext')); - $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimagetoimage'), + $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimageortext'), null, self::file_picker_options()); $countdropzones = 0; @@ -125,7 +125,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $this->repeat_elements($this->drop_zone($mform, $imagerepeats), $dropzonerepeatsatstart, $this->drop_zones_repeated_options(), 'nodropzone', 'adddropzone', self::ADD_NUM_ITEMS, - get_string('addmoredropzones', 'qtype_ddimagetoimage')); + get_string('addmoredropzones', 'qtype_ddimageortext')); } protected function drop_zone($mform, $imagerepeats) { @@ -133,15 +133,15 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $grouparray = array(); $grouparray[] = $mform->createElement('static', 'xleftlabel', '', - ' '.get_string('xleft', 'qtype_ddimagetoimage').' '); + ' '.get_string('xleft', 'qtype_ddimageortext').' '); $grouparray[] = $mform->createElement('text', 'xleft', - get_string('xleft', 'qtype_ddimagetoimage'), + get_string('xleft', 'qtype_ddimageortext'), array('size'=>5, 'class'=>'tweakcss')); $mform->setType('xleft', PARAM_NOTAGS); $grouparray[] = $mform->createElement('static', 'ytoplabel', '', - ' '.get_string('ytop', 'qtype_ddimagetoimage').' '); + ' '.get_string('ytop', 'qtype_ddimageortext').' '); $grouparray[] = $mform->createElement('text', 'ytop', - get_string('ytop', 'qtype_ddimagetoimage'), + get_string('ytop', 'qtype_ddimageortext'), array('size'=>5, 'class'=>'tweakcss')); $mform->setType('ytop', PARAM_NOTAGS); $options = array(); @@ -151,17 +151,17 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $options[$i] = $i; } $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('draggableitem', 'qtype_ddimagetoimage').' '); + get_string('draggableitem', 'qtype_ddimageortext').' '); $grouparray[] = $mform->createElement('select', 'choice', - get_string('draggableitem', 'qtype_ddimagetoimage'), $options); + get_string('draggableitem', 'qtype_ddimageortext'), $options); $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('label', 'qtype_ddimagetoimage').' '); + get_string('label', 'qtype_ddimageortext').' '); $grouparray[] = $mform->createElement('text', 'droplabel', - get_string('label', 'qtype_ddimagetoimage'), + get_string('label', 'qtype_ddimageortext'), array('size'=>10, 'class'=>'tweakcss')); $mform->setType('droplabel', PARAM_NOTAGS); $dropzone = $mform->createElement('group', 'drops', - get_string('dropzone', 'qtype_ddimagetoimage', '{no}'), $grouparray); + get_string('dropzone', 'qtype_ddimageortext', '{no}'), $grouparray); return array($dropzone); } @@ -176,18 +176,18 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $this->repeat_elements($this->draggable_image($mform), $imagerepeatsatstart, $this->draggable_images_repeated_options(), 'noitems', 'additems', self::ADD_NUM_ITEMS, - get_string('addmoreimages', 'qtype_ddimagetoimage')); + get_string('addmoreimages', 'qtype_ddimageortext')); } protected function draggable_image($mform) { $draggableimageitem = array(); $draggableimageitem[] = $mform->createElement('header', 'draggableitemheader', - get_string('draggableitemheader', 'qtype_ddimagetoimage', '{no}')); - $dragitemtypes = array('image' => get_string('draggableimage', 'qtype_ddimagetoimage'), - 'word' => get_string('draggableword', 'qtype_ddimagetoimage')); + get_string('draggableitemheader', 'qtype_ddimageortext', '{no}')); + $dragitemtypes = array('image' => get_string('draggableimage', 'qtype_ddimageortext'), + 'word' => get_string('draggableword', 'qtype_ddimageortext')); $draggableimageitem[] = $mform->createElement('select', 'dragitemtype', - get_string('draggableitemtype', 'qtype_ddimagetoimage'), + get_string('draggableitemtype', 'qtype_ddimageortext'), $dragitemtypes, array('class' => 'dragitemtype')); $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null, @@ -195,7 +195,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $grouparray = array(); $grouparray[] = $mform->createElement('text', 'draglabel', - get_string('label', 'qtype_ddimagetoimage'), + get_string('label', 'qtype_ddimageortext'), array('size'=>30, 'class'=>'tweakcss')); $mform->setType('draglabel', PARAM_NOTAGS); $options = array(); @@ -209,9 +209,9 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $options, array('class' => 'draggroup')); $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ', - get_string('infinite', 'qtype_ddimagetoimage')); + get_string('infinite', 'qtype_ddimageortext')); $draggableimageitem[] = $mform->createElement('group', 'drags', - get_string('label', 'qtype_ddimagetoimage'), $grouparray); + get_string('label', 'qtype_ddimageortext'), $grouparray); return $draggableimageitem; } @@ -252,7 +252,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { //initialise file picker for bgimage $draftitemid = file_get_submitted_draft_itemid('bgimage'); - file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', 'bgimage', !empty($question->id) ? (int) $question->id : null, self::file_picker_options()); $question->bgimage = $draftitemid; @@ -264,7 +264,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; //numbers not allowed in filearea name $itemid = isset($dragids[$imageindex]) ? $dragids[$imageindex] : null; - file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimagetoimage', + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', 'dragimage', $itemid, self::file_picker_options()); $question->dragitem[$imageindex] = $draftitemid; } @@ -286,17 +286,17 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { } $maxsizes =new stdClass(); $maxsizes->bgimage = new stdClass(); - $maxsizes->bgimage->width = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH; - $maxsizes->bgimage->height = QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXHEIGHT; + $maxsizes->bgimage->width = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH; + $maxsizes->bgimage->height = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT; $maxsizes->dragimage = new stdClass(); - $maxsizes->dragimage->width = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH; - $maxsizes->dragimage->height = QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT; + $maxsizes->dragimage->width = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH; + $maxsizes->dragimage->height = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT; $params = array('maxsizes' => $maxsizes, 'topnode' => 'fieldset#previewareaheader'); - $PAGE->requires->yui_module('moodle-qtype_ddimagetoimage-form', - 'M.qtype_ddimagetoimage.init_form', + $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', + 'M.qtype_ddimageortext.init_form', array($params)); $PAGE->requires->css('/lib/yui/3.2.0/build/cssfonts/fonts-context-min.css'); @@ -318,7 +318,7 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { public function validation($data, $files) { $errors = parent::validation($data, $files); if (!self::file_uploaded($data['bgimage'])) { - $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddimagetoimage'); + $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddimageortext'); } $allchoices = array(); @@ -332,33 +332,33 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { if ($imagechoicepresent) { if (!$ytoppresent) { $errors["drops[$i]"] = - get_string('formerror_noytop', 'qtype_ddimagetoimage'); + get_string('formerror_noytop', 'qtype_ddimageortext'); } if (!$xleftpresent) { $errors["drops[$i]"] = - get_string('formerror_noxleft', 'qtype_ddimagetoimage'); + get_string('formerror_noxleft', 'qtype_ddimageortext'); } if ($data['dragitemtype'][$choice - 1] != 'word' && !self::file_uploaded($data['dragitem'][$choice - 1])) { $errors['dragitem['.($choice - 1).']'] = - get_string('formerror_nofile', 'qtype_ddimagetoimage', $i); + get_string('formerror_nofile', 'qtype_ddimageortext', $i); } if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { $errors["drops[$i]"] = - get_string('formerror_multipledraginstance', 'qtype_ddimagetoimage', $choice); + get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); $errors['drops['.($allchoices[$choice]).']'] = - get_string('formerror_multipledraginstance', 'qtype_ddimagetoimage', $choice); + get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); $errors['drags['.($choice-1).']'] = - get_string('formerror_multipledraginstance2', 'qtype_ddimagetoimage', $choice); + get_string('formerror_multipledraginstance2', 'qtype_ddimageortext', $choice); } $allchoices[$choice] = $i; } else { if ($ytoppresent || $xleftpresent || $labelpresent) { $errors["drops[$i]"] = - get_string('formerror_noimageselected', 'qtype_ddimagetoimage'); + get_string('formerror_noimageselected', 'qtype_ddimageortext'); } } } @@ -366,10 +366,10 @@ class qtype_ddimagetoimage_edit_form extends question_edit_form { $label = $data['drags'][$dragindex]['draglabel']; if ($data['dragitemtype'][$dragindex] == 'word') { $allowedtags = '
'; - $errormessage = get_string('formerror_disallowedtags', 'qtype_ddimagetoimage'); + $errormessage = get_string('formerror_disallowedtags', 'qtype_ddimageortext'); } else { $allowedtags = ''; - $errormessage = get_string('formerror_noallowedtags', 'qtype_ddimagetoimage'); + $errormessage = get_string('formerror_noallowedtags', 'qtype_ddimageortext'); } if ($label != strip_tags($label, $allowedtags)){ $errors["drags[{$dragindex}]"] = $errormessage; diff --git a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php similarity index 81% rename from question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php rename to question/type/ddimageortext/lang/en/qtype_ddimageortext.php index 94b4b22c350..b906f89dc21 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimagetoimage.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -17,20 +17,20 @@ /** * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['addingddimagetoimage'] = 'Adding drag and drop: images onto image'; +$string['addingddimageortext'] = 'Adding drag and drop: images or text onto image'; $string['addmoredropzones'] = 'Blanks for {no} More Drop Zones'; -$string['addmoreimages'] = 'Blanks for {no} More Draggable Images'; +$string['addmoreimages'] = 'Blanks for {no} More Draggable Items'; $string['answer'] = 'Answer'; $string['bgimage'] = 'Background Image'; $string['correctansweris'] = 'The correct answer is: {$a}'; -$string['ddimagetoimage'] = 'Drag and drop: images onto image'; -$string['ddimagetoimage_help'] = 'Select a background image file, select draggable images and define the drop zones on the background image to which they must be dragged.'; -$string['ddimagetoimagesummary'] = 'Images are dragged and dropped into drop zones on a background image.'; +$string['ddimageortext'] = 'Drag and drop: images or text onto image'; +$string['ddimageortext_help'] = 'Select a background image file, select draggable images or enter text and define the drop zones on the background image to which they must be dragged.'; +$string['ddimageortextsummary'] = 'Images or text labels are dragged and dropped into drop zones on a background image.'; $string['draggableimage'] = 'Draggable image'; $string['draggableitem'] = 'Draggable item'; $string['draggableitemheader'] = 'Draggable item {$a}'; @@ -38,7 +38,7 @@ $string['draggableitemtype'] = 'Type'; $string['draggableword'] = 'Draggable text'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; -$string['editingddimagetoimage'] = 'Editing drag and drop: images onto image'; +$string['editingddimageortext'] = 'Editing drag and drop: images or text onto image'; $string['formerror_disallowedtags'] = 'You have used html tags here that are not allowed in a draggable text drag item type.'; $string['formerror_noallowedtags'] = 'No html tags are allowed in this text which is the alt text for a draggable image'; $string['formerror_noytop'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; @@ -52,15 +52,15 @@ $string['formerror_nobgimage'] = 'You need to select an image to use as the back $string['infinite'] = 'Infinite'; $string['label'] = 'Text'; $string['nolabel'] = 'No label text'; -$string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, please drag an image to each drop region.'; +$string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, please drag an item to each drop region.'; $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; $string['refresh'] = 'Refresh Preview'; -$string['shuffleimages'] = 'Shuffle Draggable Images'; +$string['shuffleimages'] = 'Shuffle Drag Items Each Time Question Is Attempted'; $string['summarisechoice'] = '{$a->no}. {$a->text}'; $string['summariseplace'] = '{$a->no}. {$a->text}'; -$string['summarisechoiceno'] = 'Image {$a}'; +$string['summarisechoiceno'] = 'Item {$a}'; $string['summariseplaceno'] = 'Drop zone {$a}'; $string['xleft'] = 'Left'; $string['ytop'] = 'Top'; \ No newline at end of file diff --git a/question/type/ddimageortext/lib.php b/question/type/ddimageortext/lib.php index 542f7c46dbc..4863b67da49 100644 --- a/question/type/ddimageortext/lib.php +++ b/question/type/ddimageortext/lib.php @@ -31,9 +31,9 @@ defined('MOODLE_INTERNAL') || die(); /** * Checks file access for essay questions. */ -function qtype_ddimagetoimage_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { +function qtype_ddimageortext_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { global $CFG; require_once($CFG->libdir . '/questionlib.php'); - question_pluginfile($course, $context, 'qtype_ddimagetoimage', + question_pluginfile($course, $context, 'qtype_ddimageortext', $filearea, $args, $forcedownload); } diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 352e6cd2a1d..bebf06d6236 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -18,7 +18,7 @@ * Drag-and-drop words into sentences question definition class. * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -35,7 +35,7 @@ require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { +class qtype_ddimageortext_question extends qtype_gapselect_question_base { public function clear_wrong_from_response(array $response) { foreach ($this->places as $place => $notused) { if (array_key_exists($this->field($place), $response) && @@ -81,7 +81,7 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { } else { $validfilearea = false; } - if ($component == 'qtype_ddimagetoimage' && $validfilearea) { + if ($component == 'qtype_ddimageortext' && $validfilearea) { $question = $qa->get_question(); $itemid = reset($args); if ($filearea == 'bgimage') { @@ -105,7 +105,7 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { if ($this->is_complete_response($response)) { return ''; } - return get_string('pleasedraganimagetoeachdropregion', 'qtype_ddimagetoimage'); + return get_string('pleasedraganimagetoeachdropregion', 'qtype_ddimageortext'); } public function classify_response(array $response) { @@ -166,7 +166,7 @@ class qtype_ddimagetoimage_question extends qtype_gapselect_question_base { * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_drag_item { +class qtype_ddimageortext_drag_item { public $id; public $text; public $no; @@ -186,9 +186,9 @@ class qtype_ddimagetoimage_drag_item { public function summarise() { if (trim($this->text) != '') { - return get_string('summarisechoice', 'qtype_ddimagetoimage', $this); + return get_string('summarisechoice', 'qtype_ddimageortext', $this); } else { - return get_string('summarisechoiceno', 'qtype_ddimagetoimage', $this->no); + return get_string('summarisechoiceno', 'qtype_ddimageortext', $this->no); } } } @@ -198,7 +198,7 @@ class qtype_ddimagetoimage_drag_item { * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_drop_zone { +class qtype_ddimageortext_drop_zone { public $no; public $text; public $group; @@ -214,10 +214,10 @@ class qtype_ddimagetoimage_drop_zone { public function summarise() { if (trim($this->text) != '') { $summariseplace = - get_string('summariseplace', 'qtype_ddimagetoimage', $this); + get_string('summariseplace', 'qtype_ddimageortext', $this); } else { $summariseplace = - get_string('summariseplaceno', 'qtype_ddimagetoimage', $this->no); + get_string('summariseplaceno', 'qtype_ddimageortext', $this->no); } return $summariseplace; } diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 0da5138b064..e025ae76fff 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -18,7 +18,7 @@ * Question type class for the drag-and-drop images onto images question type. * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -31,10 +31,10 @@ require_once($CFG->dirroot . '/question/engine/lib.php'); require_once($CFG->dirroot . '/question/format/xml/format.php'); require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); -define('QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH', 600); -define('QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXHEIGHT', 400); -define('QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH', 150); -define('QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT', 100); +define('QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH', 600); +define('QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT', 400); +define('QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH', 150); +define('QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT', 100); /** * The drag-and-drop words into sentences question type class. @@ -42,7 +42,7 @@ define('QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT', 100); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage extends question_type { +class qtype_ddimageortext extends question_type { protected function choice_group_key() { return 'draggroup'; } @@ -53,22 +53,22 @@ class qtype_ddimagetoimage extends question_type { public function get_question_options($question) { global $DB; - $question->options = $DB->get_record('qtype_ddimagetoimage', + $question->options = $DB->get_record('qtype_ddimageortext', array('questionid' => $question->id), '*', MUST_EXIST); - $question->options->drags = $DB->get_records('qtype_ddimagetoimage_drags', + $question->options->drags = $DB->get_records('qtype_ddimageortext_drags', array('questionid' => $question->id), 'no ASC', '*'); - $question->options->drops = $DB->get_records('qtype_ddimagetoimage_drops', + $question->options->drops = $DB->get_records('qtype_ddimageortext_drops', array('questionid' => $question->id), 'no ASC', '*'); parent::get_question_options($question); } protected function make_choice($dragdata) { - return new qtype_ddimagetoimage_drag_item($dragdata->label, $dragdata->no, + return new qtype_ddimageortext_drag_item($dragdata->label, $dragdata->no, $dragdata->draggroup, $dragdata->infinite, $dragdata->id); } protected function make_place($dropzonedata) { - return new qtype_ddimagetoimage_drop_zone($dropzonedata->label, $dropzonedata->no, + return new qtype_ddimageortext_drop_zone($dropzonedata->label, $dropzonedata->no, $dropzonedata->group, $dropzonedata->xleft, $dropzonedata->ytop); } @@ -119,21 +119,21 @@ class qtype_ddimagetoimage extends question_type { global $DB, $USER; $context = $formdata->context; - $options = $DB->get_record('qtype_ddimagetoimage', array('questionid' => $formdata->id)); + $options = $DB->get_record('qtype_ddimageortext', array('questionid' => $formdata->id)); if (!$options) { $options = new stdClass(); $options->questionid = $formdata->id; $options->correctfeedback = ''; $options->partiallycorrectfeedback = ''; $options->incorrectfeedback = ''; - $options->id = $DB->insert_record('qtype_ddimagetoimage', $options); + $options->id = $DB->insert_record('qtype_ddimageortext', $options); } $options->shuffleanswers = !empty($formdata->shuffleanswers); $options = $this->save_combined_feedback_helper($options, $formdata, $context, true); $this->save_hints($formdata, true); - $DB->update_record('qtype_ddimagetoimage', $options); - $DB->delete_records('qtype_ddimagetoimage_drops', array('questionid' => $formdata->id)); + $DB->update_record('qtype_ddimageortext', $options); + $DB->delete_records('qtype_ddimageortext_drops', array('questionid' => $formdata->id)); foreach (array_keys($formdata->drops) as $dropno) { if ($formdata->drops[$dropno]['choice'] == 0) { continue; @@ -146,11 +146,11 @@ class qtype_ddimagetoimage extends question_type { $drop->choice = $formdata->drops[$dropno]['choice']; $drop->label = $formdata->drops[$dropno]['droplabel']; - $DB->insert_record('qtype_ddimagetoimage_drops', $drop); + $DB->insert_record('qtype_ddimageortext_drops', $drop); } //an array of drag no -> drag id - $olddragids = $DB->get_records_menu('qtype_ddimagetoimage_drags', + $olddragids = $DB->get_records_menu('qtype_ddimageortext_drags', array('questionid' => $formdata->id), '', 'no, id'); foreach (array_keys($formdata->drags) as $dragno) { @@ -168,22 +168,22 @@ class qtype_ddimagetoimage extends question_type { if (isset($olddragids[$dragno +1])) { $drag->id = $olddragids[$dragno +1]; unset($olddragids[$dragno +1]); - $DB->update_record('qtype_ddimagetoimage_drags', $drag); + $DB->update_record('qtype_ddimageortext_drags', $drag); } else { - $drag->id = $DB->insert_record('qtype_ddimagetoimage_drags', $drag); + $drag->id = $DB->insert_record('qtype_ddimageortext_drags', $drag); } if ($formdata->dragitemtype[$dragno] == 'image') { self::constrain_image_size_in_draft_area($draftitemid, - QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXWIDTH, - QTYPE_DDIMAGETOIMAGE_DRAGIMAGE_MAXHEIGHT); + QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH, + QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT); file_save_draft_area_files($draftitemid, $formdata->context->id, - 'qtype_ddimagetoimage', 'dragimage', $drag->id, + 'qtype_ddimageortext', 'dragimage', $drag->id, array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); } else { //delete any existing files for draggable text item type $fs = get_file_storage(); - $fs->delete_area_files($formdata->context->id, 'qtype_ddimagetoimage', + $fs->delete_area_files($formdata->context->id, 'qtype_ddimageortext', 'dragimage', $drag->id); } @@ -192,14 +192,14 @@ class qtype_ddimagetoimage extends question_type { } if (!empty($olddragids)) { list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); - $DB->delete_records_select('qtype_ddimagetoimage_drags', "id $sql", $params); + $DB->delete_records_select('qtype_ddimageortext_drags', "id $sql", $params); } self::constrain_image_size_in_draft_area($formdata->bgimage, - QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXWIDTH, - QTYPE_DDIMAGETOIMAGE_BGIMAGE_MAXHEIGHT); + QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH, + QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT); file_save_draft_area_files($formdata->bgimage, $formdata->context->id, - 'qtype_ddimagetoimage', 'bgimage', $formdata->id, + 'qtype_ddimageortext', 'bgimage', $formdata->id, array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); } @@ -253,12 +253,12 @@ class qtype_ddimagetoimage extends question_type { parent::move_files($questionid, $oldcontextid, $newcontextid); $fs->move_area_files_to_new_context($oldcontextid, - $newcontextid, 'qtype_ddimagetoimage', 'bgimage', $questionid); - $dragids = $DB->get_records_menu('qtype_ddimagetoimage_drags', + $newcontextid, 'qtype_ddimageortext', 'bgimage', $questionid); + $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', array('questionid' => $questionid), 'id', 'id,1'); foreach ($dragids as $dragid => $notused) { $fs->move_area_files_to_new_context($oldcontextid, - $newcontextid, 'qtype_ddimagetoimage', 'dragimage', $dragid); + $newcontextid, 'qtype_ddimageortext', 'dragimage', $dragid); } $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); @@ -276,10 +276,10 @@ class qtype_ddimagetoimage extends question_type { parent::delete_files($questionid, $contextid); - $dragids = $DB->get_records_menu('qtype_ddimagetoimage_drags', + $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', array('questionid' => $questionid), 'id', 'id,1'); foreach ($dragids as $dragid => $notused) { - $fs->delete_area_files($contextid, 'qtype_ddimagetoimage', 'dragimage', $dragid); + $fs->delete_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $dragid); } $this->delete_files_in_combined_feedback($questionid, $contextid); @@ -295,12 +295,12 @@ class qtype_ddimagetoimage extends question_type { } $output .= $format->write_combined_feedback($question->options); $output .= $format->write_hints($question); - $files = $fs->get_area_files($contextid, 'qtype_ddimagetoimage', 'bgimage', $question->id); + $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); $output .= " ".$this->write_files($files, 2)."\n";; foreach ($question->options->drags as $drag) { $files = - $fs->get_area_files($contextid, 'qtype_ddimagetoimage', 'dragimage', $drag->id); + $fs->get_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $drag->id); $output .= " \n"; $output .= " {$drag->no}\n"; $output .= $format->writetext($drag->label, 3)."\n"; @@ -325,12 +325,12 @@ class qtype_ddimagetoimage extends question_type { } public function import_from_xml($data, $question, $format, $extra=null) { - if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimagetoimage') { + if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimageortext') { return false; } $question = $format->import_headers($data); - $question->qtype = 'ddimagetoimage'; + $question->qtype = 'ddimageortext'; $question->shuffleanswers = array_key_exists('shuffleanswers', $format->getpath($data, array('#'), array())); diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index cebc025988a..3e8fb4757ff 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -18,7 +18,7 @@ * Drag-and-drop words into sentences question renderer class. * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -35,7 +35,7 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_renderer { +class qtype_ddimageortext_renderer extends qtype_with_combined_feedback_renderer { public function head_code(question_attempt $qa) { $this->page->requires->css('/lib/yui/3.4.0/build/csscssfonts/fonts-context-min.css'); @@ -125,8 +125,8 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere 'topnode' => $topnode, 'readonly' => $options->readonly); - $PAGE->requires->yui_module('moodle-qtype_ddimagetoimage-dd', - 'M.qtype_ddimagetoimage.init_question', + $PAGE->requires->yui_module('moodle-qtype_ddimageortext-dd', + 'M.qtype_ddimageortext.init_question', array($params)); if ($qa->get_state() == question_state::$invalid) { @@ -145,14 +145,14 @@ class qtype_ddimagetoimage_renderer extends qtype_with_combined_feedback_rendere if ($filearea == 'bgimage') { $itemid = $question->id; } - $draftfiles = $fs->get_area_files($question->contextid, 'qtype_ddimagetoimage', + $draftfiles = $fs->get_area_files($question->contextid, 'qtype_ddimageortext', $filearea, $itemid, 'id'); if ($draftfiles) { foreach ($draftfiles as $file) { if ($file->is_directory()) { continue; } - $url = moodle_url::make_pluginfile_url($question->contextid, 'qtype_ddimagetoimage', + $url = moodle_url::make_pluginfile_url($question->contextid, 'qtype_ddimageortext', $filearea, "$qubaid/$slot/{$itemid}", '/', $file->get_filename()); return $url->out(); diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/simpletest/helper.php index cde426a8105..9fd9961dde6 100755 --- a/question/type/ddimageortext/simpletest/helper.php +++ b/question/type/ddimageortext/simpletest/helper.php @@ -18,7 +18,7 @@ * Test helpers for the drag-and-drop words into sentences question type. * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -33,42 +33,42 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_test_helper extends question_test_helper { +class qtype_ddimageortext_test_helper extends question_test_helper { public function get_test_questions() { return array('fox', 'maths'); } /** - * @return qtype_ddimagetoimage_question + * @return qtype_ddimageortext_question */ - public function make_ddimagetoimage_question_fox() { - question_bank::load_question_definition_classes('ddimagetoimage'); - $dd = new qtype_ddimagetoimage_question(); + public function make_ddimageortext_question_fox() { + question_bank::load_question_definition_classes('ddimageortext'); + $dd = new qtype_ddimageortext_question(); test_question_maker::initialise_a_question($dd); $dd->name = 'Drag-and-drop words into sentences question'; $dd->questiontext = 'The quick brown fox jumped over the lazy dog.'; $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; - $dd->qtype = question_bank::get_qtype('ddimagetoimage'); + $dd->qtype = question_bank::get_qtype('ddimageortext'); $dd->shufflechoices = true; test_question_maker::set_standard_combined_feedback_fields($dd); $dd->choices = $this->make_choice_structure(array( - new qtype_ddimagetoimage_drag_item('quick', 1, 1), - new qtype_ddimagetoimage_drag_item('fox', 2, 1), - new qtype_ddimagetoimage_drag_item('lazy', 1, 2), - new qtype_ddimagetoimage_drag_item('dog', 2, 2) + new qtype_ddimageortext_drag_item('quick', 1, 1), + new qtype_ddimageortext_drag_item('fox', 2, 1), + new qtype_ddimageortext_drag_item('lazy', 1, 2), + new qtype_ddimageortext_drag_item('dog', 2, 2) )); $dd->places = $this->make_place_structure(array( - new qtype_ddimagetoimage_drop_zone('', 1, 1), - new qtype_ddimagetoimage_drop_zone('', 2, 1), - new qtype_ddimagetoimage_drop_zone('', 3, 2), - new qtype_ddimagetoimage_drop_zone('', 4, 2) + new qtype_ddimageortext_drop_zone('', 1, 1), + new qtype_ddimageortext_drop_zone('', 2, 1), + new qtype_ddimageortext_drop_zone('', 3, 2), + new qtype_ddimageortext_drop_zone('', 4, 2) )); $dd->rightchoices = array(1 => 1, 2 => 2, 3 => 1, 4 => 2); @@ -95,11 +95,11 @@ class qtype_ddimagetoimage_test_helper extends question_test_helper { } /** - * @return qtype_ddimagetoimage_question + * @return qtype_ddimageortext_question */ - public function make_ddimagetoimage_question_maths() { - question_bank::load_question_definition_classes('ddimagetoimage'); - $dd = new qtype_ddimagetoimage_question(); + public function make_ddimageortext_question_maths() { + question_bank::load_question_definition_classes('ddimageortext'); + $dd = new qtype_ddimageortext_question(); test_question_maker::initialise_a_question($dd); @@ -107,22 +107,22 @@ class qtype_ddimagetoimage_test_helper extends question_test_helper { $dd->questiontext = 'Fill in the operators to make this equation work: ' . '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3'; $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; - $dd->qtype = question_bank::get_qtype('ddimagetoimage'); + $dd->qtype = question_bank::get_qtype('ddimageortext'); $dd->shufflechoices = true; test_question_maker::set_standard_combined_feedback_fields($dd); $dd->choices = $this->make_choice_structure(array( - new qtype_ddimagetoimage_drag_item('+', 1, 1), - new qtype_ddimagetoimage_drag_item('-', 2, 1) + new qtype_ddimageortext_drag_item('+', 1, 1), + new qtype_ddimageortext_drag_item('-', 2, 1) )); $dd->places = $this->make_place_structure(array( - new qtype_ddimagetoimage_drop_zone('', 1, 1), - new qtype_ddimagetoimage_drop_zone('', 2, 1), - new qtype_ddimagetoimage_drop_zone('', 3, 1), - new qtype_ddimagetoimage_drop_zone('', 4, 1) + new qtype_ddimageortext_drop_zone('', 1, 1), + new qtype_ddimageortext_drop_zone('', 2, 1), + new qtype_ddimageortext_drop_zone('', 3, 1), + new qtype_ddimageortext_drop_zone('', 4, 1) )); $dd->rightchoices = array(1 => 1, 2 => 2, 3 => 1, 4 => 2); diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index 6ddd54b12ab..e0c231138c0 100755 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -18,7 +18,7 @@ * Unit tests for the drag-and-drop words into sentences question definition class. * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); -require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.php'); +require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php'); /** @@ -36,10 +36,10 @@ require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.ph * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_question_test extends UnitTestCase { +class qtype_ddimageortext_question_test extends UnitTestCase { public function test_get_question_summary() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $this->assertEqual('The quick brown fox jumped over the lazy dog.; '. '[[Drop zone 1]] -> {1. quick / 2. fox}; '. '[[Drop zone 2]] -> {1. quick / 2. fox}; '. @@ -49,7 +49,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_get_question_summary_maths() { - $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); + $dd = test_question_maker::make_question('ddimageortext', 'maths'); $this->assertEqual('Fill in the operators to make this equation work: '. '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3; '. '[[Drop zone 1]] -> {1. + / 2. -}; '. @@ -60,7 +60,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_summarise_response() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -72,7 +72,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_summarise_response_maths() { - $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); + $dd = test_question_maker::make_question('ddimageortext', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -84,17 +84,17 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_get_random_guess_score() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $this->assertEqual(0.5, $dd->get_random_guess_score()); } public function test_get_random_guess_score_maths() { - $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); + $dd = test_question_maker::make_question('ddimageortext', 'maths'); $this->assertEqual(0.5, $dd->get_random_guess_score()); } public function test_get_right_choice_for() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -103,7 +103,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_get_right_choice_for_maths() { - $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); + $dd = test_question_maker::make_question('ddimageortext', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -114,7 +114,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_clear_wrong_from_response() { - $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); + $dd = test_question_maker::make_question('ddimageortext', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -124,7 +124,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_get_num_parts_right() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -135,7 +135,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_get_num_parts_right_maths() { - $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); + $dd = test_question_maker::make_question('ddimageortext', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -145,7 +145,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_get_expected_data() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->start_attempt(new question_attempt_step(), 1); $this->assertEqual( @@ -155,7 +155,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_get_correct_response() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -164,7 +164,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_get_correct_response_maths() { - $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); + $dd = test_question_maker::make_question('ddimageortext', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -173,7 +173,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_is_same_response() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->start_attempt(new question_attempt_step(), 1); $this->assertTrue($dd->is_same_response( @@ -197,7 +197,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { array('p1' => '1', 'p2' => '2', 'p3' => '2', 'p4' => '4'))); } public function test_is_complete_response() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->start_attempt(new question_attempt_step(), 1); $this->assertFalse($dd->is_complete_response(array())); @@ -209,7 +209,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_is_gradable_response() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->start_attempt(new question_attempt_step(), 1); $this->assertFalse($dd->is_gradable_response(array())); @@ -223,7 +223,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_grading() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -236,7 +236,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_grading_maths() { - $dd = test_question_maker::make_question('ddimagetoimage', 'maths'); + $dd = test_question_maker::make_question('ddimageortext', 'maths'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); @@ -249,7 +249,7 @@ class qtype_ddimagetoimage_question_test extends UnitTestCase { } public function test_classify_response() { - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index 72d7a387b34..9f2e1e853b0 100755 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -18,7 +18,7 @@ * Unit tests for the drag-and-drop words into sentences question definition class. * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); -require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.php'); +require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php'); /** @@ -36,12 +36,12 @@ require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.ph * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_test extends UnitTestCase { - /** @var qtype_ddimagetoimage instance of the question type class to test. */ +class qtype_ddimageortext_test extends UnitTestCase { + /** @var qtype_ddimageortext instance of the question type class to test. */ protected $qtype; public function setUp() { - $this->qtype = question_bank::get_qtype('ddimagetoimage');; + $this->qtype = question_bank::get_qtype('ddimageortext');; } public function tearDown() { @@ -49,7 +49,7 @@ class qtype_ddimagetoimage_test extends UnitTestCase { } public function test_name() { - $this->assertEqual($this->qtype->name(), 'ddimagetoimage'); + $this->assertEqual($this->qtype->name(), 'ddimageortext'); } public function test_can_analyse_responses() { diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index bb6dae2140d..6bfa468db01 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -18,7 +18,7 @@ * Unit tests for the drag-and-drop words into sentences question type. * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); -require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.php'); +require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php'); /** @@ -36,7 +36,7 @@ require_once($CFG->dirroot . '/question/type/ddimagetoimage/simpletest/helper.ph * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_base { +class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_base { protected function get_contains_drag_image_home_expectation($dragimageno, $choice, $group) { $class = 'group' . $group; @@ -51,7 +51,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ public function test_interactive_behaviour() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->hints = array( new question_hint_with_parts(13, 'This is the first hint.', FORMAT_HTML, false, false), new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true), @@ -190,7 +190,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ public function test_deferred_feedback() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'deferredfeedback', 12); @@ -293,7 +293,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ public function test_deferred_feedback_unanswered() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'deferredfeedback', 12); @@ -356,7 +356,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ public function test_deferred_feedback_partial_answer() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->shufflechoices = false; $this->start_attempt_at_question($dd, 'deferredfeedback', 3); @@ -418,7 +418,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ public function test_interactive_grading() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->hints = array( new question_hint_with_parts(1, 'This is the first hint.', FORMAT_MOODLE, true, true), @@ -602,7 +602,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ public function test_interactive_correct_no_submit() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->hints = array( new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), @@ -662,7 +662,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ public function test_interactive_partial_no_submit() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->hints = array( new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, false), @@ -724,7 +724,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ public function test_interactive_no_right_clears() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $dd->hints = array( new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, true), new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), @@ -801,7 +801,7 @@ class qtype_ddimagetoimage_walkthrough_test extends qbehaviour_walkthrough_test_ public function test_display_of_right_answer_when_shuffled() { // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimagetoimage'); + $dd = test_question_maker::make_question('ddimageortext'); $this->start_attempt_at_question($dd, 'deferredfeedback', 3); // Check the initial state. diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index d893eef47c6..db7d5ad6223 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -1,24 +1,24 @@ -.que.ddimagetoimage .qtext { +.que.ddimageortext .qtext { line-height: 2em; margin-bottom: 0.5em; display: block; } -.que.ddimagetoimage .qtext * { +.que.ddimageortext .qtext * { line-height: 2em; } -.que.ddimagetoimage div.droparea img, form.mform fieldset#previewareaheader div.droparea img { +.que.ddimageortext div.droparea img, form.mform fieldset#previewareaheader div.droparea img { border: 1px solid #000000; } -.que.ddimagetoimage .draghome, form.mform fieldset#previewareaheader .draghome { +.que.ddimageortext .draghome, form.mform fieldset#previewareaheader .draghome { vertical-align: top; margin: 5px; visibility : hidden; } -.que.ddimagetoimage div.draghome, form.mform fieldset#previewareaheader div.draghome { +.que.ddimageortext div.draghome, form.mform fieldset#previewareaheader div.draghome { border: 1px solid black; cursor: move; background-color: #B0C4DE; @@ -30,45 +30,45 @@ *display: inline; } -.que.ddimagetoimage .group1, form.mform fieldset#previewareaheader .group1 { +.que.ddimageortext .group1, form.mform fieldset#previewareaheader .group1 { background-color: #FFFFFF; } -.que.ddimagetoimage .group2, form.mform fieldset#previewareaheader .group2 { +.que.ddimageortext .group2, form.mform fieldset#previewareaheader .group2 { background-color: #B0C4DE; } -.que.ddimagetoimage .group3, form.mform fieldset#previewareaheader .group3 { +.que.ddimageortext .group3, form.mform fieldset#previewareaheader .group3 { background-color: #DCDCDC; } -.que.ddimagetoimage .group4, form.mform fieldset#previewareaheader .group4 { +.que.ddimageortext .group4, form.mform fieldset#previewareaheader .group4 { background-color: #D8BFD8; } -.que.ddimagetoimage .group5, form.mform fieldset#previewareaheader .group5 { +.que.ddimageortext .group5, form.mform fieldset#previewareaheader .group5 { background-color: #87CEFA; } -.que.ddimagetoimage .group6, form.mform fieldset#previewareaheader .group6 { +.que.ddimageortext .group6, form.mform fieldset#previewareaheader .group6 { background-color: #DAA520; } -.que.ddimagetoimage .group7, form.mform fieldset#previewareaheader .group7 { +.que.ddimageortext .group7, form.mform fieldset#previewareaheader .group7 { background-color: #FFD700; } -.que.ddimagetoimage .group8, form.mform fieldset#previewareaheader .group8 { +.que.ddimageortext .group8, form.mform fieldset#previewareaheader .group8 { background-color: #F0E68C; } -.que.ddimagetoimage .drag, form.mform fieldset#previewareaheader .drag { +.que.ddimageortext .drag, form.mform fieldset#previewareaheader .drag { border: 1px solid black; cursor: move; z-index: 2; } -.que.ddimagetoimage .dragitems.readonly .drag { +.que.ddimageortext .dragitems.readonly .drag { cursor: auto; } -.que.ddimagetoimage div.ddarea, form.mform fieldset#previewareaheader div.ddarea { +.que.ddimageortext div.ddarea, form.mform fieldset#previewareaheader div.ddarea { text-align : center; } -.que.ddimagetoimage .dropbackground, form.mform fieldset#previewareaheader .dropbackground { +.que.ddimageortext .dropbackground, form.mform fieldset#previewareaheader .dropbackground { margin:0 auto; } -.que.ddimagetoimage .dropzone { +.que.ddimageortext .dropzone { border: 1px solid black; position: absolute; z-index: 1; diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index a15d0944567..b7b745f3367 100755 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -18,7 +18,7 @@ * Version information for the drag-and-drop words into sentences question type. * * @package qtype - * @subpackage ddimagetoimage + * @subpackage ddimageortext * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index caf8fe66c9e..78bc5969c31 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -1,12 +1,12 @@ -YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { - var DDIMAGETOIMAGEDDNAME = 'ddimagetoimage_dd'; - var DDIMAGETOIMAGE_DD = function() { - DDIMAGETOIMAGE_DD.superclass.constructor.apply(this, arguments); +YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { + var DDIMAGEORTEXTDDNAME = 'ddimageortext_dd'; + var DDIMAGEORTEXT_DD = function() { + DDIMAGEORTEXT_DD.superclass.constructor.apply(this, arguments); } /** * This is the base class for the question rendering and question editing form code. */ - Y.extend(DDIMAGETOIMAGE_DD, Y.Base, { + Y.extend(DDIMAGEORTEXT_DD, Y.Base, { doc : null, polltimer : null, afterimageloaddone : false, @@ -215,24 +215,24 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { +bgimgxy[1] + this.doc.bg_img().getY()]; } }, { - NAME : DDIMAGETOIMAGEDDNAME, + NAME : DDIMAGEORTEXTDDNAME, ATTRS : { drops : {value : null}, readonly : {value : false}, topnode : {value : null} } }); - M.qtype_ddimagetoimage = M.qtype_ddimagetoimage || {}; - M.qtype_ddimagetoimage.dd_base_class = DDIMAGETOIMAGE_DD; + M.qtype_ddimageortext = M.qtype_ddimageortext || {}; + M.qtype_ddimageortext.dd_base_class = DDIMAGEORTEXT_DD; - var DDIMAGETOIMAGEQUESTIONNAME = 'ddimagetoimage_question'; - var DDIMAGETOIMAGE_QUESTION = function() { - DDIMAGETOIMAGE_QUESTION.superclass.constructor.apply(this, arguments); + var DDIMAGEORTEXTQUESTIONNAME = 'ddimageortext_question'; + var DDIMAGEORTEXT_QUESTION = function() { + DDIMAGEORTEXT_QUESTION.superclass.constructor.apply(this, arguments); }; /** * This is the code for question rendering. */ - Y.extend(DDIMAGETOIMAGE_QUESTION, M.qtype_ddimagetoimage.dd_base_class, { + Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { initializer : function(params) { this.doc = this.doc_structure(this); this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); @@ -430,7 +430,7 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { }, this); }; } - }, {NAME : DDIMAGETOIMAGEQUESTIONNAME, ATTRS : {}}); + }, {NAME : DDIMAGEORTEXTQUESTIONNAME, ATTRS : {}}); Y.Event.define('dragchange', { // Webkit and IE repeat keydown when you hold down arrow keys. @@ -460,8 +460,8 @@ YUI.add('moodle-qtype_ddimagetoimage-dd', function(Y) { this, notifier); } }); - M.qtype_ddimagetoimage.init_question = function(config) { - return new DDIMAGETOIMAGE_QUESTION(config); + M.qtype_ddimageortext.init_question = function(config) { + return new DDIMAGEORTEXT_QUESTION(config); } }, '@VERSION@', { requires:['node', 'dd', 'dd-drop', 'dd-constrain'] diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 5590e4f4b02..5983b45018e 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -1,12 +1,12 @@ /** * This is the question editing form code. */ -YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { - var DDIMAGETOIMAGEFORMNAME = 'ddimagetoimage_form'; - var DDIMAGETOIMAGE_FORM = function() { - DDIMAGETOIMAGE_FORM.superclass.constructor.apply(this, arguments); +YUI.add('moodle-qtype_ddimageortext-form', function(Y) { + var DDIMAGEORTEXTFORMNAME = 'ddimageortext_form'; + var DDIMAGEORTEXT_FORM = function() { + DDIMAGEORTEXT_FORM.superclass.constructor.apply(this, arguments); }; - Y.extend(DDIMAGETOIMAGE_FORM, M.qtype_ddimagetoimage.dd_base_class, { + Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { fp : null, initializer : function(params) { @@ -327,11 +327,11 @@ YUI.add('moodle-qtype_ddimagetoimage-form', function(Y) { } return toreturn; } - }, {NAME : DDIMAGETOIMAGEFORMNAME, ATTRS : {maxsizes:{value:null}}}); - M.qtype_ddimagetoimage = M.qtype_ddimagetoimage || {}; - M.qtype_ddimagetoimage.init_form = function(config) { - return new DDIMAGETOIMAGE_FORM(config); + }, {NAME : DDIMAGEORTEXTFORMNAME, ATTRS : {maxsizes:{value:null}}}); + M.qtype_ddimageortext = M.qtype_ddimageortext || {}; + M.qtype_ddimageortext.init_form = function(config) { + return new DDIMAGEORTEXT_FORM(config); } }, '@VERSION@', { - requires:['node', 'dd', 'dd-drop', 'dd-constrain', 'moodle-qtype_ddimagetoimage-dd', 'form_filepicker'] + requires:['node', 'dd', 'dd-drop', 'dd-constrain', 'moodle-qtype_ddimageortext-dd', 'form_filepicker'] }); \ No newline at end of file From 73b6f0006bb828c27d74c9e94e077647437117de Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 12 Sep 2011 20:12:55 +0700 Subject: [PATCH 098/208] MDL-47494 ddimageortext: NOBUG couple of small bug fixes. --- question/type/ddimageortext/edit_ddimageortext_form.php | 6 +++--- question/type/ddimageortext/questiontype.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index dde51bbabe9..5b1daca8cb7 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -65,8 +65,8 @@ class qtype_ddimageortext_edit_form extends question_edit_form { } else { $imagerepeatsatstart = $countimages; } - $imagerepeats = optional_param('noimages', $imagerepeatsatstart, PARAM_INT); - $addfields = optional_param('addimages', '', PARAM_TEXT); + $imagerepeats = optional_param('noitems', $imagerepeatsatstart, PARAM_INT); + $addfields = optional_param('additems', '', PARAM_TEXT); if (!empty($addfields)) { $imagerepeats += self::ADD_NUM_ITEMS; } @@ -259,7 +259,7 @@ class qtype_ddimageortext_edit_form extends question_edit_form { //initialise file picker for dragimages list(, $imagerepeats) = $this->get_drag_image_repeats(); - $draftitemids = optional_param('dragitem', array(), PARAM_INT); + $draftitemids = optional_param_array('dragitem', array(), PARAM_INT); for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; //numbers not allowed in filearea name diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index e025ae76fff..4224a6bbf92 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -155,7 +155,7 @@ class qtype_ddimageortext extends question_type { '', 'no, id'); foreach (array_keys($formdata->drags) as $dragno) { $info = file_get_draft_area_info($formdata->dragitem[$dragno]); - if ($info['filecount'] > 1 || !empty($formdata->drags[$dragno]['draglabel'])) { + if ($info['filecount'] > 0 || !empty($formdata->drags[$dragno]['draglabel'])) { $draftitemid = $formdata->dragitem[$dragno]; $drag = new stdClass(); @@ -184,7 +184,7 @@ class qtype_ddimageortext extends question_type { //delete any existing files for draggable text item type $fs = get_file_storage(); $fs->delete_area_files($formdata->context->id, 'qtype_ddimageortext', - 'dragimage', $drag->id); + 'dragimage', $drag->id); } } From 0a65100c42ad5c1ee0c5bd4a1c4b8421b4f06787 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 12 Sep 2011 20:16:40 +0700 Subject: [PATCH 099/208] MDL-47494 ddimageortext: NOBUG changing url to css from yui 3.4 build --- question/type/ddimageortext/edit_ddimageortext_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 5b1daca8cb7..2a524080d58 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -298,7 +298,7 @@ class qtype_ddimageortext_edit_form extends question_edit_form { $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', 'M.qtype_ddimageortext.init_form', array($params)); - $PAGE->requires->css('/lib/yui/3.2.0/build/cssfonts/fonts-context-min.css'); + $PAGE->requires->css('/lib/yui/3.4.0/build/cssfonts/fonts-context-min.css'); return $question; } From 9593b7206ec08fc68f5ff5fafbd3ce0a8316716d Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 12 Sep 2011 20:20:41 +0700 Subject: [PATCH 100/208] MDL-47494 ddimageortext: NOBUG removing erroneous require of YUI 2 code. --- question/type/ddimageortext/renderer.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 3e8fb4757ff..ea27e8c1edc 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -39,8 +39,6 @@ class qtype_ddimageortext_renderer extends qtype_with_combined_feedback_renderer public function head_code(question_attempt $qa) { $this->page->requires->css('/lib/yui/3.4.0/build/csscssfonts/fonts-context-min.css'); - $this->page->requires->yui2_lib('event'); - $this->page->requires->yui2_lib('dragdrop'); return parent::head_code($qa); } public function clear_wrong(question_attempt $qa) { From 06f00779cf8dc4f155197ba70a1508ac75f1b554 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 13 Sep 2011 19:42:37 +0700 Subject: [PATCH 101/208] MDL-47494 ddimageortext: NOBUG fixing code that constrains xy coords to within the background image. And also fixed links to css to standardize character metrics. --- .../type/ddimageortext/edit_ddimageortext_form.php | 3 ++- question/type/ddimageortext/renderer.php | 4 +++- question/type/ddimageortext/yui/dd/dd.js | 7 ++++--- question/type/ddimageortext/yui/form/form.js | 14 +++++++++----- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 2a524080d58..01f229a1207 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -298,7 +298,8 @@ class qtype_ddimageortext_edit_form extends question_edit_form { $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', 'M.qtype_ddimageortext.init_form', array($params)); - $PAGE->requires->css('/lib/yui/3.4.0/build/cssfonts/fonts-context-min.css'); + $PAGE->requires->css('/lib/yui/3.4.0/build/cssfonts-context/fonts-context-min.css'); + $PAGE->requires->css('/lib/yui/3.4.0/build/cssreset-context/cssreset-context-min.css'); return $question; } diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index ea27e8c1edc..08752a1a5db 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -38,7 +38,9 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); class qtype_ddimageortext_renderer extends qtype_with_combined_feedback_renderer { public function head_code(question_attempt $qa) { - $this->page->requires->css('/lib/yui/3.4.0/build/csscssfonts/fonts-context-min.css'); + $this->page->requires->css('/lib/yui/3.4.0/build/cssfonts-context/fonts-context-min.css'); + $this->page->requires->css( + '/lib/yui/3.4.0/build/cssreset-context/cssreset-context-min.css'); return parent::head_code($qa); } public function clear_wrong(question_attempt $qa) { diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 78bc5969c31..2365e970e28 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -92,7 +92,8 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { var oldhome = this.drag_item_home(dragitemno); var classes = 'draghome dragitemhomes'+dragitemno+' group'+group; var imghtml = ''+alt+''; - var divhtml = '
'+alt+'
'; + var divhtml = '
'+alt+'
'; if (oldhome === null) { if (url) { dragitemsarea.append(imghtml); @@ -211,8 +212,8 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { } }, convert_to_window_xy : function (bgimgxy) { - return [+bgimgxy[0] + this.doc.bg_img().getX(), - +bgimgxy[1] + this.doc.bg_img().getY()]; + return [+bgimgxy[0] + this.doc.bg_img().getX() + 1, + +bgimgxy[1] + this.doc.bg_img().getY() + 1]; } }, { NAME : DDIMAGEORTEXTDDNAME, diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 5983b45018e..e49ebeaac25 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -151,6 +151,11 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { Y.all('fieldset#dropzoneheader input').on('blur', function (e){ var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), + this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; + var constrainedxy = this.constrain_xy(draginstanceno, fromform); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], constrainedxy[0]); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); }, this); //change in selected item @@ -177,10 +182,10 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { this.draw_dd_area(); }, this); Y.all('fieldset#draggableitemheader_'+i+' input[type="text"]') - .on('blur', function (e){ - this.doc.drag_items().remove(true); + .on('blur', function (e, draginstanceno){ + this.doc.drag_item(draginstanceno).remove(true); this.draw_dd_area(); - }, this); + }, this, i); //change to infinite checkbox Y.all('fieldset#draggableitemheader_'+i+' input[type="checkbox"]') .on('change', this.set_options_for_drag_item_selectors, this); @@ -223,8 +228,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { var dragitemno = drag.getData('dragitemno'); drag.setXY(this.doc.drag_item_home(dragitemno).getXY()); } else { - var constrainedxy = this.constrain_xy(draginstanceno, fromform); - drag.setXY(this.convert_to_window_xy(constrainedxy)); + drag.setXY(this.convert_to_window_xy(fromform)); } } }, From e05bd4be139044e7edebc15cf506476f55d3c894 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 13 Sep 2011 19:44:55 +0700 Subject: [PATCH 102/208] MDL-47494 ddimageortext: NOBUG fixing import of text as well as image based drag items. --- question/type/ddimageortext/questiontype.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 4224a6bbf92..dc81a17ad83 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -352,6 +352,11 @@ class qtype_ddimageortext extends question_type { $filexml = $format->getpath($dragxml, array('#', 'file'), array()); $question->dragitem[$dragindex] = $this->import_files_to_draft_file_area($format, $filexml); + if (count($filexml)) { + $question->dragitemtype[$dragindex] = 'image'; + } else { + $question->dragitemtype[$dragindex] = 'word'; + } } $drops = $data['#']['drop']; From ea9bec768a1b6829d14a955ba262fc6e7631e8d1 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 13 Sep 2011 20:13:58 +0700 Subject: [PATCH 103/208] MDL-47494 ddimageortext: NOBUG fixing typo in code for course restore. --- .../backup/moodle2/restore_qtype_ddimageortext_plugin.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php index 104a3202b0b..f6ea4fdbf7d 100644 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php @@ -44,7 +44,7 @@ class restore_qtype_ddimageortext_plugin extends restore_qtype_plugin { $paths = array(); // Add own qtype stuff - $elename = dds; + $elename = 'dds'; $elepath = $this->get_pathfor('/'.self::qtype_name()); $paths[] = new restore_path_element($elename, $elepath); From 7e2699d919016d97cbdefcd63ec69eab1ec90d66 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 13 Sep 2011 20:27:38 +0700 Subject: [PATCH 104/208] MDL-47494 ddimageortext: NOBUG fixed broken unit tests. --- question/type/ddimageortext/simpletest/testwalkthrough.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index 6bfa468db01..179a18fb0d4 100755 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -38,14 +38,14 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php */ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_base { - protected function get_contains_drag_image_home_expectation($dragimageno, $choice, $group) { + protected function get_contains_drag_image_home_expectation($dragitemno, $choice, $group) { $class = 'group' . $group; - $class .= ' draghome dragimagehomes' . $dragimageno. ' choice'.$choice; + $class .= ' draghome dragitemhomes' . $dragitemno. ' choice'.$choice.' yui3-cssfonts'; $expectedattrs = array(); $expectedattrs['class'] = $class; - return new ContainsTagWithAttributes('img', $expectedattrs); + return new ContainsTagWithAttributes('div', $expectedattrs); } public function test_interactive_behaviour() { From 38955535bd17f7e7f90737a0320a485b99f68043 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 13 Sep 2011 20:41:07 +0700 Subject: [PATCH 105/208] MDL-47494 ddimageortext: NOBUG fixed some whitespace and coding guideline issues found by codechecker. --- question/type/ddimageortext/edit_ddimageortext_form.php | 3 +-- question/type/ddimageortext/styles.css | 1 - question/type/ddimageortext/yui/form/form.js | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 01f229a1207..f39f9c763f5 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -346,7 +346,6 @@ class qtype_ddimageortext_edit_form extends question_edit_form { get_string('formerror_nofile', 'qtype_ddimageortext', $i); } - if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { $errors["drops[$i]"] = get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); @@ -372,7 +371,7 @@ class qtype_ddimageortext_edit_form extends question_edit_form { $allowedtags = ''; $errormessage = get_string('formerror_noallowedtags', 'qtype_ddimageortext'); } - if ($label != strip_tags($label, $allowedtags)){ + if ($label != strip_tags($label, $allowedtags)) { $errors["drags[{$dragindex}]"] = $errormessage; } diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index db7d5ad6223..0d8a54417d5 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -73,4 +73,3 @@ position: absolute; z-index: 1; } - diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index e49ebeaac25..76bd8478e6b 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -77,7 +77,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { load_drag_home : function (dragitemno) { if ('image' === this.form.get_form_value('dragitemtype', [dragitemno])) { - var url = + var url = this.fp.file(this.form.to_name_with_index('dragitem', [dragitemno])).href; } else { var url = null; From e58d0a2d58fe7c43db90ab2267d09a21a4aae063 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 14 Sep 2011 19:37:22 +0700 Subject: [PATCH 106/208] MDL-47494 ddimageortext: NOBUG removing unnecessary declaration of dependencies. --- question/type/ddimageortext/yui/form/form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 76bd8478e6b..502c199a4fb 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -337,5 +337,5 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { return new DDIMAGEORTEXT_FORM(config); } }, '@VERSION@', { - requires:['node', 'dd', 'dd-drop', 'dd-constrain', 'moodle-qtype_ddimageortext-dd', 'form_filepicker'] + requires:['moodle-qtype_ddimageortext-dd', 'form_filepicker'] }); \ No newline at end of file From 0957568d3ac5f01fa5958c42db1b00efdf17c51f Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 14 Sep 2011 19:46:23 +0700 Subject: [PATCH 107/208] MDL-47494 ddimageortext: NOBUG need to use 3.2 yui url to access 3.2 yui which is the latest available in MOODLE_21_STABLE --- question/type/ddimageortext/edit_ddimageortext_form.php | 4 ++-- question/type/ddimageortext/renderer.php | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index f39f9c763f5..3603d3f76f1 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -298,8 +298,8 @@ class qtype_ddimageortext_edit_form extends question_edit_form { $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', 'M.qtype_ddimageortext.init_form', array($params)); - $PAGE->requires->css('/lib/yui/3.4.0/build/cssfonts-context/fonts-context-min.css'); - $PAGE->requires->css('/lib/yui/3.4.0/build/cssreset-context/cssreset-context-min.css'); + $PAGE->requires->css('/lib/yui/3.2.0/build/cssfonts/fonts-context-min.css'); + $PAGE->requires->css('/lib/yui/3.2.0/build/cssreset/reset-context-min.css'); return $question; } diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 08752a1a5db..afcc80a10ca 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -38,9 +38,8 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); class qtype_ddimageortext_renderer extends qtype_with_combined_feedback_renderer { public function head_code(question_attempt $qa) { - $this->page->requires->css('/lib/yui/3.4.0/build/cssfonts-context/fonts-context-min.css'); - $this->page->requires->css( - '/lib/yui/3.4.0/build/cssreset-context/cssreset-context-min.css'); + $this->page->requires->css('/lib/yui/3.2.0/build/cssfonts/fonts-context-min.css'); + $this->page->requires->css('/lib/yui/3.2.0/build/cssreset/reset-context-min.css'); return parent::head_code($qa); } public function clear_wrong(question_attempt $qa) { From 59932119c8cd0c28d9460a8ca065ed8ccac08298 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 15 Sep 2011 10:33:20 +0700 Subject: [PATCH 108/208] MDL-47494 ddimageortext: NOBUG I realised that the yui css I was using didn't actually do a lot. Instead of including yui css I copied the relevant style to the question style sheet. --- question/type/ddimageortext/edit_ddimageortext_form.php | 3 --- question/type/ddimageortext/renderer.php | 2 -- question/type/ddimageortext/styles.css | 6 ++++++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 3603d3f76f1..a044ee40433 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -298,9 +298,6 @@ class qtype_ddimageortext_edit_form extends question_edit_form { $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', 'M.qtype_ddimageortext.init_form', array($params)); - $PAGE->requires->css('/lib/yui/3.2.0/build/cssfonts/fonts-context-min.css'); - $PAGE->requires->css('/lib/yui/3.2.0/build/cssreset/reset-context-min.css'); - return $question; } diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index afcc80a10ca..32a10304814 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -38,8 +38,6 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); class qtype_ddimageortext_renderer extends qtype_with_combined_feedback_renderer { public function head_code(question_attempt $qa) { - $this->page->requires->css('/lib/yui/3.2.0/build/cssfonts/fonts-context-min.css'); - $this->page->requires->css('/lib/yui/3.2.0/build/cssreset/reset-context-min.css'); return parent::head_code($qa); } public function clear_wrong(question_attempt $qa) { diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 0d8a54417d5..435cafdd097 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -73,3 +73,9 @@ position: absolute; z-index: 1; } +.que.ddimageortext div.dragitems div.draghome, .que.ddimageortext div.dragitems div.drag, +form.mform fieldset#previewareaheader div.draghome, form.mform fieldset#previewareaheader div.drag { + font:13px/1.231 arial,helvetica,clean,sans-serif; + *font-size:small; /* for IE */ + *font:x-small; /* for IE in quirks mode */ +} From ce6d6b175b0147862dfe9ab611d793cb930e26d3 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 15 Sep 2011 12:11:45 +0700 Subject: [PATCH 109/208] MDL-47494 ddimageortext: NOBUG optional_param_array is not available in MOODLE 2.1 but must be used in MOODLE 2.2 on. --- question/type/ddimageortext/edit_ddimageortext_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index a044ee40433..616db820909 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -259,7 +259,7 @@ class qtype_ddimageortext_edit_form extends question_edit_form { //initialise file picker for dragimages list(, $imagerepeats) = $this->get_drag_image_repeats(); - $draftitemids = optional_param_array('dragitem', array(), PARAM_INT); + $draftitemids = optional_param('dragitem', array(), PARAM_INT); for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; //numbers not allowed in filearea name From 7d35968d74825e89e42807f1c1be6e157a5670d6 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 15 Sep 2011 16:21:47 +0700 Subject: [PATCH 110/208] MDL-47494 ddimageortext: NOBUG fixing a 1 pixel jump downwards and to the right seen on dropping drag items when form editing in IE9 and Chrome. --- question/type/ddimageortext/yui/dd/dd.js | 3 +-- question/type/ddimageortext/yui/form/form.js | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 2365e970e28..4c89cdce652 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -173,8 +173,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { if (!gooddrop) { mainobj.reset_drag_xy(draginstanceno); } else { - endxy = [Math.round(e.pageX), Math.round(e.pageY)]; - mainobj.set_drag_xy(draginstanceno, endxy); + mainobj.set_drag_xy(draginstanceno, [e.pageX, e.pageY]); } }, this); dd.on('drag:start', function(e) { diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 502c199a4fb..1a7f6096140 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -234,8 +234,8 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, set_drag_xy : function (draginstanceno, xy) { xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); - this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.floor(xy[0])); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.floor(xy[1])); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.round(xy[0])); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.round(xy[1])); }, reset_drag_xy : function (draginstanceno) { this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); @@ -254,8 +254,8 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { return [xleftconstrained, ytopconstrained]; }, convert_to_bg_img_xy : function (windowxy) { - return [windowxy[0] - this.doc.bg_img().getX(), - windowxy[1] - this.doc.bg_img().getY()]; + return [+windowxy[0] - this.doc.bg_img().getX()-1, + +windowxy[1] - this.doc.bg_img().getY()-1]; }, /** From 7c0a4f54df4d48fde9d60ca33d619c001950c6fc Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 15 Sep 2011 16:21:47 +0700 Subject: [PATCH 111/208] MDL-47494 ddimageortext: NOBUG fixing a 1 pixel jump downwards and to the right seen on dropping drag items when form editing in IE9 and Chrome. --- question/type/ddimageortext/yui/dd/dd.js | 3 +-- question/type/ddimageortext/yui/form/form.js | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 2365e970e28..4c89cdce652 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -173,8 +173,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { if (!gooddrop) { mainobj.reset_drag_xy(draginstanceno); } else { - endxy = [Math.round(e.pageX), Math.round(e.pageY)]; - mainobj.set_drag_xy(draginstanceno, endxy); + mainobj.set_drag_xy(draginstanceno, [e.pageX, e.pageY]); } }, this); dd.on('drag:start', function(e) { diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 502c199a4fb..1a7f6096140 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -234,8 +234,8 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, set_drag_xy : function (draginstanceno, xy) { xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); - this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.floor(xy[0])); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.floor(xy[1])); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.round(xy[0])); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.round(xy[1])); }, reset_drag_xy : function (draginstanceno) { this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); @@ -254,8 +254,8 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { return [xleftconstrained, ytopconstrained]; }, convert_to_bg_img_xy : function (windowxy) { - return [windowxy[0] - this.doc.bg_img().getX(), - windowxy[1] - this.doc.bg_img().getY()]; + return [+windowxy[0] - this.doc.bg_img().getX()-1, + +windowxy[1] - this.doc.bg_img().getY()-1]; }, /** From 649e99a8c994f30bd47dc84f0eda8b2a66c08e1f Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 16 Sep 2011 16:16:22 +0700 Subject: [PATCH 112/208] MDL-47494 ddimageortext: OU-1549 Double line spacing was accidentally copied over from ddwtos question type. --- question/type/ddimageortext/styles.css | 1 - 1 file changed, 1 deletion(-) diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 435cafdd097..ae9a3ad48d4 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -1,5 +1,4 @@ .que.ddimageortext .qtext { - line-height: 2em; margin-bottom: 0.5em; display: block; } From fda1da57e16ee34a2fa13ca76372a371a3fd6928 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 16 Sep 2011 16:16:22 +0700 Subject: [PATCH 113/208] MDL-47494 ddimageortext: OU-1549 Double line spacing was accidentally copied over from ddwtos question type. --- question/type/ddimageortext/styles.css | 1 - 1 file changed, 1 deletion(-) diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 435cafdd097..ae9a3ad48d4 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -1,5 +1,4 @@ .que.ddimageortext .qtext { - line-height: 2em; margin-bottom: 0.5em; display: block; } From 27c106ad40979baa0a693852c69c3229e5290c5d Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 20 Sep 2011 13:15:42 +0700 Subject: [PATCH 114/208] MDL-47494 ddimageortext: OU-1549 "Is question text line spacing in drag and drop questions larger than normal?" Missed one selector in style.css --- question/type/ddimageortext/styles.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index ae9a3ad48d4..bc9365df553 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -3,10 +3,6 @@ display: block; } -.que.ddimageortext .qtext * { - line-height: 2em; -} - .que.ddimageortext div.droparea img, form.mform fieldset#previewareaheader div.droparea img { border: 1px solid #000000; } From e522e6c3e6109e5116c1f36ee49425cb23756be8 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 20 Sep 2011 13:15:42 +0700 Subject: [PATCH 115/208] MDL-47494 ddimageortext: OU-1549 "Is question text line spacing in drag and drop questions larger than normal?" Missed one selector in style.css --- question/type/ddimageortext/styles.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index ae9a3ad48d4..bc9365df553 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -3,10 +3,6 @@ display: block; } -.que.ddimageortext .qtext * { - line-height: 2em; -} - .que.ddimageortext div.droparea img, form.mform fieldset#previewareaheader div.droparea img { border: 1px solid #000000; } From d2c112fd8cbe4034c84a56a724593de255d026cf Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 26 Sep 2011 14:27:35 +0700 Subject: [PATCH 116/208] MDL-47494 ddimageortext: NOBUG moved functionality for questions into base classes that can be extended by other question types. --- .../ddimageortext/edit_ddimageortext_form.php | 349 +------------ .../edit_ddtoimage_form_base.php | 381 +++++++++++++++ question/type/ddimageortext/question.php | 124 +---- question/type/ddimageortext/questionbase.php | 161 ++++++ question/type/ddimageortext/questiontype.php | 424 +--------------- .../type/ddimageortext/questiontypebase.php | 459 ++++++++++++++++++ question/type/ddimageortext/renderer.php | 145 +----- question/type/ddimageortext/rendererbase.php | 177 +++++++ 8 files changed, 1187 insertions(+), 1033 deletions(-) create mode 100644 question/type/ddimageortext/edit_ddtoimage_form_base.php create mode 100644 question/type/ddimageortext/questionbase.php create mode 100644 question/type/ddimageortext/questiontypebase.php create mode 100644 question/type/ddimageortext/rendererbase.php diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index a044ee40433..683afc227bc 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +require_once($CFG->dirroot.'/question/type/ddimageortext/edit_ddtoimage_form_base.php'); + /** * Defines the editing form for the drag-and-drop images onto images question type. * @@ -31,351 +33,6 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimageortext_edit_form extends question_edit_form { - const MAX_GROUPS = 8; - const START_NUM_ITEMS = 6; - const ADD_NUM_ITEMS = 3; - - public function qtype() { - return 'ddimageortext'; - } - - /** - * - * Options shared by all file pickers in the form. - */ - public static function file_picker_options() { - $filepickeroptions = array(); - $filepickeroptions['accepted_types'] = array('web_image'); - $filepickeroptions['maxbytes'] = 0; - $filepickeroptions['maxfiles'] = 1; - $filepickeroptions['subdirs'] = 0; - return $filepickeroptions; - } - - protected function get_drag_image_repeats() { - $countimages = 0; - if (isset($this->question->id)) { - foreach ($this->question->options->drags as $drag) { - $countimages = max($countimages, $drag->no); - } - } - if ($this->question->formoptions->repeatelements) { - $imagerepeatsatstart = max(self::START_NUM_ITEMS, $countimages + self::ADD_NUM_ITEMS); - } else { - $imagerepeatsatstart = $countimages; - } - $imagerepeats = optional_param('noitems', $imagerepeatsatstart, PARAM_INT); - $addfields = optional_param('additems', '', PARAM_TEXT); - if (!empty($addfields)) { - $imagerepeats += self::ADD_NUM_ITEMS; - } - return array($imagerepeatsatstart, $imagerepeats); - } - - /** - * definition_inner adds all specific fields to the form. - * @param object $mform (the form being built). - */ - protected function definition_inner($mform) { - - $mform->addElement('header', 'previewareaheader', - get_string('previewareaheader', 'qtype_ddimageortext')); - $mform->addElement('static', 'previewarea', - get_string('previewarea', 'qtype_ddimageortext'), - get_string('previewareamessage', 'qtype_ddimageortext')); - - $mform->registerNoSubmitButton('refresh'); - $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_ddimageortext')); - $mform->closeHeaderBefore('refresh'); - - list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); - $this->definition_drop_zones($mform, $imagerepeats); - $mform->addElement('advcheckbox', 'shuffleanswers', ' ', - get_string('shuffleimages', 'qtype_ddimageortext')); - $mform->setDefault('shuffleanswers', 0); - $mform->closeHeaderBefore('shuffleanswers'); - //add the draggable image fields to the form - $this->definition_draggable_images($mform, $imagerepeatsatstart); - - $this->add_combined_feedback_fields(true); - $this->add_interactive_settings(true, true); - } - - protected function definition_drop_zones($mform, $imagerepeats) { - $mform->addElement('header', 'dropzoneheader', - get_string('dropzoneheader', 'qtype_ddimageortext')); - - $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimageortext'), - null, self::file_picker_options()); - - $countdropzones = 0; - if (isset($this->question->id)) { - foreach ($this->question->options->drops as $drop) { - $countdropzones = max($countdropzones, $drop->no); - } - } - if ($this->question->formoptions->repeatelements) { - $dropzonerepeatsatstart = max(self::START_NUM_ITEMS, - $countdropzones + self::ADD_NUM_ITEMS); - } else { - $dropzonerepeatsatstart = $countdropzones; - } - - $this->repeat_elements($this->drop_zone($mform, $imagerepeats), $dropzonerepeatsatstart, - $this->drop_zones_repeated_options(), - 'nodropzone', 'adddropzone', self::ADD_NUM_ITEMS, - get_string('addmoredropzones', 'qtype_ddimageortext')); - } - - protected function drop_zone($mform, $imagerepeats) { - $dropzoneitem = array(); - - $grouparray = array(); - $grouparray[] = $mform->createElement('static', 'xleftlabel', '', - ' '.get_string('xleft', 'qtype_ddimageortext').' '); - $grouparray[] = $mform->createElement('text', 'xleft', - get_string('xleft', 'qtype_ddimageortext'), - array('size'=>5, 'class'=>'tweakcss')); - $mform->setType('xleft', PARAM_NOTAGS); - $grouparray[] = $mform->createElement('static', 'ytoplabel', '', - ' '.get_string('ytop', 'qtype_ddimageortext').' '); - $grouparray[] = $mform->createElement('text', 'ytop', - get_string('ytop', 'qtype_ddimageortext'), - array('size'=>5, 'class'=>'tweakcss')); - $mform->setType('ytop', PARAM_NOTAGS); - $options = array(); - - $options[0] = ''; - for ($i = 1; $i <= $imagerepeats; $i += 1) { - $options[$i] = $i; - } - $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('draggableitem', 'qtype_ddimageortext').' '); - $grouparray[] = $mform->createElement('select', 'choice', - get_string('draggableitem', 'qtype_ddimageortext'), $options); - $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('label', 'qtype_ddimageortext').' '); - $grouparray[] = $mform->createElement('text', 'droplabel', - get_string('label', 'qtype_ddimageortext'), - array('size'=>10, 'class'=>'tweakcss')); - $mform->setType('droplabel', PARAM_NOTAGS); - $dropzone = $mform->createElement('group', 'drops', - get_string('dropzone', 'qtype_ddimageortext', '{no}'), $grouparray); - return array($dropzone); - } - - protected function drop_zones_repeated_options() { - $repeatedoptions = array(); - $repeatedoptions['choice']['default'] = '0'; - return $repeatedoptions; - } - - protected function definition_draggable_images($mform, $imagerepeatsatstart) { - - $this->repeat_elements($this->draggable_image($mform), $imagerepeatsatstart, - $this->draggable_images_repeated_options(), - 'noitems', 'additems', self::ADD_NUM_ITEMS, - get_string('addmoreimages', 'qtype_ddimageortext')); - } - - protected function draggable_image($mform) { - $draggableimageitem = array(); - - $draggableimageitem[] = $mform->createElement('header', 'draggableitemheader', - get_string('draggableitemheader', 'qtype_ddimageortext', '{no}')); - $dragitemtypes = array('image' => get_string('draggableimage', 'qtype_ddimageortext'), - 'word' => get_string('draggableword', 'qtype_ddimageortext')); - $draggableimageitem[] = $mform->createElement('select', 'dragitemtype', - get_string('draggableitemtype', 'qtype_ddimageortext'), - $dragitemtypes, - array('class' => 'dragitemtype')); - $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null, - self::file_picker_options()); - - $grouparray = array(); - $grouparray[] = $mform->createElement('text', 'draglabel', - get_string('label', 'qtype_ddimageortext'), - array('size'=>30, 'class'=>'tweakcss')); - $mform->setType('draglabel', PARAM_NOTAGS); - $options = array(); - for ($i = 1; $i <= self::MAX_GROUPS; $i += 1) { - $options[$i] = $i; - } - $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('group', 'qtype_gapselect').' '); - $grouparray[] = $mform->createElement('select', 'draggroup', - get_string('group', 'qtype_gapselect'), - $options, - array('class' => 'draggroup')); - $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ', - get_string('infinite', 'qtype_ddimageortext')); - $draggableimageitem[] = $mform->createElement('group', 'drags', - get_string('label', 'qtype_ddimageortext'), $grouparray); - return $draggableimageitem; - } - - protected function draggable_images_repeated_options() { - $repeatedoptions = array(); - $repeatedoptions['draggroup']['default'] = '1'; - return $repeatedoptions; - } - - public function data_preprocessing($question) { - global $PAGE; - - $question = parent::data_preprocessing($question); - $question = $this->data_preprocessing_combined_feedback($question, true); - $question = $this->data_preprocessing_hints($question, true, true); - - $dragids = array(); // drag no -> dragid - if (!empty($question->options)) { - $question->shuffleanswers = $question->options->shuffleanswers; - $question->drags = array(); - foreach ($question->options->drags as $drag) { - $dragindex = $drag->no -1; - $question->drags[$dragindex] = array(); - $question->drags[$dragindex]['draglabel'] = $drag->label; - $question->drags[$dragindex]['infinite'] = $drag->infinite; - $question->drags[$dragindex]['draggroup'] = $drag->draggroup; - $dragids[$dragindex] = $drag->id; - } - $question->drops = array(); - foreach ($question->options->drops as $drop) { - $question->drops[$drop->no -1] = array(); - $question->drops[$drop->no -1]['choice'] = $drop->choice; - $question->drops[$drop->no -1]['droplabel'] = $drop->label; - $question->drops[$drop->no -1]['xleft'] = $drop->xleft; - $question->drops[$drop->no -1]['ytop'] = $drop->ytop; - } - } - //initialise file picker for bgimage - $draftitemid = file_get_submitted_draft_itemid('bgimage'); - - file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', - 'bgimage', !empty($question->id) ? (int) $question->id : null, - self::file_picker_options()); - $question->bgimage = $draftitemid; - - //initialise file picker for dragimages - list(, $imagerepeats) = $this->get_drag_image_repeats(); - $draftitemids = optional_param_array('dragitem', array(), PARAM_INT); - for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { - $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; - //numbers not allowed in filearea name - $itemid = isset($dragids[$imageindex]) ? $dragids[$imageindex] : null; - file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', - 'dragimage', $itemid, self::file_picker_options()); - $question->dragitem[$imageindex] = $draftitemid; - } - if (!empty($question->options)) { - foreach ($question->options->drags as $drag) { - $dragindex = $drag->no -1; - if (!isset($question->dragitem[$dragindex])) { - $fileexists = false; - } else { - $fileexists = self::file_uploaded($question->dragitem[$dragindex]); - } - $labelexists = $question->drags[$dragindex]['draglabel']; - if ($labelexists && !$fileexists) { - $question->dragitemtype[$dragindex] = 'word'; - } else { - $question->dragitemtype[$dragindex] = 'image'; - } - } - } - $maxsizes =new stdClass(); - $maxsizes->bgimage = new stdClass(); - $maxsizes->bgimage->width = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH; - $maxsizes->bgimage->height = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT; - $maxsizes->dragimage = new stdClass(); - $maxsizes->dragimage->width = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH; - $maxsizes->dragimage->height = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT; - - $params = array('maxsizes' => $maxsizes, - 'topnode' => 'fieldset#previewareaheader'); - - $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', - 'M.qtype_ddimageortext.init_form', - array($params)); - return $question; - } - - - public static function file_uploaded($draftitemid) { - $draftareafiles = file_get_drafarea_files($draftitemid); - do { - $draftareafile = array_shift($draftareafiles->list); - } while ($draftareafile !== null && $draftareafile->filename == '.'); - if ($draftareafile === null) { - return false; - } - return true; - } - - public function validation($data, $files) { - $errors = parent::validation($data, $files); - if (!self::file_uploaded($data['bgimage'])) { - $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddimageortext'); - } - - $allchoices = array(); - for ($i=0; $i < $data['nodropzone']; $i++) { - $ytoppresent = (trim($data['drops'][$i]['ytop']) !== ''); - $xleftpresent = (trim($data['drops'][$i]['ytop']) !== ''); - $labelpresent = (trim($data['drops'][$i]['droplabel']) !== ''); - $choice = $data['drops'][$i]['choice']; - $imagechoicepresent = ($choice !== '0'); - - if ($imagechoicepresent) { - if (!$ytoppresent) { - $errors["drops[$i]"] = - get_string('formerror_noytop', 'qtype_ddimageortext'); - } - if (!$xleftpresent) { - $errors["drops[$i]"] = - get_string('formerror_noxleft', 'qtype_ddimageortext'); - } - - if ($data['dragitemtype'][$choice - 1] != 'word' && - !self::file_uploaded($data['dragitem'][$choice - 1])) { - $errors['dragitem['.($choice - 1).']'] = - get_string('formerror_nofile', 'qtype_ddimageortext', $i); - } - - if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { - $errors["drops[$i]"] = - get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); - $errors['drops['.($allchoices[$choice]).']'] = - get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); - $errors['drags['.($choice-1).']'] = - get_string('formerror_multipledraginstance2', 'qtype_ddimageortext', $choice); - } - $allchoices[$choice] = $i; - } else { - if ($ytoppresent || $xleftpresent || $labelpresent) { - $errors["drops[$i]"] = - get_string('formerror_noimageselected', 'qtype_ddimageortext'); - } - } - } - for ($dragindex=0; $dragindex < $data['noitems']; $dragindex++) { - $label = $data['drags'][$dragindex]['draglabel']; - if ($data['dragitemtype'][$dragindex] == 'word') { - $allowedtags = '
'; - $errormessage = get_string('formerror_disallowedtags', 'qtype_ddimageortext'); - } else { - $allowedtags = ''; - $errormessage = get_string('formerror_noallowedtags', 'qtype_ddimageortext'); - } - if ($label != strip_tags($label, $allowedtags)) { - $errors["drags[{$dragindex}]"] = $errormessage; - } - - } - return $errors; - } - - +class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { } diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php new file mode 100644 index 00000000000..8a361a81e87 --- /dev/null +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -0,0 +1,381 @@ +. + +/** + * Base class for editing form for the drag-and-drop images onto images question type. + * + * @package qtype + * @subpackage ddimageortext + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Base class for drag-and-drop onto images editing form definition. + * + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddtoimage_edit_form_base extends question_edit_form { + const MAX_GROUPS = 8; + const START_NUM_ITEMS = 6; + const ADD_NUM_ITEMS = 3; + + public function qtype() { + return 'ddimageortext'; + } + + /** + * + * Options shared by all file pickers in the form. + */ + public static function file_picker_options() { + $filepickeroptions = array(); + $filepickeroptions['accepted_types'] = array('web_image'); + $filepickeroptions['maxbytes'] = 0; + $filepickeroptions['maxfiles'] = 1; + $filepickeroptions['subdirs'] = 0; + return $filepickeroptions; + } + + protected function get_drag_image_repeats() { + $countimages = 0; + if (isset($this->question->id)) { + foreach ($this->question->options->drags as $drag) { + $countimages = max($countimages, $drag->no); + } + } + if ($this->question->formoptions->repeatelements) { + $imagerepeatsatstart = max(self::START_NUM_ITEMS, $countimages + self::ADD_NUM_ITEMS); + } else { + $imagerepeatsatstart = $countimages; + } + $imagerepeats = optional_param('noitems', $imagerepeatsatstart, PARAM_INT); + $addfields = optional_param('additems', '', PARAM_TEXT); + if (!empty($addfields)) { + $imagerepeats += self::ADD_NUM_ITEMS; + } + return array($imagerepeatsatstart, $imagerepeats); + } + + /** + * definition_inner adds all specific fields to the form. + * @param object $mform (the form being built). + */ + protected function definition_inner($mform) { + + $mform->addElement('header', 'previewareaheader', + get_string('previewareaheader', 'qtype_ddimageortext')); + $mform->addElement('static', 'previewarea', + get_string('previewarea', 'qtype_ddimageortext'), + get_string('previewareamessage', 'qtype_ddimageortext')); + + $mform->registerNoSubmitButton('refresh'); + $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_ddimageortext')); + $mform->closeHeaderBefore('refresh'); + + list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); + $this->definition_drop_zones($mform, $imagerepeats); + $mform->addElement('advcheckbox', 'shuffleanswers', ' ', + get_string('shuffleimages', 'qtype_ddimageortext')); + $mform->setDefault('shuffleanswers', 0); + $mform->closeHeaderBefore('shuffleanswers'); + //add the draggable image fields to the form + $this->definition_draggable_images($mform, $imagerepeatsatstart); + + $this->add_combined_feedback_fields(true); + $this->add_interactive_settings(true, true); + } + + protected function definition_drop_zones($mform, $imagerepeats) { + $mform->addElement('header', 'dropzoneheader', + get_string('dropzoneheader', 'qtype_ddimageortext')); + + $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimageortext'), + null, self::file_picker_options()); + + $countdropzones = 0; + if (isset($this->question->id)) { + foreach ($this->question->options->drops as $drop) { + $countdropzones = max($countdropzones, $drop->no); + } + } + if ($this->question->formoptions->repeatelements) { + $dropzonerepeatsatstart = max(self::START_NUM_ITEMS, + $countdropzones + self::ADD_NUM_ITEMS); + } else { + $dropzonerepeatsatstart = $countdropzones; + } + + $this->repeat_elements($this->drop_zone($mform, $imagerepeats), $dropzonerepeatsatstart, + $this->drop_zones_repeated_options(), + 'nodropzone', 'adddropzone', self::ADD_NUM_ITEMS, + get_string('addmoredropzones', 'qtype_ddimageortext')); + } + + protected function drop_zone($mform, $imagerepeats) { + $dropzoneitem = array(); + + $grouparray = array(); + $grouparray[] = $mform->createElement('static', 'xleftlabel', '', + ' '.get_string('xleft', 'qtype_ddimageortext').' '); + $grouparray[] = $mform->createElement('text', 'xleft', + get_string('xleft', 'qtype_ddimageortext'), + array('size'=>5, 'class'=>'tweakcss')); + $mform->setType('xleft', PARAM_NOTAGS); + $grouparray[] = $mform->createElement('static', 'ytoplabel', '', + ' '.get_string('ytop', 'qtype_ddimageortext').' '); + $grouparray[] = $mform->createElement('text', 'ytop', + get_string('ytop', 'qtype_ddimageortext'), + array('size'=>5, 'class'=>'tweakcss')); + $mform->setType('ytop', PARAM_NOTAGS); + $options = array(); + + $options[0] = ''; + for ($i = 1; $i <= $imagerepeats; $i += 1) { + $options[$i] = $i; + } + $grouparray[] = $mform->createElement('static', '', '', ' ' . + get_string('draggableitem', 'qtype_ddimageortext').' '); + $grouparray[] = $mform->createElement('select', 'choice', + get_string('draggableitem', 'qtype_ddimageortext'), $options); + $grouparray[] = $mform->createElement('static', '', '', ' ' . + get_string('label', 'qtype_ddimageortext').' '); + $grouparray[] = $mform->createElement('text', 'droplabel', + get_string('label', 'qtype_ddimageortext'), + array('size'=>10, 'class'=>'tweakcss')); + $mform->setType('droplabel', PARAM_NOTAGS); + $dropzone = $mform->createElement('group', 'drops', + get_string('dropzone', 'qtype_ddimageortext', '{no}'), $grouparray); + return array($dropzone); + } + + protected function drop_zones_repeated_options() { + $repeatedoptions = array(); + $repeatedoptions['choice']['default'] = '0'; + return $repeatedoptions; + } + + protected function definition_draggable_images($mform, $imagerepeatsatstart) { + + $this->repeat_elements($this->draggable_image($mform), $imagerepeatsatstart, + $this->draggable_images_repeated_options(), + 'noitems', 'additems', self::ADD_NUM_ITEMS, + get_string('addmoreimages', 'qtype_ddimageortext')); + } + + protected function draggable_image($mform) { + $draggableimageitem = array(); + + $draggableimageitem[] = $mform->createElement('header', 'draggableitemheader', + get_string('draggableitemheader', 'qtype_ddimageortext', '{no}')); + $dragitemtypes = array('image' => get_string('draggableimage', 'qtype_ddimageortext'), + 'word' => get_string('draggableword', 'qtype_ddimageortext')); + $draggableimageitem[] = $mform->createElement('select', 'dragitemtype', + get_string('draggableitemtype', 'qtype_ddimageortext'), + $dragitemtypes, + array('class' => 'dragitemtype')); + $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null, + self::file_picker_options()); + + $grouparray = array(); + $grouparray[] = $mform->createElement('text', 'draglabel', + get_string('label', 'qtype_ddimageortext'), + array('size'=>30, 'class'=>'tweakcss')); + $mform->setType('draglabel', PARAM_NOTAGS); + $options = array(); + for ($i = 1; $i <= self::MAX_GROUPS; $i += 1) { + $options[$i] = $i; + } + $grouparray[] = $mform->createElement('static', '', '', ' ' . + get_string('group', 'qtype_gapselect').' '); + $grouparray[] = $mform->createElement('select', 'draggroup', + get_string('group', 'qtype_gapselect'), + $options, + array('class' => 'draggroup')); + $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ', + get_string('infinite', 'qtype_ddimageortext')); + $draggableimageitem[] = $mform->createElement('group', 'drags', + get_string('label', 'qtype_ddimageortext'), $grouparray); + return $draggableimageitem; + } + + protected function draggable_images_repeated_options() { + $repeatedoptions = array(); + $repeatedoptions['draggroup']['default'] = '1'; + return $repeatedoptions; + } + + public function data_preprocessing($question) { + global $PAGE; + + $question = parent::data_preprocessing($question); + $question = $this->data_preprocessing_combined_feedback($question, true); + $question = $this->data_preprocessing_hints($question, true, true); + + $dragids = array(); // drag no -> dragid + if (!empty($question->options)) { + $question->shuffleanswers = $question->options->shuffleanswers; + $question->drags = array(); + foreach ($question->options->drags as $drag) { + $dragindex = $drag->no -1; + $question->drags[$dragindex] = array(); + $question->drags[$dragindex]['draglabel'] = $drag->label; + $question->drags[$dragindex]['infinite'] = $drag->infinite; + $question->drags[$dragindex]['draggroup'] = $drag->draggroup; + $dragids[$dragindex] = $drag->id; + } + $question->drops = array(); + foreach ($question->options->drops as $drop) { + $question->drops[$drop->no -1] = array(); + $question->drops[$drop->no -1]['choice'] = $drop->choice; + $question->drops[$drop->no -1]['droplabel'] = $drop->label; + $question->drops[$drop->no -1]['xleft'] = $drop->xleft; + $question->drops[$drop->no -1]['ytop'] = $drop->ytop; + } + } + //initialise file picker for bgimage + $draftitemid = file_get_submitted_draft_itemid('bgimage'); + + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', + 'bgimage', !empty($question->id) ? (int) $question->id : null, + self::file_picker_options()); + $question->bgimage = $draftitemid; + + //initialise file picker for dragimages + list(, $imagerepeats) = $this->get_drag_image_repeats(); + $draftitemids = optional_param_array('dragitem', array(), PARAM_INT); + for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { + $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; + //numbers not allowed in filearea name + $itemid = isset($dragids[$imageindex]) ? $dragids[$imageindex] : null; + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', + 'dragimage', $itemid, self::file_picker_options()); + $question->dragitem[$imageindex] = $draftitemid; + } + if (!empty($question->options)) { + foreach ($question->options->drags as $drag) { + $dragindex = $drag->no -1; + if (!isset($question->dragitem[$dragindex])) { + $fileexists = false; + } else { + $fileexists = self::file_uploaded($question->dragitem[$dragindex]); + } + $labelexists = $question->drags[$dragindex]['draglabel']; + if ($labelexists && !$fileexists) { + $question->dragitemtype[$dragindex] = 'word'; + } else { + $question->dragitemtype[$dragindex] = 'image'; + } + } + } + $maxsizes =new stdClass(); + $maxsizes->bgimage = new stdClass(); + $maxsizes->bgimage->width = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH; + $maxsizes->bgimage->height = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT; + $maxsizes->dragimage = new stdClass(); + $maxsizes->dragimage->width = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH; + $maxsizes->dragimage->height = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT; + + $params = array('maxsizes' => $maxsizes, + 'topnode' => 'fieldset#previewareaheader'); + + $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', + 'M.qtype_ddimageortext.init_form', + array($params)); + return $question; + } + + + public static function file_uploaded($draftitemid) { + $draftareafiles = file_get_drafarea_files($draftitemid); + do { + $draftareafile = array_shift($draftareafiles->list); + } while ($draftareafile !== null && $draftareafile->filename == '.'); + if ($draftareafile === null) { + return false; + } + return true; + } + + public function validation($data, $files) { + $errors = parent::validation($data, $files); + if (!self::file_uploaded($data['bgimage'])) { + $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddimageortext'); + } + + $allchoices = array(); + for ($i=0; $i < $data['nodropzone']; $i++) { + $ytoppresent = (trim($data['drops'][$i]['ytop']) !== ''); + $xleftpresent = (trim($data['drops'][$i]['ytop']) !== ''); + $labelpresent = (trim($data['drops'][$i]['droplabel']) !== ''); + $choice = $data['drops'][$i]['choice']; + $imagechoicepresent = ($choice !== '0'); + + if ($imagechoicepresent) { + if (!$ytoppresent) { + $errors["drops[$i]"] = + get_string('formerror_noytop', 'qtype_ddimageortext'); + } + if (!$xleftpresent) { + $errors["drops[$i]"] = + get_string('formerror_noxleft', 'qtype_ddimageortext'); + } + + if ($data['dragitemtype'][$choice - 1] != 'word' && + !self::file_uploaded($data['dragitem'][$choice - 1])) { + $errors['dragitem['.($choice - 1).']'] = + get_string('formerror_nofile', 'qtype_ddimageortext', $i); + } + + if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { + $errors["drops[$i]"] = + get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); + $errors['drops['.($allchoices[$choice]).']'] = + get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); + $errors['drags['.($choice-1).']'] = + get_string('formerror_multipledraginstance2', 'qtype_ddimageortext', $choice); + } + $allchoices[$choice] = $i; + } else { + if ($ytoppresent || $xleftpresent || $labelpresent) { + $errors["drops[$i]"] = + get_string('formerror_noimageselected', 'qtype_ddimageortext'); + } + } + } + for ($dragindex=0; $dragindex < $data['noitems']; $dragindex++) { + $label = $data['drags'][$dragindex]['draglabel']; + if ($data['dragitemtype'][$dragindex] == 'word') { + $allowedtags = '
'; + $errormessage = get_string('formerror_disallowedtags', 'qtype_ddimageortext'); + } else { + $allowedtags = ''; + $errormessage = get_string('formerror_noallowedtags', 'qtype_ddimageortext'); + } + if ($label != strip_tags($label, $allowedtags)) { + $errors["drags[{$dragindex}]"] = $errormessage; + } + + } + return $errors; + } + + + +} diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index bebf06d6236..bb716b567ca 100755 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); +require_once($CFG->dirroot . '/question/type/ddimageortext/questionbase.php'); /** @@ -35,128 +35,8 @@ require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimageortext_question extends qtype_gapselect_question_base { - public function clear_wrong_from_response(array $response) { - foreach ($this->places as $place => $notused) { - if (array_key_exists($this->field($place), $response) && - $response[$this->field($place)] != $this->get_right_choice_for($place)) { - $response[$this->field($place)] = ''; - } - } - return $response; - } +class qtype_ddimageortext_question extends qtype_ddtoimage_question_base { - public function get_right_choice_for($placeno) { - $place = $this->places[$placeno]; - foreach ($this->choiceorder[$place->group] as $choicekey => $choiceid) { - if ($this->rightchoices[$placeno] == $choiceid) { - return $choicekey; - } - } - } - public function summarise_response(array $response) { - $allblank = true; - foreach ($this->places as $placeno => $place) { - $summariseplace = $place->summarise(); - if (array_key_exists($this->field($placeno), $response) && - $response[$this->field($placeno)]) { - $selected = $this->get_selected_choice($place->group, - $response[$this->field($placeno)]); - $summarisechoice = $selected->summarise(); - $allblank = false; - } else { - $summarisechoice = ''; - } - $choices[] = "$summariseplace -> {{$summarisechoice}}"; - } - if ($allblank) { - return null; - } - return implode(' ', $choices); - } - - public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) { - if ($filearea == 'bgimage' || $filearea == 'dragimage') { - $validfilearea = true; - } else { - $validfilearea = false; - } - if ($component == 'qtype_ddimageortext' && $validfilearea) { - $question = $qa->get_question(); - $itemid = reset($args); - if ($filearea == 'bgimage') { - return $itemid == $question->id; - } else if ($filearea == 'dragimage') { - foreach ($question->choices as $group) { - foreach ($group as $drag) { - if ($drag->id == $itemid) { - return true; - } - } - } - return false; - } - } else { - return parent::check_file_access($qa, $options, $component, - $filearea, $args, $forcedownload); - } - } - public function get_validation_error(array $response) { - if ($this->is_complete_response($response)) { - return ''; - } - return get_string('pleasedraganimagetoeachdropregion', 'qtype_ddimageortext'); - } - - public function classify_response(array $response) { - $parts = array(); - foreach ($this->places as $placeno => $place) { - $group = $place->group; - if (!array_key_exists($this->field($placeno), $response) || - !$response[$this->field($placeno)]) { - $parts[$placeno] = question_classified_response::no_response(); - continue; - } - - $fieldname = $this->field($placeno); - $choiceno = $this->choiceorder[$group][$response[$fieldname]]; - $choice = $this->choices[$group][$choiceno]; - - $correct = $this->get_right_choice_for($placeno) == $response[$fieldname]; - $parts[$placeno] = new question_classified_response( - $choiceno, $choice->summarise(), $correct?1:0); - } - return $parts; - } - - public function get_random_guess_score() { - $accum = 0; - - foreach ($this->places as $place) { - $accum += 1 / count($this->choices[$place->group]); - } - - return $accum / count($this->places); - } - - - public function get_question_summary() { - $summary = ''; - if (!html_is_blank($this->questiontext)) { - $question = $this->html_to_text($this->questiontext, $this->questiontextformat); - $summary .= $question . '; '; - } - $places = array(); - foreach ($this->places as $place) { - $cs = array(); - foreach ($this->choices[$place->group] as $choice) { - $cs[] = $choice->summarise(); - } - $places[] = '[[' . $place->summarise() . ']] -> {' . implode(' / ', $cs) . '}'; - } - $summary .= implode('; ', $places); - return $summary; - } } diff --git a/question/type/ddimageortext/questionbase.php b/question/type/ddimageortext/questionbase.php new file mode 100644 index 00000000000..3f594355ba7 --- /dev/null +++ b/question/type/ddimageortext/questionbase.php @@ -0,0 +1,161 @@ +. + +/** + * Drag-and-drop words into sentences question definition class. + * + * @package qtype + * @subpackage ddimageortext + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); + + +/** + * Represents a drag-and-drop images to image question. + * + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddtoimage_question_base extends qtype_gapselect_question_base { + public function clear_wrong_from_response(array $response) { + foreach ($this->places as $place => $notused) { + if (array_key_exists($this->field($place), $response) && + $response[$this->field($place)] != $this->get_right_choice_for($place)) { + $response[$this->field($place)] = ''; + } + } + return $response; + } + + public function get_right_choice_for($placeno) { + $place = $this->places[$placeno]; + foreach ($this->choiceorder[$place->group] as $choicekey => $choiceid) { + if ($this->rightchoices[$placeno] == $choiceid) { + return $choicekey; + } + } + } + public function summarise_response(array $response) { + $allblank = true; + foreach ($this->places as $placeno => $place) { + $summariseplace = $place->summarise(); + if (array_key_exists($this->field($placeno), $response) && + $response[$this->field($placeno)]) { + $selected = $this->get_selected_choice($place->group, + $response[$this->field($placeno)]); + $summarisechoice = $selected->summarise(); + $allblank = false; + } else { + $summarisechoice = ''; + } + $choices[] = "$summariseplace -> {{$summarisechoice}}"; + } + if ($allblank) { + return null; + } + return implode(' ', $choices); + } + + public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) { + if ($filearea == 'bgimage' || $filearea == 'dragimage') { + $validfilearea = true; + } else { + $validfilearea = false; + } + if ($component == 'qtype_ddimageortext' && $validfilearea) { + $question = $qa->get_question(); + $itemid = reset($args); + if ($filearea == 'bgimage') { + return $itemid == $question->id; + } else if ($filearea == 'dragimage') { + foreach ($question->choices as $group) { + foreach ($group as $drag) { + if ($drag->id == $itemid) { + return true; + } + } + } + return false; + } + } else { + return parent::check_file_access($qa, $options, $component, + $filearea, $args, $forcedownload); + } + } + public function get_validation_error(array $response) { + if ($this->is_complete_response($response)) { + return ''; + } + return get_string('pleasedraganimagetoeachdropregion', 'qtype_ddimageortext'); + } + + public function classify_response(array $response) { + $parts = array(); + foreach ($this->places as $placeno => $place) { + $group = $place->group; + if (!array_key_exists($this->field($placeno), $response) || + !$response[$this->field($placeno)]) { + $parts[$placeno] = question_classified_response::no_response(); + continue; + } + + $fieldname = $this->field($placeno); + $choiceno = $this->choiceorder[$group][$response[$fieldname]]; + $choice = $this->choices[$group][$choiceno]; + + $correct = $this->get_right_choice_for($placeno) == $response[$fieldname]; + $parts[$placeno] = new question_classified_response( + $choiceno, $choice->summarise(), $correct?1:0); + } + return $parts; + } + + public function get_random_guess_score() { + $accum = 0; + + foreach ($this->places as $place) { + $accum += 1 / count($this->choices[$place->group]); + } + + return $accum / count($this->places); + } + + + public function get_question_summary() { + $summary = ''; + if (!html_is_blank($this->questiontext)) { + $question = $this->html_to_text($this->questiontext, $this->questiontextformat); + $summary .= $question . '; '; + } + $places = array(); + foreach ($this->places as $place) { + $cs = array(); + foreach ($this->choices[$place->group] as $choice) { + $cs[] = $choice->summarise(); + } + $places[] = '[[' . $place->summarise() . ']] -> {' . implode(' / ', $cs) . '}'; + } + $summary .= implode('; ', $places); + return $summary; + } +} + diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index dc81a17ad83..34879f0e244 100755 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -26,10 +26,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->libdir . '/questionlib.php'); -require_once($CFG->dirroot . '/question/engine/lib.php'); -require_once($CFG->dirroot . '/question/format/xml/format.php'); -require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); +require_once($CFG->dirroot . '/question/type/ddimageortext/questiontypebase.php'); define('QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH', 600); define('QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT', 400); @@ -42,423 +39,6 @@ define('QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT', 100); * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimageortext extends question_type { - protected function choice_group_key() { - return 'draggroup'; - } - - public function requires_qtypes() { - return array('gapselect'); - } - - public function get_question_options($question) { - global $DB; - $question->options = $DB->get_record('qtype_ddimageortext', - array('questionid' => $question->id), '*', MUST_EXIST); - $question->options->drags = $DB->get_records('qtype_ddimageortext_drags', - array('questionid' => $question->id), 'no ASC', '*'); - $question->options->drops = $DB->get_records('qtype_ddimageortext_drops', - array('questionid' => $question->id), 'no ASC', '*'); - parent::get_question_options($question); - } - - protected function make_choice($dragdata) { - return new qtype_ddimageortext_drag_item($dragdata->label, $dragdata->no, - $dragdata->draggroup, $dragdata->infinite, $dragdata->id); - } - - protected function make_place($dropzonedata) { - return new qtype_ddimageortext_drop_zone($dropzonedata->label, $dropzonedata->no, - $dropzonedata->group, - $dropzonedata->xleft, $dropzonedata->ytop); - } - - protected function make_hint($hint) { - return question_hint_with_parts::load_from_record($hint); - } - - protected function initialise_question_instance(question_definition $question, $questiondata) { - parent::initialise_question_instance($question, $questiondata); - $question->shufflechoices = $questiondata->options->shuffleanswers; - - $this->initialise_combined_feedback($question, $questiondata, true); - - $question->choices = array(); - $choiceindexmap= array(); - - // Store the choices in arrays by group. - foreach ($questiondata->options->drags as $dragdata) { - - $choice = $this->make_choice($dragdata); - - if (array_key_exists($choice->choice_group(), $question->choices)) { - $question->choices[$choice->choice_group()][$dragdata->no] = $choice; - } else { - $question->choices[$choice->choice_group()][1] = $choice; - } - - end($question->choices[$choice->choice_group()]); - $choiceindexmap[$dragdata->no] = array($choice->choice_group(), - key($question->choices[$choice->choice_group()])); - } - - $question->places = array(); - $question->rightchoices = array(); - - $i = 1; - - foreach ($questiondata->options->drops as $dropdata) { - list($group, $choiceindex) = $choiceindexmap[$dropdata->choice]; - $dropdata->group = $group; - $question->places[$dropdata->no] = $this->make_place($dropdata); - $question->rightchoices[$dropdata->no] = $choiceindex; - } - } - - public function save_question_options($formdata) { - global $DB, $USER; - $context = $formdata->context; - - $options = $DB->get_record('qtype_ddimageortext', array('questionid' => $formdata->id)); - if (!$options) { - $options = new stdClass(); - $options->questionid = $formdata->id; - $options->correctfeedback = ''; - $options->partiallycorrectfeedback = ''; - $options->incorrectfeedback = ''; - $options->id = $DB->insert_record('qtype_ddimageortext', $options); - } - - $options->shuffleanswers = !empty($formdata->shuffleanswers); - $options = $this->save_combined_feedback_helper($options, $formdata, $context, true); - $this->save_hints($formdata, true); - $DB->update_record('qtype_ddimageortext', $options); - $DB->delete_records('qtype_ddimageortext_drops', array('questionid' => $formdata->id)); - foreach (array_keys($formdata->drops) as $dropno) { - if ($formdata->drops[$dropno]['choice'] == 0) { - continue; - } - $drop = new stdClass(); - $drop->questionid = $formdata->id; - $drop->no = $dropno + 1; - $drop->xleft = $formdata->drops[$dropno]['xleft']; - $drop->ytop = $formdata->drops[$dropno]['ytop']; - $drop->choice = $formdata->drops[$dropno]['choice']; - $drop->label = $formdata->drops[$dropno]['droplabel']; - - $DB->insert_record('qtype_ddimageortext_drops', $drop); - } - - //an array of drag no -> drag id - $olddragids = $DB->get_records_menu('qtype_ddimageortext_drags', - array('questionid' => $formdata->id), - '', 'no, id'); - foreach (array_keys($formdata->drags) as $dragno) { - $info = file_get_draft_area_info($formdata->dragitem[$dragno]); - if ($info['filecount'] > 0 || !empty($formdata->drags[$dragno]['draglabel'])) { - $draftitemid = $formdata->dragitem[$dragno]; - - $drag = new stdClass(); - $drag->questionid = $formdata->id; - $drag->no = $dragno + 1; - $drag->draggroup = $formdata->drags[$dragno]['draggroup']; - $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; - $drag->label = $formdata->drags[$dragno]['draglabel']; - - if (isset($olddragids[$dragno +1])) { - $drag->id = $olddragids[$dragno +1]; - unset($olddragids[$dragno +1]); - $DB->update_record('qtype_ddimageortext_drags', $drag); - } else { - $drag->id = $DB->insert_record('qtype_ddimageortext_drags', $drag); - } - - if ($formdata->dragitemtype[$dragno] == 'image') { - self::constrain_image_size_in_draft_area($draftitemid, - QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH, - QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT); - file_save_draft_area_files($draftitemid, $formdata->context->id, - 'qtype_ddimageortext', 'dragimage', $drag->id, - array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); - } else { - //delete any existing files for draggable text item type - $fs = get_file_storage(); - $fs->delete_area_files($formdata->context->id, 'qtype_ddimageortext', - 'dragimage', $drag->id); - } - - } - - } - if (!empty($olddragids)) { - list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); - $DB->delete_records_select('qtype_ddimageortext_drags', "id $sql", $params); - } - - self::constrain_image_size_in_draft_area($formdata->bgimage, - QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH, - QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT); - file_save_draft_area_files($formdata->bgimage, $formdata->context->id, - 'qtype_ddimageortext', 'bgimage', $formdata->id, - array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); - } - - - public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) { - global $USER; - $usercontext = get_context_instance(CONTEXT_USER, $USER->id); - $fs = get_file_storage(); - $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id'); - if ($draftfiles) { - foreach ($draftfiles as $file) { - if ($file->is_directory()) { - continue; - } - $imageinfo = $file->get_imageinfo(); - $width = $imageinfo['width']; - $height = $imageinfo['height']; - $mimetype = $imageinfo['mimetype']; - switch ($mimetype) { - case 'image/jpeg' : - $quality = 80; - break; - case 'image/png' : - $quality = 8; - break; - default : - $quality = null; - } - $newwidth = min($maxwidth, $width); - $newheight = min($maxheight, $height); - if ($newwidth != $width || $newheight != $height) { - $newimagefilename = $file->get_filename(); - $newimagefilename = - preg_replace('!\.!', "_{$newwidth}x{$newheight}.", $newimagefilename, 1); - $newrecord = new stdClass(); - $newrecord->contextid = $usercontext->id; - $newrecord->component = 'user'; - $newrecord->filearea = 'draft'; - $newrecord->itemid = $draftitemid; - $newrecord->filepath = '/'; - $newrecord->filename = $newimagefilename; - $fs->convert_image($newrecord, $file, $newwidth, $newheight, true, $quality); - $file->delete(); - } - } - } - } - public function move_files($questionid, $oldcontextid, $newcontextid) { - global $DB; - $fs = get_file_storage(); - - parent::move_files($questionid, $oldcontextid, $newcontextid); - $fs->move_area_files_to_new_context($oldcontextid, - $newcontextid, 'qtype_ddimageortext', 'bgimage', $questionid); - $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', - array('questionid' => $questionid), 'id', 'id,1'); - foreach ($dragids as $dragid => $notused) { - $fs->move_area_files_to_new_context($oldcontextid, - $newcontextid, 'qtype_ddimageortext', 'dragimage', $dragid); - } - - $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); - } - - /** - * Delete all the files belonging to this question. - * @param int $questionid the question being deleted. - * @param int $contextid the context the question is in. - */ - - protected function delete_files($questionid, $contextid) { - global $DB; - $fs = get_file_storage(); - - parent::delete_files($questionid, $contextid); - - $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', - array('questionid' => $questionid), 'id', 'id,1'); - foreach ($dragids as $dragid => $notused) { - $fs->delete_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $dragid); - } - - $this->delete_files_in_combined_feedback($questionid, $contextid); - } - - public function export_to_xml($question, $format, $extra = null) { - $fs = get_file_storage(); - $contextid = $question->contextid; - $output = ''; - - if ($question->options->shuffleanswers) { - $output .= " \n"; - } - $output .= $format->write_combined_feedback($question->options); - $output .= $format->write_hints($question); - $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); - $output .= " ".$this->write_files($files, 2)."\n";; - - foreach ($question->options->drags as $drag) { - $files = - $fs->get_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $drag->id); - $output .= " \n"; - $output .= " {$drag->no}\n"; - $output .= $format->writetext($drag->label, 3)."\n"; - $output .= " {$drag->draggroup}\n"; - if ($drag->infinite) { - $output .= " \n"; - } - $output .= $this->write_files($files, 3); - $output .= " \n"; - } - foreach ($question->options->drops as $drop) { - $output .= " \n"; - $output .= $format->writetext($drop->label, 3); - $output .= " {$drop->no}\n"; - $output .= " {$drop->choice}\n"; - $output .= " {$drop->xleft}\n"; - $output .= " {$drop->ytop}\n"; - $output .= " \n"; - } - - return $output; - } - - public function import_from_xml($data, $question, $format, $extra=null) { - if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimageortext') { - return false; - } - - $question = $format->import_headers($data); - $question->qtype = 'ddimageortext'; - - $question->shuffleanswers = array_key_exists('shuffleanswers', - $format->getpath($data, array('#'), array())); - - $filexml = $format->getpath($data, array('#', 'file'), array()); - $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml); - $drags = $data['#']['drag']; - $question->drags = array(); - - foreach ($drags as $dragxml) { - $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0); - $dragindex = $dragno -1; - $question->drags[$dragindex] = array(); - $question->drags[$dragindex]['draglabel'] = - $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); - $question->drags[$dragindex]['infinite'] = array_key_exists('infinite', $dragxml['#']); - $question->drags[$dragindex]['draggroup'] = - $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1); - $filexml = $format->getpath($dragxml, array('#', 'file'), array()); - $question->dragitem[$dragindex] = - $this->import_files_to_draft_file_area($format, $filexml); - if (count($filexml)) { - $question->dragitemtype[$dragindex] = 'image'; - } else { - $question->dragitemtype[$dragindex] = 'word'; - } - } - - $drops = $data['#']['drop']; - $question->drops = array(); - foreach ($drops as $dropxml) { - $dropno = $format->getpath($dropxml, array('#', 'no', 0, '#'), 0); - $dropindex = $dropno -1; - $question->drops[$dropindex] = array(); - $question->drops[$dropindex]['choice'] = - $format->getpath($dropxml, array('#', 'choice', 0, '#'), 0); - $question->drops[$dropindex]['droplabel'] = - $format->getpath($dropxml, array('#', 'text', 0, '#'), '', true); - $question->drops[$dropindex]['xleft'] = - $format->getpath($dropxml, array('#', 'xleft', 0, '#'), ''); - $question->drops[$dropindex]['ytop'] = - $format->getpath($dropxml, array('#', 'ytop', 0, '#'), ''); - } - - $format->import_combined_feedback($question, $data, true); - $format->import_hints($question, $data, true); - - return $question; - } - - - /** - * Create a draft files area, import files into it and return the draft item id. - * @param qformat_xml $format - * @param array $xml an array of nodes from the the parsed XML. - * @return integer draftitemid - */ - public function import_files_to_draft_file_area($format, $xml) { - global $USER; - $fs = get_file_storage(); - $files = $format->import_files($xml); - $usercontext = get_context_instance(CONTEXT_USER, $USER->id); - $draftitemid = file_get_unused_draft_itemid(); - foreach ($files as $file) { - $record = new stdClass(); - $record->contextid = $usercontext->id; - $record->component = 'user'; - $record->filearea = 'draft'; - $record->itemid = $draftitemid; - $record->filename = $file->name; - $record->filepath = '/'; - $fs->create_file_from_string($record, $this->decode_file($file)); - } - return $draftitemid; - } - - /** - * Convert files into text output in the given format. - * This method is copied from qformat_default as a quick fix, as the method there is - * protected. - * @param array - * @param string encoding method - * @return string $string - */ - public function write_files($files, $indent) { - if (empty($files)) { - return ''; - } - $string = ''; - foreach ($files as $file) { - if ($file->is_directory()) { - continue; - } - $string .= str_repeat(' ', $indent); - $string .= ''; - $string .= base64_encode($file->get_content()); - $string .= "\n"; - } - return $string; - } - - public function get_possible_responses($questiondata) { - $question = $this->make_question($questiondata); - - $parts = array(); - foreach ($question->places as $placeno => $place) { - $group = $place->group; - $choices = array(); - - foreach ($question->choices[$group] as $i => $choice) { - $summarisechoice = $choice->summarise(); - - $correct = $question->rightchoices[$placeno] == $i; - $choices[$choice->no] = new question_possible_response( - $summarisechoice, - $correct?1:0); - } - $choices[null] = question_possible_response::no_response(); - - $parts[$placeno] = $choices; - } - - return $parts; - } - - public function get_random_guess_score($questiondata) { - $question = $this->make_question($questiondata); - return $question->get_random_guess_score(); - } +class qtype_ddimageortext extends qtype_ddtoimage_base { } diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php new file mode 100644 index 00000000000..ede7b5e87b4 --- /dev/null +++ b/question/type/ddimageortext/questiontypebase.php @@ -0,0 +1,459 @@ +. + +/** + * Question type class for the drag-and-drop images onto images question type. + * + * @package qtype + * @subpackage ddimageortext + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->libdir . '/questionlib.php'); +require_once($CFG->dirroot . '/question/engine/lib.php'); +require_once($CFG->dirroot . '/question/format/xml/format.php'); +require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); + +/** + * The drag-and-drop words into sentences question type class. + * + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddtoimage_base extends question_type { + protected function choice_group_key() { + return 'draggroup'; + } + + public function requires_qtypes() { + return array_merge(parent::requires_qtypes(), array('ddimageortext')); + } + + public function get_question_options($question) { + global $DB; + $question->options = $DB->get_record('qtype_ddimageortext', + array('questionid' => $question->id), '*', MUST_EXIST); + $question->options->drags = $DB->get_records('qtype_ddimageortext_drags', + array('questionid' => $question->id), 'no ASC', '*'); + $question->options->drops = $DB->get_records('qtype_ddimageortext_drops', + array('questionid' => $question->id), 'no ASC', '*'); + parent::get_question_options($question); + } + + protected function make_choice($dragdata) { + return new qtype_ddimageortext_drag_item($dragdata->label, $dragdata->no, + $dragdata->draggroup, $dragdata->infinite, $dragdata->id); + } + + protected function make_place($dropzonedata) { + return new qtype_ddimageortext_drop_zone($dropzonedata->label, $dropzonedata->no, + $dropzonedata->group, + $dropzonedata->xleft, $dropzonedata->ytop); + } + + protected function make_hint($hint) { + return question_hint_with_parts::load_from_record($hint); + } + + protected function initialise_question_instance(question_definition $question, $questiondata) { + parent::initialise_question_instance($question, $questiondata); + $question->shufflechoices = $questiondata->options->shuffleanswers; + + $this->initialise_combined_feedback($question, $questiondata, true); + + $question->choices = array(); + $choiceindexmap= array(); + + // Store the choices in arrays by group. + foreach ($questiondata->options->drags as $dragdata) { + + $choice = $this->make_choice($dragdata); + + if (array_key_exists($choice->choice_group(), $question->choices)) { + $question->choices[$choice->choice_group()][$dragdata->no] = $choice; + } else { + $question->choices[$choice->choice_group()][1] = $choice; + } + + end($question->choices[$choice->choice_group()]); + $choiceindexmap[$dragdata->no] = array($choice->choice_group(), + key($question->choices[$choice->choice_group()])); + } + + $question->places = array(); + $question->rightchoices = array(); + + $i = 1; + + foreach ($questiondata->options->drops as $dropdata) { + list($group, $choiceindex) = $choiceindexmap[$dropdata->choice]; + $dropdata->group = $group; + $question->places[$dropdata->no] = $this->make_place($dropdata); + $question->rightchoices[$dropdata->no] = $choiceindex; + } + } + + public function save_question_options($formdata) { + global $DB, $USER; + $context = $formdata->context; + + $options = $DB->get_record('qtype_ddimageortext', array('questionid' => $formdata->id)); + if (!$options) { + $options = new stdClass(); + $options->questionid = $formdata->id; + $options->correctfeedback = ''; + $options->partiallycorrectfeedback = ''; + $options->incorrectfeedback = ''; + $options->id = $DB->insert_record('qtype_ddimageortext', $options); + } + + $options->shuffleanswers = !empty($formdata->shuffleanswers); + $options = $this->save_combined_feedback_helper($options, $formdata, $context, true); + $this->save_hints($formdata, true); + $DB->update_record('qtype_ddimageortext', $options); + $DB->delete_records('qtype_ddimageortext_drops', array('questionid' => $formdata->id)); + foreach (array_keys($formdata->drops) as $dropno) { + if ($formdata->drops[$dropno]['choice'] == 0) { + continue; + } + $drop = new stdClass(); + $drop->questionid = $formdata->id; + $drop->no = $dropno + 1; + $drop->xleft = $formdata->drops[$dropno]['xleft']; + $drop->ytop = $formdata->drops[$dropno]['ytop']; + $drop->choice = $formdata->drops[$dropno]['choice']; + $drop->label = $formdata->drops[$dropno]['droplabel']; + + $DB->insert_record('qtype_ddimageortext_drops', $drop); + } + + //an array of drag no -> drag id + $olddragids = $DB->get_records_menu('qtype_ddimageortext_drags', + array('questionid' => $formdata->id), + '', 'no, id'); + foreach (array_keys($formdata->drags) as $dragno) { + $info = file_get_draft_area_info($formdata->dragitem[$dragno]); + if ($info['filecount'] > 0 || !empty($formdata->drags[$dragno]['draglabel'])) { + $draftitemid = $formdata->dragitem[$dragno]; + + $drag = new stdClass(); + $drag->questionid = $formdata->id; + $drag->no = $dragno + 1; + $drag->draggroup = $formdata->drags[$dragno]['draggroup']; + $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; + $drag->label = $formdata->drags[$dragno]['draglabel']; + + if (isset($olddragids[$dragno +1])) { + $drag->id = $olddragids[$dragno +1]; + unset($olddragids[$dragno +1]); + $DB->update_record('qtype_ddimageortext_drags', $drag); + } else { + $drag->id = $DB->insert_record('qtype_ddimageortext_drags', $drag); + } + + if ($formdata->dragitemtype[$dragno] == 'image') { + self::constrain_image_size_in_draft_area($draftitemid, + QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH, + QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT); + file_save_draft_area_files($draftitemid, $formdata->context->id, + 'qtype_ddimageortext', 'dragimage', $drag->id, + array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); + } else { + //delete any existing files for draggable text item type + $fs = get_file_storage(); + $fs->delete_area_files($formdata->context->id, 'qtype_ddimageortext', + 'dragimage', $drag->id); + } + + } + + } + if (!empty($olddragids)) { + list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); + $DB->delete_records_select('qtype_ddimageortext_drags', "id $sql", $params); + } + + self::constrain_image_size_in_draft_area($formdata->bgimage, + QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH, + QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT); + file_save_draft_area_files($formdata->bgimage, $formdata->context->id, + 'qtype_ddimageortext', 'bgimage', $formdata->id, + array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); + } + + + public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) { + global $USER; + $usercontext = get_context_instance(CONTEXT_USER, $USER->id); + $fs = get_file_storage(); + $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id'); + if ($draftfiles) { + foreach ($draftfiles as $file) { + if ($file->is_directory()) { + continue; + } + $imageinfo = $file->get_imageinfo(); + $width = $imageinfo['width']; + $height = $imageinfo['height']; + $mimetype = $imageinfo['mimetype']; + switch ($mimetype) { + case 'image/jpeg' : + $quality = 80; + break; + case 'image/png' : + $quality = 8; + break; + default : + $quality = null; + } + $newwidth = min($maxwidth, $width); + $newheight = min($maxheight, $height); + if ($newwidth != $width || $newheight != $height) { + $newimagefilename = $file->get_filename(); + $newimagefilename = + preg_replace('!\.!', "_{$newwidth}x{$newheight}.", $newimagefilename, 1); + $newrecord = new stdClass(); + $newrecord->contextid = $usercontext->id; + $newrecord->component = 'user'; + $newrecord->filearea = 'draft'; + $newrecord->itemid = $draftitemid; + $newrecord->filepath = '/'; + $newrecord->filename = $newimagefilename; + $fs->convert_image($newrecord, $file, $newwidth, $newheight, true, $quality); + $file->delete(); + } + } + } + } + public function move_files($questionid, $oldcontextid, $newcontextid) { + global $DB; + $fs = get_file_storage(); + + parent::move_files($questionid, $oldcontextid, $newcontextid); + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'qtype_ddimageortext', 'bgimage', $questionid); + $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', + array('questionid' => $questionid), 'id', 'id,1'); + foreach ($dragids as $dragid => $notused) { + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'qtype_ddimageortext', 'dragimage', $dragid); + } + + $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); + } + + /** + * Delete all the files belonging to this question. + * @param int $questionid the question being deleted. + * @param int $contextid the context the question is in. + */ + + protected function delete_files($questionid, $contextid) { + global $DB; + $fs = get_file_storage(); + + parent::delete_files($questionid, $contextid); + + $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', + array('questionid' => $questionid), 'id', 'id,1'); + foreach ($dragids as $dragid => $notused) { + $fs->delete_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $dragid); + } + + $this->delete_files_in_combined_feedback($questionid, $contextid); + } + + public function export_to_xml($question, $format, $extra = null) { + $fs = get_file_storage(); + $contextid = $question->contextid; + $output = ''; + + if ($question->options->shuffleanswers) { + $output .= " \n"; + } + $output .= $format->write_combined_feedback($question->options); + $output .= $format->write_hints($question); + $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); + $output .= " ".$this->write_files($files, 2)."\n";; + + foreach ($question->options->drags as $drag) { + $files = + $fs->get_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $drag->id); + $output .= " \n"; + $output .= " {$drag->no}\n"; + $output .= $format->writetext($drag->label, 3)."\n"; + $output .= " {$drag->draggroup}\n"; + if ($drag->infinite) { + $output .= " \n"; + } + $output .= $this->write_files($files, 3); + $output .= " \n"; + } + foreach ($question->options->drops as $drop) { + $output .= " \n"; + $output .= $format->writetext($drop->label, 3); + $output .= " {$drop->no}\n"; + $output .= " {$drop->choice}\n"; + $output .= " {$drop->xleft}\n"; + $output .= " {$drop->ytop}\n"; + $output .= " \n"; + } + + return $output; + } + + public function import_from_xml($data, $question, $format, $extra=null) { + if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimageortext') { + return false; + } + + $question = $format->import_headers($data); + $question->qtype = 'ddimageortext'; + + $question->shuffleanswers = array_key_exists('shuffleanswers', + $format->getpath($data, array('#'), array())); + + $filexml = $format->getpath($data, array('#', 'file'), array()); + $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml); + $drags = $data['#']['drag']; + $question->drags = array(); + + foreach ($drags as $dragxml) { + $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0); + $dragindex = $dragno -1; + $question->drags[$dragindex] = array(); + $question->drags[$dragindex]['draglabel'] = + $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); + $question->drags[$dragindex]['infinite'] = array_key_exists('infinite', $dragxml['#']); + $question->drags[$dragindex]['draggroup'] = + $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1); + $filexml = $format->getpath($dragxml, array('#', 'file'), array()); + $question->dragitem[$dragindex] = + $this->import_files_to_draft_file_area($format, $filexml); + if (count($filexml)) { + $question->dragitemtype[$dragindex] = 'image'; + } else { + $question->dragitemtype[$dragindex] = 'word'; + } + } + + $drops = $data['#']['drop']; + $question->drops = array(); + foreach ($drops as $dropxml) { + $dropno = $format->getpath($dropxml, array('#', 'no', 0, '#'), 0); + $dropindex = $dropno -1; + $question->drops[$dropindex] = array(); + $question->drops[$dropindex]['choice'] = + $format->getpath($dropxml, array('#', 'choice', 0, '#'), 0); + $question->drops[$dropindex]['droplabel'] = + $format->getpath($dropxml, array('#', 'text', 0, '#'), '', true); + $question->drops[$dropindex]['xleft'] = + $format->getpath($dropxml, array('#', 'xleft', 0, '#'), ''); + $question->drops[$dropindex]['ytop'] = + $format->getpath($dropxml, array('#', 'ytop', 0, '#'), ''); + } + + $format->import_combined_feedback($question, $data, true); + $format->import_hints($question, $data, true); + + return $question; + } + + + /** + * Create a draft files area, import files into it and return the draft item id. + * @param qformat_xml $format + * @param array $xml an array of nodes from the the parsed XML. + * @return integer draftitemid + */ + public function import_files_to_draft_file_area($format, $xml) { + global $USER; + $fs = get_file_storage(); + $files = $format->import_files($xml); + $usercontext = get_context_instance(CONTEXT_USER, $USER->id); + $draftitemid = file_get_unused_draft_itemid(); + foreach ($files as $file) { + $record = new stdClass(); + $record->contextid = $usercontext->id; + $record->component = 'user'; + $record->filearea = 'draft'; + $record->itemid = $draftitemid; + $record->filename = $file->name; + $record->filepath = '/'; + $fs->create_file_from_string($record, $this->decode_file($file)); + } + return $draftitemid; + } + + /** + * Convert files into text output in the given format. + * This method is copied from qformat_default as a quick fix, as the method there is + * protected. + * @param array + * @param string encoding method + * @return string $string + */ + public function write_files($files, $indent) { + if (empty($files)) { + return ''; + } + $string = ''; + foreach ($files as $file) { + if ($file->is_directory()) { + continue; + } + $string .= str_repeat(' ', $indent); + $string .= ''; + $string .= base64_encode($file->get_content()); + $string .= "\n"; + } + return $string; + } + + public function get_possible_responses($questiondata) { + $question = $this->make_question($questiondata); + + $parts = array(); + foreach ($question->places as $placeno => $place) { + $group = $place->group; + $choices = array(); + + foreach ($question->choices[$group] as $i => $choice) { + $summarisechoice = $choice->summarise(); + + $correct = $question->rightchoices[$placeno] == $i; + $choices[$choice->no] = new question_possible_response( + $summarisechoice, + $correct?1:0); + } + $choices[null] = question_possible_response::no_response(); + + $parts[$placeno] = $choices; + } + + return $parts; + } + + public function get_random_guess_score($questiondata) { + $question = $this->make_question($questiondata); + return $question->get_random_guess_score(); + } + +} diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 32a10304814..335fd99c881 100755 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -26,8 +26,7 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); - +require_once($CFG->dirroot . '/question/type/ddimageortext/rendererbase.php'); /** * Generates the output for drag-and-drop words into sentences questions. @@ -35,146 +34,6 @@ require_once($CFG->dirroot . '/question/type/gapselect/rendererbase.php'); * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddimageortext_renderer extends qtype_with_combined_feedback_renderer { +class qtype_ddimageortext_renderer extends qtype_ddtoimage_renderer_base { - public function head_code(question_attempt $qa) { - return parent::head_code($qa); - } - public function clear_wrong(question_attempt $qa) { - $question = $qa->get_question(); - $response = $qa->get_last_qt_data(); - - if (!empty($response)) { - $cleanresponse = $question->clear_wrong_from_response($response); - } else { - $cleanresponse = $response; - } - $cleanresponsehtml = ''; - foreach ($cleanresponse as $fieldname => $value) { - list (, $html) = $this->hidden_field_for_qt_var($qa, $fieldname, $value); - $cleanresponsehtml .= $html; - } - return $cleanresponsehtml; - } - - public function formulation_and_controls(question_attempt $qa, - question_display_options $options) { - global $PAGE; - - $question = $qa->get_question(); - $response = $qa->get_last_qt_data(); - - $questiontext = $question->format_questiontext($qa); - - $output = html_writer::tag('div', $questiontext, array('class' => 'qtext')); - - $bgimage = self::get_url_for_image($qa, 'bgimage'); - - $img = html_writer::empty_tag('img', array('src'=>$bgimage, 'class'=>'dropbackground')); - $droparea = html_writer::tag('div', $img, array('class'=>'droparea')); - - $dragimagehomes = ''; - foreach ($question->choices as $groupno => $group) { - $dragimagehomesgroup = ''; - $orderedgroup = $question->get_ordered_choices($groupno); - foreach ($orderedgroup as $choiceno => $dragimage) { - $dragimageurl = self::get_url_for_image($qa, 'dragimage', $dragimage->id); - $classes = array("group{$groupno}", - 'draghome', - "dragitemhomes{$dragimage->no}", - "choice{$choiceno}"); - if ($dragimage->isinfinite) { - $classes[] = 'infinite'; - } - if ($dragimageurl === null) { - $classes[] = 'yui3-cssfonts'; - $dragimagehomesgroup .= html_writer::tag('div', - $dragimage->text, - array('src'=>$dragimageurl, - 'class'=>join(' ', $classes))); - } else { - $dragimagehomesgroup .= html_writer::empty_tag('img', - array('src'=>$dragimageurl, - 'alt' => $dragimage->text, - 'class'=>join(' ', $classes))); - } - } - $dragimagehomes .= html_writer::tag('div', $dragimagehomesgroup, - array('class'=>'dragitemgroup'.$groupno)); - } - - $dragitemsclass = 'dragitems'; - if ($options->readonly) { - $dragitemsclass .= ' readonly'; - } - $dragitems = html_writer::tag('div', $dragimagehomes, array('class'=> $dragitemsclass)); - $dropzones = html_writer::empty_tag('div', array('class'=>'dropzones')); - $output .= html_writer::tag('div', $droparea.$dragitems.$dropzones, - array('class'=>'ddarea')); - foreach ($question->places as $placeno => $place) { - $varname = $question->field($placeno); - list($fieldname, $html) = $this->hidden_field_for_qt_var($qa, $varname); - $output .= $html; - $question->places[$placeno]->fieldname = $fieldname; - } - $topnode = 'div#q'.$qa->get_slot().' div.ddarea'; - $params = array('drops' => $question->places, - 'topnode' => $topnode, - 'readonly' => $options->readonly); - - $PAGE->requires->yui_module('moodle-qtype_ddimageortext-dd', - 'M.qtype_ddimageortext.init_question', - array($params)); - - if ($qa->get_state() == question_state::$invalid) { - $output .= html_writer::nonempty_tag('div', - $question->get_validation_error($qa->get_last_qt_data()), - array('class' => 'validationerror')); - } - return $output; - } - - protected static function get_url_for_image(question_attempt $qa, $filearea, $itemid = 0) { - $question = $qa->get_question(); - $qubaid = $qa->get_usage_id(); - $slot = $qa->get_slot(); - $fs = get_file_storage(); - if ($filearea == 'bgimage') { - $itemid = $question->id; - } - $draftfiles = $fs->get_area_files($question->contextid, 'qtype_ddimageortext', - $filearea, $itemid, 'id'); - if ($draftfiles) { - foreach ($draftfiles as $file) { - if ($file->is_directory()) { - continue; - } - $url = moodle_url::make_pluginfile_url($question->contextid, 'qtype_ddimageortext', - $filearea, "$qubaid/$slot/{$itemid}", '/', - $file->get_filename()); - return $url->out(); - } - } - return null; - } - - protected function hidden_field_for_qt_var(question_attempt $qa, $varname, $value = null) { - if ($value === null) { - $value = $qa->get_last_qt_var($varname); - } - $fieldname = $qa->get_qt_field_name($varname); - $attributes = array('type' => 'hidden', - 'id' => str_replace(':', '_', $fieldname), - 'name' => $fieldname, - 'value' => $value); - return array($fieldname, html_writer::empty_tag('input', $attributes)."\n"); - } - - public function specific_feedback(question_attempt $qa) { - return $this->combined_feedback($qa); - } - - public function correct_response(question_attempt $qa) { - return ''; - } } diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php new file mode 100644 index 00000000000..7b228474a2a --- /dev/null +++ b/question/type/ddimageortext/rendererbase.php @@ -0,0 +1,177 @@ +. + +/** + * Drag-and-drop words into sentences question renderer class. + * + * @package qtype + * @subpackage ddimageortext + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +/** + * Generates the output for drag-and-drop words into sentences questions. + * + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_renderer { + + public function head_code(question_attempt $qa) { + return parent::head_code($qa); + } + public function clear_wrong(question_attempt $qa) { + $question = $qa->get_question(); + $response = $qa->get_last_qt_data(); + + if (!empty($response)) { + $cleanresponse = $question->clear_wrong_from_response($response); + } else { + $cleanresponse = $response; + } + $cleanresponsehtml = ''; + foreach ($cleanresponse as $fieldname => $value) { + list (, $html) = $this->hidden_field_for_qt_var($qa, $fieldname, $value); + $cleanresponsehtml .= $html; + } + return $cleanresponsehtml; + } + + public function formulation_and_controls(question_attempt $qa, + question_display_options $options) { + global $PAGE; + + $question = $qa->get_question(); + $response = $qa->get_last_qt_data(); + + $questiontext = $question->format_questiontext($qa); + + $output = html_writer::tag('div', $questiontext, array('class' => 'qtext')); + + $bgimage = self::get_url_for_image($qa, 'bgimage'); + + $img = html_writer::empty_tag('img', array('src'=>$bgimage, 'class'=>'dropbackground')); + $droparea = html_writer::tag('div', $img, array('class'=>'droparea')); + + $dragimagehomes = ''; + foreach ($question->choices as $groupno => $group) { + $dragimagehomesgroup = ''; + $orderedgroup = $question->get_ordered_choices($groupno); + foreach ($orderedgroup as $choiceno => $dragimage) { + $dragimageurl = self::get_url_for_image($qa, 'dragimage', $dragimage->id); + $classes = array("group{$groupno}", + 'draghome', + "dragitemhomes{$dragimage->no}", + "choice{$choiceno}"); + if ($dragimage->isinfinite) { + $classes[] = 'infinite'; + } + if ($dragimageurl === null) { + $classes[] = 'yui3-cssfonts'; + $dragimagehomesgroup .= html_writer::tag('div', + $dragimage->text, + array('src'=>$dragimageurl, + 'class'=>join(' ', $classes))); + } else { + $dragimagehomesgroup .= html_writer::empty_tag('img', + array('src'=>$dragimageurl, + 'alt' => $dragimage->text, + 'class'=>join(' ', $classes))); + } + } + $dragimagehomes .= html_writer::tag('div', $dragimagehomesgroup, + array('class'=>'dragitemgroup'.$groupno)); + } + + $dragitemsclass = 'dragitems'; + if ($options->readonly) { + $dragitemsclass .= ' readonly'; + } + $dragitems = html_writer::tag('div', $dragimagehomes, array('class'=> $dragitemsclass)); + $dropzones = html_writer::empty_tag('div', array('class'=>'dropzones')); + $output .= html_writer::tag('div', $droparea.$dragitems.$dropzones, + array('class'=>'ddarea')); + foreach ($question->places as $placeno => $place) { + $varname = $question->field($placeno); + list($fieldname, $html) = $this->hidden_field_for_qt_var($qa, $varname); + $output .= $html; + $question->places[$placeno]->fieldname = $fieldname; + } + $topnode = 'div#q'.$qa->get_slot().' div.ddarea'; + $params = array('drops' => $question->places, + 'topnode' => $topnode, + 'readonly' => $options->readonly); + + $PAGE->requires->yui_module('moodle-qtype_ddimageortext-dd', + 'M.qtype_ddimageortext.init_question', + array($params)); + + if ($qa->get_state() == question_state::$invalid) { + $output .= html_writer::nonempty_tag('div', + $question->get_validation_error($qa->get_last_qt_data()), + array('class' => 'validationerror')); + } + return $output; + } + + protected static function get_url_for_image(question_attempt $qa, $filearea, $itemid = 0) { + $question = $qa->get_question(); + $qubaid = $qa->get_usage_id(); + $slot = $qa->get_slot(); + $fs = get_file_storage(); + if ($filearea == 'bgimage') { + $itemid = $question->id; + } + $draftfiles = $fs->get_area_files($question->contextid, 'qtype_ddimageortext', + $filearea, $itemid, 'id'); + if ($draftfiles) { + foreach ($draftfiles as $file) { + if ($file->is_directory()) { + continue; + } + $url = moodle_url::make_pluginfile_url($question->contextid, 'qtype_ddimageortext', + $filearea, "$qubaid/$slot/{$itemid}", '/', + $file->get_filename()); + return $url->out(); + } + } + return null; + } + + protected function hidden_field_for_qt_var(question_attempt $qa, $varname, $value = null) { + if ($value === null) { + $value = $qa->get_last_qt_var($varname); + } + $fieldname = $qa->get_qt_field_name($varname); + $attributes = array('type' => 'hidden', + 'id' => str_replace(':', '_', $fieldname), + 'name' => $fieldname, + 'value' => $value); + return array($fieldname, html_writer::empty_tag('input', $attributes)."\n"); + } + + public function specific_feedback(question_attempt $qa) { + return $this->combined_feedback($qa); + } + + public function correct_response(question_attempt $qa) { + return ''; + } +} From bc1bcf6e339235466f330a916af83b4fe1299a6b Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 27 Sep 2011 19:40:41 +0700 Subject: [PATCH 117/208] MDL-47494 ddimageortext: NOBUG more refactoring --- .../ddimageortext/edit_ddimageortext_form.php | 118 +++++++++++++ .../edit_ddtoimage_form_base.php | 159 ++++-------------- 2 files changed, 148 insertions(+), 129 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 683afc227bc..10a9cff613e 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -35,4 +35,122 @@ defined('MOODLE_INTERNAL') || die(); */ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { + public function qtype() { + return 'ddimageortext'; + } + + public function js_call() { + global $PAGE; + $maxsizes =new stdClass(); + $maxsizes->bgimage = new stdClass(); + $maxsizes->bgimage->width = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH; + $maxsizes->bgimage->height = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT; + $maxsizes->dragimage = new stdClass(); + $maxsizes->dragimage->width = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH; + $maxsizes->dragimage->height = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT; + + $params = array('maxsizes' => $maxsizes, + 'topnode' => 'fieldset#previewareaheader'); + + $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', + 'M.qtype_ddimageortext.init_form', + array($params)); + } + + //drag items + + protected function definition_draggable_items($mform, $itemrepeatsatstart) { + + $this->repeat_elements($this->draggable_item($mform), $itemrepeatsatstart, + $this->draggable_items_repeated_options(), + 'noitems', 'additems', self::ADD_NUM_ITEMS, + get_string('addmoreimages', 'qtype_ddimageortext')); + } + + protected function draggable_item($mform) { + $draggableimageitem = array(); + + $draggableimageitem[] = $mform->createElement('header', 'draggableitemheader', + get_string('draggableitemheader', 'qtype_ddimageortext', '{no}')); + $dragitemtypes = array('image' => get_string('draggableimage', 'qtype_ddimageortext'), + 'word' => get_string('draggableword', 'qtype_ddimageortext')); + $draggableimageitem[] = $mform->createElement('select', 'dragitemtype', + get_string('draggableitemtype', 'qtype_ddimageortext'), + $dragitemtypes, + array('class' => 'dragitemtype')); + $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null, + self::file_picker_options()); + + $grouparray = array(); + $grouparray[] = $mform->createElement('text', 'draglabel', + get_string('label', 'qtype_ddimageortext'), + array('size'=>30, 'class'=>'tweakcss')); + $mform->setType('draglabel', PARAM_NOTAGS); + $options = array(); + for ($i = 1; $i <= self::MAX_GROUPS; $i += 1) { + $options[$i] = $i; + } + $grouparray[] = $mform->createElement('static', '', '', ' ' . + get_string('group', 'qtype_gapselect').' '); + $grouparray[] = $mform->createElement('select', 'draggroup', + get_string('group', 'qtype_gapselect'), + $options, + array('class' => 'draggroup')); + $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ', + get_string('infinite', 'qtype_ddimageortext')); + $draggableimageitem[] = $mform->createElement('group', 'drags', + get_string('label', 'qtype_ddimageortext'), $grouparray); + return $draggableimageitem; + } + + protected function draggable_items_repeated_options() { + $repeatedoptions = array(); + $repeatedoptions['draggroup']['default'] = '1'; + return $repeatedoptions; + } + + //drop zones + + protected function drop_zone($mform, $imagerepeats) { + $dropzoneitem = array(); + + $grouparray = array(); + $grouparray[] = $mform->createElement('static', 'xleftlabel', '', + ' '.get_string('xleft', 'qtype_ddimageortext').' '); + $grouparray[] = $mform->createElement('text', 'xleft', + get_string('xleft', 'qtype_ddimageortext'), + array('size'=>5, 'class'=>'tweakcss')); + $mform->setType('xleft', PARAM_NOTAGS); + $grouparray[] = $mform->createElement('static', 'ytoplabel', '', + ' '.get_string('ytop', 'qtype_ddimageortext').' '); + $grouparray[] = $mform->createElement('text', 'ytop', + get_string('ytop', 'qtype_ddimageortext'), + array('size'=>5, 'class'=>'tweakcss')); + $mform->setType('ytop', PARAM_NOTAGS); + $options = array(); + + $options[0] = ''; + for ($i = 1; $i <= $imagerepeats; $i += 1) { + $options[$i] = $i; + } + $grouparray[] = $mform->createElement('static', '', '', ' ' . + get_string('draggableitem', 'qtype_ddimageortext').' '); + $grouparray[] = $mform->createElement('select', 'choice', + get_string('draggableitem', 'qtype_ddimageortext'), $options); + $grouparray[] = $mform->createElement('static', '', '', ' ' . + get_string('label', 'qtype_ddimageortext').' '); + $grouparray[] = $mform->createElement('text', 'droplabel', + get_string('label', 'qtype_ddimageortext'), + array('size'=>10, 'class'=>'tweakcss')); + $mform->setType('droplabel', PARAM_NOTAGS); + $dropzone = $mform->createElement('group', 'drops', + get_string('dropzone', 'qtype_ddimageortext', '{no}'), $grouparray); + return array($dropzone); + } + + protected function drop_zones_repeated_options() { + $repeatedoptions = array(); + $repeatedoptions['choice']['default'] = '0'; + return $repeatedoptions; + } } diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php index 8a361a81e87..261badf2438 100644 --- a/question/type/ddimageortext/edit_ddtoimage_form_base.php +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -31,14 +31,11 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class qtype_ddtoimage_edit_form_base extends question_edit_form { +abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { const MAX_GROUPS = 8; const START_NUM_ITEMS = 6; const ADD_NUM_ITEMS = 3; - public function qtype() { - return 'ddimageortext'; - } /** * @@ -53,26 +50,6 @@ class qtype_ddtoimage_edit_form_base extends question_edit_form { return $filepickeroptions; } - protected function get_drag_image_repeats() { - $countimages = 0; - if (isset($this->question->id)) { - foreach ($this->question->options->drags as $drag) { - $countimages = max($countimages, $drag->no); - } - } - if ($this->question->formoptions->repeatelements) { - $imagerepeatsatstart = max(self::START_NUM_ITEMS, $countimages + self::ADD_NUM_ITEMS); - } else { - $imagerepeatsatstart = $countimages; - } - $imagerepeats = optional_param('noitems', $imagerepeatsatstart, PARAM_INT); - $addfields = optional_param('additems', '', PARAM_TEXT); - if (!empty($addfields)) { - $imagerepeats += self::ADD_NUM_ITEMS; - } - return array($imagerepeatsatstart, $imagerepeats); - } - /** * definition_inner adds all specific fields to the form. * @param object $mform (the form being built). @@ -89,14 +66,14 @@ class qtype_ddtoimage_edit_form_base extends question_edit_form { $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_ddimageortext')); $mform->closeHeaderBefore('refresh'); - list($imagerepeatsatstart, $imagerepeats) = $this->get_drag_image_repeats(); + list($itemrepeatsatstart, $imagerepeats) = $this->get_drag_item_repeats(); $this->definition_drop_zones($mform, $imagerepeats); $mform->addElement('advcheckbox', 'shuffleanswers', ' ', get_string('shuffleimages', 'qtype_ddimageortext')); $mform->setDefault('shuffleanswers', 0); $mform->closeHeaderBefore('shuffleanswers'); //add the draggable image fields to the form - $this->definition_draggable_images($mform, $imagerepeatsatstart); + $this->definition_draggable_items($mform, $itemrepeatsatstart); $this->add_combined_feedback_fields(true); $this->add_interactive_settings(true, true); @@ -104,7 +81,7 @@ class qtype_ddtoimage_edit_form_base extends question_edit_form { protected function definition_drop_zones($mform, $imagerepeats) { $mform->addElement('header', 'dropzoneheader', - get_string('dropzoneheader', 'qtype_ddimageortext')); + get_string('dropzoneheader', 'qtype_ddimageortext')); $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimageortext'), null, self::file_picker_options()); @@ -127,102 +104,37 @@ class qtype_ddtoimage_edit_form_base extends question_edit_form { 'nodropzone', 'adddropzone', self::ADD_NUM_ITEMS, get_string('addmoredropzones', 'qtype_ddimageortext')); } + abstract protected function drop_zone($mform, $imagerepeats); - protected function drop_zone($mform, $imagerepeats) { - $dropzoneitem = array(); + abstract protected function drop_zones_repeated_options(); - $grouparray = array(); - $grouparray[] = $mform->createElement('static', 'xleftlabel', '', - ' '.get_string('xleft', 'qtype_ddimageortext').' '); - $grouparray[] = $mform->createElement('text', 'xleft', - get_string('xleft', 'qtype_ddimageortext'), - array('size'=>5, 'class'=>'tweakcss')); - $mform->setType('xleft', PARAM_NOTAGS); - $grouparray[] = $mform->createElement('static', 'ytoplabel', '', - ' '.get_string('ytop', 'qtype_ddimageortext').' '); - $grouparray[] = $mform->createElement('text', 'ytop', - get_string('ytop', 'qtype_ddimageortext'), - array('size'=>5, 'class'=>'tweakcss')); - $mform->setType('ytop', PARAM_NOTAGS); - $options = array(); + abstract protected function definition_draggable_items($mform, $itemrepeatsatstart); - $options[0] = ''; - for ($i = 1; $i <= $imagerepeats; $i += 1) { - $options[$i] = $i; + abstract protected function draggable_item($mform); + + abstract protected function draggable_items_repeated_options(); + + protected function get_drag_item_repeats() { + $countimages = 0; + if (isset($this->question->id)) { + foreach ($this->question->options->drags as $drag) { + $countimages = max($countimages, $drag->no); + } } - $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('draggableitem', 'qtype_ddimageortext').' '); - $grouparray[] = $mform->createElement('select', 'choice', - get_string('draggableitem', 'qtype_ddimageortext'), $options); - $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('label', 'qtype_ddimageortext').' '); - $grouparray[] = $mform->createElement('text', 'droplabel', - get_string('label', 'qtype_ddimageortext'), - array('size'=>10, 'class'=>'tweakcss')); - $mform->setType('droplabel', PARAM_NOTAGS); - $dropzone = $mform->createElement('group', 'drops', - get_string('dropzone', 'qtype_ddimageortext', '{no}'), $grouparray); - return array($dropzone); - } - - protected function drop_zones_repeated_options() { - $repeatedoptions = array(); - $repeatedoptions['choice']['default'] = '0'; - return $repeatedoptions; - } - - protected function definition_draggable_images($mform, $imagerepeatsatstart) { - - $this->repeat_elements($this->draggable_image($mform), $imagerepeatsatstart, - $this->draggable_images_repeated_options(), - 'noitems', 'additems', self::ADD_NUM_ITEMS, - get_string('addmoreimages', 'qtype_ddimageortext')); - } - - protected function draggable_image($mform) { - $draggableimageitem = array(); - - $draggableimageitem[] = $mform->createElement('header', 'draggableitemheader', - get_string('draggableitemheader', 'qtype_ddimageortext', '{no}')); - $dragitemtypes = array('image' => get_string('draggableimage', 'qtype_ddimageortext'), - 'word' => get_string('draggableword', 'qtype_ddimageortext')); - $draggableimageitem[] = $mform->createElement('select', 'dragitemtype', - get_string('draggableitemtype', 'qtype_ddimageortext'), - $dragitemtypes, - array('class' => 'dragitemtype')); - $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null, - self::file_picker_options()); - - $grouparray = array(); - $grouparray[] = $mform->createElement('text', 'draglabel', - get_string('label', 'qtype_ddimageortext'), - array('size'=>30, 'class'=>'tweakcss')); - $mform->setType('draglabel', PARAM_NOTAGS); - $options = array(); - for ($i = 1; $i <= self::MAX_GROUPS; $i += 1) { - $options[$i] = $i; + if ($this->question->formoptions->repeatelements) { + $itemrepeatsatstart = max(self::START_NUM_ITEMS, $countimages + self::ADD_NUM_ITEMS); + } else { + $itemrepeatsatstart = $countimages; } - $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('group', 'qtype_gapselect').' '); - $grouparray[] = $mform->createElement('select', 'draggroup', - get_string('group', 'qtype_gapselect'), - $options, - array('class' => 'draggroup')); - $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ', - get_string('infinite', 'qtype_ddimageortext')); - $draggableimageitem[] = $mform->createElement('group', 'drags', - get_string('label', 'qtype_ddimageortext'), $grouparray); - return $draggableimageitem; - } - - protected function draggable_images_repeated_options() { - $repeatedoptions = array(); - $repeatedoptions['draggroup']['default'] = '1'; - return $repeatedoptions; + $imagerepeats = optional_param('noitems', $itemrepeatsatstart, PARAM_INT); + $addfields = optional_param('additems', '', PARAM_TEXT); + if (!empty($addfields)) { + $imagerepeats += self::ADD_NUM_ITEMS; + } + return array($itemrepeatsatstart, $imagerepeats); } public function data_preprocessing($question) { - global $PAGE; $question = parent::data_preprocessing($question); $question = $this->data_preprocessing_combined_feedback($question, true); @@ -258,7 +170,7 @@ class qtype_ddtoimage_edit_form_base extends question_edit_form { $question->bgimage = $draftitemid; //initialise file picker for dragimages - list(, $imagerepeats) = $this->get_drag_image_repeats(); + list(, $imagerepeats) = $this->get_drag_item_repeats(); $draftitemids = optional_param_array('dragitem', array(), PARAM_INT); for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; @@ -284,23 +196,12 @@ class qtype_ddtoimage_edit_form_base extends question_edit_form { } } } - $maxsizes =new stdClass(); - $maxsizes->bgimage = new stdClass(); - $maxsizes->bgimage->width = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH; - $maxsizes->bgimage->height = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT; - $maxsizes->dragimage = new stdClass(); - $maxsizes->dragimage->width = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH; - $maxsizes->dragimage->height = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT; + $this->js_call(); - $params = array('maxsizes' => $maxsizes, - 'topnode' => 'fieldset#previewareaheader'); - - $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', - 'M.qtype_ddimageortext.init_form', - array($params)); return $question; } + abstract public function js_call(); public static function file_uploaded($draftitemid) { $draftareafiles = file_get_drafarea_files($draftitemid); From eaabb891133c2d11824d1136fd03a899ee416172 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 28 Sep 2011 09:40:48 +0700 Subject: [PATCH 118/208] MDL-47494 ddimageortext: OU-1578 A text drag item with label '0' was not getting saved. --- question/type/ddimageortext/questiontypebase.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index ede7b5e87b4..ed46a7af32f 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -43,16 +43,17 @@ class qtype_ddtoimage_base extends question_type { } public function requires_qtypes() { - return array_merge(parent::requires_qtypes(), array('ddimageortext')); + return array_merge(parent::requires_qtypes()); } public function get_question_options($question) { global $DB; - $question->options = $DB->get_record('qtype_ddimageortext', + $dbprefix = 'qtype_'.$this->name(); + $question->options = $DB->get_record($dbprefix, array('questionid' => $question->id), '*', MUST_EXIST); - $question->options->drags = $DB->get_records('qtype_ddimageortext_drags', + $question->options->drags = $DB->get_records($dbprefix.'_drags', array('questionid' => $question->id), 'no ASC', '*'); - $question->options->drops = $DB->get_records('qtype_ddimageortext_drops', + $question->options->drops = $DB->get_records($dbprefix.'_drops', array('questionid' => $question->id), 'no ASC', '*'); parent::get_question_options($question); } @@ -150,7 +151,7 @@ class qtype_ddtoimage_base extends question_type { '', 'no, id'); foreach (array_keys($formdata->drags) as $dragno) { $info = file_get_draft_area_info($formdata->dragitem[$dragno]); - if ($info['filecount'] > 0 || !empty($formdata->drags[$dragno]['draglabel'])) { + if ($info['filecount'] > 0 || (trim($formdata->drags[$dragno]['draglabel'])!='')) { $draftitemid = $formdata->dragitem[$dragno]; $drag = new stdClass(); From 35d4aea9532e04f89f9b9b231e6cef8f6928be85 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 28 Sep 2011 10:44:03 +0700 Subject: [PATCH 119/208] MDL-47494 ddimageortext: OU-1597 Renaming question types. --- .../type/ddimageortext/lang/en/qtype_ddimageortext.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index b906f89dc21..0a27d38865e 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -22,15 +22,15 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['addingddimageortext'] = 'Adding drag and drop: images or text onto image'; +$string['addingddimageortext'] = 'Adding drag and drop onto images'; $string['addmoredropzones'] = 'Blanks for {no} More Drop Zones'; $string['addmoreimages'] = 'Blanks for {no} More Draggable Items'; $string['answer'] = 'Answer'; $string['bgimage'] = 'Background Image'; $string['correctansweris'] = 'The correct answer is: {$a}'; -$string['ddimageortext'] = 'Drag and drop: images or text onto image'; +$string['ddimageortext'] = 'Drag and drop onto images'; $string['ddimageortext_help'] = 'Select a background image file, select draggable images or enter text and define the drop zones on the background image to which they must be dragged.'; -$string['ddimageortextsummary'] = 'Images or text labels are dragged and dropped into drop zones on a background image.'; +$string['ddimageortextsummary'] = 'Images or text labels are dragged and dropped into visible drop zones on a background image.'; $string['draggableimage'] = 'Draggable image'; $string['draggableitem'] = 'Draggable item'; $string['draggableitemheader'] = 'Draggable item {$a}'; @@ -38,7 +38,7 @@ $string['draggableitemtype'] = 'Type'; $string['draggableword'] = 'Draggable text'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; -$string['editingddimageortext'] = 'Editing drag and drop: images or text onto image'; +$string['editingddimageortext'] = 'Editing drag and drop onto images'; $string['formerror_disallowedtags'] = 'You have used html tags here that are not allowed in a draggable text drag item type.'; $string['formerror_noallowedtags'] = 'No html tags are allowed in this text which is the alt text for a draggable image'; $string['formerror_noytop'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; From 3597982ab08ea6bb187b0968d0a7fe178fc239f3 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 28 Sep 2011 19:38:19 +0700 Subject: [PATCH 120/208] MDL-47494 ddimageortext: NOBUG further refactoring during development of ddmarker question type. --- .../ddimageortext/edit_ddimageortext_form.php | 131 ++++++++++++++++ .../edit_ddtoimage_form_base.php | 145 +----------------- 2 files changed, 138 insertions(+), 138 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 10a9cff613e..d348e8a705b 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -39,6 +39,73 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { return 'ddimageortext'; } + public function data_preprocessing($question) { + $question = parent::data_preprocessing($question); + $question = $this->data_preprocessing_combined_feedback($question, true); + $question = $this->data_preprocessing_hints($question, true, true); + + $dragids = array(); // drag no -> dragid + if (!empty($question->options)) { + $question->shuffleanswers = $question->options->shuffleanswers; + $question->drags = array(); + foreach ($question->options->drags as $drag) { + $dragindex = $drag->no -1; + $question->drags[$dragindex] = array(); + $question->drags[$dragindex]['draglabel'] = $drag->label; + $question->drags[$dragindex]['infinite'] = $drag->infinite; + $question->drags[$dragindex]['draggroup'] = $drag->draggroup; + $dragids[$dragindex] = $drag->id; + } + $question->drops = array(); + foreach ($question->options->drops as $drop) { + $question->drops[$drop->no -1] = array(); + $question->drops[$drop->no -1]['choice'] = $drop->choice; + $question->drops[$drop->no -1]['droplabel'] = $drop->label; + $question->drops[$drop->no -1]['xleft'] = $drop->xleft; + $question->drops[$drop->no -1]['ytop'] = $drop->ytop; + } + } + //initialise file picker for bgimage + $draftitemid = file_get_submitted_draft_itemid('bgimage'); + + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', + 'bgimage', !empty($question->id) ? (int) $question->id : null, + self::file_picker_options()); + $question->bgimage = $draftitemid; + + //initialise file picker for dragimages + list(, $imagerepeats) = $this->get_drag_item_repeats(); + $draftitemids = optional_param_array('dragitem', array(), PARAM_INT); + for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { + $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; + //numbers not allowed in filearea name + $itemid = isset($dragids[$imageindex]) ? $dragids[$imageindex] : null; + file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', + 'dragimage', $itemid, self::file_picker_options()); + $question->dragitem[$imageindex] = $draftitemid; + } + if (!empty($question->options)) { + foreach ($question->options->drags as $drag) { + $dragindex = $drag->no -1; + if (!isset($question->dragitem[$dragindex])) { + $fileexists = false; + } else { + $fileexists = self::file_uploaded($question->dragitem[$dragindex]); + } + $labelexists = $question->drags[$dragindex]['draglabel']; + if ($labelexists && !$fileexists) { + $question->dragitemtype[$dragindex] = 'word'; + } else { + $question->dragitemtype[$dragindex] = 'image'; + } + } + } + $this->js_call(); + + return $question; + } + + public function js_call() { global $PAGE; $maxsizes =new stdClass(); @@ -153,4 +220,68 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $repeatedoptions['choice']['default'] = '0'; return $repeatedoptions; } + + public function validation($data, $files) { + $errors = parent::validation($data, $files); + if (!self::file_uploaded($data['bgimage'])) { + $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_'.$this->qtype()); + } + + $allchoices = array(); + for ($i=0; $i < $data['nodropzone']; $i++) { + $ytoppresent = (trim($data['drops'][$i]['ytop']) !== ''); + $xleftpresent = (trim($data['drops'][$i]['ytop']) !== ''); + $labelpresent = (trim($data['drops'][$i]['droplabel']) !== ''); + $choice = $data['drops'][$i]['choice']; + $imagechoicepresent = ($choice !== '0'); + + if ($imagechoicepresent) { + if (!$ytoppresent) { + $errors["drops[$i]"] = + get_string('formerror_noytop', 'qtype_ddimageortext'); + } + if (!$xleftpresent) { + $errors["drops[$i]"] = + get_string('formerror_noxleft', 'qtype_ddimageortext'); + } + + if ($data['dragitemtype'][$choice - 1] != 'word' && + !self::file_uploaded($data['dragitem'][$choice - 1])) { + $errors['dragitem['.($choice - 1).']'] = + get_string('formerror_nofile', 'qtype_ddimageortext', $i); + } + + if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { + $errors["drops[$i]"] = + get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); + $errors['drops['.($allchoices[$choice]).']'] = + get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); + $errors['drags['.($choice-1).']'] = + get_string('formerror_multipledraginstance2', 'qtype_ddimageortext', $choice); + } + $allchoices[$choice] = $i; + } else { + if ($ytoppresent || $xleftpresent || $labelpresent) { + $errors["drops[$i]"] = + get_string('formerror_noimageselected', 'qtype_ddimageortext'); + } + } + } + for ($dragindex=0; $dragindex < $data['noitems']; $dragindex++) { + $label = $data['drags'][$dragindex]['draglabel']; + if ($data['dragitemtype'][$dragindex] == 'word') { + $allowedtags = '
'; + $errormessage = get_string('formerror_disallowedtags', 'qtype_ddimageortext'); + } else { + $allowedtags = ''; + $errormessage = get_string('formerror_noallowedtags', 'qtype_ddimageortext'); + } + if ($label != strip_tags($label, $allowedtags)) { + $errors["drags[{$dragindex}]"] = $errormessage; + } + + } + return $errors; + } + } diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php index 261badf2438..ee5b2904c29 100644 --- a/question/type/ddimageortext/edit_ddtoimage_form_base.php +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -57,19 +57,19 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { protected function definition_inner($mform) { $mform->addElement('header', 'previewareaheader', - get_string('previewareaheader', 'qtype_ddimageortext')); + get_string('previewareaheader', 'qtype_'.$this->qtype())); $mform->addElement('static', 'previewarea', - get_string('previewarea', 'qtype_ddimageortext'), - get_string('previewareamessage', 'qtype_ddimageortext')); + get_string('previewarea', 'qtype_'.$this->qtype()), + get_string('previewareamessage', 'qtype_'.$this->qtype())); $mform->registerNoSubmitButton('refresh'); - $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_ddimageortext')); + $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_'.$this->qtype())); $mform->closeHeaderBefore('refresh'); list($itemrepeatsatstart, $imagerepeats) = $this->get_drag_item_repeats(); $this->definition_drop_zones($mform, $imagerepeats); $mform->addElement('advcheckbox', 'shuffleanswers', ' ', - get_string('shuffleimages', 'qtype_ddimageortext')); + get_string('shuffleimages', 'qtype_'.$this->qtype())); $mform->setDefault('shuffleanswers', 0); $mform->closeHeaderBefore('shuffleanswers'); //add the draggable image fields to the form @@ -81,9 +81,9 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { protected function definition_drop_zones($mform, $imagerepeats) { $mform->addElement('header', 'dropzoneheader', - get_string('dropzoneheader', 'qtype_ddimageortext')); + get_string('dropzoneheader', 'qtype_'.$this->qtype())); - $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_ddimageortext'), + $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_'.$this->qtype()), null, self::file_picker_options()); $countdropzones = 0; @@ -134,73 +134,6 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { return array($itemrepeatsatstart, $imagerepeats); } - public function data_preprocessing($question) { - - $question = parent::data_preprocessing($question); - $question = $this->data_preprocessing_combined_feedback($question, true); - $question = $this->data_preprocessing_hints($question, true, true); - - $dragids = array(); // drag no -> dragid - if (!empty($question->options)) { - $question->shuffleanswers = $question->options->shuffleanswers; - $question->drags = array(); - foreach ($question->options->drags as $drag) { - $dragindex = $drag->no -1; - $question->drags[$dragindex] = array(); - $question->drags[$dragindex]['draglabel'] = $drag->label; - $question->drags[$dragindex]['infinite'] = $drag->infinite; - $question->drags[$dragindex]['draggroup'] = $drag->draggroup; - $dragids[$dragindex] = $drag->id; - } - $question->drops = array(); - foreach ($question->options->drops as $drop) { - $question->drops[$drop->no -1] = array(); - $question->drops[$drop->no -1]['choice'] = $drop->choice; - $question->drops[$drop->no -1]['droplabel'] = $drop->label; - $question->drops[$drop->no -1]['xleft'] = $drop->xleft; - $question->drops[$drop->no -1]['ytop'] = $drop->ytop; - } - } - //initialise file picker for bgimage - $draftitemid = file_get_submitted_draft_itemid('bgimage'); - - file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', - 'bgimage', !empty($question->id) ? (int) $question->id : null, - self::file_picker_options()); - $question->bgimage = $draftitemid; - - //initialise file picker for dragimages - list(, $imagerepeats) = $this->get_drag_item_repeats(); - $draftitemids = optional_param_array('dragitem', array(), PARAM_INT); - for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { - $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; - //numbers not allowed in filearea name - $itemid = isset($dragids[$imageindex]) ? $dragids[$imageindex] : null; - file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', - 'dragimage', $itemid, self::file_picker_options()); - $question->dragitem[$imageindex] = $draftitemid; - } - if (!empty($question->options)) { - foreach ($question->options->drags as $drag) { - $dragindex = $drag->no -1; - if (!isset($question->dragitem[$dragindex])) { - $fileexists = false; - } else { - $fileexists = self::file_uploaded($question->dragitem[$dragindex]); - } - $labelexists = $question->drags[$dragindex]['draglabel']; - if ($labelexists && !$fileexists) { - $question->dragitemtype[$dragindex] = 'word'; - } else { - $question->dragitemtype[$dragindex] = 'image'; - } - } - } - $this->js_call(); - - return $question; - } - abstract public function js_call(); public static function file_uploaded($draftitemid) { @@ -214,69 +147,5 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { return true; } - public function validation($data, $files) { - $errors = parent::validation($data, $files); - if (!self::file_uploaded($data['bgimage'])) { - $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_ddimageortext'); - } - - $allchoices = array(); - for ($i=0; $i < $data['nodropzone']; $i++) { - $ytoppresent = (trim($data['drops'][$i]['ytop']) !== ''); - $xleftpresent = (trim($data['drops'][$i]['ytop']) !== ''); - $labelpresent = (trim($data['drops'][$i]['droplabel']) !== ''); - $choice = $data['drops'][$i]['choice']; - $imagechoicepresent = ($choice !== '0'); - - if ($imagechoicepresent) { - if (!$ytoppresent) { - $errors["drops[$i]"] = - get_string('formerror_noytop', 'qtype_ddimageortext'); - } - if (!$xleftpresent) { - $errors["drops[$i]"] = - get_string('formerror_noxleft', 'qtype_ddimageortext'); - } - - if ($data['dragitemtype'][$choice - 1] != 'word' && - !self::file_uploaded($data['dragitem'][$choice - 1])) { - $errors['dragitem['.($choice - 1).']'] = - get_string('formerror_nofile', 'qtype_ddimageortext', $i); - } - - if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { - $errors["drops[$i]"] = - get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); - $errors['drops['.($allchoices[$choice]).']'] = - get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); - $errors['drags['.($choice-1).']'] = - get_string('formerror_multipledraginstance2', 'qtype_ddimageortext', $choice); - } - $allchoices[$choice] = $i; - } else { - if ($ytoppresent || $xleftpresent || $labelpresent) { - $errors["drops[$i]"] = - get_string('formerror_noimageselected', 'qtype_ddimageortext'); - } - } - } - for ($dragindex=0; $dragindex < $data['noitems']; $dragindex++) { - $label = $data['drags'][$dragindex]['draglabel']; - if ($data['dragitemtype'][$dragindex] == 'word') { - $allowedtags = '
'; - $errormessage = get_string('formerror_disallowedtags', 'qtype_ddimageortext'); - } else { - $allowedtags = ''; - $errormessage = get_string('formerror_noallowedtags', 'qtype_ddimageortext'); - } - if ($label != strip_tags($label, $allowedtags)) { - $errors["drags[{$dragindex}]"] = $errormessage; - } - - } - return $errors; - } - - } From c1bf1673977f876668fccb9820da167449f5e8f1 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 28 Sep 2011 19:41:41 +0700 Subject: [PATCH 121/208] MDL-47494 ddimageortext: OU-1578 Also found that filepicker is not hidden correctly when label is '0' and there is no file. --- question/type/ddimageortext/edit_ddimageortext_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index d348e8a705b..c9e36567f0f 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -92,7 +92,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { } else { $fileexists = self::file_uploaded($question->dragitem[$dragindex]); } - $labelexists = $question->drags[$dragindex]['draglabel']; + $labelexists = (trim($question->drags[$dragindex]['draglabel']) != ''); if ($labelexists && !$fileexists) { $question->dragitemtype[$dragindex] = 'word'; } else { From d39f90b34f633c6c40df59e9e667ee14a50db55e Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 14 Oct 2011 13:27:46 +0700 Subject: [PATCH 122/208] MDL-47494 ddimageortext: NOBUG updated README with instructions about how to install 2.1+ version. --- question/type/ddimageortext/README.txt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index b14ea17b18b..e3c0250c587 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -7,14 +7,21 @@ to be installed in order to work. This question type was written by Jamie Pratt (http://jamiep.org/). -This question type is compatible with Moodle 2.1. +This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or 2.2+ (master branch). -To install using git, type this command in the root of your Moodle install : +To install using git for a 2.2+ Moodle installation, type this command in the root of your Moodle +install : git clone git://github.com/jamiepratt/moodle-qtype_ddimageortext.git question/type/ddimageortext +To install using git for a 2.1+ Moodle installation, type this command in the root of your Moodle +install : + +git clone -b MOODLE_21_STABLE git://github.com/jamiepratt/moodle-qtype_ddimageortext.git question/type/ddimageortext + Then add question/type/ddimageortext to your git ignore. Alternatively, download the zip from - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/master + Moodle 2.2+ - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/master + Moodle 2.1+ - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/MOODLE_21_STABLE unzip it into the question/type folder, and then rename the new folder to ddimageortext. From ecbdefb4ea944096d0758582cddddf2eb26b2703 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 14 Oct 2011 13:27:46 +0700 Subject: [PATCH 123/208] MDL-47494 ddimageortext: NOBUG updated README with instructions about how to install 2.1+ version. --- question/type/ddimageortext/README.txt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index b14ea17b18b..e3c0250c587 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -7,14 +7,21 @@ to be installed in order to work. This question type was written by Jamie Pratt (http://jamiep.org/). -This question type is compatible with Moodle 2.1. +This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or 2.2+ (master branch). -To install using git, type this command in the root of your Moodle install : +To install using git for a 2.2+ Moodle installation, type this command in the root of your Moodle +install : git clone git://github.com/jamiepratt/moodle-qtype_ddimageortext.git question/type/ddimageortext +To install using git for a 2.1+ Moodle installation, type this command in the root of your Moodle +install : + +git clone -b MOODLE_21_STABLE git://github.com/jamiepratt/moodle-qtype_ddimageortext.git question/type/ddimageortext + Then add question/type/ddimageortext to your git ignore. Alternatively, download the zip from - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/master + Moodle 2.2+ - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/master + Moodle 2.1+ - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/MOODLE_21_STABLE unzip it into the question/type folder, and then rename the new folder to ddimageortext. From b2e57f524b01379858d92a701f7366232bc6370a Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 29 Oct 2011 12:07:50 +0700 Subject: [PATCH 124/208] MDL-47494 ddimageortext: NOBUG not using yui3-cssfonts or yui3-csssrest but forgot to remove class names --- question/type/ddimageortext/yui/dd/dd.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 4c89cdce652..faff9418b30 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -92,8 +92,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { var oldhome = this.drag_item_home(dragitemno); var classes = 'draghome dragitemhomes'+dragitemno+' group'+group; var imghtml = ''+alt+''; - var divhtml = '
'+alt+'
'; + var divhtml = '
'+alt+'
'; if (oldhome === null) { if (url) { dragitemsarea.append(imghtml); From d164d0931513e27b24d955d21c17815ce8bfd5df Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 31 Oct 2011 16:19:04 +0700 Subject: [PATCH 125/208] MDL-47494 ddimageortext: NOBUG removing unnecessary form input event responder that was causing errors --- question/type/ddimageortext/yui/form/form.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 1a7f6096140..f2ee8edd839 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -181,11 +181,6 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { this.doc.drag_items().remove(true); this.draw_dd_area(); }, this); - Y.all('fieldset#draggableitemheader_'+i+' input[type="text"]') - .on('blur', function (e, draginstanceno){ - this.doc.drag_item(draginstanceno).remove(true); - this.draw_dd_area(); - }, this, i); //change to infinite checkbox Y.all('fieldset#draggableitemheader_'+i+' input[type="checkbox"]') .on('change', this.set_options_for_drag_item_selectors, this); From eab829f3881491013ff27672dcd54e5d1b19a11f Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 31 Oct 2011 16:20:21 +0700 Subject: [PATCH 126/208] MDL-47494 ddimageortext: NOBUG removing unnecessary reference to obsolete head_code method --- question/type/ddimageortext/rendererbase.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index 7b228474a2a..08d83275713 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -34,9 +34,6 @@ defined('MOODLE_INTERNAL') || die(); */ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_renderer { - public function head_code(question_attempt $qa) { - return parent::head_code($qa); - } public function clear_wrong(question_attempt $qa) { $question = $qa->get_question(); $response = $qa->get_last_qt_data(); From 6aad8ee353065580c01ebdd318071a2b89e293d9 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 31 Oct 2011 17:38:28 +0700 Subject: [PATCH 127/208] MDL-47494 ddimageortext: NOBUG fixed disabling of select options when the background image is not loaded --- question/type/ddimageortext/yui/form/form.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index f2ee8edd839..05ba3ef07b3 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -130,9 +130,14 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { +' input[type="checkbox"]'; var cbel = Y.one(cbselector); var infinite = cbel.get('checked'); - if ((!infinite) && - (this.doc.drag_items_cloned_from(value - 1).size() !== 0)) { - optionnode.set('disabled', true); + if (!infinite) { + Y.all('fieldset#dropzoneheader select').some(function (selector) { + if (+selector.get('value') == value){ + optionnode.set('disabled', true); + return true; // stop looping + } + return false; + }, this); } } } @@ -181,6 +186,8 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { this.doc.drag_items().remove(true); this.draw_dd_area(); }, this); + Y.all('fieldset#draggableitemheader_'+i+' input[type="text"]') + .on('blur', this.set_options_for_drag_item_selectors, this); //change to infinite checkbox Y.all('fieldset#draggableitemheader_'+i+' input[type="checkbox"]') .on('change', this.set_options_for_drag_item_selectors, this); From 5429a220096243aea45dac622d6a86dc839645d6 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 2 Nov 2011 13:51:05 +0700 Subject: [PATCH 128/208] MDL-47494 ddimageortext: NOBUG have url generation code work in other question types that extend this --- question/type/ddimageortext/rendererbase.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index 08d83275713..58985ca7d05 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -136,14 +136,15 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere if ($filearea == 'bgimage') { $itemid = $question->id; } - $draftfiles = $fs->get_area_files($question->contextid, 'qtype_ddimageortext', - $filearea, $itemid, 'id'); + $componentname = $question->qtype->plugin_name(); + $draftfiles = $fs->get_area_files($question->contextid, $componentname, + $filearea, $itemid, 'id'); if ($draftfiles) { foreach ($draftfiles as $file) { if ($file->is_directory()) { continue; } - $url = moodle_url::make_pluginfile_url($question->contextid, 'qtype_ddimageortext', + $url = moodle_url::make_pluginfile_url($question->contextid, $componentname, $filearea, "$qubaid/$slot/{$itemid}", '/', $file->get_filename()); return $url->out(); From 2a1ec7554c49873e4e4cb9774545d4cf587b2958 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 3 Nov 2011 16:19:52 +0700 Subject: [PATCH 129/208] MDL-47494 ddimageortext: NOBUG allow sub classes to add class names to hidden input fields --- question/type/ddimageortext/rendererbase.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index 58985ca7d05..13e899fc974 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -153,7 +153,8 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere return null; } - protected function hidden_field_for_qt_var(question_attempt $qa, $varname, $value = null) { + protected function hidden_field_for_qt_var(question_attempt $qa, $varname, $value = null, + $classes = null) { if ($value === null) { $value = $qa->get_last_qt_var($varname); } @@ -162,6 +163,9 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere 'id' => str_replace(':', '_', $fieldname), 'name' => $fieldname, 'value' => $value); + if ($classes !== null) { + $attributes['class'] = join(' ', $classes); + } return array($fieldname, html_writer::empty_tag('input', $attributes)."\n"); } From b5cdc3e7a72dc0d217786aed10b4821094a1078f Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 4 Nov 2011 17:49:38 +0700 Subject: [PATCH 130/208] MDL-47494 ddimageortext: NOBUG adding some drop shadow to drags --- question/type/ddimageortext/styles.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index bc9365df553..95287819957 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -74,3 +74,14 @@ form.mform fieldset#previewareaheader div.draghome, form.mform fieldset#previewa *font-size:small; /* for IE */ *font:x-small; /* for IE in quirks mode */ } +form.mform fieldset#previewareaheader div.drag.yui3-dd-dragging, +.que.ddimageortext div.drag.yui3-dd-dragging { + z-index: 3; + -moz-box-shadow: 3px 3px 4px #000; + -webkit-box-shadow: 3px 3px 4px #000; + box-shadow: 3px 3px 4px #000; + /* For IE 8 */ + -ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000')"; + /* For IE 5.5 - 7 */ + filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000'); +} \ No newline at end of file From c56c771f9e2e2aba2acd9cdd954a7d39c3748f31 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 4 Nov 2011 12:51:47 +0000 Subject: [PATCH 131/208] MDL-47494 ddimageortext: Tweak lang strings and fix file permissions. --- question/type/ddimageortext/db/install.xml | 0 .../ddimageortext/lang/en/qtype_ddimageortext.php | 8 ++++---- question/type/ddimageortext/pix/icon.gif | Bin question/type/ddimageortext/question.php | 0 question/type/ddimageortext/questiontype.php | 0 question/type/ddimageortext/renderer.php | 0 question/type/ddimageortext/simpletest/helper.php | 0 .../type/ddimageortext/simpletest/testquestion.php | 0 .../ddimageortext/simpletest/testquestiontype.php | 0 .../ddimageortext/simpletest/testwalkthrough.php | 0 question/type/ddimageortext/styles.css | 0 question/type/ddimageortext/version.php | 0 12 files changed, 4 insertions(+), 4 deletions(-) mode change 100755 => 100644 question/type/ddimageortext/db/install.xml mode change 100755 => 100644 question/type/ddimageortext/pix/icon.gif mode change 100755 => 100644 question/type/ddimageortext/question.php mode change 100755 => 100644 question/type/ddimageortext/questiontype.php mode change 100755 => 100644 question/type/ddimageortext/renderer.php mode change 100755 => 100644 question/type/ddimageortext/simpletest/helper.php mode change 100755 => 100644 question/type/ddimageortext/simpletest/testquestion.php mode change 100755 => 100644 question/type/ddimageortext/simpletest/testquestiontype.php mode change 100755 => 100644 question/type/ddimageortext/simpletest/testwalkthrough.php mode change 100755 => 100644 question/type/ddimageortext/styles.css mode change 100755 => 100644 question/type/ddimageortext/version.php diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index 0a27d38865e..9f8262bf1f5 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -22,15 +22,15 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['addingddimageortext'] = 'Adding drag and drop onto images'; +$string['addingddimageortext'] = 'Adding drag and drop onto image'; $string['addmoredropzones'] = 'Blanks for {no} More Drop Zones'; $string['addmoreimages'] = 'Blanks for {no} More Draggable Items'; $string['answer'] = 'Answer'; $string['bgimage'] = 'Background Image'; $string['correctansweris'] = 'The correct answer is: {$a}'; -$string['ddimageortext'] = 'Drag and drop onto images'; +$string['ddimageortext'] = 'Drag and drop onto image'; $string['ddimageortext_help'] = 'Select a background image file, select draggable images or enter text and define the drop zones on the background image to which they must be dragged.'; -$string['ddimageortextsummary'] = 'Images or text labels are dragged and dropped into visible drop zones on a background image.'; +$string['ddimageortextsummary'] = 'Images or text labels are dragged and dropped into drop zones on a background image.'; $string['draggableimage'] = 'Draggable image'; $string['draggableitem'] = 'Draggable item'; $string['draggableitemheader'] = 'Draggable item {$a}'; @@ -38,7 +38,7 @@ $string['draggableitemtype'] = 'Type'; $string['draggableword'] = 'Draggable text'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; -$string['editingddimageortext'] = 'Editing drag and drop onto images'; +$string['editingddimageortext'] = 'Editing drag and drop onto image'; $string['formerror_disallowedtags'] = 'You have used html tags here that are not allowed in a draggable text drag item type.'; $string['formerror_noallowedtags'] = 'No html tags are allowed in this text which is the alt text for a draggable image'; $string['formerror_noytop'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; diff --git a/question/type/ddimageortext/pix/icon.gif b/question/type/ddimageortext/pix/icon.gif old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/simpletest/helper.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php old mode 100755 new mode 100644 From 2b3e53b36f4a78e6593163bdc66c97f382f7cc74 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 12 Nov 2011 15:48:37 +0700 Subject: [PATCH 132/208] MDL-47494 ddimageortext: NOBUG adding comments to identify keys for key numbers in keyboard listener --- question/type/ddimageortext/yui/dd/dd.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index faff9418b30..06b5298039d 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -439,12 +439,12 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', _keys: { - '32': 'next', - '37': 'previous', - '38': 'previous', - '39': 'next', - '40': 'next', - '27': 'remove' + '32': 'next', // Space + '37': 'previous', // Left arrow + '38': 'previous', // Up arrow + '39': 'next', // Right arrow + '40': 'next', // Down arrow + '27': 'remove' // Escape }, _keyHandler: function (e, notifier) { From b9640ba51f450c10e8e39b8797ff2a828df44188 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 18 Nov 2011 10:01:55 +0700 Subject: [PATCH 133/208] MDL-47494 ddimageortext: NOBUG moving some methods from out of the question_type base class --- question/type/ddimageortext/questiontype.php | 237 +++++++++++++++++ .../type/ddimageortext/questiontypebase.php | 248 +----------------- 2 files changed, 242 insertions(+), 243 deletions(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 34879f0e244..d5f1cec0bef 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -41,4 +41,241 @@ define('QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT', 100); */ class qtype_ddimageortext extends qtype_ddtoimage_base { + protected function make_choice($dragdata) { + return new qtype_ddimageortext_drag_item($dragdata->label, $dragdata->no, + $dragdata->draggroup, $dragdata->infinite, $dragdata->id); + } + + protected function make_place($dropzonedata) { + return new qtype_ddimageortext_drop_zone($dropzonedata->label, $dropzonedata->no, + $dropzonedata->group, + $dropzonedata->xleft, $dropzonedata->ytop); + } + + protected function make_hint($hint) { + return question_hint_with_parts::load_from_record($hint); + } + + public function save_question_options($formdata) { + global $DB, $USER; + $context = $formdata->context; + + $options = $DB->get_record('qtype_ddimageortext', array('questionid' => $formdata->id)); + if (!$options) { + $options = new stdClass(); + $options->questionid = $formdata->id; + $options->correctfeedback = ''; + $options->partiallycorrectfeedback = ''; + $options->incorrectfeedback = ''; + $options->id = $DB->insert_record('qtype_ddimageortext', $options); + } + + $options->shuffleanswers = !empty($formdata->shuffleanswers); + $options = $this->save_combined_feedback_helper($options, $formdata, $context, true); + $this->save_hints($formdata, true); + $DB->update_record('qtype_ddimageortext', $options); + $DB->delete_records('qtype_ddimageortext_drops', array('questionid' => $formdata->id)); + foreach (array_keys($formdata->drops) as $dropno) { + if ($formdata->drops[$dropno]['choice'] == 0) { + continue; + } + $drop = new stdClass(); + $drop->questionid = $formdata->id; + $drop->no = $dropno + 1; + $drop->xleft = $formdata->drops[$dropno]['xleft']; + $drop->ytop = $formdata->drops[$dropno]['ytop']; + $drop->choice = $formdata->drops[$dropno]['choice']; + $drop->label = $formdata->drops[$dropno]['droplabel']; + + $DB->insert_record('qtype_ddimageortext_drops', $drop); + } + + //an array of drag no -> drag id + $olddragids = $DB->get_records_menu('qtype_ddimageortext_drags', + array('questionid' => $formdata->id), + '', 'no, id'); + foreach (array_keys($formdata->drags) as $dragno) { + $info = file_get_draft_area_info($formdata->dragitem[$dragno]); + if ($info['filecount'] > 0 || (trim($formdata->drags[$dragno]['draglabel'])!='')) { + $draftitemid = $formdata->dragitem[$dragno]; + + $drag = new stdClass(); + $drag->questionid = $formdata->id; + $drag->no = $dragno + 1; + $drag->draggroup = $formdata->drags[$dragno]['draggroup']; + $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; + $drag->label = $formdata->drags[$dragno]['draglabel']; + + if (isset($olddragids[$dragno +1])) { + $drag->id = $olddragids[$dragno +1]; + unset($olddragids[$dragno +1]); + $DB->update_record('qtype_ddimageortext_drags', $drag); + } else { + $drag->id = $DB->insert_record('qtype_ddimageortext_drags', $drag); + } + + if ($formdata->dragitemtype[$dragno] == 'image') { + self::constrain_image_size_in_draft_area($draftitemid, + QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH, + QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT); + file_save_draft_area_files($draftitemid, $formdata->context->id, + 'qtype_ddimageortext', 'dragimage', $drag->id, + array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); + } else { + //delete any existing files for draggable text item type + $fs = get_file_storage(); + $fs->delete_area_files($formdata->context->id, 'qtype_ddimageortext', + 'dragimage', $drag->id); + } + + } + + } + if (!empty($olddragids)) { + list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); + $DB->delete_records_select('qtype_ddimageortext_drags', "id $sql", $params); + } + + self::constrain_image_size_in_draft_area($formdata->bgimage, + QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH, + QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT); + file_save_draft_area_files($formdata->bgimage, $formdata->context->id, + 'qtype_ddimageortext', 'bgimage', $formdata->id, + array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); + } + public function move_files($questionid, $oldcontextid, $newcontextid) { + global $DB; + $fs = get_file_storage(); + + parent::move_files($questionid, $oldcontextid, $newcontextid); + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'qtype_ddimageortext', 'bgimage', $questionid); + $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', + array('questionid' => $questionid), 'id', 'id,1'); + foreach ($dragids as $dragid => $notused) { + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'qtype_ddimageortext', 'dragimage', $dragid); + } + + $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); + } + + /** + * Delete all the files belonging to this question. + * @param int $questionid the question being deleted. + * @param int $contextid the context the question is in. + */ + + protected function delete_files($questionid, $contextid) { + global $DB; + $fs = get_file_storage(); + + parent::delete_files($questionid, $contextid); + + $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', + array('questionid' => $questionid), 'id', 'id,1'); + foreach ($dragids as $dragid => $notused) { + $fs->delete_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $dragid); + } + + $this->delete_files_in_combined_feedback($questionid, $contextid); + } + + + public function export_to_xml($question, $format, $extra = null) { + $fs = get_file_storage(); + $contextid = $question->contextid; + $output = ''; + + if ($question->options->shuffleanswers) { + $output .= " \n"; + } + $output .= $format->write_combined_feedback($question->options); + $output .= $format->write_hints($question); + $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); + $output .= " ".$this->write_files($files, 2)."\n";; + + foreach ($question->options->drags as $drag) { + $files = + $fs->get_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $drag->id); + $output .= " \n"; + $output .= " {$drag->no}\n"; + $output .= $format->writetext($drag->label, 3)."\n"; + $output .= " {$drag->draggroup}\n"; + if ($drag->infinite) { + $output .= " \n"; + } + $output .= $this->write_files($files, 3); + $output .= " \n"; + } + foreach ($question->options->drops as $drop) { + $output .= " \n"; + $output .= $format->writetext($drop->label, 3); + $output .= " {$drop->no}\n"; + $output .= " {$drop->choice}\n"; + $output .= " {$drop->xleft}\n"; + $output .= " {$drop->ytop}\n"; + $output .= " \n"; + } + + return $output; + } + + public function import_from_xml($data, $question, $format, $extra=null) { + if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimageortext') { + return false; + } + + $question = $format->import_headers($data); + $question->qtype = 'ddimageortext'; + + $question->shuffleanswers = array_key_exists('shuffleanswers', + $format->getpath($data, array('#'), array())); + + $filexml = $format->getpath($data, array('#', 'file'), array()); + $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml); + $drags = $data['#']['drag']; + $question->drags = array(); + + foreach ($drags as $dragxml) { + $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0); + $dragindex = $dragno -1; + $question->drags[$dragindex] = array(); + $question->drags[$dragindex]['draglabel'] = + $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); + $question->drags[$dragindex]['infinite'] = array_key_exists('infinite', $dragxml['#']); + $question->drags[$dragindex]['draggroup'] = + $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1); + $filexml = $format->getpath($dragxml, array('#', 'file'), array()); + $question->dragitem[$dragindex] = + $this->import_files_to_draft_file_area($format, $filexml); + if (count($filexml)) { + $question->dragitemtype[$dragindex] = 'image'; + } else { + $question->dragitemtype[$dragindex] = 'word'; + } + } + + $drops = $data['#']['drop']; + $question->drops = array(); + foreach ($drops as $dropxml) { + $dropno = $format->getpath($dropxml, array('#', 'no', 0, '#'), 0); + $dropindex = $dropno -1; + $question->drops[$dropindex] = array(); + $question->drops[$dropindex]['choice'] = + $format->getpath($dropxml, array('#', 'choice', 0, '#'), 0); + $question->drops[$dropindex]['droplabel'] = + $format->getpath($dropxml, array('#', 'text', 0, '#'), '', true); + $question->drops[$dropindex]['xleft'] = + $format->getpath($dropxml, array('#', 'xleft', 0, '#'), ''); + $question->drops[$dropindex]['ytop'] = + $format->getpath($dropxml, array('#', 'ytop', 0, '#'), ''); + } + + $format->import_combined_feedback($question, $data, true); + $format->import_hints($question, $data, true); + + return $question; + } + } diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index ed46a7af32f..57248c3b591 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -42,10 +42,6 @@ class qtype_ddtoimage_base extends question_type { return 'draggroup'; } - public function requires_qtypes() { - return array_merge(parent::requires_qtypes()); - } - public function get_question_options($question) { global $DB; $dbprefix = 'qtype_'.$this->name(); @@ -58,21 +54,6 @@ class qtype_ddtoimage_base extends question_type { parent::get_question_options($question); } - protected function make_choice($dragdata) { - return new qtype_ddimageortext_drag_item($dragdata->label, $dragdata->no, - $dragdata->draggroup, $dragdata->infinite, $dragdata->id); - } - - protected function make_place($dropzonedata) { - return new qtype_ddimageortext_drop_zone($dropzonedata->label, $dropzonedata->no, - $dropzonedata->group, - $dropzonedata->xleft, $dropzonedata->ytop); - } - - protected function make_hint($hint) { - return question_hint_with_parts::load_from_record($hint); - } - protected function initialise_question_instance(question_definition $question, $questiondata) { parent::initialise_question_instance($question, $questiondata); $question->shufflechoices = $questiondata->options->shuffleanswers; @@ -111,95 +92,6 @@ class qtype_ddtoimage_base extends question_type { } } - public function save_question_options($formdata) { - global $DB, $USER; - $context = $formdata->context; - - $options = $DB->get_record('qtype_ddimageortext', array('questionid' => $formdata->id)); - if (!$options) { - $options = new stdClass(); - $options->questionid = $formdata->id; - $options->correctfeedback = ''; - $options->partiallycorrectfeedback = ''; - $options->incorrectfeedback = ''; - $options->id = $DB->insert_record('qtype_ddimageortext', $options); - } - - $options->shuffleanswers = !empty($formdata->shuffleanswers); - $options = $this->save_combined_feedback_helper($options, $formdata, $context, true); - $this->save_hints($formdata, true); - $DB->update_record('qtype_ddimageortext', $options); - $DB->delete_records('qtype_ddimageortext_drops', array('questionid' => $formdata->id)); - foreach (array_keys($formdata->drops) as $dropno) { - if ($formdata->drops[$dropno]['choice'] == 0) { - continue; - } - $drop = new stdClass(); - $drop->questionid = $formdata->id; - $drop->no = $dropno + 1; - $drop->xleft = $formdata->drops[$dropno]['xleft']; - $drop->ytop = $formdata->drops[$dropno]['ytop']; - $drop->choice = $formdata->drops[$dropno]['choice']; - $drop->label = $formdata->drops[$dropno]['droplabel']; - - $DB->insert_record('qtype_ddimageortext_drops', $drop); - } - - //an array of drag no -> drag id - $olddragids = $DB->get_records_menu('qtype_ddimageortext_drags', - array('questionid' => $formdata->id), - '', 'no, id'); - foreach (array_keys($formdata->drags) as $dragno) { - $info = file_get_draft_area_info($formdata->dragitem[$dragno]); - if ($info['filecount'] > 0 || (trim($formdata->drags[$dragno]['draglabel'])!='')) { - $draftitemid = $formdata->dragitem[$dragno]; - - $drag = new stdClass(); - $drag->questionid = $formdata->id; - $drag->no = $dragno + 1; - $drag->draggroup = $formdata->drags[$dragno]['draggroup']; - $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; - $drag->label = $formdata->drags[$dragno]['draglabel']; - - if (isset($olddragids[$dragno +1])) { - $drag->id = $olddragids[$dragno +1]; - unset($olddragids[$dragno +1]); - $DB->update_record('qtype_ddimageortext_drags', $drag); - } else { - $drag->id = $DB->insert_record('qtype_ddimageortext_drags', $drag); - } - - if ($formdata->dragitemtype[$dragno] == 'image') { - self::constrain_image_size_in_draft_area($draftitemid, - QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH, - QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT); - file_save_draft_area_files($draftitemid, $formdata->context->id, - 'qtype_ddimageortext', 'dragimage', $drag->id, - array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); - } else { - //delete any existing files for draggable text item type - $fs = get_file_storage(); - $fs->delete_area_files($formdata->context->id, 'qtype_ddimageortext', - 'dragimage', $drag->id); - } - - } - - } - if (!empty($olddragids)) { - list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); - $DB->delete_records_select('qtype_ddimageortext_drags', "id $sql", $params); - } - - self::constrain_image_size_in_draft_area($formdata->bgimage, - QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH, - QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT); - file_save_draft_area_files($formdata->bgimage, $formdata->context->id, - 'qtype_ddimageortext', 'bgimage', $formdata->id, - array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); - } - - public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) { global $USER; $usercontext = get_context_instance(CONTEXT_USER, $USER->id); @@ -243,139 +135,7 @@ class qtype_ddtoimage_base extends question_type { } } } - public function move_files($questionid, $oldcontextid, $newcontextid) { - global $DB; - $fs = get_file_storage(); - parent::move_files($questionid, $oldcontextid, $newcontextid); - $fs->move_area_files_to_new_context($oldcontextid, - $newcontextid, 'qtype_ddimageortext', 'bgimage', $questionid); - $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', - array('questionid' => $questionid), 'id', 'id,1'); - foreach ($dragids as $dragid => $notused) { - $fs->move_area_files_to_new_context($oldcontextid, - $newcontextid, 'qtype_ddimageortext', 'dragimage', $dragid); - } - - $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); - } - - /** - * Delete all the files belonging to this question. - * @param int $questionid the question being deleted. - * @param int $contextid the context the question is in. - */ - - protected function delete_files($questionid, $contextid) { - global $DB; - $fs = get_file_storage(); - - parent::delete_files($questionid, $contextid); - - $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', - array('questionid' => $questionid), 'id', 'id,1'); - foreach ($dragids as $dragid => $notused) { - $fs->delete_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $dragid); - } - - $this->delete_files_in_combined_feedback($questionid, $contextid); - } - - public function export_to_xml($question, $format, $extra = null) { - $fs = get_file_storage(); - $contextid = $question->contextid; - $output = ''; - - if ($question->options->shuffleanswers) { - $output .= " \n"; - } - $output .= $format->write_combined_feedback($question->options); - $output .= $format->write_hints($question); - $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); - $output .= " ".$this->write_files($files, 2)."\n";; - - foreach ($question->options->drags as $drag) { - $files = - $fs->get_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $drag->id); - $output .= " \n"; - $output .= " {$drag->no}\n"; - $output .= $format->writetext($drag->label, 3)."\n"; - $output .= " {$drag->draggroup}\n"; - if ($drag->infinite) { - $output .= " \n"; - } - $output .= $this->write_files($files, 3); - $output .= " \n"; - } - foreach ($question->options->drops as $drop) { - $output .= " \n"; - $output .= $format->writetext($drop->label, 3); - $output .= " {$drop->no}\n"; - $output .= " {$drop->choice}\n"; - $output .= " {$drop->xleft}\n"; - $output .= " {$drop->ytop}\n"; - $output .= " \n"; - } - - return $output; - } - - public function import_from_xml($data, $question, $format, $extra=null) { - if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimageortext') { - return false; - } - - $question = $format->import_headers($data); - $question->qtype = 'ddimageortext'; - - $question->shuffleanswers = array_key_exists('shuffleanswers', - $format->getpath($data, array('#'), array())); - - $filexml = $format->getpath($data, array('#', 'file'), array()); - $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml); - $drags = $data['#']['drag']; - $question->drags = array(); - - foreach ($drags as $dragxml) { - $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0); - $dragindex = $dragno -1; - $question->drags[$dragindex] = array(); - $question->drags[$dragindex]['draglabel'] = - $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); - $question->drags[$dragindex]['infinite'] = array_key_exists('infinite', $dragxml['#']); - $question->drags[$dragindex]['draggroup'] = - $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1); - $filexml = $format->getpath($dragxml, array('#', 'file'), array()); - $question->dragitem[$dragindex] = - $this->import_files_to_draft_file_area($format, $filexml); - if (count($filexml)) { - $question->dragitemtype[$dragindex] = 'image'; - } else { - $question->dragitemtype[$dragindex] = 'word'; - } - } - - $drops = $data['#']['drop']; - $question->drops = array(); - foreach ($drops as $dropxml) { - $dropno = $format->getpath($dropxml, array('#', 'no', 0, '#'), 0); - $dropindex = $dropno -1; - $question->drops[$dropindex] = array(); - $question->drops[$dropindex]['choice'] = - $format->getpath($dropxml, array('#', 'choice', 0, '#'), 0); - $question->drops[$dropindex]['droplabel'] = - $format->getpath($dropxml, array('#', 'text', 0, '#'), '', true); - $question->drops[$dropindex]['xleft'] = - $format->getpath($dropxml, array('#', 'xleft', 0, '#'), ''); - $question->drops[$dropindex]['ytop'] = - $format->getpath($dropxml, array('#', 'ytop', 0, '#'), ''); - } - - $format->import_combined_feedback($question, $data, true); - $format->import_hints($question, $data, true); - - return $question; - } /** @@ -440,9 +200,11 @@ class qtype_ddtoimage_base extends question_type { $summarisechoice = $choice->summarise(); $correct = $question->rightchoices[$placeno] == $i; - $choices[$choice->no] = new question_possible_response( - $summarisechoice, - $correct?1:0); + if ($correct) { + $choices[$choice->no] = new question_possible_response( + $summarisechoice, + $correct?1:0); + } } $choices[null] = question_possible_response::no_response(); From fdaacb9e6058f74288b48bf67489698b6f21f6fa Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 4 Nov 2011 17:49:38 +0700 Subject: [PATCH 134/208] MDL-47494 ddimageortext: NOBUG adding some drop shadow to drags --- question/type/ddimageortext/styles.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index bc9365df553..95287819957 100755 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -74,3 +74,14 @@ form.mform fieldset#previewareaheader div.draghome, form.mform fieldset#previewa *font-size:small; /* for IE */ *font:x-small; /* for IE in quirks mode */ } +form.mform fieldset#previewareaheader div.drag.yui3-dd-dragging, +.que.ddimageortext div.drag.yui3-dd-dragging { + z-index: 3; + -moz-box-shadow: 3px 3px 4px #000; + -webkit-box-shadow: 3px 3px 4px #000; + box-shadow: 3px 3px 4px #000; + /* For IE 8 */ + -ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000')"; + /* For IE 5.5 - 7 */ + filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000'); +} \ No newline at end of file From 5a20554702460652c5ae970725f090f35e2536d3 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 4 Nov 2011 12:51:47 +0000 Subject: [PATCH 135/208] MDL-47494 ddimageortext: Tweak lang strings and fix file permissions. --- question/type/ddimageortext/db/install.xml | 0 .../ddimageortext/lang/en/qtype_ddimageortext.php | 8 ++++---- question/type/ddimageortext/pix/icon.gif | Bin question/type/ddimageortext/question.php | 0 question/type/ddimageortext/questiontype.php | 0 question/type/ddimageortext/renderer.php | 0 question/type/ddimageortext/simpletest/helper.php | 0 .../type/ddimageortext/simpletest/testquestion.php | 0 .../ddimageortext/simpletest/testquestiontype.php | 0 .../ddimageortext/simpletest/testwalkthrough.php | 0 question/type/ddimageortext/styles.css | 0 question/type/ddimageortext/version.php | 0 12 files changed, 4 insertions(+), 4 deletions(-) mode change 100755 => 100644 question/type/ddimageortext/db/install.xml mode change 100755 => 100644 question/type/ddimageortext/pix/icon.gif mode change 100755 => 100644 question/type/ddimageortext/question.php mode change 100755 => 100644 question/type/ddimageortext/questiontype.php mode change 100755 => 100644 question/type/ddimageortext/renderer.php mode change 100755 => 100644 question/type/ddimageortext/simpletest/helper.php mode change 100755 => 100644 question/type/ddimageortext/simpletest/testquestion.php mode change 100755 => 100644 question/type/ddimageortext/simpletest/testquestiontype.php mode change 100755 => 100644 question/type/ddimageortext/simpletest/testwalkthrough.php mode change 100755 => 100644 question/type/ddimageortext/styles.css mode change 100755 => 100644 question/type/ddimageortext/version.php diff --git a/question/type/ddimageortext/db/install.xml b/question/type/ddimageortext/db/install.xml old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index 0a27d38865e..9f8262bf1f5 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -22,15 +22,15 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['addingddimageortext'] = 'Adding drag and drop onto images'; +$string['addingddimageortext'] = 'Adding drag and drop onto image'; $string['addmoredropzones'] = 'Blanks for {no} More Drop Zones'; $string['addmoreimages'] = 'Blanks for {no} More Draggable Items'; $string['answer'] = 'Answer'; $string['bgimage'] = 'Background Image'; $string['correctansweris'] = 'The correct answer is: {$a}'; -$string['ddimageortext'] = 'Drag and drop onto images'; +$string['ddimageortext'] = 'Drag and drop onto image'; $string['ddimageortext_help'] = 'Select a background image file, select draggable images or enter text and define the drop zones on the background image to which they must be dragged.'; -$string['ddimageortextsummary'] = 'Images or text labels are dragged and dropped into visible drop zones on a background image.'; +$string['ddimageortextsummary'] = 'Images or text labels are dragged and dropped into drop zones on a background image.'; $string['draggableimage'] = 'Draggable image'; $string['draggableitem'] = 'Draggable item'; $string['draggableitemheader'] = 'Draggable item {$a}'; @@ -38,7 +38,7 @@ $string['draggableitemtype'] = 'Type'; $string['draggableword'] = 'Draggable text'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; -$string['editingddimageortext'] = 'Editing drag and drop onto images'; +$string['editingddimageortext'] = 'Editing drag and drop onto image'; $string['formerror_disallowedtags'] = 'You have used html tags here that are not allowed in a draggable text drag item type.'; $string['formerror_noallowedtags'] = 'No html tags are allowed in this text which is the alt text for a draggable image'; $string['formerror_noytop'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; diff --git a/question/type/ddimageortext/pix/icon.gif b/question/type/ddimageortext/pix/icon.gif old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/simpletest/helper.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css old mode 100755 new mode 100644 diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php old mode 100755 new mode 100644 From c82675e06cff7822fdda4dfe20e0dcc626fc8b18 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 12 Nov 2011 15:48:37 +0700 Subject: [PATCH 136/208] MDL-47494 ddimageortext: NOBUG adding comments to identify keys for key numbers in keyboard listener --- question/type/ddimageortext/yui/dd/dd.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index faff9418b30..06b5298039d 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -439,12 +439,12 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', _keys: { - '32': 'next', - '37': 'previous', - '38': 'previous', - '39': 'next', - '40': 'next', - '27': 'remove' + '32': 'next', // Space + '37': 'previous', // Left arrow + '38': 'previous', // Up arrow + '39': 'next', // Right arrow + '40': 'next', // Down arrow + '27': 'remove' // Escape }, _keyHandler: function (e, notifier) { From d7625a96f17e808cf8898ffddb81298ab83d9ef2 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 18 Nov 2011 10:01:55 +0700 Subject: [PATCH 137/208] MDL-47494 ddimageortext: NOBUG moving some methods from out of the question_type base class --- question/type/ddimageortext/questiontype.php | 237 +++++++++++++++++ .../type/ddimageortext/questiontypebase.php | 248 +----------------- 2 files changed, 242 insertions(+), 243 deletions(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 34879f0e244..d5f1cec0bef 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -41,4 +41,241 @@ define('QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT', 100); */ class qtype_ddimageortext extends qtype_ddtoimage_base { + protected function make_choice($dragdata) { + return new qtype_ddimageortext_drag_item($dragdata->label, $dragdata->no, + $dragdata->draggroup, $dragdata->infinite, $dragdata->id); + } + + protected function make_place($dropzonedata) { + return new qtype_ddimageortext_drop_zone($dropzonedata->label, $dropzonedata->no, + $dropzonedata->group, + $dropzonedata->xleft, $dropzonedata->ytop); + } + + protected function make_hint($hint) { + return question_hint_with_parts::load_from_record($hint); + } + + public function save_question_options($formdata) { + global $DB, $USER; + $context = $formdata->context; + + $options = $DB->get_record('qtype_ddimageortext', array('questionid' => $formdata->id)); + if (!$options) { + $options = new stdClass(); + $options->questionid = $formdata->id; + $options->correctfeedback = ''; + $options->partiallycorrectfeedback = ''; + $options->incorrectfeedback = ''; + $options->id = $DB->insert_record('qtype_ddimageortext', $options); + } + + $options->shuffleanswers = !empty($formdata->shuffleanswers); + $options = $this->save_combined_feedback_helper($options, $formdata, $context, true); + $this->save_hints($formdata, true); + $DB->update_record('qtype_ddimageortext', $options); + $DB->delete_records('qtype_ddimageortext_drops', array('questionid' => $formdata->id)); + foreach (array_keys($formdata->drops) as $dropno) { + if ($formdata->drops[$dropno]['choice'] == 0) { + continue; + } + $drop = new stdClass(); + $drop->questionid = $formdata->id; + $drop->no = $dropno + 1; + $drop->xleft = $formdata->drops[$dropno]['xleft']; + $drop->ytop = $formdata->drops[$dropno]['ytop']; + $drop->choice = $formdata->drops[$dropno]['choice']; + $drop->label = $formdata->drops[$dropno]['droplabel']; + + $DB->insert_record('qtype_ddimageortext_drops', $drop); + } + + //an array of drag no -> drag id + $olddragids = $DB->get_records_menu('qtype_ddimageortext_drags', + array('questionid' => $formdata->id), + '', 'no, id'); + foreach (array_keys($formdata->drags) as $dragno) { + $info = file_get_draft_area_info($formdata->dragitem[$dragno]); + if ($info['filecount'] > 0 || (trim($formdata->drags[$dragno]['draglabel'])!='')) { + $draftitemid = $formdata->dragitem[$dragno]; + + $drag = new stdClass(); + $drag->questionid = $formdata->id; + $drag->no = $dragno + 1; + $drag->draggroup = $formdata->drags[$dragno]['draggroup']; + $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; + $drag->label = $formdata->drags[$dragno]['draglabel']; + + if (isset($olddragids[$dragno +1])) { + $drag->id = $olddragids[$dragno +1]; + unset($olddragids[$dragno +1]); + $DB->update_record('qtype_ddimageortext_drags', $drag); + } else { + $drag->id = $DB->insert_record('qtype_ddimageortext_drags', $drag); + } + + if ($formdata->dragitemtype[$dragno] == 'image') { + self::constrain_image_size_in_draft_area($draftitemid, + QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH, + QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT); + file_save_draft_area_files($draftitemid, $formdata->context->id, + 'qtype_ddimageortext', 'dragimage', $drag->id, + array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); + } else { + //delete any existing files for draggable text item type + $fs = get_file_storage(); + $fs->delete_area_files($formdata->context->id, 'qtype_ddimageortext', + 'dragimage', $drag->id); + } + + } + + } + if (!empty($olddragids)) { + list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); + $DB->delete_records_select('qtype_ddimageortext_drags', "id $sql", $params); + } + + self::constrain_image_size_in_draft_area($formdata->bgimage, + QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH, + QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT); + file_save_draft_area_files($formdata->bgimage, $formdata->context->id, + 'qtype_ddimageortext', 'bgimage', $formdata->id, + array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); + } + public function move_files($questionid, $oldcontextid, $newcontextid) { + global $DB; + $fs = get_file_storage(); + + parent::move_files($questionid, $oldcontextid, $newcontextid); + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'qtype_ddimageortext', 'bgimage', $questionid); + $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', + array('questionid' => $questionid), 'id', 'id,1'); + foreach ($dragids as $dragid => $notused) { + $fs->move_area_files_to_new_context($oldcontextid, + $newcontextid, 'qtype_ddimageortext', 'dragimage', $dragid); + } + + $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); + } + + /** + * Delete all the files belonging to this question. + * @param int $questionid the question being deleted. + * @param int $contextid the context the question is in. + */ + + protected function delete_files($questionid, $contextid) { + global $DB; + $fs = get_file_storage(); + + parent::delete_files($questionid, $contextid); + + $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', + array('questionid' => $questionid), 'id', 'id,1'); + foreach ($dragids as $dragid => $notused) { + $fs->delete_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $dragid); + } + + $this->delete_files_in_combined_feedback($questionid, $contextid); + } + + + public function export_to_xml($question, $format, $extra = null) { + $fs = get_file_storage(); + $contextid = $question->contextid; + $output = ''; + + if ($question->options->shuffleanswers) { + $output .= " \n"; + } + $output .= $format->write_combined_feedback($question->options); + $output .= $format->write_hints($question); + $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); + $output .= " ".$this->write_files($files, 2)."\n";; + + foreach ($question->options->drags as $drag) { + $files = + $fs->get_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $drag->id); + $output .= " \n"; + $output .= " {$drag->no}\n"; + $output .= $format->writetext($drag->label, 3)."\n"; + $output .= " {$drag->draggroup}\n"; + if ($drag->infinite) { + $output .= " \n"; + } + $output .= $this->write_files($files, 3); + $output .= " \n"; + } + foreach ($question->options->drops as $drop) { + $output .= " \n"; + $output .= $format->writetext($drop->label, 3); + $output .= " {$drop->no}\n"; + $output .= " {$drop->choice}\n"; + $output .= " {$drop->xleft}\n"; + $output .= " {$drop->ytop}\n"; + $output .= " \n"; + } + + return $output; + } + + public function import_from_xml($data, $question, $format, $extra=null) { + if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimageortext') { + return false; + } + + $question = $format->import_headers($data); + $question->qtype = 'ddimageortext'; + + $question->shuffleanswers = array_key_exists('shuffleanswers', + $format->getpath($data, array('#'), array())); + + $filexml = $format->getpath($data, array('#', 'file'), array()); + $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml); + $drags = $data['#']['drag']; + $question->drags = array(); + + foreach ($drags as $dragxml) { + $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0); + $dragindex = $dragno -1; + $question->drags[$dragindex] = array(); + $question->drags[$dragindex]['draglabel'] = + $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); + $question->drags[$dragindex]['infinite'] = array_key_exists('infinite', $dragxml['#']); + $question->drags[$dragindex]['draggroup'] = + $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1); + $filexml = $format->getpath($dragxml, array('#', 'file'), array()); + $question->dragitem[$dragindex] = + $this->import_files_to_draft_file_area($format, $filexml); + if (count($filexml)) { + $question->dragitemtype[$dragindex] = 'image'; + } else { + $question->dragitemtype[$dragindex] = 'word'; + } + } + + $drops = $data['#']['drop']; + $question->drops = array(); + foreach ($drops as $dropxml) { + $dropno = $format->getpath($dropxml, array('#', 'no', 0, '#'), 0); + $dropindex = $dropno -1; + $question->drops[$dropindex] = array(); + $question->drops[$dropindex]['choice'] = + $format->getpath($dropxml, array('#', 'choice', 0, '#'), 0); + $question->drops[$dropindex]['droplabel'] = + $format->getpath($dropxml, array('#', 'text', 0, '#'), '', true); + $question->drops[$dropindex]['xleft'] = + $format->getpath($dropxml, array('#', 'xleft', 0, '#'), ''); + $question->drops[$dropindex]['ytop'] = + $format->getpath($dropxml, array('#', 'ytop', 0, '#'), ''); + } + + $format->import_combined_feedback($question, $data, true); + $format->import_hints($question, $data, true); + + return $question; + } + } diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index ed46a7af32f..57248c3b591 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -42,10 +42,6 @@ class qtype_ddtoimage_base extends question_type { return 'draggroup'; } - public function requires_qtypes() { - return array_merge(parent::requires_qtypes()); - } - public function get_question_options($question) { global $DB; $dbprefix = 'qtype_'.$this->name(); @@ -58,21 +54,6 @@ class qtype_ddtoimage_base extends question_type { parent::get_question_options($question); } - protected function make_choice($dragdata) { - return new qtype_ddimageortext_drag_item($dragdata->label, $dragdata->no, - $dragdata->draggroup, $dragdata->infinite, $dragdata->id); - } - - protected function make_place($dropzonedata) { - return new qtype_ddimageortext_drop_zone($dropzonedata->label, $dropzonedata->no, - $dropzonedata->group, - $dropzonedata->xleft, $dropzonedata->ytop); - } - - protected function make_hint($hint) { - return question_hint_with_parts::load_from_record($hint); - } - protected function initialise_question_instance(question_definition $question, $questiondata) { parent::initialise_question_instance($question, $questiondata); $question->shufflechoices = $questiondata->options->shuffleanswers; @@ -111,95 +92,6 @@ class qtype_ddtoimage_base extends question_type { } } - public function save_question_options($formdata) { - global $DB, $USER; - $context = $formdata->context; - - $options = $DB->get_record('qtype_ddimageortext', array('questionid' => $formdata->id)); - if (!$options) { - $options = new stdClass(); - $options->questionid = $formdata->id; - $options->correctfeedback = ''; - $options->partiallycorrectfeedback = ''; - $options->incorrectfeedback = ''; - $options->id = $DB->insert_record('qtype_ddimageortext', $options); - } - - $options->shuffleanswers = !empty($formdata->shuffleanswers); - $options = $this->save_combined_feedback_helper($options, $formdata, $context, true); - $this->save_hints($formdata, true); - $DB->update_record('qtype_ddimageortext', $options); - $DB->delete_records('qtype_ddimageortext_drops', array('questionid' => $formdata->id)); - foreach (array_keys($formdata->drops) as $dropno) { - if ($formdata->drops[$dropno]['choice'] == 0) { - continue; - } - $drop = new stdClass(); - $drop->questionid = $formdata->id; - $drop->no = $dropno + 1; - $drop->xleft = $formdata->drops[$dropno]['xleft']; - $drop->ytop = $formdata->drops[$dropno]['ytop']; - $drop->choice = $formdata->drops[$dropno]['choice']; - $drop->label = $formdata->drops[$dropno]['droplabel']; - - $DB->insert_record('qtype_ddimageortext_drops', $drop); - } - - //an array of drag no -> drag id - $olddragids = $DB->get_records_menu('qtype_ddimageortext_drags', - array('questionid' => $formdata->id), - '', 'no, id'); - foreach (array_keys($formdata->drags) as $dragno) { - $info = file_get_draft_area_info($formdata->dragitem[$dragno]); - if ($info['filecount'] > 0 || (trim($formdata->drags[$dragno]['draglabel'])!='')) { - $draftitemid = $formdata->dragitem[$dragno]; - - $drag = new stdClass(); - $drag->questionid = $formdata->id; - $drag->no = $dragno + 1; - $drag->draggroup = $formdata->drags[$dragno]['draggroup']; - $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; - $drag->label = $formdata->drags[$dragno]['draglabel']; - - if (isset($olddragids[$dragno +1])) { - $drag->id = $olddragids[$dragno +1]; - unset($olddragids[$dragno +1]); - $DB->update_record('qtype_ddimageortext_drags', $drag); - } else { - $drag->id = $DB->insert_record('qtype_ddimageortext_drags', $drag); - } - - if ($formdata->dragitemtype[$dragno] == 'image') { - self::constrain_image_size_in_draft_area($draftitemid, - QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH, - QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT); - file_save_draft_area_files($draftitemid, $formdata->context->id, - 'qtype_ddimageortext', 'dragimage', $drag->id, - array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); - } else { - //delete any existing files for draggable text item type - $fs = get_file_storage(); - $fs->delete_area_files($formdata->context->id, 'qtype_ddimageortext', - 'dragimage', $drag->id); - } - - } - - } - if (!empty($olddragids)) { - list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); - $DB->delete_records_select('qtype_ddimageortext_drags', "id $sql", $params); - } - - self::constrain_image_size_in_draft_area($formdata->bgimage, - QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH, - QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT); - file_save_draft_area_files($formdata->bgimage, $formdata->context->id, - 'qtype_ddimageortext', 'bgimage', $formdata->id, - array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); - } - - public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) { global $USER; $usercontext = get_context_instance(CONTEXT_USER, $USER->id); @@ -243,139 +135,7 @@ class qtype_ddtoimage_base extends question_type { } } } - public function move_files($questionid, $oldcontextid, $newcontextid) { - global $DB; - $fs = get_file_storage(); - parent::move_files($questionid, $oldcontextid, $newcontextid); - $fs->move_area_files_to_new_context($oldcontextid, - $newcontextid, 'qtype_ddimageortext', 'bgimage', $questionid); - $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', - array('questionid' => $questionid), 'id', 'id,1'); - foreach ($dragids as $dragid => $notused) { - $fs->move_area_files_to_new_context($oldcontextid, - $newcontextid, 'qtype_ddimageortext', 'dragimage', $dragid); - } - - $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); - } - - /** - * Delete all the files belonging to this question. - * @param int $questionid the question being deleted. - * @param int $contextid the context the question is in. - */ - - protected function delete_files($questionid, $contextid) { - global $DB; - $fs = get_file_storage(); - - parent::delete_files($questionid, $contextid); - - $dragids = $DB->get_records_menu('qtype_ddimageortext_drags', - array('questionid' => $questionid), 'id', 'id,1'); - foreach ($dragids as $dragid => $notused) { - $fs->delete_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $dragid); - } - - $this->delete_files_in_combined_feedback($questionid, $contextid); - } - - public function export_to_xml($question, $format, $extra = null) { - $fs = get_file_storage(); - $contextid = $question->contextid; - $output = ''; - - if ($question->options->shuffleanswers) { - $output .= " \n"; - } - $output .= $format->write_combined_feedback($question->options); - $output .= $format->write_hints($question); - $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); - $output .= " ".$this->write_files($files, 2)."\n";; - - foreach ($question->options->drags as $drag) { - $files = - $fs->get_area_files($contextid, 'qtype_ddimageortext', 'dragimage', $drag->id); - $output .= " \n"; - $output .= " {$drag->no}\n"; - $output .= $format->writetext($drag->label, 3)."\n"; - $output .= " {$drag->draggroup}\n"; - if ($drag->infinite) { - $output .= " \n"; - } - $output .= $this->write_files($files, 3); - $output .= " \n"; - } - foreach ($question->options->drops as $drop) { - $output .= " \n"; - $output .= $format->writetext($drop->label, 3); - $output .= " {$drop->no}\n"; - $output .= " {$drop->choice}\n"; - $output .= " {$drop->xleft}\n"; - $output .= " {$drop->ytop}\n"; - $output .= " \n"; - } - - return $output; - } - - public function import_from_xml($data, $question, $format, $extra=null) { - if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimageortext') { - return false; - } - - $question = $format->import_headers($data); - $question->qtype = 'ddimageortext'; - - $question->shuffleanswers = array_key_exists('shuffleanswers', - $format->getpath($data, array('#'), array())); - - $filexml = $format->getpath($data, array('#', 'file'), array()); - $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml); - $drags = $data['#']['drag']; - $question->drags = array(); - - foreach ($drags as $dragxml) { - $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0); - $dragindex = $dragno -1; - $question->drags[$dragindex] = array(); - $question->drags[$dragindex]['draglabel'] = - $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); - $question->drags[$dragindex]['infinite'] = array_key_exists('infinite', $dragxml['#']); - $question->drags[$dragindex]['draggroup'] = - $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1); - $filexml = $format->getpath($dragxml, array('#', 'file'), array()); - $question->dragitem[$dragindex] = - $this->import_files_to_draft_file_area($format, $filexml); - if (count($filexml)) { - $question->dragitemtype[$dragindex] = 'image'; - } else { - $question->dragitemtype[$dragindex] = 'word'; - } - } - - $drops = $data['#']['drop']; - $question->drops = array(); - foreach ($drops as $dropxml) { - $dropno = $format->getpath($dropxml, array('#', 'no', 0, '#'), 0); - $dropindex = $dropno -1; - $question->drops[$dropindex] = array(); - $question->drops[$dropindex]['choice'] = - $format->getpath($dropxml, array('#', 'choice', 0, '#'), 0); - $question->drops[$dropindex]['droplabel'] = - $format->getpath($dropxml, array('#', 'text', 0, '#'), '', true); - $question->drops[$dropindex]['xleft'] = - $format->getpath($dropxml, array('#', 'xleft', 0, '#'), ''); - $question->drops[$dropindex]['ytop'] = - $format->getpath($dropxml, array('#', 'ytop', 0, '#'), ''); - } - - $format->import_combined_feedback($question, $data, true); - $format->import_hints($question, $data, true); - - return $question; - } /** @@ -440,9 +200,11 @@ class qtype_ddtoimage_base extends question_type { $summarisechoice = $choice->summarise(); $correct = $question->rightchoices[$placeno] == $i; - $choices[$choice->no] = new question_possible_response( - $summarisechoice, - $correct?1:0); + if ($correct) { + $choices[$choice->no] = new question_possible_response( + $summarisechoice, + $correct?1:0); + } } $choices[null] = question_possible_response::no_response(); From d36f336d841e674bf16ed998836cbcd3e29532e4 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 19 Nov 2011 17:00:51 +0700 Subject: [PATCH 138/208] MDL-47494 ddimageortext: MDL-29058 change in api related to fix for saving feedback files --- question/type/ddimageortext/questiontype.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index d5f1cec0bef..6924c38c08a 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -190,7 +190,9 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { if ($question->options->shuffleanswers) { $output .= " \n"; } - $output .= $format->write_combined_feedback($question->options); + $output .= $format->write_combined_feedback($question->options, + $question->id, + $question->contextid); $output .= $format->write_hints($question); $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); $output .= " ".$this->write_files($files, 2)."\n";; From cb5c4e62acb73f8efe60b66376d2529eb3026138 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 19 Nov 2011 17:10:19 +0700 Subject: [PATCH 139/208] MDL-47494 ddimageortext: NOBUG fixing question tables referred to for question deleting --- question/type/ddimageortext/questiontypebase.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index 57248c3b591..586e71b4d33 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -218,5 +218,10 @@ class qtype_ddtoimage_base extends question_type { $question = $this->make_question($questiondata); return $question->get_random_guess_score(); } - + public function delete_question($questionid, $contextid) { + global $DB; + $DB->delete_records('qtype_'.$this->name().'_drags', array('questionid' => $questionid)); + $DB->delete_records('qtype_'.$this->name().'_drops', array('questionid' => $questionid)); + return parent::delete_question($questionid, $contextid); + } } From 5b7d9decd9b62575a9e5fc03d9acb5370956b1a5 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 19 Nov 2011 17:23:32 +0700 Subject: [PATCH 140/208] MDL-47494 ddimageortext: NOBUG adding main question type table that needs deleting to question_delete --- question/type/ddimageortext/questiontypebase.php | 1 + 1 file changed, 1 insertion(+) diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index 586e71b4d33..f3e60ecb285 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -220,6 +220,7 @@ class qtype_ddtoimage_base extends question_type { } public function delete_question($questionid, $contextid) { global $DB; + $DB->delete_records('qtype_'.$this->name(), array('questionid' => $questionid)); $DB->delete_records('qtype_'.$this->name().'_drags', array('questionid' => $questionid)); $DB->delete_records('qtype_'.$this->name().'_drops', array('questionid' => $questionid)); return parent::delete_question($questionid, $contextid); From 172d6dfd12bcfe3fd8b6a4133d301816e51c61e9 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 23 Nov 2011 12:50:29 +0700 Subject: [PATCH 141/208] MDL-47494 ddimageortext: NOBUG if any choice is 'infinite' return null for random guess score --- question/type/ddimageortext/questionbase.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/question/type/ddimageortext/questionbase.php b/question/type/ddimageortext/questionbase.php index 3f594355ba7..4ad33327f25 100644 --- a/question/type/ddimageortext/questionbase.php +++ b/question/type/ddimageortext/questionbase.php @@ -133,6 +133,11 @@ class qtype_ddtoimage_question_base extends qtype_gapselect_question_base { $accum = 0; foreach ($this->places as $place) { + foreach ($this->choices[$place->group] as $choice) { + if ($choice->infinite) { + return null; + } + } $accum += 1 / count($this->choices[$place->group]); } From a187ada8cf0a434cc6da449f69d767f87a1bb67f Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 23 Nov 2011 12:50:29 +0700 Subject: [PATCH 142/208] MDL-47494 ddimageortext: NOBUG if any choice is 'infinite' return null for random guess score --- question/type/ddimageortext/questionbase.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/question/type/ddimageortext/questionbase.php b/question/type/ddimageortext/questionbase.php index 3f594355ba7..4ad33327f25 100644 --- a/question/type/ddimageortext/questionbase.php +++ b/question/type/ddimageortext/questionbase.php @@ -133,6 +133,11 @@ class qtype_ddtoimage_question_base extends qtype_gapselect_question_base { $accum = 0; foreach ($this->places as $place) { + foreach ($this->choices[$place->group] as $choice) { + if ($choice->infinite) { + return null; + } + } $accum += 1 / count($this->choices[$place->group]); } From 39ed2eee2a84019dd32f9662a9ceff69f0229b3f Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 23 Nov 2011 17:04:35 +0000 Subject: [PATCH 143/208] MDL-47494 ddimageortext: Fix invalid HTML caused by empty_tag('div', ...). #2273 --- question/type/ddimageortext/rendererbase.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index 13e899fc974..a6a2ab77c87 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -102,15 +102,17 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere $dragitemsclass .= ' readonly'; } $dragitems = html_writer::tag('div', $dragimagehomes, array('class'=> $dragitemsclass)); - $dropzones = html_writer::empty_tag('div', array('class'=>'dropzones')); - $output .= html_writer::tag('div', $droparea.$dragitems.$dropzones, - array('class'=>'ddarea')); + $dropzones = html_writer::tag('div', '', array('class'=>'dropzones')); + + $hiddens = ''; foreach ($question->places as $placeno => $place) { $varname = $question->field($placeno); list($fieldname, $html) = $this->hidden_field_for_qt_var($qa, $varname); - $output .= $html; + $hiddens .= $html; $question->places[$placeno]->fieldname = $fieldname; } + $output .= html_writer::tag('div', + $droparea . $dragitems . $dropzones . $hiddens, array('class'=>'ddarea')); $topnode = 'div#q'.$qa->get_slot().' div.ddarea'; $params = array('drops' => $question->places, 'topnode' => $topnode, From 1e62114e5d0bd4a606f214fcc43a0a5cfe1e07c7 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 23 Nov 2011 17:04:35 +0000 Subject: [PATCH 144/208] MDL-47494 ddimageortext: Fix invalid HTML caused by empty_tag('div', ...). #2273 --- question/type/ddimageortext/rendererbase.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index 13e899fc974..a6a2ab77c87 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -102,15 +102,17 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere $dragitemsclass .= ' readonly'; } $dragitems = html_writer::tag('div', $dragimagehomes, array('class'=> $dragitemsclass)); - $dropzones = html_writer::empty_tag('div', array('class'=>'dropzones')); - $output .= html_writer::tag('div', $droparea.$dragitems.$dropzones, - array('class'=>'ddarea')); + $dropzones = html_writer::tag('div', '', array('class'=>'dropzones')); + + $hiddens = ''; foreach ($question->places as $placeno => $place) { $varname = $question->field($placeno); list($fieldname, $html) = $this->hidden_field_for_qt_var($qa, $varname); - $output .= $html; + $hiddens .= $html; $question->places[$placeno]->fieldname = $fieldname; } + $output .= html_writer::tag('div', + $droparea . $dragitems . $dropzones . $hiddens, array('class'=>'ddarea')); $topnode = 'div#q'.$qa->get_slot().' div.ddarea'; $params = array('drops' => $question->places, 'topnode' => $topnode, From f8f8163e94e1c2259e5d2186d5ddb12def7b6d6b Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 29 Nov 2011 07:06:24 +0700 Subject: [PATCH 145/208] MDL-47494 ddimageortext: NOBUG lang string changes --- .../type/ddimageortext/lang/en/qtype_ddimageortext.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index 9f8262bf1f5..d7e9948adc6 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -23,10 +23,10 @@ */ $string['addingddimageortext'] = 'Adding drag and drop onto image'; -$string['addmoredropzones'] = 'Blanks for {no} More Drop Zones'; -$string['addmoreimages'] = 'Blanks for {no} More Draggable Items'; +$string['addmoredropzones'] = 'Blanks for {no} more drop zones'; +$string['addmoreimages'] = 'Blanks for {no} more draggable items'; $string['answer'] = 'Answer'; -$string['bgimage'] = 'Background Image'; +$string['bgimage'] = 'Background image'; $string['correctansweris'] = 'The correct answer is: {$a}'; $string['ddimageortext'] = 'Drag and drop onto image'; $string['ddimageortext_help'] = 'Select a background image file, select draggable images or enter text and define the drop zones on the background image to which they must be dragged.'; @@ -57,7 +57,7 @@ $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; $string['refresh'] = 'Refresh Preview'; -$string['shuffleimages'] = 'Shuffle Drag Items Each Time Question Is Attempted'; +$string['shuffleimages'] = 'Shuffle drag items each time question is attempted'; $string['summarisechoice'] = '{$a->no}. {$a->text}'; $string['summariseplace'] = '{$a->no}. {$a->text}'; $string['summarisechoiceno'] = 'Item {$a}'; From 8c0650fc4ac4393d6e4bfce62026ccb9531c6a79 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 1 Dec 2011 11:49:21 +0000 Subject: [PATCH 146/208] MDL-47494 ddimageortext: Remove redundant line of code. Hints are automatically output anyway. --- question/type/ddimageortext/questiontype.php | 1 - 1 file changed, 1 deletion(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 6924c38c08a..866cf4af90a 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -193,7 +193,6 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $output .= $format->write_combined_feedback($question->options, $question->id, $question->contextid); - $output .= $format->write_hints($question); $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); $output .= " ".$this->write_files($files, 2)."\n";; From 6c6fc62627928c85850a184c61e0ac0326fbd959 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 1 Dec 2011 11:49:21 +0000 Subject: [PATCH 147/208] MDL-47494 ddimageortext: Remove redundant line of code. Hints are automatically output anyway. --- question/type/ddimageortext/questiontype.php | 1 - 1 file changed, 1 deletion(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 6924c38c08a..866cf4af90a 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -193,7 +193,6 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $output .= $format->write_combined_feedback($question->options, $question->id, $question->contextid); - $output .= $format->write_hints($question); $files = $fs->get_area_files($contextid, 'qtype_ddimageortext', 'bgimage', $question->id); $output .= " ".$this->write_files($files, 2)."\n";; From 548071f6143c45997287cd865afc0b14af090cfe Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 6 Dec 2011 14:50:19 +0000 Subject: [PATCH 148/208] MDL-47494 ddimageortext: Fix import/export and unit tests. --- question/type/ddimageortext/question.php | 6 +++--- question/type/ddimageortext/questiontype.php | 3 ++- question/type/ddimageortext/rendererbase.php | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index bb716b567ca..84d57f03c27 100644 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -51,14 +51,14 @@ class qtype_ddimageortext_drag_item { public $text; public $no; public $group; - public $isinfinite; + public $infinite; - public function __construct($alttextlabel, $no, $group = 1, $isinfinite = false, $id = 0) { + public function __construct($alttextlabel, $no, $group = 1, $infinite = false, $id = 0) { $this->id = $id; $this->text = $alttextlabel; $this->no = $no; $this->group = $group; - $this->isinfinite = $isinfinite; + $this->infinite = $infinite; } public function choice_group() { return $this->group; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 866cf4af90a..771a71a3a68 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -274,7 +274,8 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { } $format->import_combined_feedback($question, $data, true); - $format->import_hints($question, $data, true); + $format->import_hints($question, $data, true, false, + $format->get_format($question->questiontextformat)); return $question; } diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index a6a2ab77c87..a8d72c62f01 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -77,7 +77,7 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere 'draghome', "dragitemhomes{$dragimage->no}", "choice{$choiceno}"); - if ($dragimage->isinfinite) { + if ($dragimage->infinite) { $classes[] = 'infinite'; } if ($dragimageurl === null) { From 48b39366494acc981d59c7239a74dd49e0495db3 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 6 Dec 2011 14:50:19 +0000 Subject: [PATCH 149/208] MDL-47494 ddimageortext: Fix import/export and unit tests. --- question/type/ddimageortext/question.php | 6 +++--- question/type/ddimageortext/questiontype.php | 3 ++- question/type/ddimageortext/rendererbase.php | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index bb716b567ca..84d57f03c27 100644 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -51,14 +51,14 @@ class qtype_ddimageortext_drag_item { public $text; public $no; public $group; - public $isinfinite; + public $infinite; - public function __construct($alttextlabel, $no, $group = 1, $isinfinite = false, $id = 0) { + public function __construct($alttextlabel, $no, $group = 1, $infinite = false, $id = 0) { $this->id = $id; $this->text = $alttextlabel; $this->no = $no; $this->group = $group; - $this->isinfinite = $isinfinite; + $this->infinite = $infinite; } public function choice_group() { return $this->group; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 866cf4af90a..771a71a3a68 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -274,7 +274,8 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { } $format->import_combined_feedback($question, $data, true); - $format->import_hints($question, $data, true); + $format->import_hints($question, $data, true, false, + $format->get_format($question->questiontextformat)); return $question; } diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index a6a2ab77c87..a8d72c62f01 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -77,7 +77,7 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere 'draghome', "dragitemhomes{$dragimage->no}", "choice{$choiceno}"); - if ($dragimage->isinfinite) { + if ($dragimage->infinite) { $classes[] = 'infinite'; } if ($dragimageurl === null) { From 9a94582b0a1500ddbd5d5e3ae6ca0faf585c8765 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 31 Jan 2012 16:15:31 +0700 Subject: [PATCH 150/208] MDL-47494 ddimageortext: NOBUG requires the gapselect question type to be installed --- question/type/ddimageortext/questiontypebase.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index f3e60ecb285..8a68421126e 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -42,6 +42,10 @@ class qtype_ddtoimage_base extends question_type { return 'draggroup'; } + public function requires_qtypes() { + return array('gapselect'); + } + public function get_question_options($question) { global $DB; $dbprefix = 'qtype_'.$this->name(); From 1f92921f6fb8d9239ed3da0b498508d0eb933604 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 31 Jan 2012 16:59:04 +0700 Subject: [PATCH 151/208] MDL-47494 ddimageortext: NOBUG change in dependency code in qtypes --- question/type/ddimageortext/version.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index b7b745f3367..fcef8367e27 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -27,3 +27,6 @@ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2011051200; $plugin->requires = 2011051212; +$plugin->dependencies = array( + 'qtype_gapselect' => 2011020100, +); \ No newline at end of file From 77328c4143f29c740628a6e38e78939254be2c11 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 31 Jan 2012 18:00:04 +0700 Subject: [PATCH 152/208] MDL-47494 ddimageortext: NOBUG change to string identifiers --- .../ddimageortext/lang/en/qtype_ddimageortext.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index d7e9948adc6..fb2a650f9a9 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -22,15 +22,11 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['addingddimageortext'] = 'Adding drag and drop onto image'; $string['addmoredropzones'] = 'Blanks for {no} more drop zones'; $string['addmoreimages'] = 'Blanks for {no} more draggable items'; $string['answer'] = 'Answer'; $string['bgimage'] = 'Background image'; $string['correctansweris'] = 'The correct answer is: {$a}'; -$string['ddimageortext'] = 'Drag and drop onto image'; -$string['ddimageortext_help'] = 'Select a background image file, select draggable images or enter text and define the drop zones on the background image to which they must be dragged.'; -$string['ddimageortextsummary'] = 'Images or text labels are dragged and dropped into drop zones on a background image.'; $string['draggableimage'] = 'Draggable image'; $string['draggableitem'] = 'Draggable item'; $string['draggableitemheader'] = 'Draggable item {$a}'; @@ -38,7 +34,6 @@ $string['draggableitemtype'] = 'Type'; $string['draggableword'] = 'Draggable text'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; -$string['editingddimageortext'] = 'Editing drag and drop onto image'; $string['formerror_disallowedtags'] = 'You have used html tags here that are not allowed in a draggable text drag item type.'; $string['formerror_noallowedtags'] = 'No html tags are allowed in this text which is the alt text for a draggable image'; $string['formerror_noytop'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; @@ -53,6 +48,12 @@ $string['infinite'] = 'Infinite'; $string['label'] = 'Text'; $string['nolabel'] = 'No label text'; $string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, please drag an item to each drop region.'; +$string['pluginname'] = 'Drag and drop onto image'; +$string['pluginname_help'] = 'Select a background image file, select draggable images or enter text and define the drop zones on the background image to which they must be dragged.'; +$string['pluginname_link'] = 'question/type/ddimageortext'; +$string['pluginnameadding'] = 'Adding drag and drop onto image'; +$string['pluginnameediting'] = 'Editing drag and drop onto image'; +$string['pluginnamesummary'] = 'Images or text labels are dragged and dropped into drop zones on a background image.'; $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; From 5cf31e57d581b5d4e603cf145b75426a3f6b9f49 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 5 Feb 2012 12:10:13 +0700 Subject: [PATCH 153/208] MDL-47494 ddimageortext: NOBUG updating installations instruction with moodleou repo url --- question/type/ddimageortext/README.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index e3c0250c587..8f649573aef 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -2,7 +2,7 @@ A drag-and-drop question type. You can use text and / or images as drag items onto defined drop zones on a background image. This question type requires that gapselect question type -https://github.com/timhunt/moodle-qtype_gapselect/ +https://github.com/moodleou/moodle-qtype_gapselect/ to be installed in order to work. This question type was written by Jamie Pratt (http://jamiep.org/). @@ -12,16 +12,16 @@ This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or 2 To install using git for a 2.2+ Moodle installation, type this command in the root of your Moodle install : -git clone git://github.com/jamiepratt/moodle-qtype_ddimageortext.git question/type/ddimageortext +git clone git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext To install using git for a 2.1+ Moodle installation, type this command in the root of your Moodle install : -git clone -b MOODLE_21_STABLE git://github.com/jamiepratt/moodle-qtype_ddimageortext.git question/type/ddimageortext +git clone -b MOODLE_21_STABLE git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext Then add question/type/ddimageortext to your git ignore. Alternatively, download the zip from - Moodle 2.2+ - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/master - Moodle 2.1+ - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/MOODLE_21_STABLE + Moodle 2.2+ - https://github.com/moodleou/moodle-qtype_ddimageortext/zipball/master + Moodle 2.1+ - https://github.com/moodleou/moodle-qtype_ddimageortext/zipball/MOODLE_21_STABLE unzip it into the question/type folder, and then rename the new folder to ddimageortext. From a9975ec07444942895324e2b397d541264ec5c7d Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 5 Feb 2012 12:10:13 +0700 Subject: [PATCH 154/208] MDL-47494 ddimageortext: NOBUG updating installations instruction with moodleou repo url --- question/type/ddimageortext/README.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index e3c0250c587..8f649573aef 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -2,7 +2,7 @@ A drag-and-drop question type. You can use text and / or images as drag items onto defined drop zones on a background image. This question type requires that gapselect question type -https://github.com/timhunt/moodle-qtype_gapselect/ +https://github.com/moodleou/moodle-qtype_gapselect/ to be installed in order to work. This question type was written by Jamie Pratt (http://jamiep.org/). @@ -12,16 +12,16 @@ This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or 2 To install using git for a 2.2+ Moodle installation, type this command in the root of your Moodle install : -git clone git://github.com/jamiepratt/moodle-qtype_ddimageortext.git question/type/ddimageortext +git clone git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext To install using git for a 2.1+ Moodle installation, type this command in the root of your Moodle install : -git clone -b MOODLE_21_STABLE git://github.com/jamiepratt/moodle-qtype_ddimageortext.git question/type/ddimageortext +git clone -b MOODLE_21_STABLE git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext Then add question/type/ddimageortext to your git ignore. Alternatively, download the zip from - Moodle 2.2+ - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/master - Moodle 2.1+ - https://github.com/jamiepratt/moodle-qtype_ddimageortext/zipball/MOODLE_21_STABLE + Moodle 2.2+ - https://github.com/moodleou/moodle-qtype_ddimageortext/zipball/master + Moodle 2.1+ - https://github.com/moodleou/moodle-qtype_ddimageortext/zipball/MOODLE_21_STABLE unzip it into the question/type folder, and then rename the new folder to ddimageortext. From 5f924369ce0619a8921a3cccd40b529ebede3894 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 5 Feb 2012 18:37:33 +0700 Subject: [PATCH 155/208] MDL-47494 ddimageortext: NOBUG adding an alt tag to drag and drop background image --- question/type/ddimageortext/lang/en/qtype_ddimageortext.php | 1 + question/type/ddimageortext/rendererbase.php | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index fb2a650f9a9..7f36f90f7e0 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -32,6 +32,7 @@ $string['draggableitem'] = 'Draggable item'; $string['draggableitemheader'] = 'Draggable item {$a}'; $string['draggableitemtype'] = 'Type'; $string['draggableword'] = 'Draggable text'; +$string['dropbackground'] = 'Background image for dragging markers onto'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; $string['formerror_disallowedtags'] = 'You have used html tags here that are not allowed in a draggable text drag item type.'; diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index a8d72c62f01..9e52e5d0a33 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -64,7 +64,11 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere $bgimage = self::get_url_for_image($qa, 'bgimage'); - $img = html_writer::empty_tag('img', array('src'=>$bgimage, 'class'=>'dropbackground')); + $img = html_writer::empty_tag('img', + array('src'=>$bgimage, + 'class'=>'dropbackground', + 'alt' => get_string('dropbackground', 'qtype_ddimageortext'))); + $droparea = html_writer::tag('div', $img, array('class'=>'droparea')); $dragimagehomes = ''; From 81b0d1a70fc8938b631fdbd316cb519712a5acd4 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 5 Feb 2012 18:37:33 +0700 Subject: [PATCH 156/208] MDL-47494 ddimageortext: NOBUG adding an alt tag to drag and drop background image --- question/type/ddimageortext/lang/en/qtype_ddimageortext.php | 1 + question/type/ddimageortext/rendererbase.php | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index d7e9948adc6..aab070161f7 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -36,6 +36,7 @@ $string['draggableitem'] = 'Draggable item'; $string['draggableitemheader'] = 'Draggable item {$a}'; $string['draggableitemtype'] = 'Type'; $string['draggableword'] = 'Draggable text'; +$string['dropbackground'] = 'Background image for dragging markers onto'; $string['dropzone'] = 'Drop zone {$a}'; $string['dropzoneheader'] = 'Drop zones'; $string['editingddimageortext'] = 'Editing drag and drop onto image'; diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index a8d72c62f01..9e52e5d0a33 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -64,7 +64,11 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere $bgimage = self::get_url_for_image($qa, 'bgimage'); - $img = html_writer::empty_tag('img', array('src'=>$bgimage, 'class'=>'dropbackground')); + $img = html_writer::empty_tag('img', + array('src'=>$bgimage, + 'class'=>'dropbackground', + 'alt' => get_string('dropbackground', 'qtype_ddimageortext'))); + $droparea = html_writer::tag('div', $img, array('class'=>'droparea')); $dragimagehomes = ''; From c109c9012e3e368982367d3490eaca732ce976a2 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 10 Feb 2012 15:52:42 +0000 Subject: [PATCH 157/208] MDL-47494 ddimageortext: Fix version.php, and wrong qtype name in comments. --- question/type/ddimageortext/README.txt | 17 ++++++++++------- .../lang/en/qtype_ddimageortext.php | 1 + question/type/ddimageortext/question.php | 7 +++---- question/type/ddimageortext/questionbase.php | 7 +++---- question/type/ddimageortext/questiontype.php | 7 +++---- .../type/ddimageortext/questiontypebase.php | 7 +++---- question/type/ddimageortext/renderer.php | 7 +++---- question/type/ddimageortext/rendererbase.php | 7 +++---- .../type/ddimageortext/simpletest/helper.php | 11 +++++------ .../ddimageortext/simpletest/testquestion.php | 5 ++--- .../simpletest/testquestiontype.php | 7 +++---- .../simpletest/testwalkthrough.php | 7 +++---- question/type/ddimageortext/version.php | 13 ++++++++----- 13 files changed, 50 insertions(+), 53 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index 8f649573aef..8f83649867b 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -1,5 +1,7 @@ A drag-and-drop question type. -You can use text and / or images as drag items onto defined drop zones on a background image. + +You can use text and / or images as drag items onto defined drop zones on a +background image. This question type requires that gapselect question type https://github.com/moodleou/moodle-qtype_gapselect/ @@ -7,17 +9,18 @@ to be installed in order to work. This question type was written by Jamie Pratt (http://jamiep.org/). -This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or 2.2+ (master branch). +This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or +2.2+ (master branch). -To install using git for a 2.2+ Moodle installation, type this command in the root of your Moodle -install : +To install using git for a 2.2+ Moodle installation, type this command in the +root of your Moodle install: git clone git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext -To install using git for a 2.1+ Moodle installation, type this command in the root of your Moodle -install : +To install using git for a 2.1+ Moodle installation, type this command in the +root of your Moodle install: -git clone -b MOODLE_21_STABLE git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext +git clone -b MOODLE_21_STABLE git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext Then add question/type/ddimageortext to your git ignore. diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index aab070161f7..fec8c3d0414 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -54,6 +54,7 @@ $string['infinite'] = 'Infinite'; $string['label'] = 'Text'; $string['nolabel'] = 'No label text'; $string['pleasedraganimagetoeachdropregion'] = 'Your answer is not complete, please drag an item to each drop region.'; +$string['pluginname'] = 'Drag and drop onto image'; $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; diff --git a/question/type/ddimageortext/question.php b/question/type/ddimageortext/question.php index 84d57f03c27..91162b1203c 100644 --- a/question/type/ddimageortext/question.php +++ b/question/type/ddimageortext/question.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Drag-and-drop words into sentences question definition class. + * Drag-and-drop onto image question definition class. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -30,7 +29,7 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/questionbase.php'); /** - * Represents a drag-and-drop images to image question. + * Represents a drag-and-drop onto image question. * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ddimageortext/questionbase.php b/question/type/ddimageortext/questionbase.php index 4ad33327f25..6c75098985c 100644 --- a/question/type/ddimageortext/questionbase.php +++ b/question/type/ddimageortext/questionbase.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Drag-and-drop words into sentences question definition class. + * Drag-and-drop onto image question definition class. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -30,7 +29,7 @@ require_once($CFG->dirroot . '/question/type/gapselect/questionbase.php'); /** - * Represents a drag-and-drop images to image question. + * Represents a drag-and-drop onto image question. * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 771a71a3a68..2a4f7e226bf 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Question type class for the drag-and-drop images onto images question type. + * Question type class for the drag-and-drop onto image question type. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -34,7 +33,7 @@ define('QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH', 150); define('QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT', 100); /** - * The drag-and-drop words into sentences question type class. + * The drag-and-drop onto image question type class. * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index 8a68421126e..2eedfa4fef2 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Question type class for the drag-and-drop images onto images question type. + * Question type class for the drag-and-drop onto image question type. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -32,7 +31,7 @@ require_once($CFG->dirroot . '/question/format/xml/format.php'); require_once($CFG->dirroot . '/question/type/gapselect/questiontypebase.php'); /** - * The drag-and-drop words into sentences question type class. + * The drag-and-drop onto image question type class. * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ddimageortext/renderer.php b/question/type/ddimageortext/renderer.php index 335fd99c881..dde1f262fe3 100644 --- a/question/type/ddimageortext/renderer.php +++ b/question/type/ddimageortext/renderer.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Drag-and-drop words into sentences question renderer class. + * Drag-and-drop onto image question renderer class. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -29,7 +28,7 @@ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/question/type/ddimageortext/rendererbase.php'); /** - * Generates the output for drag-and-drop words into sentences questions. + * Generates the output for drag-and-drop onto image questions. * * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index 9e52e5d0a33..e1bef6adead 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Drag-and-drop words into sentences question renderer class. + * Drag-and-drop onto image question renderer class. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); /** - * Generates the output for drag-and-drop words into sentences questions. + * Generates the output for drag-and-drop onto image questions. * * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/simpletest/helper.php index 9fd9961dde6..2068f614b78 100644 --- a/question/type/ddimageortext/simpletest/helper.php +++ b/question/type/ddimageortext/simpletest/helper.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Test helpers for the drag-and-drop words into sentences question type. + * Test helpers for the drag-and-drop onto image question type. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -28,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); /** - * Test helper class for the drag-and-drop words into sentences question type. + * Test helper class for the drag-and-drop onto image question type. * * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -47,7 +46,7 @@ class qtype_ddimageortext_test_helper extends question_test_helper { test_question_maker::initialise_a_question($dd); - $dd->name = 'Drag-and-drop words into sentences question'; + $dd->name = 'Drag-and-drop onto image question'; $dd->questiontext = 'The quick brown fox jumped over the lazy dog.'; $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; $dd->qtype = question_bank::get_qtype('ddimageortext'); @@ -103,7 +102,7 @@ class qtype_ddimageortext_test_helper extends question_test_helper { test_question_maker::initialise_a_question($dd); - $dd->name = 'Drag-and-drop words into sentences question'; + $dd->name = 'Drag-and-drop onto image question'; $dd->questiontext = 'Fill in the operators to make this equation work: ' . '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3'; $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/simpletest/testquestion.php index e0c231138c0..df6628b3e7b 100644 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/simpletest/testquestion.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Unit tests for the drag-and-drop words into sentences question definition class. + * Unit tests for the drag-and-drop onto image question definition class. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/simpletest/testquestiontype.php index 9f2e1e853b0..38264429ff6 100644 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/simpletest/testquestiontype.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Unit tests for the drag-and-drop words into sentences question definition class. + * Unit tests for the drag-and-drop onto image question definition class. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -31,7 +30,7 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php /** - * Unit tests for the drag-and-drop words into sentences question definition class. + * Unit tests for the drag-and-drop onto image question definition class. * * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php index 179a18fb0d4..d16e2a72fc4 100644 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ b/question/type/ddimageortext/simpletest/testwalkthrough.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Unit tests for the drag-and-drop words into sentences question type. + * Unit tests for the drag-and-drop onto image question type. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -31,7 +30,7 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php /** - * Unit tests for the drag-and-drop words into sentences question type. + * Unit tests for the drag-and-drop onto image question type. * * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index b7b745f3367..cab72e3b3fc 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -15,15 +15,18 @@ // along with Moodle. If not, see . /** - * Version information for the drag-and-drop words into sentences question type. + * Version information for the drag-and-drop onto image question type. * - * @package qtype - * @subpackage ddimageortext + * @package qtype_ddimageortext * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2011051200; -$plugin->requires = 2011051212; +$plugin->version = 2011051200; +$plugin->requires = 2011070100; // See http://docs.moodle.org/dev/Moodle_Versions +$plugin->cron = 0; +$plugin->component = 'qtype_ddimageortext'; +$plugin->maturity = MATURITY_STABLE; +$plugin->release = '1.0'; From daac3bb85ee637b8298bb8a0d4e11e5fde9b5c0f Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 30 Mar 2012 10:29:30 +0100 Subject: [PATCH 158/208] MDL-47494 ddimageortext: Files in hints were not moved or deleted properly for OU qtypes. #3478 --- question/type/ddimageortext/questiontype.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 2a4f7e226bf..0d855c638bd 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -157,6 +157,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { } $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); + $this->move_files_in_hints($questionid, $oldcontextid, $newcontextid); } /** @@ -178,6 +179,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { } $this->delete_files_in_combined_feedback($questionid, $contextid); + $this->delete_files_in_hints($questionid, $contextid); } From 81d1cac12b7532bc6c2330a71cffce2877f68966 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 5 Apr 2012 13:33:57 +0100 Subject: [PATCH 159/208] MDL-47494 ddimageortext: Fix PHP strict errors. --- question/type/ddimageortext/questiontype.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 0d855c638bd..787530fa3f0 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -183,7 +183,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { } - public function export_to_xml($question, $format, $extra = null) { + public function export_to_xml($question, qformat_xml $format, $extra = null) { $fs = get_file_storage(); $contextid = $question->contextid; $output = ''; @@ -223,7 +223,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { return $output; } - public function import_from_xml($data, $question, $format, $extra=null) { + public function import_from_xml($data, $question, qformat_xml $format, $extra=null) { if (!isset($data['@']['type']) || $data['@']['type'] != 'ddimageortext') { return false; } From c7b2d1fbd9d033c3e0c88ce958ea563a7a4c9cc5 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 16 Jun 2012 12:42:52 +0700 Subject: [PATCH 160/208] MDL-47494 ddimageortext: NOBUG changed unit tests to use PHPUnit --- .../simpletest/testwalkthrough.php | 856 ----------------- .../{simpletest => tests}/helper.php | 0 .../question_test.php} | 172 ++-- .../questiontype_test.php} | 14 +- .../ddimageortext/tests/walkthrough_test.php | 858 ++++++++++++++++++ 5 files changed, 953 insertions(+), 947 deletions(-) delete mode 100644 question/type/ddimageortext/simpletest/testwalkthrough.php rename question/type/ddimageortext/{simpletest => tests}/helper.php (100%) rename question/type/ddimageortext/{simpletest/testquestion.php => tests/question_test.php} (53%) rename question/type/ddimageortext/{simpletest/testquestiontype.php => tests/questiontype_test.php} (79%) create mode 100644 question/type/ddimageortext/tests/walkthrough_test.php diff --git a/question/type/ddimageortext/simpletest/testwalkthrough.php b/question/type/ddimageortext/simpletest/testwalkthrough.php deleted file mode 100644 index d16e2a72fc4..00000000000 --- a/question/type/ddimageortext/simpletest/testwalkthrough.php +++ /dev/null @@ -1,856 +0,0 @@ -. - -/** - * Unit tests for the drag-and-drop onto image question type. - * - * @package qtype_ddimageortext - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); -require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php'); - - -/** - * Unit tests for the drag-and-drop onto image question type. - * - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_base { - - protected function get_contains_drag_image_home_expectation($dragitemno, $choice, $group) { - $class = 'group' . $group; - $class .= ' draghome dragitemhomes' . $dragitemno. ' choice'.$choice.' yui3-cssfonts'; - - $expectedattrs = array(); - $expectedattrs['class'] = $class; - - return new ContainsTagWithAttributes('div', $expectedattrs); - } - - public function test_interactive_behaviour() { - - // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimageortext'); - $dd->hints = array( - new question_hint_with_parts(13, 'This is the first hint.', FORMAT_HTML, false, false), - new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true), - ); - $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'interactive', 12); - - // Check the initial state. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4'), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(3), - $this->get_no_hint_visible_expectation()); - - // Save the wrong answer. - $this->process_submission(array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1')); - // Verify. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', 1), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(3), - $this->get_no_hint_visible_expectation()); - // Submit the wrong answer. - $this->process_submission( - array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1', '-submit' => 1)); - - // Verify. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', 1), - $this->get_contains_try_again_button_expectation(true), - new PatternExpectation('/' . - preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), - $this->get_contains_hint_expectation('This is the first hint')); - - // Do try again. - $this->process_submission(array('-tryagain' => 1)); - - // Verify. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', '1'), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(2), - $this->get_no_hint_visible_expectation()); - - // Submit the right answer. - $this->process_submission( - array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1)); - - // Verify. - $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(8); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', '1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', '2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', '1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', '2'), - $this->get_contains_submit_button_expectation(false), - $this->get_contains_correct_expectation(), - $this->get_no_hint_visible_expectation()); - - // Check regrading does not mess anything up. - $this->quba->regrade_all_questions(); - - // Verify. - $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(8); - } - - public function test_deferred_feedback() { - - // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimageortext'); - $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'deferredfeedback', 12); - - // Check the initial state. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4'), - $this->get_does_not_contain_feedback_expectation()); - - // Save a partial answer. - $this->process_submission(array('p1' => '2', 'p2' => '1')); - // Verify. - $this->check_current_state(question_state::$invalid); - $this->check_current_mark(null); - - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', ''), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation()); - // Save the right answer. - $this->process_submission( - array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')); - - // Verify. - $this->check_current_state(question_state::$complete); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', 2), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation()); - - // Finish the attempt. - $this->quba->finish_all_questions(); - - // Verify. - $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(12); - - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', 2), - $this->get_contains_correct_expectation()); - - // Change the right answer a bit. - $dd->rightchoices[2] = 1; - - // Check regrading does not mess anything up. - $this->quba->regrade_all_questions(); - - // Verify. - $this->check_current_state(question_state::$gradedpartial); - $this->check_current_mark(9); - } - - public function test_deferred_feedback_unanswered() { - - // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimageortext'); - $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'deferredfeedback', 12); - - // Check the initial state. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4'), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation()); - $this->check_step_count(1); - - // Save a blank response. - $this->process_submission(array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => '')); - - // Verify. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', ''), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation()); - $this->check_step_count(1); - - // Finish the attempt. - $this->quba->finish_all_questions(); - - // Verify. - $this->check_current_state(question_state::$gaveup); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2)); - } - - public function test_deferred_feedback_partial_answer() { - - // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimageortext'); - $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'deferredfeedback', 3); - - // Check the initial state. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4'), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation()); - - // Save a partial response. - $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => '')); - - // Verify. - $this->check_current_state(question_state::$invalid); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', ''), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation()); - - // Finish the attempt. - $this->quba->finish_all_questions(); - - // Verify. - $this->check_current_state(question_state::$gradedpartial); - $this->check_current_mark(1.5); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_partcorrect_expectation()); - } - - public function test_interactive_grading() { - - // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimageortext'); - $dd->hints = array( - new question_hint_with_parts(1, 'This is the first hint.', - FORMAT_MOODLE, true, true), - new question_hint_with_parts(2, 'This is the second hint.', - FORMAT_MOODLE, true, true), - ); - $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'interactive', 12); - - // Check the initial state. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->assertEqual('interactivecountback', - $this->quba->get_question_attempt($this->slot)->get_behaviour_name()); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4'), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(3), - $this->get_does_not_contain_num_parts_correct(), - $this->get_no_hint_visible_expectation()); - - // Submit an response with the first two parts right. - $this->process_submission( - array('p1' => '1', 'p2' => '2', 'p3' => '2', 'p4' => '1', '-submit' => 1)); - - // Verify. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_submit_button_expectation(false), - $this->get_contains_try_again_button_expectation(true), - $this->get_does_not_contain_correctness_expectation(), - new PatternExpectation('/' . - preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), - $this->get_contains_hint_expectation('This is the first hint'), - $this->get_contains_num_parts_correct(2), - $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', 1)); - - // Check that extract responses will return the reset data. - $prefix = $this->quba->get_field_prefix($this->slot); - $this->assertEqual(array('p1' => '1', 'p2' => '2'), - $this->quba->extract_responses($this->slot, - array($prefix . 'p1' => '1', $prefix . 'p2' => '2', '-tryagain' => 1))); - - // Do try again. - // keys p3 and p4 are extra hidden fields to clear data. - $this->process_submission( - array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => '', '-tryagain' => 1)); - - // Verify. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', ''), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_try_again_button_expectation(), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(2), - $this->get_no_hint_visible_expectation()); - - // Submit an response with the first and last parts right. - $this->process_submission( - array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '2', '-submit' => 1)); - - // Verify. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_submit_button_expectation(false), - $this->get_contains_try_again_button_expectation(true), - $this->get_does_not_contain_correctness_expectation(), - new PatternExpectation('/' . - preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), - $this->get_contains_hint_expectation('This is the second hint'), - $this->get_contains_num_parts_correct(2), - $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', 2)); - - // Do try again. - $this->process_submission( - array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => '2', '-tryagain' => 1)); - - // Verify. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', 2), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_try_again_button_expectation(), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(1), - $this->get_no_hint_visible_expectation()); - - // Submit the right answer. - $this->process_submission( - array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1)); - - // Verify. - $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(7); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', 1), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', 2), - $this->get_contains_submit_button_expectation(false), - $this->get_does_not_contain_try_again_button_expectation(), - $this->get_contains_correct_expectation(), - $this->get_no_hint_visible_expectation(), - $this->get_does_not_contain_num_parts_correct(), - $this->get_contains_standard_correct_combined_feedback_expectation()); - } - - public function test_interactive_correct_no_submit() { - - // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimageortext'); - $dd->hints = array( - new question_hint_with_parts(23, 'This is the first hint.', - FORMAT_MOODLE, false, false), - new question_hint_with_parts(24, 'This is the second hint.', - FORMAT_MOODLE, true, true), - ); - $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'interactive', 3); - - // Check the initial state. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4'), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(3), - $this->get_no_hint_visible_expectation()); - - // Save the right answer. - $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')); - - // Finish the attempt without clicking check. - $this->quba->finish_all_questions(); - - // Verify. - $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(3); - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_submit_button_expectation(false), - $this->get_contains_correct_expectation(), - $this->get_no_hint_visible_expectation()); - - // Check regrading does not mess anything up. - $this->quba->regrade_all_questions(); - - // Verify. - $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(3); - } - - public function test_interactive_partial_no_submit() { - - // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimageortext'); - $dd->hints = array( - new question_hint_with_parts(23, 'This is the first hint.', - FORMAT_MOODLE, false, false), - new question_hint_with_parts(24, 'This is the second hint.', - FORMAT_MOODLE, true, true), - ); - $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'interactive', 4); - - // Check the initial state. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4'), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(3), - $this->get_no_hint_visible_expectation()); - - // Save the a partially right answer. - $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '1')); - - // Finish the attempt without clicking check. - $this->quba->finish_all_questions(); - - // Verify. - $this->check_current_state(question_state::$gradedpartial); - $this->check_current_mark(1); - - $this->check_current_output( - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_submit_button_expectation(false), - $this->get_contains_partcorrect_expectation(), - $this->get_no_hint_visible_expectation()); - - // Check regrading does not mess anything up. - $this->quba->regrade_all_questions(); - - // Verify. - $this->check_current_state(question_state::$gradedpartial); - $this->check_current_mark(1); - } - - public function test_interactive_no_right_clears() { - - // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimageortext'); - $dd->hints = array( - new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, true), - new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), - ); - $dd->shufflechoices = false; - $this->start_attempt_at_question($dd, 'interactive', 3); - - // Check the initial state. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - - $this->check_current_output( - $this->get_contains_marked_out_of_summary(), - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4'), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(3), - $this->get_no_hint_visible_expectation()); - - // Save the a completely wrong answer. - $this->process_submission( - array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1', '-submit' => 1)); - - // Verify. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_marked_out_of_summary(), - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_submit_button_expectation(false), - $this->get_contains_hint_expectation('This is the first hint')); - - // Do try again. - $this->process_submission( - array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => '', '-tryagain' => 1)); - - // Check that all the wrong answers have been cleared. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_marked_out_of_summary(), - $this->get_contains_drag_image_home_expectation(1, 1, 1), - $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', ''), - $this->get_contains_submit_button_expectation(true), - $this->get_does_not_contain_feedback_expectation(), - $this->get_tries_remaining_expectation(2), - $this->get_no_hint_visible_expectation()); - } - - public function test_display_of_right_answer_when_shuffled() { - - // Create a drag-and-drop question. - $dd = test_question_maker::make_question('ddimageortext'); - $this->start_attempt_at_question($dd, 'deferredfeedback', 3); - - // Check the initial state. - $this->check_current_state(question_state::$todo); - $this->check_current_mark(null); - - $this->check_current_output( - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3'), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4'), - $this->get_does_not_contain_feedback_expectation()); - - // Save a partial answer. - $this->process_submission($dd->get_correct_response()); - - // Verify. - $this->check_current_state(question_state::$complete); - $this->check_current_mark(null); - $this->check_current_output( - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', - $dd->get_right_choice_for(1)), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', - $dd->get_right_choice_for(2)), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', - $dd->get_right_choice_for(3)), - $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', - $dd->get_right_choice_for(4)), - $this->get_does_not_contain_correctness_expectation(), - $this->get_does_not_contain_feedback_expectation()); - - // Finish the attempt. - $this->quba->finish_all_questions(); - - // Verify. - $this->displayoptions->rightanswer = question_display_options::VISIBLE; - $this->assertEqual('Drop zone 1 -> {1. quick} '. - 'Drop zone 2 -> {2. fox} '. - 'Drop zone 3 -> {1. lazy} '. - 'Drop zone 4 -> {2. dog}', - $dd->get_right_answer_summary()); - $this->check_current_state(question_state::$gradedright); - $this->check_current_mark(3); - } -} diff --git a/question/type/ddimageortext/simpletest/helper.php b/question/type/ddimageortext/tests/helper.php similarity index 100% rename from question/type/ddimageortext/simpletest/helper.php rename to question/type/ddimageortext/tests/helper.php diff --git a/question/type/ddimageortext/simpletest/testquestion.php b/question/type/ddimageortext/tests/question_test.php similarity index 53% rename from question/type/ddimageortext/simpletest/testquestion.php rename to question/type/ddimageortext/tests/question_test.php index df6628b3e7b..cc35d4cefe9 100644 --- a/question/type/ddimageortext/simpletest/testquestion.php +++ b/question/type/ddimageortext/tests/question_test.php @@ -25,8 +25,9 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); -require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php'); +global $CFG; +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); +require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php'); /** @@ -34,28 +35,29 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @group qtype_ddimageortext */ -class qtype_ddimageortext_question_test extends UnitTestCase { +class qtype_ddimageortext_question_test extends basic_testcase { public function test_get_question_summary() { $dd = test_question_maker::make_question('ddimageortext'); - $this->assertEqual('The quick brown fox jumped over the lazy dog.; '. - '[[Drop zone 1]] -> {1. quick / 2. fox}; '. - '[[Drop zone 2]] -> {1. quick / 2. fox}; '. - '[[Drop zone 3]] -> {1. lazy / 2. dog}; '. - '[[Drop zone 4]] -> {1. lazy / 2. dog}', - $dd->get_question_summary()); + $this->assertEquals('The quick brown fox jumped over the lazy dog.; '. + '[[Drop zone 1]] -> {1. quick / 2. fox}; '. + '[[Drop zone 2]] -> {1. quick / 2. fox}; '. + '[[Drop zone 3]] -> {1. lazy / 2. dog}; '. + '[[Drop zone 4]] -> {1. lazy / 2. dog}', + $dd->get_question_summary()); } public function test_get_question_summary_maths() { $dd = test_question_maker::make_question('ddimageortext', 'maths'); - $this->assertEqual('Fill in the operators to make this equation work: '. - '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3; '. - '[[Drop zone 1]] -> {1. + / 2. -}; '. - '[[Drop zone 2]] -> {1. + / 2. -}; '. - '[[Drop zone 3]] -> {1. + / 2. -}; '. - '[[Drop zone 4]] -> {1. + / 2. -}', - $dd->get_question_summary()); + $this->assertEquals('Fill in the operators to make this equation work: '. + '7 [[1]] 11 [[2]] 13 [[1]] 17 [[2]] 19 = 3; '. + '[[Drop zone 1]] -> {1. + / 2. -}; '. + '[[Drop zone 2]] -> {1. + / 2. -}; '. + '[[Drop zone 3]] -> {1. + / 2. -}; '. + '[[Drop zone 4]] -> {1. + / 2. -}', + $dd->get_question_summary()); } public function test_summarise_response() { @@ -63,11 +65,11 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual('Drop zone 1 -> {1. quick} '. - 'Drop zone 2 -> {1. quick} '. - 'Drop zone 3 -> {1. lazy} '. - 'Drop zone 4 -> {1. lazy}', - $dd->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); + $this->assertEquals('Drop zone 1 -> {1. quick} '. + 'Drop zone 2 -> {1. quick} '. + 'Drop zone 3 -> {1. lazy} '. + 'Drop zone 4 -> {1. lazy}', + $dd->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); } public function test_summarise_response_maths() { @@ -75,21 +77,21 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual('Drop zone 1 -> {1. +} '. - 'Drop zone 2 -> {2. -} '. - 'Drop zone 3 -> {1. +} '. - 'Drop zone 4 -> {2. -}', - $dd->summarise_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); + $this->assertEquals('Drop zone 1 -> {1. +} '. + 'Drop zone 2 -> {2. -} '. + 'Drop zone 3 -> {1. +} '. + 'Drop zone 4 -> {2. -}', + $dd->summarise_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); } public function test_get_random_guess_score() { $dd = test_question_maker::make_question('ddimageortext'); - $this->assertEqual(0.5, $dd->get_random_guess_score()); + $this->assertEquals(0.5, $dd->get_random_guess_score()); } public function test_get_random_guess_score_maths() { $dd = test_question_maker::make_question('ddimageortext', 'maths'); - $this->assertEqual(0.5, $dd->get_random_guess_score()); + $this->assertEquals(0.5, $dd->get_random_guess_score()); } public function test_get_right_choice_for() { @@ -97,8 +99,8 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(1, $dd->get_right_choice_for(1)); - $this->assertEqual(2, $dd->get_right_choice_for(2)); + $this->assertEquals(1, $dd->get_right_choice_for(1)); + $this->assertEquals(2, $dd->get_right_choice_for(2)); } public function test_get_right_choice_for_maths() { @@ -106,10 +108,10 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(1, $dd->get_right_choice_for(1)); - $this->assertEqual(2, $dd->get_right_choice_for(2)); - $this->assertEqual(1, $dd->get_right_choice_for(3)); - $this->assertEqual(2, $dd->get_right_choice_for(4)); + $this->assertEquals(1, $dd->get_right_choice_for(1)); + $this->assertEquals(2, $dd->get_right_choice_for(2)); + $this->assertEquals(1, $dd->get_right_choice_for(3)); + $this->assertEquals(2, $dd->get_right_choice_for(4)); } public function test_clear_wrong_from_response() { @@ -118,8 +120,8 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->start_attempt(new question_attempt_step(), 1); $initialresponse = array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'); - $this->assertEqual(array('p1' => '1', 'p2' => '', 'p3' => '1', 'p4' => ''), - $dd->clear_wrong_from_response($initialresponse)); + $this->assertEquals(array('p1' => '1', 'p2' => '', 'p3' => '1', 'p4' => ''), + $dd->clear_wrong_from_response($initialresponse)); } public function test_get_num_parts_right() { @@ -127,9 +129,9 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array(2, 4), + $this->assertEquals(array(2, 4), $dd->get_num_parts_right(array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '2'))); - $this->assertEqual(array(4, 4), + $this->assertEquals(array(4, 4), $dd->get_num_parts_right(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); } @@ -138,16 +140,16 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array(2, 4), - $dd->get_num_parts_right(array( - 'p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); + $this->assertEquals(array(2, 4), + $dd->get_num_parts_right(array( + 'p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); } public function test_get_expected_data() { $dd = test_question_maker::make_question('ddimageortext'); $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual( + $this->assertEquals( array('p1' => PARAM_INT, 'p2' => PARAM_INT, 'p3' => PARAM_INT, 'p4' => PARAM_INT), $dd->get_expected_data() ); @@ -158,8 +160,8 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'), - $dd->get_correct_response()); + $this->assertEquals(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'), + $dd->get_correct_response()); } public function test_get_correct_response_maths() { @@ -167,8 +169,8 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'), - $dd->get_correct_response()); + $this->assertEquals(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'), + $dd->get_correct_response()); } public function test_is_same_response() { @@ -176,24 +178,24 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->start_attempt(new question_attempt_step(), 1); $this->assertTrue($dd->is_same_response( - array(), - array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => ''))); + array(), + array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => ''))); $this->assertFalse($dd->is_same_response( - array(), - array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => ''))); + array(), + array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => ''))); $this->assertFalse($dd->is_same_response( - array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => ''), - array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => ''))); + array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => ''), + array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => ''))); $this->assertTrue($dd->is_same_response( - array('p1' => '1', 'p2' => '2', 'p3' => '3', 'p4' => '4'), - array('p1' => '1', 'p2' => '2', 'p3' => '3', 'p4' => '4'))); + array('p1' => '1', 'p2' => '2', 'p3' => '3', 'p4' => '4'), + array('p1' => '1', 'p2' => '2', 'p3' => '3', 'p4' => '4'))); $this->assertFalse($dd->is_same_response( - array('p1' => '1', 'p2' => '2', 'p3' => '3', 'p4' => '4'), - array('p1' => '1', 'p2' => '2', 'p3' => '2', 'p4' => '4'))); + array('p1' => '1', 'p2' => '2', 'p3' => '3', 'p4' => '4'), + array('p1' => '1', 'p2' => '2', 'p3' => '2', 'p4' => '4'))); } public function test_is_complete_response() { $dd = test_question_maker::make_question('ddimageortext'); @@ -201,10 +203,10 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $this->assertFalse($dd->is_complete_response(array())); $this->assertFalse($dd->is_complete_response( - array('p1' => '1', 'p2' => '1', 'p3' => '', 'p4' => ''))); + array('p1' => '1', 'p2' => '1', 'p3' => '', 'p4' => ''))); $this->assertFalse($dd->is_complete_response(array('p1' => '1'))); $this->assertTrue($dd->is_complete_response( - array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); + array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); } public function test_is_gradable_response() { @@ -213,12 +215,12 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $this->assertFalse($dd->is_gradable_response(array())); $this->assertFalse($dd->is_gradable_response( - array('p1' => '', 'p2' => '', 'p3' => '', 'p3' => ''))); + array('p1' => '', 'p2' => '', 'p3' => '', 'p3' => ''))); $this->assertTrue($dd->is_gradable_response( - array('p1' => '1', 'p2' => '1', 'p3' => ''))); + array('p1' => '1', 'p2' => '1', 'p3' => ''))); $this->assertTrue($dd->is_gradable_response(array('p1' => '1'))); $this->assertTrue($dd->is_gradable_response( - array('p1' => '1', 'p2' => '1', 'p3' => '1'))); + array('p1' => '1', 'p2' => '1', 'p3' => '1'))); } public function test_grading() { @@ -226,12 +228,12 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array(1, question_state::$gradedright), - $dd->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); - $this->assertEqual(array(0.25, question_state::$gradedpartial), - $dd->grade_response(array('p1' => '1'))); - $this->assertEqual(array(0, question_state::$gradedwrong), - $dd->grade_response(array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1'))); + $this->assertEquals(array(1, question_state::$gradedright), + $dd->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); + $this->assertEquals(array(0.25, question_state::$gradedpartial), + $dd->grade_response(array('p1' => '1'))); + $this->assertEquals(array(0, question_state::$gradedwrong), + $dd->grade_response(array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1'))); } public function test_grading_maths() { @@ -239,12 +241,12 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array(1, question_state::$gradedright), - $dd->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); - $this->assertEqual(array(0.5, question_state::$gradedpartial), - $dd->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); - $this->assertEqual(array(0, question_state::$gradedwrong), - $dd->grade_response(array('p1' => '', 'p2' => '1', 'p3' => '2', 'p4' => '1'))); + $this->assertEquals(array(1, question_state::$gradedright), + $dd->grade_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); + $this->assertEquals(array(0.5, question_state::$gradedpartial), + $dd->grade_response(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); + $this->assertEquals(array(0, question_state::$gradedwrong), + $dd->grade_response(array('p1' => '', 'p2' => '1', 'p3' => '2', 'p4' => '1'))); } public function test_classify_response() { @@ -252,17 +254,17 @@ class qtype_ddimageortext_question_test extends UnitTestCase { $dd->shufflechoices = false; $dd->start_attempt(new question_attempt_step(), 1); - $this->assertEqual(array( - 1 => new question_classified_response(1, '1. quick', 1), - 2 => new question_classified_response(2, '2. fox', 1), - 3 => new question_classified_response(1, '1. lazy', 1), - 4 => new question_classified_response(2, '2. dog', 1) - ), $dd->classify_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); - $this->assertEqual(array( - 1 => question_classified_response::no_response(), - 2 => new question_classified_response(1, '1. quick', 0), - 3 => new question_classified_response(2, '2. dog', 0), - 4 => new question_classified_response(2, '2. dog', 1) - ), $dd->classify_response(array('p1' => '', 'p2' => '1', 'p3' => '2', 'p4' => '2'))); + $this->assertEquals(array( + 1 => new question_classified_response(1, '1. quick', 1), + 2 => new question_classified_response(2, '2. fox', 1), + 3 => new question_classified_response(1, '1. lazy', 1), + 4 => new question_classified_response(2, '2. dog', 1) + ), $dd->classify_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); + $this->assertEquals(array( + 1 => question_classified_response::no_response(), + 2 => new question_classified_response(1, '1. quick', 0), + 3 => new question_classified_response(2, '2. dog', 0), + 4 => new question_classified_response(2, '2. dog', 1) + ), $dd->classify_response(array('p1' => '', 'p2' => '1', 'p3' => '2', 'p4' => '2'))); } } diff --git a/question/type/ddimageortext/simpletest/testquestiontype.php b/question/type/ddimageortext/tests/questiontype_test.php similarity index 79% rename from question/type/ddimageortext/simpletest/testquestiontype.php rename to question/type/ddimageortext/tests/questiontype_test.php index 38264429ff6..41132a26163 100644 --- a/question/type/ddimageortext/simpletest/testquestiontype.php +++ b/question/type/ddimageortext/tests/questiontype_test.php @@ -25,8 +25,9 @@ defined('MOODLE_INTERNAL') || die(); -require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php'); -require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php'); +global $CFG; +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); +require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php'); /** @@ -34,21 +35,22 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/simpletest/helper.php * * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @group qtype_ddimageortext */ -class qtype_ddimageortext_test extends UnitTestCase { +class qtype_ddimageortext_test extends basic_testcase { /** @var qtype_ddimageortext instance of the question type class to test. */ protected $qtype; - public function setUp() { + protected function setUp() { $this->qtype = question_bank::get_qtype('ddimageortext');; } - public function tearDown() { + protected function tearDown() { $this->qtype = null; } public function test_name() { - $this->assertEqual($this->qtype->name(), 'ddimageortext'); + $this->assertEquals($this->qtype->name(), 'ddimageortext'); } public function test_can_analyse_responses() { diff --git a/question/type/ddimageortext/tests/walkthrough_test.php b/question/type/ddimageortext/tests/walkthrough_test.php new file mode 100644 index 00000000000..cc6578a7876 --- /dev/null +++ b/question/type/ddimageortext/tests/walkthrough_test.php @@ -0,0 +1,858 @@ +. + +/** + * Unit tests for the drag-and-drop onto image question type. + * + * @package qtype_ddimageortext + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); +require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php'); + + +/** + * Unit tests for the drag-and-drop onto image question type. + * + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @group qtype_ddimageortext + */ +class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_base { + + protected function get_contains_drag_image_home_expectation($dragitemno, $choice, $group) { + $class = 'group' . $group; + $class .= ' draghome dragitemhomes' . $dragitemno. ' choice'.$choice.' yui3-cssfonts'; + + $expectedattrs = array(); + $expectedattrs['class'] = $class; + + return new question_contains_tag_with_attributes('div', $expectedattrs); + } + + public function test_interactive_behaviour() { + + // Create a drag-and-drop question. + $dd = test_question_maker::make_question('ddimageortext'); + $dd->hints = array( + new question_hint_with_parts(13, 'This is the first hint.', FORMAT_HTML, false, false), + new question_hint_with_parts(14, 'This is the second hint.', FORMAT_HTML, true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 12); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + + // Save the wrong answer. + $this->process_submission(array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1')); + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 1), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + // Submit the wrong answer. + $this->process_submission( + array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 1), + $this->get_contains_try_again_button_expectation(true), + new question_pattern_expectation('/' . + preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + $this->get_contains_hint_expectation('This is the first hint')); + + // Do try again. + $this->process_submission(array('-tryagain' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', '1'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(2), + $this->get_no_hint_visible_expectation()); + + // Submit the right answer. + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(8); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', '2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', '1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', '2'), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_correct_expectation(), + $this->get_no_hint_visible_expectation()); + + // Check regrading does not mess anything up. + $this->quba->regrade_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(8); + } + + public function test_deferred_feedback() { + + // Create a drag-and-drop question. + $dd = test_question_maker::make_question('ddimageortext'); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'deferredfeedback', 12); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), + $this->get_does_not_contain_feedback_expectation()); + + // Save a partial answer. + $this->process_submission(array('p1' => '2', 'p2' => '1')); + // Verify. + $this->check_current_state(question_state::$invalid); + $this->check_current_mark(null); + + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + // Save the right answer. + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')); + + // Verify. + $this->check_current_state(question_state::$complete); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + + // Finish the attempt. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(12); + + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2), + $this->get_contains_correct_expectation()); + + // Change the right answer a bit. + $dd->rightchoices[2] = 1; + + // Check regrading does not mess anything up. + $this->quba->regrade_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedpartial); + $this->check_current_mark(9); + } + + public function test_deferred_feedback_unanswered() { + + // Create a drag-and-drop question. + $dd = test_question_maker::make_question('ddimageortext'); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'deferredfeedback', 12); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + $this->check_step_count(1); + + // Save a blank response. + $this->process_submission(array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => '')); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + $this->check_step_count(1); + + // Finish the attempt. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gaveup); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2)); + } + + public function test_deferred_feedback_partial_answer() { + + // Create a drag-and-drop question. + $dd = test_question_maker::make_question('ddimageortext'); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'deferredfeedback', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + + // Save a partial response. + $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => '')); + + // Verify. + $this->check_current_state(question_state::$invalid); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + + // Finish the attempt. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedpartial); + $this->check_current_mark(1.5); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_partcorrect_expectation()); + } + + public function test_interactive_grading() { + + // Create a drag-and-drop question. + $dd = test_question_maker::make_question('ddimageortext'); + $dd->hints = array( + new question_hint_with_parts(1, 'This is the first hint.', + FORMAT_MOODLE, true, true), + new question_hint_with_parts(2, 'This is the second hint.', + FORMAT_MOODLE, true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 12); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->assertEquals('interactivecountback', + $this->quba->get_question_attempt($this->slot)->get_behaviour_name()); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_does_not_contain_num_parts_correct(), + $this->get_no_hint_visible_expectation()); + + // Submit an response with the first two parts right. + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '2', 'p4' => '1', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_try_again_button_expectation(true), + $this->get_does_not_contain_correctness_expectation(), + new question_pattern_expectation('/' . + preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + $this->get_contains_hint_expectation('This is the first hint'), + $this->get_contains_num_parts_correct(2), + $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 1)); + + // Check that extract responses will return the reset data. + $prefix = $this->quba->get_field_prefix($this->slot); + $this->assertEquals(array('p1' => '1', 'p2' => '2'), + $this->quba->extract_responses($this->slot, + array($prefix . 'p1' => '1', $prefix . 'p2' => '2', '-tryagain' => 1))); + + // Do try again. + // keys p3 and p4 are extra hidden fields to clear data. + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '', 'p4' => '', '-tryagain' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_try_again_button_expectation(), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(2), + $this->get_no_hint_visible_expectation()); + + // Submit an response with the first and last parts right. + $this->process_submission( + array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '2', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_try_again_button_expectation(true), + $this->get_does_not_contain_correctness_expectation(), + new question_pattern_expectation('/' . + preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + $this->get_contains_hint_expectation('This is the second hint'), + $this->get_contains_num_parts_correct(2), + $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2)); + + // Do try again. + $this->process_submission( + array('p1' => '1', 'p2' => '', 'p3' => '', 'p4' => '2', '-tryagain' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_try_again_button_expectation(), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(1), + $this->get_no_hint_visible_expectation()); + + // Submit the right answer. + $this->process_submission( + array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(7); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', 1), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', 2), + $this->get_contains_submit_button_expectation(false), + $this->get_does_not_contain_try_again_button_expectation(), + $this->get_contains_correct_expectation(), + $this->get_no_hint_visible_expectation(), + $this->get_does_not_contain_num_parts_correct(), + $this->get_contains_standard_correct_combined_feedback_expectation()); + } + + public function test_interactive_correct_no_submit() { + + // Create a drag-and-drop question. + $dd = test_question_maker::make_question('ddimageortext'); + $dd->hints = array( + new question_hint_with_parts(23, 'This is the first hint.', + FORMAT_MOODLE, false, false), + new question_hint_with_parts(24, 'This is the second hint.', + FORMAT_MOODLE, true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + + // Save the right answer. + $this->process_submission(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2')); + + // Finish the attempt without clicking check. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(3); + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_correct_expectation(), + $this->get_no_hint_visible_expectation()); + + // Check regrading does not mess anything up. + $this->quba->regrade_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(3); + } + + public function test_interactive_partial_no_submit() { + + // Create a drag-and-drop question. + $dd = test_question_maker::make_question('ddimageortext'); + $dd->hints = array( + new question_hint_with_parts(23, 'This is the first hint.', + FORMAT_MOODLE, false, false), + new question_hint_with_parts(24, 'This is the second hint.', + FORMAT_MOODLE, true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 4); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + + // Save the a partially right answer. + $this->process_submission(array('p1' => '1', 'p2' => '1', 'p3' => '2', 'p4' => '1')); + + // Finish the attempt without clicking check. + $this->quba->finish_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedpartial); + $this->check_current_mark(1); + + $this->check_current_output( + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_partcorrect_expectation(), + $this->get_no_hint_visible_expectation()); + + // Check regrading does not mess anything up. + $this->quba->regrade_all_questions(); + + // Verify. + $this->check_current_state(question_state::$gradedpartial); + $this->check_current_mark(1); + } + + public function test_interactive_no_right_clears() { + + // Create a drag-and-drop question. + $dd = test_question_maker::make_question('ddimageortext'); + $dd->hints = array( + new question_hint_with_parts(23, 'This is the first hint.', FORMAT_MOODLE, false, true), + new question_hint_with_parts(24, 'This is the second hint.', FORMAT_MOODLE, true, true), + ); + $dd->shufflechoices = false; + $this->start_attempt_at_question($dd, 'interactive', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + + $this->check_current_output( + $this->get_contains_marked_out_of_summary(), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(3), + $this->get_no_hint_visible_expectation()); + + // Save the a completely wrong answer. + $this->process_submission( + array('p1' => '2', 'p2' => '1', 'p3' => '2', 'p4' => '1', '-submit' => 1)); + + // Verify. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_marked_out_of_summary(), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_submit_button_expectation(false), + $this->get_contains_hint_expectation('This is the first hint')); + + // Do try again. + $this->process_submission( + array('p1' => '', 'p2' => '', 'p3' => '', 'p4' => '', '-tryagain' => 1)); + + // Check that all the wrong answers have been cleared. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_marked_out_of_summary(), + $this->get_contains_drag_image_home_expectation(1, 1, 1), + $this->get_contains_drag_image_home_expectation(2, 2, 1), + $this->get_contains_drag_image_home_expectation(1, 1, 2), + $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', ''), + $this->get_contains_submit_button_expectation(true), + $this->get_does_not_contain_feedback_expectation(), + $this->get_tries_remaining_expectation(2), + $this->get_no_hint_visible_expectation()); + } + + public function test_display_of_right_answer_when_shuffled() { + + // Create a drag-and-drop question. + $dd = test_question_maker::make_question('ddimageortext'); + $this->start_attempt_at_question($dd, 'deferredfeedback', 3); + + // Check the initial state. + $this->check_current_state(question_state::$todo); + $this->check_current_mark(null); + + $this->check_current_output( + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3'), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4'), + $this->get_does_not_contain_feedback_expectation()); + + // Save a partial answer. + $this->process_submission($dd->get_correct_response()); + + // Verify. + $this->check_current_state(question_state::$complete); + $this->check_current_mark(null); + $this->check_current_output( + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p1', + $dd->get_right_choice_for(1)), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p2', + $dd->get_right_choice_for(2)), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p3', + $dd->get_right_choice_for(3)), + $this->get_contains_hidden_expectation( + $this->quba->get_field_prefix($this->slot) . 'p4', + $dd->get_right_choice_for(4)), + $this->get_does_not_contain_correctness_expectation(), + $this->get_does_not_contain_feedback_expectation()); + + // Finish the attempt. + $this->quba->finish_all_questions(); + + // Verify. + $this->displayoptions->rightanswer = question_display_options::VISIBLE; + $this->assertEquals('Drop zone 1 -> {1. quick} '. + 'Drop zone 2 -> {2. fox} '. + 'Drop zone 3 -> {1. lazy} '. + 'Drop zone 4 -> {2. dog}', + $dd->get_right_answer_summary()); + $this->check_current_state(question_state::$gradedright); + $this->check_current_mark(3); + } +} From 4c0f4ffe8e9bf806973733c216223631b88aded0 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 19 Jun 2012 20:11:24 +0700 Subject: [PATCH 161/208] MDL-47494 ddimageortext: NOBUG change in file access api in 2.3 --- question/type/ddimageortext/lib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/lib.php b/question/type/ddimageortext/lib.php index 4863b67da49..d7100209e10 100644 --- a/question/type/ddimageortext/lib.php +++ b/question/type/ddimageortext/lib.php @@ -31,9 +31,9 @@ defined('MOODLE_INTERNAL') || die(); /** * Checks file access for essay questions. */ -function qtype_ddimageortext_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { +function qtype_ddimageortext_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { global $CFG; require_once($CFG->libdir . '/questionlib.php'); question_pluginfile($course, $context, 'qtype_ddimageortext', - $filearea, $args, $forcedownload); + $filearea, $args, $forcedownload, $options); } From 0749cc7c303def0751ed20537609a250c1d2ff4c Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 21 Jun 2012 12:45:11 +0700 Subject: [PATCH 162/208] MDL-47494 ddimageortext: NOBUG fixes for fileaccess through lib.php added missing lib.php files and fixed comments --- question/type/ddimageortext/lib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/lib.php b/question/type/ddimageortext/lib.php index 4863b67da49..40a171b505f 100644 --- a/question/type/ddimageortext/lib.php +++ b/question/type/ddimageortext/lib.php @@ -19,7 +19,7 @@ * * @since 2.0 * @package qtype - * @subpackage essay + * @subpackage ddimageortext * @copyright Dongsheng Cai * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); /** - * Checks file access for essay questions. + * Checks file access for ddimageortext questions. */ function qtype_ddimageortext_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { global $CFG; From 93905b68816419930d77c3ee22b19d77f191f22a Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 27 Jul 2012 12:54:21 +0700 Subject: [PATCH 163/208] MDL-47494 ddimageortext: OU-4193 Fix for broken drag and drop with YUI 3.5.1 --- question/type/ddimageortext/yui/dd/dd.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 06b5298039d..2df9b981796 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -151,7 +151,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { draggable_for_question : function (drag, group, choice) { var dd = new Y.DD.Drag({ node: drag, - dragMode: 'intersect' + dragMode: 'point' }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); drag.setData('group', group); @@ -161,7 +161,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { draggable_for_form : function (drag) { var dd = new Y.DD.Drag({ node: drag, - dragMode: 'intersect' + dragMode: 'point' }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); dd.on('drag:end', function(e) { var dragnode = e.target.get('node'); From 4e4b48a4789cff003a78bba2d067e84b6c6731e9 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Fri, 27 Jul 2012 13:38:51 +0700 Subject: [PATCH 164/208] MDL-47494 ddimageortext: OU-4202 fix version no to require Moodle 2.3 --- question/type/ddimageortext/version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index bccc10b2ee5..e9988519f93 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2011051200; +$plugin->version = 2012062500; $plugin->requires = 2011120500; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; From 15c668b0d62ee0af2b6ea335f33b7066fa7eb9e2 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 30 Jul 2012 13:09:21 +0700 Subject: [PATCH 165/208] MDL-47494 ddimageortext: NOBUG Hilight drop target, and use YUI dd groups. --- question/type/ddimageortext/styles.css | 8 +++++++- question/type/ddimageortext/yui/dd/dd.js | 5 +++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 95287819957..27cf612e019 100644 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -68,6 +68,12 @@ position: absolute; z-index: 1; } + +.que.ddimageortext .dropzone.yui3-dd-drop-over.yui3-dd-drop-active-valid { + border-color: #0a0; + box-shadow: 0 0 5px 5px rgba(255, 255, 150, 1); +} + .que.ddimageortext div.dragitems div.draghome, .que.ddimageortext div.dragitems div.drag, form.mform fieldset#previewareaheader div.draghome, form.mform fieldset#previewareaheader div.drag { font:13px/1.231 arial,helvetica,clean,sans-serif; @@ -84,4 +90,4 @@ form.mform fieldset#previewareaheader div.drag.yui3-dd-dragging, -ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000')"; /* For IE 5.5 - 7 */ filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000'); -} \ No newline at end of file +} diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 2df9b981796..e8fe20c907e 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -151,7 +151,8 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { draggable_for_question : function (drag, group, choice) { var dd = new Y.DD.Drag({ node: drag, - dragMode: 'point' + dragMode: 'point', + groups: [group] }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); drag.setData('group', group); @@ -419,7 +420,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { dropnode.setData('inputid', drop.fieldname.replace(':', '_')); dropnode.setData('group', drop.group); var dropdd = new Y.DD.Drop({ - node: dropnode}); + node: dropnode, groups : [drop.group]}); dropdd.on('drop:hit', function(e) { var drag = e.drag.get('node'); var drop = e.drop.get('node'); From 727d8c94ab39d470003ed74f28e77182023e3848 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 7 Aug 2012 17:32:21 +0100 Subject: [PATCH 166/208] MDL-47494 ddimageortext: Russian translation, thanks to Sergey Zolotykhin. --- .../lang/ru/qtype_ddimageortext.php | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 question/type/ddimageortext/lang/ru/qtype_ddimageortext.php diff --git a/question/type/ddimageortext/lang/ru/qtype_ddimageortext.php b/question/type/ddimageortext/lang/ru/qtype_ddimageortext.php new file mode 100644 index 00000000000..d28de24d9ca --- /dev/null +++ b/question/type/ddimageortext/lang/ru/qtype_ddimageortext.php @@ -0,0 +1,72 @@ +. + +/** + * русский перевод Золотухин Сергей Александрович + * farcrys@yandex.ru + * moodlefree.ru + * + * @package qtype_ddimageortext + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +$string['addmoredropzones'] = 'Добавить еще {no} объект'; +$string['addmoreimages'] = 'Добавить еще {no} перетаскиваемых объекта'; +$string['answer'] = 'Ответ'; +$string['bgimage'] = 'Фоновое изображения'; +$string['correctansweris'] = 'Правильный ответ: {$a}'; +$string['draggableimage'] = 'Перетаскиваемое изображение'; +$string['draggableitem'] = 'Перетаскиваемый элемент'; +$string['draggableitemheader'] = 'Перетаскиваемый элемент {$a}'; +$string['draggableitemtype'] = 'Тип'; +$string['draggableword'] = 'Перетаскиваемый текст'; +$string['dropbackground'] = 'Фоновое изображение, на которое перетаскиваются объекты'; +$string['dropzone'] = 'Drop-зона {$a}'; +$string['dropzoneheader'] = 'Drop-зона'; +$string['formerror_disallowedtags'] = 'Вы использовали HTML-теги, которые не разрешены в перетаскиваемом тексте.'; +$string['formerror_noallowedtags'] = 'HTML теги нельзя использовать в тексте, который является alt текстом для перетаскиваемого изображения'; +$string['formerror_noytop'] = 'Вы должны указать значение координат в левом верхнем углу этой области. Вы можете перетащить и поместить элемент, чтобы установить координаты, или вводить их вручную.'; +$string['formerror_noxleft'] = 'Вы должны указать значение координат в левом верхнем углу этой области. Вы можете перетащить и поместить элемент, чтобы установить координаты, или вводить их вручную.'; +$string['formerror_nofile'] = 'Вы должны выбрать или загрузить файл.'; +$string['formerror_nofile3'] = 'Вам нужно выбрать файл изображения, или удалить связанную метку и снять флажок множества.'; +$string['formerror_multipledraginstance'] = 'Вы выбрали это изображение {$a} более, чем один раз в качестве правильного ответа для drop-зоны, но он не помечен отметкой множества.'; +$string['formerror_multipledraginstance2'] = 'Вы выбрали это изображение более, чем один раз в качестве правильного ответа для drop-зоны, но он не помечен отметкой множества.'; +$string['formerror_noimageselected'] = 'Вы должны выбрать перетаскиваемый элемент в качестве правильного ответа для drop-зоны.'; +$string['formerror_nobgimage'] = 'Вы должны выбрать изображение для использования в качестве фона для области перетаскивания.'; +$string['infinite'] = 'множество'; +$string['label'] = 'Текст'; +$string['nolabel'] = 'Нет метки текста'; +$string['pleasedraganimagetoeachdropregion'] = 'Ваш ответ не полный. Пожалуйста, перетащите каждый элемент в соответствующую область.'; +$string['pluginname'] = 'Перетащи и оставь (с изображением)'; +$string['pluginname_help'] = 'Выберите файл (фоновое изображение), выберите перетаскиваемое изображение или текст и определите drop-зоны (области, в которые необходимо переместить элементы).'; +$string['pluginname_link'] = 'question/type/ddimageortext'; +$string['pluginnameadding'] = 'Добавить вопрос типа "Перетащи и оставь (с изображением)"'; +$string['pluginnameediting'] = 'Редактировать вопрос типа "Перетащи и оставь (с изображением)"'; +$string['pluginnamesummary'] = 'Изображение или текст необходимо перетащить внутрь drop-зон на фоновом изображении.'; +$string['previewarea'] = 'Превью -'; +$string['previewareaheader'] = 'Превью'; +$string['previewareamessage'] = 'Выберите файл (фоновое изображение), выберите перетаскиваемое изображение или запишите текст. +Затем определите перетаскиваемые элементы для каждой drop-зоны - области, в которые студенту необходимо переместить элементы.'; +$string['refresh'] = 'Обновить превью'; +$string['shuffleimages'] = 'Перемешивать перетаскиваемые элементы при каждой попытке'; +$string['summarisechoice'] = '{$a->no}. {$a->text}'; +$string['summariseplace'] = '{$a->no}. {$a->text}'; +$string['summarisechoiceno'] = 'Элемент {$a}'; +$string['summariseplaceno'] = 'Drop-зона {$a}'; +$string['xleft'] = 'слева'; +$string['ytop'] = 'сверху'; From 39a6b826d22e407d90ca4ce6868f33f248a827ad Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 16 Aug 2012 16:31:46 +0200 Subject: [PATCH 167/208] MDL-47494 ddimageortext: Update release information. --- question/type/ddimageortext/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index e9988519f93..56d3ef6a060 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -25,12 +25,12 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2012062500; +$plugin->version = 2012081600; $plugin->requires = 2011120500; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.0'; +$plugin->release = '1.1 for Moodle 2.3+'; $plugin->dependencies = array( 'qtype_gapselect' => 2011020100, From 95fe59ff627313c7af0a2375fea735ce7a1ac48e Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 16 Aug 2012 16:32:36 +0200 Subject: [PATCH 168/208] MDL-47494 ddimageortext: Update release information. --- question/type/ddimageortext/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index bccc10b2ee5..15a347ccdf9 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -25,12 +25,12 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2011051200; +$plugin->version = 2012081600; $plugin->requires = 2011120500; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.0'; +$plugin->release = '1.1 for Moodle 2.2'; $plugin->dependencies = array( 'qtype_gapselect' => 2011020100, From 1f8e5648fb7d4cb5cb8b3a39d6b5514073b494d7 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 16 Aug 2012 16:38:16 +0200 Subject: [PATCH 169/208] MDL-47494 ddimageortext: Fix required version. --- question/type/ddimageortext/version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 56d3ef6a060..353ff7afbf5 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2012081600; -$plugin->requires = 2011120500; +$plugin->requires = 2012062500; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; From 07ef9448bf971d5e8ed4ccf7135800554bec37cd Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 20 Aug 2012 14:38:44 +0100 Subject: [PATCH 170/208] MDL-47494 ddimageortext: New icon by Paul Hillery. --- question/type/ddimageortext/pix/icon.gif | Bin 361 -> 0 bytes question/type/ddimageortext/pix/icon.png | Bin 0 -> 1140 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 question/type/ddimageortext/pix/icon.gif create mode 100644 question/type/ddimageortext/pix/icon.png diff --git a/question/type/ddimageortext/pix/icon.gif b/question/type/ddimageortext/pix/icon.gif deleted file mode 100644 index f5705c637b7bd1003995fef64a48e51ae378b29e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 361 zcmV-v0hazpNk%w1VGsZi0M!5hBQ{wtLSi#VYBWe{H%DSPK~XzRY&}qMKT&T(RB}aB zZb(;iNm+AIQBhKKqgQyQU3{rwf2(7Gu4i?RXoRY1hOuplvvG~5a*eiikhge}xq60} zeTkicikg9qqJx^fhLNL)iiL=t!HuHAkEXAarpA@1$CjzcnXAd1r@5W4$DXLVp|iuH zv(BWrsiwBjsJGFmxYD%4w8YV`#nG|R+_Bu{x#H`-?(@s`_V)Ms-~9dV{r&v_00000 z00000A^8Le002DzEC2ui01yBW000Jtz>siAEDCwZq*8g@5T4NJCU-Ertp!prI)Z4IPFA2C1n50Hg({2?+-V0|KO^rydi#yu5}^QNdG3ImO1u#XLsK HL_q*M7u=r% diff --git a/question/type/ddimageortext/pix/icon.png b/question/type/ddimageortext/pix/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e368b120236c4b5f044aa70ce1106aeec83ca10b GIT binary patch literal 1140 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m=!WZB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPA){ffi_eM3D1{oGuTzrd=COM+4n&cLd=IHa;5RX-@T zIKQ+g85kdF$}r8qu)}W=NFmTQRxbI;rManjC7v#}NH&+v914naXS4SsP zLqk_XCu3t5H$w|o10z=>V?z@sm|oAk;*!L?EaktajPe2qhPZE&z926mBL{OyhUGl&Pc6s;ND?g z`MOi7M&#$AI`90*O(OiRJ%$=K>-(NCwehk?9sFKfukDb>Bpd%^&c=1Gxn6oRHZ9(H zE@nq$#iVVy8}&{nJ@i#r_BhK<|0~l%<)tB^`HGqC4PpzcWR9;eh&`(KV6M=D_rELW z)t-38`f1(kWto#s6-FOc4XwGkEw|!HL50>HR;CjQcE20seztAk|M%Nh;b{zopr0F5z$a{vGU literal 0 HcmV?d00001 From ad8234a323e54212d8c26614b06fc66bef0257ed Mon Sep 17 00:00:00 2001 From: Nicolas Dunand Date: Thu, 30 Aug 2012 14:34:05 +0200 Subject: [PATCH 171/208] MDL-47494 ddimageortext: Added French translation --- .../lang/fr/qtype_ddimageortext.php | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 question/type/ddimageortext/lang/fr/qtype_ddimageortext.php diff --git a/question/type/ddimageortext/lang/fr/qtype_ddimageortext.php b/question/type/ddimageortext/lang/fr/qtype_ddimageortext.php new file mode 100644 index 00000000000..35b8541dade --- /dev/null +++ b/question/type/ddimageortext/lang/fr/qtype_ddimageortext.php @@ -0,0 +1,68 @@ +. + +/** + * + * @package qtype + * @subpackage ddimageortext + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['addmoredropzones'] = 'Vides pour {no} zones de dépôt supplémentaires'; +$string['addmoreimages'] = 'Vides pour {no} éléments déplaçables supplémentaires'; +$string['answer'] = 'Réponse'; +$string['bgimage'] = 'Image de fond'; +$string['correctansweris'] = 'La réponse correcte est: {$a}'; +$string['draggableimage'] = 'Image déplaçable'; +$string['draggableitem'] = 'Elément déplaçable'; +$string['draggableitemheader'] = 'Elément déplaçable {$a}'; +$string['draggableitemtype'] = 'Type'; +$string['draggableword'] = 'Texte déplaçable'; +$string['dropbackground'] = 'Image de fond pouvant être recouverte de marqueurs déplaçables'; +$string['dropzone'] = 'Zone de dépôt {$a}'; +$string['dropzoneheader'] = 'Zones de dépôt'; +$string['formerror_disallowedtags'] = 'Vous avez utilisé des tags html qui ne sont pas autorisés dans un texte déplaçable.'; +$string['formerror_noallowedtags'] = 'Aucun tag html autorisé dans ce texte qui constitue l\'annotation visible (balise alt) d\'une image déplaçable'; +$string['formerror_noytop'] = 'Vous devez donner une valeur pour les coordonnées y du coin supérieur gauche de cette zone de dépôt. Vous pouvez déplacer la zone de dépôt au-dessus pour définir les coordonnées ou les entrer manuellement ici.'; +$string['formerror_noxleft'] = 'Vous devez donner une valeur pour les coordonnées x du coin supérieur gauche de cette zone de dépôt. Vous pouvez déplacer la zone de dépôt au-dessus pour définir les coordonnées ou les entrer manuellement ici.'; +$string['formerror_nofile'] = 'Vous devez uploader ou sélectionner un fichier à utiliser ici.'; +$string['formerror_nofile3'] = 'Vous devez sélectionner un fichier image ici, ou effacer le label associé et décocher la case infini.'; +$string['formerror_multipledraginstance'] = 'Vous avez sélectionné cette image {$a} plus d\'une fois comme le choix correct d\'une zone de dépôt mais elle n\'est pas considérée comme étant un élément déplaçable à l\'infini.'; +$string['formerror_multipledraginstance2'] = 'Vous avez sélectionné cette image plus d\'une fois comme le choix correct d\'une zone de dépôt mais elle n\'est pas considérée comme étant un élément déplaçable à l\'infini.'; +$string['formerror_noimageselected'] = 'Vous devez sélectionner un élément déplaçable pour être le choix correct de cette zone de dépôt.'; +$string['formerror_nobgimage'] = 'Vous devez sélectionner une image à utiliser comme fond pour cette aire de glisser-déposer.'; +$string['infinite'] = 'Infini'; +$string['label'] = 'Texte'; +$string['nolabel'] = 'Pas de label'; +$string['pleasedraganimagetoeachdropregion'] = 'Votre réponse est incomplète, veuillez déposer un élément dans chaque région de dépôt.'; +$string['pluginname'] = 'Glisser-déposer sur image'; +$string['pluginname_help'] = 'Sélectionnez un fichier image de fond, sélectionnez une ou plusieurs images déplaçables ou entrez un texte et définissez les zones de dépôt sur l\'image de fond sur lesquelles elles doivent être déposées.'; +$string['pluginname_link'] = 'question/type/ddimageortext'; +$string['pluginnameadding'] = 'Ajout de glisser-déposer sur image'; +$string['pluginnameediting'] = 'Edition de glisser-déposer sur image'; +$string['pluginnamesummary'] = 'Les images ou les labels sont glissés et déposés dans des zones de dépôt sur une image de fond.'; +$string['previewarea'] = 'Zone de prévisualisation -'; +$string['previewareaheader'] = 'Aperçu'; +$string['previewareamessage'] = 'Sélectionnez un fichier image de fond et sélectionnez une ou plusieurs images déplaçables ou entrez simplement un texte qui sera rendu déplaçable. Puis choisissez un élément déplaçable pour chaque \'zone de dépôt\', et déplacez l\'élément jusqu\'à l\'endroit ou l\'étudiant devra le placer'; +$string['refresh'] = 'Rafraîchir l\'aperçu'; +$string['shuffleimages'] = 'Mélanger les éléments déplaçables lors de chaque tentative'; +$string['summarisechoice'] = '{$a->no}. {$a->text}'; +$string['summariseplace'] = '{$a->no}. {$a->text}'; +$string['summarisechoiceno'] = 'Elément {$a}'; +$string['summariseplaceno'] = 'Zone de dépôt {$a}'; +$string['xleft'] = 'Gauche'; +$string['ytop'] = 'Haut'; \ No newline at end of file From ae64c686089ba0317f8a579854af9a5cddec5c77 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 28 Sep 2012 18:13:10 +0100 Subject: [PATCH 172/208] MDL-47494 ddimageortext: Form validation should ensure coordinates are ints. --- .../ddimageortext/edit_ddimageortext_form.php | 24 ++++++++++++------- .../edit_ddtoimage_form_base.php | 1 - .../lang/en/qtype_ddimageortext.php | 4 +++- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index d3f0833c536..ee6c36bc229 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -217,6 +217,8 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { protected function drop_zones_repeated_options() { $repeatedoptions = array(); + $repeatedoptions['xleft']['type'] = PARAM_INT; + $repeatedoptions['ytop']['type'] = PARAM_INT; $repeatedoptions['choice']['default'] = '0'; return $repeatedoptions; } @@ -230,19 +232,23 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $allchoices = array(); for ($i=0; $i < $data['nodropzone']; $i++) { $ytoppresent = (trim($data['drops'][$i]['ytop']) !== ''); - $xleftpresent = (trim($data['drops'][$i]['ytop']) !== ''); + $xleftpresent = (trim($data['drops'][$i]['xleft']) !== ''); + $ytopisint = (string) clean_param($data['drops'][$i]['ytop'], PARAM_INT) === trim($data['drops'][$i]['ytop']); + $xleftisint = (string) clean_param($data['drops'][$i]['xleft'], PARAM_INT) === trim($data['drops'][$i]['xleft']); $labelpresent = (trim($data['drops'][$i]['droplabel']) !== ''); $choice = $data['drops'][$i]['choice']; $imagechoicepresent = ($choice !== '0'); if ($imagechoicepresent) { if (!$ytoppresent) { - $errors["drops[$i]"] = - get_string('formerror_noytop', 'qtype_ddimageortext'); + $errors["drops[$i]"] = get_string('formerror_noytop', 'qtype_ddimageortext'); + } else if (!$ytopisint) { + $errors["drops[$i]"] = get_string('formerror_notintytop', 'qtype_ddimageortext'); } if (!$xleftpresent) { - $errors["drops[$i]"] = - get_string('formerror_noxleft', 'qtype_ddimageortext'); + $errors["drops[$i]"] = get_string('formerror_noxleft', 'qtype_ddimageortext'); + } else if (!$xleftisint) { + $errors["drops[$i]"] = get_string('formerror_notintxleft', 'qtype_ddimageortext'); } if ($data['dragitemtype'][$choice - 1] != 'word' && @@ -253,17 +259,17 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { $errors["drops[$i]"] = - get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); + get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); $errors['drops['.($allchoices[$choice]).']'] = - get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); + get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); $errors['drags['.($choice-1).']'] = - get_string('formerror_multipledraginstance2', 'qtype_ddimageortext', $choice); + get_string('formerror_multipledraginstance2', 'qtype_ddimageortext', $choice); } $allchoices[$choice] = $i; } else { if ($ytoppresent || $xleftpresent || $labelpresent) { $errors["drops[$i]"] = - get_string('formerror_noimageselected', 'qtype_ddimageortext'); + get_string('formerror_noimageselected', 'qtype_ddimageortext'); } } } diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php index ee5b2904c29..3e7f5c28388 100644 --- a/question/type/ddimageortext/edit_ddtoimage_form_base.php +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -36,7 +36,6 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { const START_NUM_ITEMS = 6; const ADD_NUM_ITEMS = 3; - /** * * Options shared by all file pickers in the form. diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index d7e9948adc6..384b1a84566 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -42,9 +42,11 @@ $string['editingddimageortext'] = 'Editing drag and drop onto image'; $string['formerror_disallowedtags'] = 'You have used html tags here that are not allowed in a draggable text drag item type.'; $string['formerror_noallowedtags'] = 'No html tags are allowed in this text which is the alt text for a draggable image'; $string['formerror_noytop'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; -$string['formerror_noxleft'] = 'You must provide a value for the y coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; +$string['formerror_noxleft'] = 'You must provide a value for the x coords for the top left corner of this drop area. You can drag and drop the drop area above to set the coordinates or enter them manually here.'; $string['formerror_nofile'] = 'You need to upload or select a file to use here.'; $string['formerror_nofile3'] = 'You need to select an image file here, or delete the associated label and uncheck the infinite checkbox.'; +$string['formerror_notintytop'] = 'The y coords must be an integer.'; +$string['formerror_notintxleft'] = 'The x coords must be an integer.'; $string['formerror_multipledraginstance'] = 'You have selected this image {$a} more than once as the correct choice for a drop zone but it is not marked as being an infinite drag item.'; $string['formerror_multipledraginstance2'] = 'You have selected this image more than once as the correct choice for a drop zone but it is not marked as being an infinite drag item.'; $string['formerror_noimageselected'] = 'You need to select a drag item to be the correct choice for this drop zone.'; From 7a6539401fbd494e4c02ad79099c88c07c5873fc Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 15 Jan 2013 14:40:36 +0000 Subject: [PATCH 173/208] MDL-47494 ddimageortext: Fix incorrect preg_quote without delimiter. --- question/type/ddimageortext/tests/walkthrough_test.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/tests/walkthrough_test.php b/question/type/ddimageortext/tests/walkthrough_test.php index cc6578a7876..ea1ec43dfe7 100644 --- a/question/type/ddimageortext/tests/walkthrough_test.php +++ b/question/type/ddimageortext/tests/walkthrough_test.php @@ -127,7 +127,7 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->quba->get_field_prefix($this->slot) . 'p4', 1), $this->get_contains_try_again_button_expectation(true), new question_pattern_expectation('/' . - preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'), $this->get_contains_hint_expectation('This is the first hint')); // Do try again. @@ -469,7 +469,7 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), new question_pattern_expectation('/' . - preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'), $this->get_contains_hint_expectation('This is the first hint'), $this->get_contains_num_parts_correct(2), $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), @@ -532,7 +532,7 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), new question_pattern_expectation('/' . - preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'), + preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'), $this->get_contains_hint_expectation('This is the second hint'), $this->get_contains_num_parts_correct(2), $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), From 0cf0f8604165cf1856b5dc72a9d140b77f00e6fc Mon Sep 17 00:00:00 2001 From: Colin Chambers Date: Tue, 29 Jan 2013 15:35:51 +0000 Subject: [PATCH 174/208] MDL-47494 ddimageortext: MDL-37759 Question: Drag Drop Images group add more link --- question/type/ddimageortext/edit_ddtoimage_form_base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php index 3e7f5c28388..335840fe5ee 100644 --- a/question/type/ddimageortext/edit_ddtoimage_form_base.php +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -101,7 +101,7 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { $this->repeat_elements($this->drop_zone($mform, $imagerepeats), $dropzonerepeatsatstart, $this->drop_zones_repeated_options(), 'nodropzone', 'adddropzone', self::ADD_NUM_ITEMS, - get_string('addmoredropzones', 'qtype_ddimageortext')); + get_string('addmoredropzones', 'qtype_ddimageortext'), true); } abstract protected function drop_zone($mform, $imagerepeats); From 784c54ea36db221ffc161f0e53337b957081d1f3 Mon Sep 17 00:00:00 2001 From: Colin Chambers Date: Wed, 30 Jan 2013 11:32:13 +0000 Subject: [PATCH 175/208] MDL-47494 ddimageortext: MDL-37463 Question: Drag drop image form lang capitalisation --- question/type/ddimageortext/lang/en/qtype_ddimageortext.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index 014bf9e1a4b..1ca222417ee 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -60,7 +60,7 @@ $string['pluginnamesummary'] = 'Images or text labels are dragged and dropped in $string['previewarea'] = 'Preview area -'; $string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; -$string['refresh'] = 'Refresh Preview'; +$string['refresh'] = 'Refresh preview'; $string['shuffleimages'] = 'Shuffle drag items each time question is attempted'; $string['summarisechoice'] = '{$a->no}. {$a->text}'; $string['summariseplace'] = '{$a->no}. {$a->text}'; From 66d2356bd3ec09771d35f0da0f464eca96134810 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 14 Mar 2013 14:21:45 +0000 Subject: [PATCH 176/208] MDL-47494 ddimageortext: Clean up comments in unit tests. --- question/type/ddimageortext/tests/question_test.php | 12 ++++++------ .../type/ddimageortext/tests/questiontype_test.php | 12 ++++++------ .../type/ddimageortext/tests/walkthrough_test.php | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/question/type/ddimageortext/tests/question_test.php b/question/type/ddimageortext/tests/question_test.php index cc35d4cefe9..32c2a69dfd3 100644 --- a/question/type/ddimageortext/tests/question_test.php +++ b/question/type/ddimageortext/tests/question_test.php @@ -17,9 +17,9 @@ /** * Unit tests for the drag-and-drop onto image question definition class. * - * @package qtype_ddimageortext - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype_ddimageortext + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -33,9 +33,9 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php'); /** * Unit tests for the matching question definition class. * - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @group qtype_ddimageortext + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @group qtype_ddimageortext */ class qtype_ddimageortext_question_test extends basic_testcase { diff --git a/question/type/ddimageortext/tests/questiontype_test.php b/question/type/ddimageortext/tests/questiontype_test.php index 41132a26163..287473b5716 100644 --- a/question/type/ddimageortext/tests/questiontype_test.php +++ b/question/type/ddimageortext/tests/questiontype_test.php @@ -17,9 +17,9 @@ /** * Unit tests for the drag-and-drop onto image question definition class. * - * @package qtype_ddimageortext - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype_ddimageortext + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -33,9 +33,9 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php'); /** * Unit tests for the drag-and-drop onto image question definition class. * - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @group qtype_ddimageortext + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @group qtype_ddimageortext */ class qtype_ddimageortext_test extends basic_testcase { /** @var qtype_ddimageortext instance of the question type class to test. */ diff --git a/question/type/ddimageortext/tests/walkthrough_test.php b/question/type/ddimageortext/tests/walkthrough_test.php index ea1ec43dfe7..ce7f431960f 100644 --- a/question/type/ddimageortext/tests/walkthrough_test.php +++ b/question/type/ddimageortext/tests/walkthrough_test.php @@ -17,9 +17,9 @@ /** * Unit tests for the drag-and-drop onto image question type. * - * @package qtype_ddimageortext - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype_ddimageortext + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -33,9 +33,9 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php'); /** * Unit tests for the drag-and-drop onto image question type. * - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @group qtype_ddimageortext + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @group qtype_ddimageortext */ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_base { From 8312572b8b8be68fdefcd216d605bd2e008e220f Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 14 Mar 2013 14:22:04 +0000 Subject: [PATCH 177/208] MDL-47494 ddimageortext: Move lang strings to AMOS. --- .../lang/fr/qtype_ddimageortext.php | 68 ------------------ .../lang/ru/qtype_ddimageortext.php | 72 ------------------- 2 files changed, 140 deletions(-) delete mode 100644 question/type/ddimageortext/lang/fr/qtype_ddimageortext.php delete mode 100644 question/type/ddimageortext/lang/ru/qtype_ddimageortext.php diff --git a/question/type/ddimageortext/lang/fr/qtype_ddimageortext.php b/question/type/ddimageortext/lang/fr/qtype_ddimageortext.php deleted file mode 100644 index 35b8541dade..00000000000 --- a/question/type/ddimageortext/lang/fr/qtype_ddimageortext.php +++ /dev/null @@ -1,68 +0,0 @@ -. - -/** - * - * @package qtype - * @subpackage ddimageortext - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -$string['addmoredropzones'] = 'Vides pour {no} zones de dépôt supplémentaires'; -$string['addmoreimages'] = 'Vides pour {no} éléments déplaçables supplémentaires'; -$string['answer'] = 'Réponse'; -$string['bgimage'] = 'Image de fond'; -$string['correctansweris'] = 'La réponse correcte est: {$a}'; -$string['draggableimage'] = 'Image déplaçable'; -$string['draggableitem'] = 'Elément déplaçable'; -$string['draggableitemheader'] = 'Elément déplaçable {$a}'; -$string['draggableitemtype'] = 'Type'; -$string['draggableword'] = 'Texte déplaçable'; -$string['dropbackground'] = 'Image de fond pouvant être recouverte de marqueurs déplaçables'; -$string['dropzone'] = 'Zone de dépôt {$a}'; -$string['dropzoneheader'] = 'Zones de dépôt'; -$string['formerror_disallowedtags'] = 'Vous avez utilisé des tags html qui ne sont pas autorisés dans un texte déplaçable.'; -$string['formerror_noallowedtags'] = 'Aucun tag html autorisé dans ce texte qui constitue l\'annotation visible (balise alt) d\'une image déplaçable'; -$string['formerror_noytop'] = 'Vous devez donner une valeur pour les coordonnées y du coin supérieur gauche de cette zone de dépôt. Vous pouvez déplacer la zone de dépôt au-dessus pour définir les coordonnées ou les entrer manuellement ici.'; -$string['formerror_noxleft'] = 'Vous devez donner une valeur pour les coordonnées x du coin supérieur gauche de cette zone de dépôt. Vous pouvez déplacer la zone de dépôt au-dessus pour définir les coordonnées ou les entrer manuellement ici.'; -$string['formerror_nofile'] = 'Vous devez uploader ou sélectionner un fichier à utiliser ici.'; -$string['formerror_nofile3'] = 'Vous devez sélectionner un fichier image ici, ou effacer le label associé et décocher la case infini.'; -$string['formerror_multipledraginstance'] = 'Vous avez sélectionné cette image {$a} plus d\'une fois comme le choix correct d\'une zone de dépôt mais elle n\'est pas considérée comme étant un élément déplaçable à l\'infini.'; -$string['formerror_multipledraginstance2'] = 'Vous avez sélectionné cette image plus d\'une fois comme le choix correct d\'une zone de dépôt mais elle n\'est pas considérée comme étant un élément déplaçable à l\'infini.'; -$string['formerror_noimageselected'] = 'Vous devez sélectionner un élément déplaçable pour être le choix correct de cette zone de dépôt.'; -$string['formerror_nobgimage'] = 'Vous devez sélectionner une image à utiliser comme fond pour cette aire de glisser-déposer.'; -$string['infinite'] = 'Infini'; -$string['label'] = 'Texte'; -$string['nolabel'] = 'Pas de label'; -$string['pleasedraganimagetoeachdropregion'] = 'Votre réponse est incomplète, veuillez déposer un élément dans chaque région de dépôt.'; -$string['pluginname'] = 'Glisser-déposer sur image'; -$string['pluginname_help'] = 'Sélectionnez un fichier image de fond, sélectionnez une ou plusieurs images déplaçables ou entrez un texte et définissez les zones de dépôt sur l\'image de fond sur lesquelles elles doivent être déposées.'; -$string['pluginname_link'] = 'question/type/ddimageortext'; -$string['pluginnameadding'] = 'Ajout de glisser-déposer sur image'; -$string['pluginnameediting'] = 'Edition de glisser-déposer sur image'; -$string['pluginnamesummary'] = 'Les images ou les labels sont glissés et déposés dans des zones de dépôt sur une image de fond.'; -$string['previewarea'] = 'Zone de prévisualisation -'; -$string['previewareaheader'] = 'Aperçu'; -$string['previewareamessage'] = 'Sélectionnez un fichier image de fond et sélectionnez une ou plusieurs images déplaçables ou entrez simplement un texte qui sera rendu déplaçable. Puis choisissez un élément déplaçable pour chaque \'zone de dépôt\', et déplacez l\'élément jusqu\'à l\'endroit ou l\'étudiant devra le placer'; -$string['refresh'] = 'Rafraîchir l\'aperçu'; -$string['shuffleimages'] = 'Mélanger les éléments déplaçables lors de chaque tentative'; -$string['summarisechoice'] = '{$a->no}. {$a->text}'; -$string['summariseplace'] = '{$a->no}. {$a->text}'; -$string['summarisechoiceno'] = 'Elément {$a}'; -$string['summariseplaceno'] = 'Zone de dépôt {$a}'; -$string['xleft'] = 'Gauche'; -$string['ytop'] = 'Haut'; \ No newline at end of file diff --git a/question/type/ddimageortext/lang/ru/qtype_ddimageortext.php b/question/type/ddimageortext/lang/ru/qtype_ddimageortext.php deleted file mode 100644 index d28de24d9ca..00000000000 --- a/question/type/ddimageortext/lang/ru/qtype_ddimageortext.php +++ /dev/null @@ -1,72 +0,0 @@ -. - -/** - * русский перевод Золотухин Сергей Александрович - * farcrys@yandex.ru - * moodlefree.ru - * - * @package qtype_ddimageortext - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - - -$string['addmoredropzones'] = 'Добавить еще {no} объект'; -$string['addmoreimages'] = 'Добавить еще {no} перетаскиваемых объекта'; -$string['answer'] = 'Ответ'; -$string['bgimage'] = 'Фоновое изображения'; -$string['correctansweris'] = 'Правильный ответ: {$a}'; -$string['draggableimage'] = 'Перетаскиваемое изображение'; -$string['draggableitem'] = 'Перетаскиваемый элемент'; -$string['draggableitemheader'] = 'Перетаскиваемый элемент {$a}'; -$string['draggableitemtype'] = 'Тип'; -$string['draggableword'] = 'Перетаскиваемый текст'; -$string['dropbackground'] = 'Фоновое изображение, на которое перетаскиваются объекты'; -$string['dropzone'] = 'Drop-зона {$a}'; -$string['dropzoneheader'] = 'Drop-зона'; -$string['formerror_disallowedtags'] = 'Вы использовали HTML-теги, которые не разрешены в перетаскиваемом тексте.'; -$string['formerror_noallowedtags'] = 'HTML теги нельзя использовать в тексте, который является alt текстом для перетаскиваемого изображения'; -$string['formerror_noytop'] = 'Вы должны указать значение координат в левом верхнем углу этой области. Вы можете перетащить и поместить элемент, чтобы установить координаты, или вводить их вручную.'; -$string['formerror_noxleft'] = 'Вы должны указать значение координат в левом верхнем углу этой области. Вы можете перетащить и поместить элемент, чтобы установить координаты, или вводить их вручную.'; -$string['formerror_nofile'] = 'Вы должны выбрать или загрузить файл.'; -$string['formerror_nofile3'] = 'Вам нужно выбрать файл изображения, или удалить связанную метку и снять флажок множества.'; -$string['formerror_multipledraginstance'] = 'Вы выбрали это изображение {$a} более, чем один раз в качестве правильного ответа для drop-зоны, но он не помечен отметкой множества.'; -$string['formerror_multipledraginstance2'] = 'Вы выбрали это изображение более, чем один раз в качестве правильного ответа для drop-зоны, но он не помечен отметкой множества.'; -$string['formerror_noimageselected'] = 'Вы должны выбрать перетаскиваемый элемент в качестве правильного ответа для drop-зоны.'; -$string['formerror_nobgimage'] = 'Вы должны выбрать изображение для использования в качестве фона для области перетаскивания.'; -$string['infinite'] = 'множество'; -$string['label'] = 'Текст'; -$string['nolabel'] = 'Нет метки текста'; -$string['pleasedraganimagetoeachdropregion'] = 'Ваш ответ не полный. Пожалуйста, перетащите каждый элемент в соответствующую область.'; -$string['pluginname'] = 'Перетащи и оставь (с изображением)'; -$string['pluginname_help'] = 'Выберите файл (фоновое изображение), выберите перетаскиваемое изображение или текст и определите drop-зоны (области, в которые необходимо переместить элементы).'; -$string['pluginname_link'] = 'question/type/ddimageortext'; -$string['pluginnameadding'] = 'Добавить вопрос типа "Перетащи и оставь (с изображением)"'; -$string['pluginnameediting'] = 'Редактировать вопрос типа "Перетащи и оставь (с изображением)"'; -$string['pluginnamesummary'] = 'Изображение или текст необходимо перетащить внутрь drop-зон на фоновом изображении.'; -$string['previewarea'] = 'Превью -'; -$string['previewareaheader'] = 'Превью'; -$string['previewareamessage'] = 'Выберите файл (фоновое изображение), выберите перетаскиваемое изображение или запишите текст. -Затем определите перетаскиваемые элементы для каждой drop-зоны - области, в которые студенту необходимо переместить элементы.'; -$string['refresh'] = 'Обновить превью'; -$string['shuffleimages'] = 'Перемешивать перетаскиваемые элементы при каждой попытке'; -$string['summarisechoice'] = '{$a->no}. {$a->text}'; -$string['summariseplace'] = '{$a->no}. {$a->text}'; -$string['summarisechoiceno'] = 'Элемент {$a}'; -$string['summariseplaceno'] = 'Drop-зона {$a}'; -$string['xleft'] = 'слева'; -$string['ytop'] = 'сверху'; From 81c87fa76dcfc7fbde0db1773f2d43d4d10b9b5f Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 14 Mar 2013 14:22:59 +0000 Subject: [PATCH 178/208] MDL-47494 ddimageortext: Fix codechecker and jshint issues. --- ...ackup_qtype_ddimageortext_plugin.class.php | 15 +++--- ...store_qtype_ddimageortext_plugin.class.php | 49 +++++++++--------- .../ddimageortext/edit_ddimageortext_form.php | 30 +++++------ .../edit_ddtoimage_form_base.php | 2 +- question/type/ddimageortext/questiontype.php | 4 +- question/type/ddimageortext/yui/dd/dd.js | 51 +++++++++---------- question/type/ddimageortext/yui/form/form.js | 46 ++++++++--------- 7 files changed, 95 insertions(+), 102 deletions(-) diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php index 929a2269aa9..e328408352a 100644 --- a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php @@ -15,19 +15,18 @@ // along with Moodle. If not, see . /** - * @package moodlecore - * @subpackage backup-moodle2 - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype_ddimageortext + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** - * Provides the information to backup ddimageortext questions + * Provides the information to backup ddimageortext questions. * - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class backup_qtype_ddimageortext_plugin extends backup_qtype_plugin { @@ -36,7 +35,7 @@ class backup_qtype_ddimageortext_plugin extends backup_qtype_plugin { } /** - * Returns the qtype information to attach to question element + * Returns the qtype information to attach to question element. */ protected function define_question_plugin_structure() { $qtype = self::qtype_name(); diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php index f6ea4fdbf7d..b4e8d8943cf 100644 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php @@ -15,20 +15,19 @@ // along with Moodle. If not, see . /** - * @package moodlecore - * @subpackage backup-moodle2 - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype_ddimageortext + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * restore plugin class that provides the necessary information - * needed to restore one ddimageortext qtype plugin + * needed to restore one ddimageortext qtype plugin. * - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class restore_qtype_ddimageortext_plugin extends restore_qtype_plugin { @@ -37,13 +36,13 @@ class restore_qtype_ddimageortext_plugin extends restore_qtype_plugin { } /** - * Returns the paths to be handled by the plugin at question level + * Returns the paths to be handled by the plugin at question level. */ protected function define_question_plugin_structure() { $paths = array(); - // Add own qtype stuff + // Add own qtype stuff. $elename = 'dds'; $elepath = $this->get_pathfor('/'.self::qtype_name()); $paths[] = new restore_path_element($elename, $elepath); @@ -56,11 +55,11 @@ class restore_qtype_ddimageortext_plugin extends restore_qtype_plugin { $elepath = $this->get_pathfor('/drops/drop'); $paths[] = new restore_path_element($elename, $elepath); - return $paths; // And we return the interesting paths + return $paths; // And we return the interesting paths. } /** - * Process the qtype/{qtypename} element + * Process the qtype/{qtypename} element. */ public function process_dds($data) { global $DB; @@ -70,25 +69,25 @@ class restore_qtype_ddimageortext_plugin extends restore_qtype_plugin { $data = (object)$data; $oldid = $data->id; - // Detect if the question is created or mapped + // Detect if the question is created or mapped. $oldquestionid = $this->get_old_parentid('question'); $newquestionid = $this->get_new_parentid('question'); $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; // If the question has been created by restore, - // we need to create its qtype_ddimageortext too + // we need to create its qtype_ddimageortext too. if ($questioncreated) { - // Adjust some columns + // Adjust some columns. $data->questionid = $newquestionid; - // Insert record + // Insert record. $newitemid = $DB->insert_record($prefix, $data); - // Create mapping (needed for decoding links) + // Create mapping (needed for decoding links). $this->set_mapping($prefix, $oldid, $newitemid); } } /** - * Process the qtype/drags/drag element + * Process the qtype/drags/drag element. */ public function process_drag($data) { global $DB; @@ -98,23 +97,23 @@ class restore_qtype_ddimageortext_plugin extends restore_qtype_plugin { $data = (object)$data; $oldid = $data->id; - // Detect if the question is created or mapped + // Detect if the question is created or mapped. $oldquestionid = $this->get_old_parentid('question'); $newquestionid = $this->get_new_parentid('question'); $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; if ($questioncreated) { $data->questionid = $newquestionid; - // Insert record + // Insert record. $newitemid = $DB->insert_record("{$prefix}_drags", $data); - // Create mapping (there are files and states based on this) + // Create mapping (there are files and states based on this). $this->set_mapping("{$prefix}_drags", $oldid, $newitemid); } } /** - * Process the qtype/drags/drag element + * Process the qtype/drags/drag element. */ public function process_drop($data) { global $DB; @@ -124,21 +123,21 @@ class restore_qtype_ddimageortext_plugin extends restore_qtype_plugin { $data = (object)$data; $oldid = $data->id; - // Detect if the question is created or mapped + // Detect if the question is created or mapped. $oldquestionid = $this->get_old_parentid('question'); $newquestionid = $this->get_new_parentid('question'); $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; if ($questioncreated) { $data->questionid = $newquestionid; - // Insert record + // Insert record. $newitemid = $DB->insert_record("{$prefix}_drops", $data); - // Create mapping (there are files and states based on this) + // Create mapping (there are files and states based on this). $this->set_mapping("{$prefix}_drops", $oldid, $newitemid); } } /** - * Return the contents of this qtype to be processed by the links decoder + * Return the contents of this qtype to be processed by the links decoder. */ public static function define_decode_contents() { diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 1e868fee2f0..1f82049ad26 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -14,24 +14,25 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -require_once($CFG->dirroot.'/question/type/ddimageortext/edit_ddtoimage_form_base.php'); /** * Defines the editing form for the drag-and-drop images onto images question type. * - * @package qtype - * @subpackage ddimageortext - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype_ddimageortext + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); +require_once($CFG->dirroot . '/question/type/ddimageortext/edit_ddtoimage_form_base.php'); + + /** * Drag-and-drop images onto images editing form definition. * - * @copyright 2009 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2009 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { @@ -44,7 +45,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $question = $this->data_preprocessing_combined_feedback($question, true); $question = $this->data_preprocessing_hints($question, true, true); - $dragids = array(); // drag no -> dragid + $dragids = array(); // Drag no -> dragid. if (!empty($question->options)) { $question->shuffleanswers = $question->options->shuffleanswers; $question->drags = array(); @@ -65,7 +66,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $question->drops[$drop->no -1]['ytop'] = $drop->ytop; } } - //initialise file picker for bgimage + // Initialise file picker for bgimage. $draftitemid = file_get_submitted_draft_itemid('bgimage'); file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', @@ -73,12 +74,12 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { self::file_picker_options()); $question->bgimage = $draftitemid; - //initialise file picker for dragimages + // Initialise file picker for dragimages. list(, $imagerepeats) = $this->get_drag_item_repeats(); $draftitemids = optional_param_array('dragitem', array(), PARAM_INT); for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; - //numbers not allowed in filearea name + // Numbers not allowed in filearea name. $itemid = isset($dragids[$imageindex]) ? $dragids[$imageindex] : null; file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', 'dragimage', $itemid, self::file_picker_options()); @@ -124,7 +125,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { array($params)); } - //drag items + // Drag items. protected function definition_draggable_items($mform, $itemrepeatsatstart) { @@ -176,7 +177,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { return $repeatedoptions; } - //drop zones + // Drop zones. protected function drop_zone($mform, $imagerepeats) { $dropzoneitem = array(); @@ -223,7 +224,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { return $repeatedoptions; } - public function validation($data, $files) { + public function validation($data, $files) { $errors = parent::validation($data, $files); if (!self::file_uploaded($data['bgimage'])) { $errors["bgimage"] = get_string('formerror_nobgimage', 'qtype_'.$this->qtype()); @@ -289,5 +290,4 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { } return $errors; } - } diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php index 335840fe5ee..d834aa9ea36 100644 --- a/question/type/ddimageortext/edit_ddtoimage_form_base.php +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -71,7 +71,7 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { get_string('shuffleimages', 'qtype_'.$this->qtype())); $mform->setDefault('shuffleanswers', 0); $mform->closeHeaderBefore('shuffleanswers'); - //add the draggable image fields to the form + // Add the draggable image fields to the form. $this->definition_draggable_items($mform, $itemrepeatsatstart); $this->add_combined_feedback_fields(true); diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 787530fa3f0..e848a9547b6 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -89,7 +89,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $DB->insert_record('qtype_ddimageortext_drops', $drop); } - //an array of drag no -> drag id + // An array of drag no -> drag id. $olddragids = $DB->get_records_menu('qtype_ddimageortext_drags', array('questionid' => $formdata->id), '', 'no, id'); @@ -121,7 +121,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { 'qtype_ddimageortext', 'dragimage', $drag->id, array('subdirs' => 0, 'maxbytes' => 0, 'maxfiles' => 1)); } else { - //delete any existing files for draggable text item type + // Delete any existing files for draggable text item type. $fs = get_file_storage(); $fs->delete_area_files($formdata->context->id, 'qtype_ddimageortext', 'dragimage', $drag->id); diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index e8fe20c907e..0d5177809b2 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -2,7 +2,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { var DDIMAGEORTEXTDDNAME = 'ddimageortext_dd'; var DDIMAGEORTEXT_DD = function() { DDIMAGEORTEXT_DD.superclass.constructor.apply(this, arguments); - } + }; /** * This is the base class for the question rendering and question editing form code. */ @@ -120,8 +120,8 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { var classes = node.getAttribute('class'); if (classes !== '') { var classesarr = classes.split(' '); - for (index in classesarr) { - var patt1 = new RegExp('^'+prefix+'([0-9])+$'); + for (var index = 0; index < classesarr.length; index++) { + var patt1 = new RegExp('^' + prefix + '([0-9])+$'); if (patt1.test(classesarr[index])) { var patt2 = new RegExp('([0-9])+$'); var match = patt2.exec(classesarr[index]); @@ -149,7 +149,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { return drag; }, draggable_for_question : function (drag, group, choice) { - var dd = new Y.DD.Drag({ + new Y.DD.Drag({ node: drag, dragMode: 'point', groups: [group] @@ -168,7 +168,6 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { var dragnode = e.target.get('node'); var draginstanceno = dragnode.getData('draginstanceno'); var gooddrop = dragnode.getData('gooddrop'); - var endxy; if (!gooddrop) { mainobj.reset_drag_xy(draginstanceno); @@ -183,7 +182,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { } - } + }; }, update_padding_sizes_all : function () { @@ -233,7 +232,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { * This is the code for question rendering. */ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { - initializer : function(params) { + initializer : function() { this.doc = this.doc_structure(this); this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); this.doc.bg_img().after('load', this.poll_for_image_load, this, @@ -250,7 +249,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { var dragitemno = +this.doc.get_classname_numeric_suffix(dragitemhome, 'dragitemhomes'); var choice = +this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); - var group = +this.doc.get_classname_numeric_suffix(dragitemhome, 'group') + var group = +this.doc.get_classname_numeric_suffix(dragitemhome, 'group'); var groupsize = this.doc.drop_zone_group(group).size(); var dragnode = this.doc.clone_new_drag_item(i, dragitemno); i++; @@ -275,8 +274,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { this.doc.drop_zones().each( function(v){ v.on('dragchange', this.drop_zone_key_press, this); - } - , this); + }, this); } }, drop_zone_key_press : function (e) { @@ -304,7 +302,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { var next; var current = this.current_drag_in_drop(drop); if ('' === current) { - if (direction == 1) { + if (direction === 1) { next = 1; } else { next = 1; @@ -381,22 +379,20 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { }, get_choices_for_drop : function(choice, drop) { var group = drop.getData('group'); - var dragitem = null; - var dragitems = this.doc.top_node() - .all('div.dragitemgroup'+group+' .choice'+choice+'.drag'); - return dragitems; + return this.doc.top_node().all( + 'div.dragitemgroup' + group + ' .choice' + choice + '.drag'); }, get_unplaced_choice_for_drop : function(choice, drop) { var dragitems = this.get_choices_for_drop(choice, drop); var dragitem = null; - if (dragitems.some(function (d) { + dragitems.some(function (d) { if (!d.hasClass('placed') && !d.hasClass('yui3-dd-dragging')) { dragitem = d; return true; } else { return false; } - })); + }); return dragitem; }, init_drops : function () { @@ -407,7 +403,14 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { dropareas.append(groupnode); groupnodes[groupno] = groupnode; } - for (var dropno in this.get('drops')){ + var drop_hit_handler = function(e) { + var drag = e.drag.get('node'); + var drop = e.drop.get('node'); + if (+drop.getData('group') === drag.getData('group')){ + this.place_drag_in_drop(drag, drop); + } + }; + for (var dropno in this.get('drops')) { var drop = this.get('drops')[dropno]; var nodeclass = 'dropzone group'+drop.group+' place'+dropno; var title = drop.text.replace('"', '\"'); @@ -421,14 +424,8 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { dropnode.setData('group', drop.group); var dropdd = new Y.DD.Drop({ node: dropnode, groups : [drop.group]}); - dropdd.on('drop:hit', function(e) { - var drag = e.drag.get('node'); - var drop = e.drop.get('node'); - if (+drop.getData('group') === drag.getData('group')){ - this.place_drag_in_drop(drag, drop); - } - }, this); - }; + dropdd.on('drop:hit', drop_hit_handler, this); + } } }, {NAME : DDIMAGEORTEXTQUESTIONNAME, ATTRS : {}}); @@ -462,7 +459,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { }); M.qtype_ddimageortext.init_question = function(config) { return new DDIMAGEORTEXT_QUESTION(config); - } + }; }, '@VERSION@', { requires:['node', 'dd', 'dd-drop', 'dd-constrain'] }); diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 05ba3ef07b3..46808cba954 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -9,7 +9,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { fp : null, - initializer : function(params) { + initializer : function() { this.fp = this.file_pickers(); Y.one(this.get('topnode')).append('
'+ '
'+ @@ -76,11 +76,9 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, load_drag_home : function (dragitemno) { + var url = null; if ('image' === this.form.get_form_value('dragitemtype', [dragitemno])) { - var url = - this.fp.file(this.form.to_name_with_index('dragitem', [dragitemno])).href; - } else { - var url = null; + url = this.fp.file(this.form.to_name_with_index('dragitem', [dragitemno])).href; } this.doc.add_or_update_drag_item_home(dragitemno, url, this.form.get_form_value('drags', [dragitemno, 'draglabel']), @@ -106,12 +104,12 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); if ('image' === this.form.get_form_value('dragitemtype', [i]) && file.name !== null) { - dragitemsoptions[i+1] = (i+1)+'. '+label+' ('+file.name+')'; - } else if (label != '') { - dragitemsoptions[i+1] = (i+1)+'. '+label; + dragitemsoptions[i + 1] = (i + 1) + '. ' + label + ' (' + file.name + ')'; + } else if (label !== '') { + dragitemsoptions[i + 1] = (i + 1) + '. ' + label; } } - for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { + for (i = 0; i < this.form.get_form_value('nodropzone', []); i++) { var selector = Y.one('#id_drops_'+i+'_choice'); var selectedvalue = selector.get('value'); selector.all('option').remove(true); @@ -121,7 +119,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { + dragitemsoptions[value] + ''; selector.append(option); - var optionnode = selector.one('option[value="' + value + '"]') + var optionnode = selector.one('option[value="' + value + '"]'); if (value === +selectedvalue) { optionnode.set('selected', true); } else { @@ -132,7 +130,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { var infinite = cbel.get('checked'); if (!infinite) { Y.all('fieldset#dropzoneheader select').some(function (selector) { - if (+selector.get('value') == value){ + if (+selector.get('value') === value) { optionnode.set('disabled', true); return true; // stop looping } @@ -153,7 +151,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { //events triggered by changes to form data //x and y coordinates - Y.all('fieldset#dropzoneheader input').on('blur', function (e){ + Y.all('fieldset#dropzoneheader input').on('blur', function (e) { var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), @@ -164,7 +162,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, this); //change in selected item - Y.all('fieldset#dropzoneheader select').on('change', function (e){ + Y.all('fieldset#dropzoneheader select').on('change', function (e) { var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; var old = this.doc.drag_item(draginstanceno); @@ -176,13 +174,13 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { for (var i=0; i < this.form.get_form_value('noitems', []); i++) { //change to group selector - Y.all('fieldset#draggableitemheader_'+i+' select.draggroup') - .on('change', function (e){ + Y.all('fieldset#draggableitemheader_'+i+' select.draggroup').on( + 'change', function () { this.doc.drag_items().remove(true); this.draw_dd_area(); }, this); - Y.all('fieldset#draggableitemheader_'+i+' select.dragitemtype') - .on('change', function (e){ + Y.all('fieldset#draggableitemheader_' + i + ' select.dragitemtype').on( + 'change', function () { this.doc.drag_items().remove(true); this.draw_dd_area(); }, this); @@ -193,7 +191,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { .on('change', this.set_options_for_drag_item_selectors, this); } //event on file picker new file selection - Y.after(function (e){ + Y.after(function (e) { var name = this.fp.name(e.id); if (name !== 'bgimage') { this.doc.drag_items().remove(true); @@ -226,7 +224,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { if (null !== drag && !drag.hasClass('yui3-dd-dragging')) { var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; - if (fromform[0] == '' && fromform[1] == '') { + if (fromform[0] === '' && fromform[1] === '') { var dragitemno = drag.getData('dragitemno'); drag.setXY(this.doc.drag_item_home(dragitemno).getXY()); } else { @@ -273,7 +271,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, get_el : function (name, indexes) { var form = document.getElementById('mform1'); - return form.elements[this.to_name_with_index(name, indexes)] + return form.elements[this.to_name_with_index(name, indexes)]; }, get_form_value : function(name, indexes) { var el = this.get_el(name, indexes); @@ -312,7 +310,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { draftitemidstoname = {}; nametoparentnode = {}; var filepickers = Y.all('form.mform input.filepickerhidden'); - filepickers.each(function(filepicker, k, items) { + filepickers.each(function(filepicker) { draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); }, this); @@ -330,14 +328,14 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { name : function (draftitemid) { return draftitemidstoname[draftitemid]; } - } + }; return toreturn; } }, {NAME : DDIMAGEORTEXTFORMNAME, ATTRS : {maxsizes:{value:null}}}); M.qtype_ddimageortext = M.qtype_ddimageortext || {}; M.qtype_ddimageortext.init_form = function(config) { return new DDIMAGEORTEXT_FORM(config); - } + }; }, '@VERSION@', { requires:['moodle-qtype_ddimageortext-dd', 'form_filepicker'] -}); \ No newline at end of file +}); From a214a28fd14ad2449196a3be0e3c28cf474213fa Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 14 Mar 2013 14:23:07 +0000 Subject: [PATCH 179/208] MDL-47494 ddimageortext: Bump version number. --- question/type/ddimageortext/README.txt | 5 ++--- question/type/ddimageortext/version.php | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index 8f83649867b..0f4109b189c 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -9,10 +9,9 @@ to be installed in order to work. This question type was written by Jamie Pratt (http://jamiep.org/). -This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or -2.2+ (master branch). +This question type is compatible with Moodle 2.3+. -To install using git for a 2.2+ Moodle installation, type this command in the +To install using git for a 2.3+ Moodle installation, type this command in the root of your Moodle install: git clone git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 353ff7afbf5..a7ce5c88b9c 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -25,13 +25,13 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2012081600; +$plugin->version = 2013031400; $plugin->requires = 2012062500; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.1 for Moodle 2.3+'; +$plugin->release = '1.2 for Moodle 2.3+'; $plugin->dependencies = array( - 'qtype_gapselect' => 2011020100, + 'qtype_gapselect' => 2013031400, ); From 4139151f7530a1256e557c8a303f3ba7e66da971 Mon Sep 17 00:00:00 2001 From: Colin Chambers Date: Fri, 26 Apr 2013 16:13:42 +0100 Subject: [PATCH 180/208] MDL-47494 ddimageortext: Update OU Qtype ddimageortext for simplified forms #6614 --- .../ddimageortext/edit_ddimageortext_form.php | 66 +++++++++--------- .../edit_ddtoimage_form_base.php | 23 +++---- .../lang/en/qtype_ddimageortext.php | 5 +- question/type/ddimageortext/questiontype.php | 13 ++-- question/type/ddimageortext/styles.css | 67 ++++++++++++++----- question/type/ddimageortext/version.php | 8 +-- question/type/ddimageortext/yui/form/form.js | 33 +++++---- 7 files changed, 119 insertions(+), 96 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 1f82049ad26..83c1c437418 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -52,7 +52,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { foreach ($question->options->drags as $drag) { $dragindex = $drag->no -1; $question->drags[$dragindex] = array(); - $question->drags[$dragindex]['draglabel'] = $drag->label; + $question->draglabel[$dragindex] = $drag->label; $question->drags[$dragindex]['infinite'] = $drag->infinite; $question->drags[$dragindex]['draggroup'] = $drag->draggroup; $dragids[$dragindex] = $drag->id; @@ -93,11 +93,11 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { } else { $fileexists = self::file_uploaded($question->dragitem[$dragindex]); } - $labelexists = (trim($question->drags[$dragindex]['draglabel']) != ''); + $labelexists = (trim($question->draglabel[$dragindex]) != ''); if ($labelexists && !$fileexists) { - $question->dragitemtype[$dragindex] = 'word'; + $question->drags[$dragindex]['dragitemtype'] = 'word'; } else { - $question->dragitemtype[$dragindex] = 'image'; + $question->drags[$dragindex]['dragitemtype'] = 'image'; } } } @@ -118,7 +118,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $maxsizes->dragimage->height = QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT; $params = array('maxsizes' => $maxsizes, - 'topnode' => 'fieldset#previewareaheader'); + 'topnode' => 'fieldset#id_previewareaheader'); $PAGE->requires->yui_module('moodle-qtype_ddimageortext-form', 'M.qtype_ddimageortext.init_form', @@ -128,38 +128,31 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { // Drag items. protected function definition_draggable_items($mform, $itemrepeatsatstart) { - + $mform->addElement('header', 'draggableitemheader', + get_string('draggableitems', 'qtype_ddimageortext')); + $mform->addElement('advcheckbox', 'shuffleanswers', ' ', + get_string('shuffleimages', 'qtype_'.$this->qtype())); + $mform->setDefault('shuffleanswers', 0); $this->repeat_elements($this->draggable_item($mform), $itemrepeatsatstart, $this->draggable_items_repeated_options(), 'noitems', 'additems', self::ADD_NUM_ITEMS, - get_string('addmoreimages', 'qtype_ddimageortext')); + get_string('addmoreimages', 'qtype_ddimageortext'), true); } protected function draggable_item($mform) { $draggableimageitem = array(); - $draggableimageitem[] = $mform->createElement('header', 'draggableitemheader', - get_string('draggableitemheader', 'qtype_ddimageortext', '{no}')); + $grouparray = array(); $dragitemtypes = array('image' => get_string('draggableimage', 'qtype_ddimageortext'), 'word' => get_string('draggableword', 'qtype_ddimageortext')); - $draggableimageitem[] = $mform->createElement('select', 'dragitemtype', + $grouparray[] = $mform->createElement('select', 'dragitemtype', get_string('draggableitemtype', 'qtype_ddimageortext'), $dragitemtypes, array('class' => 'dragitemtype')); - $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null, - self::file_picker_options()); - - $grouparray = array(); - $grouparray[] = $mform->createElement('text', 'draglabel', - get_string('label', 'qtype_ddimageortext'), - array('size'=>30, 'class'=>'tweakcss')); - $mform->setType('draglabel', PARAM_NOTAGS); $options = array(); for ($i = 1; $i <= self::MAX_GROUPS; $i += 1) { $options[$i] = $i; } - $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('group', 'qtype_gapselect').' '); $grouparray[] = $mform->createElement('select', 'draggroup', get_string('group', 'qtype_gapselect'), $options, @@ -167,7 +160,15 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ', get_string('infinite', 'qtype_ddimageortext')); $draggableimageitem[] = $mform->createElement('group', 'drags', - get_string('label', 'qtype_ddimageortext'), $grouparray); + get_string('draggableitemheader', 'qtype_ddimageortext', '{no}'), $grouparray); + + $draggableimageitem[] = $mform->createElement('filepicker', 'dragitem', '', null, + self::file_picker_options()); + + $draggableimageitem[] = $mform->createElement('text', 'draglabel', + get_string('label', 'qtype_ddimageortext'), + array('size'=>30, 'class'=>'tweakcss')); + $mform->setType('draglabel', PARAM_NOTAGS); return $draggableimageitem; } @@ -183,30 +184,20 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $dropzoneitem = array(); $grouparray = array(); - $grouparray[] = $mform->createElement('static', 'xleftlabel', '', - ' '.get_string('xleft', 'qtype_ddimageortext').' '); $grouparray[] = $mform->createElement('text', 'xleft', get_string('xleft', 'qtype_ddimageortext'), array('size'=>5, 'class'=>'tweakcss')); - $mform->setType('xleft', PARAM_NOTAGS); - $grouparray[] = $mform->createElement('static', 'ytoplabel', '', - ' '.get_string('ytop', 'qtype_ddimageortext').' '); $grouparray[] = $mform->createElement('text', 'ytop', get_string('ytop', 'qtype_ddimageortext'), array('size'=>5, 'class'=>'tweakcss')); - $mform->setType('ytop', PARAM_NOTAGS); $options = array(); $options[0] = ''; for ($i = 1; $i <= $imagerepeats; $i += 1) { $options[$i] = $i; } - $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('draggableitem', 'qtype_ddimageortext').' '); $grouparray[] = $mform->createElement('select', 'choice', get_string('draggableitem', 'qtype_ddimageortext'), $options); - $grouparray[] = $mform->createElement('static', '', '', ' ' . - get_string('label', 'qtype_ddimageortext').' '); $grouparray[] = $mform->createElement('text', 'droplabel', get_string('label', 'qtype_ddimageortext'), array('size'=>10, 'class'=>'tweakcss')); @@ -218,8 +209,11 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { protected function drop_zones_repeated_options() { $repeatedoptions = array(); - $repeatedoptions['xleft']['type'] = PARAM_INT; - $repeatedoptions['ytop']['type'] = PARAM_INT; + // The next two are PARAM_RAW becuase we need to distinguish 0 and ''. + // We do the necessary validation in the validation method. + $repeatedoptions['drops[xleft]']['type'] = PARAM_RAW; + $repeatedoptions['drops[ytop]']['type'] = PARAM_RAW; + $repeatedoptions['drops[droplabel]']['type'] = PARAM_TEXT; $repeatedoptions['choice']['default'] = '0'; return $repeatedoptions; } @@ -252,7 +246,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $errors["drops[$i]"] = get_string('formerror_notintxleft', 'qtype_ddimageortext'); } - if ($data['dragitemtype'][$choice - 1] != 'word' && + if ($data['drags'][$choice - 1]['dragitemtype'] != 'word' && !self::file_uploaded($data['dragitem'][$choice - 1])) { $errors['dragitem['.($choice - 1).']'] = get_string('formerror_nofile', 'qtype_ddimageortext', $i); @@ -275,8 +269,8 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { } } for ($dragindex=0; $dragindex < $data['noitems']; $dragindex++) { - $label = $data['drags'][$dragindex]['draglabel']; - if ($data['dragitemtype'][$dragindex] == 'word') { + $label = $data['draglabel'][$dragindex]; + if ($data['drags'][$dragindex]['dragitemtype'] == 'word') { $allowedtags = '
'; $errormessage = get_string('formerror_disallowedtags', 'qtype_ddimageortext'); } else { diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php index d834aa9ea36..099ec22a5aa 100644 --- a/question/type/ddimageortext/edit_ddtoimage_form_base.php +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -63,14 +63,13 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { $mform->registerNoSubmitButton('refresh'); $mform->addElement('submit', 'refresh', get_string('refresh', 'qtype_'.$this->qtype())); - $mform->closeHeaderBefore('refresh'); + $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_'.$this->qtype()), + null, self::file_picker_options()); + $mform->closeHeaderBefore('dropzoneheader'); list($itemrepeatsatstart, $imagerepeats) = $this->get_drag_item_repeats(); $this->definition_drop_zones($mform, $imagerepeats); - $mform->addElement('advcheckbox', 'shuffleanswers', ' ', - get_string('shuffleimages', 'qtype_'.$this->qtype())); - $mform->setDefault('shuffleanswers', 0); - $mform->closeHeaderBefore('shuffleanswers'); + // Add the draggable image fields to the form. $this->definition_draggable_items($mform, $itemrepeatsatstart); @@ -82,21 +81,17 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { $mform->addElement('header', 'dropzoneheader', get_string('dropzoneheader', 'qtype_'.$this->qtype())); - $mform->addElement('filepicker', 'bgimage', get_string('bgimage', 'qtype_'.$this->qtype()), - null, self::file_picker_options()); - $countdropzones = 0; if (isset($this->question->id)) { foreach ($this->question->options->drops as $drop) { $countdropzones = max($countdropzones, $drop->no); } } - if ($this->question->formoptions->repeatelements) { - $dropzonerepeatsatstart = max(self::START_NUM_ITEMS, - $countdropzones + self::ADD_NUM_ITEMS); - } else { - $dropzonerepeatsatstart = $countdropzones; + + if (!$countdropzones) { + $countdropzones = self::START_NUM_ITEMS; } + $dropzonerepeatsatstart = $countdropzones; $this->repeat_elements($this->drop_zone($mform, $imagerepeats), $dropzonerepeatsatstart, $this->drop_zones_repeated_options(), @@ -107,7 +102,7 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { abstract protected function drop_zones_repeated_options(); - abstract protected function definition_draggable_items($mform, $itemrepeatsatstart); + abstract protected function definition_draggable_items($mform, $itemrepeatsatstart) ; abstract protected function draggable_item($mform); diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index 1ca222417ee..1ee1492e5aa 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -29,6 +29,7 @@ $string['bgimage'] = 'Background image'; $string['correctansweris'] = 'The correct answer is: {$a}'; $string['draggableimage'] = 'Draggable image'; $string['draggableitem'] = 'Draggable item'; +$string['draggableitems'] = 'Draggable items'; $string['draggableitemheader'] = 'Draggable item {$a}'; $string['draggableitemtype'] = 'Type'; $string['draggableword'] = 'Draggable text'; @@ -57,8 +58,8 @@ $string['pluginname_link'] = 'question/type/ddimageortext'; $string['pluginnameadding'] = 'Adding drag and drop onto image'; $string['pluginnameediting'] = 'Editing drag and drop onto image'; $string['pluginnamesummary'] = 'Images or text labels are dragged and dropped into drop zones on a background image.'; -$string['previewarea'] = 'Preview area -'; -$string['previewareaheader'] = 'Preview'; +$string['previewarea'] = ''; +$string['previewareaheader'] = 'Background image'; $string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; $string['refresh'] = 'Refresh preview'; $string['shuffleimages'] = 'Shuffle drag items each time question is attempted'; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index e848a9547b6..83c75a1f9ab 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -95,7 +95,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { '', 'no, id'); foreach (array_keys($formdata->drags) as $dragno) { $info = file_get_draft_area_info($formdata->dragitem[$dragno]); - if ($info['filecount'] > 0 || (trim($formdata->drags[$dragno]['draglabel'])!='')) { + if ($info['filecount'] > 0 || (trim($formdata->draglabel[$dragno])!='')) { $draftitemid = $formdata->dragitem[$dragno]; $drag = new stdClass(); @@ -103,7 +103,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $drag->no = $dragno + 1; $drag->draggroup = $formdata->drags[$dragno]['draggroup']; $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; - $drag->label = $formdata->drags[$dragno]['draglabel']; + $drag->label = $formdata->draglabel[$dragno]; if (isset($olddragids[$dragno +1])) { $drag->id = $olddragids[$dragno +1]; @@ -113,7 +113,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $drag->id = $DB->insert_record('qtype_ddimageortext_drags', $drag); } - if ($formdata->dragitemtype[$dragno] == 'image') { + if ($formdata->drags[$dragno]['dragitemtype'] == 'image') { self::constrain_image_size_in_draft_area($draftitemid, QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXWIDTH, QTYPE_DDIMAGEORTEXT_DRAGIMAGE_MAXHEIGHT); @@ -130,6 +130,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { } } + if (!empty($olddragids)) { list($sql, $params) = $DB->get_in_or_equal(array_values($olddragids)); $DB->delete_records_select('qtype_ddimageortext_drags', "id $sql", $params); @@ -243,7 +244,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0); $dragindex = $dragno -1; $question->drags[$dragindex] = array(); - $question->drags[$dragindex]['draglabel'] = + $question->draglabel[$dragindex] = $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); $question->drags[$dragindex]['infinite'] = array_key_exists('infinite', $dragxml['#']); $question->drags[$dragindex]['draggroup'] = @@ -252,9 +253,9 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $question->dragitem[$dragindex] = $this->import_files_to_draft_file_area($format, $filexml); if (count($filexml)) { - $question->dragitemtype[$dragindex] = 'image'; + $question->drags[$dragindex]['dragitemtype'] = 'image'; } else { - $question->dragitemtype[$dragindex] = 'word'; + $question->drags[$dragindex]['dragitemtype'] = 'word'; } } diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 27cf612e019..0ee6b36d224 100644 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -3,17 +3,17 @@ display: block; } -.que.ddimageortext div.droparea img, form.mform fieldset#previewareaheader div.droparea img { +.que.ddimageortext div.droparea img, form.mform fieldset#id_previewareaheader div.droparea img { border: 1px solid #000000; } -.que.ddimageortext .draghome, form.mform fieldset#previewareaheader .draghome { +.que.ddimageortext .draghome, form.mform fieldset#id_previewareaheader .draghome { vertical-align: top; margin: 5px; visibility : hidden; } -.que.ddimageortext div.draghome, form.mform fieldset#previewareaheader div.draghome { +.que.ddimageortext div.draghome, form.mform fieldset#id_previewareaheader div.draghome { border: 1px solid black; cursor: move; background-color: #B0C4DE; @@ -25,31 +25,31 @@ *display: inline; } -.que.ddimageortext .group1, form.mform fieldset#previewareaheader .group1 { +.que.ddimageortext .group1, form.mform fieldset#id_previewareaheader .group1 { background-color: #FFFFFF; } -.que.ddimageortext .group2, form.mform fieldset#previewareaheader .group2 { +.que.ddimageortext .group2, form.mform fieldset#id_previewareaheader .group2 { background-color: #B0C4DE; } -.que.ddimageortext .group3, form.mform fieldset#previewareaheader .group3 { +.que.ddimageortext .group3, form.mform fieldset#id_previewareaheader .group3 { background-color: #DCDCDC; } -.que.ddimageortext .group4, form.mform fieldset#previewareaheader .group4 { +.que.ddimageortext .group4, form.mform fieldset#id_previewareaheader .group4 { background-color: #D8BFD8; } -.que.ddimageortext .group5, form.mform fieldset#previewareaheader .group5 { +.que.ddimageortext .group5, form.mform fieldset#id_previewareaheader .group5 { background-color: #87CEFA; } -.que.ddimageortext .group6, form.mform fieldset#previewareaheader .group6 { +.que.ddimageortext .group6, form.mform fieldset#id_previewareaheader .group6 { background-color: #DAA520; } -.que.ddimageortext .group7, form.mform fieldset#previewareaheader .group7 { +.que.ddimageortext .group7, form.mform fieldset#id_previewareaheader .group7 { background-color: #FFD700; } -.que.ddimageortext .group8, form.mform fieldset#previewareaheader .group8 { +.que.ddimageortext .group8, form.mform fieldset#id_previewareaheader .group8 { background-color: #F0E68C; } -.que.ddimageortext .drag, form.mform fieldset#previewareaheader .drag { +.que.ddimageortext .drag, form.mform fieldset#id_previewareaheader .drag { border: 1px solid black; cursor: move; z-index: 2; @@ -57,10 +57,10 @@ .que.ddimageortext .dragitems.readonly .drag { cursor: auto; } -.que.ddimageortext div.ddarea, form.mform fieldset#previewareaheader div.ddarea { +.que.ddimageortext div.ddarea, form.mform fieldset#id_previewareaheader div.ddarea { text-align : center; } -.que.ddimageortext .dropbackground, form.mform fieldset#previewareaheader .dropbackground { +.que.ddimageortext .dropbackground, form.mform fieldset#id_previewareaheader .dropbackground { margin:0 auto; } .que.ddimageortext .dropzone { @@ -75,12 +75,12 @@ } .que.ddimageortext div.dragitems div.draghome, .que.ddimageortext div.dragitems div.drag, -form.mform fieldset#previewareaheader div.draghome, form.mform fieldset#previewareaheader div.drag { +form.mform fieldset#id_previewareaheader div.draghome, form.mform fieldset#id_previewareaheader div.drag { font:13px/1.231 arial,helvetica,clean,sans-serif; *font-size:small; /* for IE */ *font:x-small; /* for IE in quirks mode */ } -form.mform fieldset#previewareaheader div.drag.yui3-dd-dragging, +form.mform fieldset#id_previewareaheader div.drag.yui3-dd-dragging, .que.ddimageortext div.drag.yui3-dd-dragging { z-index: 3; -moz-box-shadow: 3px 3px 4px #000; @@ -91,3 +91,38 @@ form.mform fieldset#previewareaheader div.drag.yui3-dd-dragging, /* For IE 5.5 - 7 */ filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#000000'); } +/* Editing form. Style repeated elements*/ +/*Top*/ +body#page-question-type-ddimageortext div[id^=fgroup_id_][id*=drags_] { + background: #EEE; + margin-top: 0; + margin-bottom: 0; + padding-bottom: 5px; + padding-top: 5px; + border: 1px solid #BBB; + border-bottom: 0; +} +body#page-question-type-ddimageortext div[id^=fgroup_id_][id*=drags_] .fgrouplabel label { + font-weight: bold; +} +/* Middle */ +body#page-question-type-ddimageortext div[id^=fitem_id_][id*=dragitem_] { + background: #EEE; + margin-bottom: 0; + margin-top: 0; + padding-bottom: 5px; + padding-top: 5px; + border: 1px solid #BBB; + border-top: 0; + border-bottom: 0; +} +/* Bottom */ +body#page-question-type-ddimageortext div[id^=fitem_id_][id*=draglabel_] { + background: #EEE; + margin-bottom: 2em; + margin-top: 0; + padding-bottom: 5px; + padding-top: 5px; + border: 1px solid #BBB; + border-top: 0; +} diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index a7ce5c88b9c..939243ab4b2 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -25,13 +25,13 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2013031400; -$plugin->requires = 2012062500; +$plugin->version = 2013052000; +$plugin->requires = 2013051400; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.2 for Moodle 2.3+'; +$plugin->release = '1.3 for Moodle 2.5+'; $plugin->dependencies = array( - 'qtype_gapselect' => 2013031400, + 'qtype_gapselect' => 2013042900, ); diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 46808cba954..557f2902976 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -11,8 +11,8 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { initializer : function() { this.fp = this.file_pickers(); - Y.one(this.get('topnode')).append('
'+ - '
'+ + var tn = Y.one(this.get('topnode')); + tn.one('div.fcontainer').append('
'+ '
'); this.doc = this.doc_structure(this); this.draw_dd_area(); @@ -77,11 +77,11 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { load_drag_home : function (dragitemno) { var url = null; - if ('image' === this.form.get_form_value('dragitemtype', [dragitemno])) { + if ('image' === this.form.get_form_value('drags', [dragitemno, 'dragitemtype'])) { url = this.fp.file(this.form.to_name_with_index('dragitem', [dragitemno])).href; } this.doc.add_or_update_drag_item_home(dragitemno, url, - this.form.get_form_value('drags', [dragitemno, 'draglabel']), + this.form.get_form_value('draglabel', [dragitemno]), this.form.get_form_value('drags', [dragitemno, 'draggroup'])); }, @@ -100,9 +100,9 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { set_options_for_drag_item_selectors : function () { var dragitemsoptions = {0: ''}; for (var i=0; i < this.form.get_form_value('noitems', []); i++) { - var label = this.form.get_form_value('drags', [i, 'draglabel']); + var label = this.form.get_form_value('draglabel', [i]); var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); - if ('image' === this.form.get_form_value('dragitemtype', [i]) + if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype']) && file.name !== null) { dragitemsoptions[i + 1] = (i + 1) + '. ' + label + ' (' + file.name + ')'; } else if (label !== '') { @@ -124,12 +124,9 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { optionnode.set('selected', true); } else { if (value !== 0) { // no item option is always selectable - var cbselector = 'fieldset#draggableitemheader_'+(value-1) - +' input[type="checkbox"]'; - var cbel = Y.one(cbselector); - var infinite = cbel.get('checked'); - if (!infinite) { - Y.all('fieldset#dropzoneheader select').some(function (selector) { + var cbel = Y.one('#id_drags_'+(value-1)+'_infinite'); + if (cbel && !cbel.get('checked')) { + Y.all('fieldset#id_dropzoneheader select').some(function (selector) { if (+selector.get('value') === value) { optionnode.set('disabled', true); return true; // stop looping @@ -144,14 +141,14 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, stop_selector_events : function () { - Y.all('fieldset#dropzoneheader select').detachAll(); + Y.all('fieldset#id_dropzoneheader select').detachAll(); }, setup_form_events : function () { //events triggered by changes to form data //x and y coordinates - Y.all('fieldset#dropzoneheader input').on('blur', function (e) { + Y.all('fieldset#id_dropzoneheader input').on('blur', function (e) { var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), @@ -162,7 +159,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, this); //change in selected item - Y.all('fieldset#dropzoneheader select').on('change', function (e) { + Y.all('fieldset#id_dropzoneheader select').on('change', function (e) { var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; var old = this.doc.drag_item(draginstanceno); @@ -174,12 +171,12 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { for (var i=0; i < this.form.get_form_value('noitems', []); i++) { //change to group selector - Y.all('fieldset#draggableitemheader_'+i+' select.draggroup').on( + Y.all('#fgroup_id_drags_'+i+' select.draggroup').on( 'change', function () { this.doc.drag_items().remove(true); this.draw_dd_area(); }, this); - Y.all('fieldset#draggableitemheader_' + i + ' select.dragitemtype').on( + Y.all('#fgroup_id_drags_'+i+' select.dragitemtype').on( 'change', function () { this.doc.drag_items().remove(true); this.draw_dd_area(); @@ -202,7 +199,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { update_visibility_of_file_pickers : function() { for (var i=0; i < this.form.get_form_value('noitems', []); i++) { - if ('image' === this.form.get_form_value('dragitemtype', [i])) { + if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype'])) { Y.one('input#id_dragitem_'+i).get('parentNode').get('parentNode') .setStyle('display', 'block'); } else { From e9a2711b855ddc02001fb5effb418fe36816992c Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 22 May 2013 14:02:38 +0100 Subject: [PATCH 181/208] MDL-47494 ddimageortext: Final form improvement tweaks. #6614 --- .../ddimageortext/edit_ddimageortext_form.php | 2 +- .../ddimageortext/edit_ddtoimage_form_base.php | 17 +++++++++-------- .../lang/en/qtype_ddimageortext.php | 3 +-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 83c1c437418..adfe694fe73 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -131,7 +131,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $mform->addElement('header', 'draggableitemheader', get_string('draggableitems', 'qtype_ddimageortext')); $mform->addElement('advcheckbox', 'shuffleanswers', ' ', - get_string('shuffleimages', 'qtype_'.$this->qtype())); + get_string('shuffleimages', 'qtype_'.$this->qtype())); $mform->setDefault('shuffleanswers', 0); $this->repeat_elements($this->draggable_item($mform), $itemrepeatsatstart, $this->draggable_items_repeated_options(), diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php index 099ec22a5aa..c7ece0f71ee 100644 --- a/question/type/ddimageortext/edit_ddtoimage_form_base.php +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -51,14 +51,14 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { /** * definition_inner adds all specific fields to the form. - * @param object $mform (the form being built). + * @param MoodleQuickForm $mform (the form being built). */ protected function definition_inner($mform) { $mform->addElement('header', 'previewareaheader', get_string('previewareaheader', 'qtype_'.$this->qtype())); - $mform->addElement('static', 'previewarea', - get_string('previewarea', 'qtype_'.$this->qtype()), + $mform->setExpanded('previewareaheader'); + $mform->addElement('static', 'previewarea', '', get_string('previewareamessage', 'qtype_'.$this->qtype())); $mform->registerNoSubmitButton('refresh'); @@ -102,7 +102,7 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { abstract protected function drop_zones_repeated_options(); - abstract protected function definition_draggable_items($mform, $itemrepeatsatstart) ; + abstract protected function definition_draggable_items($mform, $itemrepeatsatstart); abstract protected function draggable_item($mform); @@ -115,11 +115,12 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { $countimages = max($countimages, $drag->no); } } - if ($this->question->formoptions->repeatelements) { - $itemrepeatsatstart = max(self::START_NUM_ITEMS, $countimages + self::ADD_NUM_ITEMS); - } else { - $itemrepeatsatstart = $countimages; + + if (!$countimages) { + $countimages = self::START_NUM_ITEMS; } + $itemrepeatsatstart = $countimages; + $imagerepeats = optional_param('noitems', $itemrepeatsatstart, PARAM_INT); $addfields = optional_param('additems', '', PARAM_TEXT); if (!empty($addfields)) { diff --git a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php index 1ee1492e5aa..a79053031db 100644 --- a/question/type/ddimageortext/lang/en/qtype_ddimageortext.php +++ b/question/type/ddimageortext/lang/en/qtype_ddimageortext.php @@ -58,8 +58,7 @@ $string['pluginname_link'] = 'question/type/ddimageortext'; $string['pluginnameadding'] = 'Adding drag and drop onto image'; $string['pluginnameediting'] = 'Editing drag and drop onto image'; $string['pluginnamesummary'] = 'Images or text labels are dragged and dropped into drop zones on a background image.'; -$string['previewarea'] = ''; -$string['previewareaheader'] = 'Background image'; +$string['previewareaheader'] = 'Preview'; $string['previewareamessage'] = 'Select a background image file and select draggable images or just enter text that will be made draggable. Then choose a drag item for each \'drop zone\', and drag the drag item to where the student should drag it to.'; $string['refresh'] = 'Refresh preview'; $string['shuffleimages'] = 'Shuffle drag items each time question is attempted'; From 09e43f0a688d64516705229db088b49698d94ca8 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 22 May 2013 14:05:26 +0100 Subject: [PATCH 182/208] MDL-47494 ddimageortext: Fix failing unit tests. --- .../ddimageortext/tests/walkthrough_test.php | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/question/type/ddimageortext/tests/walkthrough_test.php b/question/type/ddimageortext/tests/walkthrough_test.php index ce7f431960f..95adfaaf57e 100644 --- a/question/type/ddimageortext/tests/walkthrough_test.php +++ b/question/type/ddimageortext/tests/walkthrough_test.php @@ -396,9 +396,9 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p2', 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->quba->get_field_prefix($this->slot) . 'p3', 0), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', ''), + $this->quba->get_field_prefix($this->slot) . 'p4', 0), $this->get_does_not_contain_correctness_expectation(), $this->get_does_not_contain_feedback_expectation()); @@ -506,9 +506,9 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p2', 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->quba->get_field_prefix($this->slot) . 'p3', 0), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', ''), + $this->quba->get_field_prefix($this->slot) . 'p4', 0), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_try_again_button_expectation(), $this->get_does_not_contain_correctness_expectation(), @@ -560,9 +560,9 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', ''), + $this->quba->get_field_prefix($this->slot) . 'p2', 0), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->quba->get_field_prefix($this->slot) . 'p3', 0), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p4', 2), $this->get_contains_submit_button_expectation(true), @@ -786,13 +786,13 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_drag_image_home_expectation(1, 1, 2), $this->get_contains_drag_image_home_expectation(2, 2, 2), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p1', ''), + $this->quba->get_field_prefix($this->slot) . 'p1', 0), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p2', ''), + $this->quba->get_field_prefix($this->slot) . 'p2', 0), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p3', ''), + $this->quba->get_field_prefix($this->slot) . 'p3', 0), $this->get_contains_hidden_expectation( - $this->quba->get_field_prefix($this->slot) . 'p4', ''), + $this->quba->get_field_prefix($this->slot) . 'p4', 0), $this->get_contains_submit_button_expectation(true), $this->get_does_not_contain_feedback_expectation(), $this->get_tries_remaining_expectation(2), From cdf20995e9b242ce5211810b8155a4ea5af736a7 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 1 Jul 2013 15:38:58 +0100 Subject: [PATCH 183/208] MDL-47494 ddimageortext: Update version and readme for the 1.3 release. --- question/type/ddimageortext/README.txt | 21 +++++++-------------- question/type/ddimageortext/version.php | 4 ++-- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/question/type/ddimageortext/README.txt b/question/type/ddimageortext/README.txt index 0f4109b189c..1532a2a799c 100644 --- a/question/type/ddimageortext/README.txt +++ b/question/type/ddimageortext/README.txt @@ -1,4 +1,4 @@ -A drag-and-drop question type. +A drag-and-drop question type You can use text and / or images as drag items onto defined drop zones on a background image. @@ -9,21 +9,14 @@ to be installed in order to work. This question type was written by Jamie Pratt (http://jamiep.org/). -This question type is compatible with Moodle 2.3+. - -To install using git for a 2.3+ Moodle installation, type this command in the -root of your Moodle install: - -git clone git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext - -To install using git for a 2.1+ Moodle installation, type this command in the -root of your Moodle install: - -git clone -b MOODLE_21_STABLE git://github.com/moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext +This version of this question type is compatible with Moodle 2.5+. There are +other versions available for Moodle 2.3+. +To install using git, type this command in the root of your Moodle install + git clone git@github.com:moodleou/moodle-qtype_ddimageortext.git question/type/ddimageortext Then add question/type/ddimageortext to your git ignore. + Alternatively, download the zip from - Moodle 2.2+ - https://github.com/moodleou/moodle-qtype_ddimageortext/zipball/master - Moodle 2.1+ - https://github.com/moodleou/moodle-qtype_ddimageortext/zipball/MOODLE_21_STABLE + https://github.com/moodleou/moodle-qtype_ddimageortext/zipball/master unzip it into the question/type folder, and then rename the new folder to ddimageortext. diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 939243ab4b2..fe60e1b63c4 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2013052000; +$plugin->version = 2013070100; $plugin->requires = 2013051400; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; @@ -33,5 +33,5 @@ $plugin->maturity = MATURITY_STABLE; $plugin->release = '1.3 for Moodle 2.5+'; $plugin->dependencies = array( - 'qtype_gapselect' => 2013042900, + 'qtype_gapselect' => 2013070100, ); From 86687aadb61d4fda6fcd1b5542082128597828ce Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 2 Aug 2013 14:28:56 +0100 Subject: [PATCH 184/208] MDL-47494 ddimageortext: Fix use of deprecated context functions. Also, improve import to use new qformat_xml method. --- question/type/ddimageortext/questiontype.php | 5 ++-- .../type/ddimageortext/questiontypebase.php | 29 +------------------ 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index 83c75a1f9ab..b3546c9ef06 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -236,7 +236,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $format->getpath($data, array('#'), array())); $filexml = $format->getpath($data, array('#', 'file'), array()); - $question->bgimage = $this->import_files_to_draft_file_area($format, $filexml); + $question->bgimage = $format->import_files_as_draft($filexml); $drags = $data['#']['drag']; $question->drags = array(); @@ -250,8 +250,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $question->drags[$dragindex]['draggroup'] = $format->getpath($dragxml, array('#', 'draggroup', 0, '#'), 1); $filexml = $format->getpath($dragxml, array('#', 'file'), array()); - $question->dragitem[$dragindex] = - $this->import_files_to_draft_file_area($format, $filexml); + $question->dragitem[$dragindex] = $format->import_files_as_draft($filexml); if (count($filexml)) { $question->drags[$dragindex]['dragitemtype'] = 'image'; } else { diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index 4a370244681..7acfca73cd0 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -93,7 +93,7 @@ class qtype_ddtoimage_base extends question_type { public static function constrain_image_size_in_draft_area($draftitemid, $maxwidth, $maxheight) { global $USER; - $usercontext = get_context_instance(CONTEXT_USER, $USER->id); + $usercontext = context_user::instance($USER->id); $fs = get_file_storage(); $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid, 'id'); if ($draftfiles) { @@ -135,33 +135,6 @@ class qtype_ddtoimage_base extends question_type { } } - - - /** - * Create a draft files area, import files into it and return the draft item id. - * @param qformat_xml $format - * @param array $xml an array of nodes from the the parsed XML. - * @return integer draftitemid - */ - public function import_files_to_draft_file_area($format, $xml) { - global $USER; - $fs = get_file_storage(); - $files = $format->import_files($xml); - $usercontext = get_context_instance(CONTEXT_USER, $USER->id); - $draftitemid = file_get_unused_draft_itemid(); - foreach ($files as $file) { - $record = new stdClass(); - $record->contextid = $usercontext->id; - $record->component = 'user'; - $record->filearea = 'draft'; - $record->itemid = $draftitemid; - $record->filename = $file->name; - $record->filepath = '/'; - $fs->create_file_from_string($record, $this->decode_file($file)); - } - return $draftitemid; - } - /** * Convert files into text output in the given format. * This method is copied from qformat_default as a quick fix, as the method there is From 874104d5afd9b801a6c9afb17785d92553e711a6 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 7 Aug 2013 19:37:32 +0100 Subject: [PATCH 185/208] MDL-47494 ddimageortext: Fix incorrect PARAM_TEXT. --- question/type/ddimageortext/edit_ddimageortext_form.php | 2 +- question/type/ddimageortext/edit_ddtoimage_form_base.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index adfe694fe73..4202b410970 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -213,7 +213,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { // We do the necessary validation in the validation method. $repeatedoptions['drops[xleft]']['type'] = PARAM_RAW; $repeatedoptions['drops[ytop]']['type'] = PARAM_RAW; - $repeatedoptions['drops[droplabel]']['type'] = PARAM_TEXT; + $repeatedoptions['drops[droplabel]']['type'] = PARAM_RAW; $repeatedoptions['choice']['default'] = '0'; return $repeatedoptions; } diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php index c7ece0f71ee..5cc6b4b699b 100644 --- a/question/type/ddimageortext/edit_ddtoimage_form_base.php +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -122,8 +122,8 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { $itemrepeatsatstart = $countimages; $imagerepeats = optional_param('noitems', $itemrepeatsatstart, PARAM_INT); - $addfields = optional_param('additems', '', PARAM_TEXT); - if (!empty($addfields)) { + $addfields = optional_param('additems', false, PARAM_BOOL); + if ($addfields) { $imagerepeats += self::ADD_NUM_ITEMS; } return array($itemrepeatsatstart, $imagerepeats); From ff8fee7f82b35d3919eb082c8a4d3099a05bdaf3 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 20 Aug 2013 11:38:42 +0700 Subject: [PATCH 186/208] MDL-47494 ddimageortext: CONTRIB-4557 make sure bg image is not re-sized by bootstrap based themes. --- question/type/ddimageortext/styles.css | 1 + 1 file changed, 1 insertion(+) diff --git a/question/type/ddimageortext/styles.css b/question/type/ddimageortext/styles.css index 0ee6b36d224..5754309fa3e 100644 --- a/question/type/ddimageortext/styles.css +++ b/question/type/ddimageortext/styles.css @@ -5,6 +5,7 @@ .que.ddimageortext div.droparea img, form.mform fieldset#id_previewareaheader div.droparea img { border: 1px solid #000000; + max-width: none; } .que.ddimageortext .draghome, form.mform fieldset#id_previewareaheader .draghome { From e7a04b042334daf8266618ca45e87b3b9e4b9a33 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 8 Jan 2014 11:45:33 +0000 Subject: [PATCH 187/208] MDL-47494 ddimageortext: Incorrect types causing tags to be stripped. #9127 --- question/type/ddimageortext/edit_ddimageortext_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 4202b410970..ee15f390d8c 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -168,7 +168,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $draggableimageitem[] = $mform->createElement('text', 'draglabel', get_string('label', 'qtype_ddimageortext'), array('size'=>30, 'class'=>'tweakcss')); - $mform->setType('draglabel', PARAM_NOTAGS); + $mform->setType('draglabel', PARAM_RAW); // These are validated manually. return $draggableimageitem; } From 864d36c9392c14b1f6b0e9ebfe1748dedd0074cc Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 8 Jan 2014 13:08:26 +0000 Subject: [PATCH 188/208] MDL-47494 ddimageortext: Update version number for the 1.4 release. --- question/type/ddimageortext/version.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index fe60e1b63c4..6a4601b24e0 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -25,13 +25,13 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2013070100; +$plugin->version = 2014010800; $plugin->requires = 2013051400; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.3 for Moodle 2.5+'; +$plugin->release = '1.4 for Moodle 2.5+'; $plugin->dependencies = array( - 'qtype_gapselect' => 2013070100, + 'qtype_gapselect' => 2014010800, ); From 13ee9a2639e651685c36a2bb048db1ec6052e7ee Mon Sep 17 00:00:00 2001 From: James Pratt Date: Fri, 18 Apr 2014 19:40:50 +0700 Subject: [PATCH 189/208] MDL-47494 ddimageortext: MDL-45111 quiz responses report : fatal error when counting responses not all possible responses where returned by question type method. --- question/type/ddimageortext/questionbase.php | 8 ++++++-- question/type/ddimageortext/questiontypebase.php | 13 +++---------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/question/type/ddimageortext/questionbase.php b/question/type/ddimageortext/questionbase.php index 6c75098985c..38b1a96eadd 100644 --- a/question/type/ddimageortext/questionbase.php +++ b/question/type/ddimageortext/questionbase.php @@ -122,8 +122,12 @@ class qtype_ddtoimage_question_base extends qtype_gapselect_question_base { $choice = $this->choices[$group][$choiceno]; $correct = $this->get_right_choice_for($placeno) == $response[$fieldname]; - $parts[$placeno] = new question_classified_response( - $choiceno, $choice->summarise(), $correct?1:0); + if ($correct) { + $grade = 1; + } else { + $grade = 0; + } + $parts[$placeno] = new question_classified_response($choiceno, $choice->summarise(), $grade); } return $parts; } diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index 7acfca73cd0..2512852da0d 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -60,7 +60,7 @@ class qtype_ddtoimage_base extends question_type { $this->initialise_combined_feedback($question, $questiondata, true); $question->choices = array(); - $choiceindexmap= array(); + $choiceindexmap = array(); // Store the choices in arrays by group. foreach ($questiondata->options->drags as $dragdata) { @@ -165,18 +165,11 @@ class qtype_ddtoimage_base extends question_type { $parts = array(); foreach ($question->places as $placeno => $place) { - $group = $place->group; $choices = array(); - foreach ($question->choices[$group] as $i => $choice) { - $summarisechoice = $choice->summarise(); - + foreach ($question->choices[$place->group] as $i => $choice) { $correct = $question->rightchoices[$placeno] == $i; - if ($correct) { - $choices[$choice->no] = new question_possible_response( - $summarisechoice, - $correct?1:0); - } + $choices[$choice->no] = new question_possible_response($choice->summarise(), $correct ? 1 : 0); } $choices[null] = question_possible_response::no_response(); From dacc4272714bb582edd5c58c3806408fbc512b2c Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 28 Apr 2014 20:23:01 +0100 Subject: [PATCH 190/208] MDL-47494 ddimageortext: Update version.php for the 1.5 release. --- question/type/ddimageortext/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 6a4601b24e0..57ccc69f6b9 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -25,12 +25,12 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2014010800; +$plugin->version = 2014042800; $plugin->requires = 2013051400; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.4 for Moodle 2.5+'; +$plugin->release = '1.5 for Moodle 2.5+'; $plugin->dependencies = array( 'qtype_gapselect' => 2014010800, From 3b5048294f933d429b65e66b9f1464230448b310 Mon Sep 17 00:00:00 2001 From: M Kassaei Date: Mon, 3 Nov 2014 14:37:38 +0000 Subject: [PATCH 191/208] MDL-47494 ddimageortext: Adding a behat feature to ddimageotext qtype, #12175 --- .../tests/behat/basic_test.feature | 198 ++++++++++++++++++ .../tests/behat/import_test.feature | 30 +++ .../tests/fixtures/oceanflooranswer.jpg | Bin 0 -> 24934 bytes .../tests/fixtures/oceanfloorbase.jpg | Bin 0 -> 9881 bytes .../tests/fixtures/testquestion.moodle.xml | 181 ++++++++++++++++ 5 files changed, 409 insertions(+) create mode 100644 question/type/ddimageortext/tests/behat/basic_test.feature create mode 100644 question/type/ddimageortext/tests/behat/import_test.feature create mode 100644 question/type/ddimageortext/tests/fixtures/oceanflooranswer.jpg create mode 100644 question/type/ddimageortext/tests/fixtures/oceanfloorbase.jpg create mode 100644 question/type/ddimageortext/tests/fixtures/testquestion.moodle.xml diff --git a/question/type/ddimageortext/tests/behat/basic_test.feature b/question/type/ddimageortext/tests/behat/basic_test.feature new file mode 100644 index 00000000000..65e20190a2c --- /dev/null +++ b/question/type/ddimageortext/tests/behat/basic_test.feature @@ -0,0 +1,198 @@ +@ou @ou_vle @qtype @qtype_ddimageortext +Feature: Test all the basic functionality of this question type + In order to evaluate students responses, As a teacher I need to + create and preview ddimageortext (Drag and drop onto image) questions. + + # Due to complexity and since the javascript code needs to be converted at some stage, + # we are not going to test attempting this qtype. However, we will do all other + # possible testings, such as creating the question preview it and seeing the + # correct information on the preview string as well as backing-up and restoring + # the course containing this qtype. + + # Another way to test attempting this qtype while previewing it, it write a + # customised step for tabbing through place-holders and another customised + # step for making use of arrow keys in order to go through the list of choices. + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | T1 | Teacher1 | teacher1@moodle.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + + @javascript + Scenario: Create, edit then preview a ddimageortext question. + Given I log in as "teacher1" + And I follow "Course 1" + And I navigate to "Question bank" node in "Course administration" + Then I should see "Question bank" + + # Create a new question + # We have to set the fields individually, because of the step for uploading the background image. + Given I press "Create a new question ..." + And I set the field "Drag and drop onto image" to "1" + Then I press "Add" + And I should see "Adding drag and drop onto image" + Then I set the field "Question name" to "Drag and drop onto image 001" + And I set the field "Question text" to "Identify the features in this cross-section." + And I set the field "General feedback" to "The locations are now labelled on the diagram below." + Given I upload "question/type/ddimageortext/tests/fixtures/oceanfloorbase.jpg" file to "Background image" filemanager + + # Draggable items + Given I follow "Draggable items" + Then I press "Blanks for 3 more draggable items" + + And I set the field "id_drags_0_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_0" to "island
arc" + + And I set the field "id_drags_1_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_1" to "mid-ocean
ridge" + + And I set the field "id_drags_2_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_2" to "abyssal
plain" + + And I set the field "id_drags_3_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_3" to "continental
rise" + + And I set the field "id_drags_4_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_4" to "ocean
trench" + + And I set the field "id_drags_5_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_5" to "continental
slope" + + And I set the field "id_drags_6_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_6" to "mountain
belt" + + And I set the field "id_drags_7_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_7" to "continental
shelf" + + # Drop zones + Given I follow "Drop zones" + Then I press "Blanks for 3 more drop zones" + + And I set the field "id_drops_0_xleft" to "53" + And I set the field "id_drops_0_ytop" to "17" + And I set the field "id_drops_0_choice" to "7" + + And I set the field "id_drops_1_xleft" to "172" + And I set the field "id_drops_1_ytop" to "2" + And I set the field "id_drops_1_choice" to "8" + + And I set the field "id_drops_2_xleft" to "363" + And I set the field "id_drops_2_ytop" to "31" + And I set the field "id_drops_2_choice" to "5" + + And I set the field "id_drops_3_xleft" to "440" + And I set the field "id_drops_3_ytop" to "13" + And I set the field "id_drops_3_choice" to "3" + + And I set the field "id_drops_4_xleft" to "115" + And I set the field "id_drops_4_ytop" to "74" + And I set the field "id_drops_4_choice" to "6" + + And I set the field "id_drops_5_xleft" to "210" + And I set the field "id_drops_5_ytop" to "94" + And I set the field "id_drops_5_choice" to "4" + + And I set the field "id_drops_6_xleft" to "310" + And I set the field "id_drops_6_ytop" to "87" + And I set the field "id_drops_6_choice" to "1" + + And I set the field "id_drops_7_xleft" to "479" + And I set the field "id_drops_7_ytop" to "84" + And I set the field "id_drops_7_choice" to "2" + + + And I press "id_submitbutton" + Then I should see "Drag and drop onto image 001" + + # Preview it. + When I click on "Preview" "link" in the "Drag and drop onto image 001" "table_row" + And I switch to "questionpreview" window + Then I should see "Preview question: Drag and drop onto image 001" + And I switch to the main window + + # Backup the course and restore it. + When I log out + And I log in as "admin" + When I backup "Course 1" course using this options: + | Confirmation | Filename | test_backup.mbz | + When I restore "test_backup.mbz" backup into a new course using this options: + | Schema | Course name | Course 2 | + Then I should see "Course 2" + When I navigate to "Question bank" node in "Course administration" + Then I should see "Drag and drop onto image 001" + + # Edit the copy and verify the form field contents. + When I click on "Edit" "link" in the "Drag and drop onto image 001" "table_row" + Then the following fields match these values: + | Question name | Drag and drop onto image 001 | + | Question text | Identify the features in this cross-section. | + | General feedback | The locations are now labelled on the diagram below. | + + # Draggable items + | id_drags_0_dragitemtype | Draggable text | + | id_draglabel_0 | island
arc | + + | id_drags_1_dragitemtype | Draggable text | + | id_draglabel_1 | mid-ocean
ridge | + + | id_drags_2_dragitemtype | Draggable text | + | id_draglabel_2 | abyssal
plain | + + | id_drags_3_dragitemtype | Draggable text | + | id_draglabel_3 | continental
rise | + + | id_drags_4_dragitemtype | Draggable text | + | id_draglabel_4 | ocean
trench | + + | id_drags_5_dragitemtype | Draggable text | + | id_draglabel_5 | continental
slope | + + | id_drags_6_dragitemtype | Draggable text | + | id_draglabel_6 | mountain
belt | + + | id_drags_7_dragitemtype | Draggable text | + | id_draglabel_7 | continental
shelf | + + # Drop zones + | id_drops_0_xleft | 53 | + | id_drops_0_ytop | 17 | + | id_drops_0_choice | 7 | + + | id_drops_1_xleft | 172 | + | id_drops_1_ytop | 2 | + | id_drops_1_choice | 8 | + + | id_drops_2_xleft | 363 | + | id_drops_2_ytop | 31 | + | id_drops_2_choice | 5 | + + | id_drops_3_xleft | 440 | + | id_drops_3_ytop | 13 | + | id_drops_3_choice | 3 | + + | id_drops_4_xleft | 115 | + | id_drops_4_ytop | 74 | + | id_drops_4_choice | 6 | + + | id_drops_5_xleft | 210 | + | id_drops_5_ytop | 94 | + | id_drops_5_choice | 4 | + + | id_drops_6_xleft | 310 | + | id_drops_6_ytop | 87 | + | id_drops_6_choice | 1 | + + | id_drops_7_xleft | 479 | + | id_drops_7_ytop | 84 | + | id_drops_7_choice | 2 | + + And I set the following fields to these values: + | Question name | Edited question name | + And I press "id_submitbutton" + Then I should see "Edited question name" diff --git a/question/type/ddimageortext/tests/behat/import_test.feature b/question/type/ddimageortext/tests/behat/import_test.feature new file mode 100644 index 00000000000..ab4ddf770c2 --- /dev/null +++ b/question/type/ddimageortext/tests/behat/import_test.feature @@ -0,0 +1,30 @@ +@ou @ou_vle @qtype @qtype_ddimageortext +Feature: Test all the basic functionality of this question type + As a manager/teacher i should be able to import questions from other courses to this course + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | T1 | Teacher1 | teacher1@moodle.com | + | manager1 | M1 | Manager1 | manager11@moodle.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + | manager1 | C1 | manager | + And I log in as "teacher1" + And I follow "Course 1" + + @javascript + Scenario: import a variable numeric sets question. + When I navigate to "Import" node in "Course administration > Question bank" + And I set the field "id_format_xml" to "1" + And I upload "question/type/ddimageortext/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager + And I press "id_submitbutton" + Then I should see "Parsing questions from import file." + And I should see "Importing 1 questions from file" + And I should see "Identify the features in this cross-section by dragging the labels into the boxes." + And I press "Continue" + And I should see "Imported Drag and drop onto image 001" diff --git a/question/type/ddimageortext/tests/fixtures/oceanflooranswer.jpg b/question/type/ddimageortext/tests/fixtures/oceanflooranswer.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe20f07267d049f5a48e3c02986d42ef16e002d1 GIT binary patch literal 24934 zcmeFZXH*njw=P;pQbdrPX_Y8Zat0B}0)j%5QGz7NIkrerQWGR61<8^_gM?P1fRb~R zBpI6AK+}Ed{m#B;@9+K2xO?9{&i!%6xa}xdaNv{)wAM%?wZ;(=uQ&LipQ&3RRGSg8}Gty8{ z(BGwJWMP3oAXIes*zd8jGqXZi|0)Cze3Y1onC$v>GFEB|YS#b9AKW*9;yRFfO&1^U z9&n8U51#@L*9kxX0FMx??OzrCw-4Smd;+kR*Kd&A1aGLn4P3*+$G-;FA2a~GI|%$8 zAfOuiszztiXqqu50(-QV6Ip{1i|VC3NB;=a!#Dkd%= zDJ8A+SXo6?OqbwaqJAJ9`HYPcLsDUqAoQu<(e;ckiPTlRhM;q^6~3 zwj7HH@hf6yRL!VLO}eNU3k}gzyqIxfbgym5v8Io@k=+Vd%_{t zsUIbLs{Ve1O+*hxW9dFjLd!0?#BuPKY5%b7zh>Cm|CVL{%dmg9YX%_2#{)YLp8`+- zE}+Zu2*0I40G-rH%S)YVY@X`nckRiI*c|Tku?GZ{O}bgP-R2Bzr-Hd*Ln})V45t9> zTpk{$aH!Jafded0KjDDShfp&!11V>Bg_mgXR0$piL!~w0fYl56jsqoZB;+~{SP}y7 z?md~*RgO2yg8!|wD$G+H@TsR=0sX`j2OI`@jp;mkUg;_BM|&Y2y>z93sH=cW8Z>-YE(77t>C=88!CAd)Xd+@hKV zvTUS`nC|r~hY)}Tzg%J!%0(9n=mdHr3;rq}2mDxCqUeEcp#$w23de3F9}7FdCC=C=8>gzg^?_IE{&JUJiwA~i zCHO^(v%v4@Qp4)5JOYPVggljnJrT(X*z@R~ezwZC=sLJq7GCSyr-2bxUg0aZc z@(G}>RV0jjbHcmHa8Kwx^A|d2eZ>@^q>vPvTyWf_#==&wWK!LQ4KcUTiqp1m@uT4t|sC3^+Y^Xap)QcvO=o84_&I9UcWOpha`|4mg&BbuQ z$2lb0{$w93r~0>Z^W{nLejk=h)5i#5HnsRvylLvMV{W#;J~luM|F2Odn!qE)BJPVJJwNW zO#PVwGV0EId-o8CaMHwn-mu3{g^k|-24pf;g2mzksT@?OlJ{^S?TfowP+tZNVla7~&i(<*xZA09;ieb@B=*X_UO(*Hl-ZnAev(M4D) zEys==wlUFY98kSEAyK9CvZ&u4+ot*1+Qx5fKz`u!ZPf)?sF`VS5)R@|h=K+f6BrNA-+z(6|U$6HZOkvYYk7iCGpo%e>+01_Rj zd=+w)$}BBj@MV4r(cL#P(b>*2r^NSDJwt5>h;Le}%>ty#+uXJN{d1&k&tYul7Uk&A z4oK#fTX}|jE;d$QOrxXU3R^dtiJyDl9{>~^S;>s54?o=L{F4_QCKdb3u`@>&+uz8j z&<>-_{PXax1a!u@yF9170hLI+Fx$P-4K4QzGp9wzME%i;z~0TVH|!T3EVgf6OKwV- zimqIiT`34sQ1*CkKB~^*S-2_Fc@D=?+_Cej9jU|YE` zYzh=UkvJgSwqlQ1>e4$s=|sVyvWSOQGt;p#rU5}=s=~6uPZfce996UGLwcR9n&8<* z3;wp3P6lyA@IAs=96&N?KD&8(B?0(b?fPPlprW_9mS4p#^Rk#PF6A_*txdb<&M>;{ z-+`Uvb8ho#)4W;vqs;#Mc5t-gyNNv+y_)kxHnr>Tqksa%{uMig2jAGK2JpUj)~%=r z`8*!$)OK4-SerSE6U!!lJSNuqY$-B^zwSzYMzbuvZMXoLO6_1Y>##uSiYEyq#Swas z!w+V$YLRe-9g{KGafZg!)<-zDK~A;Y`&p*H$Xi#<7kN>$1lIe!D^jtEekCkTzzVw_R_5vCjXV;?Ozn-?CiOn-lF4qXI!it zsxIE^=uAnUclk2vF{j*u!})dLuK18XswDGRw~rf8>9w|Ix4g|!hl$>`??D`;Vx5|U zeKizKsz2xO=Pt&EH#1%b>!cRVa3zS$DL2rtnpQRkM)#1;F0#A(i2G-lZ%6VP3!Sy^XaaS2fHwz5k=>tFhbe6CHT*uk`;$?RP8BU zo@vLiv{a&WOir{j9E(&n>8P|dqbRx+g5*KTvNLJ(Oiuyjfo%H+&2LQR&g0AchHp*9 z9?ILC&#uV^_KZy=6&LM`mEiyxu+EJdx{fZ}I>^cezwn6K74_B8I+<*pXQLdM=8l|= z&1UkNIN;8dx;(ofX*_QvP%_hGmaZpkltZ1XKPG?2*Bb{sKe)A8V{EvcQbW#3V3Lez zi@GyF;78g=k@-^h13k%2{JD=P!HBva%Zf{_j2%y!r=nyteai*d&EL3Esu=mZs=-d1 z#-ur;Ue#x9GWsQs*mE_&YB@KolQ>nC;K`XD)^Xa}{$oc4rT=K+ZJ3Y;d%4TjK9+dS z*Bh}M>wl>>v9sspWbt(5#NzsvahS0AtYHUfX`X_B$@B1-O$sBX=$HoaqxkVn2m^BU zaSb?dLmz>uc6ouzG+MPiMb}i>b}5!}My66^_a;r48s`EK^iA+rBS7ZAlF^Qy08m=R z%;adbI)y74W4%A7rQ)*}I3NUTLM5JYi36Bm2~En>P{nR)U1i|Edib5S!|*m{*4qbf zIQkcstlW&gQhHqT^=m4Ya#uI7*E)n@_NFV)Pw5JfWCMGl164xgaV8Jaq zTE}S_HKGw--;MPPz5c5c^kkwn>v_x9{gv?*bY+3Va+R1rtoLG(O=tVEwEcf;QY*#3ZR=c=m7NfWiG31yuDo@|^PvI;lr! zNf_ zDDLu~*P^&T{^Mx8;=*dGzK89YjVK%!=~cAVZ&qQLA zddrIdCi7)TO z>ns^f2Fswb5epNaQe&{o5+88DN|e1+mvi?guA$BQuX*~)z`2ZC0rkvhH#|8n%CY+ z-ihPAKN;hnInq8>ypvG5f@GfGrqe3gpsStP6k@3{`_{$L^4jX`$peE2+P^m=Eb)Fk zl^t;TcF;rK1p}0+?HM^sTua}HmxdHB{Kgx?%OQNOPx9$G0JOi6-{@t7WSgN}Fv){> zuqgu&(Q6^LTuvtmLSJ^c|ugdLLND~a4Ub?)vdU!X`WI0Gl1BKDsI>iA_ zPUenE>_cYf2E80ZUfwR;>fyHXFZI+c>!HsMyo(Ca&-Ag2lg>M0j{5{AIz>IQ5et45 z$pTM)QCrccy}GwV1YH{dX!gXOX^g$D*EINAl{xU9Glj^h!1X|FxbZuFJ}>F9aw+Vid~Z0^`P*ZN`ZzvGSLkRR`wjwoa55eO2rt{84=ocV?L% zBw!D-C^dd3Ix;fN(>+A{c@)83n?L-u+`J(W+w)~ z$1ytfTNmLuNd;zG8DR@r*`Ebv51sg{sVRE^N>}2CB6=ofGjlDyE^gG7`0xHacYX5u z`2z#|Pcwb40k;E2+|Q)+u*t|iaQe4;1T-LylPpSpr+htoNB8ZFus%rT{-+^Xwc!Mq z=$8nlv=pKvYm!51rSOC?A!51hQCTK}85g+M{CzJLjjhQ`>24Iq+G;A(tAsrR6{Wiz zcoaoH8WrP!-inDR=R7x!865Dvv4DNW(FZfRQGO&j7`J%%Sk~_^gq;r(OC!+xsIwkN zcgrD+y8JJ-Dif1JfPa~lj@`AEIqm^IOF{5~{uWjS)_eP4{VLiYj!jZGCq;FzYmvTZ zh^Y%k!YZ@GtxaWD7-@?M%WgI@(#s^0vF`p_ z=i&Wpdt%?o8xIHT0z2ML**?8}u<%B`TR{M(u@^QrKD<6a8Cv^DSDEH<7RdVax}X-p zxAtH^Y$k8etnY&d^pRM?__&7^g(Z&uD#;c0`$dk%HYr8ct8|FwkXNzqqzKBck&%lL zy`MUqyh_L^}MWq;H?)c~Fh0GYq?JXNKgk2YeTTP(6LUHw%~WUTi%)+3sRK z++&We{sn7SIFP|c>JWq7$?Jgw`biZ2)pk#)`~y^SMJiF5$8s#?E%{{;J_$XG&Z-|F z$(p<=-jtsu9?g1M<0EKim-IlN-)Uk_TEN8z}f4AO;R<>R)X>! zYC=LEaSJ|~=}r@Lu8VHv(VR7-d6~1SO?7rA_(w$N!TrR}Vi|Z}(=SiPiZ>Jf2CXH& zh1eA%2?KncSkZYN9brj4r;n-(2@86IDQ@BC&%>Wk27FyP#sRF;7K==F$FY_R(-nJs zY-5~JLe7&yG9@uD`;XSDNuRy^?L2=tl62;UZIy9x$&S`)HJ`)*p%)fw?xnsu&@n8F z(Wd|B3*B*NjrpzWEk?^lqd}3tL8f*ib$v_mU02nVtoZ9_- zM(l`jPr{a(xgA5l2Y#hP@6KpqZd`xPp=K39l)Z9UF0+J<{IZon+x$gj!*$CzdpEg- zmzuSZpOvBEF~b{(r;SH}*NP)A({`EfZhf}ivet8Zlt~ve+ZoczB)&TFhd2%P zKABQ=@6ESjSuCsNS6nXWmmJ)ivllSb6LQ+Xds@LGi#m-H{LVXhBUD#O8b*A4!W%R7!oN%GTHwP@~v6Je}<#TPRZ4LfFDv#4G--V+~r9>3ASqbB)--NX1p*5^#58TK-27YA5O zzNnNz!7y=13eX{duwP3$$e+V+5uC8AUg&5XU`4HPVL!S#ijLU|oU$X9^a9NP+3A8@X{prN_=5ly6N}gId9H2 z98gt0h|P3y)Ucp@&s76&wTYbXKuJt1(VI3&TwzKY+qcFAe;NIUQccXuGp42N=Jrb)K6QD`%EHG^())r zZs>^hrx`N2d@p)k*m+X;Zp8a(^pUBN%nG;VqDF4Xk9K2a-pVxnI?l)vX>FOTQ8VDI zk97Rv+{u%AL@oSAUaR#s-r}%vfR_0FdC|qK{`ocRS6Dn)*>qxte`Zcl6>dE=dq@@} zh|rEegr*AS+n*~*Dok~hhQ0+=#!o6sUT*X)jpw_6`D|rRdi~B@B68gjGtSf%B<&QR z>#rckl1?W6)7clCUf3;Jo9BYfyo~F?kwh_MAu4h*!REx& z=g64P_J~a)6~+fQ5B=5#$)U+$aqOm4>EP*I;eQ^AzA6O85fU8mm>vhbN5l*^9mJKv zukH`7^|bod8XAg?%!?&gX9w>@aLf@`ci9P)EgSOF&gvYzs( zCqV9LB}=GZD`$nJ!M=~d0gk?d6(XRT@sIKo!pYmMs?dbHYXD8M?#8-z7f~3CDoyLR( zU0=En|J-n?a1N<$g!}oeCmJv@^DO!N#;mT(LZ9&HC24Fjd)Y$^D_;#7fv^yk2OBc! zhM^4|7BLB`7~Wkvg+rQy+<$}UP_8_5Nxgfo)iP5SpwkGrGEs5G64v@J@+rmwAk~ezr2U;i6*Pj1u&F#z(2cxNl9rF0!3)O?QH=~ZU zTsXQ0-&Yd0{)Fmw`7H-&EDMU?r&XKIPxMxq+4zEgO_^3VdyS#~L1jI6)U z3dj2EV*R06K}Znc|5JHE|0qxO)axmB?6beZ`KIdmrn%ecl?nFk*m#hH5?z$oT-vNnZb-mH)Sw{l|x{ zvY#vbTLn+BDlIF28A7=K4@2xOgUjO;>MJwl9?<0$^=n>Ae}p;cwRJAidF`rdH;wR# zX3j>duN^tFX8>QG-_a-e9!e_Y&Bj*B+E{>=tF+j1-=<|O*qKB;kfnQMf31S@>C-zi z0R4k%Ni6E5Qhdy%Ld=4~LE?;#(v-l>_GWLq**$jP;pThu7jjiWr7mQP=Jr_5Do2z4 zVz!nzlUIjT_{hG#&IBCrBwMv5=VYZsXPY^7==Xh{lU}<6=vDMr3G9b0 zuZ77Z%)N|dSX7RHW9EBXw>*15H0=j#aDEQ}{h~h+8a8JXd!uAjPsv8_K$wWfNR7bz ztnv;51$!?hNN&6#Y^VNN{WIEfTlvy-l0p<(^W(1Wn&0c4yYlLM*3VtiU5ozolrPMi zOdAdQ`G~rjd}q?+t9hXRSU0gV2LNn2tLn&^&?ZJhqOlH(##IrE(8uD@Vq*?_JCDwN zNfljx-Y(|4)nhy$F|jzlm%4qCSvZ14RvvCzWgf6Zv@XMMnP26$BZ8S)qBQAZf1Wz| zx%016et5!g?;FD*ru+LVspk-(KC_!$DPP%BPiI~sDUx+L)HL?HM8zc%%s4=dIsY(cGzb(Dj&F!Moa|rTgH?{cJZ~*XI9)gxJ8}*VC zSTU>-m_TitTaReo6u&HM{2Y_Z$FpZmo?Q$`(K9gYwlQx`8mo5T0CIbYq3Z%)j{AK% z-#u`OODL^bQzs_ymMqPH$F(RBR=|sA95QV75{lRGfYr{?0IPU*UOpsF9;0 zl64TZQFqxdr_#-|E5CKKS$#;I6s5*0MSaL%=&E=^=;$4)alW(XOWm%{4#U6r5cuO?*8=S_S3*1;r@&eSLKc*r!ykhXB-9L|+X-Wn3Pwg?J^jc15N})fE40H;xz~7-s@>>z@)C@?|iam+ET9vU1A|6Xt?jT3npx#dq!=&;?~u;bC92^|a{{GUqrHnbIYP34}rM)a%Mswek&`I^EehIb<@lh z@z5_@(#O(q35ESIH?pivThi0F%hT&~8l|%CJ^Wccyx4dqXYr%MBjd}52XZ}edoElx zIhuu&`~rOYOYc2sa|&q_h1`%r-PD>)N^5V|(%vjsNzTw+RP|uA_Q~*=Kgb>hRnW^n#{tBqTT~8l0xo-8x;NU}hNLS$vh;3-3`kq1|MRW- zy#|>@0tWunygXHZRJ}k|LTU_b`M)#2O^|<)eT^Af;X-I|jlJhQ3)afRS-}K{G;8wzLv5Fx$K$KFN~!-k4J;(*^@1+kon;-a6INxiJy%e%s%EgV?o!4f9v>sIjGhv5eH#`50gf`x!0zfB*V|owX^sa)mz@ey^emIP+KM zW@Z;Q^&nThkcr#>0t}Aonkdi_Hj~`9B?hH7_skhU*X{J>;U4`ZpEcjv!=<$ zo#Oymw}hT@{G?sgz*TP9xB!2>xw82ASw)ZfqG!oc>iSVNtbQPV`JE8&u6XCqR|pw8 z$~uQd#4Oo5`@NcrApxcQ9>JTy;vGp+fDB4+(4OP*w6%70H)9LCbyF>sA;pKHc(D0} z0ZVtS+ZQGNLind%59i;1{v2mI!qTkRT#pR1POcMQDkTP>e5Z#JCzX18UT`npIj^&A zNYnPc73UuValSgolmu25ZJVBTWE-3wJz+GjcVoWj`e4V^Xn4xsmlSe`AR&H{*CTsw zg|ul~HfhtsN{OWp_w^276`_phWkiWG&ZX zXm~C6@RsqR4tP;D5!QT>A@?yrxH1LyL)6a}6Kc?sbhS7(yqdd*Eri=Khg^vIunCE1 zG1?JP`=am!mm*fJjAZ`wslXQ7Ea2z-4?W-V?bL{o36rv>Q7o9y$-#s(gp%aqUAv@#Av83^w3lM-p z9yxf#$q`BW<3-6G#d&0)e~dY3*e>>E+3F4`k{qw>Xj zBeG@sfM6-)2b=6|3mPCv!Fy?8e5>v zx=IIgN@`pqYhy4!T2x>K67@zBTxH1*Me3Y;@0-^ZZfj z&pRMXu{7^Y^?RjwQ*TN>VQIEp*vBu=J;}L2-)3r^r=9DCe@N_i9U31j?P4fwJvR!8 zN*srsGs4j(!M8vF5zGVn3r&46K09boK@Ao$8COQSl{B@g6gIyVXb|C*b!ClW+hxsy zr1SQ)g{MJcP6d7x)cnW<#y%^~2OctaAp%O28Yem2sERWA`jUky`-ET44PRxHK(6Id zz3yuUG|c)p%a>-Km+q=}tfOJ51`HE8yD;Dz!&1t?cs~|<;PXAIU|Lp>+Ka2*xR4mD zIgUL-oCHKRL<;hcw+6{#;!W){B3et)u;-1aHzRtB=8m&zMH$3drPKYCTHLYeKKnw& zBzxXr>@l~SVdS3ut!xi-Mo#Ax*&KY1N{OBwYWncK^JRChC}L6Z`%|scHAoa!vYc>& zN+|(p#asu4B`355)(;KV<_13q2@^_;16vwy7=#))!N5~-pX6_WFb1>>{36Z{dEr@K z1h&{LsI46xK(Um@m7sVD!5IiYbKJ_-B8P{`t-3?V;#nv! z*+9~GtOu+8%S;iU5*5Del)tgY+ zi2PoM(HRDJ8re#hk);09vYcmbQ;=s`6hGAP$j{v3)Q{KOq>j&M^6*+I)rB!l{l)`-~(g0h?MmV6B7tFAS3^F;npI=VgO>izpq!Q@G+pwc0-&e_P= zvR!f|O8xVTkF+nU%UC{A3^uZ8gl2R-n$2io->-J*XZ_%3HIiLqX6#^4;!`xQG9H=?{^})T@~r&Bkvqd{CJo6Kv;)u2wrYiro5G&RovJts(*Ne)X?Gc*GJxM-8eKE zDa*=z6_sOnT=3U*#A=4l-PX+j#Q;%rl>hG7=RwF9k$sTqxg#$Z1?9PKj^`#O~%1?%*Patb2PTg63}3# z&+gcxa4P5kxzOS88vm3zbp!#!*5U0@0>qhj{d9poQFR|GE!?G-L0o>p)+yG-|EHOOO-J2YT2voZe&(SflQ5J9Up z>6-HS%oLnOc{w%(nq0-&es+jAED!C#d+X)9?6M$2F7ngk{`09Vyy-*4-CEHrn7NaM z&N%zzjG7pW_occM`}f;X)Nf38tzW#g5Dm&Uik7)giq<_`X)eG46}jt&+gAN+U!7p! zdWxizO^;Cr_NIn_Cccqn&ZhUY>UYU*=2gG=0xc#e0|IvClb4K73znnzBV4XZmNT1^ zCj)PJm1yTpOcPLcr(jgyeV&M#20wwa7@Z77n;x8i%ZYNy@-6IR>Ap}_LXDw z^xgC+9zu?Uhra>oVw&1~j_rV8aZKN-_9Vz7rf-fx6SmCn9K6aw$g@U1ov058SytGY z+IM!8Eg&njmf4I?D)4T`*=9nGxmGAQB%}@ep%r9vH5|% zY0la^z=xgW08Ek`B_eQu!9ij9vP8YTEJdM(DN%jw?k8`P6k$JyJQWiCH11%Zs=@hL zrAx<72|9@jT7*~mKtt*Rq$$=btjZ+JUJPJ@Sjt?ZV2o#WWDKq6 zvtUikjw5yyc}R+~xQdAcdGyKgKaCr1J(Al43gm;M3#~U#%Tu;kh`)~*8AbPpESsv{ zNP1!Ec{$ww;y3B~8y)6ruDsous^j%GT;}7Qy5bVk_RcR=@aq!Sf4T%U(_Lj8x!qil zK{*cv7tEV?KkYv8f@5P!Oh;M;Lp9``IOXUTy&pQo;9R9u=h>IZscq3 zbGE@|HC3;2Gu|hob(yf*%?9y_gruf0U7l3=FK$N=@7^-2xHqIH-@1d5>zh#>Ru#Kx zUtJ>VnoT~pW!sEZj>@9l#Bo{c?KiN~BG!n4%Q@|dP z;KnjW*YGUOrF>3Q#EIRxhi3(y96=MI_>JK9w+F`-H+@rjOm*%g*N^2xkhS)BHf#(w zvMx_(Izr%S`1LjUgQ~LDD_cRnUm#TBsn1Y9g^PV>^-eNy~Ift>5xp z>RlnI-0gV`e<2727Id(xWkSAZPrVpWR}FhhUPNpt&b#_opH$1ZF4-tBMNT0PStM5` z8vR-Vir@7lEp1D@Ub$5wj03o}Y#kJC%W82=mGd2&F}5#X>eWAFcuh>v(T*?;b+{|ZHbzZ-F#qDf?al@{ujzmK)Hm7h!{~JC$hUEjc10y+;^b|ry~tEG+_}-QBoW8f*gId zxrhVGyCA57Kr2u!#)5Dt>?abFY0i01j8|jl;q}7B0KDRvq+bGOcwRa|byWxNA^Dj9+yMI3dO}*=e(G~+bv6=H^O>#h~z79r-`DQg0`J@SxCjcb%kfg-|v>BnyV^ua`p`{a)1e53iz z^|0IQhf@v`Gr`kfw)*pBQwl^x;E&CZ7?w6Se6j5wVaFBKaK3bP?B?95Tz%xhwbN~N z6x};7lN(PYQvCJDJ1GIOUP?}$DOqNUg#whtySxKZAKJs2Osz+gFLQ2Rj)e|?h$kC; zD+RnIr@tGcK*xr^q!SIldbsa~1AR{)d!yJZ!w8Imj+NY}Os9vFuTf{70yU=4~meol`J_{PZnv0>5ZKxhevvHbaV&cHa z^m)>U?zQ!30lVy|>=z;dVxS3smgaNLgM$d|?d;o$e$z!7*Dt7~KG$m8aHi^Yqf9=Q z<05G5B0v<9=?szC*S0);ct+LB{NN+UYC=`@N`=l*B?Y>m938R$O`gN(q(8*@LU|~0 zMl#QER!D+j8VTy$m7kDH&oE%_l4t*W5JO=CJD`EgM8U2#!mOlWowoSJzWYky9z|D0 z1|BhTiA38~Mo@%3)swmz-H+9|o{6N1AN${Y_j@Exc;0sK zvMWFV!vhP?J=T&1^Ov{0F4%i;G)T1ERM^Py1tlW_5CSN>Pjrr#mItsj2J$lsU=Xr& zI}?jm;;>hdJ6#&|-nTNfgUwondRORI<36kzkrp~;mSr}z)J6YnjBoa{)9&O#zg<0? zW>4%)VV`V)wHKj{K#gnkdoKE311O;y6tQ1Y7WHn!1=pMt?U z+k3K{^A%14S_7Fu9#*`!t%c+bo&fUJFZ8PbAR(Fg{x!rGS*P-E6kh!DvwF{t)H%LH zFp$abP0dv)m~HP7`uF_j=6UL68=I)Db*h91+1v`!CL8UMXUX)L+2a_Qr)E$-ekBUW z&K!ZQ(^eMTzBl-^-lSaq@a7MT@WdPX@wsQUQ6O>pHw$z@9WQsu_KHe}2=+T_76-hm z*!V+3InHW**r(@jXG0@3KrZzSz?!b)jxM~xGcU`naO@S6@kUK{f~4RAWqP1gky6>W z;TijhDs~07b51D3%i3QBfrg zX3GC_ap(W_{Vy4DW5zDhR`8r#9`v(S21z&|--~3C{2;4waEbN1*U}ZywkcxLxlT(w z$avb@WKrEA){XM0{fEjLM8uWcWBai*Q8-zXd^2ryVNaQ<>Y7$yL$Lt6w!A?S)4Ox% z+W>Nnk-TO&=NiZGadHGVRI{2w>Gedy9fVo+w^^mf`OJ4`nsmR<$Pwy~isq8GW(Z^! zZr*Yt`*GXkJHz8k*+|P<`S^YD;>0L%w@_2tcVf8|M!su>K_*Y(DsbKUx@&#BywTj9 zImYKujZQPZpChhT9MrN;6q&vcqUHxm+$Vxrt0pT%xhn+4wtEH2^TPjlM?U4b?e}AY zjxxn1RaW5ox_HvsI<^6cq0&}$X+A)nvnCgB7<1;^`q>oQ&3LWVZ@(8<%9&=@jKF(n ztM{Oj;OULQdDgeNwx8_{)E!d%ZIWw@A3E)(aMKV7u{6a#kk^-it}zGZ4?#Z|`_^`5 zjFATh8j;2Ew{Y23_&qgwWR+uZbXMzE`fHWteLP7Oq3f1M`kt)G3U4LVpqssYnWC*t zv5~Q?N!{vbpGLgM`7hCEk3ZP+x97eL6tNXPM5dMLJqU~hhHSO(U>FA&b6w<*fQ-oP z1Ic00Z>Sk2?#!K%wA}#_k^|6Ywn;f*~`URbnYLpLbGX6 zw~q;xr32Tb+yz$>d!6_dxLF3XjeWxbw=Tk8WB5^Y7%mtp(R=}o=w!6qylAX>dy}w^ zBJ7f*u1WqiSy%KE9MBbG71dp-d6kA-WmwU))+*D_nL#Nm956fR5w*xsu=|(Gx?sZr>a;zry+REDVx4?o8jpA<%xurz=o~P!f*_J=Su>C2dk>SkE+lr>(9oW8QPNAi==To3FG@*EZ(Onvo)ux88)^AbT;! z(@EU1eoXA%nhUmvTKpn#mpgT*Um>|(iGjJ$kOp7s=G%^p=gF1eeu<+;r^$@1(;Z;2 zjj9HNROpIAKRDx8HORkZUIX_ihv9&3SsYMX1UuyLp+s+Y2yN14i_VeyH=J9&!HhV&DIMDhA4RKJs>Sf{#+z;04)cT5?@ z)U@|q6(Y4CeW#k|FuVZc6r_kG60IvPhrQ$b^GYQPb~*w_>l#=bKWzb5M}EKo*vA!Z zJv}pzYtdQeT|PF%k^7VrMxX0)srKT;EdATMdb%- z0-cF#yFyHlO8O!=&KTrWJi{#KT-IP1lEu{X4EG)tf97CL)LaH82LkV8)ZC`HHDbT* z$Izr$C;r55j_A6aH1o)&JUeQy+)b__xpEVFG~1o{i=}?my-sa~=O=X{9`T)=>y;8Z z(r*#w}6Wy~TGQL8KKbv2oAszfpMrYbUNyUt+=6 zh}JPEV_kvh1_MdO_Ws`c9? z^S-v-(mL+2AWCfhRg8B(NhVQMCKJPWR|tG!U>W3Mh>&P8bBL1FFk zEv5D&yW0!)6XFM-j~*U2cb+kw`3Y=2V1MHAgYDA~mU2pUxf=nSYv+PvysO*hVhXq8 z4IyZCu{b4)zxo=kanaqT4Kfz-sqbJr))NZHD{iKZxnbMiVH6j1$Bv6TNJ@MEyx#=5 zKT_@R%x`FX4qLTyV5yuvTv;NGy-%55VD8zianUx@1)tWkF2RKG^b8Jli-xSu7}Oi-mz)gP?y{K>t=yH9vzai0_FM4&GJ5wWZEzp@YWR-J^7ON=l_^`>wo%Wr=;-KQ zBAPh^_g#$G682WptyD~D-rYB?i(+^u$K((?w1K4<^+fJi)DC(tPF+0P^uC97c8wlw7IvL|{OaNuj~A`Ox7P$&CFdGBRB?+yCgBpwNt zW^*dksyVBfVyfPl7;mh~hMDP{c@3SPZ1KvE>rtgbj3@wDr>DObUKDbC8RR8KzRRL* zqUK!KiWp`0#r6|+e(y}IxUHssWOHsbt#TAjZ>r>j$h+J@nrx#9M_WN?5Aq?w(jRtO zoJzPN_AvTi(B3lqc%qYI8XS3ZNY}sU)yMhmc;1l8h{`j!r^{c>7?Y}FI4r5y-zNHv6KpAZYYRk8zpQN~0 z5#@TgzGbqbf05^BSFs8Jehl*umm*B~n^2Oi!+WpA6li=SpQaeSNZ~E{9AZBGDPEnm zQ!Rxpl7VA5+7pzXxSVrQus$3R`G;fu3ifUB=eJ>b?zwI8YR>e}8yB(1Upws8CZvBi z*1V#Pb!RsTkLGX{uR1&|k`;dtphLLrjt+gO^=SErktyHNtj@Jxe@fL!E2(w^1=i-m z-s-CpSmSrS+6*SDsu{aGW-~5kvOPAYP-mU-N3A!-r6$wTkO!c9IWSIwhYyhPx^!G9 zH@ttzkzLkz&^mU;-lr&2n7sD#8#9qRaf9?pX<*A&mm&;>jFHL3A{Or`7i6(lD}2we z?G1|;PBo=zb3u|@0LbrDl%qj5dL0hi;RP{S;Ve&atK-kIgWBnjyXyWdx!=DLzjtmV z_DWi{f^_HPV!v*A=AQGja)4V3eboNi3#-ut3q>9Z&%q|asI_5lrUHKbhrQR(f^aOO zY>fNW_OVPUcV3-T9OUl^0?PJxB3?}_(J8OT%+-{3gk`dUk^CwfSXF+nXI`%RC`df}VO)2aV(9wFwOa-CaO%K}{ zsKrU)G3!jR_8Jb9%|ex0W05@ab$M;tmvU!Ux8%WBx0mUHo57BQaxSqExnRwf^#2mJ zFE%fJYC}q%@4<_lWu=z3WBnnwP3@#jXF6{-FrC%KR}Tvp-pq7mP&EC1f>l|&(4T7J$60%wl2lr2q&@p;nD+2XP2Un>(x%2mPtH)HrT zVE=+K5JXhr2KhLkXXE0h(w4qV{ziW#k=^71U#8hO-)phkFY4oFZf1%m?TkD;67Gwc z?g+lb2PhDgvi9@7FvYKv{3o;JR9d+P4Q454BgXlrk6TdxYrF5{Pl)Ybs(TTry6ZbA zV1nVbi?E?lQ0eEXhhP=7mh(=SzCRDrJ&C0`^qJmAZrFpeKaDXQ^#A#PtL@0ePvsMy z?BT84f62-9lC=LvJ4YT3_1dOe(W%6~)*>*&0K(>@;q&lyxw; zy2vspTMDBrlYJ>mOfyPM$h8y(V+>|~eXo0N-#zKO=Y02ke|_il$DH@f% zq}S1qb|xGUTLO0KX=`m?9gKMe+>*|*h>s4EtJlhlnu2xBX(MG9O6bE$qp?S(7$Hwp zdvCn*_GFT@%xZ8>ehGTxuG_;c&jn=KJIK78<1EvhnlTw+Q0(~%q(Ei5I*s)f1ozoi__(K8{# zsr@e!b@J|-7vNu7BGvE9IQm|6d(e=)l{;!8P8F|l=zf-vV)@~e(=e7kwsJeql}5xz z+M^js*zlq%W3b!1#m92CtY9+G+eM7fhI1{&rSNtm)iju!<`I<4{C+NTKySG2`--Ja7|IdF-fbCoF# zTC|ZUc#wDfr6RcFqK_eA9M9bGzGQ&SzWh)t3x&GH1QevP`r z(9Ww4hOrCvjPqRJctFb7T6i5=1*NH&Ry6 z5OVd}lmWs01LlDE8Ys5v(5Aa{ZdST;#0#kW|3N7aV8zEQ0o8GPi4VvMLhxY+Ism^- zwGJ1*!j!FSV+BF2hLWIR%Za57#BFgiXn&pPQmlZn4Q?dd3DkS`2CJhbXi>^_D*8km zyCP+EN=i4Fzd~4wKlEqKSTu@nUaqG(RV_dHjRbxq>Z}G(qd^*7wP;KbO679$sb@ci z-04X^2mIuBk=iXXPskE}XM|I#oGtq6`~7bsuiogpJ7Gc~9-KIOqG*5IvrO{PcecH? z+U^RiVI}CN6+aq`cSz&=elBEn_nlAJ%{w+++tXCPi8@A4$)~qe7=|0HeD+$sAbTu`MC?wlbh-z1^r8!BoOX zu6kCN1{*c{+L59-I}V9X5UwBCN4#rGH;N73h0!p6J00lQG&Se3c4e#oPMC<4gWSp3 zw0DcL&s0l;-_0Y%-)j2_&Jf7VRL^}Tqe6pH?NTxC=-R5QOsT!$V)fl9^&jCO6|UET z(d1)01KX!VX!srzA_+S#+m2~HUlYM2zPFR(Xm?7^(2MO!)ykV#$k*QKai;uCwyD;f zmuA4UkxWvemyujwgOSqpHRScqSLXnaGA+?_PpM027m|SZ2oc- z*>9h(<5-~m0A5uB?|*yGT{+hzbi|LCn!q2*;$qm+LnjRhQ>zX$ewrn5u}5N}7D63< zX+D)A$4y(qH(1-t#HF=SYIiAQ;_lnD1da0XyDV>W$}uRN$*$IRKd#|*`V5j6r_uVo z^=7Yosts3slkZhnVVSgydX$`@MIn=Yjl^fD?}NC#fEG%{eF(gU%X2xgnuCsJ&Ro@T z=o5FWR;2DaV0t1^c-isx;6hABoo#5Xq1z~Jmrn5;P8P=CFpL?5ufA1#%{a!ZY~T0t zc-KwZqT9WA6h;tRZHLTVR8}j8i3FEaOOQ_gBoT?KC(65~jQ@79u71Ka_(72rN`yO7 zVmR9F`jDEsZhbAuM>_NO*;5Oh&57pkw(QS(ntgG%02fywT0tX~=7=SyI)kc7?4{?) z#%J~8)7XyS{`YPpF$ID1x!(V2^xu^^DAH56L`pG{l1d%w-odMjTxyQr-hyEhX8DTqJ);1R+%uDkx5xWpA> zWY{ED?il#xZ0KMA6h7Q`RuMc=*uX&Gg}7x2>mx|FSjc%MEl>@{T%KO&qWR{W)b-JB zRkAahE7{~77-J-LR*dcT-LYOD*QY+Z>2H^?NnQI9+kU(?i>buNQ8A~cuTM~=CB$N| z_@RABc^WS(^1>w@l<-3%J4%F7mP1uEPgjP>v8%Q$&lqp3UNrJTlBlrk;Y#wV)|~|e z%cjbfVHAvBnWC{%_1G{g*s4rDoXwbnkfrth%Nlczh;dM&GpJWhh5H|!Nf-2A5|__k zG}vw;o(7a%4g6`IdNrR??@RQEl9SXU#HxOnLmkBg8di0mJ(_n$2zT1ox-nn>aHoo# zxYxb{@eUDNdYvn2GLzN62;6Ck@n3Af(9{5)wN$WjFxiEGK~z63Wbrh6qgN%!M5DrK zvpqxFhk2Tb6e&IUok3g2s$`*1cv=5hH=Gu`e~}3nqZW>=F!pU@{B9%I34qsf~w( zOHw)fG_f0jz_}>>5=3bz&!O9Mu?S6dkV`T-5%0mg0GT;JFG&mMgMn|!uEgpSm+sV3 zGbOSaA*>RoVSjI0Xjqg|5$$%|s6GNk78{%h$g7YQ(1Azh!G0SfTEE%}&Kf1?`x`@3 zL(a3nN!pkqV|AjhY&>pcsEd z0=7de2!P-|w6Am0I&T$%4N4lvdsBga|J75?*8?c?l~%0WYJGR*x}T@{w0Oeb{NP@Y zctZA_(zwOXygcco&unRIQl?g3vR{cHpZ^!@na1LJ|N8bNBkue=HvSIL9O%bvi>y?T z>0ZzpL@N+~CHi(vqI{K($4rO{4qzL*Sp^`#EeYaJ5fdP>2b1-g?Tcc@C4NnwY|MY8 z2jbs5)JL;8n}dPra#K7DGR%d9{8|vJyewebY*s6N>EqO4EvFs+63|Uy)PE*m|uz?v%-Xyo$ z^IJ^OhY`Me3>3(jc+Ec~Vv7@J!q+t?SNu=~OBLkpDfe&!RGp?1ESo)5HhLC&qQK*5?JFbjKh00GZ|W;2%`{LyTtn1NV<)*Il60a7?jR`a+vBi33m zTKp^Dm+wl_OEnOmxHMs;IS{RwS5{%mYw|(Z+RNZvBS1QK2OQh@7(`em*4BH;xMZ=D zkgs(fLglC@|MNt8k0R|>TWsDVzT5&>u$m5PY8b%!Bt?VR4w**(5*i@n#nHjUWTU$NNlSirlgy%dgSWCM4*d{6sgjy z6agur_m1>V^5cE?zIX4t=86YMkA|fIr#y7;o#3UdJQV{;4A}2pj0j8p%0aJm&v<$3_v~(Bg!C)p% zri*NB92^|9jF-7DvvaeubFlw>2m!t;hy-+jl=K2S9hi>&KYiiq05B<#a88+!;4*Ly zOh5=Gz%>CJ06;*DxAv#Ozg`6A2#N4klAb3c$19Xl1Lp_`3D4o}#{*>P`9vH$ctsYt1*xI>0arf}_^7aV|4hao=9v%@F|1u%*)$2D&=^2?> z**Up+A3mW=O3TVWS5!7MHZ`}jwzYTk^$&a>92y?MOwY{D%`Yr2Ew5~C@9ggF9~>SX z|HMTA5dH<$Uy=PCE-)U~IXo>ypr5!1&Uxa65KKhODMCVX6AChSp}j2nl$7pP?EB*S z^IT#&oAeg0-^dua#ix0;enR^N*?$b!v;PvZzXJOkE(}0HNPs7g5DX{+#|;tuD0B>e zdIaznNw50+th>*?Dld-Qi@IGX`ql@2W+AmHK$NaiSt!f6I%az{tMmnTTn{rBjqm~~?OB*xArXb%rly>nVs30>OB$v}WH&HOr%qF{*d>KbbUf85NNjJyNr>BIIF%*6uUTJJbr7^=_C< zz|-&WMDxW~mmrRosOP~w9zgMi?U4SaNnNjTBkPvbIh9yK5<;SLRG_!1XWDj1RBg+P ztKY^~dk>FAw(X87z2i_sQmR zmx+Ek(CyNj@DH_bDsWg|x7fb=KAK6J#p2#ODreAMjy9|3^%C7?*4(N5*2{vNZH*M* zHm;!h8DybC!vl-b4Sx<5Z@z{fwBsZ8P%ngTP3l6+)MK=LI0cfZI_6`mG;EHtX`S<) zrD(_=y47$a2YMd{Nzsqb;$wECgQ`4u4OO87{!b+KEz}@DcuOmOI@u=aEGubdR?)iT zsi%e{BOee0u=;(~bFKHZ3ZWdfm0XL&0pYd03hcd2`mP^V%9~nkoS9nt{hF!tkX(ht zZ$SFYTSvkYYP*LeCueY-0ih}Xt$I(FMPk`FG*C9&yLpG1&xO#1FNBDI*jp-6GfVLH{^sX9EjQu@G~J14_v8_0rY}pN z#yMWUjZ}O5R~51zTEXzkmM!KnPu%%7il&~41)0`w?zBKxH&bMx+XZ{MTwmMXoOjL- ze1w!+?DjishIm_QQV?>{TeWR4Q9~?9^Z0@Ei2s_rbL)#J$eG00N&axLmg%|J zB}CDg${mi8W=vga>+tvJB~JQ#L;my|#W8+j@uES z8OqxW?@%4VtmCocP*Xwo*);kwf^yx6(M!lNL&#ekP;`diiaHwYH>^y?n;$IXg$6zQI)#Eo=Y|=NNHdm4@sl)UFvL zd_imka21#Mm@I2$Uonsvk1yUv z84x6bIJjQ}By~&g%N@?uv?_gnyjQ?5q*vs$>-)ShL~5M5n@mzlU%#Vhg)GLKeo9`t z?Nrqs-Vneu;3tNtCAiw1!u{rR@mP(s=++{E0sQHK!G!>Lwa0WZYo!MKYsBRn(qNeBB<7XW8L@jpyB{wOh&4RGwouyR0IgSggS~-& z+bMqAF@FF3N$&2thkZ=Z%NbKlzEwT)okh zc)%!Q^mWUqXHF!MH!^X!Acl!B^7`u7#ld&yBKZF-6^bDo+kz8_;rar^a`#GQ#~hXp zi~~rUf0RF$C_IxMzbBmYK!xt!_1~O40|$IpamE4E3Y^N*S6zFwK9`i9mm_g=@%Iy& zc}0ojWoGj$PmWykj5L3>uo!rEc!M7YtPX)Zw=Q>Iqr01BGy-vPa>`TAHWnR2mU?f~ zE47nMCh^$Pi6w%_ImwhLdPh#Ri=60Cu|DF-MxLoF95Po8Wy2kk#!V*I`GY!x>7!LS zsx3%v5X(Nx59zs;UX23`x3KXH1@Qdk9!IReeAZ;d762nwU*(OkD1T(Ots|i z>W9r_-a#ji^U`1EscDKcH1khqD#)xbu(Xc3gxPYOXcMivpWtyWrC~Ain<*mKPowPF zjD~@bLsQ?%4SjtYQ&a!c3HMS`bjOe4Nb^UJo)g0!36R$DJ+7tL@^20I({r>?TQ51< z4SS2x41bvO{mbh@twNE*9vr|) zDT}SRu|wbW0?Q(^sn`M`P@#jx`2YJG$zhCqZh9d2l{2Ozll|RWWZfR&GSmQLWYEq% z2rdZjImj;IWpv8t9h8uu8_2AsG3LA$!8KL&{h{kJYIQE{huwiF!J&8{RYOU9vw{%v zVNlbnZ!MXAQLHr9D<;fe3_H>b^wV~jc<+WG{tL%-HYplbg{Y%%8zEJyeOS3V91 z{&EMqzKA8faR~isdFlOEN<}M1pS5x+3;_ zL3lwIPo}%fWJu*6DttzE)fesBfbEv%yfY(2*Kp_|wK3sCbqFf;QN&ZO{VV0wiajUv z*tA@l=Bpb@$rR^aPtLjep9`bJ0YH!4t~tZ~hZ~>;`UiSs?#p)jT(X6_wP8pE0h7G34p5S%Nh#%WYi{}QBNd2WEBD+JG z{)SDvST-8W_LYLQq;bt`9g0WVBIS(IkA#|Eh>Ur%?j$vBNBayeKI;|E;lu&id`AWF z=XDJUH@LeaCCzmTR2ZTwBlru2_McU^&MKY;i~l&DoBRsPfxSMp#sM**DLBA5`6yzc z83$0NcyY{f1>z&ZHidr@8vQOz%BtU8y(6>L{tno5_L6R$y~*u*fvON69ptVYx4g<| ziL+zut>bBE3gcC4Ujl=K{a^8Z8q(P!$$OfytdTQ%L(%R#2@7FmU9bqp4^a-y{&`-_ zNyZy8cNxPLt^JjW(WSC*!XUrT;ARrA>{(Kg#*2R8e`CzliZmk=VVKO2}|)^0|JnY#Qt z*FR`q%VO6#hOQIFWR)Cqe1-mO^d_(P^Mg61fCZ!tdt15^o7brdze$cP!dF0U}R%{2XsEZAnO1a_v%75wr3L>kYZYH`Dc2i>b!lUM>DM zbyUBAjC@L4NLXg{Z>*OTP)@%v7x@0wJjh6lnahtKWW$t;1qv z@xY~lHI}o>)E#gSOuXu(kEC4eO3tCdmF^pY_OC1^7_w5owo29snXnXwJ1qHl^v7Ix z^`VH6JmL7NE6xVd9^AzNWy5OQL1i}231<8#zqMs#Py|KBMrCQBD9ymv{po+cAneb zl8GMM+HxV}!BKQ*wv6~dnG2;hEm`P5pQ)lA#hw`L-oE`TU(r9)9nhP4>(BrG;sm}h zvCV1483+Ogn0M*o0F7)^XFGdBr=KX&BP5r0)bu+9t39Ugm{S{-K{bwcv)L7YoIing zmifXg+jR_2J$$yX zEF;LoD{5l4-i9t~RQHzGCIEph%vna|#~V8wJeRxc=C(gv$XUi;*9yOw7oMP{E*BZn z=9HX3cD-?Ktin;IB0=CTZ_lkzJ=01L$a`Xt6wzz}i*&2cwEHCO z9W^|tGrW_+$o36l#Uk({G4*A(1c*q__qH}C#Aa8bcv^fk_YTAhxnr0=FDw=XgUaUn$F{07h6m-}& zh0hVUsown|L;h1a;MckZh>tKHB40U3l*;0NOH~G&@0NG#t2&17SiT5^zQoiO8Ue|pNaYbtwbFT z@PV1+@7`AYaiO%r*2&5GapGW%iqkm?ZYXav;V>Z*<)ZWL2}5jh#*&OyJXe>MP5Qz; zeWN!9opKecwW>$Y6@p{riEVaTy!i@?veI8&pJl(7HMK`{;?n<~?q&X9@Osf&YGl0T z)}!~+u>L1)78)lkRY6Wpj@wLKWnA9Q$Zj|}Yw#80P^)`-_X!3^{gnD1FiqMfl?K}n zRI_`zt>lx71#lCZn$IX6Q5>3K8=P=JCQPr&G(@hUR0?w-mo##htS`P4se)`_XRsma zTOCY%?rSPt&b9fH5LQwHSN%@%q|08rmSgvaYaC*UdngfJ>lWR#cP1d4d#M81SrK|= zmT#jYVs?+D68^U5qn5NK-DD#dMy@QQ({8h@w?uL^eK}{XCt>8(;-oF6-EjqRvNDGE5EbwTWaGIwhie*dJnrTgs=r$#8P~=K zVUJsn)NlZ7awiot4L8}ANk`7WpBlhwuWgoAwiOl{^jv0@lk8&&hpn>SL@rQzTV527 za=Mf_sa71SeZO1@k(=L$KQp?KDQwfXu|nKm5Ub_4dj zfYW#r9!dKQBJKAukOD5zr3{X&F5r&W77ta+PUvjgrWS3AkFO()gOC9%N;FVYhsRdx zlMJoskUD5Xp_@Lw=;503^yab(9l=GRO%w7_mZ}%zUCEmJYtnOj`b6N)hu0mlJ^^w= zYB`6qhUKJ{p=q`VCW|f!^lNV5f(Xlo&cw-pFHG@fi!?`qJG4bVE8U0H{nM$uzh$Xx z)ipLRAEi8Bag1hUX61w`l#v}x(ImF~MPeYh1H_uwLIqFSYPd5M8PrMejA}(O#mP@> zU{q}g-rKG?f(bN#{6TA&M`gSOxDFnm4Fo9O%?jW388+_f+HTt{t`N-v3206pmIV6= zY`N_A{y^+14{3(i(1%#~ncY&LIjk@4SFY(fJM>w0fOmaFTmf0^;{Z!o-n#s3i}L|l zt=V?Zw8ng@*K+-A)}zDDCWczJ;#<8e`J>sRwl*k&*g$3vZnk2S>f)vKu@58*_x#Eq ze6AU?vUTr7mgQ5!O9aa>)UpDWiz}na^31B|wr9jhzxA%x&%2ArWb|#E-kp9Sn_XJ9 z#fx-uuCYkm7k4>i=z`!gC8uD-l3gzj*feLv0raL0G(ynlvjlWc^rQ$kSp!s46899- zaDXYkGO~{Mz$+`QVbg<}yQ*8Sf*_#gV}J|g&W||!uz+PdL^tSH^6Yvl@PE7HF<2^1 zZ}}x$4O06iA@FK%9ufOgknv{wqTInO4k&~iE#rWpoU>xZdBGDB$#OAyW;yez13v4B zT|ULN$)=_=z^=e^*6D(>NVu@$#(cd%%t%|uq#D@~dwsF_x+r8Tyqh0WOC()dK57@LK%dnlas(OBSNz(P~9 z*UO;P>waIs1I$c51oxoEdTtadT4l0J^IkrPM{^#DgZr^e>r$9CEV7lO;I?&A4{(vF_Frfr5Fm4(7Y-zNv9Rs(<;-%EA?adg~sQB zfPEwT&=BOOCRfsf9b!A9Q>9*PH+N0x_mX|?XHk!=;6Jd)>Hxl^ncQP+!jQH^0f*SL zY>lwgj@As7nIB|D+G1w?1sa=qp8Vx8_`0m+rF~RRqiCaCt$)duHf?Ky*O+LkFWB_* z#9SPRY5fph;En)2evFLFsb)yT0k#^vP0UzDSZUVFw(fmmPm zMin~!P)<|$RvPx!Mb9%=rv<_O{I3CGIG{~g3kRU?o;JH#;DFHXYO1Z+I;aZ$9ETEq zRs;Vj$sde+={_|Rc)ePcYQHCxMEYWK&{{yNyHP?y!AOr=o{jG9kc^UATkb{xtk5O1 zIJxkIBgO8!VhBy`rSu2^^?$Ul5%#^S_MQ$l!Q>>n*$bGcuzQ5_L0~{U#$+xP#x?OP0J?RnW!vsnCd@0c@xK! z@#0DJ8a-5rC{9}mBr#tYFl2^)74?yuyDNLyFeR_8Zgl@qoCI|Iwj-@Vu03LAKi8pJ z-h6t=%A7X~Tk(oZvUpwCr8ksUs)PN*nlG$o9iOab`=vLO>yDrn3G(c2$Sf4Pe;mtb zDJQs1{rOTo*`ftC;ssH0TbpnPbApPB(iDa8x3{yvh1X2yA~rwV?e_b6{6Rc{Kle6% zoB!JTkLtmCt0p=1lSj;simUB7U{@R^R@{~$$K<@;l7GXfO95UMwcJ}@DR*+9u| z=y)mXNu+448V{n}lZTsVv>2qOC|K6Eu8kw58eI+Ex>Txi1qzhX=NIs?E0gvHTX*A8 zTK+7*|3jap$DFd_EAL5**y>~)psYTVUwSBw1Gpr5&b)76Llepve-0ZCATi?_#1pWO zOd;Fhz@L_FQ}=&ajmKAMQcQif;F<#xbNkKZ_xM=rz(=$5}VXV{S literal 0 HcmV?d00001 diff --git a/question/type/ddimageortext/tests/fixtures/testquestion.moodle.xml b/question/type/ddimageortext/tests/fixtures/testquestion.moodle.xml new file mode 100644 index 00000000000..a602d8e190a --- /dev/null +++ b/question/type/ddimageortext/tests/fixtures/testquestion.moodle.xml @@ -0,0 +1,181 @@ + + + + + + $course$/Default for C1 + + + + + + + + Imported Drag and drop onto image 001 + + + Identify the features in this cross-section by dragging the labels into the boxes.

+

Use the mouse to drag the boxed words into the empty boxes. Alternatively, use the tab key to select an empty box, then use the space key to cycle through the options.

]]>
+
+ + The locations are now labelled on the diagram below.

+

labelled ocean floor

+

More information about the major features of the Earth's surface can be found in Block 3, Section 6.2.

]]>
+/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCACfAlEDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD6V+I+t3nhzwD4k8QWKxSXWl6XdXkCTAmNniiZ1DAEErlRnBBx3FZn2H4of9Dj4R/8Ji5/+T6Pjj/yRrxz/wBi9qH/AKTyV11dVjlucj9h+KH/AEOPhH/wmLn/AOT6PsPxQ/6HHwj/AOExc/8AyfXXUUWQXZyP2H4of9Dj4R/8Ji5/+T6PsPxQ/wChx8I/+Exc/wDyfXXUUWQXZyP2H4of9Dj4R/8ACYuf/k+j7D8UP+hx8I/+Exc//J9ddRRZBdnI/Yfih/0OPhH/AMJi5/8Ak+j7D8UMH/isPCRIzgDwtdHp7fb811w/X25rzf4oeMby2uf+Ef0C7+z3aBHvLyONJvs+QGSJA4ZfMIwx3KcKeR84YTNxirsunGU5WRsix+KBBP8AwmHhHjGf+KYuT3x2v6X7D8UM/wDI4eERx38MXPv/ANP/ALV57rvjPxLrtnHYzyJpcakLM+nXEqS3TL3WQYeJSQfkQk4H+sYFkOlZ/ErXI/D8GnR6aLjV1RVbUbhh5UmAP3nlx4Z3yMsmFX0c1h9YgbvCVktUdgLH4nnp4w8JfT/hF7nP5C//AM4NJ9h+J/zf8Vj4Q4/6lm4/+T6840PxX4i0W/k1D7fc619ojCz21/dMI5WA+VlAUrCwyGPlpsbLArwu3TvPiL4su2LW8WnaZDsxsjje4lU+0p2oPxjNH1mmOWCqqXKdr9h+KHfxj4Qz2/4pi5/+T6PsPxQ/6HHwj/4TFz/8n1wOn+OPF+nylpNTi1dSxJhvoFiBXHyqjwopUk9WKvgc4PSvS/Bvi3TvE8En2WOe2vIFVri1nADxBs7TkEhgdpIK5464YFRpTrU57GVWhUprUpfYfih/0OPhH/wmLn/5Po+w/FD/AKHHwj/4TFz/APJ9ddRWtkYttHI/Yfih/wBDj4R/8Ji5/wDk+j7D8UP+hx8I/wDhMXP/AMn111FFkF2cj9h+KH/Q4+Ef/CYuf/k+j7D8UP8AocfCP/hMXP8A8n111FFkF2eaeJNd8ceH76zsb/xfok13exSzQQWHgPUr6RkiMYkcrBduVUGWMZOBlhWf/wAJl41/6Dcv/hp9e/8Aj1ds/wDyW/w3/wBi3rH/AKU6ZXoFZSlZ2NYxurnhP/CZeNf+g3L/AOGn17/49R/wmXjX/oNy/wDhp9e/+PV7tRU87K5EeE/8Jl41/wCg3L/4afXv/j1H/CZeNf8AoNy/+Gn17/49XuLXNst3HZtcRLcyI0iQlwHZFKhmC9SAWUE9tw9alo52Hs0eE/8ACZeNf+g3L/4afXv/AI9R/wAJl41/6Dcv/hp9e/8Aj1e7UUc7DkR4T/wmXjX/AKDcv/hp9e/+PUf8Jr4uWa3juPE9vZi4uYrWOW8+GGtW8XmyyLHGrSSXCou53VQWIGSK9xvLm3s7SW7u7iK3t4UMkssrhERQMlmJ4AA7muN+NZB8E2pHI/4SLQ//AE7WlNTYOCsZv2H4of8AQ4+Ef/CYuf8A5Po+w/FD/ocfCP8A4TFz/wDJ9ddRW1kYXZyP2H4of9Dj4R/8Ji5/+T6PsPxQ/wChx8I/+Exc/wDyfXXUUWQXZyP2H4of9Dj4R/8ACYuf/k+j7D8UP+hx8I/+Exc//J9ddRRZBdnI/Yfih/0OPhH/AMJi5/8Ak+j7D8UP+hx8I/8AhMXP/wAn111FFkF2cj9h+KH/AEOPhH/wmLn/AOT6PsPxQ/6HHwj/AOExc/8AyfXXUUWQXZyP2H4of9Dj4R/8Ji5/+T6PsPxQ/wChx8I/+Exc/wDyfXXUUWQXZyP2H4of9Dj4R/8ACYuf/k+j7D8UP+hx8I/+Exc//J9ddRRZBdnI/Yfih/0OPhH/AMJi5/8Ak+j7D8UP+hx8I/8AhMXP/wAn111FFkF2cj9h+KH/AEOPhH/wmLn/AOT6PsPxQ/6HHwj/AOExc/8AyfXXUUWQXZyP2H4of9Dj4R/8Ji5/+T6PsPxQ/wChx8I/+Exc/wDyfXXUUWQXZyP2H4of9Dj4R/8ACYuf/k+j7D8UP+hx8I/+Exc//J9ddRRZBdnI/Yfih/0OPhH/AMJi5/8Ak+j7D8UP+hx8I/8AhMXP/wAn111FFkF2cj9h+KH/AEOPhH/wmLn/AOT6PsPxQ/6HHwj/AOExc/8AyfXXUUWQXZyP2H4of9Dj4R/8Ji5/+T6PsPxQ/wChx8I/+Exc/wDyfXXUUWQXZyP2H4of9Dj4R/8ACYuf/k+j7D8UP+hx8I/+Exc//J9ddRRZBdnI/Yfih/0OPhH/AMJi5/8Ak+j7D8UP+hx8I/8AhMXP/wAn111FFkF2cj9h+KH/AEOPhH/wmLn/AOT6PsPxQ/6HHwj/AOExc/8AyfXXUUWQXZyP2H4of9Dj4R/8Ji5/+T6PsPxQ/wChx8I/+Exc/wDyfXXUUWQXZyP2H4of9Dj4R/8ACYuf/k+j7D8UP+hx8I/+Exc//J9ddRRZBdnI/Yfih/0OPhH/AMJi5/8Ak+j7D8UP+hx8I/8AhMXP/wAn111FFkF2cj9h+KH/AEOPhH/wmLn/AOT6PCGq+Kf+E01rw54j1DSL/wCx6dY3sE9hp8tp/r5LpGRleeXOPs6kEEfePFddXH6T/wAlo8S/9i7pH/pTqVFgud1k+pooorM0OH+OP/JGvHP/AGL2of8ApPJXXVyPxx/5I145/wCxe1D/ANJ5K66tEZvYKKKKYgooooAMVh+LfEX9gf2XHDo2pazd6rfGytLWxMId3EMszEmaSNAAkLnls5wAOa2+ck56ep46Z/l/I15frfikar8cvA2iWCxvZWOsXIuLgjJkuF02+XYpzgBBuB4OWbHylCDE5qKLhDmNzWvEnjz+y7gaP8J/EpvmQCE3V9paxq2erbbwkgfe28bjxleteYReFviMiuZPhv4hnmlYyzTPqGm75ZW5kdiLr+I846V9P0VzVF7TSR10puk7xPmP/hGfiJgg/DLXSD2+3aZj64+1YBxkZHYnOTzQfDPxFO7Pwz15t3Lbr7TDuPqf9K5r6corH6vA3+uVT5kHhr4i5z/wrTX8+v2/Tf8A5L5/H/69J/wjPxF3h/8AhWeu7gc5+3aZk/U/aq+nKitLm2u4jLa3EVxGHeMtE4YBlYqy5HcMCCOxBFP6vAPrdU+aB4Z+IgXb/wAKz17b6fb9NwB6Y+14/PNXNA0n4maN4isdXt/hnruY5dlyn9oab+8gf/WjJussThWA4+ZFJOAQfotriNbuO1Ky+ZIjSAiJigClQcvjaD8wwCQTzgHBxLTjRjF3RNTETnHlkeXa9441nQ9E1DW9U+GHjC20/T7aS6uZvtGlv5cUalnbat4ScAE4AJOOBXbVj/Hb/kiHjz/sW9R/9JpK2Oqgj/62PUetdlObejOCcEtgooorQzCiiigDmn/5Lf4b/wCxb1j/ANKdMqfxHe6rd+LNTsofFZ8NWmj6bBfb/JgeObe0u5pzKpPkqIgMI0Z5b5+mIH/5Lf4b/wCxb1j/ANKdMrrtY8P6DrNzZ3Or6Jpuoz2T+ZaS3VqkrW75B3IWBKnKg5GOg9K55/GdNN+6cNrWv64ms6rqdv4g8i30rW7DTI9LEERhuo5/s25nYqZfMP2hthR1UbUyD82adnqnim5udOuZvE90INU1rVdJNslrbhIYovthikQmPd5q+QgyxZCByhOTXo1xoOhXOuW+u3Gi6dNq1snlwX0lqjXES8/KshG5R8zcA9z61NHpmmx+T5en2ieRM9xFthUeXK+7fIvHDNvfJHJ3NnqaXuuHK1r/AMC3/B8uhspRXT+rP9bettTxvStc13w78KfD8Wn6zNIU8B3moJJNDCxWaJLYxdEAwgkZQMcjG7cea2df1/xV4ek16wXVL3WZfL0uS3YQWqT27XdzJDIsWRHEQoQFPNzhj8zMOK7yPRPClsV0mPSNFhM0FxttFtol3xOymfCY5VmKF+MElc84q/c6Xpt0LkXOnWkwu4Bb3PmQq3nRDdiN8j5l+dvlPHzH1NaTqKfvNav/ADv/AMC4SlFrb+tPv6/eeYWGs+NJ5NO0O51PU9Mlm15rJri7XT5L/wAg2Ek+JFgMkCuHAKnauV2ZUjJZnhSfVdQ+IHh2/wBU8Q3kslpY65ayDyYEW5W3voogzgR5DMoRm2FRlBgKCwPcoPAvhrTI4kHhvRrDTLvYijybeK0uJF6AcBJGWXpwSH/2udQ6JopmtZzpGnmS0mkntn+zJuhkkyZHQ4+Vm3Nkjk5OetTzpapa/wDAt+t/MXMkrW/q7/4H3Hh2t+KNevtI1uzudW1fUNL1XwjqWoQyXttYwwyqoj8uW1SFjOkRWRuLjLY285DV6R8Zv+REsv8AsYNC/wDTraVv2fhHwpZRXEVn4Y0S2juvM+0LFYRIJt4AfcAvzbgADnrjmsL41gDwTagcD/hItD/9O1pS5lyqNtv6/wCB/lsTNpr7/wAbf5G5RRRXQcYUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAHn3wn8B6Nrnws8Ja3qmqeMLi/1DRLK6upf+Eu1RfMlkgRnbC3AAyxJwAB6V03/CrvC//P74w/8ACx1b/wCSaf8AAn/kiHgP/sW9O/8ASaOuzrluzqsjif8AhV3hf/n98Yf+Fjq3/wAk0f8ACrvC/wDz++MP/Cx1b/5JrO8VfEO4i8Pa6lvoeu6Ffx6Le6hpl1f28IScQAAuqB2ZSC6HZKiHB5HBA2bXx3ZnzEvtG1nT5I5bZdtzDGC8VxJ5cdwNrnEZYEEHDp/Ei8U9bJ9/6/r0fYbjZa+f4W/zRX/4Vd4X/wCf3xh/4WOrf/JNH/CrvC//AD++MP8AwsdW/wDkmr+teNLHT7yaxt9O1DU71LyOyjt7Xyg007QmYorSSIoKxDedzKMEAZJxUN343ENvpyweF/EN1qV9HNKNMWOCK5iSFlWRm82VIyAzKBsdt24Mu5fmpXdrhy+RW/4Vd4X/AOf3xh/4WOrf/JNH/CrvC/8Az++MP/Cx1b/5Jqz4k8cx6Lpyal/wjHiS+slsft91NDaJGLSHGf3izPGxcAMTGgZ1xyoyubfhDVLvUdX8TxTz+bBZamkNqNgGyM2lvJjgZPzSMcnJ5x0AqkpO/l/ml+oculzL/wCFXeF/+f3xh/4WOrf/ACTWV8OrX+zdb8b6PFealc2en69HFai+1Ca8kiRtOspSokmdnxvkdsE4BY4r0uvO/B//ACOvxF/7GKH/ANNOn06b1M6i906miiitzAKKKKACiiigArj9J/5LR4l/7F3SP/SnUq7CuP0n/ktHiX/sXdI/9KdSoGjuqKKKyNDh/jj/AMka8c/9i9qH/pPJXXVyPxx/5I145/7F7UP/AEnkrrq0Rm9gorM1XxBoOkzx2+q61p1jNKu6KOe5RGkH+yCQT+FZ13478J233tahl4z+4jeU/wDjimk5xW7GoSfQ6SkPt0754x2/nXnuqfFXTFjA0TS77UpGUlWmRrSINnhG8xRKCexEZHvXGeI/FfiDX1ks7y9itbJmObWyHlmRCM7ZHyWYf7vlgjggjisp14x6m9LC1Kjska/jvxzd6xdNp+gXs9rpMR2yXcDFJbxsY/dMMFYwTuDphmIByFA8zm/A8ccPxX8ARRRpGiapcKqINqqBpt7gAdABngVUVQqhVAAAwoA+6MkjH51d8G/8lc8Bf9hW5/8ATbe1we2dSoux6roRpUWlufTleOWFpeXt1otzN4g18NqniXVdNulTVJ1Q2qNessaqHxGQYkxIgWQAYDAcV7HRXamlujzlL3Wv62a/W/yPGDqtqLHR7Xxb4n1DSvD8Uur2/wBtbV5rQyTQXflWySXQdXZvKEmFZz5hUkhitVdT8XanpvhTVf7f127sNWvvBFtPp8c8ht55rpUuTM0UYxiYZiLhBlflzgAV7jVTStRstUtWurCbzokmlgZtpXDxSNG4wQOjKwz0OOMiqjO3T+tf69FsWppO6Wn/AAb2/D+tjy7VWvzrGtawNa1hJrDxXplnbRJfyrAkMy2KyoYg2xwwkf7ynBJK4JJrGhvdF0D4eXOnf2xeQM3iu+gujceJZ7KOF/OnkRLi7JeW2RkVGGzBdmTORIxPter6hZ6TpV3qmoTeTZ2kLzzybS2xFBLHABJwB0AzUltd2ty8yW9xFK8DiOZUcExsVDBWA6HaynB7EHvScvc5Uv6Vv8r/AD+9c3u2t/STX6nglrr3iBfA9wW1fUYpodA8SNGRfzSshhuYlgbzZAryFEOFkdQxBz3r0zwbBNpvj3XdKXUdSurX+zrG8CXl5JcbZpHuVkZDISUBEafIuEGOAMmu1opuonFK2v8AwbilJONrd/zX6K3zOM+O3/JEPHn/AGLeo/8ApNJXKfD3x2tyYtD8ST7NSLBbW6YALeIeFyRwsxyOMAMdpX7xVer+O3/JEPHn/Yt6j/6TSV4M8MMkTQyJGY2zlWUY6Y4GOD3yMflxXNOr7NpmlKh7WMu6PpHkHDcN6UVwfwy8Wx3tnb+HdVuHGrQp5cTyKQLuNcEPuPLPtHzDgthnUBDx3oBJxj8uf0ruhNTV0efOEoOzQlFFFUSc0/8AyW/w3/2Lesf+lOmV6BXn7/8AJb/Df/Yt6x/6U6ZXoFc9T4jop/CFct8SLjWodNsotDu54J57sJIlm9st7MgjdituLr9yXyoYh/4FkI5Arqapa3pGla5p76drWmWWp2TkF7e7gWaNiDkEqwIODzUGidjy2ym1jxDrvhsw+I9Qsr1NJ1eK4vTZW6XatFdWyFCuJIN4ZQrMoKNhigXI20r7xv431DTLK706LUklg8NWeryvYLp6WjzSrIW+0/a5VcQjy/8AlkVIBfL5249fs9I0qyS1Sz0yytktIDb2yxQKghiO3MaYHyqdq/KOPlHoKq3vhfwzejTheeHdIuRpeP7PEtlG/wBkxjHlZHyY2r93HQelaOatb+t5P9Vp5Fcyt/X9fP8A4Y8untru/wDiNbSpql5p/wDxWYaSK3ELq5/sVG5Lo3ZSuQRw7HrtZfaKqf2Zpv2n7V/Z9p5/n/aPN8ld/m+X5fmZxnds+Td128dKt0TmpJJdEvysKcuZryVvxf8AmFcT8bP+RKtf+xi0P/07WldtXE/Gz/kSrX/sYtD/APTtaVC3Iext0UUV1HKFFFFABRRRQAUUUUAFFFFABRRRQAUUZ9iP89fTH40d+/4ii4WOQvLnxjqvxB1Lw94e1bQdLtdP0qyvHe+0mW8kle4lu0IBS5iChRbL2JJY81d/4R/4nf8AQ6eD/wDwlbn/AOWFHhX/AJLR4q/7F3Rv/SnU672sJSaZvGKaOC/4R/4nf9Dp4P8A/CVuf/lhR/wj/wATv+h08H/+Erc//LCu9rN0zX9C1S8vbLTNa02+urB9l5Db3SSPbtkjEiqSUOQeDjofSp55dyuRdjlP+Ef+J3/Q6eD/APwlbn/5YUf8I/8AE7/odPB//hK3P/ywrptN8UeGdT0y61TTfEWkXthZ7vtV1b3sckUG0bm3upIXA5OTwKQ+KvC48Pf8JGfEmjjRc4/tH7dH9mzu2483dt+98vXrxRzy7hyLsc1/wj/xO/6HTwf/AOErc/8Aywo/4R/4nf8AQ6eD/wDwlbn/AOWFdFc+MPCVrpcGq3PijRINPuIzLDdSX8SwyIGVSyuWwRuZRkHqwHetmKRJYllidXjdQyspyGB6EHuKfNIOWJwn/CP/ABO/6HTwf/4Stz/8sKyvFB+Inhexs9VvfEnhXUbVtV0+znt4fD1xbyMlzeQ27FZDeuFIEpYZVhkdK9SrifjZ/wAiVa/9jFof/p2tKFN3E4RH/An/AJIh4D/7FvTv/SaOuyddyMoYrkYyOorjfgT/AMkQ8B/9i3p3/pNHXZ1DVyzySx+DQigvTNrGmC9utIu9KkvbXRVhnuROE/f3L+YzTzApksSoO4/Kuc10Gq6A1npWval4pv7jWTdWA0+NNN0qTzI4AW2gRxmR3lLPlnGF+VSFTBJ7uuP0/wAe2V/fG2j0jWLe2a7uLCPUJooxbtcxO6mMYcvz5bEMU2Hgbt3y0pP3df69O29vnYtNvV7X/wCD+l/lcqp4T1fU/h1Z6Xqk+lHVbkrd6rHqGmLfWc8zfM8bwllJVWI27XBHlpyQCDVvfhtLL4O03w7Hd+HrqG0eWSS31XQFvLLc7Fh5MHmq0Ij3FYwJCFQlSGOGBp3j+6074f6HrOqaFrusM+hw6lqd7ZW8KxQKYwzu290DHhm2RBmAH3Rlc6V142srG+ureO21nVLiTVRp8FvFHCP3v2NbkLGSyDYV/ikOQ7HJC4I1nB3krf0nb/hhJSjp2/p/8EwPFnwiTX7S30+41i1u7KLSE01TqmmLe3EDKrD7RbyM4WKVty722MTsXBXANdx4a0I6NdavOboTnUrtLkgR7PL228UO3qc/6rdnj72O2TL4W1u38Q6LHqdtb3NsGklhkguFUSRSRyNHIjbSVJDowypIOMgkc1qUnKSbv13++4rt/wBf12CvO/B//I6/EX/sYof/AE06fXoled+D/wDkdfiL/wBjFD/6adPp0/iM6nwnU0UHGfqeM8UHj72Bk4Ge/BP9Py5re5zXCikJAGWIAzjk+v6+lU7jVLKDWLXSJJdt5dQyzQx4OWWIoHPHvKg/Gi4F2ijv/n1x9MUenv09/X/PT3ougCuP0n/ktHiX/sXdI/8ASnUq6MapYnWjowm/05bcXJiKMB5W7bu3Y29QeM59q5zSf+S0eJf+xd0j/wBKdSoY0d1RRRWRqcP8cf8AkjXjn/sXtQ/9J5K66uR+OP8AyRrxz/2L2of+k8lddWhm9jzH4z/8hHTzzkxMCcnP3h/jXAgnAGTxnueld98Z/wDkIad/1yb+YrgK8jEN87R72DivZp2DsR1yAOef59fxzS54AGQAMYBOPrjoD9KSiuc7bhVzwb/yVzwF/wBhW5/9Nt7VOrng3/krngL/ALCtz/6bb2tKXxIwxH8Jn05RRRXonihXiXgy8gg163i0nXL2bXpPEOqrc6V9scxLZfaLo72t87FTeFIm2glyE34O2vbaKOlv6/r9Cr+7y/1s1+p842erazqHg/xJ9r1ayluG8LXj6zZx+IbnUJo7nyxgyW8kKpYsCZB5SsoOSArbMr6f8NINPtPG/juCO7nN9JqcM72817JIVia1h2usbsQql/MUMoA+Tb0QAd/RWntNNu/5p/oNy93l/rp/kFFFFZkHGfHb/kiHjz/sW9R/9JpK8K5xxxXuvx2/5Ih48/7FvUf/AEmkrwquXE9D0MB9r5DXRTj76Mrh1aNyrKRjaQwIIIIGD1GBXSaX478W2CxwzX1rqcQbLfbbYCZ1/uo8ZVQvuysa536HBowOgUY9O35elYRqyjszqqUKdT4j0Cy+Kdz5jnUvDQjiHRrW/Ern6q6Rgf8AfRq1D8WNLZyJfD2vW6j+KUW2D9MTE/mBXmq/KDtwPoMD8ulIAF5XKH/YO3P1x1raONmc0sup9GegeIfEHw88QX1he6rdeIbO/tY5YYJbGbULV0jlMZkVpLRgGUmKM4JIyop8Fn8NJ5Gii8f6w0iAF4/+E/1Hcv1H2rI/HFee49eenJJNA4OQSDkHIPNaLGfzIzeXfyyPXoPAvh+eFZoda8YSRsMqyeMtVIP4/aaf/wAK/wBEGP8AibeMz7nxjquP/SnP5ce9eLNYWDXS3TWVsZ1+7IYl3AexxWguq+JYLRbbT/Fms2SBs7llSZiPTMyvx7Crji4PdGM8BVWzPWP+Ff6JjP8Aa3jPrjP/AAmOq4/9Ka534eeErHVtAurq/wBc8ZzSx6xqlsrf8Jfqi4jhv54oxgXAHEaKM9TjJySTXHJ4o8eI4CeJllRBgtPZZlP1ZCoH/fJqLwx4i8RaBaXFrMby5glvrm6Bs7iPeXnnklYbHCrhd+D85Oc8V0wqUpNK6Rx1aVemr2bPWf8AhX+if9Bbxn/4WGrf/JFH/CvtFz/yFfGf/hY6t/8AJFcnoviptXLJY+Ibtpxy8DqI5guSAwjZQxUlTz064zWj9v1fnOrXoxhiBsJAzg5wOmePXJ6V6McDzr3WmeVUzL2fxJo2/wDhX2i/9BXxn/4WOrf/ACRSf8K78PNNbyXFz4mvBb3MV1HFeeJ9SuIvNikWSNmjknZG2uisAwIyBWL9v1f/AKC99+S//E0fb9W/6C97+S//ABNX/ZlQj+16bPR/89KP89K85+36t/0GL78l/wDiaT7fq3/QXvvyX/4mq/s6qL+1KR6P/npR/npXnH2/Vv8AoL335L/8TR9v1b/oL335L/8AE0f2dVD+1KR6P/npR/npXnH2/Vv+gvffkv8A8TR9v1b/AKC99+S//E0f2dVD+1KR6P8A56Uf56V5x9v1b/oL335L/wDE0fb9W/6C99+S/wDxNH9nVQ/tSkej/wCelH+elecfb9W/6C99+S//ABNH2/Vv+gvffkv/AMTR/Z1UP7UpHo/+elH1/ka84+36t/0F778l/wDiaPt+rZA/ta+bPTAXn6fLS/s6oH9qUr7E3xd17UdOudIsNJvbi0nl824kmgCsVCBVCsGDDDF2IyOqHril+D2vX+py6xYapezXtzA8F0JpAq4SUFAg2gAYMLE4/vD1rzbUb641XxFqN/cXElwEcWcLyZBdIiQAQOmJXmA9sH2qbw7fXmn+JrBrW8uoI7yOW2bysAO/ysrEkf8ATJ1HvJ7146lP6xyX0Pf9nH6p7RrU9h8K/wDJaPFX/Yu6N/6U6nXe15P8Iprif4qeLmubiWdxomkANJjIHn6jxwBXrFXWg4TcWY0JqdNSQ2VS8TIGKllIBHb3ryC38H+JNS8PWugyaEmkSaT4YutF+1zXETRXssghUeV5bOwhPkksZFRvmXCn5set3t1b2VnPeXc0cFvBG0sssjBVRFGSxJ4AAGcmsLQPG/hbWdA0jWrfWrCG31dENos11Gru7EL5eAxBcMwQqCcNx1rON9bf1e6X6/qbptL+v6/y6WOb8R2GveKPDV79n8K3fhu8iksXjcz2bXlyLecSlEwZIsAZ8vzGwWY5VB8xyl0LxZa6JJf22ma/PfXmtLd3L3LaS+qwott5QmhUKtokmVVCSXPlljncdq+jW3ifw1cvqSW3iHSJm0rP9oiO9jY2eM583B/d42t97HQ+lLZ+JPDt5aX93aa/pVxbaczJfTRXkbJasoywkYHCEDruxihvT8fy/wAkC00t5f8AAOA+H/g7XdN1PS7jWLIu1vDrXmTSSws2+6u4pIyfLCruZA+dqAA5GBkZ7b4c6ddaR8P/AA9pN9AILqz0y3gmiDBtjpGqsuVJBwR2OKqaj468PwWuj6jaappl7pGo3UsD6lFfRm3gWOCaVnLjKkDySp5GM5zxiui0+8s9RsYb7T7qC7tJ0EkM8EgeORTyGVhwQfUVblLls/L9f82Em3v11/EnrifjZ/yJVr/2MWh/+na0rtq4D9oBnT4bbo3ZHGuaMVZeqn+1LXBFTFXkkZzdotlz4E/8kQ8B/wDYt6d/6TR12deGeBPFfj/wv4H0Hwz/AMId4au/7I023sftH/CRzp5vlRKm/b9iO3O3OMnGeprZ/wCFkeP/APoRPDX/AIVE/wD8g10fUcR/Izl+v4b+dHrVebeCvC2uToX1PUjBpcGuahexWD2BSfzDdT+W3mlsGEqwcKEySQd5X5awtH+LPjjVLWW4t/AXh5EiuZ7ZhJ4nmB3RStGxGLI8Eoce2OnSrn/CyfH3/Qi+Gf8AwqJ//kGj6jXatyMp5hh0uVzX9Jr9R+vfB0avo9hpF3q+nXVpa6JFpQN9oy3MkDIjL9otS0m2B2yu47XJCJgjANdRa+CjDrsWqnUwxTWBqZjFvjP+gfZNmd3/AAPP4Y71yn/CyPH3/Qi+Gf8AwqJ//kGj/hZHj7/oRfDP/hUT/wDyDWn1XFXb5Xr/AMODzOg/tr+tD0Twpo39haXLZfaftHmXt1db9m3HnTvLtxk9N+M98Z46VrV5L/wsnx9/0Ivhn/wqJ/8A5Bo/4WR4+/6EXwz/AOFRP/8AINQ8FiW7uDE8xwzbbmj1qvO/B/8AyOvxF/7GKH/006fWT/wsjx9/0Ivhn/wqJ/8A5BrA0O48SnWfEes6i0GlS6xqSXYtLC7NzHGq2lvb8yPEhLEwE/dAAI61rRwFdy1jYwr5jh1DSVyb4zaDrOo69DqOkabLf3EOnOlnDPaC4tnn3EqqPHLHLZzHK/6QG2428/LzWvtA8T3Hju5vJ7KeS6bXLS4s7+GJcxaephaSMXG/McYUSxtD5YLlmIDeYzjaF/qwx/xN7w4BHJQ98/3e3b0yaDfaqQAdWvMDpymR/wCO11f2bVZw/wBp0jmvD+ieLE8b6Nq1toa6RdTXF+dSnGnsfJ3wymNLi4a4Z7xRJ5e0qVQKoA8s7EHR+K9E8b3V3bNDqFlNq48P6xbW+oWdq1pBb3Eotjbkq8kjKcoTnJyV6U7+0NW5zq95nIOcJ/8AE/X8/TilXUNWXGNXvePVlPf3FL+zaof2pSOZs/BniB7LWZNH0+fS5LewgntbV7dLWKfU4LgzpuHmOHYGNY3nLYdZD8z8kWb7w14gudO0zV9Ss2nt9Vv7nUdf02a0+1+W0qItqskAZRMIIo0iK8/NtcKwGV3Pt+rcEaveAjv8nHGOPl/GkF/qwxjV70AKVA+QjB7crR/ZtUFmlIT4Z6Dr2la1p8+r292ix6NLCXnuFkMLNdtIkRYMR8sTKo5bCjG58ZOzpP8AyWjxL/2Lukf+lOpU/wAHXOoTao4ub+4nUQnCvtA6r6AdyemBzjpimaT/AMlo8S/9i7pH/pTqVclWm6cuVnoUKyqw5kd1RRRXOdRw/wAcf+SNeOf+xe1D/wBJ5K66uR+OP/JGvHP/AGL2of8ApPJXXVoZvY8x+M//ACENO/65N/MVwFd/8Z/+Qhp3/XJv5iuArx8T/EZ9Bg/4SCiiisDqCqmq6XpurW622q6daX8KuHWO5hWRQwBGQGBGcEjPuat0UA1cwf8AhC/B3/Qp6D/4Lov/AImj/hC/B3/Qp6D/AOC6L/4mt6inzPuTyR7GD/whfg7/AKFPQf8AwXRf/E0f8IX4O/6FPQf/AAXRf/E1vUUcz7hyR7GD/wAIX4O/6FPQf/BdF/8AE0f8IX4O/wChT0H/AMF0X/xNb1FHM+4ckexg/wDCF+Dv+hT0H/wXRf8AxNH/AAhfg7/oU9B/8F0X/wATW9VN9QX+0JNPttP1rULmKJJpU07Sbm88tHLhCxhjYLkxvjOM7TTTk9hNQiruxm/8IX4O/wChT0H/AMF0X/xNb1VvtF9/0K3jP/wldR/+MUfaL7/oVvGf/hK6j/8AGKbhN9GSqlJbNFmiq32i+/6Fbxn/AOErqP8A8Yo+0X3/AEK3jP8A8JXUf/jFHs5dh+2p/wAyLNFVvtF9/wBCt4z/APCV1H/4xR9ovv8AoVvGf/hK6j/8YodOT6B7Wn/MizRVb7Rff9Ct4z/8JXUf/jFH2i+/6Fbxn/4Suo//ABil7OXYPa0/5l95ZoqlJqPk3Nrb3uk+INPa7lMMD3+h3drHI4Rn2B5YlXdtRzjOcKau0mnHcuMlJXTDAJBIDY6ZFB6YPI75/wA8cZHHrQOT7Ud85Cg8jnt6UtyrkN3bQXO1p1OVOUlVirIeeQwIIOCRkHJBIOa6Hw74imSeHTNdlWSdiUhvWAQSPu4EgHyo7DgMAA5XGFbCnnNQvbPT7Zrq/uoLSJcZlncRqM+7YFYdxrNxrEMtpo+hyXNu4Obm9Jtrf5hjI3DzWJz1CAf7Q5J78HjZ0JLXQ8nHYCjiIPm0Z7aYTngNjnqMH279+fypfK+n61z3w51W9vNMGl61cRz6xZRoJ7hY9i3Kk4EgBJGQ3ytzndzjDLnrPJPpX2NDEqrHmPgq2EdGbg1qip5X+cGjyz6/oat+R7fqaPIP939TW3tDF0yp5Z9f0NHln/INWvJP939TR5J/u/qaPaB7Mq+Wf8g0eWf8g1a8k/3f1NHkn+7+po9oHIVfLP8AkGjyz6/oateSf7v6mjyT/d/U0e0D2ZV8s+v6Gjyz/kGrXkH+5+ppDC3bg/j6fWj2gKmVhHz12j6E1jeLNRbSNGmnhZFvpx5NmpUtmdh8vGecAMzdyFJ4reuXhtLWW6u54ra3hUySTSyBURRnOWJAAGBknAwRjNeaapfz61qz6jKjxWsWY7KGRChRD/GwI3K7BASGxsXaMAl8+fjsdGjTeup6uWZdLE1VpoVrOCO0tIbeLcY4UCJkknaAAMnqecnnNNv0me33W+wXMTpPDvcqnmIVdNx7LlcfQmpzjj0GOnoBij3zjnOa+MjUakpn38qcZ0+S2jVj0j4IXsOpfEHxJf24cRXHh/R5E3gBgDPqXDAE4YHIIzwQRXsFfM/wh8WaB4D8b+JZNel1WG21Ox09LL7PpVzdx71uLzeimCN8ZedGwxyWl464Hrh+Lfg0LuMfioA45/4RLVe/T/l27160putLnXU8BUlhl7NvY7qZS8ToOrKQK848EeHdbhPg46jpUtg+keHbrTJ3eaJyk262VWXY5yrCJ2B6gY3BTxV3/hbfg3/nn4q/8JLVf/kaj/hbfg3/AJ5+Kv8AwktV/wDkakoTV1bf/Jr9WVGvFbNHEWXgPxW3ha+0q7g166u7LwzdaRam9n01baV5ERQtv5EaymMmMHM7IR8uQxJK9Z4o8K6rPrWp3thpkc1utro7QwCSNftJtLqaV4Rk4B2su3dhckcgZIt/8Lb8G/8APPxV/wCElqv/AMjUjfF3wYql2TxSFHUnwlqmB/5L1f7zt/V7h7aHLy3VvX08/JBcaZqGvar4f1S48IDSUt9ea9uYp5oHnKrZyxJNKI2Zd+8xqArudoQkjBC7fw90y70jQJ7S9txBI2p386oGU/JLdyyIeCRyrqcdRnnmsU/FzwaOqeKR9fCWqfT/AJ9qP+Ft+Df+efir/wAJLVf/AJGpWny8tglWg1Ztf1f/ADZ3lcB8fxn4b4/6jmi/+nS1p/8Awtvwb/zz8Vf+Elqv/wAjVy3xS8d6F4p8LQaJotp4kmvZtZ0qRVl8NahAgSPULeSRmkkgVFCojMSSOlOnCSmtDKrUg4PVbE/ln/INHlfT8qteSf7v6mjyj/dr6p1ND4+EPeRyHw6QHRL7Iz/xO9TH/k7NXS+X7fpWH8N0zol/j/oOap/6XT/4V03kt7/nU06nul1oe+yp5Y9KPLHpVzyGo8lq09oZchU8r2/Sk8v2q55TcdgfU00RyEgBD/dxjkn057459PcVPtrdRqk+xV8sen+c0vl+1Z194m0Kz1UaZLfbrgSrC4jhd1jdsAK7KCqH5kPzENhwduDmpdf1vS9D8r+0bllaYsI444pJpGCgFmCxqx2gEc+4HUqDmsVC25q8JO+xb8selHlj0p2nXVpqVql3p91DcwOCQ0ThgMEghsZwQRg+hyDz1siIkjAyTyPQj61oq0XqmZyouLs0VfL9v0pPLHpVvyG96PJb0qucn2aKnlj0pfL9v0q35JpPIb3pe0F7NF7weu3UpM8fuj/Nai0n/ktHiX/sXdI/9KdSq74YQrfvkf8ALP8AqKpaT/yWjxL/ANi7pH/pTqVeFjHeq2fRZerUEd1RRRXCeicP8cf+SNeOf+xe1D/0nkrrq5H44/8AJGvHP/Yvah/6TyV11aGb2PMfjP8A8hDTv+uTfzFcBXf/ABn/AOQhp3/XJv5iuArx8T/EZ9Bg/wCEgooorA6gooooAKKKKACiiigAooooAK7b9nL/AJKD4y/7BWk/+jdQria7b9nL/koPjL/sFaT/AOjdQrfD/GcuM/hHuVFcLHfapfeKdWu5fFv9jWekapBYrYPDAYJ1eOJv3jMPM8xzKVTY6gHZ8rchszT9f15tX0/VJNfaSDUddvtJbSTBEIoUgFztZGCCXzR9nVmLOykM+FHy47ul/wCun+fy62PL5bptf1v/AJP16XPTaiS5tnu5LNLiJrmJFkkhDguisWCsV6gEqwB77T6V4Vr2peKL74Zv/anim7uV13wNdalOotbZBBLGlvxHiMHa4lcOG3dfkKV1niXXPEWmXt1pNjrcjmCHQkiuJoIWZmuL2SGZ2CoFJZFA4AA6qBWzoyXre342/Mr2Ttf+un+Z6dRXkepeIPFmnrc+HodQ1rV7geI/7NjvbWGxS/8AJ+wrdceaI7bduJXJX7mcAt81S6VqvjLWrnSNHuNdvNGlez1RriaKOxluWNvcwxxF9omhWTaxDqvGS2AhwFycWvuv8rX/ACJ5Hex6vUV3c21pGst1cRQRs6RhpXCguzBVXJ7liAB3JArx/wAIazeG/wBW8aat4je1aTwRpl9cBrWN7aF2W5YyeWqiRgpVmCh+d7DP3dtD+2vENxc3+ha3da3OtpfeH7mNdYSwW4RpNQAbH2I7AhEakBxuHPYitfYtVFTfdL8bDcGn935L/Oxr/tO/8gzwX/2Mh/8ATdfV5rjoccc4684/D8/T3r0L9q2W6h0HwdJZWYvLgeJcRwmTYGJ0+9HLYOAM54BPHAJwK8abR9W1ZSde1cRRNjfZaW5hRgO0kufMb327F/2a83EL3jvwbtB+pd1bxDpWm3P2Oad577buFlboZZyPXYmWA9yAKqGTxVqnKQw+HoHGfMmAmu2HbCj5I8+7SEd1rV0rTNO0m3+z6bY21pGTuYRRKpc+rHHzH3bJq2OOgAz1wMZ+v+fpisNjru2Yum+GtLtbpL6dZdSv0ztvL2QyyKx/u54QeygA981tgnAGTgdBnj8fWkwOPQdPrRSepSSGkXEd1Be2U5hvrdw0M20kbscq4/iVhhWGQcAEEMAw9F8LeJbHXE8glbXUox+/s2kBZSMZZTxvTBXDgY+YA7Wyo89HPGTj6n14rB8ThZdT8MwyqHjbUmBU9OLS5cAD0DqrY/vAHtXoYTHzouy2PMzHLYYiPNsz31kKg7hjPK5YAY+p7/p70bTn+L6Yz+oryC0uNUsg32DXtWtnb+Nrkz7fZVl3qo9gK04/FHiqGFYor+0uH7SXtiGP/kMxivUjm9O/vHhTyGsn7p6WAp6A0uBXn1r418QxRH7VbaVeyZ6JHLbj8yZakbx/rQ6eGtMP11hh/wC0K6I5lRl1OeWT4hdDvcCjb7VwH/Cf6938Lab/AODeT/5HqzF491B1GfD9tu7hdQYj8CYhVf2hR6sn+yMR/KdtgUAdOOPWuHm8e6iIx5Ph6zds4w2pMv8AKE1naj8QPE0n2K0s9F0awuL7UrKxS6lu3vEi8+5ihLGIJEWwJCcb16daX9o0ejF/ZOIW8bHpOCORlh+X/wBc/gDVPV9RsNItGutRvIraPO1TIeWfP3FA5ZuD8o+b2pNS8A/Eu6tjDB8RfDdi5OfOg8JOz/8AkS8cfpXPH4I+MnuPtVz8RtJu7rBHn3Hh6eRwCckLuvSEBIB2qAoIGAKxqZhp7qNKeV+8ud6HM+ItcuPEVwrOktrpML5ggkIDzlSMSy4OCB2jBO0kMctgRUwAMYAGBge3rj0z7ew6AV23/ClvGPH/ABX+g5Hf/hGps4xgD/j96d//AK3FH/ClfGP/AEP+g/8AhMy//JteJiI1K0rs+mw88Ph48sTiaOPTiu2/4Ur4x/6H/Qf/AAmZf/k2j/hSvjH/AKH/AEH/AMJmX/5NrH2Ezo+uUzh5kSaFopkEsbDDK/IP1Hr79a3/AA74xn0qEWmux3F1agfub+FDLJs7CQDLSMeBvXLNkbxwXOz/AMKV8Y/9D/oP/hMy/wDybSf8KU8YDp4+0EZGDjwzLz9R9tx+HSujDSq0HoceLWHxMbSOh0nUNN1W2Nzpl/bXsO7YXgkEgBxyPlzhv9k4NWypwOMHGcDncK42X4FeKJblLp/HPh/7SgIS4XwzMsqZ9HF6GH4GuO8Pa14s06O7tX8QJPLYajfaftnt91vMYbmWHzMu5mXIjB2+cQM168cya+NHhSyZSf7p3PY9tYfxAvbrSfAXiHVbCUw3lnpV1cQSAA7JEiYq2DwcEd6l8F+IovEMdxby2ptNQtdhnhD71IPRlJAO04I5AIIPGCGMPxcjA+FPi4/9QO9x/wB+HrvjXjON0efLDunU5ZI3NvIPrnn2PX27Zo2+1WYIybdGPdQfzGf60vlNg/LyB6E9s54z+meOTiqVVJXZlKleVkitt+lIAD05+hrldZ8fWMVxJbaFa/2tJEQHl87yrceoWTDeZj+8oKg8FgQQMOfxn4qklMkJ0eGA/wAElpJKV/4H5qj81FctTMaUHZs7KeVV6i0R6Nj2oIAAODzXm/8AwmPiz/n40P8A8F8n/wAfqM+MfGGTi78PY7Z06U/+3FR/atB9ToWSV072R0nwyTGg6gcdde1X9L+cY/Wuox34A7EnGa8j0LW/Fej2k1tbahobpNd3F2xk06UkPNM8rAYuBwC5A9sVpJ4w8YZO650QknnZp0oI+hM5pLNKCW4TyXESlfQ9JwS+xQS3pg5P0A5ps7xQQPcTyRwwoCXkkbCx465P868R+KWt+IbvwD4lWfXLgW76RdCS2jiiWNsxNxnZv/8AHq+hv+FT/Cz/AKJp4M/8EVt/8RUf2op/Arh/Yzp/xGcDqHjvQ4Vzp/2nVnOMPZIGj5OMiZiI2A74YkdwK5bVNf1nWVe3aRNMtNpRoLGfdJIMkqDLgMF5QjYF+b7xYcV7P/wqf4Wf9E08Gf8Agitv/iKP+FT/AAs/6Jp4M/8ABFbf/EVy1sTVqq17Hbh8LRou/Lc8F+zW32M2f2aH7MVKGHYNm05+Xb0xyeMY5I6U5VkMpmubq5u5vLSLzLiQu3loTsQn+ILk8tkkksSWJNe8f8Kn+Fn/AETTwZ/4Irb/AOIo/wCFT/Cz/omngz/wRW3/AMRXD7KdviPT+swvfk/r7jwm3a5tLk3Om31zYysQZDE+VkwAPmRgVbAAAJGVHCkCt6w8ba3AEXUtPttSU/NJJayGGQ4+7tjcsD9d6+4Fesf8Kn+Fn/RNPBn/AIIrb/4ij/hU/wALP+iaeDP/AARW3/xFdFKdWltI5cRGhX1lDX1ODtPHPh2bd9ruJdLdFBlF9GY0j/7a8xn/AL6rfsLuz1C1W60+8gvIX4WSCVWQn/ezit3/AIVP8LP+iaeDP/BFbf8AxFH/AAqf4Wf9E08Gf+CK2/8AiK7o5hUS1R5k8spSemhlFTnODznAAP5c45/T3oABXqufrmvJNTt28NfETxvo3hKZfDmnQ6vA0dpp1rAkKltOs2YhDGVXJJJwBknmtJPFfiqEIIr6xuVXl5LuxZ3PtmN0H6VazWns9yP7DqP3o7HrWgD/AEx8jB2envWXpP8AyWjxL/2Lukf+lOpVlfDnxLqeq699hudMs0jFtveeOdlYnjgRFcd/75+lauk/8lo8S/8AYu6R/wClOpVnUrRqy5omlCjKjHklud1RRRXOdRw/xx/5I145/wCxe1D/ANJ5K66uR+OP/JGvHP8A2L2of+k8lddWhm9jzH4z/wDIQ07/AK5N/MVwFd/8Z/8AkIad/wBcm/mK4CvHxP8AEZ9Bg/4SCiiisDqCiiigAooooAKKKKACiiigArtv2cv+Sg+Mv+wVpP8A6N1CuJrtv2cv+Sg+Mv8AsFaT/wCjdQrfD/GcuM/hHsF14f0G61y31260TTZ9Wtl2W99Jao1xEvPCyEblHzNwD3PrRDoGhQ65PrsWi6bHq1xH5U18tqguJE4+VpMbiPlXgnsPStKiu48m5SXR9JWGKFdLsRFDbNaRILddscDbQ0SjHCHauVHB2j0FVdM0nwy9mi6bpukNbQ7IEFvBGUT7PIdiDaMDypA2B/A2cYNcZ4g1nxFZeOWmfVtQj0aPUbW0AsorK4soxJ5a+VdKxF0szNJwYyUUPExBG8HP8N3OqXLWfh6w1640KK4vNevJLq2iheZ2h1AqEHnI6BcSlm+XPC4I5zaT5ef+tr/8E05Hb7vxv/kelajoWiajZ3llqGjadeW164ku4Z7ZJEuGAUBnUjDEBFAJz90egp9npGlWSWqWemWVslpAbe2WKBUEMR25jTA+VTtX5Rx8o9BXlFp4s8Sa1A98fFkOji28J2eueVBbQmOeVvP3s3mqzeQdiZAKsAVw6nOZ7jxb4yuvE89xaWmrQWdlqFlaPFu05NPKSpAz+c00i3Pm/vmC+XgZEY2udwZcr5nHt/w3/A7kyvHR/wBaJ/qj0seH9BDxONE0wPDaGyib7KmY7c4zCvHEZwPlHHHSotN8LeGNNtVtNO8OaPZ26MrLFb2UcaAq/mKQFAGQ/wAw9Dz1rXoqetybnkX7TmP7M8F5GR/wkhyD0P8AxLr7g+1eakk4yScep/l6e+MV6V+07/yDPBf/AGMh/wDTdfV5pXFifiPUwP8ADfqFbPwt8Bf8J3/wkl7e+LfEGmLp+riyggsFtBGE+yW0uT5sDsWLTP8AxYxjisavS/2Yv+QZ40/7GQf+m6xpYeKctSsZOUYKztqH/CirH/ooPjP8tO/+RKP+FFWP/RQfGf5ad/8AIld/a+L/AA/c+IG0OG7na7EjwhzZzC3eVAS8aTlPKeRQGyisWG1sj5TirB8QfCU0F9OupyLDY2sl5JLJZzxpLbx/flhZkAnQcZaLePmXn5hnrVOL2R5/PV2u/wATih8CrH/ooPjP8tO/+RKguf2ftJuJrWabx74zZ7SUywHOnja5RkJ4tOfldhz6+uK6zXfid4f0/Tpbq1i1G9kgvrS0mt1026WRVnl2LKq+UWeMgOVZQVcrtVskVp3fjHRtNmu11DUi5W/+xxQ2+nztKJfsyz+VtUMZHKZYFQM5C4LDmlSVr2/rT/NC9pUavdnD/wDCirH/AKKD4z/LTv8A5EoPwJsCCP8AhP8Axjz/ALOnf/IldxL468Mx6Raaot1eXEF4ZBDHbadcT3H7ttsm6BIzKmxvlbco2kgNgkCo9T+IPhHTtpn1VpI2tYrwy21rNcRJby7tk7PGjKsR2Nl2IUYGSMjK9kv5fwF7Wpa/Mzi/+FE2Pf4geMz9Rpx/9tKP+FFWX/RQvGn/AJT/AP5Err7Hx9pEs/icXsV3ZQeH7xLWWaS0nxPujjZfL/djexZ9oRN5b5CMh1yxPHNlqWoaJDobNJHdas+nX0d3ZzW88BW0lnAMcoR0Y7Yz8y4Ktx1Bpqinsul/kN1Ki3k+vXsrni/xD8IHwP4x0HT7bxJrGrW2p6ffTSpqCWvyPDJaBCphhjPSZ85z26YqgQCMFQfrz+Vdt+0b/wAlB8G/9grVv/Run1xNcNdJT0PSwsnKndsXJ55P4cVWuyTqXh4Ek/8AFSaP1JP/ADEbf1qxVa6/5Cfh7/sZNH/9ONvUU/iRrV/hy9GfWNFFFekeGU7i+SDVIbSSWzRHt5Zm8y52y4QoMqmPmQbvmbI2naMHdxh3PjnQZdEXVvD+p6Zr8H9o2thI1jfJKkbTTRx8sm4ZUSBtvf2zmqvjbQLrV/EEcv8AZiX9g2gajZTRPc+SsjzNblYywyyhhG/zAHGPpnmLLQPFt/bXct5p+psW1DSXjbWBp63xSC7EkuXtMRtCqcqGJfcZPUZ0hGLcb+V//Arfl/macsdGehx+JvDcmvyeH4/EGkvrEQ3Saet5GblBtDZMedwGCD06HNLpPiTw7q1xPbaVr+lX89vGks0dteRytEjjKswUkgEHIJ4IrzdPD3jG88cafdXOmXVrYWGt3V20UZsEsWjkjuESaIIDctK3mKZDIyjc74BGMH/CB65J4R0DSotPt7ee28G3OmTiSRdiXMn2UiNipJKsY5MlQR19RmYJNXbt/wAM3+iXz+QnFXaT/r+v66ndeGfGOk+JNevrHRLyx1GztbS3uFvrO7WaOQyPMhQbcgFfJ9T97oMc9HXFeCbfV7jxprPiDUPC82gQ3mnWNvGk80Dyu8T3G/d5LuowJExzyCOhyB2tEkk9CXvp5fkv1Cvk6141PxCQWB/4STWOQxH/ADEbj0r6xr5Otf8AkJeIf+xk1j/043FcuJ+E68F/EfoX9Gvf7L8SaXqi4ASfyJdoAV4JSqSE5GNqHbIR6RgjpXpHxhjI+EfjL5fu6DfE89CIJMj8MGvLL23jurKe1nG+KZCjr0ypBGPyJH0r0HxVqb63+zj4j1KeUSXDeG76G6kUYVp44JI5MD+7vDY/nXXgKztys480oe9GaO4tYiLaMAMfkHTvgAV5h8TNc/tPUJ/DVrJiytSv9obD/wAfDkA+Qcf8s8EMwAKuSF3Da6N3/izXB4f8GyamgV5/KRLVGGVaViqpuAIJUOctjkKCccV4vbQiGBYy7SNk5kc5Lscszk4GWLFiTgEliTnNXjMTyx5UZZdgvaT55LRD8fIE6qP4TyM9jj2/pS984GfXv+fX8zRRXi3vqz6VWtZIX8/zNAJAxk+3JpKKAFyfU/maTqcnnnnNFFJ6gYHxFH/FvfEY/wCoVdf+imr7FkbZGz4ztBOK+O/iL/yT7xH/ANgq6/8ARTV9iuodGQ9GGDXXQvyux5uNtzI840j4geJtUh0w2vg6xWXWNK/tPT1l1llXy18rzVmIgJjP71dm0SBv4tlTxePYZ2e+03Sri4uLzTNLns4pb1kjke7kmWNGXBWIKVy0ihmIPRtqg9Do/hHTdL/sX7PPdt/Y+lPpdvvdTuibyss+FGW/cryMDk8dMZqfDnRY9LFhHealGU0+xsoJ1lQSwfY2doJVO3HmBnJOQVOACuMg979mr2/pXd/wt8zkfLZ236dun9f0ij4S8VLYXniR/G2p6fokp1xLW3hutTVoQxs7dvLheQJuBJZgNqk5J2g5q3a+N7uTVoXuNEjh0G5v7jT7e/F4Wm86HzdzSQ7AEiJhkCsJGJ+TKjcdu14T8OReHl1Bl1LUNSuNRuhdXNxeshd5PKjjyAiKqjEa8AAA5xgYAoWngfT7fXU1D+0dTltIbqa9t9MkeP7LBcTBxJKuEEhJ82X5WdlG84UYXEN3t6L77L9b6/gF073/AK3/AOB+OpTsvG2pJ4bu/FWs+HY7LQE019StriHUFmlMQUMFljZEEbspBAVpFGGBYYG7O0D4oR6tp2uPbReHL690u2juf+Jb4iiuLPy3LDMtwUTytmxmfKHC4K7z8o29N8CWVrZXGmXOs63qOkyWb2MGn3NwghtoGGCieWiu5AAAeRndQOGGWy258Di90e5sNT8VeIdQlllgliuppIFe2aGQSR7ESJYjhxkl0Yt0YkAAJ26f8H/K/wCH5iXn/X/A38zA0T4o3Os2sSaZpOj6jfS6w2lI1jrguLJmFo1yJFuFiyVwNrDy8qc8NjB7TwXrcviDQE1C4shZXCzz208CzeaqSQyvE+18LuXchIJVSQRkA8Vm6X4GsLLUIdRl1TVb69TUP7RkmuZIyZZvsptiWCoAF2HO1QoBAwAOK2/D+kW2iWElnavK8b3U9yTKQTumleVhwBwGcge2OvWqfLy6b6f8ETtZW/rf/gHzn4z/AOSuePf+wrbf+m2yqpjcfTjqAM//AK6t+Mv+SuePf+wrbf8AptsqqL1rzKvxs9mg7Ul6HZ/BwAeJbrgHdZPkYx/Gnp/+uup0n/ktHiX/ALF3SP8A0p1KuX+Dv/Iy3H/Xk/8A6GldRpP/ACWjxL/2Lukf+lOpV6WF/ho8jHL96/Q7qiiitDmOH+OP/JGvHP8A2L2of+k8lddXI/HH/kjXjn/sXtQ/9J5K66tDN7HmPxn/AOQhp3/XJv5iuArv/jP/AMhDTv8Ark38xXAV4+J/iM+gwf8ACQUUUVgdQUUUUAFFFFABRRRQAUUUUAFdt+zl/wAlB8Zf9grSf/RuoVxNU309f7Qk1C21DWtPuZYkhlfTtWubPzEQuUDCGRQ2DI+M5xuNaUpqErsxr03Uhyo+tKK+Tvs99/0NPjP/AMKrUf8A4/R9nvv+hp8Z/wDhVaj/APH66frMTh+pVO6Pp248OeHrjXofEFxoOlzaxAu2G/e0ja4jXBGFkI3AfMeh7n1puqeGfDeq6eNO1Tw/pN9ZLO1wLe5s45IxKxYtJtYEbiWYlupLH1r5k+z33/Q0+M//AAqtR/8Aj9H2e+/6Gnxn/wCFVqP/AMfo+sxD6lU7o+jLrwZo194sm13VLGw1EGC1jtoLmzST7NJA8zLKjNnDfvsDABG3rzxp3Xh/QbrXLfXbrRNNn1a2XZb30lqjXES88LIRuUfM3APc+tfMH2e+/wChp8Z/+FVqP/x+j7Pff9DT4z/8KrUf/j9N4qL1G8FUfVH1jRXyd9nvv+hp8Z/+FVqP/wAfo+z33/Q0+M//AAqtR/8Aj9L6zEX1Kp3R6p+07/yDPBf/AGMh/wDTdfV5pVKTTvOubW4vdW8Qag1pKZoEv9cu7qONyjJvCSysu7a7jOM4Y1drnqzU5XR24ek6UbMK9L/Zi/5BnjT/ALGQf+m6xrzSvS/2Yv8AkGeNP+xkH/pusavDfEZY3+GvU63w3pPijSbp9H26OdB+1XNx9r8+VruRZneQR+VsCoVaTHmeY2Qn3AW+XmpPAXim98NHQr2TRIY9O8O3Wi6dNDNIxuzKkaLLKpjHkACIZRTJkt1+UZ9VorvjJxd/6/rV/wDDnmxm4tOPQ4Lxb4Q1i/1HUtQ019PMkkOkm1inldFaSzupJ2V2VG2qwZQGAYjnjjmVPCOpnxYusSSWQi/4SH+1Cgdiwj/s37LtHy/e8zn0285zxXVa7q+n6Hpzahqlx5FsrpGWCM5LOwRFCqCSSzAAAdTWKPGmjQWt1eXN7cSxrdpbxW0Ok3X2pXaBJREYQrSO+1i52oNq8MAUY1Uaktbf1t/khqUrW8rfK1vyOU1P4d6zss7u2aO7u7e51Mm3j1+80tWiurszq3nWylyVAUFCpUliQRtGbcvw+v00HXtMtZbBPt/hiDR7c75dqyoLjcWLl32EzLglnbg59+kn8c+GotIs9UW7u7iG83+THa6fcTz/ALs7ZN0MaGRNjfK+5RsYgNgnFb1hd2t/YwX1lcRXNrcRrLDNEwZJEYZVlI4IIIOaSlJXf9dw9o1Lm6vX8b/ocRqPhvxZGniqPR7mwhGq3ltd28v2uWGRgscMU8DMsZMW5ISFlQswL5CgqCc/wl4B1rTNVtb+6ntgq67/AGnJE2pXN68aHT2tvLE04LyEOQcttG3oFwFr02ilGclrfpb5af5L+m7pSaVv62seG/tG/wDJQfBv/YK1b/0bp9cTXbftG/8AJQfBv/YK1b/0bp9cTXn4j4z1MH/CCq11/wAhPw9/2Mmj/wDpxt6s1Wuv+Qn4e/7GTR//AE429Z0/iRtW/hy9GfWNFFFekeGFZviDX9B8O2kd34g1vTdIt5H8tJb66SBGfBO0FyATgE49jWlXD/Eqz8SXOqaU2h2V4YhFPHLeactl9rgZjHtXN2GUQMAxfYrPlEwDzlSbS0HFJ7nUHXdEF5a2Z1nTvtN4gktoftKb51KltyLnLDarHI7AntTdA1/QvEFvLcaDrWm6tDFJ5cklldJOqPjO0lCQDgjj3rzPw74C1+PwlqGkXNrDa3U/g2x0eN2lUoZ4xciRCVz8vzpk7cYbgcEDvvClxe3tzc3d74Pk8PsIooA9zNbvPMF3Hb+5ZwI13fLl85ZvlXq2kopSaTuDVvw/Jf5/h93QUUUVAgr5Otf+Qn4h/wCxk1j/ANONxX1jXyda/wDIT8Q/9jJrH/pxuK58T8J2YL+I/QsjGeeldB4St5tf8E+NfA1rPFHc6nplw+nvcPtiBngMLxggZCo4jZjg8yjAOa584PFLG9xBdxXtpdT2l3ESUuIW2yDIIIzg8EE5+vYgEYUavs5XOzE0fbRsdP8AFXVf7S8SQ6XBIWt9Hy8zKMhrxlC7hgcbEcr9ZWBAKk1y/HHXPqTn8qZBDHBEsUShVT7vcj156k8nk5JyT1p9KrVdSVyqFJUoWQUUUVkbdLBRRRQAUUUUAYPxF/5J94j/AOwVdf8Aopq+xq+OfiL/AMk+8R/9gq6/9FNX2NXZhtmebjviQU2RtkbPjO0E4p1I6h0ZD0YYNdEr20OJb6nnFl8QXktNO1/U9CktYrvQ7nVLaO31FpCYV+zEK8ZVE8xjLgEk7QvDYdgIofFHifT/ABVrZ1jR4kvTY6ZDZadBqjS2rTTT3KBvNaNSgOF3t5eQE4D4APRf8IDoTaXp+mTtdz2tjo0mjIjygGSBxECWKgHf+5XBXGMnjpjH1rwNLZ6RqV7Fe+IPE2r3CWaiSa7tobhBbzM8ckJESwiRPMYhXARyoDnBYnaUoLRbf/bfnb5XKk1ZqPb8br8PTUh1P4nyaRaXket6bpGkajb6ommL9u1oQ2TSG2W4LtcNHlU2khf3ZYnb8oydvV+AvE1t4t8NQ6za/Z9rSSQv9nuVuIS8blGMcq8SISuVbAJBGQpyBy3hPwZf3VhqN/q13relapdaqL+1uZJLV763K2yW5Zwivb7nVXyqqyBXGAGHHd6LYHTdOjtGvry/dSWe5u5A8srEkljgBRyfuqFUDhQAAKhpLTyX32V/1Jdnt/X9f13LlFFFSI+Y/GX/ACVzx7/2Fbb/ANNtlVQcVb8Zf8lc8e/9hW2/9NtlVOvNrfGz2aH8Jeh2vwc/5GW4H/Tk3/oaV1Gk/wDJaPEv/Yu6R/6U6lXL/Bz/AJGa5/68m/8AQ0rqNJ/5LR4l/wCxd0j/ANKdSr1ML/DR5OP/AIzO6ooorQ5jh/jj/wAka8c/9i9qH/pPJXXVyPxx/wCSNeOf+xe1D/0nkrrq0MzzH4z/APIQ07/rk38xXAV6B8aAf7Q07pjym6nHcVwGD6H8q8fEfxGe/g/4SEopcH0P5UYPofyrGx1iUUuD6H8qMH0P5UWASilwfQ/lRg+h/KiwCUUuD6H8qMH0P5UWASilwfQ/lRg+h/KiwCUUuD6H8qMH0P5UWASilwfQ/lRg+h/KiwCUUuD6H8qMH0P5UWASilwfQ/lRg+h/KiwCUUuD6H8qMH0P5UWASilwfQ/lRg+h/KiwCV6X+zF/yDPGn/YyD/03WNea4PofyrY+Fvj0+BP+Eksr3wj4h1NdQ1cXsE9g1oYyn2S2iwfNnRgwaF/4cYxzW9BpS1OTGRcoJLXU+j6K8j/4XrZf9E98afnp3/yXR/wvWy/6J740/PTv/kuuvnj3PO9lP+VnoHjbR7jXNHgs7ZoVePUbK6bzSQpSG5jlYcA8lUIHvjp1rnNd8IatONcmt7bTL2S91lL+3jlv7iykRBaRQnZcwqZIJMo3KhtyEqcbyRhf8L1sv+ie+NPz07/5Lo/4XrZf9E98afnp3/yXTVVJNJ/1p/kilGqlaz+4s6j4B8Rzafod1LdPqOpWEN1BJAfEt9YgRzSK6L9rhUyzeWEVMyLl/vHaRg+g+FtLGi+HNP0lfL/0S3SI+WXK5A5wZGZyP95mPqTXmv8AwvWy/wCie+NPz07/AOS6P+F62X/RPfGn56d/8l0vaR7on2U/5fwPXKK8j/4XrZf9E98afnp3/wAl0f8AC9bL/onvjT89O/8Akujnj3D2U/5WZP7Rv/JQfBv/AGCtW/8ARun1xNaHxD8XN448Y6DqFt4Z1rSLbTNPvoZX1Brb53mktCgUQzSHpC+c47dc1QwfQ/lXFXac9D08KnGnZiVR1idbNtKv5Y7h4bPW9Mup/IgeZ1iivoJJGCICzYVWOACeKv4PofyowfQ/lWcXZ3N5R5otdz1//hd/w6/5/de/8JjUv/kej/hd/wAOv+f3Xv8AwmNS/wDkevIMH0P5UYPofyro+svscf1GPc9f/wCF3/Dr/n917/wmNS/+R6P+F3/Dr/n917/wmNS/+R68gwfQ/lRg+h/Kj6y+wfUY9z1//hd/w6/5/de/8JjUv/kej/hd/wAOv+f3Xv8AwmNS/wDkevIMH0P5UYPofyo+svsH1GPc9f8A+F3/AA6/5/de/wDCY1L/AOR6P+F3/Dr/AJ/de/8ACY1L/wCR68gwfQ/lRg+h/Kj6y+wfUY9z1/8A4Xf8Ov8An917/wAJjUv/AJHrxHR51vG1W/ijuEhvNb1O6g8+B4XaKW+nkjYo4DLlWU4IB5q/g+h/KjB9D+VRUq86sa0cMqUrpiUUuD6H8qMH0P5VjZHQJRS4PofyowfQ/lRYBKKXB9D+VGD6H8qLDEopcH0P5UYPofyosAlFLg+h/KjB9D+VFgM/xHp39seHtS0nzvI+22ktt5m3ds3oV3YyM4znGRXYf8LO+Kf/AEEfBn/ghuf/AJNrn8H0P5UYPofyq4zlHZmU6MKmskdB/wALO+Kf/QR8Gf8Aghuf/k2j/hZ3xT/6CPgz/wAENz/8m1z+D6H8qMH0P5VXtp9yPqtLsdB/ws74p/8AQR8Gf+CG5/8Ak2j/AIWd8U/+gj4M/wDBDc//ACbXP4PofyowfQ/lR7afcPqtLsdB/wALO+Kf/QR8Gf8Aghuf/k2j/hZ3xT/6CPgz/wAENz/8m1z+D6H8qMH0P5Ue2n3D6rS7HQf8LO+Kf/QR8Gf+CG5/+TaP+FnfFP8A6CPgz/wQ3P8A8m1z+D6H8qMH0P5Ue2n3BYWl2K6tqt5rWs63rd1ZXF/q12lzL9jtWgiTbbxQBVVpJD92EEkt1J6VPS4PofyoxWb953ZsoqMbI7T4Of8AIzXP/Xk3/oaV1Gk/8lo8S/8AYu6R/wClOpVy/wAHP+RnuRg5+xNwBn+NP8a6jSf+S0eJf+xd0j/0p1KvVwtvZo8THr96/Q7qiiitDmOH+OP/ACRrxz/2L2of+k8lddUGvaNa63o9/o+p232iwv7eS2uYt5XzIpFKuuVIIyCRkEGua/4Vnof/AD/eMP8AwsNU/wDkmruRY0fEnhjTtfmhlvXuFaJSF8pwOpHXINZH/CuPD/8Az0vv+/i//E1N/wAKz0P/AJ/vGH/hYap/8k0f8Kz0P/n+8Yf+Fhqn/wAk1Dpwbu0axrTirJkP/CuPD/8Az0vv+/i//E0f8K48P/8APS+/7+L/APE1N/wrPQ/+f7xh/wCFhqn/AMk0f8Kz0P8A5/vGH/hYap/8k0vZQ7D+sVe5D/wrjw//AM9L7/v4v/xNH/CuPD//AD0vv+/i/wDxNTf8Kz0P/n+8Yf8AhYap/wDJNH/Cs9D/AOf7xh/4WGqf/JNHsodg+sVe5D/wrjw//wA9L7/v4v8A8TR/wrjw/wD89L7/AL+L/wDE1N/wrPQ/+f7xh/4WGqf/ACTR/wAKz0P/AJ/vGH/hYap/8k0eyh2D6xV7kP8Awrjw/wD89L7/AL+L/wDE0f8ACuPD/wDz0vv+/i//ABNTf8Kz0P8A5/vGH/hYap/8k0f8Kz0P/n+8Yf8AhYap/wDJNHsodg+sVe5D/wAK48P/APPS+/7+L/8AE0f8K48P/wDPS+/7+L/8TU3/AArPQ/8An+8Yf+Fhqn/yTR/wrPQ/+f7xh/4WGqf/ACTR7KHYPrFXuQ/8K48P/wDPS+/7+L/8TR/wrjw//wA9L7/v4v8A8TU3/Cs9D/5/vGH/AIWGqf8AyTR/wrPQ/wDn+8Yf+Fhqn/yTR7KHYPrFXuQ/8K48P/8APS+/7+L/APE0f8K48P8A/PS+/wC/i/8AxNTf8Kz0P/n+8Yf+Fhqn/wAk0f8ACs9D/wCf7xh/4WGqf/JNHsodg+sVe5D/AMK48P8A/PS+/wC/i/8AxNH/AArjw/8A89L7/v4v/wATU3/Cs9D/AOf7xh/4WGqf/JNH/Cs9D/5/vGH/AIWGqf8AyTR7KHYPrFXuQ/8ACuPD/wDz0vv+/i//ABNH/CuPD/8Az0vv+/i//E1N/wAKz0P/AJ/vGH/hYap/8k0f8Kz0P/n+8Yf+Fhqn/wAk0eyh2D6xV7kP/CuPD/8Az0vv+/i//E0f8K48P/8APS+/7+L/APE1N/wrPQ/+f7xh/wCFhqn/AMk0f8Kz0P8A5/vGH/hYap/8k0eyh2D6xV7kP/CuPD//AD0vv+/i/wDxNH/CuPD/APz0vv8Av4v/AMTU3/Cs9D/5/vGH/hYap/8AJNH/AArPQ/8An+8Yf+Fhqn/yTR7KHYPrFXuQ/wDCuPD/APz0vv8Av4v/AMTR/wAK48P/APPS+/7+L/8AE1N/wrPQ/wDn+8Yf+Fhqn/yTR/wrPQ/+f7xh/wCFhqn/AMk0eyh2D6xV7kP/AArjw/8A89L7/v4v/wATR/wrjw//AM9L7/v4v/xNTf8ACs9D/wCf7xh/4WGqf/JNH/Cs9D/5/vGH/hYap/8AJNHsodg+sVe5D/wrjw//AM9L7/v4v/xNH/CuPD//AD0vv+/i/wDxNTf8Kz0P/n+8Yf8AhYap/wDJNH/Cs9D/AOf7xh/4WGqf/JNHsodg+sVe5D/wrjw//wA9L7/v4v8A8TR/wrjw/wD89L7/AL+L/wDE1N/wrPQ/+f7xh/4WGqf/ACTR/wAKz0P/AJ/vGH/hYap/8k0eyh2D6xV7kP8Awrjw/wD89L7/AL+L/wDE0f8ACuPD/wDz0vv+/i//ABNTf8Kz0P8A5/vGH/hYap/8k0f8Kz0P/n+8Yf8AhYap/wDJNHsodg+sVe5D/wAK48P/APPS+/7+L/8AE0f8K48P/wDPS+/7+L/8TU3/AArPQ/8An+8Yf+Fhqn/yTR/wrPQ/+f7xh/4WGqf/ACTR7KHYPrFXuQ/8K48P/wDPS+/7+L/8TR/wrjw//wA9L7/v4v8A8TU3/Cs9D/5/vGH/AIWGqf8AyTR/wrPQ/wDn+8Yf+Fhqn/yTR7KHYPrFXuQ/8K48P/8APS+/7+L/APE0f8K48P8A/PS+/wC/i/8AxNTf8Kz0P/n+8Yf+Fhqn/wAk0f8ACs9D/wCf7xh/4WGqf/JNHsodg+sVe5D/AMK48P8A/PS+/wC/i/8AxNH/AArjw/8A89L7/v4v/wATU3/Cs9D/AOf7xh/4WGqf/JNH/Cs9D/5/vGH/AIWGqf8AyTR7KHYPrFXuQ/8ACuPD/wDz0vv+/i//ABNH/CuPD/8Az0vv+/i//E1N/wAKz0P/AJ/vGH/hYap/8k0f8Kz0P/n+8Yf+Fhqn/wAk0eyh2D6xV7kP/CuPD/8Az0vv+/i//E0f8K48P/8APS+/7+L/APE1N/wrPQ/+f7xh/wCFhqn/AMk0f8Kz0P8A5/vGH/hYap/8k0eyh2D6xV7kP/CuPD//AD0vv+/i/wDxNH/CuPD/APz0vv8Av4v/AMTU3/Cs9D/5/vGH/hYap/8AJNH/AArPQ/8An+8Yf+Fhqn/yTR7KHYPrFXuQ/wDCuPD/APz0vv8Av4v/AMTR/wAK48P/APPS+/7+L/8AE1N/wrPQ/wDn+8Yf+Fhqn/yTR/wrPQ/+f7xh/wCFhqn/AMk0eyh2D6xV7kP/AArjw/8A89L7/v4v/wATR/wrjw//AM9L7/v4v/xNTf8ACs9D/wCf7xh/4WGqf/JNH/Cs9D/5/vGH/hYap/8AJNHsodg+sVe5D/wrjw//AM9L7/v4v/xNH/CuPD//AD0vv+/i/wDxNTf8Kz0P/n+8Yf8AhYap/wDJNH/Cs9D/AOf7xh/4WGqf/JNHsodg+sVe5D/wrjw//wA9L7/v4v8A8TR/wrjw/wD89L7/AL+L/wDE1N/wrPQ/+f7xh/4WGqf/ACTR/wAKz0P/AJ/vGH/hYap/8k0eyh2D6xV7kP8Awrjw/wD89L7/AL+L/wDE0f8ACuPD/wDz0vv+/i//ABNTf8Kz0P8A5/vGH/hYap/8k0f8Kz0P/n+8Yf8AhYap/wDJNHsodg+sVe5D/wAK48P/APPS+/7+L/8AE0f8K48P/wDPS+/7+L/8TU3/AArPQ/8An+8Yf+Fhqn/yTR/wrPQ/+f7xh/4WGqf/ACTR7KHYPrFXuQ/8K48P/wDPS+/7+L/8TR/wrjw//wA9L7/v4v8A8TU3/Cs9D/5/vGH/AIWGqf8AyTR/wrPQ/wDn+8Yf+Fhqn/yTR7KHYPrFXuQ/8K48P/8APS+/7+L/APE0f8K48P8A/PS+/wC/i/8AxNTf8Kz0P/n+8Yf+Fhqn/wAk0f8ACs9D/wCf7xh/4WGqf/JNHsodg+sVe5D/AMK48P8A/PS+/wC/i/8AxNH/AArjw/8A89L7/v4v/wATU3/Cs9D/AOf7xh/4WGqf/JNH/Cs9D/5/vGH/AIWGqf8AyTR7KHYPrFXuQ/8ACuPD/wDz0vv+/i//ABNH/CuPD/8Az0vv+/i//E1N/wAKz0P/AJ/vGH/hYap/8k0f8Kz0P/n+8Yf+Fhqn/wAk0eyh2H9Yq9yH/hXHh/8A56X3/fxf/iaP+Fb+H/8Anpff9/F/+Jqb/hWeh/8AP94w/wDCw1T/AOSaP+FZ6H/z/eMP/Cw1T/5Jpeyp9hfWKvcu+HfCWl6Devd2TXDSNEYiJWBGCwPYDngVnaT/AMlo8S/9i7pH/pTqVSf8Kz0P/n+8Yf8AhYap/wDJNaXhjwZpPhy9vL3Tk1KS6vY4op577Vbm9kZIi5RQ08jlQDLIcDAyxrSKUVZGcpSk7s6SinbG9KKm47H/2Q== +
+ 1.0000000 + 0.3333333 + 0 + + Your answer is correct.

]]>
+
+ + Your answer is partially correct.

]]>
+
+ + Your answer is incorrect.

]]>
+
+ /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCACVAkMDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD6wooorrOQKKKKACiiigAooqK7uILO0mu7qZILeBDJLI5CqigZLEngADkmgCj4l17SvDumG/1e7NtAziNdsbSPI552oiKzOQAWwFPCsegNZviTxtoeh2Fvcea2oy3caS2ltYskks8ZIxIu5ggT/bZlU9ASSqnybxLrk/ifWn1WRHitEXytPt/ulIDgiRlPR5CMn+6AoxkFjl29tb25lNvbwRGWUyybECh2PBPT733RkjJUHkiuGeMSlZHpUsvcopydj6Bttc0mfw9H4h+3RRaY8Cz/AGidvLCRkZy2/BXAPIPIIrF8MePtE1/V20y3jvraRk32sl3EI1uwBltmSWVlAyUdUb72F+Vtvi620O5d3mOiSCWOJ5G8tH/56BDlEc92ALHuaddW8F3A0FzDHPE4AkWRAwYDBAIPB5ye/U9qj66+xost0d3r0PeNW8U+HNJumtNR1uwgutu77MZgZyPaMHe34Cqmj+OvCuq3ItbTVVjmd/LSO6gktjK/91PNVd59hmvErW3t7WLyLaGOGE8bYlCgD3AH9adPHHcwtFPFHKjgq8ciKyHIwwwRyCODweKPrz7CWWK17n0fRXknwu8T3dlrUXh/U72e5sbgbLNriQyPBLyQrMc5V+QNxO0hUGQyhfWzx1rup1FUV0edVpOlJxluFFFFWZhRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRkZxRWH4u8U6T4Ztomv2lmuLjP2e0gXdLNhcnAJAAHHzMVXLBd2WFDdhpNuyM/wCJviY+HtDEVnKq6rfEx2hwGMfTfMUPVY8jrwWZB1YZ8fkuNUn0+LT7/WNS1CzgffHBd3HnBTu3AM5w02G+YeYWCnG3AFTarf3us6zcazqTr9pmwqojFo4Y1LbY0PBIGSdxA3EnhQQBBXk4jEylK0T28LhIxjeS1Ex1BBP1PX/9XpS0UVyneFFFFABRRRQAyZPMRQrPEyuJImTGYZB0dSfusOCCM4NewfDzxlHr8J07UfKt9agjzMiZCXCrgGaPPO3OAyZJQ4BJBV28ioiuJ7G7tdTskP2mynjuYlUKpcpnKBj93epdCegVyK6cNX5HY48Zh1VjzLc+jaKpaJqtjrWlw6jps4ntpclTyCrDOVKnlWBBUqeQRg1dr107q54DVgooooAKKKKACiiigAooooAKKjtp4LmMyW80cyK7xlo2DAMjFWXI7hgQR2IIqSgAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACgc9KKraff2mo273FnOs8azSwMy54kido5F57qyMp9dtAFmiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKK4X4k+Jde0HULOLSn08QTREyCe2Z3JBx8pEigfiDUTmoK7KhBzdkd1RXit1458V3AG3U4rbII/cWkec/wDA91YGqXep6xF5et6vfanHs2NHO6pE6k8hoogsTH0bYT71zvGU0dkcvrS6Hrfib4geH9JWWC2uE1fUY2Mf2W0cOUf0lb7sXH97Bx0BPFeR3dzeahqE+qalP59/cY82QcBACcRxjsi9hz1JySzM0aqFCqFVUAyFUcDjGBzx9MClrjq4h1PdR6WHwcaOu7CiiiuY6wooooAKKKKACiiigApQASPekooAu+G9b1Xw5fNd6U6mKVg13ZOx8q5YAZYHHySYAAbA6KG3bQK9x0DVbPWtFtdVsG/0e4jDhTjdGc4KNjhWVsqw6gqQeRXgPTnI/EZrY8J+JdR8M3++AS3OnSSZuLHcvXAy8ecBWGOB91gOfmO8duGxHLpLY8zGYPm9+B7rRXOaP468J6n5Swa1bQTytsS3uybaZ277UkALD3UEV0Y5AI5B6H1r0lJPZnkOLW4UUUUxBRRRQAUUDnp6ZooA5P4TknwveEk5HiDWh17f2pc4/QV1lcl8Jv8AkVr3/sYNa/8ATpdV1tCAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiisjxN4i0zw5Bbz6m86xzy+WpihaVgdpbJCgttwO3cii4JXNeisnwx4i03xJb3FzpbzPFbz+QxliaMltitkBgDjDDr3BrWoAKKKKACiiigAooooAKKKKACiiigArk/hR/yK95/2MGtf+nO6rrK5P4UEf8ACMXvt4g1r/053VAup1lFFFAwooooAKKKKACj/wDVRXD/ABA+IUPhLXLPTri0tQk8BnNxfXws4pcNjyYZHXy3m4zsd4xhl+bngE3Y7ij/AOvXB3fxIs4vFE2lW9lHcW9vqUOmXDLcj7V58hVAyQbfmiVpFDOWBwshCkAM0Nn8T7BvFK6RejSbW3ee6h86LVo7iW2a3V3f7SiDy4QVjkYfvGIGNwU7gquFz0KivP8AWvH+kxatY6vp+u2mo+HItF1W/vJbCRLlW+zG2J2spIJVXk49TVaH4qRIs5vdJhUwJb3EklpffaIYraS5WGRnkCDa8W7eyDK7VJV2Ap3C56TRXn+ofEu2guJLWCxtxNLqN1ZWEl5efZ7edbUIs8rvsYxhZmaIBVdmKgjAJ2y+DPF9x4l8VW5iSe20+fSHnNpMiZSaO6aEsGHLKSvykHay4YdaLhc7uiiigYV5j8Z/+Qhp3/XJv5ivTq8x+M//ACENO/65N/MVzYv+GzrwP8ZHAUUUV5B9AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFH4kD2oooARl3DayqQeoJyPwPUD6VFY2ltYySTWEa2Ez/emtCYXb6sm1jU1FNSkvhJcIS+KI+C71WBy6a7r5J/vavcyAfg0gA/CtJPFPiyPYIPEl9HGpHyNHBJn6l0Zv1rKoq1Wn/MZPDUn9k6i3+IvjBZW859Fki4VALGQOPcnzsH8AK04vijqiyRxyeHrORMYeVb9kOfZPKP/AKFXCUVosXUMngaL2PTh8WfDUdos+o2ms2jlseULB7ls+uId4x7nmpl+LHgUsiNrSQyPysU6GKT6bHwa8rpMckDnd1zgfnxyK3hjH9pHNPLE/hZ6F8K/FelReGr1GF0xOu6vIGWBiCr6jcODn0+YV1n/AAl+k4J23mBjn7M3fp2rwj+zrJZGnt4WtbhyC0ttI0EjAZwN6ENjJ5BODknFadhrutaawFwf7YtwSckJFcoSWztYYQjlRggcZO5ulehhcVhqmk00zy8XgsZS1hZo9k/4S/SOu2864/49m6/lR/wl+kf3bz/wGb/CuL0q9stUs0vNNuPNgcYDcq6kNjayt8wYcgowGDg1Z2f7R/MV7MMBRmuZM+enmVenLlkjq/8AhL9I/u3n/gM3+FH/AAl+kf3bz/wGb/CuV8s/3j+Yo2H+8fzFX/ZtPuL+1KvY6r/hL9I/u3n/AIDN/hR/wl+kf3bz/wABm/wrldn+2fzFGz/bP5ij+zafcP7Uq9jqv+Ev0j+7ef8AgM3+FH/CX6R/dvP/AAGb/CuV2f7Z/MUbP9s/mKP7Np9w/tSr2Oq/4S/SP7t5/wCAzf4Uf8JfpH928/8AAZv8K5XZ/tn8xRs/2z+Yo/s2n3D+1KvY6r/hL9I/u3n/AIDN/hR/wl+kf3bz/wABm/wrldn+2fzFGz/bP5ij+zafcP7Uq9jqv+Ev0j+7ef8AgM3+FH/CX6R/dvP/AAGb/CuV2f7Z/MUFMdXI/EUf2bT7h/alXsdV/wAJfpPZbz/wGb/CvNPiVr1vr/ii2itRL5GnWxUMfl3ySsC6sD/dWOIg9/MNbl1JBawTXV3OIbeBGkmkLABUUZY+2B19K86sWmnEt9coy3N9KbidXwWUsB8hPQ7YwiZHZa8jNqNKhTUU9We5kdWtia3NJaR1Ot+FuvWuieI763uzcsL+zjkhSOIsFML4djju3noP+Ae1ej/8JfpP928/8Bm/wrw/z/sV/p+oEsUt7kCbDAKY3+RyfQKHDf8AAM9q9GEWVGDuB+YVWVUKdelq9iM7r1MLW0W51X/CX6R/dvP/AAGb/Cj/AIS/SP7t5/4DN/hXK7P9s/mKNn+2fzFer/ZtPueN/alXsdV/wl+kf3bz/wABm/wo/wCEv0j+7ef+Azf4Vyuz/bP5ijZ/tn8xR/ZtPuH9qVex1X/CX6R/dvP/AAGb/Cj/AIS/SP7t5/4DN/hXK7D/AHj+Yo2H+8fzFH9m0+4f2pV7HVf8JfpH928/8Bm/wo/4S/SP7t5/4DN/hXK7P9s/mKNn+2fzFH9m0+4f2pV7HVf8JfpH928/8Bm/wo/4S/SP7t5/4DN/hXK7P9s/mKNn+2fzFH9m0+4f2pV7HVf8JfpP928/8Bm/wrlfhd4p0uDw5fRSLdk/29q7g/Z2PDajO/p1w2PwoEfI+b9a5z4dx50S+wP+YzqY/wDJ2aoeXU7rUtZjVcHKx6b/AMJfpP8AdvP/AAGb/Cj/AIS/Sf7t5/4DN/hXK+UfWjyjV/2bT7kf2pV7HVf8JfpP928/8Bm/wo/4S/Sf7t5/4DN/hXK+UaPKPrR/ZtPuH9qVex1X/CX6T/dvP/AZv8KP+Ev0n+7ef+Azf4VyvlGjyjR/ZtPuH9qVex1X/CXaT/dvP/AZv8K5/wATHwt4ieX7fJriRXVo1neQxGVI7mAk7o3Xkc7mw64fBPzDFVfKPrR5RoeW0+4v7UqvoSyQeD21N74R6uqy3cV7NZx+atvJcxBBHKY+mR5aHAwpKqzAsAai0yw8G6fe6RdQS6+66I8n9mwSPM0VsskbIVCkfMAr4BYsyj5QQMqTyjR5R9aX9mUu4f2pV7Grq974U1i9iudTs7ufZZ3Nm0Ulsxjkhn8sSq6jhgfLX9aowxeDlttRtrtNZ1GHUbL+z5hemaYi12v+5UnnGHYFs7243MSBiDyjR5Ro/syl3F/alXsTRx+EotG0bTbUatZvo0e2wu4Y38+E7drZfB37xnfuBDHBILAEavg608LwapEdEtryKa3smt1MplIMZk8xtxc5ZizFizHcdxzzmsTyjnrW54LQLqch/wCmJ/mtY4jAwpU3JM6MNmFSrUUWjrqKKK8s9oK8x+M//IQ07/rk38xXp1eY/Gf/AJCGnf8AXJv5iubF/wANnXgf4yOAoooryD6AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACilwfTrSDrxyaAA8HB4OcfjQSRyDg+v/wBaqOr6xpejxpJqF9DAJcLEhyZJyegRBy59lyay11LxBqmBo+lLp9s3P2rVBhsDusCEMR/vMh9M0+UmTN8XNzpNw+p2JRXjDefBI2I54+u1z0yMDa38B7lTtPomgarp2v6La61pV2t3Y3aeZDMr5zk4YHHQjABHYgivH4vC1nPIJ9aubjWp8ghbvHkRn1EK4jH12lh6966vwzrEfh7UXM5K6RdMglYn5bRvuiQ9whHyvztGA54Lk+3lmPcHySeh87nGWe2j7WnHVfieh7PajafQ/mKu+WvpR5YyRtOR1FfT+0PkHTsUtp9D+Yo2n0P5irvlpnGOaPKH92j2hPsiltPofzFG0+h/MVd8pfSjyl9KPaByFLafQ/mKNp9D+Yq75S+lHlL6Ue0DkKW0+h/MUbT6H8xV3yl9KBEhOADmj2geyKJAHXj8RShdpzypzjtnNXPLXnqAOufyrm/GHiCPRkFjpyxTarNHuSN1JjgQkjzZQCCFyWUAEM5GOiuy5VcTGnG8jajhpVpcsDD8e6kJ5h4dtZOBtOoFe0YAKw56bmOCR2ReQN6k4hzjHc4zj1I/+tio4IvLDFneWWRjJLNIQWkZiSWOABlicnAUABQAMYElfG43GPE1Oboj9Ay7BRwlLlXXcZPFFNC8M0aSROux0ddysuMEEdx7V1/gPUTqGkfZLqdpNQsCIrkyPvaUfN5cpJ5O4AEsON6uB91scnz2xmlt57qx1CDU7Bv9IhDKY3bak0bfejY8keqn+Fgpzjcra5di3halnszHNsAsXRuviW3oenbTkDByegyKNvsfzFM0HUdP1vT/ALbYSfKDtmiIAeJ8DdHIo6MMg4yRjaVLrg1fES88dBmvsIV1NXR8FUounK0intPofzFG0+h/MVdMSjGRjPT3o8pfSq9oR7MpBGJwAc/UUBSRkcg98in6vdWml6TeanfyeTaWdvJPPIULhI0Usx2jk4A6DrVoxqWzgHrgsM8/z5BP0NL2pXsyltPofzFG0+h/MVd8pfSjyl9KftCeQpbT6H8xRtPofzFXfKX0o8pfSj2gchS2e1cz8OE/4kd//wBhzVP/AEumrsvJHpXLfDKPdoWoE9te1Uf+T9xWbqe+jaMP3bNzaPQ0bKveUvpR5a+lae0MeQo7KXYPQ1d8oc/L060eUuemcdeMn8qTqgqdyjsHHTkZFGz+ePx64rP1/wAQ6TorGCYyXV/tyLO2w0p5PU8BBwcO5GSNq5NcbfeIPE1zc/bYryG2KMDHYxqpiZVOSjyMhchvm5UKMMPk3LluOrmVKk0mz0KGVV66dkehBQc4BOOtGznHeuF13xPf6tLEujy3WlW6IGkkkt4zMZTwY/3gcBEPddwc9DsBL3tG8ZNAq2/iG2fP3Uu7WAuj+nmICzAnJ5AIOCSY87aUc0oyly3Llk2JjT5+U6zZzijaPQ07Sr/S9WthcaXf219BnG6CVXUnv0JwR6GrhiUEgjp1rtjWUtjznRcd0UdlGyrvlp6UpjUHBFV7RE8hR2j0NbHhNNuoSEd4j/Naq+UuM44rS8Oxhb2Rh08v+orlxU+akzpwcLVos36KKK8U+hCvMfjP/wAhDTv+uTfzFenV5j8Z/wDkIad/1yb+Yrmxf8NnXgf4yOAoooryD6AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKBycDk0c9utYEnht9QkY6/qtzqULMSton+j2wB7MgJMnuZCw/2e1USx974o09J3tNMjl1q9BwYbFVcKT2kkOEj9wzbj6VEbTxNqp/07UIdFtWGBBZEzXA/wB6V12r9EQ/7w61uWlvb2dsltaQRW8CDCRRJsUD2AOPrnFS0XQWkZuj6DpOkyPNZWii5lBWW5lYyzy5675G+Yg+hJA9BWjzxnknr7Clopcw4x5QpeD1BPtx06EUlKvWhO2w7J6Mk0zxZqHhV9N0yGJL+xu7g29vbvIYzbYjeXCPzmMLHIQpXIZlUFVUAdbbfEDSWRjfaZq1hGvUvB54c+qrCzN+JANeYeI/+Qz4X/7Cb/8ApFdVu16FPMK1ONr3PJrZTQrSk7WPRY/GHhZoBNLr1paIe145tyPwlANXtL1jRtUGdM1rT74f9O9ykn/oJNeWY75zjsT1/So7qCC5j8u5hinjJ+7KiuP1BrpjnM+sTjlkFN/DI9o8tqPLavC20LQ266Lpp+tqlN/4R/QO2iaZ/wCAqf8AxNa/2wuxn/q+/wCY928ujy2xmvEY9N0+NAq2FqFHRRGqj8MCkm0vS5l2TadaSqDnBt1P8xR/bMf5Sf8AV9/zntrhY13yOqKP4mOBWFe+L/C1usivr1jPIhw8NtIbiVfrHEGP5g15ZBoujW8glt9JsYZPVLdAf6irwwAAAAPbt+Y/lUSzhvZFx4fivikdDrHja+vFMOi2T2MRyDdXiK0hXPBjjBOCRzl8YIAMYzXNQxGMvK0kk080hkmmlcvI8hAyxJOTwAOSRwoAG0ASUV5tbGVK3xbHs4XAUcKvc1YUUUVynYFB6UUUARos8F0L2xu7iwvNm0z27Dnk9VYEEctgMG2lsgA810mn+ONatwi6hp9pfxhizTWzmCQADjEb7lLe+9R7Vz9BxjkflXVRxlalonocdbL8PX1ktTu7Lx14ekCpezTaTIykut5GURceswzEM+m/NdSEygccqcYPY5rxwkjgjIPLAYIP6j+db3wz1NtJ12PQyT/Z2oBhbKpO2CVF3bQAMBHUE4AADKDjLk162FzNzfLI8LG5MqUHKkzf+LSEfCrxcfTQ73/0Q9dMib0VhWJ8X0I+EvjBsdNDvc/9+HrpbWPNrH8pB2L2/wBkV6ntPePGcPcKvl/yz+FL5Z546cHjpWb4y8QWvh2xQtAbq9um22lorgGRgBl2JB2xrkbnIO3cqgbmUHy3Wbi912VpdcuPtqsQY7QrttoQOypk5+rbmz0ZRgLy4jMI0dDrweV1MTqj0u78TeGLO6a1u/Emj29wvWKW9jRx+BbNR/8ACW+Ef+hq0P8A8GEX/wAVXm0SLFGI4wEUdFU4A/AcfkadlvU/n/8AXrz/AO2Z/wAp6seH4dZM9Ebxl4NHB8X6ACOudSh/+Krm/h34s8JWuiX0dz4o0SB21rU5FWS/iUlHvpmVgC3QqQQe4INc8MnnPPfj/wCvR/np/wDXp/2xP+Ur+wY2tzM9GTxh4PcnZ4r0Jz/s38TE/QBqrXfjbw5DMYkubu7lwSqQ2cjK30kK+WPzrgupxkkZ45xSHkdPbFTLOaj+GIRyCkt5M6e68d3kpj/s/Q1hQggyX06+ZGf+ucYdXH1kXPtWBf6lrmpgLqWsXCpgfubEm3iUg54wfMwR1BkYegFQUVxVcwxFTrY76OV4en9m5HaW1vaRGO3ghgU5JWNdqgnG4DBPXLHOO/WpKKK5G5OV5HoKMYrliFH1oopDIZrO2muEuHi23EY2pOjFJo8/3XU5UfQ8dq0LPWPENguLPW5JEVAI4b5PtCRn68SN/wB9/hVWit6eJqU/hkc1TC0q3xROhs/HOsQmOO/0i0u41H72W2uGhY+yxHII9/MFalv8QND+ziS9tdW09iSCjWZlY+/+j7x+J5riqPr+lddPNa0fM4KmS4eeysejReLvCrBPM1/TrUvwqXcot5D/AMBkIPaup8Mywzy+fbTxTxPHlXjcMp57EV4i3uSSBxjt+GOtdX8HbGyPjKe8Fpb/AGlLJgs2wB8AqMbsA9/cV1QzOVV8jW5xVcmjQSqRex7DRRRWhiFeY/Gf/kIad/1yb+Yr06vMfjP/AMhDTv8Ark38xXNi/wCGzrwP8ZHAUUUV5B9AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFKvWkpR14OKAMLxGD/bPhgY5GpuD7H7HdVuVla3Zz3OpaFNEhaO0vmkkwwARPs0659/mdB+datU/hRK+IKKKKkoKKKKACiiigAooooAKKKKACiiigAooooAKKKKAA9KgvHnhhF3ap5tzaypdRR52iSWNg6DPYblCn1Ump6DyMVcXZ3IlHnVj0z4qzWt98EvFmoWbia2ufDV5LbyDo0bW0jKfpgrz3rqwbeDT/PuZkhiji3SO7BVRQASST0AHNeWvftdfs5eNrCQkzabpWp2pyMDb9maSNVHdRG4TPqhrf+L2qG28PWHh6GVhJqX+uZcjNrHtLnHQhiY4yh6q7HtXve3/AHamfKLCt1PZrucBqWo3Ouavdazco8a3AUQQuCDBCudiEH+LBLHIyC7KGZVFRUDgDC7RnOMADpgYAorwqk3OfMz6qjSVKKhEKKKKzNAooooAKKKKACiiigAooooAKKKKACiiigAooooAVetdp8Hf+RluP+vJ/wD0NK4sda7T4O/8jLcf9eT/APoaV0Yb+KjmxX8KXp+p6xRRRXsHzoV5j8Z/+Qhp3/XJv5ivTq8x+M//ACENO/65N/MVzYv+GzrwP8ZHAUUUV5B9AFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRyOR1oooA1PCOsWmialeJq1mdQ0XVbP7FfweT5oZV37P3XQqQ7q477lJ4Q1U1nU7rXNaudZvYxBJOFjjgDBvs8S/djzjDcliccbpGI4AqtRWrrSceQwjQhGfOFFFFZG4UUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABXa/Bz/AJGa5/68m/8AQ0riq7X4Of8AIzXP/Xk3/oaVthf4qObF/wAGXyPWKKKK9o+dCvMfjP8A8hDTv+uTfzFenV578WNM1DUL6xeysJ7kJGwYxxlscjriubFJum7HVg2lVVzzSitX/hHNf/6A1/8A9+W/wo/4RzX/APoDX/8A35b/AArzPZy7Hu+1h3MqitX/AIRzX/8AoDX/AP35b/Cj/hHNf/6A1/8A9+W/wo9nLsHtYdzKorV/4RzX/wDoDX//AH5b/Cj/AIRzX/8AoDX/AP35b/Cj2cuwe1h3MqitX/hHNf8A+gNf/wDflv8ACj/hHNf/AOgNf/8Aflv8KPZy7B7WHcyqK1f+Ec1//oDX/wD35b/Cj/hHNf8A+gNf/wDflv8ACj2cuwe1h3MqitX/AIRzX/8AoDX/AP35b/Cj/hHNf/6A1/8A9+W/wo9nLsHtYdzKorV/4RzX/wDoDX//AH5b/Cj/AIRzX/8AoDX/AP35b/Cj2cuwe1h3MqitX/hHNf8A+gNf/wDflv8ACj/hHNf/AOgNf/8Aflv8KPZy7B7WHcyqK1f+Ec1//oDX/wD35b/Cj/hHNf8A+gNf/wDflv8ACj2cuwe1h3MqitX/AIRzX/8AoDX/AP35b/Cj/hHNf/6A1/8A9+W/wo9nLsHtYdzKorV/4RzX/wDoDX//AH5b/Cj/AIRzX/8AoDX/AP35b/Cj2cuwe1h3MqitX/hHNf8A+gNf/wDflv8ACj/hHNf/AOgNf/8Aflv8KPZy7B7WHcyqK1f+Ec1//oDX/wD35b/Cj/hHNf8A+gNf/wDflv8ACj2cuwe1h3MqitX/AIRzX/8AoDX/AP35b/Cj/hHNf/6A1/8A9+W/wo9nLsHtYdzKorV/4RzX/wDoDX//AH5b/Cj/AIRzX/8AoDX/AP35b/Cj2cuwe1h3MqitX/hHNf8A+gNf/wDflv8ACj/hHNf/AOgNf/8Aflv8KPZy7B7WHcyqK1f+Ec1//oDX/wD35b/Cj/hHNf8A+gNf/wDflv8ACj2cuwe1h3MqitX/AIRzX/8AoDX/AP35b/Cj/hHNf/6A1/8A9+W/wo9nLsHtYdzKorV/4RzX/wDoDX//AH5b/Cj/AIRzX/8AoDX/AP35b/Cj2cuwe1h3MqitX/hHNf8A+gNf/wDflv8ACj/hHNf/AOgNf/8Aflv8KPZy7B7WHcyqK1f+Ec1//oDX/wD35b/Cj/hHNf8A+gNf/wDflv8ACj2cuwe1h3MqitX/AIRzX/8AoDX/AP35b/Cj/hHNf/6A1/8A9+W/wo9nLsHtYdzKorV/4RzX/wDoDX//AH5b/Cj/AIRzX/8AoDX/AP35b/Cj2cuwe1h3MqitX/hHNf8A+gNf/wDflv8ACj/hHNf/AOgNf/8Aflv8KPZy7B7WHcyqK1f+Ec1//oDX/wD35b/Cj/hHNf8A+gNf/wDflv8ACj2cuwe1h3MqitX/AIRzX/8AoDX/AP35b/Cj/hHNf/6A1/8A9+W/wo9nLsHtYdzKorV/4RzX/wDoDX//AH5b/Cj/AIRzX/8AoDX/AP35b/Cj2cuwe1h3MqitX/hHNf8A+gNf/wDflv8ACj/hHNf/AOgNf/8Aflv8KPZy7B7WHcyqK1f+Ec1//oDX/wD35b/Cj/hHNf8A+gNf/wDflv8ACj2cuwe1h3MqitX/AIRzX/8AoDX/AP35b/Cj/hHNf/6A1/8A9+W/wo9nLsHtYdzKorV/4RzX/wDoDX//AH5b/Cj/AIRzX/8AoDX/AP35b/Cj2cuwe1h3MqitX/hHNf8A+gNf/wDflv8ACj/hHNf/AOgNf/8Aflv8KPZy7B7WHcyqK1f+Ec1//oDX/wD35b/Cj/hHNf8A+gNf/wDflv8ACj2cuwe1h3MqitX/AIRzX/8AoDX/AP35b/Cj/hHNf/6A1/8A9+W/wo9nLsP2sO5lV2vwc/5Ga5/68m/9DSuf/wCEd8Qf9AW+/wC/Lf4V1vwr0nVLDxDPNe6fc20bWjKGkjKjO9OMkdeDW2Hi1UWhzYmpB0pa9P1PS6KKK9Y8AKKKKOoIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA/9k= + + + 1 + arc]]> + + 1 + + + 2 + ridge]]> + + 1 + + + 3 + plain]]> + + 1 + + + 4 + rise]]> + + 1 + + + 5 + trench]]> + + 1 + + + 6 + slope]]> + + 1 + + + 7 + belt]]> + + 1 + + + 8 + shelf]]> + + 1 + + + + 1 + 7 + 53 + 17 + + + + 2 + 8 + 172 + 2 + + + + 3 + 5 + 363 + 31 + + + + 4 + 3 + 440 + 13 + + + + 5 + 6 + 115 + 74 + + + + 6 + 4 + 210 + 94 + + + + 7 + 1 + 310 + 87 + + + + 8 + 2 + 479 + 84 + + + Incorrect placements will be removed.

]]>
+ + +
+ + +
  • The abyssal plain is a flat almost featureless expanse of ocean floor 4km to 6km below sea-level.
  • +
  • The continental rise is the gently sloping part of the ocean floor beyond the continental slope.
  • +
  • The continental shelf is the gently sloping ocean floor just offshore from the land.
  • +
  • The continental slope is the relatively steep part of the ocean floor beyond the continental shelf.
  • +
  • A mid-ocean ridge is a broad submarine ridge several kilometres high.
  • +
  • A mountain belt is a long range of mountains.
  • +
  • An island arc is a chain of volcanic islands.
  • +
  • An oceanic trench is a deep trough in the ocean floor.
  • + ]]>
    + +
    + + Incorrect placements will be removed.

    ]]>
    + + +
    + + +
  • The abyssal plain is a flat almost featureless expanse of ocean floor 4km to 6km below sea-level.
  • +
  • The continental rise is the gently sloping part of the ocean floor beyond the continental slope.
  • +
  • The continental shelf is the gently sloping ocean floor just offshore from the land.
  • +
  • The continental slope is the relatively steep part of the ocean floor beyond the continental shelf.
  • +
  • A mid-ocean ridge is a broad submarine ridge several kilometres high.
  • +
  • A mountain belt is a long range of mountains.
  • +
  • An island arc is a chain of volcanic islands.
  • +
  • An oceanic trench is a deep trough in the ocean floor.
  • + ]]>
    + +
    +
    +
    \ No newline at end of file From aea4a6b6fa88d1ba2b968d753734100c01182ce9 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 12 Nov 2014 16:00:45 +0000 Subject: [PATCH 192/208] MDL-47494 ddimageortext: Bump the version number for the 1.6 release. --- question/type/ddimageortext/version.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 57ccc69f6b9..1385dbd31db 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -17,21 +17,20 @@ /** * Version information for the drag-and-drop onto image question type. * - * @package qtype_ddimageortext - * @copyright 2011 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qtype_ddimageortext + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); - -$plugin->version = 2014042800; -$plugin->requires = 2013051400; +$plugin->version = 2014111200; +$plugin->requires = 2013101800; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.5 for Moodle 2.5+'; +$plugin->release = '1.6 for Moodle 2.6+'; $plugin->dependencies = array( - 'qtype_gapselect' => 2014010800, + 'qtype_gapselect' => 2014111200, ); From 51c3521aa5aba30ef4ca046ff53d7df254e73367 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 28 Nov 2014 18:42:04 +0000 Subject: [PATCH 193/208] MDL-47494 ddimageortext: Fix lots of coding style issues. --- ...ackup_qtype_ddimageortext_plugin.class.php | 6 ++ ...store_qtype_ddimageortext_plugin.class.php | 4 +- .../ddimageortext/edit_ddimageortext_form.php | 34 +++++----- question/type/ddimageortext/questiontype.php | 14 ++-- question/type/ddimageortext/rendererbase.php | 28 ++++---- .../ddimageortext/tests/question_test.php | 1 - .../ddimageortext/tests/questiontype_test.php | 1 - .../ddimageortext/tests/walkthrough_test.php | 8 ++- question/type/ddimageortext/yui/dd/dd.js | 47 +++++++------- question/type/ddimageortext/yui/form/form.js | 64 +++++++++---------- 10 files changed, 105 insertions(+), 102 deletions(-) diff --git a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php index e328408352a..f5066f83469 100644 --- a/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/backup_qtype_ddimageortext_plugin.class.php @@ -15,6 +15,8 @@ // along with Moodle. If not, see . /** + * Backup code for qtype_ddimageortext. + * * @package qtype_ddimageortext * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -30,6 +32,10 @@ defined('MOODLE_INTERNAL') || die(); */ class backup_qtype_ddimageortext_plugin extends backup_qtype_plugin { + /** + * Returns the question type this is. + * @return string question type name, like 'ddimageortext'. + */ protected static function qtype_name() { return 'ddimageortext'; } diff --git a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php index b4e8d8943cf..00a996e165a 100644 --- a/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php +++ b/question/type/ddimageortext/backup/moodle2/restore_qtype_ddimageortext_plugin.class.php @@ -15,6 +15,7 @@ // along with Moodle. If not, see . /** + * Restore code for qtype_ddimageortext. * @package qtype_ddimageortext * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -23,8 +24,7 @@ defined('MOODLE_INTERNAL') || die(); /** - * restore plugin class that provides the necessary information - * needed to restore one ddimageortext qtype plugin. + * Restore plugin class for the ddimageortext question type. * * @copyright 2011 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index ee15f390d8c..ae82fbcc34f 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -50,7 +50,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $question->shuffleanswers = $question->options->shuffleanswers; $question->drags = array(); foreach ($question->options->drags as $drag) { - $dragindex = $drag->no -1; + $dragindex = $drag->no - 1; $question->drags[$dragindex] = array(); $question->draglabel[$dragindex] = $drag->label; $question->drags[$dragindex]['infinite'] = $drag->infinite; @@ -59,11 +59,11 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { } $question->drops = array(); foreach ($question->options->drops as $drop) { - $question->drops[$drop->no -1] = array(); - $question->drops[$drop->no -1]['choice'] = $drop->choice; - $question->drops[$drop->no -1]['droplabel'] = $drop->label; - $question->drops[$drop->no -1]['xleft'] = $drop->xleft; - $question->drops[$drop->no -1]['ytop'] = $drop->ytop; + $question->drops[$drop->no - 1] = array(); + $question->drops[$drop->no - 1]['choice'] = $drop->choice; + $question->drops[$drop->no - 1]['droplabel'] = $drop->label; + $question->drops[$drop->no - 1]['xleft'] = $drop->xleft; + $question->drops[$drop->no - 1]['ytop'] = $drop->ytop; } } // Initialise file picker for bgimage. @@ -78,7 +78,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { list(, $imagerepeats) = $this->get_drag_item_repeats(); $draftitemids = optional_param_array('dragitem', array(), PARAM_INT); for ($imageindex = 0; $imageindex < $imagerepeats; $imageindex++) { - $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] :0; + $draftitemid = isset($draftitemids[$imageindex]) ? $draftitemids[$imageindex] : 0; // Numbers not allowed in filearea name. $itemid = isset($dragids[$imageindex]) ? $dragids[$imageindex] : null; file_prepare_draft_area($draftitemid, $this->context->id, 'qtype_ddimageortext', @@ -87,7 +87,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { } if (!empty($question->options)) { foreach ($question->options->drags as $drag) { - $dragindex = $drag->no -1; + $dragindex = $drag->no - 1; if (!isset($question->dragitem[$dragindex])) { $fileexists = false; } else { @@ -109,7 +109,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { public function js_call() { global $PAGE; - $maxsizes =new stdClass(); + $maxsizes = new stdClass(); $maxsizes->bgimage = new stdClass(); $maxsizes->bgimage->width = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXWIDTH; $maxsizes->bgimage->height = QTYPE_DDIMAGEORTEXT_BGIMAGE_MAXHEIGHT; @@ -167,7 +167,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $draggableimageitem[] = $mform->createElement('text', 'draglabel', get_string('label', 'qtype_ddimageortext'), - array('size'=>30, 'class'=>'tweakcss')); + array('size' => 30, 'class' => 'tweakcss')); $mform->setType('draglabel', PARAM_RAW); // These are validated manually. return $draggableimageitem; } @@ -186,10 +186,10 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { $grouparray = array(); $grouparray[] = $mform->createElement('text', 'xleft', get_string('xleft', 'qtype_ddimageortext'), - array('size'=>5, 'class'=>'tweakcss')); + array('size' => 5, 'class' => 'tweakcss')); $grouparray[] = $mform->createElement('text', 'ytop', get_string('ytop', 'qtype_ddimageortext'), - array('size'=>5, 'class'=>'tweakcss')); + array('size' => 5, 'class' => 'tweakcss')); $options = array(); $options[0] = ''; @@ -200,7 +200,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { get_string('draggableitem', 'qtype_ddimageortext'), $options); $grouparray[] = $mform->createElement('text', 'droplabel', get_string('label', 'qtype_ddimageortext'), - array('size'=>10, 'class'=>'tweakcss')); + array('size' => 10, 'class' => 'tweakcss')); $mform->setType('droplabel', PARAM_NOTAGS); $dropzone = $mform->createElement('group', 'drops', get_string('dropzone', 'qtype_ddimageortext', '{no}'), $grouparray); @@ -225,7 +225,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { } $allchoices = array(); - for ($i=0; $i < $data['nodropzone']; $i++) { + for ($i = 0; $i < $data['nodropzone']; $i++) { $ytoppresent = (trim($data['drops'][$i]['ytop']) !== ''); $xleftpresent = (trim($data['drops'][$i]['xleft']) !== ''); $ytopisint = (string) clean_param($data['drops'][$i]['ytop'], PARAM_INT) === trim($data['drops'][$i]['ytop']); @@ -252,12 +252,12 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { get_string('formerror_nofile', 'qtype_ddimageortext', $i); } - if (isset($allchoices[$choice]) && !$data['drags'][$choice-1]['infinite']) { + if (isset($allchoices[$choice]) && !$data['drags'][$choice - 1]['infinite']) { $errors["drops[$i]"] = get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); $errors['drops['.($allchoices[$choice]).']'] = get_string('formerror_multipledraginstance', 'qtype_ddimageortext', $choice); - $errors['drags['.($choice-1).']'] = + $errors['drags['.($choice - 1).']'] = get_string('formerror_multipledraginstance2', 'qtype_ddimageortext', $choice); } $allchoices[$choice] = $i; @@ -268,7 +268,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { } } } - for ($dragindex=0; $dragindex < $data['noitems']; $dragindex++) { + for ($dragindex = 0; $dragindex < $data['noitems']; $dragindex++) { $label = $data['draglabel'][$dragindex]; if ($data['drags'][$dragindex]['dragitemtype'] == 'word') { $allowedtags = '
    '; diff --git a/question/type/ddimageortext/questiontype.php b/question/type/ddimageortext/questiontype.php index b3546c9ef06..05fd85da464 100644 --- a/question/type/ddimageortext/questiontype.php +++ b/question/type/ddimageortext/questiontype.php @@ -95,19 +95,19 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { '', 'no, id'); foreach (array_keys($formdata->drags) as $dragno) { $info = file_get_draft_area_info($formdata->dragitem[$dragno]); - if ($info['filecount'] > 0 || (trim($formdata->draglabel[$dragno])!='')) { + if ($info['filecount'] > 0 || (trim($formdata->draglabel[$dragno]) != '')) { $draftitemid = $formdata->dragitem[$dragno]; $drag = new stdClass(); $drag->questionid = $formdata->id; $drag->no = $dragno + 1; $drag->draggroup = $formdata->drags[$dragno]['draggroup']; - $drag->infinite = empty($formdata->drags[$dragno]['infinite'])? 0 : 1; + $drag->infinite = empty($formdata->drags[$dragno]['infinite']) ? 0 : 1; $drag->label = $formdata->draglabel[$dragno]; - if (isset($olddragids[$dragno +1])) { - $drag->id = $olddragids[$dragno +1]; - unset($olddragids[$dragno +1]); + if (isset($olddragids[$dragno + 1])) { + $drag->id = $olddragids[$dragno + 1]; + unset($olddragids[$dragno + 1]); $DB->update_record('qtype_ddimageortext_drags', $drag); } else { $drag->id = $DB->insert_record('qtype_ddimageortext_drags', $drag); @@ -242,7 +242,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { foreach ($drags as $dragxml) { $dragno = $format->getpath($dragxml, array('#', 'no', 0, '#'), 0); - $dragindex = $dragno -1; + $dragindex = $dragno - 1; $question->drags[$dragindex] = array(); $question->draglabel[$dragindex] = $format->getpath($dragxml, array('#', 'text', 0, '#'), '', true); @@ -262,7 +262,7 @@ class qtype_ddimageortext extends qtype_ddtoimage_base { $question->drops = array(); foreach ($drops as $dropxml) { $dropno = $format->getpath($dropxml, array('#', 'no', 0, '#'), 0); - $dropindex = $dropno -1; + $dropindex = $dropno - 1; $question->drops[$dropindex] = array(); $question->drops[$dropindex]['choice'] = $format->getpath($dropxml, array('#', 'choice', 0, '#'), 0); diff --git a/question/type/ddimageortext/rendererbase.php b/question/type/ddimageortext/rendererbase.php index e1bef6adead..bcd08f1a7e7 100644 --- a/question/type/ddimageortext/rendererbase.php +++ b/question/type/ddimageortext/rendererbase.php @@ -63,12 +63,11 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere $bgimage = self::get_url_for_image($qa, 'bgimage'); - $img = html_writer::empty_tag('img', - array('src'=>$bgimage, - 'class'=>'dropbackground', - 'alt' => get_string('dropbackground', 'qtype_ddimageortext'))); + $img = html_writer::empty_tag('img', array( + 'src' => $bgimage, 'class' => 'dropbackground', + 'alt' => get_string('dropbackground', 'qtype_ddimageortext'))); - $droparea = html_writer::tag('div', $img, array('class'=>'droparea')); + $droparea = html_writer::tag('div', $img, array('class' => 'droparea')); $dragimagehomes = ''; foreach ($question->choices as $groupno => $group) { @@ -85,27 +84,24 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere } if ($dragimageurl === null) { $classes[] = 'yui3-cssfonts'; - $dragimagehomesgroup .= html_writer::tag('div', - $dragimage->text, - array('src'=>$dragimageurl, - 'class'=>join(' ', $classes))); + $dragimagehomesgroup .= html_writer::tag('div', $dragimage->text, + array('src' => $dragimageurl, 'class' => join(' ', $classes))); } else { $dragimagehomesgroup .= html_writer::empty_tag('img', - array('src'=>$dragimageurl, - 'alt' => $dragimage->text, - 'class'=>join(' ', $classes))); + array('src' => $dragimageurl, 'alt' => $dragimage->text, + 'class' => join(' ', $classes))); } } $dragimagehomes .= html_writer::tag('div', $dragimagehomesgroup, - array('class'=>'dragitemgroup'.$groupno)); + array('class' => 'dragitemgroup' . $groupno)); } $dragitemsclass = 'dragitems'; if ($options->readonly) { $dragitemsclass .= ' readonly'; } - $dragitems = html_writer::tag('div', $dragimagehomes, array('class'=> $dragitemsclass)); - $dropzones = html_writer::tag('div', '', array('class'=>'dropzones')); + $dragitems = html_writer::tag('div', $dragimagehomes, array('class' => $dragitemsclass)); + $dropzones = html_writer::tag('div', '', array('class' => 'dropzones')); $hiddens = ''; foreach ($question->places as $placeno => $place) { @@ -115,7 +111,7 @@ class qtype_ddtoimage_renderer_base extends qtype_with_combined_feedback_rendere $question->places[$placeno]->fieldname = $fieldname; } $output .= html_writer::tag('div', - $droparea . $dragitems . $dropzones . $hiddens, array('class'=>'ddarea')); + $droparea . $dragitems . $dropzones . $hiddens, array('class' => 'ddarea')); $topnode = 'div#q'.$qa->get_slot().' div.ddarea'; $params = array('drops' => $question->places, 'topnode' => $topnode, diff --git a/question/type/ddimageortext/tests/question_test.php b/question/type/ddimageortext/tests/question_test.php index 32c2a69dfd3..cc3256d4130 100644 --- a/question/type/ddimageortext/tests/question_test.php +++ b/question/type/ddimageortext/tests/question_test.php @@ -35,7 +35,6 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php'); * * @copyright 2009 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @group qtype_ddimageortext */ class qtype_ddimageortext_question_test extends basic_testcase { diff --git a/question/type/ddimageortext/tests/questiontype_test.php b/question/type/ddimageortext/tests/questiontype_test.php index 287473b5716..0c36e33b858 100644 --- a/question/type/ddimageortext/tests/questiontype_test.php +++ b/question/type/ddimageortext/tests/questiontype_test.php @@ -35,7 +35,6 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php'); * * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @group qtype_ddimageortext */ class qtype_ddimageortext_test extends basic_testcase { /** @var qtype_ddimageortext instance of the question type class to test. */ diff --git a/question/type/ddimageortext/tests/walkthrough_test.php b/question/type/ddimageortext/tests/walkthrough_test.php index 95adfaaf57e..cc392bcb29a 100644 --- a/question/type/ddimageortext/tests/walkthrough_test.php +++ b/question/type/ddimageortext/tests/walkthrough_test.php @@ -35,10 +35,16 @@ require_once($CFG->dirroot . '/question/type/ddimageortext/tests/helper.php'); * * @copyright 2010 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @group qtype_ddimageortext */ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_base { + /** + * Get an expectation that the output contains an item ready to drag. + * @param int $dragitemno the item number. + * @param int $choice which choice this is. + * @param int $group which drag group it belongs to. + * @return question_contains_tag_with_attributes the required expectation. + */ protected function get_contains_drag_image_home_expectation($dragitemno, $choice, $group) { $class = 'group' . $group; $class .= ' draghome dragitemhomes' . $dragitemno. ' choice'.$choice.' yui3-cssfonts'; diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js index 0d5177809b2..b6b88a0d770 100644 --- a/question/type/ddimageortext/yui/dd/dd.js +++ b/question/type/ddimageortext/yui/dd/dd.js @@ -70,7 +70,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { return topnode.all('div.dropzones div.group' + groupno); }, drag_items_cloned_from : function(dragitemno) { - return dragitemsarea.all('.dragitems'+dragitemno); + return dragitemsarea.all('.dragitems' + dragitemno); }, drag_item : function(draginstanceno) { return dragitemsarea.one('.draginstance' + draginstanceno); @@ -85,14 +85,14 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { return topnode.one('.dropbackground'); }, load_bg_img : function (url) { - dropbgarea.setContent(''); + dropbgarea.setContent(''); this.bg_img().on('load', this.on_image_load, this, 'bg_image'); }, add_or_update_drag_item_home : function (dragitemno, url, alt, group) { var oldhome = this.drag_item_home(dragitemno); - var classes = 'draghome dragitemhomes'+dragitemno+' group'+group; - var imghtml = ''+alt+''; - var divhtml = '
    '+alt+'
    '; + var classes = 'draghome dragitemhomes' + dragitemno + ' group' + group; + var imghtml = '' + alt + ''; + var divhtml = '
    ' + alt + '
    '; if (oldhome === null) { if (url) { dragitemsarea.append(imghtml); @@ -107,7 +107,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { } oldhome.remove(true); } - var newlycreated = dragitemsarea.one('.dragitemhomes'+dragitemno); + var newlycreated = dragitemsarea.one('.dragitemhomes' + dragitemno); if (newlycreated !== null) { newlycreated.setData('groupno', group); newlycreated.setData('dragitemno', dragitemno); @@ -125,11 +125,11 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { if (patt1.test(classesarr[index])) { var patt2 = new RegExp('([0-9])+$'); var match = patt2.exec(classesarr[index]); - return +match[0]; + return + match[0]; } } } - throw 'Prefix "'+prefix+'" not found in class names.'; + throw 'Prefix "' + prefix + '" not found in class names.'; }, clone_new_drag_item : function (draginstanceno, dragitemno) { var draghome = this.drag_item_home(dragitemno); @@ -191,7 +191,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { } }, update_padding_size_for_group : function (groupno) { - var groupitems = this.doc.top_node().all('.draghome.group'+groupno); + var groupitems = this.doc.top_node().all('.draghome.group' + groupno); if (groupitems.size() !== 0) { var maxwidth = 0; var maxheight = 0; @@ -202,16 +202,16 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { groupitems.each(function(item) { var margintopbottom = Math.round((10 + maxheight - item.get('clientHeight')) / 2); var marginleftright = Math.round((10 + maxwidth - item.get('clientWidth')) / 2); - item.setStyle('padding', margintopbottom+'px '+marginleftright+'px ' - +margintopbottom+'px '+marginleftright+'px'); + item.setStyle('padding', margintopbottom + 'px ' + marginleftright + 'px ' + + margintopbottom + 'px ' + marginleftright + 'px'); }, this); this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, 'height': maxheight + 10}); } }, convert_to_window_xy : function (bgimgxy) { - return [+bgimgxy[0] + this.doc.bg_img().getX() + 1, - +bgimgxy[1] + this.doc.bg_img().getY() + 1]; + return [Number(bgimgxy[0]) + this.doc.bg_img().getX() + 1, + Number(bgimgxy[1]) + this.doc.bg_img().getY() + 1]; } }, { NAME : DDIMAGEORTEXTDDNAME, @@ -246,10 +246,9 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { this.update_padding_sizes_all(); var i = 0; this.doc.drag_item_homes().each(function(dragitemhome){ - var dragitemno = - +this.doc.get_classname_numeric_suffix(dragitemhome, 'dragitemhomes'); - var choice = +this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); - var group = +this.doc.get_classname_numeric_suffix(dragitemhome, 'group'); + var dragitemno = Number(this.doc.get_classname_numeric_suffix(dragitemhome, 'dragitemhomes')); + var choice = + this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); + var group = + this.doc.get_classname_numeric_suffix(dragitemhome, 'group'); var groupsize = this.doc.drop_zone_group(group).size(); var dragnode = this.doc.clone_new_drag_item(i, dragitemno); i++; @@ -328,7 +327,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { }, current_drag_in_drop : function (drop) { var inputid = drop.getData('inputid'); - var inputnode = Y.one('input#'+inputid); + var inputnode = Y.one('input#' + inputid); return inputnode.get('value'); }, remove_drag_from_drop : function (drop) { @@ -336,7 +335,7 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { }, place_drag_in_drop : function (drag, drop) { var inputid = drop.getData('inputid'); - var inputnode = Y.one('input#'+inputid); + var inputnode = Y.one('input#' + inputid); if (drag !== null) { inputnode.set('value', drag.getData('choice')); } else { @@ -398,23 +397,23 @@ YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { init_drops : function () { var dropareas = this.doc.top_node().one('div.dropzones'); var groupnodes = {}; - for (var groupno =1; groupno <= 8; groupno++) { - var groupnode = Y.Node.create('
    '); + for (var groupno = 1; groupno <= 8; groupno++) { + var groupnode = Y.Node.create('
    '); dropareas.append(groupnode); groupnodes[groupno] = groupnode; } var drop_hit_handler = function(e) { var drag = e.drag.get('node'); var drop = e.drop.get('node'); - if (+drop.getData('group') === drag.getData('group')){ + if (Number(drop.getData('group')) === drag.getData('group')){ this.place_drag_in_drop(drag, drop); } }; for (var dropno in this.get('drops')) { var drop = this.get('drops')[dropno]; - var nodeclass = 'dropzone group'+drop.group+' place'+dropno; + var nodeclass = 'dropzone group' + drop.group + ' place' + dropno; var title = drop.text.replace('"', '\"'); - var dropnodehtml = '
     
    '; + var dropnodehtml = '
     
    '; var dropnode = Y.Node.create(dropnodehtml); groupnodes[drop.group].append(dropnode); dropnode.setStyles({'opacity': 0.5}); diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js index 557f2902976..3af5227e053 100644 --- a/question/type/ddimageortext/yui/form/form.js +++ b/question/type/ddimageortext/yui/form/form.js @@ -12,7 +12,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { initializer : function() { this.fp = this.file_pickers(); var tn = Y.one(this.get('topnode')); - tn.one('div.fcontainer').append('
    '+ + tn.one('div.fcontainer').append('
    ' + '
    '); this.doc = this.doc_structure(this); this.draw_dd_area(); @@ -69,8 +69,8 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, load_drag_homes : function () { - //set up drag items homes - for (var i=0; i < this.form.get_form_value('noitems', []); i++) { + // Set up drag items homes. + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { this.load_drag_home(i); } }, @@ -86,8 +86,8 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, update_drag_instances : function () { - //set up drop zones - for (var i=0; i < this.form.get_form_value('nodropzone', []); i++) { + // Set up drop zones. + for (var i = 0; i < this.form.get_form_value('nodropzone', []); i++) { var dragitemno = this.form.get_form_value('drops', [i, 'choice']); if (dragitemno !== '0' && (this.doc.drag_item(i) === null)) { var drag = this.doc.clone_new_drag_item(i, dragitemno - 1); @@ -99,7 +99,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, set_options_for_drag_item_selectors : function () { var dragitemsoptions = {0: ''}; - for (var i=0; i < this.form.get_form_value('noitems', []); i++) { + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { var label = this.form.get_form_value('draglabel', [i]); var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype']) @@ -110,26 +110,24 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { } } for (i = 0; i < this.form.get_form_value('nodropzone', []); i++) { - var selector = Y.one('#id_drops_'+i+'_choice'); + var selector = Y.one('#id_drops_' + i + '_choice'); var selectedvalue = selector.get('value'); selector.all('option').remove(true); for (var value in dragitemsoptions) { - value = +value; - var option = ''; + value = + value; + var option = ''; selector.append(option); var optionnode = selector.one('option[value="' + value + '"]'); - if (value === +selectedvalue) { + if (value === + selectedvalue) { optionnode.set('selected', true); } else { - if (value !== 0) { // no item option is always selectable - var cbel = Y.one('#id_drags_'+(value-1)+'_infinite'); + if (value !== 0) { // No item option is always selectable. + var cbel = Y.one('#id_drags_' + (value - 1) + '_infinite'); if (cbel && !cbel.get('checked')) { Y.all('fieldset#id_dropzoneheader select').some(function (selector) { - if (+selector.get('value') === value) { + if (Number(selector.get('value')) === value) { optionnode.set('disabled', true); - return true; // stop looping + return true; // Stop looping. } return false; }, this); @@ -145,9 +143,9 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, setup_form_events : function () { - //events triggered by changes to form data + // Events triggered by changes to form data. - //x and y coordinates + // X and y coordinates. Y.all('fieldset#id_dropzoneheader input').on('blur', function (e) { var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; @@ -158,7 +156,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); }, this); - //change in selected item + // Change in selected item. Y.all('fieldset#id_dropzoneheader select').on('change', function (e) { var name = e.target.getAttribute('name'); var draginstanceno = this.form.from_name_with_index(name).indexes[0]; @@ -169,25 +167,25 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { this.draw_dd_area(); }, this); - for (var i=0; i < this.form.get_form_value('noitems', []); i++) { - //change to group selector - Y.all('#fgroup_id_drags_'+i+' select.draggroup').on( + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + // Change to group selector. + Y.all('#fgroup_id_drags_' + i + ' select.draggroup').on( 'change', function () { this.doc.drag_items().remove(true); this.draw_dd_area(); }, this); - Y.all('#fgroup_id_drags_'+i+' select.dragitemtype').on( + Y.all('#fgroup_id_drags_' + i + ' select.dragitemtype').on( 'change', function () { this.doc.drag_items().remove(true); this.draw_dd_area(); }, this); - Y.all('fieldset#draggableitemheader_'+i+' input[type="text"]') + Y.all('fieldset#draggableitemheader_' + i + ' input[type="text"]') .on('blur', this.set_options_for_drag_item_selectors, this); - //change to infinite checkbox - Y.all('fieldset#draggableitemheader_'+i+' input[type="checkbox"]') + // Change to infinite checkbox. + Y.all('fieldset#draggableitemheader_' + i + ' input[type="checkbox"]') .on('change', this.set_options_for_drag_item_selectors, this); } - //event on file picker new file selection + // Event on file picker new file selection. Y.after(function (e) { var name = this.fp.name(e.id); if (name !== 'bgimage') { @@ -198,12 +196,12 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { }, update_visibility_of_file_pickers : function() { - for (var i=0; i < this.form.get_form_value('noitems', []); i++) { + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype'])) { - Y.one('input#id_dragitem_'+i).get('parentNode').get('parentNode') + Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') .setStyle('display', 'block'); } else { - Y.one('input#id_dragitem_'+i).get('parentNode').get('parentNode') + Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') .setStyle('display', 'none'); } } @@ -251,8 +249,8 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { return [xleftconstrained, ytopconstrained]; }, convert_to_bg_img_xy : function (windowxy) { - return [+windowxy[0] - this.doc.bg_img().getX()-1, - +windowxy[1] - this.doc.bg_img().getY()-1]; + return [Number(windowxy[0]) - this.doc.bg_img().getX() - 1, + Number(windowxy[1]) - this.doc.bg_img().getY() - 1]; }, /** @@ -261,7 +259,7 @@ YUI.add('moodle-qtype_ddimageortext-form', function(Y) { form : { to_name_with_index : function(name, indexes) { var indexstring = name; - for (var i=0; i < indexes.length; i++) { + for (var i = 0; i < indexes.length; i++) { indexstring = indexstring + '[' + indexes[i] + ']'; } return indexstring; From 145f46ed2883374eedbe28db6082bcf517cbdf48 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 2 Dec 2014 18:02:48 +0000 Subject: [PATCH 194/208] MDL-47494 ddimageortext: DD markers / onto image: form, drag items before drop zones. #12656 That is a more logical order, and now that sections of the form are collapsible, it is not necessary to put the drop zones right beside the preview. --- question/type/ddimageortext/edit_ddtoimage_form_base.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/question/type/ddimageortext/edit_ddtoimage_form_base.php b/question/type/ddimageortext/edit_ddtoimage_form_base.php index 5cc6b4b699b..81b47049ce5 100644 --- a/question/type/ddimageortext/edit_ddtoimage_form_base.php +++ b/question/type/ddimageortext/edit_ddtoimage_form_base.php @@ -67,11 +67,10 @@ abstract class qtype_ddtoimage_edit_form_base extends question_edit_form { null, self::file_picker_options()); $mform->closeHeaderBefore('dropzoneheader'); + // Add the draggable image fields & drop zones to the form. list($itemrepeatsatstart, $imagerepeats) = $this->get_drag_item_repeats(); - $this->definition_drop_zones($mform, $imagerepeats); - - // Add the draggable image fields to the form. $this->definition_draggable_items($mform, $itemrepeatsatstart); + $this->definition_drop_zones($mform, $imagerepeats); $this->add_combined_feedback_fields(true); $this->add_interactive_settings(true, true); From 42865c8448e9fb07173bdc12540d928ff993f756 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 13 Feb 2015 17:38:38 +0000 Subject: [PATCH 195/208] MDL-47494 ddimageortext: Improve the drag-drop question Behat tests. * Added tests for previewing the question, to make sure it works when attempted. * Added Moodle XML export tests. * Reorganised the tests to follow the 'Test one thing per scenario' best practice. This commit requires MDL-49154 to work. --- .../ddimageortext/tests/behat/add.feature | 96 +++++++++ .../tests/behat/backup_and_restore.feature | 100 +++++++++ .../tests/behat/basic_test.feature | 198 ------------------ .../tests/behat/behat_qtype_ddimageortext.php | 83 ++++++++ .../ddimageortext/tests/behat/edit.feature | 33 +++ .../ddimageortext/tests/behat/export.feature | 37 ++++ .../{import_test.feature => import.feature} | 16 +- .../ddimageortext/tests/behat/preview.feature | 60 ++++++ question/type/ddimageortext/tests/helper.php | 113 +++++++++- 9 files changed, 529 insertions(+), 207 deletions(-) create mode 100644 question/type/ddimageortext/tests/behat/add.feature create mode 100644 question/type/ddimageortext/tests/behat/backup_and_restore.feature delete mode 100644 question/type/ddimageortext/tests/behat/basic_test.feature create mode 100644 question/type/ddimageortext/tests/behat/behat_qtype_ddimageortext.php create mode 100644 question/type/ddimageortext/tests/behat/edit.feature create mode 100644 question/type/ddimageortext/tests/behat/export.feature rename question/type/ddimageortext/tests/behat/{import_test.feature => import.feature} (70%) create mode 100644 question/type/ddimageortext/tests/behat/preview.feature diff --git a/question/type/ddimageortext/tests/behat/add.feature b/question/type/ddimageortext/tests/behat/add.feature new file mode 100644 index 00000000000..f1aa2dc3bfb --- /dev/null +++ b/question/type/ddimageortext/tests/behat/add.feature @@ -0,0 +1,96 @@ +@ou @ou_vle @qtype @qtype_ddimageortext +Feature: Test creating a drag and drop onto image question + As a teacher + In order to test my students + I need to be able to create drag and drop onto image questions + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | T1 | Teacher1 | teacher1@moodle.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + And I log in as "teacher1" + And I follow "Course 1" + And I navigate to "Question bank" node in "Course administration" + + @javascript + Scenario: Create a drag and drop onto image question + When I press "Create a new question ..." + And I set the field "Drag and drop onto image" to "1" + And I press "Add" + And I set the field "Question name" to "Drag and drop onto image 001" + And I set the field "Question text" to "Identify the features in this cross-section." + And I set the field "General feedback" to "The locations are now labelled on the diagram below." + And I upload "question/type/ddimageortext/tests/fixtures/oceanfloorbase.jpg" file to "Background image" filemanager + + # Draggable items + And I follow "Draggable items" + And I press "Blanks for 3 more draggable items" + + And I set the field "id_drags_0_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_0" to "island
    arc" + + And I set the field "id_drags_1_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_1" to "mid-ocean
    ridge" + + And I set the field "id_drags_2_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_2" to "abyssal
    plain" + + And I set the field "id_drags_3_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_3" to "continental
    rise" + + And I set the field "id_drags_4_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_4" to "ocean
    trench" + + And I set the field "id_drags_5_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_5" to "continental
    slope" + + And I set the field "id_drags_6_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_6" to "mountain
    belt" + + And I set the field "id_drags_7_dragitemtype" to "Draggable text" + And I set the field "id_draglabel_7" to "continental
    shelf" + + # Drop zones + And I follow "Drop zones" + And I press "Blanks for 3 more drop zones" + + And I set the field "id_drops_0_xleft" to "53" + And I set the field "id_drops_0_ytop" to "17" + And I set the field "id_drops_0_choice" to "7" + + And I set the field "id_drops_1_xleft" to "172" + And I set the field "id_drops_1_ytop" to "2" + And I set the field "id_drops_1_choice" to "8" + + And I set the field "id_drops_2_xleft" to "363" + And I set the field "id_drops_2_ytop" to "31" + And I set the field "id_drops_2_choice" to "5" + + And I set the field "id_drops_3_xleft" to "440" + And I set the field "id_drops_3_ytop" to "13" + And I set the field "id_drops_3_choice" to "3" + + And I set the field "id_drops_4_xleft" to "115" + And I set the field "id_drops_4_ytop" to "74" + And I set the field "id_drops_4_choice" to "6" + + And I set the field "id_drops_5_xleft" to "210" + And I set the field "id_drops_5_ytop" to "94" + And I set the field "id_drops_5_choice" to "4" + + And I set the field "id_drops_6_xleft" to "310" + And I set the field "id_drops_6_ytop" to "87" + And I set the field "id_drops_6_choice" to "1" + + And I set the field "id_drops_7_xleft" to "479" + And I set the field "id_drops_7_ytop" to "84" + And I set the field "id_drops_7_choice" to "2" + + And I press "id_submitbutton" + Then I should see "Drag and drop onto image 001" diff --git a/question/type/ddimageortext/tests/behat/backup_and_restore.feature b/question/type/ddimageortext/tests/behat/backup_and_restore.feature new file mode 100644 index 00000000000..8384e97adfa --- /dev/null +++ b/question/type/ddimageortext/tests/behat/backup_and_restore.feature @@ -0,0 +1,100 @@ +@ou @ou_vle @qtype @qtype_ddimageortext +Feature: Test duplicating a quiz containing a drag and drop onto image question + As a teacher + In order re-use my courses containing drag and drop onto image questions + I need to be able to backup and restore them + + Background: + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "question categories" exist: + | contextlevel | reference | name | + | Course | C1 | Test questions | + And the following "questions" exist: + | questioncategory | qtype | name | template | + | Test questions | ddimageortext | Drag onto image | xsection | + And the following "activities" exist: + | activity | name | course | idnumber | + | quiz | Test quiz | C1 | quiz1 | + And quiz "Test quiz" contains the following questions: + | Drag onto image | 1 | + And I log in as "admin" + And I follow "Course 1" + + @javascript + Scenario: Backup and restore a course containing a drag and drop onto image question + When I backup "Course 1" course using this options: + | Confirmation | Filename | test_backup.mbz | + And I restore "test_backup.mbz" backup into a new course using this options: + | Schema | Course name | Course 2 | + And I navigate to "Question bank" node in "Course administration" + And I click on "Edit" "link" in the "Drag onto image" "table_row" + Then the following fields match these values: + | Question name | Drag onto image | + | General feedback |

    More information about the major features of the Earth's surface can be found in Block 3, Section 6.2.

    | + | Default mark | 1 | + | Shuffle | 0 | + | id_drags_0_dragitemtype | Draggable text | + | id_drags_0_draggroup | 1 | + | id_draglabel_0 | island
    arc | + | id_drags_1_dragitemtype | Draggable text | + | id_drags_1_draggroup | 1 | + | id_draglabel_1 | mid-ocean
    ridge | + | id_drags_2_dragitemtype | Draggable text | + | id_drags_2_draggroup | 1 | + | id_draglabel_2 | abyssal
    plain | + | id_drags_3_dragitemtype | Draggable text | + | id_drags_3_draggroup | 1 | + | id_draglabel_3 | continental
    rise | + | id_drags_4_dragitemtype | Draggable text | + | id_drags_4_draggroup | 1 | + | id_draglabel_4 | ocean
    trench | + | id_drags_5_dragitemtype | Draggable text | + | id_drags_5_draggroup | 1 | + | id_draglabel_5 | continental
    slope | + | id_drags_6_dragitemtype | Draggable text | + | id_drags_6_draggroup | 1 | + | id_draglabel_6 | mountain
    belt | + | id_drags_7_dragitemtype | Draggable text | + | id_drags_7_draggroup | 1 | + | id_draglabel_7 | continental
    shelf | + | id_drops_0_xleft | 53 | + | id_drops_0_ytop | 17 | + | id_drops_0_choice | 7. mountainbelt | + | id_drops_1_xleft | 172 | + | id_drops_1_ytop | 2 | + | id_drops_1_choice | 8. continentalshelf | + | id_drops_2_xleft | 363 | + | id_drops_2_ytop | 31 | + | id_drops_2_choice | 5. oceantrench | + | id_drops_3_xleft | 440 | + | id_drops_3_ytop | 13 | + | id_drops_3_choice | 3. abyssalplain | + | id_drops_4_xleft | 115 | + | id_drops_4_ytop | 74 | + | id_drops_4_choice | 6. continentalslope | + | id_drops_5_xleft | 210 | + | id_drops_5_ytop | 94 | + | id_drops_5_choice | 4. continentalrise | + | id_drops_6_xleft | 310 | + | id_drops_6_ytop | 87 | + | id_drops_6_choice | 1. islandarc | + | id_drops_7_xleft | 479 | + | id_drops_7_ytop | 84 | + | id_drops_7_choice | 2. mid-oceanridge | + | For any correct response | Well done! | + | For any partially correct response | Parts, but only parts, of your response are correct. | + | id_shownumcorrect | 1 | + | For any incorrect response | That is not right at all. | + | Penalty for each incorrect try | 0.3333333 | + | Hint 1 | Incorrect placements will be removed. | + | id_hintclearwrong_0 | 1 | + | id_hintshownumcorrect_0 | 1 | + | id_hintclearwrong_1 | 0 | + | id_hintshownumcorrect_1 | 1 | + | Hint 3 | Incorrect placements will be removed. | + | id_hintclearwrong_2 | 1 | + | id_hintshownumcorrect_2 | 1 | + | id_hintclearwrong_3 | 0 | + | id_hintshownumcorrect_3 | 1 | diff --git a/question/type/ddimageortext/tests/behat/basic_test.feature b/question/type/ddimageortext/tests/behat/basic_test.feature deleted file mode 100644 index 65e20190a2c..00000000000 --- a/question/type/ddimageortext/tests/behat/basic_test.feature +++ /dev/null @@ -1,198 +0,0 @@ -@ou @ou_vle @qtype @qtype_ddimageortext -Feature: Test all the basic functionality of this question type - In order to evaluate students responses, As a teacher I need to - create and preview ddimageortext (Drag and drop onto image) questions. - - # Due to complexity and since the javascript code needs to be converted at some stage, - # we are not going to test attempting this qtype. However, we will do all other - # possible testings, such as creating the question preview it and seeing the - # correct information on the preview string as well as backing-up and restoring - # the course containing this qtype. - - # Another way to test attempting this qtype while previewing it, it write a - # customised step for tabbing through place-holders and another customised - # step for making use of arrow keys in order to go through the list of choices. - - Background: - Given the following "users" exist: - | username | firstname | lastname | email | - | teacher1 | T1 | Teacher1 | teacher1@moodle.com | - And the following "courses" exist: - | fullname | shortname | category | - | Course 1 | C1 | 0 | - And the following "course enrolments" exist: - | user | course | role | - | teacher1 | C1 | editingteacher | - - @javascript - Scenario: Create, edit then preview a ddimageortext question. - Given I log in as "teacher1" - And I follow "Course 1" - And I navigate to "Question bank" node in "Course administration" - Then I should see "Question bank" - - # Create a new question - # We have to set the fields individually, because of the step for uploading the background image. - Given I press "Create a new question ..." - And I set the field "Drag and drop onto image" to "1" - Then I press "Add" - And I should see "Adding drag and drop onto image" - Then I set the field "Question name" to "Drag and drop onto image 001" - And I set the field "Question text" to "Identify the features in this cross-section." - And I set the field "General feedback" to "The locations are now labelled on the diagram below." - Given I upload "question/type/ddimageortext/tests/fixtures/oceanfloorbase.jpg" file to "Background image" filemanager - - # Draggable items - Given I follow "Draggable items" - Then I press "Blanks for 3 more draggable items" - - And I set the field "id_drags_0_dragitemtype" to "Draggable text" - And I set the field "id_draglabel_0" to "island
    arc" - - And I set the field "id_drags_1_dragitemtype" to "Draggable text" - And I set the field "id_draglabel_1" to "mid-ocean
    ridge" - - And I set the field "id_drags_2_dragitemtype" to "Draggable text" - And I set the field "id_draglabel_2" to "abyssal
    plain" - - And I set the field "id_drags_3_dragitemtype" to "Draggable text" - And I set the field "id_draglabel_3" to "continental
    rise" - - And I set the field "id_drags_4_dragitemtype" to "Draggable text" - And I set the field "id_draglabel_4" to "ocean
    trench" - - And I set the field "id_drags_5_dragitemtype" to "Draggable text" - And I set the field "id_draglabel_5" to "continental
    slope" - - And I set the field "id_drags_6_dragitemtype" to "Draggable text" - And I set the field "id_draglabel_6" to "mountain
    belt" - - And I set the field "id_drags_7_dragitemtype" to "Draggable text" - And I set the field "id_draglabel_7" to "continental
    shelf" - - # Drop zones - Given I follow "Drop zones" - Then I press "Blanks for 3 more drop zones" - - And I set the field "id_drops_0_xleft" to "53" - And I set the field "id_drops_0_ytop" to "17" - And I set the field "id_drops_0_choice" to "7" - - And I set the field "id_drops_1_xleft" to "172" - And I set the field "id_drops_1_ytop" to "2" - And I set the field "id_drops_1_choice" to "8" - - And I set the field "id_drops_2_xleft" to "363" - And I set the field "id_drops_2_ytop" to "31" - And I set the field "id_drops_2_choice" to "5" - - And I set the field "id_drops_3_xleft" to "440" - And I set the field "id_drops_3_ytop" to "13" - And I set the field "id_drops_3_choice" to "3" - - And I set the field "id_drops_4_xleft" to "115" - And I set the field "id_drops_4_ytop" to "74" - And I set the field "id_drops_4_choice" to "6" - - And I set the field "id_drops_5_xleft" to "210" - And I set the field "id_drops_5_ytop" to "94" - And I set the field "id_drops_5_choice" to "4" - - And I set the field "id_drops_6_xleft" to "310" - And I set the field "id_drops_6_ytop" to "87" - And I set the field "id_drops_6_choice" to "1" - - And I set the field "id_drops_7_xleft" to "479" - And I set the field "id_drops_7_ytop" to "84" - And I set the field "id_drops_7_choice" to "2" - - - And I press "id_submitbutton" - Then I should see "Drag and drop onto image 001" - - # Preview it. - When I click on "Preview" "link" in the "Drag and drop onto image 001" "table_row" - And I switch to "questionpreview" window - Then I should see "Preview question: Drag and drop onto image 001" - And I switch to the main window - - # Backup the course and restore it. - When I log out - And I log in as "admin" - When I backup "Course 1" course using this options: - | Confirmation | Filename | test_backup.mbz | - When I restore "test_backup.mbz" backup into a new course using this options: - | Schema | Course name | Course 2 | - Then I should see "Course 2" - When I navigate to "Question bank" node in "Course administration" - Then I should see "Drag and drop onto image 001" - - # Edit the copy and verify the form field contents. - When I click on "Edit" "link" in the "Drag and drop onto image 001" "table_row" - Then the following fields match these values: - | Question name | Drag and drop onto image 001 | - | Question text | Identify the features in this cross-section. | - | General feedback | The locations are now labelled on the diagram below. | - - # Draggable items - | id_drags_0_dragitemtype | Draggable text | - | id_draglabel_0 | island
    arc | - - | id_drags_1_dragitemtype | Draggable text | - | id_draglabel_1 | mid-ocean
    ridge | - - | id_drags_2_dragitemtype | Draggable text | - | id_draglabel_2 | abyssal
    plain | - - | id_drags_3_dragitemtype | Draggable text | - | id_draglabel_3 | continental
    rise | - - | id_drags_4_dragitemtype | Draggable text | - | id_draglabel_4 | ocean
    trench | - - | id_drags_5_dragitemtype | Draggable text | - | id_draglabel_5 | continental
    slope | - - | id_drags_6_dragitemtype | Draggable text | - | id_draglabel_6 | mountain
    belt | - - | id_drags_7_dragitemtype | Draggable text | - | id_draglabel_7 | continental
    shelf | - - # Drop zones - | id_drops_0_xleft | 53 | - | id_drops_0_ytop | 17 | - | id_drops_0_choice | 7 | - - | id_drops_1_xleft | 172 | - | id_drops_1_ytop | 2 | - | id_drops_1_choice | 8 | - - | id_drops_2_xleft | 363 | - | id_drops_2_ytop | 31 | - | id_drops_2_choice | 5 | - - | id_drops_3_xleft | 440 | - | id_drops_3_ytop | 13 | - | id_drops_3_choice | 3 | - - | id_drops_4_xleft | 115 | - | id_drops_4_ytop | 74 | - | id_drops_4_choice | 6 | - - | id_drops_5_xleft | 210 | - | id_drops_5_ytop | 94 | - | id_drops_5_choice | 4 | - - | id_drops_6_xleft | 310 | - | id_drops_6_ytop | 87 | - | id_drops_6_choice | 1 | - - | id_drops_7_xleft | 479 | - | id_drops_7_ytop | 84 | - | id_drops_7_choice | 2 | - - And I set the following fields to these values: - | Question name | Edited question name | - And I press "id_submitbutton" - Then I should see "Edited question name" diff --git a/question/type/ddimageortext/tests/behat/behat_qtype_ddimageortext.php b/question/type/ddimageortext/tests/behat/behat_qtype_ddimageortext.php new file mode 100644 index 00000000000..a1a5239cd15 --- /dev/null +++ b/question/type/ddimageortext/tests/behat/behat_qtype_ddimageortext.php @@ -0,0 +1,83 @@ +. + +/** + * Behat steps definitions for drag and drop onto image. + * + * @package qtype_ddimageortext + * @category test + * @copyright 2015 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. + +require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php'); + +/** + * Steps definitions related with the drag and drop onto image question type. + * + * @copyright 2015 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class behat_qtype_ddimageortext extends behat_base { + + /** + * Get the xpath for a given drag item. + * @param string $dragitem the text of the item to drag. + * @return string the xpath expression. + */ + protected function drag_xpath($dragitem) { + return '//div[contains(@class, " drag ") and contains(normalize-space(.), "' . $this->escape($dragitem) . '")]'; + } + + /** + * Get the xpath for a given drop box. + * @param string $dragitem the number of the drop box. + * @return string the xpath expression. + */ + protected function drop_xpath($placenumber) { + return '//div[contains(@class, "dropzone ") and contains(@class, "place' . $placenumber . ' ")]'; + } + + /** + * Drag the drag item with the given text to the given space. + * + * @param string $dragitem the text of the item to drag. + * @param int $placenumber the number of the place to drop into. + * + * @Given /^I drag "(?P[^"]*)" to place "(?P\d+)" in the drag and drop onto image question$/ + * + */ + public function i_drag_to_place_in_the_drag_and_drop_onto_image_question($dragitem, $placenumber) { + $generalcontext = behat_context_helper::get('behat_general'); + $generalcontext->i_drag_and_i_drop_it_in($this->drag_xpath($dragitem), + 'xpath_element', $this->drop_xpath($placenumber), 'xpath_element'); + } + + /** + * Type some characters while focussed on a given drop box. + * + * @param string $keys the characters to type. + * @param int $placenumber the number of the place to drop into. + * + * @Given /^I type "(?P[^"]*)" on place "(?P\d+)" in the drag and drop onto image question$/ + */ + public function i_type_on_place_in_the_drag_and_drop_onto_image_question($keys, $placenumber) { + $generalcontext = behat_context_helper::get('behat_general'); + $generalcontext->i_type_into_the($keys, $this->drop_xpath($placenumber), 'xpath_element'); + } +} diff --git a/question/type/ddimageortext/tests/behat/edit.feature b/question/type/ddimageortext/tests/behat/edit.feature new file mode 100644 index 00000000000..ca18b7ea220 --- /dev/null +++ b/question/type/ddimageortext/tests/behat/edit.feature @@ -0,0 +1,33 @@ +@ou @ou_vle @qtype @qtype_ddimageortext +Feature: Test editing a drag and drop onto image questions + As a teacher + In order to be able to update my drag and drop onto image questions + I need to edit them + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | T1 | Teacher1 | teacher1@example.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + And the following "question categories" exist: + | contextlevel | reference | name | + | Course | C1 | Test questions | + And the following "questions" exist: + | questioncategory | qtype | name | template | + | Test questions | ddimageortext | Drag onto image | xsection | + And I log in as "teacher1" + And I follow "Course 1" + And I navigate to "Question bank" node in "Course administration" + + @javascript + Scenario: Edit a drag and drop onto image question + When I click on "Edit" "link" in the "Drag onto image" "table_row" + And I set the following fields to these values: + | Question name | Edited question name | + And I press "id_submitbutton" + Then I should see "Edited question name" diff --git a/question/type/ddimageortext/tests/behat/export.feature b/question/type/ddimageortext/tests/behat/export.feature new file mode 100644 index 00000000000..ee2d80b9333 --- /dev/null +++ b/question/type/ddimageortext/tests/behat/export.feature @@ -0,0 +1,37 @@ +@ou @ou_vle @qtype @qtype_ddimageortext +Feature: Test exporting drag and drop onto image questions + As a teacher + In order to be able to reuse my drag and drop onto image questions + I need to export them + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | T1 | Teacher1 | teacher1@example.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + And the following "question categories" exist: + | contextlevel | reference | name | + | Course | C1 | Test questions | + And the following "questions" exist: + | questioncategory | qtype | name | template | + | Test questions | ddimageortext | Drag onto image | xsection | + And I log in as "teacher1" + And I follow "Course 1" + + @javascript + Scenario: Export a drag and drop onto image question + # Import sample file. + When I navigate to "Export" node in "Course administration > Question bank" + And I set the field "id_format_xml" to "1" + And I press "Export questions to file" + And following "click here" should download between "18500" and "19000" bytes + # If the download step is the last in the scenario then we can sometimes run + # into the situation where the download page causes a http redirect but behat + # has already conducted its reset (generating an error). By putting a logout + # step we avoid behat doing the reset until we are off that page. + And I log out diff --git a/question/type/ddimageortext/tests/behat/import_test.feature b/question/type/ddimageortext/tests/behat/import.feature similarity index 70% rename from question/type/ddimageortext/tests/behat/import_test.feature rename to question/type/ddimageortext/tests/behat/import.feature index ab4ddf770c2..58079b9653b 100644 --- a/question/type/ddimageortext/tests/behat/import_test.feature +++ b/question/type/ddimageortext/tests/behat/import.feature @@ -1,24 +1,24 @@ @ou @ou_vle @qtype @qtype_ddimageortext -Feature: Test all the basic functionality of this question type - As a manager/teacher i should be able to import questions from other courses to this course +Feature: Test importing drag and drop onto image questions + As a teacher + In order to reuse drag and drop onto image questions + I need to import them Background: - Given the following "users" exist: + Given the following "users" exist: | username | firstname | lastname | email | - | teacher1 | T1 | Teacher1 | teacher1@moodle.com | - | manager1 | M1 | Manager1 | manager11@moodle.com | + | teacher1 | T1 | Teacher1 | teacher1@example.com | And the following "courses" exist: | fullname | shortname | category | | Course 1 | C1 | 0 | And the following "course enrolments" exist: | user | course | role | | teacher1 | C1 | editingteacher | - | manager1 | C1 | manager | And I log in as "teacher1" And I follow "Course 1" - @javascript - Scenario: import a variable numeric sets question. + @javascript @_file_upload + Scenario: import drag and drop onto image question. When I navigate to "Import" node in "Course administration > Question bank" And I set the field "id_format_xml" to "1" And I upload "question/type/ddimageortext/tests/fixtures/testquestion.moodle.xml" file to "Import" filemanager diff --git a/question/type/ddimageortext/tests/behat/preview.feature b/question/type/ddimageortext/tests/behat/preview.feature new file mode 100644 index 00000000000..7fde499e362 --- /dev/null +++ b/question/type/ddimageortext/tests/behat/preview.feature @@ -0,0 +1,60 @@ +@ou @ou_vle @qtype @qtype_ddimageortext +Feature: Preview a drag-drop onto image question + As a teacher + In order to check my drag-drop onto image questions will work for students + I need to preview them + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | T1 | Teacher1 | teacher1@moodle.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + And the following "question categories" exist: + | contextlevel | reference | name | + | Course | C1 | Test questions | + And the following "questions" exist: + | questioncategory | qtype | name | template | + | Test questions | ddimageortext | Drag onto image | xsection | + Given I log in as "teacher1" + And I follow "Course 1" + And I navigate to "Question bank" node in "Course administration" + + @javascript + Scenario: Preview a question using the mouse. + When I click on "Preview" "link" in the "Drag onto image" "table_row" + And I switch to "questionpreview" window + And I wait "2" seconds + # Odd, but the
    s go to nothing, not a space. + And I drag "mountainbelt" to place "1" in the drag and drop onto image question + And I drag "continentalshelf" to place "2" in the drag and drop onto image question + And I drag "oceantrench" to place "3" in the drag and drop onto image question + And I drag "abyssalplain" to place "4" in the drag and drop onto image question + And I drag "continentalslope" to place "5" in the drag and drop onto image question + And I drag "continentalrise" to place "6" in the drag and drop onto image question + And I drag "islandarc" to place "7" in the drag and drop onto image question + And I drag "mid-oceanridge" to place "8" in the drag and drop onto image question + And I press "Submit and finish" + Then the state of "Identify the features" question is shown as "Correct" + And I should see "Mark 1.00 out of 1.00" + + @javascript + Scenario: Preview a question using the keyboard. + When I click on "Preview" "link" in the "Drag onto image" "table_row" + And I switch to "questionpreview" window + And I wait "1" seconds + And I type " " on place "1" in the drag and drop onto image question + And I type " " on place "2" in the drag and drop onto image question + And I type " " on place "3" in the drag and drop onto image question + And I type " " on place "4" in the drag and drop onto image question + And I type " " on place "5" in the drag and drop onto image question + And I type " " on place "6" in the drag and drop onto image question + And I type " " on place "7" in the drag and drop onto image question + And I type " " on place "8" in the drag and drop onto image question + And I press "Submit and finish" + Then the state of "Identify the features" question is shown as "Correct" + And I should see "Mark 1.00 out of 1.00" diff --git a/question/type/ddimageortext/tests/helper.php b/question/type/ddimageortext/tests/helper.php index 2068f614b78..864b5119d66 100644 --- a/question/type/ddimageortext/tests/helper.php +++ b/question/type/ddimageortext/tests/helper.php @@ -34,7 +34,7 @@ defined('MOODLE_INTERNAL') || die(); */ class qtype_ddimageortext_test_helper extends question_test_helper { public function get_test_questions() { - return array('fox', 'maths'); + return array('fox', 'maths', 'xsection'); } /** @@ -127,4 +127,115 @@ class qtype_ddimageortext_test_helper extends question_test_helper { return $dd; } + + /** + * @return stdClass date to create a ddimageortext question. + */ + public function get_ddimageortext_question_form_data_xsection() { + global $CFG, $USER; + $fromform = new stdClass(); + + $bgdraftitemid = 0; + file_prepare_draft_area($bgdraftitemid, null, null, null, null); + $fs = get_file_storage(); + $filerecord = new stdClass(); + $filerecord->contextid = context_user::instance($USER->id)->id; + $filerecord->component = 'user'; + $filerecord->filearea = 'draft'; + $filerecord->itemid = $bgdraftitemid; + $filerecord->filepath = '/'; + $filerecord->filename = 'oceanfloorbase.jpg'; + $fs->create_file_from_pathname($filerecord, $CFG->dirroot . + '/question/type/ddimageortext/tests/fixtures/oceanfloorbase.jpg'); + + $fromform->name = 'Geography cross-section'; + $fromform->questiontext = array( + 'text' => '

    Identify the features in this cross-section by dragging the labels into the boxes.

    +

    Use the mouse to drag the boxed words into the empty boxes. Alternatively, use the tab key to select an empty box, then use the space key to cycle through the options.

    ', + 'format' => FORMAT_HTML, + ); + $fromform->defaultmark = 1; + $fromform->generalfeedback = array( + 'text' => '

    More information about the major features of the Earth\'s surface can be found in Block 3, Section 6.2.

    ', + 'format' => FORMAT_HTML, + ); + $fromform->bgimage = $bgdraftitemid; + $fromform->shuffleanswers = 0; + $fromform->drags = array( + array('dragitemtype' => 'word', 'draggroup' => '1', 'infinite' => '0'), + array('dragitemtype' => 'word', 'draggroup' => '1', 'infinite' => '0'), + array('dragitemtype' => 'word', 'draggroup' => '1', 'infinite' => '0'), + array('dragitemtype' => 'word', 'draggroup' => '1', 'infinite' => '0'), + array('dragitemtype' => 'word', 'draggroup' => '1', 'infinite' => '0'), + array('dragitemtype' => 'word', 'draggroup' => '1', 'infinite' => '0'), + array('dragitemtype' => 'word', 'draggroup' => '1', 'infinite' => '0'), + array('dragitemtype' => 'word', 'draggroup' => '1', 'infinite' => '0'), + ); + $fromform->dragitem = array(0, 0, 0, 0, 0, 0, 0, 0); + $fromform->draglabel = + array( + 'island
    arc', + 'mid-ocean
    ridge', + 'abyssal
    plain', + 'continental
    rise', + 'ocean
    trench', + 'continental
    slope', + 'mountain
    belt', + 'continental
    shelf', + ); + $fromform->drops = array( + array('xleft' => '53', 'ytop' => '17', 'choice' => '7', 'droplabel' => ''), + array('xleft' => '172', 'ytop' => '2', 'choice' => '8', 'droplabel' => ''), + array('xleft' => '363', 'ytop' => '31', 'choice' => '5', 'droplabel' => ''), + array('xleft' => '440', 'ytop' => '13', 'choice' => '3', 'droplabel' => ''), + array('xleft' => '115', 'ytop' => '74', 'choice' => '6', 'droplabel' => ''), + array('xleft' => '210', 'ytop' => '94', 'choice' => '4', 'droplabel' => ''), + array('xleft' => '310', 'ytop' => '87', 'choice' => '1', 'droplabel' => ''), + array('xleft' => '479', 'ytop' => '84', 'choice' => '2', 'droplabel' => ''), + ); + + test_question_maker::set_standard_combined_feedback_form_data($fromform); + + $fromform->penalty ='0.3333333'; + $fromform->hint = array( + array( + 'text' => '

    Incorrect placements will be removed.

    ', + 'format' => FORMAT_HTML, + ), + array( + 'text' => '
      +
    • The abyssal plain is a flat almost featureless expanse of ocean floor 4km to 6km below sea-level.
    • +
    • The continental rise is the gently sloping part of the ocean floor beyond the continental slope.
    • +
    • The continental shelf is the gently sloping ocean floor just offshore from the land.
    • +
    • The continental slope is the relatively steep part of the ocean floor beyond the continental shelf.
    • +
    • A mid-ocean ridge is a broad submarine ridge several kilometres high.
    • +
    • A mountain belt is a long range of mountains.
    • +
    • An island arc is a chain of volcanic islands.
    • +
    • An oceanic trench is a deep trough in the ocean floor.
    • +
    ', + 'format' => FORMAT_HTML, + ), + array( + 'text' => '

    Incorrect placements will be removed.

    ', + 'format' => FORMAT_HTML, + ), + array( + 'text' => '
      +
    • The abyssal plain is a flat almost featureless expanse of ocean floor 4km to 6km below sea-level.
    • +
    • The continental rise is the gently sloping part of the ocean floor beyond the continental slope.
    • +
    • The continental shelf is the gently sloping ocean floor just offshore from the land.
    • +
    • The continental slope is the relatively steep part of the ocean floor beyond the continental shelf.
    • +
    • A mid-ocean ridge is a broad submarine ridge several kilometres high.
    • +
    • A mountain belt is a long range of mountains.
    • +
    • An island arc is a chain of volcanic islands.
    • +
    • An oceanic trench is a deep trough in the ocean floor.
    • +
    ', + 'format' => FORMAT_HTML, + ), + ); + $fromform->hintclearwrong = array(1, 0, 1, 0); + $fromform->hintshownumcorrect = array(1, 1, 1, 1); + + return $fromform; + } } From cf5977991c092462804810bc2c42221e1788d8bd Mon Sep 17 00:00:00 2001 From: M Kassaei Date: Thu, 29 Jan 2015 16:47:09 +0000 Subject: [PATCH 196/208] MDL-47494 ddimageortext: Convert the JavaScript to use Shifter. #13314 --- .../moodle-qtype_ddimageortext-dd-debug.js | 482 ++++++++++++++++++ .../moodle-qtype_ddimageortext-dd-min.js | 2 + .../moodle-qtype_ddimageortext-dd.js | 482 ++++++++++++++++++ .../moodle-qtype_ddimageortext-form-debug.js | 354 +++++++++++++ .../moodle-qtype_ddimageortext-form-min.js | 2 + .../moodle-qtype_ddimageortext-form.js | 354 +++++++++++++ question/type/ddimageortext/yui/dd/dd.js | 464 ----------------- question/type/ddimageortext/yui/form/form.js | 336 ------------ .../yui/src/ddimageortext/build.json | 10 + .../yui/src/ddimageortext/js/ddimageortext.js | 478 +++++++++++++++++ .../src/ddimageortext/meta/ddimageortext.json | 10 + .../ddimageortext/yui/src/form/build.json | 10 + .../ddimageortext/yui/src/form/js/form.js | 349 +++++++++++++ .../ddimageortext/yui/src/form/meta/form.json | 8 + 14 files changed, 2541 insertions(+), 800 deletions(-) create mode 100644 question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js create mode 100644 question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js create mode 100644 question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js create mode 100644 question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js create mode 100644 question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js create mode 100644 question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form.js delete mode 100644 question/type/ddimageortext/yui/dd/dd.js delete mode 100644 question/type/ddimageortext/yui/form/form.js create mode 100644 question/type/ddimageortext/yui/src/ddimageortext/build.json create mode 100644 question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js create mode 100644 question/type/ddimageortext/yui/src/ddimageortext/meta/ddimageortext.json create mode 100644 question/type/ddimageortext/yui/src/form/build.json create mode 100644 question/type/ddimageortext/yui/src/form/js/form.js create mode 100644 question/type/ddimageortext/yui/src/form/meta/form.json diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js new file mode 100644 index 00000000000..10bacdda793 --- /dev/null +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js @@ -0,0 +1,482 @@ +YUI.add('moodle-qtype_ddimageortext-dd', function (Y, NAME) { + +// This file is part of Moodle - http://moodle.org/ +// +// 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 . + +var DDIMAGEORTEXTDDNAME = 'ddimageortext_dd'; +var DDIMAGEORTEXT_DD = function() { + DDIMAGEORTEXT_DD.superclass.constructor.apply(this, arguments); +}; + +/** + * This is the base class for the question rendering and question editing form code. + */ +Y.extend(DDIMAGEORTEXT_DD, Y.Base, { + doc : null, + polltimer : null, + afterimageloaddone : false, + poll_for_image_load : function (e, waitforimageconstrain, pause, doafterwords) { + if (this.afterimageloaddone) { + return; + } + var bgdone = this.doc.bg_img().get('complete'); + if (waitforimageconstrain) { + bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); + } + var alldragsloaded = !this.doc.drag_item_homes().some(function(dragitemhome){ + //in 'some' loop returning true breaks the loop and is passed as return value from + //'some' else returns false. Can be though of as equivalent to ||. + if (dragitemhome.get('tagName') !== 'IMG'){ + return false; + } + var done = (dragitemhome.get('complete')); + if (waitforimageconstrain) { + done = done && dragitemhome.hasClass('constrained'); + } + return !done; + }); + if (bgdone && alldragsloaded) { + if (this.polltimer !== null) { + this.polltimer.cancel(); + this.polltimer = null; + } + this.doc.drag_item_homes().detach('load', this.poll_for_image_load); + this.doc.bg_img().detach('load', this.poll_for_image_load); + if (pause !== 0) { + Y.later(pause, this, doafterwords); + } else { + doafterwords.call(this); + } + this.afterimageloaddone = true; + } else if (this.polltimer === null) { + var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; + this.polltimer = + Y.later(1000, this, this.poll_for_image_load, pollarguments, true); + } + }, + /** + * Object to encapsulate operations on dd area. + */ + doc_structure : function (mainobj) { + var topnode = Y.one(this.get('topnode')); + var dragitemsarea = topnode.one('div.dragitems'); + var dropbgarea = topnode.one('div.droparea'); + return { + top_node : function() { + return topnode; + }, + drag_items : function() { + return dragitemsarea.all('.drag'); + }, + drop_zones : function() { + return topnode.all('div.dropzones div.dropzone'); + }, + drop_zone_group : function(groupno) { + return topnode.all('div.dropzones div.group' + groupno); + }, + drag_items_cloned_from : function(dragitemno) { + return dragitemsarea.all('.dragitems' + dragitemno); + }, + drag_item : function(draginstanceno) { + return dragitemsarea.one('.draginstance' + draginstanceno); + }, + drag_items_in_group : function(groupno) { + return dragitemsarea.all('.drag.group' + groupno); + }, + drag_item_homes : function() { + return dragitemsarea.all('.draghome'); + }, + bg_img : function() { + return topnode.one('.dropbackground'); + }, + load_bg_img : function (url) { + dropbgarea.setContent(''); + this.bg_img().on('load', this.on_image_load, this, 'bg_image'); + }, + add_or_update_drag_item_home : function (dragitemno, url, alt, group) { + var oldhome = this.drag_item_home(dragitemno); + var classes = 'draghome dragitemhomes' + dragitemno + ' group' + group; + var imghtml = '' + alt + ''; + var divhtml = '
    ' + alt + '
    '; + if (oldhome === null) { + if (url) { + dragitemsarea.append(imghtml); + } else if (alt !== '') { + dragitemsarea.append(divhtml); + } + } else { + if (url) { + dragitemsarea.insert(imghtml, oldhome); + } else if (alt !== '') { + dragitemsarea.insert(divhtml, oldhome); + } + oldhome.remove(true); + } + var newlycreated = dragitemsarea.one('.dragitemhomes' + dragitemno); + if (newlycreated !== null) { + newlycreated.setData('groupno', group); + newlycreated.setData('dragitemno', dragitemno); + } + }, + drag_item_home : function (dragitemno) { + return dragitemsarea.one('.dragitemhomes' + dragitemno); + }, + get_classname_numeric_suffix : function(node, prefix) { + var classes = node.getAttribute('class'); + if (classes !== '') { + var classesarr = classes.split(' '); + for (var index = 0; index < classesarr.length; index++) { + var patt1 = new RegExp('^' + prefix + '([0-9])+$'); + if (patt1.test(classesarr[index])) { + var patt2 = new RegExp('([0-9])+$'); + var match = patt2.exec(classesarr[index]); + return + match[0]; + } + } + } + throw 'Prefix "' + prefix + '" not found in class names.'; + }, + clone_new_drag_item : function (draginstanceno, dragitemno) { + var draghome = this.drag_item_home(dragitemno); + if (draghome === null) { + return null; + } + var drag = draghome.cloneNode(true); + drag.removeClass('dragitemhomes' + dragitemno); + drag.addClass('dragitems' + dragitemno); + drag.addClass('draginstance' + draginstanceno); + drag.removeClass('draghome'); + drag.addClass('drag'); + drag.setStyles({'visibility': 'visible', 'position' : 'absolute'}); + drag.setData('draginstanceno', draginstanceno); + drag.setData('dragitemno', dragitemno); + draghome.get('parentNode').appendChild(drag); + return drag; + }, + draggable_for_question : function (drag, group, choice) { + new Y.DD.Drag({ + node: drag, + dragMode: 'point', + groups: [group] + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + + drag.setData('group', group); + drag.setData('choice', choice); + + }, + draggable_for_form : function (drag) { + var dd = new Y.DD.Drag({ + node: drag, + dragMode: 'point' + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + dd.on('drag:end', function(e) { + var dragnode = e.target.get('node'); + var draginstanceno = dragnode.getData('draginstanceno'); + var gooddrop = dragnode.getData('gooddrop'); + + if (!gooddrop) { + mainobj.reset_drag_xy(draginstanceno); + } else { + mainobj.set_drag_xy(draginstanceno, [e.pageX, e.pageY]); + } + }, this); + dd.on('drag:start', function(e) { + var drag = e.target; + drag.get('node').setData('gooddrop', false); + }, this); + + } + + }; + }, + + update_padding_sizes_all : function () { + for (var groupno = 1; groupno <= 8; groupno++) { + this.update_padding_size_for_group(groupno); + } + }, + update_padding_size_for_group : function (groupno) { + var groupitems = this.doc.top_node().all('.draghome.group' + groupno); + if (groupitems.size() !== 0) { + var maxwidth = 0; + var maxheight = 0; + groupitems.each(function(item){ + maxwidth = Math.max(maxwidth, item.get('clientWidth')); + maxheight = Math.max(maxheight, item.get('clientHeight')); + }, this); + groupitems.each(function(item) { + var margintopbottom = Math.round((10 + maxheight - item.get('clientHeight')) / 2); + var marginleftright = Math.round((10 + maxwidth - item.get('clientWidth')) / 2); + item.setStyle('padding', margintopbottom + 'px ' + marginleftright + 'px ' + + margintopbottom + 'px ' + marginleftright + 'px'); + }, this); + this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, + 'height': maxheight + 10}); + } + }, + convert_to_window_xy : function (bgimgxy) { + return [Number(bgimgxy[0]) + this.doc.bg_img().getX() + 1, + Number(bgimgxy[1]) + this.doc.bg_img().getY() + 1]; + } +}, { + NAME : DDIMAGEORTEXTDDNAME, + ATTRS : { + drops : {value : null}, + readonly : {value : false}, + topnode : {value : null} + } +}); + +M.qtype_ddimageortext = M.qtype_ddimageortext || {}; +M.qtype_ddimageortext.dd_base_class = DDIMAGEORTEXT_DD; + +var DDIMAGEORTEXTQUESTIONNAME = 'ddimageortext_question'; +var DDIMAGEORTEXT_QUESTION = function() { + DDIMAGEORTEXT_QUESTION.superclass.constructor.apply(this, arguments); +}; +/** + * This is the code for question rendering. + */ +Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { + initializer : function() { + this.doc = this.doc_structure(this); + this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); + this.doc.bg_img().after('load', this.poll_for_image_load, this, + false, 0, this.create_all_drag_and_drops); + this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, + false, 0, this.create_all_drag_and_drops); + Y.later(500, this, this.reposition_drags_for_question, [], true); + }, + create_all_drag_and_drops : function () { + this.init_drops(); + this.update_padding_sizes_all(); + var i = 0; + this.doc.drag_item_homes().each(function(dragitemhome){ + var dragitemno = Number(this.doc.get_classname_numeric_suffix(dragitemhome, 'dragitemhomes')); + var choice = + this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); + var group = + this.doc.get_classname_numeric_suffix(dragitemhome, 'group'); + var groupsize = this.doc.drop_zone_group(group).size(); + var dragnode = this.doc.clone_new_drag_item(i, dragitemno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + if (dragnode.hasClass('infinite')) { + var dragstocreate = groupsize - 1; + while (dragstocreate > 0) { + dragnode = this.doc.clone_new_drag_item(i, dragitemno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + dragstocreate--; + } + } + }, this); + this.reposition_drags_for_question(); + if (!this.get('readonly')) { + this.doc.drop_zones().set('tabIndex', 0); + this.doc.drop_zones().each( + function(v){ + v.on('dragchange', this.drop_zone_key_press, this); + }, this); + } + }, + drop_zone_key_press : function (e) { + switch (e.direction) { + case 'next' : + this.place_next_drag_in(e.target); + break; + case 'previous' : + this.place_previous_drag_in(e.target); + break; + case 'remove' : + this.remove_drag_from_drop(e.target); + break; + } + e.preventDefault(); + this.reposition_drags_for_question(); + }, + place_next_drag_in : function (drop) { + this.search_for_unplaced_drop_choice(drop, 1); + }, + place_previous_drag_in : function (drop) { + this.search_for_unplaced_drop_choice(drop, -1); + }, + search_for_unplaced_drop_choice : function (drop, direction) { + var next; + var current = this.current_drag_in_drop(drop); + if ('' === current) { + if (direction === 1) { + next = 1; + } else { + next = 1; + var groupno = drop.getData('group'); + this.doc.drag_items_in_group(groupno).each(function(drag) { + next = Math.max(next, drag.getData('choice')); + }, this); + } + } else { + next = + current + direction; + } + var drag; + do { + if (this.get_choices_for_drop(next, drop).size() === 0){ + this.remove_drag_from_drop(drop); + return; + } else { + drag = this.get_unplaced_choice_for_drop(next, drop); + } + next = next + direction; + } while (drag === null); + this.place_drag_in_drop(drag, drop); + }, + current_drag_in_drop : function (drop) { + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#' + inputid); + return inputnode.get('value'); + }, + remove_drag_from_drop : function (drop) { + this.place_drag_in_drop(null, drop); + }, + place_drag_in_drop : function (drag, drop) { + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#' + inputid); + if (drag !== null) { + inputnode.set('value', drag.getData('choice')); + } else { + inputnode.set('value', ''); + } + }, + reposition_drags_for_question : function() { + this.doc.drag_items().removeClass('placed'); + this.doc.drag_items().each (function (dragitem) { + if (dragitem.dd !== undefined) { + dragitem.dd.detachAll('drag:start'); + } + }, this); + this.doc.drop_zones().each(function(dropzone) { + var relativexy = dropzone.getData('xy'); + dropzone.setXY(this.convert_to_window_xy(relativexy)); + var inputcss = 'input#' + dropzone.getData('inputid'); + var input = this.doc.top_node().one(inputcss); + var choice = input.get('value'); + if (choice !== "") { + var dragitem = this.get_unplaced_choice_for_drop(choice, dropzone); + if (dragitem !== null) { + dragitem.setXY(dropzone.getXY()); + dragitem.addClass('placed'); + if (dragitem.dd !== undefined) { + dragitem.dd.once('drag:start', function (e, input) { + input.set('value', ''); + e.target.get('node').removeClass('placed'); + },this, input); + } + } + } + }, this); + this.doc.drag_items().each(function(dragitem) { + if (!dragitem.hasClass('placed') && !dragitem.hasClass('yui3-dd-dragging')) { + var dragitemhome = this.doc.drag_item_home(dragitem.getData('dragitemno')); + dragitem.setXY(dragitemhome.getXY()); + } + }, this); + }, + get_choices_for_drop : function(choice, drop) { + var group = drop.getData('group'); + return this.doc.top_node().all( + 'div.dragitemgroup' + group + ' .choice' + choice + '.drag'); + }, + get_unplaced_choice_for_drop : function(choice, drop) { + var dragitems = this.get_choices_for_drop(choice, drop); + var dragitem = null; + dragitems.some(function (d) { + if (!d.hasClass('placed') && !d.hasClass('yui3-dd-dragging')) { + dragitem = d; + return true; + } else { + return false; + } + }); + return dragitem; + }, + init_drops : function () { + var dropareas = this.doc.top_node().one('div.dropzones'); + var groupnodes = {}; + for (var groupno = 1; groupno <= 8; groupno++) { + var groupnode = Y.Node.create('
    '); + dropareas.append(groupnode); + groupnodes[groupno] = groupnode; + } + var drop_hit_handler = function(e) { + var drag = e.drag.get('node'); + var drop = e.drop.get('node'); + if (Number(drop.getData('group')) === drag.getData('group')){ + this.place_drag_in_drop(drag, drop); + } + }; + for (var dropno in this.get('drops')) { + var drop = this.get('drops')[dropno]; + var nodeclass = 'dropzone group' + drop.group + ' place' + dropno; + var title = drop.text.replace('"', '\"'); + var dropnodehtml = '
     
    '; + var dropnode = Y.Node.create(dropnodehtml); + groupnodes[drop.group].append(dropnode); + dropnode.setStyles({'opacity': 0.5}); + dropnode.setData('xy', drop.xy); + dropnode.setData('place', dropno); + dropnode.setData('inputid', drop.fieldname.replace(':', '_')); + dropnode.setData('group', drop.group); + var dropdd = new Y.DD.Drop({ + node: dropnode, groups : [drop.group]}); + dropdd.on('drop:hit', drop_hit_handler, this); + } + } +}, {NAME : DDIMAGEORTEXTQUESTIONNAME, ATTRS : {}}); + +Y.Event.define('dragchange', { + // Webkit and IE repeat keydown when you hold down arrow keys. + // Opera links keypress to page scroll; others keydown. + // Firefox prevents page scroll via preventDefault() on either + // keydown or keypress. + _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', + + _keys: { + '32': 'next', // Space + '37': 'previous', // Left arrow + '38': 'previous', // Up arrow + '39': 'next', // Right arrow + '40': 'next', // Down arrow + '27': 'remove' // Escape + }, + + _keyHandler: function (e, notifier) { + if (this._keys[e.keyCode]) { + e.direction = this._keys[e.keyCode]; + notifier.fire(e); + } + }, + + on: function (node, sub, notifier) { + sub._detacher = node.on(this._event, this._keyHandler, + this, notifier); + } +}); + +M.qtype_ddimageortext.init_question = function(config) { + return new DDIMAGEORTEXT_QUESTION(config); +}; + +}, '@VERSION@', {"requires": ["node", "dd", "dd-drop", "dd-constrain"]}); diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js new file mode 100644 index 00000000000..a7f8f78af6e --- /dev/null +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js @@ -0,0 +1,2 @@ +YUI.add("moodle-qtype_ddimageortext-dd",function(e,t){var n="ddimageortext_dd",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,e.Base,{doc:null,polltimer:null,afterimageloaddone:!1,poll_for_image_load:function(t,n,r,i){if(this.afterimageloaddone)return;var s=this.doc.bg_img().get("complete");n&&(s=s&&this.doc.bg_img().hasClass("constrained"));var o=!this.doc.drag_item_homes().some(function(e){if(e.get("tagName")!=="IMG")return!1;var t=e.get("complete");return n&&(t=t&&e.hasClass("constrained")),!t});if(s&&o)this.polltimer!==null&&(this.polltimer.cancel(),this.polltimer=null),this.doc.drag_item_homes().detach("load",this.poll_for_image_load),this.doc.bg_img().detach("load",this.poll_for_image_load),r!==0?e.later(r,this,i):i.call(this),this.afterimageloaddone=!0;else if(this.polltimer===null){var u=[null,n,r,i];this.polltimer=e.later(1e3,this,this.poll_for_image_load,u,!0)}},doc_structure:function(t){var n=e.one(this.get("topnode")),r=n.one("div.dragitems"),i=n.one("div.droparea");return{top_node:function(){return n},drag_items:function(){return r.all(".drag")},drop_zones:function(){return n.all("div.dropzones div.dropzone")},drop_zone_group:function(e){return n.all("div.dropzones div.group"+e)},drag_items_cloned_from:function(e){return r.all(".dragitems"+e)},drag_item:function(e){return r.one(".draginstance"+e)},drag_items_in_group:function(e){return r.all(".drag.group"+e)},drag_item_homes:function(){return r.all(".draghome")},bg_img:function(){return n.one(".dropbackground")},load_bg_img:function(e){i.setContent(''),this.bg_img().on("load",this.on_image_load,this,"bg_image")},add_or_update_drag_item_home:function(e,t,n,i){var s=this.drag_item_home(e),o="draghome dragitemhomes"+e+" group"+i,u=''+n+'',a='
    '+n+"
    ";s===null?t?r.append(u):n!==""&&r.append(a):(t?r.insert(u,s):n!==""&&r.insert(a,s),s.remove(!0));var f=r.one(".dragitemhomes"+e);f!==null&&(f.setData("groupno",i),f.setData("dragitemno",e))},drag_item_home:function(e){return r.one(".dragitemhomes"+e)},get_classname_numeric_suffix:function(e,t){var n=e.getAttribute("class");if(n!==""){var r=n.split(" ");for(var i=0;i0)o=this.doc.clone_new_drag_item(e,n),e++,this.get("readonly")||this.doc.draggable_for_question(o,i,r),u--}},this),this.reposition_drags_for_question(),this.get("readonly")||(this.doc.drop_zones().set("tabIndex",0),this.doc.drop_zones().each(function(e){e.on("dragchange",this.drop_zone_key_press,this)},this))},drop_zone_key_press:function(e){switch(e.direction){case"next":this.place_next_drag_in(e.target);break;case"previous":this.place_previous_drag_in(e.target);break;case"remove":this.remove_drag_from_drop(e.target)}e.preventDefault(),this.reposition_drags_for_question()},place_next_drag_in:function(e){this.search_for_unplaced_drop_choice(e,1)},place_previous_drag_in:function(e){this.search_for_unplaced_drop_choice(e,-1)},search_for_unplaced_drop_choice +:function(e,t){var n,r=this.current_drag_in_drop(e);if(""===r)if(t===1)n=1;else{n=1;var i=e.getData("group");this.doc.drag_items_in_group(i).each(function(e){n=Math.max(n,e.getData("choice"))},this)}else n=+r+t;var s;do{if(this.get_choices_for_drop(n,e).size()===0){this.remove_drag_from_drop(e);return}s=this.get_unplaced_choice_for_drop(n,e),n+=t}while(s===null);this.place_drag_in_drop(s,e)},current_drag_in_drop:function(t){var n=t.getData("inputid"),r=e.one("input#"+n);return r.get("value")},remove_drag_from_drop:function(e){this.place_drag_in_drop(null,e)},place_drag_in_drop:function(t,n){var r=n.getData("inputid"),i=e.one("input#"+r);t!==null?i.set("value",t.getData("choice")):i.set("value","")},reposition_drags_for_question:function(){this.doc.drag_items().removeClass("placed"),this.doc.drag_items().each(function(e){e.dd!==undefined&&e.dd.detachAll("drag:start")},this),this.doc.drop_zones().each(function(e){var t=e.getData("xy");e.setXY(this.convert_to_window_xy(t));var n="input#"+e.getData("inputid"),r=this.doc.top_node().one(n),i=r.get("value");if(i!==""){var s=this.get_unplaced_choice_for_drop(i,e);s!==null&&(s.setXY(e.getXY()),s.addClass("placed"),s.dd!==undefined&&s.dd.once("drag:start",function(e,t){t.set("value",""),e.target.get("node").removeClass("placed")},this,r))}},this),this.doc.drag_items().each(function(e){if(!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")){var t=this.doc.drag_item_home(e.getData("dragitemno"));e.setXY(t.getXY())}},this)},get_choices_for_drop:function(e,t){var n=t.getData("group");return this.doc.top_node().all("div.dragitemgroup"+n+" .choice"+e+".drag")},get_unplaced_choice_for_drop:function(e,t){var n=this.get_choices_for_drop(e,t),r=null;return n.some(function(e){return!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")?(r=e,!0):!1}),r},init_drops:function(){var t=this.doc.top_node().one("div.dropzones"),n={};for(var r=1;r<=8;r++){var i=e.Node.create('
    ');t.append(i),n[r]=i}var s=function(e){var t=e.drag.get("node"),n=e.drop.get("node");Number(n.getData("group"))===t.getData("group")&&this.place_drag_in_drop(t,n)};for(var o in this.get("drops")){var u=this.get("drops")[o],a="dropzone group"+u.group+" place"+o,f=u.text.replace('"','"'),l='
     
    ',c=e.Node.create(l);n[u.group].append(c),c.setStyles({opacity:.5}),c.setData("xy",u.xy),c.setData("place",o),c.setData("inputid",u.fieldname.replace(":","_")),c.setData("group",u.group);var h=new e.DD.Drop({node:c,groups:[u.group]});h.on("drop:hit",s,this)}}},{NAME:i,ATTRS:{}}),e.Event.define("dragchange",{_event:e.UA.webkit||e.UA.ie?"keydown":"keypress",_keys:{32:"next",37:"previous",38:"previous",39:"next",40:"next",27:"remove"},_keyHandler:function(e,t){this._keys[e.keyCode]&&(e.direction=this._keys[e.keyCode],t.fire(e))},on:function(e,t,n){t._detacher=e.on(this._event,this._keyHandler,this,n)}}),M.qtype_ddimageortext.init_question=function(e){return new s(e)}},"@VERSION@",{requires:["node","dd","dd-drop","dd-constrain"]}); diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js new file mode 100644 index 00000000000..10bacdda793 --- /dev/null +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js @@ -0,0 +1,482 @@ +YUI.add('moodle-qtype_ddimageortext-dd', function (Y, NAME) { + +// This file is part of Moodle - http://moodle.org/ +// +// 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 . + +var DDIMAGEORTEXTDDNAME = 'ddimageortext_dd'; +var DDIMAGEORTEXT_DD = function() { + DDIMAGEORTEXT_DD.superclass.constructor.apply(this, arguments); +}; + +/** + * This is the base class for the question rendering and question editing form code. + */ +Y.extend(DDIMAGEORTEXT_DD, Y.Base, { + doc : null, + polltimer : null, + afterimageloaddone : false, + poll_for_image_load : function (e, waitforimageconstrain, pause, doafterwords) { + if (this.afterimageloaddone) { + return; + } + var bgdone = this.doc.bg_img().get('complete'); + if (waitforimageconstrain) { + bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); + } + var alldragsloaded = !this.doc.drag_item_homes().some(function(dragitemhome){ + //in 'some' loop returning true breaks the loop and is passed as return value from + //'some' else returns false. Can be though of as equivalent to ||. + if (dragitemhome.get('tagName') !== 'IMG'){ + return false; + } + var done = (dragitemhome.get('complete')); + if (waitforimageconstrain) { + done = done && dragitemhome.hasClass('constrained'); + } + return !done; + }); + if (bgdone && alldragsloaded) { + if (this.polltimer !== null) { + this.polltimer.cancel(); + this.polltimer = null; + } + this.doc.drag_item_homes().detach('load', this.poll_for_image_load); + this.doc.bg_img().detach('load', this.poll_for_image_load); + if (pause !== 0) { + Y.later(pause, this, doafterwords); + } else { + doafterwords.call(this); + } + this.afterimageloaddone = true; + } else if (this.polltimer === null) { + var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; + this.polltimer = + Y.later(1000, this, this.poll_for_image_load, pollarguments, true); + } + }, + /** + * Object to encapsulate operations on dd area. + */ + doc_structure : function (mainobj) { + var topnode = Y.one(this.get('topnode')); + var dragitemsarea = topnode.one('div.dragitems'); + var dropbgarea = topnode.one('div.droparea'); + return { + top_node : function() { + return topnode; + }, + drag_items : function() { + return dragitemsarea.all('.drag'); + }, + drop_zones : function() { + return topnode.all('div.dropzones div.dropzone'); + }, + drop_zone_group : function(groupno) { + return topnode.all('div.dropzones div.group' + groupno); + }, + drag_items_cloned_from : function(dragitemno) { + return dragitemsarea.all('.dragitems' + dragitemno); + }, + drag_item : function(draginstanceno) { + return dragitemsarea.one('.draginstance' + draginstanceno); + }, + drag_items_in_group : function(groupno) { + return dragitemsarea.all('.drag.group' + groupno); + }, + drag_item_homes : function() { + return dragitemsarea.all('.draghome'); + }, + bg_img : function() { + return topnode.one('.dropbackground'); + }, + load_bg_img : function (url) { + dropbgarea.setContent(''); + this.bg_img().on('load', this.on_image_load, this, 'bg_image'); + }, + add_or_update_drag_item_home : function (dragitemno, url, alt, group) { + var oldhome = this.drag_item_home(dragitemno); + var classes = 'draghome dragitemhomes' + dragitemno + ' group' + group; + var imghtml = '' + alt + ''; + var divhtml = '
    ' + alt + '
    '; + if (oldhome === null) { + if (url) { + dragitemsarea.append(imghtml); + } else if (alt !== '') { + dragitemsarea.append(divhtml); + } + } else { + if (url) { + dragitemsarea.insert(imghtml, oldhome); + } else if (alt !== '') { + dragitemsarea.insert(divhtml, oldhome); + } + oldhome.remove(true); + } + var newlycreated = dragitemsarea.one('.dragitemhomes' + dragitemno); + if (newlycreated !== null) { + newlycreated.setData('groupno', group); + newlycreated.setData('dragitemno', dragitemno); + } + }, + drag_item_home : function (dragitemno) { + return dragitemsarea.one('.dragitemhomes' + dragitemno); + }, + get_classname_numeric_suffix : function(node, prefix) { + var classes = node.getAttribute('class'); + if (classes !== '') { + var classesarr = classes.split(' '); + for (var index = 0; index < classesarr.length; index++) { + var patt1 = new RegExp('^' + prefix + '([0-9])+$'); + if (patt1.test(classesarr[index])) { + var patt2 = new RegExp('([0-9])+$'); + var match = patt2.exec(classesarr[index]); + return + match[0]; + } + } + } + throw 'Prefix "' + prefix + '" not found in class names.'; + }, + clone_new_drag_item : function (draginstanceno, dragitemno) { + var draghome = this.drag_item_home(dragitemno); + if (draghome === null) { + return null; + } + var drag = draghome.cloneNode(true); + drag.removeClass('dragitemhomes' + dragitemno); + drag.addClass('dragitems' + dragitemno); + drag.addClass('draginstance' + draginstanceno); + drag.removeClass('draghome'); + drag.addClass('drag'); + drag.setStyles({'visibility': 'visible', 'position' : 'absolute'}); + drag.setData('draginstanceno', draginstanceno); + drag.setData('dragitemno', dragitemno); + draghome.get('parentNode').appendChild(drag); + return drag; + }, + draggable_for_question : function (drag, group, choice) { + new Y.DD.Drag({ + node: drag, + dragMode: 'point', + groups: [group] + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + + drag.setData('group', group); + drag.setData('choice', choice); + + }, + draggable_for_form : function (drag) { + var dd = new Y.DD.Drag({ + node: drag, + dragMode: 'point' + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + dd.on('drag:end', function(e) { + var dragnode = e.target.get('node'); + var draginstanceno = dragnode.getData('draginstanceno'); + var gooddrop = dragnode.getData('gooddrop'); + + if (!gooddrop) { + mainobj.reset_drag_xy(draginstanceno); + } else { + mainobj.set_drag_xy(draginstanceno, [e.pageX, e.pageY]); + } + }, this); + dd.on('drag:start', function(e) { + var drag = e.target; + drag.get('node').setData('gooddrop', false); + }, this); + + } + + }; + }, + + update_padding_sizes_all : function () { + for (var groupno = 1; groupno <= 8; groupno++) { + this.update_padding_size_for_group(groupno); + } + }, + update_padding_size_for_group : function (groupno) { + var groupitems = this.doc.top_node().all('.draghome.group' + groupno); + if (groupitems.size() !== 0) { + var maxwidth = 0; + var maxheight = 0; + groupitems.each(function(item){ + maxwidth = Math.max(maxwidth, item.get('clientWidth')); + maxheight = Math.max(maxheight, item.get('clientHeight')); + }, this); + groupitems.each(function(item) { + var margintopbottom = Math.round((10 + maxheight - item.get('clientHeight')) / 2); + var marginleftright = Math.round((10 + maxwidth - item.get('clientWidth')) / 2); + item.setStyle('padding', margintopbottom + 'px ' + marginleftright + 'px ' + + margintopbottom + 'px ' + marginleftright + 'px'); + }, this); + this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, + 'height': maxheight + 10}); + } + }, + convert_to_window_xy : function (bgimgxy) { + return [Number(bgimgxy[0]) + this.doc.bg_img().getX() + 1, + Number(bgimgxy[1]) + this.doc.bg_img().getY() + 1]; + } +}, { + NAME : DDIMAGEORTEXTDDNAME, + ATTRS : { + drops : {value : null}, + readonly : {value : false}, + topnode : {value : null} + } +}); + +M.qtype_ddimageortext = M.qtype_ddimageortext || {}; +M.qtype_ddimageortext.dd_base_class = DDIMAGEORTEXT_DD; + +var DDIMAGEORTEXTQUESTIONNAME = 'ddimageortext_question'; +var DDIMAGEORTEXT_QUESTION = function() { + DDIMAGEORTEXT_QUESTION.superclass.constructor.apply(this, arguments); +}; +/** + * This is the code for question rendering. + */ +Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { + initializer : function() { + this.doc = this.doc_structure(this); + this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); + this.doc.bg_img().after('load', this.poll_for_image_load, this, + false, 0, this.create_all_drag_and_drops); + this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, + false, 0, this.create_all_drag_and_drops); + Y.later(500, this, this.reposition_drags_for_question, [], true); + }, + create_all_drag_and_drops : function () { + this.init_drops(); + this.update_padding_sizes_all(); + var i = 0; + this.doc.drag_item_homes().each(function(dragitemhome){ + var dragitemno = Number(this.doc.get_classname_numeric_suffix(dragitemhome, 'dragitemhomes')); + var choice = + this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); + var group = + this.doc.get_classname_numeric_suffix(dragitemhome, 'group'); + var groupsize = this.doc.drop_zone_group(group).size(); + var dragnode = this.doc.clone_new_drag_item(i, dragitemno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + if (dragnode.hasClass('infinite')) { + var dragstocreate = groupsize - 1; + while (dragstocreate > 0) { + dragnode = this.doc.clone_new_drag_item(i, dragitemno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + dragstocreate--; + } + } + }, this); + this.reposition_drags_for_question(); + if (!this.get('readonly')) { + this.doc.drop_zones().set('tabIndex', 0); + this.doc.drop_zones().each( + function(v){ + v.on('dragchange', this.drop_zone_key_press, this); + }, this); + } + }, + drop_zone_key_press : function (e) { + switch (e.direction) { + case 'next' : + this.place_next_drag_in(e.target); + break; + case 'previous' : + this.place_previous_drag_in(e.target); + break; + case 'remove' : + this.remove_drag_from_drop(e.target); + break; + } + e.preventDefault(); + this.reposition_drags_for_question(); + }, + place_next_drag_in : function (drop) { + this.search_for_unplaced_drop_choice(drop, 1); + }, + place_previous_drag_in : function (drop) { + this.search_for_unplaced_drop_choice(drop, -1); + }, + search_for_unplaced_drop_choice : function (drop, direction) { + var next; + var current = this.current_drag_in_drop(drop); + if ('' === current) { + if (direction === 1) { + next = 1; + } else { + next = 1; + var groupno = drop.getData('group'); + this.doc.drag_items_in_group(groupno).each(function(drag) { + next = Math.max(next, drag.getData('choice')); + }, this); + } + } else { + next = + current + direction; + } + var drag; + do { + if (this.get_choices_for_drop(next, drop).size() === 0){ + this.remove_drag_from_drop(drop); + return; + } else { + drag = this.get_unplaced_choice_for_drop(next, drop); + } + next = next + direction; + } while (drag === null); + this.place_drag_in_drop(drag, drop); + }, + current_drag_in_drop : function (drop) { + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#' + inputid); + return inputnode.get('value'); + }, + remove_drag_from_drop : function (drop) { + this.place_drag_in_drop(null, drop); + }, + place_drag_in_drop : function (drag, drop) { + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#' + inputid); + if (drag !== null) { + inputnode.set('value', drag.getData('choice')); + } else { + inputnode.set('value', ''); + } + }, + reposition_drags_for_question : function() { + this.doc.drag_items().removeClass('placed'); + this.doc.drag_items().each (function (dragitem) { + if (dragitem.dd !== undefined) { + dragitem.dd.detachAll('drag:start'); + } + }, this); + this.doc.drop_zones().each(function(dropzone) { + var relativexy = dropzone.getData('xy'); + dropzone.setXY(this.convert_to_window_xy(relativexy)); + var inputcss = 'input#' + dropzone.getData('inputid'); + var input = this.doc.top_node().one(inputcss); + var choice = input.get('value'); + if (choice !== "") { + var dragitem = this.get_unplaced_choice_for_drop(choice, dropzone); + if (dragitem !== null) { + dragitem.setXY(dropzone.getXY()); + dragitem.addClass('placed'); + if (dragitem.dd !== undefined) { + dragitem.dd.once('drag:start', function (e, input) { + input.set('value', ''); + e.target.get('node').removeClass('placed'); + },this, input); + } + } + } + }, this); + this.doc.drag_items().each(function(dragitem) { + if (!dragitem.hasClass('placed') && !dragitem.hasClass('yui3-dd-dragging')) { + var dragitemhome = this.doc.drag_item_home(dragitem.getData('dragitemno')); + dragitem.setXY(dragitemhome.getXY()); + } + }, this); + }, + get_choices_for_drop : function(choice, drop) { + var group = drop.getData('group'); + return this.doc.top_node().all( + 'div.dragitemgroup' + group + ' .choice' + choice + '.drag'); + }, + get_unplaced_choice_for_drop : function(choice, drop) { + var dragitems = this.get_choices_for_drop(choice, drop); + var dragitem = null; + dragitems.some(function (d) { + if (!d.hasClass('placed') && !d.hasClass('yui3-dd-dragging')) { + dragitem = d; + return true; + } else { + return false; + } + }); + return dragitem; + }, + init_drops : function () { + var dropareas = this.doc.top_node().one('div.dropzones'); + var groupnodes = {}; + for (var groupno = 1; groupno <= 8; groupno++) { + var groupnode = Y.Node.create('
    '); + dropareas.append(groupnode); + groupnodes[groupno] = groupnode; + } + var drop_hit_handler = function(e) { + var drag = e.drag.get('node'); + var drop = e.drop.get('node'); + if (Number(drop.getData('group')) === drag.getData('group')){ + this.place_drag_in_drop(drag, drop); + } + }; + for (var dropno in this.get('drops')) { + var drop = this.get('drops')[dropno]; + var nodeclass = 'dropzone group' + drop.group + ' place' + dropno; + var title = drop.text.replace('"', '\"'); + var dropnodehtml = '
     
    '; + var dropnode = Y.Node.create(dropnodehtml); + groupnodes[drop.group].append(dropnode); + dropnode.setStyles({'opacity': 0.5}); + dropnode.setData('xy', drop.xy); + dropnode.setData('place', dropno); + dropnode.setData('inputid', drop.fieldname.replace(':', '_')); + dropnode.setData('group', drop.group); + var dropdd = new Y.DD.Drop({ + node: dropnode, groups : [drop.group]}); + dropdd.on('drop:hit', drop_hit_handler, this); + } + } +}, {NAME : DDIMAGEORTEXTQUESTIONNAME, ATTRS : {}}); + +Y.Event.define('dragchange', { + // Webkit and IE repeat keydown when you hold down arrow keys. + // Opera links keypress to page scroll; others keydown. + // Firefox prevents page scroll via preventDefault() on either + // keydown or keypress. + _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', + + _keys: { + '32': 'next', // Space + '37': 'previous', // Left arrow + '38': 'previous', // Up arrow + '39': 'next', // Right arrow + '40': 'next', // Down arrow + '27': 'remove' // Escape + }, + + _keyHandler: function (e, notifier) { + if (this._keys[e.keyCode]) { + e.direction = this._keys[e.keyCode]; + notifier.fire(e); + } + }, + + on: function (node, sub, notifier) { + sub._detacher = node.on(this._event, this._keyHandler, + this, notifier); + } +}); + +M.qtype_ddimageortext.init_question = function(config) { + return new DDIMAGEORTEXT_QUESTION(config); +}; + +}, '@VERSION@', {"requires": ["node", "dd", "dd-drop", "dd-constrain"]}); diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js new file mode 100644 index 00000000000..ec97e7b75aa --- /dev/null +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js @@ -0,0 +1,354 @@ +YUI.add('moodle-qtype_ddimageortext-form', function (Y, NAME) { + +// This file is part of Moodle - http://moodle.org/ +// +// 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 . + +/** + * This is the question editing form code. + */ +var DDIMAGEORTEXTFORMNAME = 'moodle-qtype_ddimageortext-form'; +var DDIMAGEORTEXT_FORM = function() { + DDIMAGEORTEXT_FORM.superclass.constructor.apply(this, arguments); +}; + +Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { + fp : null, + + initializer : function() { + this.fp = this.file_pickers(); + var tn = Y.one(this.get('topnode')); + tn.one('div.fcontainer').append('
    ' + + '
    '); + this.doc = this.doc_structure(this); + this.draw_dd_area(); + }, + + draw_dd_area : function() { + var bgimageurl = this.fp.file('bgimage').href; + this.stop_selector_events(); + this.set_options_for_drag_item_selectors(); + if (bgimageurl !== null) { + this.doc.load_bg_img(bgimageurl); + this.load_drag_homes(); + + var drop = new Y.DD.Drop({ + node: this.doc.bg_img() + }); + //Listen for a drop:hit on the background image + drop.on('drop:hit', function(e) { + e.drag.get('node').setData('gooddrop', true); + }); + + this.afterimageloaddone = false; + this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); + this.doc.drag_item_homes() + .on('load', this.constrain_image_size, this, 'dragimage'); + this.doc.bg_img().after('load', this.poll_for_image_load, this, + true, 0, this.after_all_images_loaded); + this.doc.drag_item_homes() .after('load', this.poll_for_image_load, this, + true, 0, this.after_all_images_loaded); + } else { + this.setup_form_events(); + } + this.update_visibility_of_file_pickers(); + }, + + after_all_images_loaded : function () { + this.update_padding_sizes_all(); + this.update_drag_instances(); + this.reposition_drags_for_form(); + this.set_options_for_drag_item_selectors(); + this.setup_form_events(); + Y.later(500, this, this.reposition_drags_for_form, [], true); + }, + + constrain_image_size : function (e, imagetype) { + var maxsize = this.get('maxsizes')[imagetype]; + var reduceby = Math.max(e.target.get('width') / maxsize.width, + e.target.get('height') / maxsize.height); + if (reduceby > 1) { + e.target.set('width', Math.floor(e.target.get('width') / reduceby)); + } + e.target.addClass('constrained'); + e.target.detach('load', this.constrain_image_size); + }, + + load_drag_homes : function () { + // Set up drag items homes. + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + this.load_drag_home(i); + } + }, + + load_drag_home : function (dragitemno) { + var url = null; + if ('image' === this.form.get_form_value('drags', [dragitemno, 'dragitemtype'])) { + url = this.fp.file(this.form.to_name_with_index('dragitem', [dragitemno])).href; + } + this.doc.add_or_update_drag_item_home(dragitemno, url, + this.form.get_form_value('draglabel', [dragitemno]), + this.form.get_form_value('drags', [dragitemno, 'draggroup'])); + }, + + update_drag_instances : function () { + // Set up drop zones. + for (var i = 0; i < this.form.get_form_value('nodropzone', []); i++) { + var dragitemno = this.form.get_form_value('drops', [i, 'choice']); + if (dragitemno !== '0' && (this.doc.drag_item(i) === null)) { + var drag = this.doc.clone_new_drag_item(i, dragitemno - 1); + if (drag !== null) { + this.doc.draggable_for_form(drag); + } + } + } + }, + set_options_for_drag_item_selectors : function () { + var dragitemsoptions = {0: ''}; + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + var label = this.form.get_form_value('draglabel', [i]); + var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); + if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype']) + && file.name !== null) { + dragitemsoptions[i + 1] = (i + 1) + '. ' + label + ' (' + file.name + ')'; + } else if (label !== '') { + dragitemsoptions[i + 1] = (i + 1) + '. ' + label; + } + } + for (i = 0; i < this.form.get_form_value('nodropzone', []); i++) { + var selector = Y.one('#id_drops_' + i + '_choice'); + var selectedvalue = selector.get('value'); + selector.all('option').remove(true); + for (var value in dragitemsoptions) { + value = + value; + var option = ''; + selector.append(option); + var optionnode = selector.one('option[value="' + value + '"]'); + if (value === + selectedvalue) { + optionnode.set('selected', true); + } else { + if (value !== 0) { // No item option is always selectable. + var cbel = Y.one('#id_drags_' + (value - 1) + '_infinite'); + if (cbel && !cbel.get('checked')) { + Y.all('fieldset#id_dropzoneheader select').some(function (selector) { + if (Number(selector.get('value')) === value) { + optionnode.set('disabled', true); + return true; // Stop looping. + } + return false; + }, this); + } + } + } + } + } + }, + + stop_selector_events : function () { + Y.all('fieldset#id_dropzoneheader select').detachAll(); + }, + + setup_form_events : function () { + // Events triggered by changes to form data. + + // X and y coordinates. + Y.all('fieldset#id_dropzoneheader input').on('blur', function (e) { + var name = e.target.getAttribute('name'); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), + this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; + var constrainedxy = this.constrain_xy(draginstanceno, fromform); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], constrainedxy[0]); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); + }, this); + + // Change in selected item. + Y.all('fieldset#id_dropzoneheader select').on('change', function (e) { + var name = e.target.getAttribute('name'); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + var old = this.doc.drag_item(draginstanceno); + if (old !== null) { + old.remove(true); + } + this.draw_dd_area(); + }, this); + + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + // Change to group selector. + Y.all('#fgroup_id_drags_' + i + ' select.draggroup').on( + 'change', function () { + this.doc.drag_items().remove(true); + this.draw_dd_area(); + }, this); + Y.all('#fgroup_id_drags_' + i + ' select.dragitemtype').on( + 'change', function () { + this.doc.drag_items().remove(true); + this.draw_dd_area(); + }, this); + Y.all('fieldset#draggableitemheader_' + i + ' input[type="text"]') + .on('blur', this.set_options_for_drag_item_selectors, this); + // Change to infinite checkbox. + Y.all('fieldset#draggableitemheader_' + i + ' input[type="checkbox"]') + .on('change', this.set_options_for_drag_item_selectors, this); + } + // Event on file picker new file selection. + Y.after(function (e) { + var name = this.fp.name(e.id); + if (name !== 'bgimage') { + this.doc.drag_items().remove(true); + } + this.draw_dd_area(); + }, M.form_filepicker, 'callback', this); + }, + + update_visibility_of_file_pickers : function() { + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype'])) { + Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') + .setStyle('display', 'block'); + } else { + Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') + .setStyle('display', 'none'); + } + } + }, + + reposition_drags_for_form : function() { + this.doc.drag_items().each(function (drag) { + var draginstanceno = drag.getData('draginstanceno'); + this.reposition_drag_for_form(draginstanceno); + }, this); + }, + + reposition_drag_for_form : function (draginstanceno) { + var drag = this.doc.drag_item(draginstanceno); + if (null !== drag && !drag.hasClass('yui3-dd-dragging')) { + var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), + this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; + if (fromform[0] === '' && fromform[1] === '') { + var dragitemno = drag.getData('dragitemno'); + drag.setXY(this.doc.drag_item_home(dragitemno).getXY()); + } else { + drag.setXY(this.convert_to_window_xy(fromform)); + } + } + }, + set_drag_xy : function (draginstanceno, xy) { + xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.round(xy[0])); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.round(xy[1])); + }, + reset_drag_xy : function (draginstanceno) { + this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); + }, + + //make sure xy value is not out of bounds of bg image + constrain_xy : function (draginstanceno, bgimgxy) { + var drag = this.doc.drag_item(draginstanceno); + var xleftconstrained = + Math.min(bgimgxy[0], this.doc.bg_img().get('width') - drag.get('offsetWidth')); + var ytopconstrained = + Math.min(bgimgxy[1], this.doc.bg_img().get('height') - drag.get('offsetHeight')); + xleftconstrained = Math.max(xleftconstrained, 0); + ytopconstrained = Math.max(ytopconstrained, 0); + return [xleftconstrained, ytopconstrained]; + }, + convert_to_bg_img_xy : function (windowxy) { + return [Number(windowxy[0]) - this.doc.bg_img().getX() - 1, + Number(windowxy[1]) - this.doc.bg_img().getY() - 1]; + }, + + /** + * Low level operations on form. + */ + form : { + to_name_with_index : function(name, indexes) { + var indexstring = name; + for (var i = 0; i < indexes.length; i++) { + indexstring = indexstring + '[' + indexes[i] + ']'; + } + return indexstring; + }, + get_el : function (name, indexes) { + var form = document.getElementById('mform1'); + return form.elements[this.to_name_with_index(name, indexes)]; + }, + get_form_value : function(name, indexes) { + var el = this.get_el(name, indexes); + if (el.type === 'checkbox') { + return el.checked; + } else { + return el.value; + } + }, + set_form_value : function(name, indexes, value) { + var el = this.get_el(name, indexes); + if (el.type === 'checkbox') { + el.checked = value; + } else { + el.value = value; + } + }, + from_name_with_index : function(name) { + var toreturn = {}; + toreturn.indexes = []; + var bracket = name.indexOf('['); + toreturn.name = name.substring(0, bracket); + while (bracket !== -1) { + var end = name.indexOf(']', bracket + 1); + toreturn.indexes.push(name.substring(bracket + 1, end)); + bracket = name.indexOf('[', end + 1); + } + return toreturn; + } + }, + + file_pickers : function () { + var draftitemidstoname; + var nametoparentnode; + if (draftitemidstoname === undefined) { + draftitemidstoname = {}; + nametoparentnode = {}; + var filepickers = Y.all('form.mform input.filepickerhidden'); + filepickers.each(function(filepicker) { + draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); + nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); + }, this); + } + var toreturn = { + file : function (name) { + var parentnode = nametoparentnode[name]; + var fileanchor = parentnode.one('div.filepicker-filelist a'); + if (fileanchor) { + return {href : fileanchor.get('href'), name : fileanchor.get('innerHTML')}; + } else { + return {href : null, name : null}; + } + }, + name : function (draftitemid) { + return draftitemidstoname[draftitemid]; + } + }; + return toreturn; + } +}, {NAME : DDIMAGEORTEXTFORMNAME, ATTRS : {maxsizes:{value:null}}}); +M.qtype_ddimageortext = M.qtype_ddimageortext || {}; +M.qtype_ddimageortext.init_form = function(config) { + return new DDIMAGEORTEXT_FORM(config); +}; + + + +}, '@VERSION@', {"requires": ["moodle-qtype_ddimageortext-dd", "form_filepicker"]}); diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js new file mode 100644 index 00000000000..eba956ab617 --- /dev/null +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js @@ -0,0 +1,2 @@ +YUI.add("moodle-qtype_ddimageortext-form",function(e,t){var n="moodle-qtype_ddimageortext-form",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,M.qtype_ddimageortext.dd_base_class,{fp:null,initializer:function(){this.fp=this.file_pickers();var t=e.one(this.get("topnode"));t.one("div.fcontainer").append('
    '),this.doc=this.doc_structure(this),this.draw_dd_area()},draw_dd_area:function(){var t=this.fp.file("bgimage").href;this.stop_selector_events(),this.set_options_for_drag_item_selectors();if(t!==null){this.doc.load_bg_img(t),this.load_drag_homes();var n=new e.DD.Drop({node:this.doc.bg_img()});n.on("drop:hit",function(e){e.drag.get("node").setData("gooddrop",!0)}),this.afterimageloaddone=!1,this.doc.bg_img().on("load",this.constrain_image_size,this,"bgimage"),this.doc.drag_item_homes().on("load",this.constrain_image_size,this,"dragimage"),this.doc.bg_img().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded),this.doc.drag_item_homes().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded)}else this.setup_form_events();this.update_visibility_of_file_pickers()},after_all_images_loaded:function(){this.update_padding_sizes_all(),this.update_drag_instances(),this.reposition_drags_for_form(),this.set_options_for_drag_item_selectors(),this.setup_form_events(),e.later(500,this,this.reposition_drags_for_form,[],!0)},constrain_image_size:function(e,t){var n=this.get("maxsizes")[t],r=Math.max(e.target.get("width")/n.width,e.target.get("height")/n.height);r>1&&e.target.set("width",Math.floor(e.target.get("width")/r)),e.target.addClass("constrained"),e.target.detach("load",this.constrain_image_size)},load_drag_homes:function(){for(var e=0;e'+t[u]+"";s.append(a);var f=s.one('option[value="'+u+'"]');if(u===+o)f.set("selected",!0);else if(u!==0){var l=e.one("#id_drags_"+(u-1)+"_infinite");l&&!l.get("checked")&&e.all("fieldset#id_dropzoneheader select").some(function(e){return Number(e.get("value"))===u?(f.set("disabled",!0),!0):!1},this)}}}},stop_selector_events:function(){e.all("fieldset#id_dropzoneheader select").detachAll()},setup_form_events:function(){e.all("fieldset#id_dropzoneheader input").on("blur",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=[this.form.get_form_value("drops",[n,"xleft"]),this.form.get_form_value("drops",[n,"ytop"])],i=this.constrain_xy(n,r);this.form.set_form_value("drops",[n,"xleft"],i[0]),this.form.set_form_value("drops",[n,"ytop"],i[1])},this),e.all("fieldset#id_dropzoneheader select").on("change",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=this.doc.drag_item(n);r!==null&&r.remove(!0),this.draw_dd_area()},this);for(var t=0;t. + +/** + * This is the question editing form code. + */ +var DDIMAGEORTEXTFORMNAME = 'moodle-qtype_ddimageortext-form'; +var DDIMAGEORTEXT_FORM = function() { + DDIMAGEORTEXT_FORM.superclass.constructor.apply(this, arguments); +}; + +Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { + fp : null, + + initializer : function() { + this.fp = this.file_pickers(); + var tn = Y.one(this.get('topnode')); + tn.one('div.fcontainer').append('
    ' + + '
    '); + this.doc = this.doc_structure(this); + this.draw_dd_area(); + }, + + draw_dd_area : function() { + var bgimageurl = this.fp.file('bgimage').href; + this.stop_selector_events(); + this.set_options_for_drag_item_selectors(); + if (bgimageurl !== null) { + this.doc.load_bg_img(bgimageurl); + this.load_drag_homes(); + + var drop = new Y.DD.Drop({ + node: this.doc.bg_img() + }); + //Listen for a drop:hit on the background image + drop.on('drop:hit', function(e) { + e.drag.get('node').setData('gooddrop', true); + }); + + this.afterimageloaddone = false; + this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); + this.doc.drag_item_homes() + .on('load', this.constrain_image_size, this, 'dragimage'); + this.doc.bg_img().after('load', this.poll_for_image_load, this, + true, 0, this.after_all_images_loaded); + this.doc.drag_item_homes() .after('load', this.poll_for_image_load, this, + true, 0, this.after_all_images_loaded); + } else { + this.setup_form_events(); + } + this.update_visibility_of_file_pickers(); + }, + + after_all_images_loaded : function () { + this.update_padding_sizes_all(); + this.update_drag_instances(); + this.reposition_drags_for_form(); + this.set_options_for_drag_item_selectors(); + this.setup_form_events(); + Y.later(500, this, this.reposition_drags_for_form, [], true); + }, + + constrain_image_size : function (e, imagetype) { + var maxsize = this.get('maxsizes')[imagetype]; + var reduceby = Math.max(e.target.get('width') / maxsize.width, + e.target.get('height') / maxsize.height); + if (reduceby > 1) { + e.target.set('width', Math.floor(e.target.get('width') / reduceby)); + } + e.target.addClass('constrained'); + e.target.detach('load', this.constrain_image_size); + }, + + load_drag_homes : function () { + // Set up drag items homes. + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + this.load_drag_home(i); + } + }, + + load_drag_home : function (dragitemno) { + var url = null; + if ('image' === this.form.get_form_value('drags', [dragitemno, 'dragitemtype'])) { + url = this.fp.file(this.form.to_name_with_index('dragitem', [dragitemno])).href; + } + this.doc.add_or_update_drag_item_home(dragitemno, url, + this.form.get_form_value('draglabel', [dragitemno]), + this.form.get_form_value('drags', [dragitemno, 'draggroup'])); + }, + + update_drag_instances : function () { + // Set up drop zones. + for (var i = 0; i < this.form.get_form_value('nodropzone', []); i++) { + var dragitemno = this.form.get_form_value('drops', [i, 'choice']); + if (dragitemno !== '0' && (this.doc.drag_item(i) === null)) { + var drag = this.doc.clone_new_drag_item(i, dragitemno - 1); + if (drag !== null) { + this.doc.draggable_for_form(drag); + } + } + } + }, + set_options_for_drag_item_selectors : function () { + var dragitemsoptions = {0: ''}; + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + var label = this.form.get_form_value('draglabel', [i]); + var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); + if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype']) + && file.name !== null) { + dragitemsoptions[i + 1] = (i + 1) + '. ' + label + ' (' + file.name + ')'; + } else if (label !== '') { + dragitemsoptions[i + 1] = (i + 1) + '. ' + label; + } + } + for (i = 0; i < this.form.get_form_value('nodropzone', []); i++) { + var selector = Y.one('#id_drops_' + i + '_choice'); + var selectedvalue = selector.get('value'); + selector.all('option').remove(true); + for (var value in dragitemsoptions) { + value = + value; + var option = ''; + selector.append(option); + var optionnode = selector.one('option[value="' + value + '"]'); + if (value === + selectedvalue) { + optionnode.set('selected', true); + } else { + if (value !== 0) { // No item option is always selectable. + var cbel = Y.one('#id_drags_' + (value - 1) + '_infinite'); + if (cbel && !cbel.get('checked')) { + Y.all('fieldset#id_dropzoneheader select').some(function (selector) { + if (Number(selector.get('value')) === value) { + optionnode.set('disabled', true); + return true; // Stop looping. + } + return false; + }, this); + } + } + } + } + } + }, + + stop_selector_events : function () { + Y.all('fieldset#id_dropzoneheader select').detachAll(); + }, + + setup_form_events : function () { + // Events triggered by changes to form data. + + // X and y coordinates. + Y.all('fieldset#id_dropzoneheader input').on('blur', function (e) { + var name = e.target.getAttribute('name'); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), + this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; + var constrainedxy = this.constrain_xy(draginstanceno, fromform); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], constrainedxy[0]); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); + }, this); + + // Change in selected item. + Y.all('fieldset#id_dropzoneheader select').on('change', function (e) { + var name = e.target.getAttribute('name'); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + var old = this.doc.drag_item(draginstanceno); + if (old !== null) { + old.remove(true); + } + this.draw_dd_area(); + }, this); + + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + // Change to group selector. + Y.all('#fgroup_id_drags_' + i + ' select.draggroup').on( + 'change', function () { + this.doc.drag_items().remove(true); + this.draw_dd_area(); + }, this); + Y.all('#fgroup_id_drags_' + i + ' select.dragitemtype').on( + 'change', function () { + this.doc.drag_items().remove(true); + this.draw_dd_area(); + }, this); + Y.all('fieldset#draggableitemheader_' + i + ' input[type="text"]') + .on('blur', this.set_options_for_drag_item_selectors, this); + // Change to infinite checkbox. + Y.all('fieldset#draggableitemheader_' + i + ' input[type="checkbox"]') + .on('change', this.set_options_for_drag_item_selectors, this); + } + // Event on file picker new file selection. + Y.after(function (e) { + var name = this.fp.name(e.id); + if (name !== 'bgimage') { + this.doc.drag_items().remove(true); + } + this.draw_dd_area(); + }, M.form_filepicker, 'callback', this); + }, + + update_visibility_of_file_pickers : function() { + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype'])) { + Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') + .setStyle('display', 'block'); + } else { + Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') + .setStyle('display', 'none'); + } + } + }, + + reposition_drags_for_form : function() { + this.doc.drag_items().each(function (drag) { + var draginstanceno = drag.getData('draginstanceno'); + this.reposition_drag_for_form(draginstanceno); + }, this); + }, + + reposition_drag_for_form : function (draginstanceno) { + var drag = this.doc.drag_item(draginstanceno); + if (null !== drag && !drag.hasClass('yui3-dd-dragging')) { + var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), + this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; + if (fromform[0] === '' && fromform[1] === '') { + var dragitemno = drag.getData('dragitemno'); + drag.setXY(this.doc.drag_item_home(dragitemno).getXY()); + } else { + drag.setXY(this.convert_to_window_xy(fromform)); + } + } + }, + set_drag_xy : function (draginstanceno, xy) { + xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.round(xy[0])); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.round(xy[1])); + }, + reset_drag_xy : function (draginstanceno) { + this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); + }, + + //make sure xy value is not out of bounds of bg image + constrain_xy : function (draginstanceno, bgimgxy) { + var drag = this.doc.drag_item(draginstanceno); + var xleftconstrained = + Math.min(bgimgxy[0], this.doc.bg_img().get('width') - drag.get('offsetWidth')); + var ytopconstrained = + Math.min(bgimgxy[1], this.doc.bg_img().get('height') - drag.get('offsetHeight')); + xleftconstrained = Math.max(xleftconstrained, 0); + ytopconstrained = Math.max(ytopconstrained, 0); + return [xleftconstrained, ytopconstrained]; + }, + convert_to_bg_img_xy : function (windowxy) { + return [Number(windowxy[0]) - this.doc.bg_img().getX() - 1, + Number(windowxy[1]) - this.doc.bg_img().getY() - 1]; + }, + + /** + * Low level operations on form. + */ + form : { + to_name_with_index : function(name, indexes) { + var indexstring = name; + for (var i = 0; i < indexes.length; i++) { + indexstring = indexstring + '[' + indexes[i] + ']'; + } + return indexstring; + }, + get_el : function (name, indexes) { + var form = document.getElementById('mform1'); + return form.elements[this.to_name_with_index(name, indexes)]; + }, + get_form_value : function(name, indexes) { + var el = this.get_el(name, indexes); + if (el.type === 'checkbox') { + return el.checked; + } else { + return el.value; + } + }, + set_form_value : function(name, indexes, value) { + var el = this.get_el(name, indexes); + if (el.type === 'checkbox') { + el.checked = value; + } else { + el.value = value; + } + }, + from_name_with_index : function(name) { + var toreturn = {}; + toreturn.indexes = []; + var bracket = name.indexOf('['); + toreturn.name = name.substring(0, bracket); + while (bracket !== -1) { + var end = name.indexOf(']', bracket + 1); + toreturn.indexes.push(name.substring(bracket + 1, end)); + bracket = name.indexOf('[', end + 1); + } + return toreturn; + } + }, + + file_pickers : function () { + var draftitemidstoname; + var nametoparentnode; + if (draftitemidstoname === undefined) { + draftitemidstoname = {}; + nametoparentnode = {}; + var filepickers = Y.all('form.mform input.filepickerhidden'); + filepickers.each(function(filepicker) { + draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); + nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); + }, this); + } + var toreturn = { + file : function (name) { + var parentnode = nametoparentnode[name]; + var fileanchor = parentnode.one('div.filepicker-filelist a'); + if (fileanchor) { + return {href : fileanchor.get('href'), name : fileanchor.get('innerHTML')}; + } else { + return {href : null, name : null}; + } + }, + name : function (draftitemid) { + return draftitemidstoname[draftitemid]; + } + }; + return toreturn; + } +}, {NAME : DDIMAGEORTEXTFORMNAME, ATTRS : {maxsizes:{value:null}}}); +M.qtype_ddimageortext = M.qtype_ddimageortext || {}; +M.qtype_ddimageortext.init_form = function(config) { + return new DDIMAGEORTEXT_FORM(config); +}; + + + +}, '@VERSION@', {"requires": ["moodle-qtype_ddimageortext-dd", "form_filepicker"]}); diff --git a/question/type/ddimageortext/yui/dd/dd.js b/question/type/ddimageortext/yui/dd/dd.js deleted file mode 100644 index b6b88a0d770..00000000000 --- a/question/type/ddimageortext/yui/dd/dd.js +++ /dev/null @@ -1,464 +0,0 @@ -YUI.add('moodle-qtype_ddimageortext-dd', function(Y) { - var DDIMAGEORTEXTDDNAME = 'ddimageortext_dd'; - var DDIMAGEORTEXT_DD = function() { - DDIMAGEORTEXT_DD.superclass.constructor.apply(this, arguments); - }; - /** - * This is the base class for the question rendering and question editing form code. - */ - Y.extend(DDIMAGEORTEXT_DD, Y.Base, { - doc : null, - polltimer : null, - afterimageloaddone : false, - poll_for_image_load : function (e, waitforimageconstrain, pause, doafterwords) { - if (this.afterimageloaddone) { - return; - } - var bgdone = this.doc.bg_img().get('complete'); - if (waitforimageconstrain) { - bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); - } - var alldragsloaded = !this.doc.drag_item_homes().some(function(dragitemhome){ - //in 'some' loop returning true breaks the loop and is passed as return value from - //'some' else returns false. Can be though of as equivalent to ||. - if (dragitemhome.get('tagName') !== 'IMG'){ - return false; - } - var done = (dragitemhome.get('complete')); - if (waitforimageconstrain) { - done = done && dragitemhome.hasClass('constrained'); - } - return !done; - }); - if (bgdone && alldragsloaded) { - if (this.polltimer !== null) { - this.polltimer.cancel(); - this.polltimer = null; - } - this.doc.drag_item_homes().detach('load', this.poll_for_image_load); - this.doc.bg_img().detach('load', this.poll_for_image_load); - if (pause !== 0) { - Y.later(pause, this, doafterwords); - } else { - doafterwords.call(this); - } - this.afterimageloaddone = true; - } else if (this.polltimer === null) { - var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; - this.polltimer = - Y.later(1000, this, this.poll_for_image_load, pollarguments, true); - } - }, - /** - * Object to encapsulate operations on dd area. - */ - doc_structure : function (mainobj) { - var topnode = Y.one(this.get('topnode')); - var dragitemsarea = topnode.one('div.dragitems'); - var dropbgarea = topnode.one('div.droparea'); - return { - top_node : function() { - return topnode; - }, - drag_items : function() { - return dragitemsarea.all('.drag'); - }, - drop_zones : function() { - return topnode.all('div.dropzones div.dropzone'); - }, - drop_zone_group : function(groupno) { - return topnode.all('div.dropzones div.group' + groupno); - }, - drag_items_cloned_from : function(dragitemno) { - return dragitemsarea.all('.dragitems' + dragitemno); - }, - drag_item : function(draginstanceno) { - return dragitemsarea.one('.draginstance' + draginstanceno); - }, - drag_items_in_group : function(groupno) { - return dragitemsarea.all('.drag.group' + groupno); - }, - drag_item_homes : function() { - return dragitemsarea.all('.draghome'); - }, - bg_img : function() { - return topnode.one('.dropbackground'); - }, - load_bg_img : function (url) { - dropbgarea.setContent(''); - this.bg_img().on('load', this.on_image_load, this, 'bg_image'); - }, - add_or_update_drag_item_home : function (dragitemno, url, alt, group) { - var oldhome = this.drag_item_home(dragitemno); - var classes = 'draghome dragitemhomes' + dragitemno + ' group' + group; - var imghtml = '' + alt + ''; - var divhtml = '
    ' + alt + '
    '; - if (oldhome === null) { - if (url) { - dragitemsarea.append(imghtml); - } else if (alt !== '') { - dragitemsarea.append(divhtml); - } - } else { - if (url) { - dragitemsarea.insert(imghtml, oldhome); - } else if (alt !== '') { - dragitemsarea.insert(divhtml, oldhome); - } - oldhome.remove(true); - } - var newlycreated = dragitemsarea.one('.dragitemhomes' + dragitemno); - if (newlycreated !== null) { - newlycreated.setData('groupno', group); - newlycreated.setData('dragitemno', dragitemno); - } - }, - drag_item_home : function (dragitemno) { - return dragitemsarea.one('.dragitemhomes' + dragitemno); - }, - get_classname_numeric_suffix : function(node, prefix) { - var classes = node.getAttribute('class'); - if (classes !== '') { - var classesarr = classes.split(' '); - for (var index = 0; index < classesarr.length; index++) { - var patt1 = new RegExp('^' + prefix + '([0-9])+$'); - if (patt1.test(classesarr[index])) { - var patt2 = new RegExp('([0-9])+$'); - var match = patt2.exec(classesarr[index]); - return + match[0]; - } - } - } - throw 'Prefix "' + prefix + '" not found in class names.'; - }, - clone_new_drag_item : function (draginstanceno, dragitemno) { - var draghome = this.drag_item_home(dragitemno); - if (draghome === null) { - return null; - } - var drag = draghome.cloneNode(true); - drag.removeClass('dragitemhomes' + dragitemno); - drag.addClass('dragitems' + dragitemno); - drag.addClass('draginstance' + draginstanceno); - drag.removeClass('draghome'); - drag.addClass('drag'); - drag.setStyles({'visibility': 'visible', 'position' : 'absolute'}); - drag.setData('draginstanceno', draginstanceno); - drag.setData('dragitemno', dragitemno); - draghome.get('parentNode').appendChild(drag); - return drag; - }, - draggable_for_question : function (drag, group, choice) { - new Y.DD.Drag({ - node: drag, - dragMode: 'point', - groups: [group] - }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); - - drag.setData('group', group); - drag.setData('choice', choice); - - }, - draggable_for_form : function (drag) { - var dd = new Y.DD.Drag({ - node: drag, - dragMode: 'point' - }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); - dd.on('drag:end', function(e) { - var dragnode = e.target.get('node'); - var draginstanceno = dragnode.getData('draginstanceno'); - var gooddrop = dragnode.getData('gooddrop'); - - if (!gooddrop) { - mainobj.reset_drag_xy(draginstanceno); - } else { - mainobj.set_drag_xy(draginstanceno, [e.pageX, e.pageY]); - } - }, this); - dd.on('drag:start', function(e) { - var drag = e.target; - drag.get('node').setData('gooddrop', false); - }, this); - - } - - }; - }, - - update_padding_sizes_all : function () { - for (var groupno = 1; groupno <= 8; groupno++) { - this.update_padding_size_for_group(groupno); - } - }, - update_padding_size_for_group : function (groupno) { - var groupitems = this.doc.top_node().all('.draghome.group' + groupno); - if (groupitems.size() !== 0) { - var maxwidth = 0; - var maxheight = 0; - groupitems.each(function(item){ - maxwidth = Math.max(maxwidth, item.get('clientWidth')); - maxheight = Math.max(maxheight, item.get('clientHeight')); - }, this); - groupitems.each(function(item) { - var margintopbottom = Math.round((10 + maxheight - item.get('clientHeight')) / 2); - var marginleftright = Math.round((10 + maxwidth - item.get('clientWidth')) / 2); - item.setStyle('padding', margintopbottom + 'px ' + marginleftright + 'px ' + - margintopbottom + 'px ' + marginleftright + 'px'); - }, this); - this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, - 'height': maxheight + 10}); - } - }, - convert_to_window_xy : function (bgimgxy) { - return [Number(bgimgxy[0]) + this.doc.bg_img().getX() + 1, - Number(bgimgxy[1]) + this.doc.bg_img().getY() + 1]; - } - }, { - NAME : DDIMAGEORTEXTDDNAME, - ATTRS : { - drops : {value : null}, - readonly : {value : false}, - topnode : {value : null} - } - }); - M.qtype_ddimageortext = M.qtype_ddimageortext || {}; - M.qtype_ddimageortext.dd_base_class = DDIMAGEORTEXT_DD; - - var DDIMAGEORTEXTQUESTIONNAME = 'ddimageortext_question'; - var DDIMAGEORTEXT_QUESTION = function() { - DDIMAGEORTEXT_QUESTION.superclass.constructor.apply(this, arguments); - }; - /** - * This is the code for question rendering. - */ - Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { - initializer : function() { - this.doc = this.doc_structure(this); - this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); - this.doc.bg_img().after('load', this.poll_for_image_load, this, - false, 0, this.create_all_drag_and_drops); - this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, - false, 0, this.create_all_drag_and_drops); - Y.later(500, this, this.reposition_drags_for_question, [], true); - }, - create_all_drag_and_drops : function () { - this.init_drops(); - this.update_padding_sizes_all(); - var i = 0; - this.doc.drag_item_homes().each(function(dragitemhome){ - var dragitemno = Number(this.doc.get_classname_numeric_suffix(dragitemhome, 'dragitemhomes')); - var choice = + this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); - var group = + this.doc.get_classname_numeric_suffix(dragitemhome, 'group'); - var groupsize = this.doc.drop_zone_group(group).size(); - var dragnode = this.doc.clone_new_drag_item(i, dragitemno); - i++; - if (!this.get('readonly')) { - this.doc.draggable_for_question(dragnode, group, choice); - } - if (dragnode.hasClass('infinite')) { - var dragstocreate = groupsize - 1; - while (dragstocreate > 0) { - dragnode = this.doc.clone_new_drag_item(i, dragitemno); - i++; - if (!this.get('readonly')) { - this.doc.draggable_for_question(dragnode, group, choice); - } - dragstocreate--; - } - } - }, this); - this.reposition_drags_for_question(); - if (!this.get('readonly')) { - this.doc.drop_zones().set('tabIndex', 0); - this.doc.drop_zones().each( - function(v){ - v.on('dragchange', this.drop_zone_key_press, this); - }, this); - } - }, - drop_zone_key_press : function (e) { - switch (e.direction) { - case 'next' : - this.place_next_drag_in(e.target); - break; - case 'previous' : - this.place_previous_drag_in(e.target); - break; - case 'remove' : - this.remove_drag_from_drop(e.target); - break; - } - e.preventDefault(); - this.reposition_drags_for_question(); - }, - place_next_drag_in : function (drop) { - this.search_for_unplaced_drop_choice(drop, 1); - }, - place_previous_drag_in : function (drop) { - this.search_for_unplaced_drop_choice(drop, -1); - }, - search_for_unplaced_drop_choice : function (drop, direction) { - var next; - var current = this.current_drag_in_drop(drop); - if ('' === current) { - if (direction === 1) { - next = 1; - } else { - next = 1; - var groupno = drop.getData('group'); - this.doc.drag_items_in_group(groupno).each(function(drag) { - next = Math.max(next, drag.getData('choice')); - }, this); - } - } else { - next = + current + direction; - } - var drag; - do { - if (this.get_choices_for_drop(next, drop).size() === 0){ - this.remove_drag_from_drop(drop); - return; - } else { - drag = this.get_unplaced_choice_for_drop(next, drop); - } - next = next + direction; - } while (drag === null); - this.place_drag_in_drop(drag, drop); - }, - current_drag_in_drop : function (drop) { - var inputid = drop.getData('inputid'); - var inputnode = Y.one('input#' + inputid); - return inputnode.get('value'); - }, - remove_drag_from_drop : function (drop) { - this.place_drag_in_drop(null, drop); - }, - place_drag_in_drop : function (drag, drop) { - var inputid = drop.getData('inputid'); - var inputnode = Y.one('input#' + inputid); - if (drag !== null) { - inputnode.set('value', drag.getData('choice')); - } else { - inputnode.set('value', ''); - } - }, - reposition_drags_for_question : function() { - this.doc.drag_items().removeClass('placed'); - this.doc.drag_items().each (function (dragitem) { - if (dragitem.dd !== undefined) { - dragitem.dd.detachAll('drag:start'); - } - }, this); - this.doc.drop_zones().each(function(dropzone) { - var relativexy = dropzone.getData('xy'); - dropzone.setXY(this.convert_to_window_xy(relativexy)); - var inputcss = 'input#' + dropzone.getData('inputid'); - var input = this.doc.top_node().one(inputcss); - var choice = input.get('value'); - if (choice !== "") { - var dragitem = this.get_unplaced_choice_for_drop(choice, dropzone); - if (dragitem !== null) { - dragitem.setXY(dropzone.getXY()); - dragitem.addClass('placed'); - if (dragitem.dd !== undefined) { - dragitem.dd.once('drag:start', function (e, input) { - input.set('value', ''); - e.target.get('node').removeClass('placed'); - },this, input); - } - } - } - }, this); - this.doc.drag_items().each(function(dragitem) { - if (!dragitem.hasClass('placed') && !dragitem.hasClass('yui3-dd-dragging')) { - var dragitemhome = this.doc.drag_item_home(dragitem.getData('dragitemno')); - dragitem.setXY(dragitemhome.getXY()); - } - }, this); - }, - get_choices_for_drop : function(choice, drop) { - var group = drop.getData('group'); - return this.doc.top_node().all( - 'div.dragitemgroup' + group + ' .choice' + choice + '.drag'); - }, - get_unplaced_choice_for_drop : function(choice, drop) { - var dragitems = this.get_choices_for_drop(choice, drop); - var dragitem = null; - dragitems.some(function (d) { - if (!d.hasClass('placed') && !d.hasClass('yui3-dd-dragging')) { - dragitem = d; - return true; - } else { - return false; - } - }); - return dragitem; - }, - init_drops : function () { - var dropareas = this.doc.top_node().one('div.dropzones'); - var groupnodes = {}; - for (var groupno = 1; groupno <= 8; groupno++) { - var groupnode = Y.Node.create('
    '); - dropareas.append(groupnode); - groupnodes[groupno] = groupnode; - } - var drop_hit_handler = function(e) { - var drag = e.drag.get('node'); - var drop = e.drop.get('node'); - if (Number(drop.getData('group')) === drag.getData('group')){ - this.place_drag_in_drop(drag, drop); - } - }; - for (var dropno in this.get('drops')) { - var drop = this.get('drops')[dropno]; - var nodeclass = 'dropzone group' + drop.group + ' place' + dropno; - var title = drop.text.replace('"', '\"'); - var dropnodehtml = '
     
    '; - var dropnode = Y.Node.create(dropnodehtml); - groupnodes[drop.group].append(dropnode); - dropnode.setStyles({'opacity': 0.5}); - dropnode.setData('xy', drop.xy); - dropnode.setData('place', dropno); - dropnode.setData('inputid', drop.fieldname.replace(':', '_')); - dropnode.setData('group', drop.group); - var dropdd = new Y.DD.Drop({ - node: dropnode, groups : [drop.group]}); - dropdd.on('drop:hit', drop_hit_handler, this); - } - } - }, {NAME : DDIMAGEORTEXTQUESTIONNAME, ATTRS : {}}); - - Y.Event.define('dragchange', { - // Webkit and IE repeat keydown when you hold down arrow keys. - // Opera links keypress to page scroll; others keydown. - // Firefox prevents page scroll via preventDefault() on either - // keydown or keypress. - _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', - - _keys: { - '32': 'next', // Space - '37': 'previous', // Left arrow - '38': 'previous', // Up arrow - '39': 'next', // Right arrow - '40': 'next', // Down arrow - '27': 'remove' // Escape - }, - - _keyHandler: function (e, notifier) { - if (this._keys[e.keyCode]) { - e.direction = this._keys[e.keyCode]; - notifier.fire(e); - } - }, - - on: function (node, sub, notifier) { - sub._detacher = node.on(this._event, this._keyHandler, - this, notifier); - } - }); - M.qtype_ddimageortext.init_question = function(config) { - return new DDIMAGEORTEXT_QUESTION(config); - }; -}, '@VERSION@', { - requires:['node', 'dd', 'dd-drop', 'dd-constrain'] -}); diff --git a/question/type/ddimageortext/yui/form/form.js b/question/type/ddimageortext/yui/form/form.js deleted file mode 100644 index 3af5227e053..00000000000 --- a/question/type/ddimageortext/yui/form/form.js +++ /dev/null @@ -1,336 +0,0 @@ -/** - * This is the question editing form code. - */ -YUI.add('moodle-qtype_ddimageortext-form', function(Y) { - var DDIMAGEORTEXTFORMNAME = 'ddimageortext_form'; - var DDIMAGEORTEXT_FORM = function() { - DDIMAGEORTEXT_FORM.superclass.constructor.apply(this, arguments); - }; - Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { - fp : null, - - initializer : function() { - this.fp = this.file_pickers(); - var tn = Y.one(this.get('topnode')); - tn.one('div.fcontainer').append('
    ' + - '
    '); - this.doc = this.doc_structure(this); - this.draw_dd_area(); - }, - - draw_dd_area : function() { - var bgimageurl = this.fp.file('bgimage').href; - this.stop_selector_events(); - this.set_options_for_drag_item_selectors(); - if (bgimageurl !== null) { - this.doc.load_bg_img(bgimageurl); - this.load_drag_homes(); - - var drop = new Y.DD.Drop({ - node: this.doc.bg_img() - }); - //Listen for a drop:hit on the background image - drop.on('drop:hit', function(e) { - e.drag.get('node').setData('gooddrop', true); - }); - - this.afterimageloaddone = false; - this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); - this.doc.drag_item_homes() - .on('load', this.constrain_image_size, this, 'dragimage'); - this.doc.bg_img().after('load', this.poll_for_image_load, this, - true, 0, this.after_all_images_loaded); - this.doc.drag_item_homes() .after('load', this.poll_for_image_load, this, - true, 0, this.after_all_images_loaded); - } else { - this.setup_form_events(); - } - this.update_visibility_of_file_pickers(); - }, - - after_all_images_loaded : function () { - this.update_padding_sizes_all(); - this.update_drag_instances(); - this.reposition_drags_for_form(); - this.set_options_for_drag_item_selectors(); - this.setup_form_events(); - Y.later(500, this, this.reposition_drags_for_form, [], true); - }, - - constrain_image_size : function (e, imagetype) { - var maxsize = this.get('maxsizes')[imagetype]; - var reduceby = Math.max(e.target.get('width') / maxsize.width, - e.target.get('height') / maxsize.height); - if (reduceby > 1) { - e.target.set('width', Math.floor(e.target.get('width') / reduceby)); - } - e.target.addClass('constrained'); - e.target.detach('load', this.constrain_image_size); - }, - - load_drag_homes : function () { - // Set up drag items homes. - for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { - this.load_drag_home(i); - } - }, - - load_drag_home : function (dragitemno) { - var url = null; - if ('image' === this.form.get_form_value('drags', [dragitemno, 'dragitemtype'])) { - url = this.fp.file(this.form.to_name_with_index('dragitem', [dragitemno])).href; - } - this.doc.add_or_update_drag_item_home(dragitemno, url, - this.form.get_form_value('draglabel', [dragitemno]), - this.form.get_form_value('drags', [dragitemno, 'draggroup'])); - }, - - update_drag_instances : function () { - // Set up drop zones. - for (var i = 0; i < this.form.get_form_value('nodropzone', []); i++) { - var dragitemno = this.form.get_form_value('drops', [i, 'choice']); - if (dragitemno !== '0' && (this.doc.drag_item(i) === null)) { - var drag = this.doc.clone_new_drag_item(i, dragitemno - 1); - if (drag !== null) { - this.doc.draggable_for_form(drag); - } - } - } - }, - set_options_for_drag_item_selectors : function () { - var dragitemsoptions = {0: ''}; - for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { - var label = this.form.get_form_value('draglabel', [i]); - var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); - if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype']) - && file.name !== null) { - dragitemsoptions[i + 1] = (i + 1) + '. ' + label + ' (' + file.name + ')'; - } else if (label !== '') { - dragitemsoptions[i + 1] = (i + 1) + '. ' + label; - } - } - for (i = 0; i < this.form.get_form_value('nodropzone', []); i++) { - var selector = Y.one('#id_drops_' + i + '_choice'); - var selectedvalue = selector.get('value'); - selector.all('option').remove(true); - for (var value in dragitemsoptions) { - value = + value; - var option = ''; - selector.append(option); - var optionnode = selector.one('option[value="' + value + '"]'); - if (value === + selectedvalue) { - optionnode.set('selected', true); - } else { - if (value !== 0) { // No item option is always selectable. - var cbel = Y.one('#id_drags_' + (value - 1) + '_infinite'); - if (cbel && !cbel.get('checked')) { - Y.all('fieldset#id_dropzoneheader select').some(function (selector) { - if (Number(selector.get('value')) === value) { - optionnode.set('disabled', true); - return true; // Stop looping. - } - return false; - }, this); - } - } - } - } - } - }, - - stop_selector_events : function () { - Y.all('fieldset#id_dropzoneheader select').detachAll(); - }, - - setup_form_events : function () { - // Events triggered by changes to form data. - - // X and y coordinates. - Y.all('fieldset#id_dropzoneheader input').on('blur', function (e) { - var name = e.target.getAttribute('name'); - var draginstanceno = this.form.from_name_with_index(name).indexes[0]; - var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), - this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; - var constrainedxy = this.constrain_xy(draginstanceno, fromform); - this.form.set_form_value('drops', [draginstanceno, 'xleft'], constrainedxy[0]); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); - }, this); - - // Change in selected item. - Y.all('fieldset#id_dropzoneheader select').on('change', function (e) { - var name = e.target.getAttribute('name'); - var draginstanceno = this.form.from_name_with_index(name).indexes[0]; - var old = this.doc.drag_item(draginstanceno); - if (old !== null) { - old.remove(true); - } - this.draw_dd_area(); - }, this); - - for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { - // Change to group selector. - Y.all('#fgroup_id_drags_' + i + ' select.draggroup').on( - 'change', function () { - this.doc.drag_items().remove(true); - this.draw_dd_area(); - }, this); - Y.all('#fgroup_id_drags_' + i + ' select.dragitemtype').on( - 'change', function () { - this.doc.drag_items().remove(true); - this.draw_dd_area(); - }, this); - Y.all('fieldset#draggableitemheader_' + i + ' input[type="text"]') - .on('blur', this.set_options_for_drag_item_selectors, this); - // Change to infinite checkbox. - Y.all('fieldset#draggableitemheader_' + i + ' input[type="checkbox"]') - .on('change', this.set_options_for_drag_item_selectors, this); - } - // Event on file picker new file selection. - Y.after(function (e) { - var name = this.fp.name(e.id); - if (name !== 'bgimage') { - this.doc.drag_items().remove(true); - } - this.draw_dd_area(); - }, M.form_filepicker, 'callback', this); - }, - - update_visibility_of_file_pickers : function() { - for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { - if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype'])) { - Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') - .setStyle('display', 'block'); - } else { - Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') - .setStyle('display', 'none'); - } - } - }, - - reposition_drags_for_form : function() { - this.doc.drag_items().each(function (drag) { - var draginstanceno = drag.getData('draginstanceno'); - this.reposition_drag_for_form(draginstanceno); - }, this); - }, - - reposition_drag_for_form : function (draginstanceno) { - var drag = this.doc.drag_item(draginstanceno); - if (null !== drag && !drag.hasClass('yui3-dd-dragging')) { - var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), - this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; - if (fromform[0] === '' && fromform[1] === '') { - var dragitemno = drag.getData('dragitemno'); - drag.setXY(this.doc.drag_item_home(dragitemno).getXY()); - } else { - drag.setXY(this.convert_to_window_xy(fromform)); - } - } - }, - set_drag_xy : function (draginstanceno, xy) { - xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); - this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.round(xy[0])); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.round(xy[1])); - }, - reset_drag_xy : function (draginstanceno) { - this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); - this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); - }, - - //make sure xy value is not out of bounds of bg image - constrain_xy : function (draginstanceno, bgimgxy) { - var drag = this.doc.drag_item(draginstanceno); - var xleftconstrained = - Math.min(bgimgxy[0], this.doc.bg_img().get('width') - drag.get('offsetWidth')); - var ytopconstrained = - Math.min(bgimgxy[1], this.doc.bg_img().get('height') - drag.get('offsetHeight')); - xleftconstrained = Math.max(xleftconstrained, 0); - ytopconstrained = Math.max(ytopconstrained, 0); - return [xleftconstrained, ytopconstrained]; - }, - convert_to_bg_img_xy : function (windowxy) { - return [Number(windowxy[0]) - this.doc.bg_img().getX() - 1, - Number(windowxy[1]) - this.doc.bg_img().getY() - 1]; - }, - - /** - * Low level operations on form. - */ - form : { - to_name_with_index : function(name, indexes) { - var indexstring = name; - for (var i = 0; i < indexes.length; i++) { - indexstring = indexstring + '[' + indexes[i] + ']'; - } - return indexstring; - }, - get_el : function (name, indexes) { - var form = document.getElementById('mform1'); - return form.elements[this.to_name_with_index(name, indexes)]; - }, - get_form_value : function(name, indexes) { - var el = this.get_el(name, indexes); - if (el.type === 'checkbox') { - return el.checked; - } else { - return el.value; - } - }, - set_form_value : function(name, indexes, value) { - var el = this.get_el(name, indexes); - if (el.type === 'checkbox') { - el.checked = value; - } else { - el.value = value; - } - }, - from_name_with_index : function(name) { - var toreturn = {}; - toreturn.indexes = []; - var bracket = name.indexOf('['); - toreturn.name = name.substring(0, bracket); - while (bracket !== -1) { - var end = name.indexOf(']', bracket + 1); - toreturn.indexes.push(name.substring(bracket + 1, end)); - bracket = name.indexOf('[', end + 1); - } - return toreturn; - } - }, - - file_pickers : function () { - var draftitemidstoname; - var nametoparentnode; - if (draftitemidstoname === undefined) { - draftitemidstoname = {}; - nametoparentnode = {}; - var filepickers = Y.all('form.mform input.filepickerhidden'); - filepickers.each(function(filepicker) { - draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); - nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); - }, this); - } - var toreturn = { - file : function (name) { - var parentnode = nametoparentnode[name]; - var fileanchor = parentnode.one('div.filepicker-filelist a'); - if (fileanchor) { - return {href : fileanchor.get('href'), name : fileanchor.get('innerHTML')}; - } else { - return {href : null, name : null}; - } - }, - name : function (draftitemid) { - return draftitemidstoname[draftitemid]; - } - }; - return toreturn; - } - }, {NAME : DDIMAGEORTEXTFORMNAME, ATTRS : {maxsizes:{value:null}}}); - M.qtype_ddimageortext = M.qtype_ddimageortext || {}; - M.qtype_ddimageortext.init_form = function(config) { - return new DDIMAGEORTEXT_FORM(config); - }; -}, '@VERSION@', { - requires:['moodle-qtype_ddimageortext-dd', 'form_filepicker'] -}); diff --git a/question/type/ddimageortext/yui/src/ddimageortext/build.json b/question/type/ddimageortext/yui/src/ddimageortext/build.json new file mode 100644 index 00000000000..00d07c6bf8c --- /dev/null +++ b/question/type/ddimageortext/yui/src/ddimageortext/build.json @@ -0,0 +1,10 @@ +{ + "name": "moodle-qtype_ddimageortext-dd", + "builds": { + "moodle-qtype_ddimageortext-dd": { + "jsfiles": [ + "ddimageortext.js" + ] + } + } +} diff --git a/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js b/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js new file mode 100644 index 00000000000..d22e07c7e41 --- /dev/null +++ b/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js @@ -0,0 +1,478 @@ +// This file is part of Moodle - http://moodle.org/ +// +// 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 . + +var DDIMAGEORTEXTDDNAME = 'ddimageortext_dd'; +var DDIMAGEORTEXT_DD = function() { + DDIMAGEORTEXT_DD.superclass.constructor.apply(this, arguments); +}; + +/** + * This is the base class for the question rendering and question editing form code. + */ +Y.extend(DDIMAGEORTEXT_DD, Y.Base, { + doc : null, + polltimer : null, + afterimageloaddone : false, + poll_for_image_load : function (e, waitforimageconstrain, pause, doafterwords) { + if (this.afterimageloaddone) { + return; + } + var bgdone = this.doc.bg_img().get('complete'); + if (waitforimageconstrain) { + bgdone = bgdone && this.doc.bg_img().hasClass('constrained'); + } + var alldragsloaded = !this.doc.drag_item_homes().some(function(dragitemhome){ + //in 'some' loop returning true breaks the loop and is passed as return value from + //'some' else returns false. Can be though of as equivalent to ||. + if (dragitemhome.get('tagName') !== 'IMG'){ + return false; + } + var done = (dragitemhome.get('complete')); + if (waitforimageconstrain) { + done = done && dragitemhome.hasClass('constrained'); + } + return !done; + }); + if (bgdone && alldragsloaded) { + if (this.polltimer !== null) { + this.polltimer.cancel(); + this.polltimer = null; + } + this.doc.drag_item_homes().detach('load', this.poll_for_image_load); + this.doc.bg_img().detach('load', this.poll_for_image_load); + if (pause !== 0) { + Y.later(pause, this, doafterwords); + } else { + doafterwords.call(this); + } + this.afterimageloaddone = true; + } else if (this.polltimer === null) { + var pollarguments = [null, waitforimageconstrain, pause, doafterwords]; + this.polltimer = + Y.later(1000, this, this.poll_for_image_load, pollarguments, true); + } + }, + /** + * Object to encapsulate operations on dd area. + */ + doc_structure : function (mainobj) { + var topnode = Y.one(this.get('topnode')); + var dragitemsarea = topnode.one('div.dragitems'); + var dropbgarea = topnode.one('div.droparea'); + return { + top_node : function() { + return topnode; + }, + drag_items : function() { + return dragitemsarea.all('.drag'); + }, + drop_zones : function() { + return topnode.all('div.dropzones div.dropzone'); + }, + drop_zone_group : function(groupno) { + return topnode.all('div.dropzones div.group' + groupno); + }, + drag_items_cloned_from : function(dragitemno) { + return dragitemsarea.all('.dragitems' + dragitemno); + }, + drag_item : function(draginstanceno) { + return dragitemsarea.one('.draginstance' + draginstanceno); + }, + drag_items_in_group : function(groupno) { + return dragitemsarea.all('.drag.group' + groupno); + }, + drag_item_homes : function() { + return dragitemsarea.all('.draghome'); + }, + bg_img : function() { + return topnode.one('.dropbackground'); + }, + load_bg_img : function (url) { + dropbgarea.setContent(''); + this.bg_img().on('load', this.on_image_load, this, 'bg_image'); + }, + add_or_update_drag_item_home : function (dragitemno, url, alt, group) { + var oldhome = this.drag_item_home(dragitemno); + var classes = 'draghome dragitemhomes' + dragitemno + ' group' + group; + var imghtml = '' + alt + ''; + var divhtml = '
    ' + alt + '
    '; + if (oldhome === null) { + if (url) { + dragitemsarea.append(imghtml); + } else if (alt !== '') { + dragitemsarea.append(divhtml); + } + } else { + if (url) { + dragitemsarea.insert(imghtml, oldhome); + } else if (alt !== '') { + dragitemsarea.insert(divhtml, oldhome); + } + oldhome.remove(true); + } + var newlycreated = dragitemsarea.one('.dragitemhomes' + dragitemno); + if (newlycreated !== null) { + newlycreated.setData('groupno', group); + newlycreated.setData('dragitemno', dragitemno); + } + }, + drag_item_home : function (dragitemno) { + return dragitemsarea.one('.dragitemhomes' + dragitemno); + }, + get_classname_numeric_suffix : function(node, prefix) { + var classes = node.getAttribute('class'); + if (classes !== '') { + var classesarr = classes.split(' '); + for (var index = 0; index < classesarr.length; index++) { + var patt1 = new RegExp('^' + prefix + '([0-9])+$'); + if (patt1.test(classesarr[index])) { + var patt2 = new RegExp('([0-9])+$'); + var match = patt2.exec(classesarr[index]); + return + match[0]; + } + } + } + throw 'Prefix "' + prefix + '" not found in class names.'; + }, + clone_new_drag_item : function (draginstanceno, dragitemno) { + var draghome = this.drag_item_home(dragitemno); + if (draghome === null) { + return null; + } + var drag = draghome.cloneNode(true); + drag.removeClass('dragitemhomes' + dragitemno); + drag.addClass('dragitems' + dragitemno); + drag.addClass('draginstance' + draginstanceno); + drag.removeClass('draghome'); + drag.addClass('drag'); + drag.setStyles({'visibility': 'visible', 'position' : 'absolute'}); + drag.setData('draginstanceno', draginstanceno); + drag.setData('dragitemno', dragitemno); + draghome.get('parentNode').appendChild(drag); + return drag; + }, + draggable_for_question : function (drag, group, choice) { + new Y.DD.Drag({ + node: drag, + dragMode: 'point', + groups: [group] + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + + drag.setData('group', group); + drag.setData('choice', choice); + + }, + draggable_for_form : function (drag) { + var dd = new Y.DD.Drag({ + node: drag, + dragMode: 'point' + }).plug(Y.Plugin.DDConstrained, {constrain2node: topnode}); + dd.on('drag:end', function(e) { + var dragnode = e.target.get('node'); + var draginstanceno = dragnode.getData('draginstanceno'); + var gooddrop = dragnode.getData('gooddrop'); + + if (!gooddrop) { + mainobj.reset_drag_xy(draginstanceno); + } else { + mainobj.set_drag_xy(draginstanceno, [e.pageX, e.pageY]); + } + }, this); + dd.on('drag:start', function(e) { + var drag = e.target; + drag.get('node').setData('gooddrop', false); + }, this); + + } + + }; + }, + + update_padding_sizes_all : function () { + for (var groupno = 1; groupno <= 8; groupno++) { + this.update_padding_size_for_group(groupno); + } + }, + update_padding_size_for_group : function (groupno) { + var groupitems = this.doc.top_node().all('.draghome.group' + groupno); + if (groupitems.size() !== 0) { + var maxwidth = 0; + var maxheight = 0; + groupitems.each(function(item){ + maxwidth = Math.max(maxwidth, item.get('clientWidth')); + maxheight = Math.max(maxheight, item.get('clientHeight')); + }, this); + groupitems.each(function(item) { + var margintopbottom = Math.round((10 + maxheight - item.get('clientHeight')) / 2); + var marginleftright = Math.round((10 + maxwidth - item.get('clientWidth')) / 2); + item.setStyle('padding', margintopbottom + 'px ' + marginleftright + 'px ' + + margintopbottom + 'px ' + marginleftright + 'px'); + }, this); + this.doc.drop_zone_group(groupno).setStyles({'width': maxwidth + 10, + 'height': maxheight + 10}); + } + }, + convert_to_window_xy : function (bgimgxy) { + return [Number(bgimgxy[0]) + this.doc.bg_img().getX() + 1, + Number(bgimgxy[1]) + this.doc.bg_img().getY() + 1]; + } +}, { + NAME : DDIMAGEORTEXTDDNAME, + ATTRS : { + drops : {value : null}, + readonly : {value : false}, + topnode : {value : null} + } +}); + +M.qtype_ddimageortext = M.qtype_ddimageortext || {}; +M.qtype_ddimageortext.dd_base_class = DDIMAGEORTEXT_DD; + +var DDIMAGEORTEXTQUESTIONNAME = 'ddimageortext_question'; +var DDIMAGEORTEXT_QUESTION = function() { + DDIMAGEORTEXT_QUESTION.superclass.constructor.apply(this, arguments); +}; +/** + * This is the code for question rendering. + */ +Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { + initializer : function() { + this.doc = this.doc_structure(this); + this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); + this.doc.bg_img().after('load', this.poll_for_image_load, this, + false, 0, this.create_all_drag_and_drops); + this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, + false, 0, this.create_all_drag_and_drops); + Y.later(500, this, this.reposition_drags_for_question, [], true); + }, + create_all_drag_and_drops : function () { + this.init_drops(); + this.update_padding_sizes_all(); + var i = 0; + this.doc.drag_item_homes().each(function(dragitemhome){ + var dragitemno = Number(this.doc.get_classname_numeric_suffix(dragitemhome, 'dragitemhomes')); + var choice = + this.doc.get_classname_numeric_suffix(dragitemhome, 'choice'); + var group = + this.doc.get_classname_numeric_suffix(dragitemhome, 'group'); + var groupsize = this.doc.drop_zone_group(group).size(); + var dragnode = this.doc.clone_new_drag_item(i, dragitemno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + if (dragnode.hasClass('infinite')) { + var dragstocreate = groupsize - 1; + while (dragstocreate > 0) { + dragnode = this.doc.clone_new_drag_item(i, dragitemno); + i++; + if (!this.get('readonly')) { + this.doc.draggable_for_question(dragnode, group, choice); + } + dragstocreate--; + } + } + }, this); + this.reposition_drags_for_question(); + if (!this.get('readonly')) { + this.doc.drop_zones().set('tabIndex', 0); + this.doc.drop_zones().each( + function(v){ + v.on('dragchange', this.drop_zone_key_press, this); + }, this); + } + }, + drop_zone_key_press : function (e) { + switch (e.direction) { + case 'next' : + this.place_next_drag_in(e.target); + break; + case 'previous' : + this.place_previous_drag_in(e.target); + break; + case 'remove' : + this.remove_drag_from_drop(e.target); + break; + } + e.preventDefault(); + this.reposition_drags_for_question(); + }, + place_next_drag_in : function (drop) { + this.search_for_unplaced_drop_choice(drop, 1); + }, + place_previous_drag_in : function (drop) { + this.search_for_unplaced_drop_choice(drop, -1); + }, + search_for_unplaced_drop_choice : function (drop, direction) { + var next; + var current = this.current_drag_in_drop(drop); + if ('' === current) { + if (direction === 1) { + next = 1; + } else { + next = 1; + var groupno = drop.getData('group'); + this.doc.drag_items_in_group(groupno).each(function(drag) { + next = Math.max(next, drag.getData('choice')); + }, this); + } + } else { + next = + current + direction; + } + var drag; + do { + if (this.get_choices_for_drop(next, drop).size() === 0){ + this.remove_drag_from_drop(drop); + return; + } else { + drag = this.get_unplaced_choice_for_drop(next, drop); + } + next = next + direction; + } while (drag === null); + this.place_drag_in_drop(drag, drop); + }, + current_drag_in_drop : function (drop) { + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#' + inputid); + return inputnode.get('value'); + }, + remove_drag_from_drop : function (drop) { + this.place_drag_in_drop(null, drop); + }, + place_drag_in_drop : function (drag, drop) { + var inputid = drop.getData('inputid'); + var inputnode = Y.one('input#' + inputid); + if (drag !== null) { + inputnode.set('value', drag.getData('choice')); + } else { + inputnode.set('value', ''); + } + }, + reposition_drags_for_question : function() { + this.doc.drag_items().removeClass('placed'); + this.doc.drag_items().each (function (dragitem) { + if (dragitem.dd !== undefined) { + dragitem.dd.detachAll('drag:start'); + } + }, this); + this.doc.drop_zones().each(function(dropzone) { + var relativexy = dropzone.getData('xy'); + dropzone.setXY(this.convert_to_window_xy(relativexy)); + var inputcss = 'input#' + dropzone.getData('inputid'); + var input = this.doc.top_node().one(inputcss); + var choice = input.get('value'); + if (choice !== "") { + var dragitem = this.get_unplaced_choice_for_drop(choice, dropzone); + if (dragitem !== null) { + dragitem.setXY(dropzone.getXY()); + dragitem.addClass('placed'); + if (dragitem.dd !== undefined) { + dragitem.dd.once('drag:start', function (e, input) { + input.set('value', ''); + e.target.get('node').removeClass('placed'); + },this, input); + } + } + } + }, this); + this.doc.drag_items().each(function(dragitem) { + if (!dragitem.hasClass('placed') && !dragitem.hasClass('yui3-dd-dragging')) { + var dragitemhome = this.doc.drag_item_home(dragitem.getData('dragitemno')); + dragitem.setXY(dragitemhome.getXY()); + } + }, this); + }, + get_choices_for_drop : function(choice, drop) { + var group = drop.getData('group'); + return this.doc.top_node().all( + 'div.dragitemgroup' + group + ' .choice' + choice + '.drag'); + }, + get_unplaced_choice_for_drop : function(choice, drop) { + var dragitems = this.get_choices_for_drop(choice, drop); + var dragitem = null; + dragitems.some(function (d) { + if (!d.hasClass('placed') && !d.hasClass('yui3-dd-dragging')) { + dragitem = d; + return true; + } else { + return false; + } + }); + return dragitem; + }, + init_drops : function () { + var dropareas = this.doc.top_node().one('div.dropzones'); + var groupnodes = {}; + for (var groupno = 1; groupno <= 8; groupno++) { + var groupnode = Y.Node.create('
    '); + dropareas.append(groupnode); + groupnodes[groupno] = groupnode; + } + var drop_hit_handler = function(e) { + var drag = e.drag.get('node'); + var drop = e.drop.get('node'); + if (Number(drop.getData('group')) === drag.getData('group')){ + this.place_drag_in_drop(drag, drop); + } + }; + for (var dropno in this.get('drops')) { + var drop = this.get('drops')[dropno]; + var nodeclass = 'dropzone group' + drop.group + ' place' + dropno; + var title = drop.text.replace('"', '\"'); + var dropnodehtml = '
     
    '; + var dropnode = Y.Node.create(dropnodehtml); + groupnodes[drop.group].append(dropnode); + dropnode.setStyles({'opacity': 0.5}); + dropnode.setData('xy', drop.xy); + dropnode.setData('place', dropno); + dropnode.setData('inputid', drop.fieldname.replace(':', '_')); + dropnode.setData('group', drop.group); + var dropdd = new Y.DD.Drop({ + node: dropnode, groups : [drop.group]}); + dropdd.on('drop:hit', drop_hit_handler, this); + } + } +}, {NAME : DDIMAGEORTEXTQUESTIONNAME, ATTRS : {}}); + +Y.Event.define('dragchange', { + // Webkit and IE repeat keydown when you hold down arrow keys. + // Opera links keypress to page scroll; others keydown. + // Firefox prevents page scroll via preventDefault() on either + // keydown or keypress. + _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', + + _keys: { + '32': 'next', // Space + '37': 'previous', // Left arrow + '38': 'previous', // Up arrow + '39': 'next', // Right arrow + '40': 'next', // Down arrow + '27': 'remove' // Escape + }, + + _keyHandler: function (e, notifier) { + if (this._keys[e.keyCode]) { + e.direction = this._keys[e.keyCode]; + notifier.fire(e); + } + }, + + on: function (node, sub, notifier) { + sub._detacher = node.on(this._event, this._keyHandler, + this, notifier); + } +}); + +M.qtype_ddimageortext.init_question = function(config) { + return new DDIMAGEORTEXT_QUESTION(config); +}; \ No newline at end of file diff --git a/question/type/ddimageortext/yui/src/ddimageortext/meta/ddimageortext.json b/question/type/ddimageortext/yui/src/ddimageortext/meta/ddimageortext.json new file mode 100644 index 00000000000..a9e0af6b4d2 --- /dev/null +++ b/question/type/ddimageortext/yui/src/ddimageortext/meta/ddimageortext.json @@ -0,0 +1,10 @@ +{ + "moodle-qtype_ddimageortext-dd": { + "requires": [ + "node", + "dd", + "dd-drop", + "dd-constrain" + ] + } +} diff --git a/question/type/ddimageortext/yui/src/form/build.json b/question/type/ddimageortext/yui/src/form/build.json new file mode 100644 index 00000000000..8e57acce72f --- /dev/null +++ b/question/type/ddimageortext/yui/src/form/build.json @@ -0,0 +1,10 @@ +{ + "name": "moodle-qtype_ddimageortext-form", + "builds": { + "moodle-qtype_ddimageortext-form": { + "jsfiles": [ + "form.js" + ] + } + } +} diff --git a/question/type/ddimageortext/yui/src/form/js/form.js b/question/type/ddimageortext/yui/src/form/js/form.js new file mode 100644 index 00000000000..bbd94130264 --- /dev/null +++ b/question/type/ddimageortext/yui/src/form/js/form.js @@ -0,0 +1,349 @@ +// This file is part of Moodle - http://moodle.org/ +// +// 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 . + +/** + * This is the question editing form code. + */ +var DDIMAGEORTEXTFORMNAME = 'moodle-qtype_ddimageortext-form'; +var DDIMAGEORTEXT_FORM = function() { + DDIMAGEORTEXT_FORM.superclass.constructor.apply(this, arguments); +}; + +Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { + fp : null, + + initializer : function() { + this.fp = this.file_pickers(); + var tn = Y.one(this.get('topnode')); + tn.one('div.fcontainer').append('
    ' + + '
    '); + this.doc = this.doc_structure(this); + this.draw_dd_area(); + }, + + draw_dd_area : function() { + var bgimageurl = this.fp.file('bgimage').href; + this.stop_selector_events(); + this.set_options_for_drag_item_selectors(); + if (bgimageurl !== null) { + this.doc.load_bg_img(bgimageurl); + this.load_drag_homes(); + + var drop = new Y.DD.Drop({ + node: this.doc.bg_img() + }); + //Listen for a drop:hit on the background image + drop.on('drop:hit', function(e) { + e.drag.get('node').setData('gooddrop', true); + }); + + this.afterimageloaddone = false; + this.doc.bg_img().on('load', this.constrain_image_size, this, 'bgimage'); + this.doc.drag_item_homes() + .on('load', this.constrain_image_size, this, 'dragimage'); + this.doc.bg_img().after('load', this.poll_for_image_load, this, + true, 0, this.after_all_images_loaded); + this.doc.drag_item_homes() .after('load', this.poll_for_image_load, this, + true, 0, this.after_all_images_loaded); + } else { + this.setup_form_events(); + } + this.update_visibility_of_file_pickers(); + }, + + after_all_images_loaded : function () { + this.update_padding_sizes_all(); + this.update_drag_instances(); + this.reposition_drags_for_form(); + this.set_options_for_drag_item_selectors(); + this.setup_form_events(); + Y.later(500, this, this.reposition_drags_for_form, [], true); + }, + + constrain_image_size : function (e, imagetype) { + var maxsize = this.get('maxsizes')[imagetype]; + var reduceby = Math.max(e.target.get('width') / maxsize.width, + e.target.get('height') / maxsize.height); + if (reduceby > 1) { + e.target.set('width', Math.floor(e.target.get('width') / reduceby)); + } + e.target.addClass('constrained'); + e.target.detach('load', this.constrain_image_size); + }, + + load_drag_homes : function () { + // Set up drag items homes. + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + this.load_drag_home(i); + } + }, + + load_drag_home : function (dragitemno) { + var url = null; + if ('image' === this.form.get_form_value('drags', [dragitemno, 'dragitemtype'])) { + url = this.fp.file(this.form.to_name_with_index('dragitem', [dragitemno])).href; + } + this.doc.add_or_update_drag_item_home(dragitemno, url, + this.form.get_form_value('draglabel', [dragitemno]), + this.form.get_form_value('drags', [dragitemno, 'draggroup'])); + }, + + update_drag_instances : function () { + // Set up drop zones. + for (var i = 0; i < this.form.get_form_value('nodropzone', []); i++) { + var dragitemno = this.form.get_form_value('drops', [i, 'choice']); + if (dragitemno !== '0' && (this.doc.drag_item(i) === null)) { + var drag = this.doc.clone_new_drag_item(i, dragitemno - 1); + if (drag !== null) { + this.doc.draggable_for_form(drag); + } + } + } + }, + set_options_for_drag_item_selectors : function () { + var dragitemsoptions = {0: ''}; + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + var label = this.form.get_form_value('draglabel', [i]); + var file = this.fp.file(this.form.to_name_with_index('dragitem', [i])); + if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype']) + && file.name !== null) { + dragitemsoptions[i + 1] = (i + 1) + '. ' + label + ' (' + file.name + ')'; + } else if (label !== '') { + dragitemsoptions[i + 1] = (i + 1) + '. ' + label; + } + } + for (i = 0; i < this.form.get_form_value('nodropzone', []); i++) { + var selector = Y.one('#id_drops_' + i + '_choice'); + var selectedvalue = selector.get('value'); + selector.all('option').remove(true); + for (var value in dragitemsoptions) { + value = + value; + var option = ''; + selector.append(option); + var optionnode = selector.one('option[value="' + value + '"]'); + if (value === + selectedvalue) { + optionnode.set('selected', true); + } else { + if (value !== 0) { // No item option is always selectable. + var cbel = Y.one('#id_drags_' + (value - 1) + '_infinite'); + if (cbel && !cbel.get('checked')) { + Y.all('fieldset#id_dropzoneheader select').some(function (selector) { + if (Number(selector.get('value')) === value) { + optionnode.set('disabled', true); + return true; // Stop looping. + } + return false; + }, this); + } + } + } + } + } + }, + + stop_selector_events : function () { + Y.all('fieldset#id_dropzoneheader select').detachAll(); + }, + + setup_form_events : function () { + // Events triggered by changes to form data. + + // X and y coordinates. + Y.all('fieldset#id_dropzoneheader input').on('blur', function (e) { + var name = e.target.getAttribute('name'); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), + this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; + var constrainedxy = this.constrain_xy(draginstanceno, fromform); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], constrainedxy[0]); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], constrainedxy[1]); + }, this); + + // Change in selected item. + Y.all('fieldset#id_dropzoneheader select').on('change', function (e) { + var name = e.target.getAttribute('name'); + var draginstanceno = this.form.from_name_with_index(name).indexes[0]; + var old = this.doc.drag_item(draginstanceno); + if (old !== null) { + old.remove(true); + } + this.draw_dd_area(); + }, this); + + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + // Change to group selector. + Y.all('#fgroup_id_drags_' + i + ' select.draggroup').on( + 'change', function () { + this.doc.drag_items().remove(true); + this.draw_dd_area(); + }, this); + Y.all('#fgroup_id_drags_' + i + ' select.dragitemtype').on( + 'change', function () { + this.doc.drag_items().remove(true); + this.draw_dd_area(); + }, this); + Y.all('fieldset#draggableitemheader_' + i + ' input[type="text"]') + .on('blur', this.set_options_for_drag_item_selectors, this); + // Change to infinite checkbox. + Y.all('fieldset#draggableitemheader_' + i + ' input[type="checkbox"]') + .on('change', this.set_options_for_drag_item_selectors, this); + } + // Event on file picker new file selection. + Y.after(function (e) { + var name = this.fp.name(e.id); + if (name !== 'bgimage') { + this.doc.drag_items().remove(true); + } + this.draw_dd_area(); + }, M.form_filepicker, 'callback', this); + }, + + update_visibility_of_file_pickers : function() { + for (var i = 0; i < this.form.get_form_value('noitems', []); i++) { + if ('image' === this.form.get_form_value('drags', [i, 'dragitemtype'])) { + Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') + .setStyle('display', 'block'); + } else { + Y.one('input#id_dragitem_' + i).get('parentNode').get('parentNode') + .setStyle('display', 'none'); + } + } + }, + + reposition_drags_for_form : function() { + this.doc.drag_items().each(function (drag) { + var draginstanceno = drag.getData('draginstanceno'); + this.reposition_drag_for_form(draginstanceno); + }, this); + }, + + reposition_drag_for_form : function (draginstanceno) { + var drag = this.doc.drag_item(draginstanceno); + if (null !== drag && !drag.hasClass('yui3-dd-dragging')) { + var fromform = [this.form.get_form_value('drops', [draginstanceno, 'xleft']), + this.form.get_form_value('drops', [draginstanceno, 'ytop'])]; + if (fromform[0] === '' && fromform[1] === '') { + var dragitemno = drag.getData('dragitemno'); + drag.setXY(this.doc.drag_item_home(dragitemno).getXY()); + } else { + drag.setXY(this.convert_to_window_xy(fromform)); + } + } + }, + set_drag_xy : function (draginstanceno, xy) { + xy = this.constrain_xy(draginstanceno, this.convert_to_bg_img_xy(xy)); + this.form.set_form_value('drops', [draginstanceno, 'xleft'], Math.round(xy[0])); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], Math.round(xy[1])); + }, + reset_drag_xy : function (draginstanceno) { + this.form.set_form_value('drops', [draginstanceno, 'xleft'], ''); + this.form.set_form_value('drops', [draginstanceno, 'ytop'], ''); + }, + + //make sure xy value is not out of bounds of bg image + constrain_xy : function (draginstanceno, bgimgxy) { + var drag = this.doc.drag_item(draginstanceno); + var xleftconstrained = + Math.min(bgimgxy[0], this.doc.bg_img().get('width') - drag.get('offsetWidth')); + var ytopconstrained = + Math.min(bgimgxy[1], this.doc.bg_img().get('height') - drag.get('offsetHeight')); + xleftconstrained = Math.max(xleftconstrained, 0); + ytopconstrained = Math.max(ytopconstrained, 0); + return [xleftconstrained, ytopconstrained]; + }, + convert_to_bg_img_xy : function (windowxy) { + return [Number(windowxy[0]) - this.doc.bg_img().getX() - 1, + Number(windowxy[1]) - this.doc.bg_img().getY() - 1]; + }, + + /** + * Low level operations on form. + */ + form : { + to_name_with_index : function(name, indexes) { + var indexstring = name; + for (var i = 0; i < indexes.length; i++) { + indexstring = indexstring + '[' + indexes[i] + ']'; + } + return indexstring; + }, + get_el : function (name, indexes) { + var form = document.getElementById('mform1'); + return form.elements[this.to_name_with_index(name, indexes)]; + }, + get_form_value : function(name, indexes) { + var el = this.get_el(name, indexes); + if (el.type === 'checkbox') { + return el.checked; + } else { + return el.value; + } + }, + set_form_value : function(name, indexes, value) { + var el = this.get_el(name, indexes); + if (el.type === 'checkbox') { + el.checked = value; + } else { + el.value = value; + } + }, + from_name_with_index : function(name) { + var toreturn = {}; + toreturn.indexes = []; + var bracket = name.indexOf('['); + toreturn.name = name.substring(0, bracket); + while (bracket !== -1) { + var end = name.indexOf(']', bracket + 1); + toreturn.indexes.push(name.substring(bracket + 1, end)); + bracket = name.indexOf('[', end + 1); + } + return toreturn; + } + }, + + file_pickers : function () { + var draftitemidstoname; + var nametoparentnode; + if (draftitemidstoname === undefined) { + draftitemidstoname = {}; + nametoparentnode = {}; + var filepickers = Y.all('form.mform input.filepickerhidden'); + filepickers.each(function(filepicker) { + draftitemidstoname[filepicker.get('value')] = filepicker.get('name'); + nametoparentnode[filepicker.get('name')] = filepicker.get('parentNode'); + }, this); + } + var toreturn = { + file : function (name) { + var parentnode = nametoparentnode[name]; + var fileanchor = parentnode.one('div.filepicker-filelist a'); + if (fileanchor) { + return {href : fileanchor.get('href'), name : fileanchor.get('innerHTML')}; + } else { + return {href : null, name : null}; + } + }, + name : function (draftitemid) { + return draftitemidstoname[draftitemid]; + } + }; + return toreturn; + } +}, {NAME : DDIMAGEORTEXTFORMNAME, ATTRS : {maxsizes:{value:null}}}); +M.qtype_ddimageortext = M.qtype_ddimageortext || {}; +M.qtype_ddimageortext.init_form = function(config) { + return new DDIMAGEORTEXT_FORM(config); +}; + diff --git a/question/type/ddimageortext/yui/src/form/meta/form.json b/question/type/ddimageortext/yui/src/form/meta/form.json new file mode 100644 index 00000000000..bbd02235751 --- /dev/null +++ b/question/type/ddimageortext/yui/src/form/meta/form.json @@ -0,0 +1,8 @@ +{ + "moodle-qtype_ddimageortext-form": { + "requires": [ + "moodle-qtype_ddimageortext-dd", + "form_filepicker" + ] + } +} From 682bf667eabad4d030ca4403b8a0d4153aa78b97 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 13 Feb 2015 18:59:00 +0000 Subject: [PATCH 197/208] MDL-47494 ddimageortext: Update dd qtype tests to use js_pending not fixed waits #14895 --- question/type/ddimageortext/tests/behat/preview.feature | 2 -- .../moodle-qtype_ddimageortext-dd-debug.js | 6 +++++- .../moodle-qtype_ddimageortext-dd-min.js | 4 ++-- .../moodle-qtype_ddimageortext-dd.js | 6 +++++- .../moodle-qtype_ddimageortext-form-debug.js | 3 +++ .../moodle-qtype_ddimageortext-form-min.js | 4 ++-- .../moodle-qtype_ddimageortext-form.js | 3 +++ .../ddimageortext/yui/src/ddimageortext/js/ddimageortext.js | 6 +++++- question/type/ddimageortext/yui/src/form/js/form.js | 3 +++ 9 files changed, 28 insertions(+), 9 deletions(-) diff --git a/question/type/ddimageortext/tests/behat/preview.feature b/question/type/ddimageortext/tests/behat/preview.feature index 7fde499e362..5fd5954229f 100644 --- a/question/type/ddimageortext/tests/behat/preview.feature +++ b/question/type/ddimageortext/tests/behat/preview.feature @@ -28,7 +28,6 @@ Feature: Preview a drag-drop onto image question Scenario: Preview a question using the mouse. When I click on "Preview" "link" in the "Drag onto image" "table_row" And I switch to "questionpreview" window - And I wait "2" seconds # Odd, but the
    s go to nothing, not a space. And I drag "mountainbelt" to place "1" in the drag and drop onto image question And I drag "continentalshelf" to place "2" in the drag and drop onto image question @@ -46,7 +45,6 @@ Feature: Preview a drag-drop onto image question Scenario: Preview a question using the keyboard. When I click on "Preview" "link" in the "Drag onto image" "table_row" And I switch to "questionpreview" window - And I wait "1" seconds And I type " " on place "1" in the drag and drop onto image question And I type " " on place "2" in the drag and drop onto image question And I type " " on place "3" in the drag and drop onto image question diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js index 10bacdda793..60417571ffa 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js @@ -250,14 +250,17 @@ var DDIMAGEORTEXT_QUESTION = function() { * This is the code for question rendering. */ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { + pendingid: '', initializer : function() { + this.pendingid = 'qtype_ddimageortext-' + Math.random().toString(36).slice(2); // Random string. + M.util.js_pending(this.pendingid); this.doc = this.doc_structure(this); this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); this.doc.bg_img().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); - Y.later(500, this, this.reposition_drags_for_question, [], true); + Y.later(500, this, this.reposition_drags_for_question, [pendingid], true); }, create_all_drag_and_drops : function () { this.init_drops(); @@ -293,6 +296,7 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { v.on('dragchange', this.drop_zone_key_press, this); }, this); } + M.util.js_complete(this.pendingid); }, drop_zone_key_press : function (e) { switch (e.direction) { diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js index a7f8f78af6e..92f8b43654c 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js @@ -1,2 +1,2 @@ -YUI.add("moodle-qtype_ddimageortext-dd",function(e,t){var n="ddimageortext_dd",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,e.Base,{doc:null,polltimer:null,afterimageloaddone:!1,poll_for_image_load:function(t,n,r,i){if(this.afterimageloaddone)return;var s=this.doc.bg_img().get("complete");n&&(s=s&&this.doc.bg_img().hasClass("constrained"));var o=!this.doc.drag_item_homes().some(function(e){if(e.get("tagName")!=="IMG")return!1;var t=e.get("complete");return n&&(t=t&&e.hasClass("constrained")),!t});if(s&&o)this.polltimer!==null&&(this.polltimer.cancel(),this.polltimer=null),this.doc.drag_item_homes().detach("load",this.poll_for_image_load),this.doc.bg_img().detach("load",this.poll_for_image_load),r!==0?e.later(r,this,i):i.call(this),this.afterimageloaddone=!0;else if(this.polltimer===null){var u=[null,n,r,i];this.polltimer=e.later(1e3,this,this.poll_for_image_load,u,!0)}},doc_structure:function(t){var n=e.one(this.get("topnode")),r=n.one("div.dragitems"),i=n.one("div.droparea");return{top_node:function(){return n},drag_items:function(){return r.all(".drag")},drop_zones:function(){return n.all("div.dropzones div.dropzone")},drop_zone_group:function(e){return n.all("div.dropzones div.group"+e)},drag_items_cloned_from:function(e){return r.all(".dragitems"+e)},drag_item:function(e){return r.one(".draginstance"+e)},drag_items_in_group:function(e){return r.all(".drag.group"+e)},drag_item_homes:function(){return r.all(".draghome")},bg_img:function(){return n.one(".dropbackground")},load_bg_img:function(e){i.setContent(''),this.bg_img().on("load",this.on_image_load,this,"bg_image")},add_or_update_drag_item_home:function(e,t,n,i){var s=this.drag_item_home(e),o="draghome dragitemhomes"+e+" group"+i,u=''+n+'',a='
    '+n+"
    ";s===null?t?r.append(u):n!==""&&r.append(a):(t?r.insert(u,s):n!==""&&r.insert(a,s),s.remove(!0));var f=r.one(".dragitemhomes"+e);f!==null&&(f.setData("groupno",i),f.setData("dragitemno",e))},drag_item_home:function(e){return r.one(".dragitemhomes"+e)},get_classname_numeric_suffix:function(e,t){var n=e.getAttribute("class");if(n!==""){var r=n.split(" ");for(var i=0;i0)o=this.doc.clone_new_drag_item(e,n),e++,this.get("readonly")||this.doc.draggable_for_question(o,i,r),u--}},this),this.reposition_drags_for_question(),this.get("readonly")||(this.doc.drop_zones().set("tabIndex",0),this.doc.drop_zones().each(function(e){e.on("dragchange",this.drop_zone_key_press,this)},this))},drop_zone_key_press:function(e){switch(e.direction){case"next":this.place_next_drag_in(e.target);break;case"previous":this.place_previous_drag_in(e.target);break;case"remove":this.remove_drag_from_drop(e.target)}e.preventDefault(),this.reposition_drags_for_question()},place_next_drag_in:function(e){this.search_for_unplaced_drop_choice(e,1)},place_previous_drag_in:function(e){this.search_for_unplaced_drop_choice(e,-1)},search_for_unplaced_drop_choice -:function(e,t){var n,r=this.current_drag_in_drop(e);if(""===r)if(t===1)n=1;else{n=1;var i=e.getData("group");this.doc.drag_items_in_group(i).each(function(e){n=Math.max(n,e.getData("choice"))},this)}else n=+r+t;var s;do{if(this.get_choices_for_drop(n,e).size()===0){this.remove_drag_from_drop(e);return}s=this.get_unplaced_choice_for_drop(n,e),n+=t}while(s===null);this.place_drag_in_drop(s,e)},current_drag_in_drop:function(t){var n=t.getData("inputid"),r=e.one("input#"+n);return r.get("value")},remove_drag_from_drop:function(e){this.place_drag_in_drop(null,e)},place_drag_in_drop:function(t,n){var r=n.getData("inputid"),i=e.one("input#"+r);t!==null?i.set("value",t.getData("choice")):i.set("value","")},reposition_drags_for_question:function(){this.doc.drag_items().removeClass("placed"),this.doc.drag_items().each(function(e){e.dd!==undefined&&e.dd.detachAll("drag:start")},this),this.doc.drop_zones().each(function(e){var t=e.getData("xy");e.setXY(this.convert_to_window_xy(t));var n="input#"+e.getData("inputid"),r=this.doc.top_node().one(n),i=r.get("value");if(i!==""){var s=this.get_unplaced_choice_for_drop(i,e);s!==null&&(s.setXY(e.getXY()),s.addClass("placed"),s.dd!==undefined&&s.dd.once("drag:start",function(e,t){t.set("value",""),e.target.get("node").removeClass("placed")},this,r))}},this),this.doc.drag_items().each(function(e){if(!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")){var t=this.doc.drag_item_home(e.getData("dragitemno"));e.setXY(t.getXY())}},this)},get_choices_for_drop:function(e,t){var n=t.getData("group");return this.doc.top_node().all("div.dragitemgroup"+n+" .choice"+e+".drag")},get_unplaced_choice_for_drop:function(e,t){var n=this.get_choices_for_drop(e,t),r=null;return n.some(function(e){return!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")?(r=e,!0):!1}),r},init_drops:function(){var t=this.doc.top_node().one("div.dropzones"),n={};for(var r=1;r<=8;r++){var i=e.Node.create('
    ');t.append(i),n[r]=i}var s=function(e){var t=e.drag.get("node"),n=e.drop.get("node");Number(n.getData("group"))===t.getData("group")&&this.place_drag_in_drop(t,n)};for(var o in this.get("drops")){var u=this.get("drops")[o],a="dropzone group"+u.group+" place"+o,f=u.text.replace('"','"'),l='
     
    ',c=e.Node.create(l);n[u.group].append(c),c.setStyles({opacity:.5}),c.setData("xy",u.xy),c.setData("place",o),c.setData("inputid",u.fieldname.replace(":","_")),c.setData("group",u.group);var h=new e.DD.Drop({node:c,groups:[u.group]});h.on("drop:hit",s,this)}}},{NAME:i,ATTRS:{}}),e.Event.define("dragchange",{_event:e.UA.webkit||e.UA.ie?"keydown":"keypress",_keys:{32:"next",37:"previous",38:"previous",39:"next",40:"next",27:"remove"},_keyHandler:function(e,t){this._keys[e.keyCode]&&(e.direction=this._keys[e.keyCode],t.fire(e))},on:function(e,t,n){t._detacher=e.on(this._event,this._keyHandler,this,n)}}),M.qtype_ddimageortext.init_question=function(e){return new s(e)}},"@VERSION@",{requires:["node","dd","dd-drop","dd-constrain"]}); +YUI.add("moodle-qtype_ddimageortext-dd",function(e,t){var n="ddimageortext_dd",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,e.Base,{doc:null,polltimer:null,afterimageloaddone:!1,poll_for_image_load:function(t,n,r,i){if(this.afterimageloaddone)return;var s=this.doc.bg_img().get("complete");n&&(s=s&&this.doc.bg_img().hasClass("constrained"));var o=!this.doc.drag_item_homes().some(function(e){if(e.get("tagName")!=="IMG")return!1;var t=e.get("complete");return n&&(t=t&&e.hasClass("constrained")),!t});if(s&&o)this.polltimer!==null&&(this.polltimer.cancel(),this.polltimer=null),this.doc.drag_item_homes().detach("load",this.poll_for_image_load),this.doc.bg_img().detach("load",this.poll_for_image_load),r!==0?e.later(r,this,i):i.call(this),this.afterimageloaddone=!0;else if(this.polltimer===null){var u=[null,n,r,i];this.polltimer=e.later(1e3,this,this.poll_for_image_load,u,!0)}},doc_structure:function(t){var n=e.one(this.get("topnode")),r=n.one("div.dragitems"),i=n.one("div.droparea");return{top_node:function(){return n},drag_items:function(){return r.all(".drag")},drop_zones:function(){return n.all("div.dropzones div.dropzone")},drop_zone_group:function(e){return n.all("div.dropzones div.group"+e)},drag_items_cloned_from:function(e){return r.all(".dragitems"+e)},drag_item:function(e){return r.one(".draginstance"+e)},drag_items_in_group:function(e){return r.all(".drag.group"+e)},drag_item_homes:function(){return r.all(".draghome")},bg_img:function(){return n.one(".dropbackground")},load_bg_img:function(e){i.setContent(''),this.bg_img().on("load",this.on_image_load,this,"bg_image")},add_or_update_drag_item_home:function(e,t,n,i){var s=this.drag_item_home(e),o="draghome dragitemhomes"+e+" group"+i,u=''+n+'',a='
    '+n+"
    ";s===null?t?r.append(u):n!==""&&r.append(a):(t?r.insert(u,s):n!==""&&r.insert(a,s),s.remove(!0));var f=r.one(".dragitemhomes"+e);f!==null&&(f.setData("groupno",i),f.setData("dragitemno",e))},drag_item_home:function(e){return r.one(".dragitemhomes"+e)},get_classname_numeric_suffix:function(e,t){var n=e.getAttribute("class");if(n!==""){var r=n.split(" ");for(var i=0;i0)o=this.doc.clone_new_drag_item(e,n),e++,this.get("readonly")||this.doc.draggable_for_question(o,i,r),u--}},this),this.reposition_drags_for_question(),this.get("readonly")||(this.doc.drop_zones().set("tabIndex",0),this.doc.drop_zones().each(function(e){e.on("dragchange",this.drop_zone_key_press,this)},this)),M.util.js_complete(this.pendingid)},drop_zone_key_press:function(e){switch(e.direction){case"next":this.place_next_drag_in(e.target);break;case"previous":this.place_previous_drag_in(e.target);break;case"remove":this.remove_drag_from_drop(e.target)}e.preventDefault(),this.reposition_drags_for_question()}, +place_next_drag_in:function(e){this.search_for_unplaced_drop_choice(e,1)},place_previous_drag_in:function(e){this.search_for_unplaced_drop_choice(e,-1)},search_for_unplaced_drop_choice:function(e,t){var n,r=this.current_drag_in_drop(e);if(""===r)if(t===1)n=1;else{n=1;var i=e.getData("group");this.doc.drag_items_in_group(i).each(function(e){n=Math.max(n,e.getData("choice"))},this)}else n=+r+t;var s;do{if(this.get_choices_for_drop(n,e).size()===0){this.remove_drag_from_drop(e);return}s=this.get_unplaced_choice_for_drop(n,e),n+=t}while(s===null);this.place_drag_in_drop(s,e)},current_drag_in_drop:function(t){var n=t.getData("inputid"),r=e.one("input#"+n);return r.get("value")},remove_drag_from_drop:function(e){this.place_drag_in_drop(null,e)},place_drag_in_drop:function(t,n){var r=n.getData("inputid"),i=e.one("input#"+r);t!==null?i.set("value",t.getData("choice")):i.set("value","")},reposition_drags_for_question:function(){this.doc.drag_items().removeClass("placed"),this.doc.drag_items().each(function(e){e.dd!==undefined&&e.dd.detachAll("drag:start")},this),this.doc.drop_zones().each(function(e){var t=e.getData("xy");e.setXY(this.convert_to_window_xy(t));var n="input#"+e.getData("inputid"),r=this.doc.top_node().one(n),i=r.get("value");if(i!==""){var s=this.get_unplaced_choice_for_drop(i,e);s!==null&&(s.setXY(e.getXY()),s.addClass("placed"),s.dd!==undefined&&s.dd.once("drag:start",function(e,t){t.set("value",""),e.target.get("node").removeClass("placed")},this,r))}},this),this.doc.drag_items().each(function(e){if(!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")){var t=this.doc.drag_item_home(e.getData("dragitemno"));e.setXY(t.getXY())}},this)},get_choices_for_drop:function(e,t){var n=t.getData("group");return this.doc.top_node().all("div.dragitemgroup"+n+" .choice"+e+".drag")},get_unplaced_choice_for_drop:function(e,t){var n=this.get_choices_for_drop(e,t),r=null;return n.some(function(e){return!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")?(r=e,!0):!1}),r},init_drops:function(){var t=this.doc.top_node().one("div.dropzones"),n={};for(var r=1;r<=8;r++){var i=e.Node.create('
    ');t.append(i),n[r]=i}var s=function(e){var t=e.drag.get("node"),n=e.drop.get("node");Number(n.getData("group"))===t.getData("group")&&this.place_drag_in_drop(t,n)};for(var o in this.get("drops")){var u=this.get("drops")[o],a="dropzone group"+u.group+" place"+o,f=u.text.replace('"','"'),l='
     
    ',c=e.Node.create(l);n[u.group].append(c),c.setStyles({opacity:.5}),c.setData("xy",u.xy),c.setData("place",o),c.setData("inputid",u.fieldname.replace(":","_")),c.setData("group",u.group);var h=new e.DD.Drop({node:c,groups:[u.group]});h.on("drop:hit",s,this)}}},{NAME:i,ATTRS:{}}),e.Event.define("dragchange",{_event:e.UA.webkit||e.UA.ie?"keydown":"keypress",_keys:{32:"next",37:"previous",38:"previous",39:"next",40:"next",27:"remove"},_keyHandler:function(e,t){this._keys[e.keyCode]&&(e.direction=this._keys[e.keyCode],t.fire(e))},on:function(e,t,n){t._detacher=e.on(this._event,this._keyHandler,this,n)}}),M.qtype_ddimageortext.init_question=function(e){return new s(e)}},"@VERSION@",{requires:["node","dd","dd-drop","dd-constrain"]}); diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js index 10bacdda793..60417571ffa 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js @@ -250,14 +250,17 @@ var DDIMAGEORTEXT_QUESTION = function() { * This is the code for question rendering. */ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { + pendingid: '', initializer : function() { + this.pendingid = 'qtype_ddimageortext-' + Math.random().toString(36).slice(2); // Random string. + M.util.js_pending(this.pendingid); this.doc = this.doc_structure(this); this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); this.doc.bg_img().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); - Y.later(500, this, this.reposition_drags_for_question, [], true); + Y.later(500, this, this.reposition_drags_for_question, [pendingid], true); }, create_all_drag_and_drops : function () { this.init_drops(); @@ -293,6 +296,7 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { v.on('dragchange', this.drop_zone_key_press, this); }, this); } + M.util.js_complete(this.pendingid); }, drop_zone_key_press : function (e) { switch (e.direction) { diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js index ec97e7b75aa..e8722250900 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js @@ -24,9 +24,12 @@ var DDIMAGEORTEXT_FORM = function() { }; Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { + pendingid: '', fp : null, initializer : function() { + this.pendingid = 'qtype_ddimageortext-form-' + Math.random().toString(36).slice(2); // Random string. + M.util.js_pending(this.pendingid); this.fp = this.file_pickers(); var tn = Y.one(this.get('topnode')); tn.one('div.fcontainer').append('
    ' + diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js index eba956ab617..c5fdf05f1d8 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js @@ -1,2 +1,2 @@ -YUI.add("moodle-qtype_ddimageortext-form",function(e,t){var n="moodle-qtype_ddimageortext-form",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,M.qtype_ddimageortext.dd_base_class,{fp:null,initializer:function(){this.fp=this.file_pickers();var t=e.one(this.get("topnode"));t.one("div.fcontainer").append('
    '),this.doc=this.doc_structure(this),this.draw_dd_area()},draw_dd_area:function(){var t=this.fp.file("bgimage").href;this.stop_selector_events(),this.set_options_for_drag_item_selectors();if(t!==null){this.doc.load_bg_img(t),this.load_drag_homes();var n=new e.DD.Drop({node:this.doc.bg_img()});n.on("drop:hit",function(e){e.drag.get("node").setData("gooddrop",!0)}),this.afterimageloaddone=!1,this.doc.bg_img().on("load",this.constrain_image_size,this,"bgimage"),this.doc.drag_item_homes().on("load",this.constrain_image_size,this,"dragimage"),this.doc.bg_img().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded),this.doc.drag_item_homes().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded)}else this.setup_form_events();this.update_visibility_of_file_pickers()},after_all_images_loaded:function(){this.update_padding_sizes_all(),this.update_drag_instances(),this.reposition_drags_for_form(),this.set_options_for_drag_item_selectors(),this.setup_form_events(),e.later(500,this,this.reposition_drags_for_form,[],!0)},constrain_image_size:function(e,t){var n=this.get("maxsizes")[t],r=Math.max(e.target.get("width")/n.width,e.target.get("height")/n.height);r>1&&e.target.set("width",Math.floor(e.target.get("width")/r)),e.target.addClass("constrained"),e.target.detach("load",this.constrain_image_size)},load_drag_homes:function(){for(var e=0;e'+t[u]+"";s.append(a);var f=s.one('option[value="'+u+'"]');if(u===+o)f.set("selected",!0);else if(u!==0){var l=e.one("#id_drags_"+(u-1)+"_infinite");l&&!l.get("checked")&&e.all("fieldset#id_dropzoneheader select").some(function(e){return Number(e.get("value"))===u?(f.set("disabled",!0),!0):!1},this)}}}},stop_selector_events:function(){e.all("fieldset#id_dropzoneheader select").detachAll()},setup_form_events:function(){e.all("fieldset#id_dropzoneheader input").on("blur",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=[this.form.get_form_value("drops",[n,"xleft"]),this.form.get_form_value("drops",[n,"ytop"])],i=this.constrain_xy(n,r);this.form.set_form_value("drops",[n,"xleft"],i[0]),this.form.set_form_value("drops",[n,"ytop"],i[1])},this),e.all("fieldset#id_dropzoneheader select").on("change",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=this.doc.drag_item(n);r!==null&&r.remove(!0),this.draw_dd_area()},this);for(var t=0;t
    '),this.doc=this.doc_structure(this),this.draw_dd_area()},draw_dd_area:function(){var t=this.fp.file("bgimage").href;this.stop_selector_events(),this.set_options_for_drag_item_selectors();if(t!==null){this.doc.load_bg_img(t),this.load_drag_homes();var n=new e.DD.Drop({node:this.doc.bg_img()});n.on("drop:hit",function(e){e.drag.get("node").setData("gooddrop",!0)}),this.afterimageloaddone=!1,this.doc.bg_img().on("load",this.constrain_image_size,this,"bgimage"),this.doc.drag_item_homes().on("load",this.constrain_image_size,this,"dragimage"),this.doc.bg_img().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded),this.doc.drag_item_homes().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded)}else this.setup_form_events();this.update_visibility_of_file_pickers()},after_all_images_loaded:function(){this.update_padding_sizes_all(),this.update_drag_instances(),this.reposition_drags_for_form(),this.set_options_for_drag_item_selectors(),this.setup_form_events(),e.later(500,this,this.reposition_drags_for_form,[],!0)},constrain_image_size:function(e,t){var n=this.get("maxsizes")[t],r=Math.max(e.target.get("width")/n.width,e.target.get("height")/n.height);r>1&&e.target.set("width",Math.floor(e.target.get("width")/r)),e.target.addClass("constrained"),e.target.detach("load",this.constrain_image_size)},load_drag_homes:function(){for(var e=0;e'+t[u]+"";s.append(a);var f=s.one('option[value="'+u+'"]');if(u===+o)f.set("selected",!0);else if(u!==0){var l=e.one("#id_drags_"+(u-1)+"_infinite");l&&!l.get("checked")&&e.all("fieldset#id_dropzoneheader select").some(function(e){return Number(e.get("value"))===u?(f.set("disabled",!0),!0):!1},this)}}}},stop_selector_events:function(){e.all("fieldset#id_dropzoneheader select").detachAll()},setup_form_events:function(){e.all("fieldset#id_dropzoneheader input").on("blur",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=[this.form.get_form_value("drops",[n,"xleft"]),this.form.get_form_value("drops",[n,"ytop"])],i=this.constrain_xy(n,r);this.form.set_form_value("drops",[n,"xleft"],i[0]),this.form.set_form_value("drops",[n,"ytop"],i[1])},this),e.all("fieldset#id_dropzoneheader select").on("change",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=this.doc.drag_item(n);r!==null&&r.remove(!0),this.draw_dd_area()},this);for(var t=0;t
    ' + diff --git a/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js b/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js index d22e07c7e41..f5b312c8df7 100644 --- a/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js +++ b/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js @@ -248,14 +248,17 @@ var DDIMAGEORTEXT_QUESTION = function() { * This is the code for question rendering. */ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { + pendingid: '', initializer : function() { + this.pendingid = 'qtype_ddimageortext-' + Math.random().toString(36).slice(2); // Random string. + M.util.js_pending(this.pendingid); this.doc = this.doc_structure(this); this.poll_for_image_load(null, false, 0, this.create_all_drag_and_drops); this.doc.bg_img().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); - Y.later(500, this, this.reposition_drags_for_question, [], true); + Y.later(500, this, this.reposition_drags_for_question, [pendingid], true); }, create_all_drag_and_drops : function () { this.init_drops(); @@ -291,6 +294,7 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { v.on('dragchange', this.drop_zone_key_press, this); }, this); } + M.util.js_complete(this.pendingid); }, drop_zone_key_press : function (e) { switch (e.direction) { diff --git a/question/type/ddimageortext/yui/src/form/js/form.js b/question/type/ddimageortext/yui/src/form/js/form.js index bbd94130264..a786dca647f 100644 --- a/question/type/ddimageortext/yui/src/form/js/form.js +++ b/question/type/ddimageortext/yui/src/form/js/form.js @@ -22,9 +22,12 @@ var DDIMAGEORTEXT_FORM = function() { }; Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { + pendingid: '', fp : null, initializer : function() { + this.pendingid = 'qtype_ddimageortext-form-' + Math.random().toString(36).slice(2); // Random string. + M.util.js_pending(this.pendingid); this.fp = this.file_pickers(); var tn = Y.one(this.get('topnode')); tn.one('div.fcontainer').append('
    ' + From d804067d09caa2e88f49456e0c008973532f259c Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 20 Feb 2015 13:46:54 +0000 Subject: [PATCH 198/208] MDL-47494 ddimageortext: Fix dd qtype Behat tests to not use the generic type step. #14895 --- .../tests/behat/behat_qtype_ddimageortext.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/tests/behat/behat_qtype_ddimageortext.php b/question/type/ddimageortext/tests/behat/behat_qtype_ddimageortext.php index a1a5239cd15..b5b3e947d79 100644 --- a/question/type/ddimageortext/tests/behat/behat_qtype_ddimageortext.php +++ b/question/type/ddimageortext/tests/behat/behat_qtype_ddimageortext.php @@ -77,7 +77,12 @@ class behat_qtype_ddimageortext extends behat_base { * @Given /^I type "(?P[^"]*)" on place "(?P\d+)" in the drag and drop onto image question$/ */ public function i_type_on_place_in_the_drag_and_drop_onto_image_question($keys, $placenumber) { - $generalcontext = behat_context_helper::get('behat_general'); - $generalcontext->i_type_into_the($keys, $this->drop_xpath($placenumber), 'xpath_element'); + $node = $this->get_selected_node('xpath_element', $this->drop_xpath($placenumber)); + $this->ensure_node_is_visible($node); + foreach (str_split($keys) as $key) { + $node->keyDown($key); + $node->keyPress($key); + $node->keyUp($key); + } } } From c5091dc01ffd14c39aea36fc7ff1548c54a4a6ac Mon Sep 17 00:00:00 2001 From: "pau.ferrer-ocana" Date: Mon, 16 Mar 2015 10:29:10 +0100 Subject: [PATCH 199/208] MDL-47494 ddimageortext: Solve error when showing more than one question in the same page --- .../moodle-qtype_ddimageortext-dd-debug.js | 2 +- .../moodle-qtype_ddimageortext-dd-min.js | 2 +- .../moodle-qtype_ddimageortext-dd.js | 2 +- .../ddimageortext/yui/src/ddimageortext/js/ddimageortext.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js index 60417571ffa..3818881f000 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js @@ -260,7 +260,7 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { false, 0, this.create_all_drag_and_drops); this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); - Y.later(500, this, this.reposition_drags_for_question, [pendingid], true); + Y.later(500, this, this.reposition_drags_for_question, [this.pendingid], true); }, create_all_drag_and_drops : function () { this.init_drops(); diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js index 92f8b43654c..845933c9d62 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js @@ -1,2 +1,2 @@ -YUI.add("moodle-qtype_ddimageortext-dd",function(e,t){var n="ddimageortext_dd",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,e.Base,{doc:null,polltimer:null,afterimageloaddone:!1,poll_for_image_load:function(t,n,r,i){if(this.afterimageloaddone)return;var s=this.doc.bg_img().get("complete");n&&(s=s&&this.doc.bg_img().hasClass("constrained"));var o=!this.doc.drag_item_homes().some(function(e){if(e.get("tagName")!=="IMG")return!1;var t=e.get("complete");return n&&(t=t&&e.hasClass("constrained")),!t});if(s&&o)this.polltimer!==null&&(this.polltimer.cancel(),this.polltimer=null),this.doc.drag_item_homes().detach("load",this.poll_for_image_load),this.doc.bg_img().detach("load",this.poll_for_image_load),r!==0?e.later(r,this,i):i.call(this),this.afterimageloaddone=!0;else if(this.polltimer===null){var u=[null,n,r,i];this.polltimer=e.later(1e3,this,this.poll_for_image_load,u,!0)}},doc_structure:function(t){var n=e.one(this.get("topnode")),r=n.one("div.dragitems"),i=n.one("div.droparea");return{top_node:function(){return n},drag_items:function(){return r.all(".drag")},drop_zones:function(){return n.all("div.dropzones div.dropzone")},drop_zone_group:function(e){return n.all("div.dropzones div.group"+e)},drag_items_cloned_from:function(e){return r.all(".dragitems"+e)},drag_item:function(e){return r.one(".draginstance"+e)},drag_items_in_group:function(e){return r.all(".drag.group"+e)},drag_item_homes:function(){return r.all(".draghome")},bg_img:function(){return n.one(".dropbackground")},load_bg_img:function(e){i.setContent(''),this.bg_img().on("load",this.on_image_load,this,"bg_image")},add_or_update_drag_item_home:function(e,t,n,i){var s=this.drag_item_home(e),o="draghome dragitemhomes"+e+" group"+i,u=''+n+'',a='
    '+n+"
    ";s===null?t?r.append(u):n!==""&&r.append(a):(t?r.insert(u,s):n!==""&&r.insert(a,s),s.remove(!0));var f=r.one(".dragitemhomes"+e);f!==null&&(f.setData("groupno",i),f.setData("dragitemno",e))},drag_item_home:function(e){return r.one(".dragitemhomes"+e)},get_classname_numeric_suffix:function(e,t){var n=e.getAttribute("class");if(n!==""){var r=n.split(" ");for(var i=0;i0)o=this.doc.clone_new_drag_item(e,n),e++,this.get("readonly")||this.doc.draggable_for_question(o,i,r),u--}},this),this.reposition_drags_for_question(),this.get("readonly")||(this.doc.drop_zones().set("tabIndex",0),this.doc.drop_zones().each(function(e){e.on("dragchange",this.drop_zone_key_press,this)},this)),M.util.js_complete(this.pendingid)},drop_zone_key_press:function(e){switch(e.direction){case"next":this.place_next_drag_in(e.target);break;case"previous":this.place_previous_drag_in(e.target);break;case"remove":this.remove_drag_from_drop(e.target)}e.preventDefault(),this.reposition_drags_for_question()}, +YUI.add("moodle-qtype_ddimageortext-dd",function(e,t){var n="ddimageortext_dd",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,e.Base,{doc:null,polltimer:null,afterimageloaddone:!1,poll_for_image_load:function(t,n,r,i){if(this.afterimageloaddone)return;var s=this.doc.bg_img().get("complete");n&&(s=s&&this.doc.bg_img().hasClass("constrained"));var o=!this.doc.drag_item_homes().some(function(e){if(e.get("tagName")!=="IMG")return!1;var t=e.get("complete");return n&&(t=t&&e.hasClass("constrained")),!t});if(s&&o)this.polltimer!==null&&(this.polltimer.cancel(),this.polltimer=null),this.doc.drag_item_homes().detach("load",this.poll_for_image_load),this.doc.bg_img().detach("load",this.poll_for_image_load),r!==0?e.later(r,this,i):i.call(this),this.afterimageloaddone=!0;else if(this.polltimer===null){var u=[null,n,r,i];this.polltimer=e.later(1e3,this,this.poll_for_image_load,u,!0)}},doc_structure:function(t){var n=e.one(this.get("topnode")),r=n.one("div.dragitems"),i=n.one("div.droparea");return{top_node:function(){return n},drag_items:function(){return r.all(".drag")},drop_zones:function(){return n.all("div.dropzones div.dropzone")},drop_zone_group:function(e){return n.all("div.dropzones div.group"+e)},drag_items_cloned_from:function(e){return r.all(".dragitems"+e)},drag_item:function(e){return r.one(".draginstance"+e)},drag_items_in_group:function(e){return r.all(".drag.group"+e)},drag_item_homes:function(){return r.all(".draghome")},bg_img:function(){return n.one(".dropbackground")},load_bg_img:function(e){i.setContent(''),this.bg_img().on("load",this.on_image_load,this,"bg_image")},add_or_update_drag_item_home:function(e,t,n,i){var s=this.drag_item_home(e),o="draghome dragitemhomes"+e+" group"+i,u=''+n+'',a='
    '+n+"
    ";s===null?t?r.append(u):n!==""&&r.append(a):(t?r.insert(u,s):n!==""&&r.insert(a,s),s.remove(!0));var f=r.one(".dragitemhomes"+e);f!==null&&(f.setData("groupno",i),f.setData("dragitemno",e))},drag_item_home:function(e){return r.one(".dragitemhomes"+e)},get_classname_numeric_suffix:function(e,t){var n=e.getAttribute("class");if(n!==""){var r=n.split(" ");for(var i=0;i0)o=this.doc.clone_new_drag_item(e,n),e++,this.get("readonly")||this.doc.draggable_for_question(o,i,r),u--}},this),this.reposition_drags_for_question(),this.get("readonly")||(this.doc.drop_zones().set("tabIndex",0),this.doc.drop_zones().each(function(e){e.on("dragchange",this.drop_zone_key_press,this)},this)),M.util.js_complete(this.pendingid)},drop_zone_key_press:function(e){switch(e.direction){case"next":this.place_next_drag_in(e.target);break;case"previous":this.place_previous_drag_in(e.target);break;case"remove":this.remove_drag_from_drop(e.target)}e.preventDefault(),this.reposition_drags_for_question()}, place_next_drag_in:function(e){this.search_for_unplaced_drop_choice(e,1)},place_previous_drag_in:function(e){this.search_for_unplaced_drop_choice(e,-1)},search_for_unplaced_drop_choice:function(e,t){var n,r=this.current_drag_in_drop(e);if(""===r)if(t===1)n=1;else{n=1;var i=e.getData("group");this.doc.drag_items_in_group(i).each(function(e){n=Math.max(n,e.getData("choice"))},this)}else n=+r+t;var s;do{if(this.get_choices_for_drop(n,e).size()===0){this.remove_drag_from_drop(e);return}s=this.get_unplaced_choice_for_drop(n,e),n+=t}while(s===null);this.place_drag_in_drop(s,e)},current_drag_in_drop:function(t){var n=t.getData("inputid"),r=e.one("input#"+n);return r.get("value")},remove_drag_from_drop:function(e){this.place_drag_in_drop(null,e)},place_drag_in_drop:function(t,n){var r=n.getData("inputid"),i=e.one("input#"+r);t!==null?i.set("value",t.getData("choice")):i.set("value","")},reposition_drags_for_question:function(){this.doc.drag_items().removeClass("placed"),this.doc.drag_items().each(function(e){e.dd!==undefined&&e.dd.detachAll("drag:start")},this),this.doc.drop_zones().each(function(e){var t=e.getData("xy");e.setXY(this.convert_to_window_xy(t));var n="input#"+e.getData("inputid"),r=this.doc.top_node().one(n),i=r.get("value");if(i!==""){var s=this.get_unplaced_choice_for_drop(i,e);s!==null&&(s.setXY(e.getXY()),s.addClass("placed"),s.dd!==undefined&&s.dd.once("drag:start",function(e,t){t.set("value",""),e.target.get("node").removeClass("placed")},this,r))}},this),this.doc.drag_items().each(function(e){if(!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")){var t=this.doc.drag_item_home(e.getData("dragitemno"));e.setXY(t.getXY())}},this)},get_choices_for_drop:function(e,t){var n=t.getData("group");return this.doc.top_node().all("div.dragitemgroup"+n+" .choice"+e+".drag")},get_unplaced_choice_for_drop:function(e,t){var n=this.get_choices_for_drop(e,t),r=null;return n.some(function(e){return!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")?(r=e,!0):!1}),r},init_drops:function(){var t=this.doc.top_node().one("div.dropzones"),n={};for(var r=1;r<=8;r++){var i=e.Node.create('
    ');t.append(i),n[r]=i}var s=function(e){var t=e.drag.get("node"),n=e.drop.get("node");Number(n.getData("group"))===t.getData("group")&&this.place_drag_in_drop(t,n)};for(var o in this.get("drops")){var u=this.get("drops")[o],a="dropzone group"+u.group+" place"+o,f=u.text.replace('"','"'),l='
     
    ',c=e.Node.create(l);n[u.group].append(c),c.setStyles({opacity:.5}),c.setData("xy",u.xy),c.setData("place",o),c.setData("inputid",u.fieldname.replace(":","_")),c.setData("group",u.group);var h=new e.DD.Drop({node:c,groups:[u.group]});h.on("drop:hit",s,this)}}},{NAME:i,ATTRS:{}}),e.Event.define("dragchange",{_event:e.UA.webkit||e.UA.ie?"keydown":"keypress",_keys:{32:"next",37:"previous",38:"previous",39:"next",40:"next",27:"remove"},_keyHandler:function(e,t){this._keys[e.keyCode]&&(e.direction=this._keys[e.keyCode],t.fire(e))},on:function(e,t,n){t._detacher=e.on(this._event,this._keyHandler,this,n)}}),M.qtype_ddimageortext.init_question=function(e){return new s(e)}},"@VERSION@",{requires:["node","dd","dd-drop","dd-constrain"]}); diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js index 60417571ffa..3818881f000 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js @@ -260,7 +260,7 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { false, 0, this.create_all_drag_and_drops); this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); - Y.later(500, this, this.reposition_drags_for_question, [pendingid], true); + Y.later(500, this, this.reposition_drags_for_question, [this.pendingid], true); }, create_all_drag_and_drops : function () { this.init_drops(); diff --git a/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js b/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js index f5b312c8df7..5741acbd5d7 100644 --- a/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js +++ b/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js @@ -258,7 +258,7 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { false, 0, this.create_all_drag_and_drops); this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, false, 0, this.create_all_drag_and_drops); - Y.later(500, this, this.reposition_drags_for_question, [pendingid], true); + Y.later(500, this, this.reposition_drags_for_question, [this.pendingid], true); }, create_all_drag_and_drops : function () { this.init_drops(); From 52b8f798a4e228cb41eaa78bcbe7058db8c79603 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 18 Mar 2015 13:28:41 +0000 Subject: [PATCH 200/208] MDL-47494 ddimageortext: Add outestssufficient marker. --- question/type/ddimageortext/version.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 1385dbd31db..18333e880c2 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -34,3 +34,5 @@ $plugin->release = '1.6 for Moodle 2.6+'; $plugin->dependencies = array( 'qtype_gapselect' => 2014111200, ); + +$plugin->outestssufficient = true; From 4aee9404329becfa5e6f380dee7c6cbf734b0be5 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 18 Mar 2015 13:56:54 +0000 Subject: [PATCH 201/208] MDL-47494 ddimageortext: Bump version for 1.7 release. --- question/type/ddimageortext/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 18333e880c2..1c2efe11000 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -24,12 +24,12 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2014111200; +$plugin->version = 2015031800; $plugin->requires = 2013101800; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.6 for Moodle 2.6+'; +$plugin->release = '1.7 for Moodle 2.6+'; $plugin->dependencies = array( 'qtype_gapselect' => 2014111200, From 2bf2e46ce338a7775ef3406a08c89c7c2e21976c Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 8 May 2015 12:21:36 +0100 Subject: [PATCH 202/208] MDL-47494 ddimageortext: ddimageortext: statistics failed when drag items were grouped #51569 The error in classify_response caused a fatal error in the quiz statistics report. Correctly testing this required some updates to the unit tests to correctly replicate what happens when a question is attempted. --- question/type/ddimageortext/questionbase.php | 6 +- .../type/ddimageortext/questiontypebase.php | 6 + question/type/ddimageortext/tests/helper.php | 11 +- .../ddimageortext/tests/question_test.php | 16 +-- .../ddimageortext/tests/walkthrough_test.php | 116 +++++++++--------- question/type/ddimageortext/version.php | 4 +- 6 files changed, 83 insertions(+), 76 deletions(-) diff --git a/question/type/ddimageortext/questionbase.php b/question/type/ddimageortext/questionbase.php index 38b1a96eadd..68fa585a9b0 100644 --- a/question/type/ddimageortext/questionbase.php +++ b/question/type/ddimageortext/questionbase.php @@ -118,8 +118,8 @@ class qtype_ddtoimage_question_base extends qtype_gapselect_question_base { } $fieldname = $this->field($placeno); - $choiceno = $this->choiceorder[$group][$response[$fieldname]]; - $choice = $this->choices[$group][$choiceno]; + $choicekey = $this->choiceorder[$group][$response[$fieldname]]; + $choice = $this->choices[$group][$choicekey]; $correct = $this->get_right_choice_for($placeno) == $response[$fieldname]; if ($correct) { @@ -127,7 +127,7 @@ class qtype_ddtoimage_question_base extends qtype_gapselect_question_base { } else { $grade = 0; } - $parts[$placeno] = new question_classified_response($choiceno, $choice->summarise(), $grade); + $parts[$placeno] = new question_classified_response($choice->no, $choice->summarise(), $grade); } return $parts; } diff --git a/question/type/ddimageortext/questiontypebase.php b/question/type/ddimageortext/questiontypebase.php index 2512852da0d..2c2f9e0e77f 100644 --- a/question/type/ddimageortext/questiontypebase.php +++ b/question/type/ddimageortext/questiontypebase.php @@ -63,6 +63,12 @@ class qtype_ddtoimage_base extends question_type { $choiceindexmap = array(); // Store the choices in arrays by group. + // This code is weird. The first choice in each group gets key 1 in the + // $question->choices[$choice->choice_group()] array, and the others get + // key $choice->no. Therefore you need to think carefully whether you + // are using the key, or $choice->no. This is presumably a mistake, but + // one that is now essentially un-fixable, since many questions of this + // type have been attempted, and theys keys get stored in the attempt data. foreach ($questiondata->options->drags as $dragdata) { $choice = $this->make_choice($dragdata); diff --git a/question/type/ddimageortext/tests/helper.php b/question/type/ddimageortext/tests/helper.php index 864b5119d66..2ecf449454f 100644 --- a/question/type/ddimageortext/tests/helper.php +++ b/question/type/ddimageortext/tests/helper.php @@ -58,8 +58,8 @@ class qtype_ddimageortext_test_helper extends question_test_helper { $dd->choices = $this->make_choice_structure(array( new qtype_ddimageortext_drag_item('quick', 1, 1), new qtype_ddimageortext_drag_item('fox', 2, 1), - new qtype_ddimageortext_drag_item('lazy', 1, 2), - new qtype_ddimageortext_drag_item('dog', 2, 2) + new qtype_ddimageortext_drag_item('lazy', 3, 2), + new qtype_ddimageortext_drag_item('dog', 4, 2) )); @@ -69,7 +69,7 @@ class qtype_ddimageortext_test_helper extends question_test_helper { new qtype_ddimageortext_drop_zone('', 3, 2), new qtype_ddimageortext_drop_zone('', 4, 2) )); - $dd->rightchoices = array(1 => 1, 2 => 2, 3 => 1, 4 => 2); + $dd->rightchoices = array(1 => 1, 2 => 2, 3 => 1, 4 => 4); return $dd; } @@ -78,9 +78,10 @@ class qtype_ddimageortext_test_helper extends question_test_helper { $choicestructure = array(); foreach ($choices as $choice) { if (!isset($choicestructure[$choice->group])) { - $choicestructure[$choice->group] = array(); + $choicestructure[$choice->group][1] = $choice; + } else { + $choicestructure[$choice->group][$choice->no] = $choice; } - $choicestructure[$choice->group][$choice->no] = $choice; } return $choicestructure; } diff --git a/question/type/ddimageortext/tests/question_test.php b/question/type/ddimageortext/tests/question_test.php index cc3256d4130..08e64b1aa77 100644 --- a/question/type/ddimageortext/tests/question_test.php +++ b/question/type/ddimageortext/tests/question_test.php @@ -43,8 +43,8 @@ class qtype_ddimageortext_question_test extends basic_testcase { $this->assertEquals('The quick brown fox jumped over the lazy dog.; '. '[[Drop zone 1]] -> {1. quick / 2. fox}; '. '[[Drop zone 2]] -> {1. quick / 2. fox}; '. - '[[Drop zone 3]] -> {1. lazy / 2. dog}; '. - '[[Drop zone 4]] -> {1. lazy / 2. dog}', + '[[Drop zone 3]] -> {3. lazy / 4. dog}; '. + '[[Drop zone 4]] -> {3. lazy / 4. dog}', $dd->get_question_summary()); } @@ -66,8 +66,8 @@ class qtype_ddimageortext_question_test extends basic_testcase { $this->assertEquals('Drop zone 1 -> {1. quick} '. 'Drop zone 2 -> {1. quick} '. - 'Drop zone 3 -> {1. lazy} '. - 'Drop zone 4 -> {1. lazy}', + 'Drop zone 3 -> {3. lazy} '. + 'Drop zone 4 -> {3. lazy}', $dd->summarise_response(array('p1' => '1', 'p2' => '1', 'p3' => '1', 'p4' => '1'))); } @@ -256,14 +256,14 @@ class qtype_ddimageortext_question_test extends basic_testcase { $this->assertEquals(array( 1 => new question_classified_response(1, '1. quick', 1), 2 => new question_classified_response(2, '2. fox', 1), - 3 => new question_classified_response(1, '1. lazy', 1), - 4 => new question_classified_response(2, '2. dog', 1) + 3 => new question_classified_response(3, '3. lazy', 1), + 4 => new question_classified_response(4, '4. dog', 1) ), $dd->classify_response(array('p1' => '1', 'p2' => '2', 'p3' => '1', 'p4' => '2'))); $this->assertEquals(array( 1 => question_classified_response::no_response(), 2 => new question_classified_response(1, '1. quick', 0), - 3 => new question_classified_response(2, '2. dog', 0), - 4 => new question_classified_response(2, '2. dog', 1) + 3 => new question_classified_response(4, '4. dog', 0), + 4 => new question_classified_response(4, '4. dog', 1) ), $dd->classify_response(array('p1' => '', 'p2' => '1', 'p3' => '2', 'p4' => '2'))); } } diff --git a/question/type/ddimageortext/tests/walkthrough_test.php b/question/type/ddimageortext/tests/walkthrough_test.php index cc392bcb29a..40b791037a3 100644 --- a/question/type/ddimageortext/tests/walkthrough_test.php +++ b/question/type/ddimageortext/tests/walkthrough_test.php @@ -73,8 +73,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( @@ -97,8 +97,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 2), $this->get_contains_hidden_expectation( @@ -121,8 +121,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 2), $this->get_contains_hidden_expectation( @@ -146,8 +146,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', '2'), $this->get_contains_hidden_expectation( @@ -172,8 +172,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', '1'), $this->get_contains_hidden_expectation( @@ -208,8 +208,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( @@ -229,8 +229,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 2), $this->get_contains_hidden_expectation( @@ -251,8 +251,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( @@ -274,8 +274,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( @@ -310,8 +310,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( @@ -333,8 +333,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', ''), $this->get_contains_hidden_expectation( @@ -356,8 +356,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2)); + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2)); } public function test_deferred_feedback_partial_answer() { @@ -373,8 +373,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( @@ -395,8 +395,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( @@ -417,8 +417,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_partcorrect_expectation()); } @@ -443,8 +443,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( @@ -469,8 +469,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), @@ -505,8 +505,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( @@ -532,8 +532,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), @@ -561,8 +561,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( @@ -588,8 +588,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 1), $this->get_contains_hidden_expectation( @@ -625,8 +625,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( @@ -652,8 +652,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_correct_expectation(), $this->get_no_hint_visible_expectation()); @@ -686,8 +686,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( @@ -714,8 +714,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->check_current_output( $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_partcorrect_expectation(), $this->get_no_hint_visible_expectation()); @@ -747,8 +747,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_marked_out_of_summary(), $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1'), $this->get_contains_hidden_expectation( @@ -773,8 +773,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_marked_out_of_summary(), $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_submit_button_expectation(false), $this->get_contains_hint_expectation('This is the first hint')); @@ -789,8 +789,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_marked_out_of_summary(), $this->get_contains_drag_image_home_expectation(1, 1, 1), $this->get_contains_drag_image_home_expectation(2, 2, 1), - $this->get_contains_drag_image_home_expectation(1, 1, 2), - $this->get_contains_drag_image_home_expectation(2, 2, 2), + $this->get_contains_drag_image_home_expectation(3, 1, 2), + $this->get_contains_drag_image_home_expectation(4, 2, 2), $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p1', 0), $this->get_contains_hidden_expectation( @@ -855,8 +855,8 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->displayoptions->rightanswer = question_display_options::VISIBLE; $this->assertEquals('Drop zone 1 -> {1. quick} '. 'Drop zone 2 -> {2. fox} '. - 'Drop zone 3 -> {1. lazy} '. - 'Drop zone 4 -> {2. dog}', + 'Drop zone 3 -> {3. lazy} '. + 'Drop zone 4 -> {4. dog}', $dd->get_right_answer_summary()); $this->check_current_state(question_state::$gradedright); $this->check_current_mark(3); diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 1c2efe11000..18333e880c2 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -24,12 +24,12 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2015031800; +$plugin->version = 2014111200; $plugin->requires = 2013101800; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.7 for Moodle 2.6+'; +$plugin->release = '1.6 for Moodle 2.6+'; $plugin->dependencies = array( 'qtype_gapselect' => 2014111200, From 9b74b3b540d8e7d2928d347cf37a16548eaf9a44 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 8 May 2015 16:41:25 +0100 Subject: [PATCH 203/208] MDL-47494 ddimageortext: Fix Behat tests for 2.9. --- .../type/ddimageortext/tests/behat/backup_and_restore.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/question/type/ddimageortext/tests/behat/backup_and_restore.feature b/question/type/ddimageortext/tests/behat/backup_and_restore.feature index 8384e97adfa..f1115688e0d 100644 --- a/question/type/ddimageortext/tests/behat/backup_and_restore.feature +++ b/question/type/ddimageortext/tests/behat/backup_and_restore.feature @@ -20,6 +20,7 @@ Feature: Test duplicating a quiz containing a drag and drop onto image question And quiz "Test quiz" contains the following questions: | Drag onto image | 1 | And I log in as "admin" + And I am on site homepage And I follow "Course 1" @javascript From 56f6628e9c6ead3652475169e3ae40da5b4fc937 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 11 May 2015 07:38:24 +0100 Subject: [PATCH 204/208] MDL-47494 ddimageortext: Bump version for 1.8 release. --- question/type/ddimageortext/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddimageortext/version.php b/question/type/ddimageortext/version.php index 18333e880c2..8ea598a72af 100644 --- a/question/type/ddimageortext/version.php +++ b/question/type/ddimageortext/version.php @@ -24,12 +24,12 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2014111200; +$plugin->version = 2015051000; $plugin->requires = 2013101800; $plugin->cron = 0; $plugin->component = 'qtype_ddimageortext'; $plugin->maturity = MATURITY_STABLE; -$plugin->release = '1.6 for Moodle 2.6+'; +$plugin->release = '1.8 for Moodle 2.6+'; $plugin->dependencies = array( 'qtype_gapselect' => 2014111200, From be1ce906b5032f29c6f4c2635961b8b1cfa45137 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 21 May 2015 15:58:55 +0100 Subject: [PATCH 205/208] MDL-47494 ddimageortext: Fix behat failures. --- question/type/ddimageortext/tests/behat/preview.feature | 2 ++ 1 file changed, 2 insertions(+) diff --git a/question/type/ddimageortext/tests/behat/preview.feature b/question/type/ddimageortext/tests/behat/preview.feature index 5fd5954229f..70061d224ee 100644 --- a/question/type/ddimageortext/tests/behat/preview.feature +++ b/question/type/ddimageortext/tests/behat/preview.feature @@ -40,6 +40,7 @@ Feature: Preview a drag-drop onto image question And I press "Submit and finish" Then the state of "Identify the features" question is shown as "Correct" And I should see "Mark 1.00 out of 1.00" + And I switch to the main window @javascript Scenario: Preview a question using the keyboard. @@ -56,3 +57,4 @@ Feature: Preview a drag-drop onto image question And I press "Submit and finish" Then the state of "Identify the features" question is shown as "Correct" And I should see "Mark 1.00 out of 1.00" + And I switch to the main window From 8f21a4fb12eee74322d334cb7e7301258ce05cdc Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 21 May 2015 15:59:03 +0100 Subject: [PATCH 206/208] MDL-47494 ddimageortext: Fix editing form javascript. --- .../moodle-qtype_ddimageortext-form-debug.js | 4 +++- .../moodle-qtype_ddimageortext-form-min.js | 4 ++-- .../moodle-qtype_ddimageortext-form.js | 4 +++- question/type/ddimageortext/yui/src/form/js/form.js | 4 +++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js index e8722250900..21affd05581 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-debug.js @@ -60,10 +60,11 @@ Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { .on('load', this.constrain_image_size, this, 'dragimage'); this.doc.bg_img().after('load', this.poll_for_image_load, this, true, 0, this.after_all_images_loaded); - this.doc.drag_item_homes() .after('load', this.poll_for_image_load, this, + this.doc.drag_item_homes().after('load', this.poll_for_image_load, this, true, 0, this.after_all_images_loaded); } else { this.setup_form_events(); + M.util.js_complete(this.pendingid); } this.update_visibility_of_file_pickers(); }, @@ -232,6 +233,7 @@ Y.extend(DDIMAGEORTEXT_FORM, M.qtype_ddimageortext.dd_base_class, { var draginstanceno = drag.getData('draginstanceno'); this.reposition_drag_for_form(draginstanceno); }, this); + M.util.js_complete(this.pendingid); }, reposition_drag_for_form : function (draginstanceno) { diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js index c5fdf05f1d8..198e5098468 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-form/moodle-qtype_ddimageortext-form-min.js @@ -1,2 +1,2 @@ -YUI.add("moodle-qtype_ddimageortext-form",function(e,t){var n="moodle-qtype_ddimageortext-form",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,M.qtype_ddimageortext.dd_base_class,{pendingid:"",fp:null,initializer:function(){this.pendingid="qtype_ddimageortext-form-"+Math.random().toString(36).slice(2),M.util.js_pending(this.pendingid),this.fp=this.file_pickers();var t=e.one(this.get("topnode"));t.one("div.fcontainer").append('
    '),this.doc=this.doc_structure(this),this.draw_dd_area()},draw_dd_area:function(){var t=this.fp.file("bgimage").href;this.stop_selector_events(),this.set_options_for_drag_item_selectors();if(t!==null){this.doc.load_bg_img(t),this.load_drag_homes();var n=new e.DD.Drop({node:this.doc.bg_img()});n.on("drop:hit",function(e){e.drag.get("node").setData("gooddrop",!0)}),this.afterimageloaddone=!1,this.doc.bg_img().on("load",this.constrain_image_size,this,"bgimage"),this.doc.drag_item_homes().on("load",this.constrain_image_size,this,"dragimage"),this.doc.bg_img().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded),this.doc.drag_item_homes().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded)}else this.setup_form_events();this.update_visibility_of_file_pickers()},after_all_images_loaded:function(){this.update_padding_sizes_all(),this.update_drag_instances(),this.reposition_drags_for_form(),this.set_options_for_drag_item_selectors(),this.setup_form_events(),e.later(500,this,this.reposition_drags_for_form,[],!0)},constrain_image_size:function(e,t){var n=this.get("maxsizes")[t],r=Math.max(e.target.get("width")/n.width,e.target.get("height")/n.height);r>1&&e.target.set("width",Math.floor(e.target.get("width")/r)),e.target.addClass("constrained"),e.target.detach("load",this.constrain_image_size)},load_drag_homes:function(){for(var e=0;e'+t[u]+"";s.append(a);var f=s.one('option[value="'+u+'"]');if(u===+o)f.set("selected",!0);else if(u!==0){var l=e.one("#id_drags_"+(u-1)+"_infinite");l&&!l.get("checked")&&e.all("fieldset#id_dropzoneheader select").some(function(e){return Number(e.get("value"))===u?(f.set("disabled",!0),!0):!1},this)}}}},stop_selector_events:function(){e.all("fieldset#id_dropzoneheader select").detachAll()},setup_form_events:function(){e.all("fieldset#id_dropzoneheader input").on("blur",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=[this.form.get_form_value("drops",[n,"xleft"]),this.form.get_form_value("drops",[n,"ytop"])],i=this.constrain_xy(n,r);this.form.set_form_value("drops",[n,"xleft"],i[0]),this.form.set_form_value("drops",[n,"ytop"],i[1])},this),e.all("fieldset#id_dropzoneheader select").on("change",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=this.doc.drag_item(n);r!==null&&r.remove(!0),this.draw_dd_area()},this);for(var t=0;t
    '),this.doc=this.doc_structure(this),this.draw_dd_area()},draw_dd_area:function(){var t=this.fp.file("bgimage").href;this.stop_selector_events(),this.set_options_for_drag_item_selectors();if(t!==null){this.doc.load_bg_img(t),this.load_drag_homes();var n=new e.DD.Drop({node:this.doc.bg_img()});n.on("drop:hit",function(e){e.drag.get("node").setData("gooddrop",!0)}),this.afterimageloaddone=!1,this.doc.bg_img().on("load",this.constrain_image_size,this,"bgimage"),this.doc.drag_item_homes().on("load",this.constrain_image_size,this,"dragimage"),this.doc.bg_img().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded),this.doc.drag_item_homes().after("load",this.poll_for_image_load,this,!0,0,this.after_all_images_loaded)}else this.setup_form_events(),M.util.js_complete(this.pendingid);this.update_visibility_of_file_pickers()},after_all_images_loaded:function(){this.update_padding_sizes_all(),this.update_drag_instances(),this.reposition_drags_for_form(),this.set_options_for_drag_item_selectors(),this.setup_form_events(),e.later(500,this,this.reposition_drags_for_form,[],!0)},constrain_image_size:function(e,t){var n=this.get("maxsizes")[t],r=Math.max(e.target.get("width")/n.width,e.target.get("height")/n.height);r>1&&e.target.set("width",Math.floor(e.target.get("width")/r)),e.target.addClass("constrained"),e.target.detach("load",this.constrain_image_size)},load_drag_homes:function(){for(var e=0;e'+t[u]+"";s.append(a);var f=s.one('option[value="'+u+'"]');if(u===+o)f.set("selected",!0);else if(u!==0){var l=e.one("#id_drags_"+(u-1)+"_infinite");l&&!l.get("checked")&&e.all("fieldset#id_dropzoneheader select").some(function(e){return Number(e.get("value"))===u?(f.set("disabled",!0),!0):!1},this)}}}},stop_selector_events:function(){e.all("fieldset#id_dropzoneheader select").detachAll()},setup_form_events:function(){e.all("fieldset#id_dropzoneheader input").on("blur",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=[this.form.get_form_value("drops",[n,"xleft"]),this.form.get_form_value("drops",[n,"ytop"])],i=this.constrain_xy(n,r);this.form.set_form_value("drops",[n,"xleft"],i[0]),this.form.set_form_value("drops",[n,"ytop"],i[1])},this),e.all("fieldset#id_dropzoneheader select").on("change",function(e){var t=e.target.getAttribute("name"),n=this.form.from_name_with_index(t).indexes[0],r=this.doc.drag_item(n);r!==null&&r.remove(!0),this.draw_dd_area()},this);for(var t=0;t Date: Fri, 12 Jun 2015 14:02:44 +0100 Subject: [PATCH 207/208] MDL-47494 ddimageortext: Fix drag and drop on Android touch devices. #85108 The initial suggestion for how to do this fix came from Davo Smith. --- .../moodle-qtype_ddimageortext-dd-debug.js | 40 ++++++++++++++++++- .../moodle-qtype_ddimageortext-dd-min.js | 4 +- .../moodle-qtype_ddimageortext-dd.js | 40 ++++++++++++++++++- .../yui/src/ddimageortext/js/ddimageortext.js | 40 ++++++++++++++++++- 4 files changed, 119 insertions(+), 5 deletions(-) diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js index 3818881f000..57f2e21cf3e 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-debug.js @@ -174,7 +174,6 @@ Y.extend(DDIMAGEORTEXT_DD, Y.Base, { drag.setData('group', group); drag.setData('choice', choice); - }, draggable_for_form : function (drag) { var dd = new Y.DD.Drag({ @@ -250,6 +249,7 @@ var DDIMAGEORTEXT_QUESTION = function() { * This is the code for question rendering. */ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { + touchscrolldisable: null, pendingid: '', initializer : function() { this.pendingid = 'qtype_ddimageortext-' + Math.random().toString(36).slice(2); // Random string. @@ -262,6 +262,38 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { false, 0, this.create_all_drag_and_drops); Y.later(500, this, this.reposition_drags_for_question, [this.pendingid], true); }, + + /** + * prevent_touchmove_from_scrolling allows users of touch screen devices to + * use drag and drop and normal scrolling at the same time. I.e. when + * touching and dragging a draggable item, the screen does not scroll, but + * you can scroll by touching other area of the screen apart from the + * draggable items. + */ + prevent_touchmove_from_scrolling : function(drag) { + var touchstart = (Y.UA.ie) ? 'MSPointerStart' : 'touchstart'; + var touchend = (Y.UA.ie) ? 'MSPointerEnd' : 'touchend'; + var touchmove = (Y.UA.ie) ? 'MSPointerMove' : 'touchmove'; + + // Disable scrolling when touching the draggable items. + drag.on(touchstart, function() { + if (this.touchscrolldisable) { + return; // Already disabled. + } + this.touchscrolldisable = Y.one('body').on(touchmove, function(e) { + e = e || window.event; + e.preventDefault(); + }); + }, this); + + // Allow scrolling after releasing the draggable items. + drag.on(touchend, function() { + if (this.touchscrolldisable) { + this.touchscrolldisable.detach(); + this.touchscrolldisable = null; + } + }, this); + }, create_all_drag_and_drops : function () { this.init_drops(); this.update_padding_sizes_all(); @@ -275,6 +307,9 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { i++; if (!this.get('readonly')) { this.doc.draggable_for_question(dragnode, group, choice); + + // Prevent scrolling whilst dragging on Adroid devices. + this.prevent_touchmove_from_scrolling(dragnode); } if (dragnode.hasClass('infinite')) { var dragstocreate = groupsize - 1; @@ -283,6 +318,9 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { i++; if (!this.get('readonly')) { this.doc.draggable_for_question(dragnode, group, choice); + + // Prevent scrolling whilst dragging on Adroid devices. + this.prevent_touchmove_from_scrolling(dragnode); } dragstocreate--; } diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js index 845933c9d62..98965e41160 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd-min.js @@ -1,2 +1,2 @@ -YUI.add("moodle-qtype_ddimageortext-dd",function(e,t){var n="ddimageortext_dd",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,e.Base,{doc:null,polltimer:null,afterimageloaddone:!1,poll_for_image_load:function(t,n,r,i){if(this.afterimageloaddone)return;var s=this.doc.bg_img().get("complete");n&&(s=s&&this.doc.bg_img().hasClass("constrained"));var o=!this.doc.drag_item_homes().some(function(e){if(e.get("tagName")!=="IMG")return!1;var t=e.get("complete");return n&&(t=t&&e.hasClass("constrained")),!t});if(s&&o)this.polltimer!==null&&(this.polltimer.cancel(),this.polltimer=null),this.doc.drag_item_homes().detach("load",this.poll_for_image_load),this.doc.bg_img().detach("load",this.poll_for_image_load),r!==0?e.later(r,this,i):i.call(this),this.afterimageloaddone=!0;else if(this.polltimer===null){var u=[null,n,r,i];this.polltimer=e.later(1e3,this,this.poll_for_image_load,u,!0)}},doc_structure:function(t){var n=e.one(this.get("topnode")),r=n.one("div.dragitems"),i=n.one("div.droparea");return{top_node:function(){return n},drag_items:function(){return r.all(".drag")},drop_zones:function(){return n.all("div.dropzones div.dropzone")},drop_zone_group:function(e){return n.all("div.dropzones div.group"+e)},drag_items_cloned_from:function(e){return r.all(".dragitems"+e)},drag_item:function(e){return r.one(".draginstance"+e)},drag_items_in_group:function(e){return r.all(".drag.group"+e)},drag_item_homes:function(){return r.all(".draghome")},bg_img:function(){return n.one(".dropbackground")},load_bg_img:function(e){i.setContent(''),this.bg_img().on("load",this.on_image_load,this,"bg_image")},add_or_update_drag_item_home:function(e,t,n,i){var s=this.drag_item_home(e),o="draghome dragitemhomes"+e+" group"+i,u=''+n+'',a='
    '+n+"
    ";s===null?t?r.append(u):n!==""&&r.append(a):(t?r.insert(u,s):n!==""&&r.insert(a,s),s.remove(!0));var f=r.one(".dragitemhomes"+e);f!==null&&(f.setData("groupno",i),f.setData("dragitemno",e))},drag_item_home:function(e){return r.one(".dragitemhomes"+e)},get_classname_numeric_suffix:function(e,t){var n=e.getAttribute("class");if(n!==""){var r=n.split(" ");for(var i=0;i0)o=this.doc.clone_new_drag_item(e,n),e++,this.get("readonly")||this.doc.draggable_for_question(o,i,r),u--}},this),this.reposition_drags_for_question(),this.get("readonly")||(this.doc.drop_zones().set("tabIndex",0),this.doc.drop_zones().each(function(e){e.on("dragchange",this.drop_zone_key_press,this)},this)),M.util.js_complete(this.pendingid)},drop_zone_key_press:function(e){switch(e.direction){case"next":this.place_next_drag_in(e.target);break;case"previous":this.place_previous_drag_in(e.target);break;case"remove":this.remove_drag_from_drop(e.target)}e.preventDefault(),this.reposition_drags_for_question()}, -place_next_drag_in:function(e){this.search_for_unplaced_drop_choice(e,1)},place_previous_drag_in:function(e){this.search_for_unplaced_drop_choice(e,-1)},search_for_unplaced_drop_choice:function(e,t){var n,r=this.current_drag_in_drop(e);if(""===r)if(t===1)n=1;else{n=1;var i=e.getData("group");this.doc.drag_items_in_group(i).each(function(e){n=Math.max(n,e.getData("choice"))},this)}else n=+r+t;var s;do{if(this.get_choices_for_drop(n,e).size()===0){this.remove_drag_from_drop(e);return}s=this.get_unplaced_choice_for_drop(n,e),n+=t}while(s===null);this.place_drag_in_drop(s,e)},current_drag_in_drop:function(t){var n=t.getData("inputid"),r=e.one("input#"+n);return r.get("value")},remove_drag_from_drop:function(e){this.place_drag_in_drop(null,e)},place_drag_in_drop:function(t,n){var r=n.getData("inputid"),i=e.one("input#"+r);t!==null?i.set("value",t.getData("choice")):i.set("value","")},reposition_drags_for_question:function(){this.doc.drag_items().removeClass("placed"),this.doc.drag_items().each(function(e){e.dd!==undefined&&e.dd.detachAll("drag:start")},this),this.doc.drop_zones().each(function(e){var t=e.getData("xy");e.setXY(this.convert_to_window_xy(t));var n="input#"+e.getData("inputid"),r=this.doc.top_node().one(n),i=r.get("value");if(i!==""){var s=this.get_unplaced_choice_for_drop(i,e);s!==null&&(s.setXY(e.getXY()),s.addClass("placed"),s.dd!==undefined&&s.dd.once("drag:start",function(e,t){t.set("value",""),e.target.get("node").removeClass("placed")},this,r))}},this),this.doc.drag_items().each(function(e){if(!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")){var t=this.doc.drag_item_home(e.getData("dragitemno"));e.setXY(t.getXY())}},this)},get_choices_for_drop:function(e,t){var n=t.getData("group");return this.doc.top_node().all("div.dragitemgroup"+n+" .choice"+e+".drag")},get_unplaced_choice_for_drop:function(e,t){var n=this.get_choices_for_drop(e,t),r=null;return n.some(function(e){return!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")?(r=e,!0):!1}),r},init_drops:function(){var t=this.doc.top_node().one("div.dropzones"),n={};for(var r=1;r<=8;r++){var i=e.Node.create('
    ');t.append(i),n[r]=i}var s=function(e){var t=e.drag.get("node"),n=e.drop.get("node");Number(n.getData("group"))===t.getData("group")&&this.place_drag_in_drop(t,n)};for(var o in this.get("drops")){var u=this.get("drops")[o],a="dropzone group"+u.group+" place"+o,f=u.text.replace('"','"'),l='
     
    ',c=e.Node.create(l);n[u.group].append(c),c.setStyles({opacity:.5}),c.setData("xy",u.xy),c.setData("place",o),c.setData("inputid",u.fieldname.replace(":","_")),c.setData("group",u.group);var h=new e.DD.Drop({node:c,groups:[u.group]});h.on("drop:hit",s,this)}}},{NAME:i,ATTRS:{}}),e.Event.define("dragchange",{_event:e.UA.webkit||e.UA.ie?"keydown":"keypress",_keys:{32:"next",37:"previous",38:"previous",39:"next",40:"next",27:"remove"},_keyHandler:function(e,t){this._keys[e.keyCode]&&(e.direction=this._keys[e.keyCode],t.fire(e))},on:function(e,t,n){t._detacher=e.on(this._event,this._keyHandler,this,n)}}),M.qtype_ddimageortext.init_question=function(e){return new s(e)}},"@VERSION@",{requires:["node","dd","dd-drop","dd-constrain"]}); +YUI.add("moodle-qtype_ddimageortext-dd",function(e,t){var n="ddimageortext_dd",r=function(){r.superclass.constructor.apply(this,arguments)};e.extend(r,e.Base,{doc:null,polltimer:null,afterimageloaddone:!1,poll_for_image_load:function(t,n,r,i){if(this.afterimageloaddone)return;var s=this.doc.bg_img().get("complete");n&&(s=s&&this.doc.bg_img().hasClass("constrained"));var o=!this.doc.drag_item_homes().some(function(e){if(e.get("tagName")!=="IMG")return!1;var t=e.get("complete");return n&&(t=t&&e.hasClass("constrained")),!t});if(s&&o)this.polltimer!==null&&(this.polltimer.cancel(),this.polltimer=null),this.doc.drag_item_homes().detach("load",this.poll_for_image_load),this.doc.bg_img().detach("load",this.poll_for_image_load),r!==0?e.later(r,this,i):i.call(this),this.afterimageloaddone=!0;else if(this.polltimer===null){var u=[null,n,r,i];this.polltimer=e.later(1e3,this,this.poll_for_image_load,u,!0)}},doc_structure:function(t){var n=e.one(this.get("topnode")),r=n.one("div.dragitems"),i=n.one("div.droparea");return{top_node:function(){return n},drag_items:function(){return r.all(".drag")},drop_zones:function(){return n.all("div.dropzones div.dropzone")},drop_zone_group:function(e){return n.all("div.dropzones div.group"+e)},drag_items_cloned_from:function(e){return r.all(".dragitems"+e)},drag_item:function(e){return r.one(".draginstance"+e)},drag_items_in_group:function(e){return r.all(".drag.group"+e)},drag_item_homes:function(){return r.all(".draghome")},bg_img:function(){return n.one(".dropbackground")},load_bg_img:function(e){i.setContent(''),this.bg_img().on("load",this.on_image_load,this,"bg_image")},add_or_update_drag_item_home:function(e,t,n,i){var s=this.drag_item_home(e),o="draghome dragitemhomes"+e+" group"+i,u=''+n+'',a='
    '+n+"
    ";s===null?t?r.append(u):n!==""&&r.append(a):(t?r.insert(u,s):n!==""&&r.insert(a,s),s.remove(!0));var f=r.one(".dragitemhomes"+e);f!==null&&(f.setData("groupno",i),f.setData("dragitemno",e))},drag_item_home:function(e){return r.one(".dragitemhomes"+e)},get_classname_numeric_suffix:function(e,t){var n=e.getAttribute("class");if(n!==""){var r=n.split(" ");for(var i=0;i0)o=this.doc.clone_new_drag_item(e,n),e++,this.get("readonly")||(this.doc.draggable_for_question(o,i,r),this.prevent_touchmove_from_scrolling +(o)),u--}},this),this.reposition_drags_for_question(),this.get("readonly")||(this.doc.drop_zones().set("tabIndex",0),this.doc.drop_zones().each(function(e){e.on("dragchange",this.drop_zone_key_press,this)},this)),M.util.js_complete(this.pendingid)},drop_zone_key_press:function(e){switch(e.direction){case"next":this.place_next_drag_in(e.target);break;case"previous":this.place_previous_drag_in(e.target);break;case"remove":this.remove_drag_from_drop(e.target)}e.preventDefault(),this.reposition_drags_for_question()},place_next_drag_in:function(e){this.search_for_unplaced_drop_choice(e,1)},place_previous_drag_in:function(e){this.search_for_unplaced_drop_choice(e,-1)},search_for_unplaced_drop_choice:function(e,t){var n,r=this.current_drag_in_drop(e);if(""===r)if(t===1)n=1;else{n=1;var i=e.getData("group");this.doc.drag_items_in_group(i).each(function(e){n=Math.max(n,e.getData("choice"))},this)}else n=+r+t;var s;do{if(this.get_choices_for_drop(n,e).size()===0){this.remove_drag_from_drop(e);return}s=this.get_unplaced_choice_for_drop(n,e),n+=t}while(s===null);this.place_drag_in_drop(s,e)},current_drag_in_drop:function(t){var n=t.getData("inputid"),r=e.one("input#"+n);return r.get("value")},remove_drag_from_drop:function(e){this.place_drag_in_drop(null,e)},place_drag_in_drop:function(t,n){var r=n.getData("inputid"),i=e.one("input#"+r);t!==null?i.set("value",t.getData("choice")):i.set("value","")},reposition_drags_for_question:function(){this.doc.drag_items().removeClass("placed"),this.doc.drag_items().each(function(e){e.dd!==undefined&&e.dd.detachAll("drag:start")},this),this.doc.drop_zones().each(function(e){var t=e.getData("xy");e.setXY(this.convert_to_window_xy(t));var n="input#"+e.getData("inputid"),r=this.doc.top_node().one(n),i=r.get("value");if(i!==""){var s=this.get_unplaced_choice_for_drop(i,e);s!==null&&(s.setXY(e.getXY()),s.addClass("placed"),s.dd!==undefined&&s.dd.once("drag:start",function(e,t){t.set("value",""),e.target.get("node").removeClass("placed")},this,r))}},this),this.doc.drag_items().each(function(e){if(!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")){var t=this.doc.drag_item_home(e.getData("dragitemno"));e.setXY(t.getXY())}},this)},get_choices_for_drop:function(e,t){var n=t.getData("group");return this.doc.top_node().all("div.dragitemgroup"+n+" .choice"+e+".drag")},get_unplaced_choice_for_drop:function(e,t){var n=this.get_choices_for_drop(e,t),r=null;return n.some(function(e){return!e.hasClass("placed")&&!e.hasClass("yui3-dd-dragging")?(r=e,!0):!1}),r},init_drops:function(){var t=this.doc.top_node().one("div.dropzones"),n={};for(var r=1;r<=8;r++){var i=e.Node.create('
    ');t.append(i),n[r]=i}var s=function(e){var t=e.drag.get("node"),n=e.drop.get("node");Number(n.getData("group"))===t.getData("group")&&this.place_drag_in_drop(t,n)};for(var o in this.get("drops")){var u=this.get("drops")[o],a="dropzone group"+u.group+" place"+o,f=u.text.replace('"','"'),l='
     
    ',c=e.Node.create(l);n[u.group].append(c),c.setStyles({opacity:.5}),c.setData("xy",u.xy),c.setData("place",o),c.setData("inputid",u.fieldname.replace(":","_")),c.setData("group",u.group);var h=new e.DD.Drop({node:c,groups:[u.group]});h.on("drop:hit",s,this)}}},{NAME:i,ATTRS:{}}),e.Event.define("dragchange",{_event:e.UA.webkit||e.UA.ie?"keydown":"keypress",_keys:{32:"next",37:"previous",38:"previous",39:"next",40:"next",27:"remove"},_keyHandler:function(e,t){this._keys[e.keyCode]&&(e.direction=this._keys[e.keyCode],t.fire(e))},on:function(e,t,n){t._detacher=e.on(this._event,this._keyHandler,this,n)}}),M.qtype_ddimageortext.init_question=function(e){return new s(e)}},"@VERSION@",{requires:["node","dd","dd-drop","dd-constrain"]}); diff --git a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js index 3818881f000..57f2e21cf3e 100644 --- a/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js +++ b/question/type/ddimageortext/yui/build/moodle-qtype_ddimageortext-dd/moodle-qtype_ddimageortext-dd.js @@ -174,7 +174,6 @@ Y.extend(DDIMAGEORTEXT_DD, Y.Base, { drag.setData('group', group); drag.setData('choice', choice); - }, draggable_for_form : function (drag) { var dd = new Y.DD.Drag({ @@ -250,6 +249,7 @@ var DDIMAGEORTEXT_QUESTION = function() { * This is the code for question rendering. */ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { + touchscrolldisable: null, pendingid: '', initializer : function() { this.pendingid = 'qtype_ddimageortext-' + Math.random().toString(36).slice(2); // Random string. @@ -262,6 +262,38 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { false, 0, this.create_all_drag_and_drops); Y.later(500, this, this.reposition_drags_for_question, [this.pendingid], true); }, + + /** + * prevent_touchmove_from_scrolling allows users of touch screen devices to + * use drag and drop and normal scrolling at the same time. I.e. when + * touching and dragging a draggable item, the screen does not scroll, but + * you can scroll by touching other area of the screen apart from the + * draggable items. + */ + prevent_touchmove_from_scrolling : function(drag) { + var touchstart = (Y.UA.ie) ? 'MSPointerStart' : 'touchstart'; + var touchend = (Y.UA.ie) ? 'MSPointerEnd' : 'touchend'; + var touchmove = (Y.UA.ie) ? 'MSPointerMove' : 'touchmove'; + + // Disable scrolling when touching the draggable items. + drag.on(touchstart, function() { + if (this.touchscrolldisable) { + return; // Already disabled. + } + this.touchscrolldisable = Y.one('body').on(touchmove, function(e) { + e = e || window.event; + e.preventDefault(); + }); + }, this); + + // Allow scrolling after releasing the draggable items. + drag.on(touchend, function() { + if (this.touchscrolldisable) { + this.touchscrolldisable.detach(); + this.touchscrolldisable = null; + } + }, this); + }, create_all_drag_and_drops : function () { this.init_drops(); this.update_padding_sizes_all(); @@ -275,6 +307,9 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { i++; if (!this.get('readonly')) { this.doc.draggable_for_question(dragnode, group, choice); + + // Prevent scrolling whilst dragging on Adroid devices. + this.prevent_touchmove_from_scrolling(dragnode); } if (dragnode.hasClass('infinite')) { var dragstocreate = groupsize - 1; @@ -283,6 +318,9 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { i++; if (!this.get('readonly')) { this.doc.draggable_for_question(dragnode, group, choice); + + // Prevent scrolling whilst dragging on Adroid devices. + this.prevent_touchmove_from_scrolling(dragnode); } dragstocreate--; } diff --git a/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js b/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js index 5741acbd5d7..ecefd836219 100644 --- a/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js +++ b/question/type/ddimageortext/yui/src/ddimageortext/js/ddimageortext.js @@ -172,7 +172,6 @@ Y.extend(DDIMAGEORTEXT_DD, Y.Base, { drag.setData('group', group); drag.setData('choice', choice); - }, draggable_for_form : function (drag) { var dd = new Y.DD.Drag({ @@ -248,6 +247,7 @@ var DDIMAGEORTEXT_QUESTION = function() { * This is the code for question rendering. */ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { + touchscrolldisable: null, pendingid: '', initializer : function() { this.pendingid = 'qtype_ddimageortext-' + Math.random().toString(36).slice(2); // Random string. @@ -260,6 +260,38 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { false, 0, this.create_all_drag_and_drops); Y.later(500, this, this.reposition_drags_for_question, [this.pendingid], true); }, + + /** + * prevent_touchmove_from_scrolling allows users of touch screen devices to + * use drag and drop and normal scrolling at the same time. I.e. when + * touching and dragging a draggable item, the screen does not scroll, but + * you can scroll by touching other area of the screen apart from the + * draggable items. + */ + prevent_touchmove_from_scrolling : function(drag) { + var touchstart = (Y.UA.ie) ? 'MSPointerStart' : 'touchstart'; + var touchend = (Y.UA.ie) ? 'MSPointerEnd' : 'touchend'; + var touchmove = (Y.UA.ie) ? 'MSPointerMove' : 'touchmove'; + + // Disable scrolling when touching the draggable items. + drag.on(touchstart, function() { + if (this.touchscrolldisable) { + return; // Already disabled. + } + this.touchscrolldisable = Y.one('body').on(touchmove, function(e) { + e = e || window.event; + e.preventDefault(); + }); + }, this); + + // Allow scrolling after releasing the draggable items. + drag.on(touchend, function() { + if (this.touchscrolldisable) { + this.touchscrolldisable.detach(); + this.touchscrolldisable = null; + } + }, this); + }, create_all_drag_and_drops : function () { this.init_drops(); this.update_padding_sizes_all(); @@ -273,6 +305,9 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { i++; if (!this.get('readonly')) { this.doc.draggable_for_question(dragnode, group, choice); + + // Prevent scrolling whilst dragging on Adroid devices. + this.prevent_touchmove_from_scrolling(dragnode); } if (dragnode.hasClass('infinite')) { var dragstocreate = groupsize - 1; @@ -281,6 +316,9 @@ Y.extend(DDIMAGEORTEXT_QUESTION, M.qtype_ddimageortext.dd_base_class, { i++; if (!this.get('readonly')) { this.doc.draggable_for_question(dragnode, group, choice); + + // Prevent scrolling whilst dragging on Adroid devices. + this.prevent_touchmove_from_scrolling(dragnode); } dragstocreate--; } From 4a53044a10afdce33e066e2da98f541df94e2d73 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 21 Aug 2015 12:35:36 +0100 Subject: [PATCH 208/208] MDL-47494 ddimageortext: Fix unit tests for 3.0 compatibility. --- question/type/ddimageortext/tests/walkthrough_test.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/question/type/ddimageortext/tests/walkthrough_test.php b/question/type/ddimageortext/tests/walkthrough_test.php index 40b791037a3..71e3eef575a 100644 --- a/question/type/ddimageortext/tests/walkthrough_test.php +++ b/question/type/ddimageortext/tests/walkthrough_test.php @@ -132,8 +132,6 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_hidden_expectation( $this->quba->get_field_prefix($this->slot) . 'p4', 1), $this->get_contains_try_again_button_expectation(true), - new question_pattern_expectation('/' . - preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'), $this->get_contains_hint_expectation('This is the first hint')); // Do try again. @@ -474,8 +472,6 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_submit_button_expectation(false), $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), - new question_pattern_expectation('/' . - preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'), $this->get_contains_hint_expectation('This is the first hint'), $this->get_contains_num_parts_correct(2), $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(), @@ -537,8 +533,6 @@ class qtype_ddimageortext_walkthrough_test extends qbehaviour_walkthrough_test_b $this->get_contains_submit_button_expectation(false), $this->get_contains_try_again_button_expectation(true), $this->get_does_not_contain_correctness_expectation(), - new question_pattern_expectation('/' . - preg_quote(get_string('notcomplete', 'qbehaviour_interactive'), '/') . '/'), $this->get_contains_hint_expectation('This is the second hint'), $this->get_contains_num_parts_correct(2), $this->get_contains_standard_partiallycorrect_combined_feedback_expectation(),