mirror of
https://github.com/moodle/moodle.git
synced 2025-04-07 17:33:18 +02:00
MDL-77856 qtype_multianswer: Use Bootstrap Popover for subq feedback
The YUI Overlay widget encloses the subquestion feedback in a div which causes a div element to be enclosed in the subquestion span. This leads to an accessibility issue in terms of HTML parsing as inline elements (span) should not contain block elements (div) The YUI Overlay widget is also not accessible as it does not really hide the overlay contents via aria-hidden when the overlay is not being shown. It's better if we stop using this and use Bootstrap's popover component which is more accessible by default. This patch also removes module.js for the qtype_multianswer plugin as it only contains codes related to rendering the feedback contents in the YUI overlay widget which is no longer necessary.
This commit is contained in:
parent
fba0658777
commit
e3c0c2f2c2
@ -1,54 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* JavaScript required by the multianswer question type.
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage multianswer
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
M.qtype_multianswer = M.qtype_multianswer || {};
|
||||
|
||||
|
||||
M.qtype_multianswer.init = function (Y, questiondiv) {
|
||||
Y.one(questiondiv).all('span.subquestion').each(function(subqspan) {
|
||||
var feedbackspan = subqspan.one('.feedbackspan');
|
||||
if (!feedbackspan) {
|
||||
return;
|
||||
}
|
||||
|
||||
var overlay = new Y.Overlay({
|
||||
srcNode: feedbackspan,
|
||||
visible: false,
|
||||
align: {
|
||||
node: subqspan,
|
||||
points: [Y.WidgetPositionAlign.TC, Y.WidgetPositionAlign.BC]
|
||||
},
|
||||
constrain: subqspan.ancestor('div.que'),
|
||||
zIndex: 1,
|
||||
preventOverlap: true
|
||||
});
|
||||
overlay.render();
|
||||
|
||||
Y.on('mouseover', function() { overlay.show(); }, subqspan);
|
||||
Y.on('mouseout', function() { overlay.hide(); }, subqspan);
|
||||
|
||||
feedbackspan.removeClass('accesshide');
|
||||
});
|
||||
};
|
@ -88,13 +88,6 @@ class qtype_multianswer_renderer extends qtype_renderer {
|
||||
array('class' => 'validationerror'));
|
||||
}
|
||||
|
||||
$this->page->requires->js_init_call('M.qtype_multianswer.init',
|
||||
array('#' . $qa->get_outer_question_div_unique_id()), false, array(
|
||||
'name' => 'qtype_multianswer',
|
||||
'fullpath' => '/question/type/multianswer/module.js',
|
||||
'requires' => array('base', 'node', 'event', 'overlay'),
|
||||
));
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
@ -202,8 +195,33 @@ abstract class qtype_multianswer_subq_renderer_base extends qtype_renderer {
|
||||
return '';
|
||||
}
|
||||
|
||||
return html_writer::tag('span', implode('<br />', $feedback),
|
||||
array('class' => 'feedbackspan accesshide'));
|
||||
return html_writer::tag('span', implode('<br />', $feedback), [
|
||||
'class' => 'feedbackspan',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the feedback icon for a sub-question which is also the trigger for the feedback popover.
|
||||
*
|
||||
* @param string $icon The feedback icon
|
||||
* @param string $feedbackcontents The feedback contents to be shown on the popover.
|
||||
* @return string
|
||||
*/
|
||||
protected function get_feedback_image(string $icon, string $feedbackcontents): string {
|
||||
if ($icon === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return html_writer::tag('button', $icon, [
|
||||
'type' => 'button',
|
||||
'class' => 'btn btn-link p-0',
|
||||
'data-toggle' => 'popover',
|
||||
'data-container' => 'body',
|
||||
'data-content' => $feedbackcontents,
|
||||
'data-placement' => 'right',
|
||||
'data-trigger' => 'focus',
|
||||
'data-html' => 'true',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -315,8 +333,7 @@ class qtype_multianswer_textfield_renderer extends qtype_multianswer_subq_render
|
||||
$output .= html_writer::tag('label', $this->get_answer_label(),
|
||||
array('class' => 'subq accesshide', 'for' => $inputattributes['id']));
|
||||
$output .= html_writer::empty_tag('input', $inputattributes);
|
||||
$output .= $feedbackimg;
|
||||
$output .= $feedbackpopup;
|
||||
$output .= $this->get_feedback_image($feedbackimg, $feedbackpopup);
|
||||
$output .= html_writer::end_tag('span');
|
||||
|
||||
return $output;
|
||||
@ -385,8 +402,7 @@ class qtype_multianswer_multichoice_inline_renderer
|
||||
$output .= html_writer::tag('label', $this->get_answer_label(),
|
||||
array('class' => 'subq accesshide', 'for' => $inputattributes['id']));
|
||||
$output .= $select;
|
||||
$output .= $feedbackimg;
|
||||
$output .= $feedbackpopup;
|
||||
$output .= $this->get_feedback_image($feedbackimg, $feedbackpopup);
|
||||
$output .= html_writer::end_tag('span');
|
||||
|
||||
return $output;
|
||||
|
@ -41,7 +41,7 @@ class walkthrough_test extends \qbehaviour_walkthrough_test_base {
|
||||
|
||||
protected function get_contains_subq_status(question_state $state) {
|
||||
return new \question_pattern_expectation('~' .
|
||||
preg_quote($state->default_string(true), '~') . '<br />~');
|
||||
preg_quote($state->default_string(true), '~') . '~');
|
||||
}
|
||||
|
||||
public function test_deferred_feedback() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user