MDL-69266 qtype_ddwtos: 'unlimited' options fail in 3.9
authorHuong Nguyen <huongnv13@gmail.com>
Mon, 5 Oct 2020 06:33:08 +0000 (13:33 +0700)
committerHuong Nguyen <huongnv13@gmail.com>
Thu, 15 Oct 2020 13:05:52 +0000 (20:05 +0700)
question/type/ddwtos/amd/build/ddwtos.min.js
question/type/ddwtos/amd/build/ddwtos.min.js.map
question/type/ddwtos/amd/src/ddwtos.js
question/type/ddwtos/tests/behat/behat_qtype_ddwtos.php
question/type/ddwtos/tests/behat/preview.feature
question/type/ddwtos/tests/helper.php

index 5aa26ef..52b8e6b 100644 (file)
Binary files a/question/type/ddwtos/amd/build/ddwtos.min.js and b/question/type/ddwtos/amd/build/ddwtos.min.js differ
index 9f6a640..86c11dd 100644 (file)
Binary files a/question/type/ddwtos/amd/build/ddwtos.min.js.map and b/question/type/ddwtos/amd/build/ddwtos.min.js.map differ
index bad4324..d7460c1 100644 (file)
@@ -171,7 +171,19 @@ define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys
             // Get the clone of the drag.
             var hiddenDrag = thisQ.getDragClone(unplacedDrag);
             if (hiddenDrag.length) {
-                hiddenDrag.addClass('active');
+                if (unplacedDrag.hasClass('infinite')) {
+                    var noOfDrags = thisQ.noOfDropsInGroup(thisQ.getGroup(unplacedDrag));
+                    var cloneDrags = thisQ.getInfiniteDragClones(unplacedDrag, false);
+                    if (cloneDrags.length < noOfDrags) {
+                        var cloneDrag = unplacedDrag.clone();
+                        hiddenDrag.after(cloneDrag);
+                        questionManager.addEventHandlersToDrag(cloneDrag);
+                    } else {
+                        hiddenDrag.addClass('active');
+                    }
+                } else {
+                    hiddenDrag.addClass('active');
+                }
             }
             // Send the drag to drop.
             thisQ.sendDragToDrop(thisQ.getUnplacedChoice(thisQ.getGroup(input), choice), drop);
