define(['jquery', 'core/custom_interaction_events'], function($, CustomEvents) {
var SELECTORS = {
- CHOICE_ELEMENT: '.answer input',
- CLEAR_CHOICE_ELEMENT: 'div[class="qtype_multichoice_clearchoice"]'
+ ANSWER_RADIOS: '.answer input',
+ CLEARRESULTS_BUTTON: 'button[data-action="clearresults"]'
};
- /**
- * Mark clear choice radio as checked.
- *
- * @param {Object} clearChoiceContainer The clear choice option container.
- */
- var checkClearChoiceRadio = function(clearChoiceContainer) {
- clearChoiceContainer.find('input[type="radio"]').prop('checked', true);
- };
-
- /**
- * Get the clear choice div container.
- *
- * @param {Object} root The question root element.
- * @param {string} fieldPrefix The question outer div prefix.
- * @returns {Object} The clear choice div container.
- */
- var getClearChoiceElement = function(root, fieldPrefix) {
- return root.find('div[id="' + fieldPrefix + '"]');
- };
-
- /**
- * Hide clear choice option.
- *
- * @param {Object} clearChoiceContainer The clear choice option container.
- */
- var hideClearChoiceOption = function(clearChoiceContainer) {
- clearChoiceContainer.addClass('sr-only');
- };
-
- /**
- * Shows clear choice option.
- *
- * @param {Object} clearChoiceContainer The clear choice option container.
- */
- var showClearChoiceOption = function(clearChoiceContainer) {
- clearChoiceContainer.removeClass('sr-only');
- };
+ var CSSHIDDEN = 'd-none';
/**
* Register event listeners for the clear choice module.
*
* @param {Object} root The question outer div prefix.
- * @param {string} fieldPrefix The "Clear choice" div prefix.
*/
- var registerEventListeners = function(root, fieldPrefix) {
- var clearChoiceContainer = getClearChoiceElement(root, fieldPrefix);
-
- root.on(CustomEvents.events.activate, SELECTORS.CLEAR_CHOICE_ELEMENT, function(e, data) {
+ var registerEventListeners = function(root) {
- // Mark the clear choice radio element as checked.
- checkClearChoiceRadio(clearChoiceContainer);
- // Now that the hidden radio has been checked, hide the clear choice option.
- hideClearChoiceOption(clearChoiceContainer);
+ var clearChoiceButton = root.find(SELECTORS.CLEARRESULTS_BUTTON);
- data.originalEvent.preventDefault();
+ root.on(CustomEvents.events.activate, SELECTORS.CLEARRESULTS_BUTTON, function(e, data) {
+ root.find(SELECTORS.ANSWER_RADIOS).each(function() {
+ $(this).prop('checked', false);
+ });
+ $(e.target).addClass(CSSHIDDEN);
+ data.originalEvent.preventDefault();
});
- root.on(CustomEvents.events.activate, SELECTORS.CHOICE_ELEMENT, function() {
- // If the event has been triggered by any other choice, show the clear choice option.
- showClearChoiceOption(clearChoiceContainer);
+ root.on(CustomEvents.events.activate, SELECTORS.ANSWER_RADIOS, function() {
+ clearChoiceButton.removeClass(CSSHIDDEN);
});
};
* Initialise clear choice module.
* @param {string} root The question outer div prefix.
- * @param {string} fieldPrefix The "Clear choice" div prefix.
*/
- var init = function(root, fieldPrefix) {
+ var init = function(root) {
root = $('#' + root);
- registerEventListeners(root, fieldPrefix);
+ registerEventListeners(root);
};
return {
}
}
- $clearchoiceid = $this->get_input_id($qa, -1);
- $clearchoicefieldname = $qa->get_qt_field_name('clearchoice');
- $clearchoiceradioattrs = [
- 'type' => $this->get_input_type(),
- 'name' => $qa->get_qt_field_name('answer'),
- 'id' => $clearchoiceid,
- 'value' => -1,
- 'class' => 'sr-only'
- ];
+ $questiondivid = $qa->get_outer_question_div_unique_id();
- $cssclass = 'qtype_multichoice_clearchoice';
// When no choice selected during rendering, then hide the clear choice option.
+ $cssclass = '';
if (!$hascheckedchoice && $response == -1) {
- $cssclass .= ' sr-only';
- $clearchoiceradioattrs['checked'] = 'checked';
+ $cssclass = 'd-none';
}
- // Adds an hidden radio that will be checked to give the impression the choice has been cleared.
- $clearchoiceradio = html_writer::empty_tag('input', $clearchoiceradioattrs);
- $clearchoiceradio .= html_writer::link('', get_string('clearchoice', 'qtype_multichoice'),
- ['for' => $clearchoiceid, 'role' => 'button']);
- // Now wrap the radio and label inside a div.
- $result = html_writer::tag('div', $clearchoiceradio, ['id' => $clearchoicefieldname, 'class' => $cssclass]);
+ $clearchoicebutton = html_writer::tag('button', get_string('clearchoice', 'qtype_multichoice'), [
+ 'class' => 'btn btn-link ml-3 ' . $cssclass,
+ 'data-action' => 'clearresults',
+ 'data-target' => '#' . $questiondivid
+ ]);
// Load required clearchoice AMD module.
$this->page->requires->js_call_amd('qtype_multichoice/clearchoice', 'init',
- [$qa->get_outer_question_div_unique_id(), $clearchoicefieldname]);
+ [$questiondivid]);
- return $result;
+ return $clearchoicebutton;
}
}
--- /dev/null
+@qtype @qtype_multichoice
+Feature: Clear my answers
+ As a student
+ In order to reset Multiple choice ansers
+ I need to clear my choice
+
+ Background:
+ Given the following "users" exist:
+ | username | firstname | lastname | email |
+ | student1 | S1 | Student1 | student1@moodle.com |
+ And the following "courses" exist:
+ | fullname | shortname | category |
+ | Course 1 | C1 | 0 |
+ And the following "course enrolments" exist:
+ | user | course | role |
+ | student1 | C1 | student |
+ And the following "question categories" exist:
+ | contextlevel | reference | name |
+ | Course | C1 | Test questions |
+ And the following "questions" exist:
+ | questioncategory | qtype | name | template | questiontext |
+ | Test questions | multichoice | Multi-choice-001 | one_of_four | Question One |
+ And the following "activities" exist:
+ | activity | name | intro | course | idnumber | preferredbehaviour | canredoquestions |
+ | quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | immediatefeedback | 1 |
+ And quiz "Quiz 1" contains the following questions:
+ | question | page |
+ | Multi-choice-001 | 1 |
+
+ @javascript
+ Scenario: Attempt a quiz and reset my chosen answer.
+ When I log in as "student1"
+ And I am on "Course 1" course homepage
+ And I follow "Quiz 1"
+ And I press "Attempt quiz now"
+ And I should see "Question One"
+ And I click on "Four" "radio" in the "Question One" "question"
+ And I should see "Clear my choice"
+ And I click on "Clear my choice" "button" in the "Question One" "question"
+ Then I should not see "Clear my choice"
+ And I click on "Check" "button" in the "Question One" "question"
+ And I should see "Please select an answer" in the "Question One" "question"
new question_pattern_expectation('/class="r0 correct"/'),
new question_pattern_expectation('/class="r1"/'));
}
-
- /**
- * Test for clear choice option.
- */
- public function test_deferredfeedback_feedback_multichoice_clearchoice() {
-
- // Create a multichoice, single question.
- $mc = test_question_maker::make_a_multichoice_single_question();
- $mc->shuffleanswers = false;
-
- $clearchoice = -1;
- $rightchoice = 0;
- $wrongchoice = 2;
-
- $this->start_attempt_at_question($mc, 'deferredfeedback', 3);
-
- // Let's first submit the wrong choice (2).
- $this->process_submission(array('answer' => $wrongchoice)); // Wrong choice (2).
-
- $this->check_current_mark(null);
- // Clear choice radio should not be checked.
- $this->check_current_output(
- $this->get_contains_mc_radio_expectation($rightchoice, true, false), // Not checked.
- $this->get_contains_mc_radio_expectation($rightchoice + 1, true, false), // Not checked.
- $this->get_contains_mc_radio_expectation($rightchoice + 2, true, true), // Wrong choice (2) checked.
- $this->get_contains_mc_radio_expectation($clearchoice, true, false), // Not checked.
- $this->get_does_not_contain_correctness_expectation(),
- $this->get_does_not_contain_feedback_expectation()
- );
-
- // Now, let's clear our previous choice.
- $this->process_submission(array('answer' => $clearchoice)); // Clear choice (-1).
- $this->check_current_mark(null);
-
- // This time, the clear choice radio should be the only one checked.
- $this->check_current_output(
- $this->get_contains_mc_radio_expectation($rightchoice, true, false), // Not checked.
- $this->get_contains_mc_radio_expectation($rightchoice + 1, true, false), // Not checked.
- $this->get_contains_mc_radio_expectation($rightchoice + 2, true, false), // Not checked.
- $this->get_contains_mc_radio_expectation($clearchoice, true, true), // Clear choice radio checked.
- $this->get_does_not_contain_correctness_expectation(),
- $this->get_does_not_contain_feedback_expectation()
- );
-
- // Finally, let's submit the right choice.
- $this->process_submission(array('answer' => $rightchoice)); // Right choice (0).
- $this->check_current_state(question_state::$complete);
- $this->check_current_mark(null);
- $this->check_current_output(
- $this->get_contains_mc_radio_expectation($rightchoice, true, true),
- $this->get_contains_mc_radio_expectation($rightchoice + 1, true, false),
- $this->get_contains_mc_radio_expectation($rightchoice + 2, true, false),
- $this->get_contains_mc_radio_expectation($clearchoice, true, false),
- $this->get_does_not_contain_correctness_expectation(),
- $this->get_does_not_contain_feedback_expectation()
- );
-
- // Finish the attempt.
- $this->finish();
-
- // Verify.
- $this->check_current_state(question_state::$gradedright);
- $this->check_current_mark(3);
- $this->check_current_output(
- $this->get_contains_mc_radio_expectation($rightchoice, false, true),
- $this->get_contains_correct_expectation(),
- new question_pattern_expectation('/class="r0 correct"/'),
- new question_pattern_expectation('/class="r1"/'));
- }
}
.que.multichoice .answer div.r1 .icon.fa-remove {
text-indent: 0;
}
-.qtype_multichoice_clearchoice {
- padding-top: 10px;
- a {
- cursor: pointer;
- text-decoration: underline;
- padding-left: 30px;
- }
-}
.formulation input[type="text"],
.formulation select {
.que.multichoice .answer div.r1 .icon.fa-remove {
text-indent: 0; }
-.qtype_multichoice_clearchoice {
- padding-top: 10px; }
- .qtype_multichoice_clearchoice a {
- cursor: pointer;
- text-decoration: underline;
- padding-left: 30px; }
-
.formulation input[type="text"],
.formulation select {
width: auto;
.que.multichoice .answer div.r1 .icon.fa-remove {
text-indent: 0; }
-.qtype_multichoice_clearchoice {
- padding-top: 10px; }
- .qtype_multichoice_clearchoice a {
- cursor: pointer;
- text-decoration: underline;
- padding-left: 30px; }
-
.formulation input[type="text"],
.formulation select {
width: auto;