Skip to content

Commit

Permalink
MDL-73597 Questions: Form checker integration for D&D question types
Browse files Browse the repository at this point in the history
  • Loading branch information
HuongNV13 committed Mar 16, 2022
1 parent 967d9b2 commit 0c33dbb
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 9 deletions.
2 changes: 1 addition & 1 deletion question/type/ddimageortext/amd/build/question.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion question/type/ddimageortext/amd/build/question.min.js.map

Large diffs are not rendered by default.

69 changes: 68 additions & 1 deletion question/type/ddimageortext/amd/src/question.js
Expand Up @@ -20,7 +20,17 @@
* @copyright 2018 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys) {
define([
'jquery',
'core/dragdrop',
'core/key_codes',
'core_form/changechecker'
], function(
$,
dragDrop,
keys,
FormChangeChecker
) {

"use strict";

Expand All @@ -34,6 +44,7 @@ define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys
*/
function DragDropOntoImageQuestion(containerId, readOnly, places) {
this.containerId = containerId;
this.questionAnswer = {};
M.util.js_pending('qtype_ddimageortext-init-' + this.containerId);
this.places = places;
this.allImagesLoaded = false;
Expand Down Expand Up @@ -301,6 +312,48 @@ define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys
var drop = root.find('.dropzone.place' + place);
thisQ.sendDragToDrop(unplacedDrag, drop);
});

// Save the question answer.
thisQ.questionAnswer = thisQ.getQuestionAnsweredValues();
};

/**
* Get the question answered values.
*
* @return {Object} Contain key-value with key is the input id and value is the input value.
*/
DragDropOntoImageQuestion.prototype.getQuestionAnsweredValues = function() {
let result = {};
this.getRoot().find('input.placeinput').each((i, inputNode) => {
result[inputNode.id] = inputNode.value;
});

return result;
};

/**
* Check if the question is being interacted or not.
*
* @return {boolean} Return true if the user has changed the question-answer.
*/
DragDropOntoImageQuestion.prototype.isQuestionInteracted = function() {
const oldAnswer = this.questionAnswer;
const newAnswer = this.getQuestionAnsweredValues();
let isInteracted = false;

// First, check both answers have the same structure or not.
if (JSON.stringify(newAnswer) !== JSON.stringify(oldAnswer)) {
isInteracted = true;
return isInteracted;
}
// Check the values.
Object.keys(newAnswer).forEach(key => {
if (newAnswer[key] !== oldAnswer[key]) {
isInteracted = true;
}
});

return isInteracted;
};

/**
Expand Down Expand Up @@ -1131,6 +1184,12 @@ define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys
if (questionManager.isKeyboardNavigation) {
questionManager.isKeyboardNavigation = false;
}
if (thisQ.isQuestionInteracted()) {
// The user has interacted with the draggable items. We need to mark the form as dirty.
questionManager.handleFormDirty();
// Save the new answered value.
thisQ.questionAnswer = thisQ.getQuestionAnsweredValues();
}
},

/**
Expand All @@ -1141,6 +1200,14 @@ define(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys
getQuestionForEvent: function(e) {
var containerId = $(e.currentTarget).closest('.que.ddimageortext').attr('id');
return questionManager.questions[containerId];
},

/**
* Handle when the form is dirty.
*/
handleFormDirty: function() {
const responseForm = document.getElementById('responseform');
FormChangeChecker.markFormAsDirty(responseForm);
}
};

Expand Down
2 changes: 1 addition & 1 deletion question/type/ddmarker/amd/build/question.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion question/type/ddmarker/amd/build/question.min.js.map

Large diffs are not rendered by default.

71 changes: 70 additions & 1 deletion question/type/ddmarker/amd/src/question.js
Expand Up @@ -21,7 +21,19 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

define(['jquery', 'core/dragdrop', 'qtype_ddmarker/shapes', 'core/key_codes'], function($, dragDrop, Shapes, keys) {
define([
'jquery',
'core/dragdrop',
'qtype_ddmarker/shapes',
'core/key_codes',
'core_form/changechecker'
], function(
$,
dragDrop,
Shapes,
keys,
FormChangeChecker
) {

"use strict";

Expand All @@ -41,6 +53,7 @@ define(['jquery', 'core/dragdrop', 'qtype_ddmarker/shapes', 'core/key_codes'], f
this.shapes = [];
this.shapeSVGs = [];
this.isPrinting = false;
this.questionAnswer = {};
if (readOnly) {
this.getRoot().addClass('qtype_ddmarker-readonly');
}
Expand Down Expand Up @@ -150,6 +163,48 @@ define(['jquery', 'core/dragdrop', 'qtype_ddmarker/shapes', 'core/key_codes'], f
thisQ.cloneDragIfNeeded(drag);
}
});

// Save the question answer.
thisQ.questionAnswer = thisQ.getQuestionAnsweredValues();
};

/**
* Get the question answered values.
*
* @return {Object} Contain key-value with key is the input id and value is the input value.
*/
DragDropMarkersQuestion.prototype.getQuestionAnsweredValues = function() {
let result = {};
this.getRoot().find('input.choices').each((i, inputNode) => {
result[inputNode.id] = inputNode.value;
});

return result;
};

/**
* Check if the question is being interacted or not.
*
* @return {boolean} Return true if the user has changed the question-answer.
*/
DragDropMarkersQuestion.prototype.isQuestionInteracted = function() {
const oldAnswer = this.questionAnswer;
const newAnswer = this.getQuestionAnsweredValues();
let isInteracted = false;

// First, check both answers have the same structure or not.
if (JSON.stringify(newAnswer) !== JSON.stringify(oldAnswer)) {
isInteracted = true;
return isInteracted;
}
// Check the values.
Object.keys(newAnswer).forEach(key => {
if (newAnswer[key] !== oldAnswer[key]) {
isInteracted = true;
}
});

return isInteracted;
};

/**
Expand Down Expand Up @@ -320,6 +375,12 @@ define(['jquery', 'core/dragdrop', 'qtype_ddmarker/shapes', 'core/key_codes'], f
}

this.getRoot().find('input.choice' + choiceNo).val(coords.join(';'));
if (this.isQuestionInteracted()) {
// The user has interacted with the draggable items. We need to mark the form as dirty.
questionManager.handleFormDirty();
// Save the new answered value.
this.questionAnswer = this.getQuestionAnsweredValues();
}
};

/**
Expand Down Expand Up @@ -844,6 +905,14 @@ define(['jquery', 'core/dragdrop', 'qtype_ddmarker/shapes', 'core/key_codes'], f
getQuestionForEvent: function(e) {
var containerId = $(e.currentTarget).closest('.que.ddmarker').attr('id');
return questionManager.questions[containerId];
},

/**
* Handle when the form is dirty.
*/
handleFormDirty: function() {
const responseForm = document.getElementById('responseform');
FormChangeChecker.markFormAsDirty(responseForm);
}
};

Expand Down

0 comments on commit 0c33dbb

Please sign in to comment.