@@ -251,7 +263,7 @@ define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys
         });
         this.getRoot().find('span.draghome.placed.group' + this.getGroup(drag)).not('.beingdragged').each(function(i, dropNode) {
             var drop = $(dropNode);
-            if (thisQ.isPointInDrop(pageX, pageY, drop)) {
+            if (thisQ.isPointInDrop(pageX, pageY, drop) && !thisQ.isDragSameAsDrop(drag, drop)) {
                 drop.addClass('valid-drag-over-drop');
             } else {
                 drop.removeClass('valid-drag-over-drop');
@@ -286,7 +298,7 @@ define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys
 
         root.find('span.draghome.placed.group' + this.getGroup(drag)).not('.beingdragged').each(function(i, placedNode) {
             var placedDrag = $(placedNode);
-            if (!thisQ.isPointInDrop(pageX, pageY, placedDrag)) {
+            if (!thisQ.isPointInDrop(pageX, pageY, placedDrag) || thisQ.isDragSameAsDrop(drag, placedDrag)) {
                 // Not this placed drag.
                 return true;
             }
@@ -700,6 +712,17 @@ define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys
         return this.getRoot().find('.drop.group' + this.getGroup(drag) + '.place' + currentPlace);
     };
 
+    /**
+     * Check that the drag is drop to it's clone.
+     *
+     * @param {jQuery} drag The drag.
+     * @param {jQuery} drop The drop.
+     * @returns {boolean}
+     */
+    DragDropToTextQuestion.prototype.isDragSameAsDrop = function(drag, drop) {
+        return this.getChoice(drag) === this.getChoice(drop) && this.getGroup(drag) === this.getGroup(drop);
+    };
+
     /**
      * Singleton that tracks all the DragDropToTextQuestions on this page, and deals
      * with event dispatching.
@@ -758,6 +781,8 @@ define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys
          * @param {jQuery} element Element to bind the event
          */
         addEventHandlersToDrag: function(element) {
+            // Unbind all the mousedown and touchstart events to prevent double binding.
+            element.unbind('mousedown touchstart');
             element.on('mousedown touchstart', questionManager.handleDragStart);
         },
 
index 8123248..f04131d 100644 (file)
@@ -41,8 +41,8 @@ class behat_qtype_ddwtos extends behat_base {
      * @return string the xpath expression.
      */
     protected function drag_xpath($dragitem) {
-        return '//span[contains(@class, "draghome") and contains(., "' . $this->escape($dragitem) .
-                '") and not(contains(@class, "dragplaceholder"))]';
+        return '//div[@class="answercontainer"]//span[contains(@class, "draghome") and contains(., "' .
+                $this->escape($dragitem) . '") and not(contains(@class, "dragplaceholder"))]';
     }
 
     /**
@@ -86,4 +86,15 @@ class behat_qtype_ddwtos extends behat_base {
             $this->wait_for_pending_js();
         }
     }
+
+    /**
+     * Check that the given drag exist in drag home area
+     *
+     * @param string $dragitem the text of the drag item.
+     *
+     * @Given /^I should see "(?P<drag_item>[^"]*)" in the home area of drag and drop into text question$/
+     */
+    public function i_should_see_drag_in_the_home_area($dragitem) {
+        $this->ensure_element_exists($this->drag_xpath($dragitem), 'xpath_element');
+    }
 }
index 4abf47c..3f2bb01 100644 (file)
@@ -18,8 +18,9 @@ Feature: Preview a drag-drop into text question
       | contextlevel | reference | name           |
       | Course       | C1        | Test questions |
     And the following "questions" exist:
-      | questioncategory | qtype  | name         | template |
-      | Test questions   | ddwtos | Drag to text | fox      |
+      | questioncategory | qtype  | name                  | template |
+      | Test questions   | ddwtos | Drag to text          | fox      |
+      | Test questions   | ddwtos | Drag to text infinite | infinite |
     Given I log in as "teacher1"
     And I am on "Course 1" course homepage
     And I navigate to "Question bank" in current page administration
@@ -79,3 +80,16 @@ Feature: Preview a drag-drop into text question
     Then the state of "The" 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 infinite question.
+    When I choose "Preview" action for "Drag to text infinite" in the question bank
+    And I switch to "questionpreview" window
+    # Increase window size.
+    # Keep window large else drag will scroll the window to find element.
+    And I change window size to "medium"
+    And I press "Fill in correct responses"
+    Then I should see "Option1" in the home area of drag and drop into text question
+    And I should see "Option2" in the home area of drag and drop into text question
+    And I should see "Option3" in the home area of drag and drop into text question
+    And I switch to the main window
index 3ccd35b..a317695 100644 (file)
@@ -34,7 +34,7 @@ defined('MOODLE_INTERNAL') || die();
  */
 class qtype_ddwtos_test_helper extends question_test_helper {
     public function get_test_questions() {
-        return array('fox', 'maths', 'oddgroups', 'missingchoiceno');
+        return array('fox', 'maths', 'oddgroups', 'missingchoiceno', 'infinite');
     }
 
     /**
@@ -186,4 +186,28 @@ class qtype_ddwtos_test_helper extends question_test_helper {
 
         return $dd;
     }
+
+    /**
+     * This is a simple question with infinite mode.
+     *
+     * @return stdClass data to create a ddwtos question.
+     */
+    public function get_ddwtos_question_form_data_infinite() {
+        $fromform = new stdClass();
+
+        $fromform->name = 'Drag-and-drop infinite question';
+        $fromform->questiontext = ['text' => 'One [[1]] Two [[2]] Three [[3]]', 'format' => FORMAT_HTML];
+        $fromform->defaultmark = 1.0;
+        $fromform->generalfeedback = ['text' => 'This is general feedback', 'format' => FORMAT_HTML];
+        $fromform->choices = [
+                ['answer' => 'Option1', 'choicegroup' => '1', 'infinite' => true],
+                ['answer' => 'Option2', 'choicegroup' => '1', 'infinite' => true],
+                ['answer' => 'Option3', 'choicegroup' => '1', 'infinite' => true]
+        ];
+        test_question_maker::set_standard_combined_feedback_form_data($fromform);
+        $fromform->shownumcorrect = 0;
+        $fromform->penalty = 0.3333333;
+
+        return $fromform;
+    }
 }