MDL-76597 mod_quiz: Add a default sr-only section heading

Add a default sr-only section heading in order to prevent having an
empty heading for the quiz section which is not good for accessibility.

Plus:
- There's also an existing issue where filters are never applied to
section headings on load. This has been fixed in this commit as well.
- Button role added for the edit section button which enables it to
take advantage of the theme highlighting when it receives focus.
This commit is contained in:
Jun Pataleta 2023-01-04 20:30:48 +08:00
parent b8b905cd90
commit e4f1f254c9
5 changed files with 99 additions and 15 deletions

View File

@ -393,24 +393,32 @@ class edit_renderer extends \plugin_renderer_base {
$sectionstyle = ' only-has-one-slot';
}
if ($section->heading) {
$sectionheadingtext = format_string($section->heading);
$sectionheading = html_writer::span($sectionheadingtext, 'instancesection');
} else {
// Use a sr-only default section heading, so we don't end up with an empty section heading.
$sectionheadingtext = get_string('sectionnoname', 'quiz');
$sectionheading = html_writer::span($sectionheadingtext, 'instancesection sr-only');
}
$output .= html_writer::start_tag('li', array('id' => 'section-'.$section->id,
'class' => 'section main clearfix'.$sectionstyle, 'role' => 'region',
'aria-label' => $section->heading));
'aria-label' => $sectionheadingtext));
$output .= html_writer::start_div('content');
$output .= html_writer::start_div('section-heading');
$headingtext = $this->heading(html_writer::span(
html_writer::span($section->heading, 'instancesection'), 'sectioninstance'), 3);
$headingtext = $this->heading(html_writer::span($sectionheading, 'sectioninstance'), 3);
if (!$structure->can_be_edited()) {
$editsectionheadingicon = '';
} else {
$editsectionheadingicon = html_writer::link(new \moodle_url('#'),
$this->pix_icon('t/editstring', get_string('sectionheadingedit', 'quiz', $section->heading),
$this->pix_icon('t/editstring', get_string('sectionheadingedit', 'quiz', $sectionheadingtext),
'moodle', array('class' => 'editicon visibleifjs')),
array('class' => 'editing_section', 'data-action' => 'edit_section_title'));
array('class' => 'editing_section', 'data-action' => 'edit_section_title', 'role' => 'button'));
}
$output .= html_writer::div($headingtext . $editsectionheadingicon, 'instancesectioncontainer');
@ -481,7 +489,7 @@ class edit_renderer extends \plugin_renderer_base {
* @return string HTML to output.
*/
public function section_remove_icon($section) {
$title = get_string('sectionheadingremove', 'quiz', $section->heading);
$title = get_string('sectionheadingremove', 'quiz', format_string($section->heading));
$url = new \moodle_url('/mod/quiz/edit.php',
array('sesskey' => sesskey(), 'removesection' => '1', 'sectionid' => $section->id));
$image = $this->pix_icon('t/delete', $title);
@ -1239,6 +1247,7 @@ class edit_renderer extends \plugin_renderer_base {
'numquestionsx',
'sectionheadingedit',
'sectionheadingremove',
'sectionnoname',
'removepagebreak',
'questiondependencyadd',
'questiondependencyfree',

View File

@ -1027,7 +1027,18 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.INSTANCESECTIONAREA));
this.edit_section_title_clear(activity);
if (newtext !== null && newtext !== oldtext) {
activity.one(SELECTOR.INSTANCESECTION).setContent(newtext);
var instancesection = activity.one(SELECTOR.INSTANCESECTION);
var instancesectiontext = newtext;
if (newtext.trim() === '') {
// Add a sr-only default section heading text to make sure we don't end up with an empty section heading.
instancesectiontext = M.util.get_string('sectionnoname', 'quiz');
instancesection.addClass('sr-only');
} else {
// Show the section heading when a non-empty value is set.
instancesection.removeClass('sr-only');
}
instancesection.setContent(instancesectiontext);
var data = {
'class': 'section',
'field': 'updatesectiontitle',
@ -1036,7 +1047,21 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
};
this.send_request(data, spinner, function(response) {
if (response) {
activity.one(SELECTOR.INSTANCESECTION).setContent(response.instancesection);
// Set the content of the section heading if for some reason the response is different from the new text.
// e.g. filters were applied, the update failed, etc.
if (newtext !== response.instancesection) {
if (response.instancesection.trim() === '') {
// Add a sr-only default section heading text.
instancesectiontext = M.util.get_string('sectionnoname', 'quiz');
instancesection.addClass('sr-only');
} else {
instancesectiontext = response.instancesection;
// Show the section heading when a non-empty value is set.
instancesection.removeClass('sr-only');
}
instancesection.setContent(instancesectiontext);
}
activity.one(SELECTOR.EDITSECTIONICON).set('title',
M.util.get_string('sectionheadingedit', 'quiz', response.instancesection));
activity.one(SELECTOR.EDITSECTIONICON).set('alt',

File diff suppressed because one or more lines are too long

View File

@ -1027,7 +1027,18 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.INSTANCESECTIONAREA));
this.edit_section_title_clear(activity);
if (newtext !== null && newtext !== oldtext) {
activity.one(SELECTOR.INSTANCESECTION).setContent(newtext);
var instancesection = activity.one(SELECTOR.INSTANCESECTION);
var instancesectiontext = newtext;
if (newtext.trim() === '') {
// Add a sr-only default section heading text to make sure we don't end up with an empty section heading.
instancesectiontext = M.util.get_string('sectionnoname', 'quiz');
instancesection.addClass('sr-only');
} else {
// Show the section heading when a non-empty value is set.
instancesection.removeClass('sr-only');
}
instancesection.setContent(instancesectiontext);
var data = {
'class': 'section',
'field': 'updatesectiontitle',
@ -1036,7 +1047,21 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
};
this.send_request(data, spinner, function(response) {
if (response) {
activity.one(SELECTOR.INSTANCESECTION).setContent(response.instancesection);
// Set the content of the section heading if for some reason the response is different from the new text.
// e.g. filters were applied, the update failed, etc.
if (newtext !== response.instancesection) {
if (response.instancesection.trim() === '') {
// Add a sr-only default section heading text.
instancesectiontext = M.util.get_string('sectionnoname', 'quiz');
instancesection.addClass('sr-only');
} else {
instancesectiontext = response.instancesection;
// Show the section heading when a non-empty value is set.
instancesection.removeClass('sr-only');
}
instancesection.setContent(instancesectiontext);
}
activity.one(SELECTOR.EDITSECTIONICON).set('title',
M.util.get_string('sectionheadingedit', 'quiz', response.instancesection));
activity.one(SELECTOR.EDITSECTIONICON).set('alt',

View File

@ -211,7 +211,18 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
var spinner = M.util.add_spinner(Y, activity.one(SELECTOR.INSTANCESECTIONAREA));
this.edit_section_title_clear(activity);
if (newtext !== null && newtext !== oldtext) {
activity.one(SELECTOR.INSTANCESECTION).setContent(newtext);
var instancesection = activity.one(SELECTOR.INSTANCESECTION);
var instancesectiontext = newtext;
if (newtext.trim() === '') {
// Add a sr-only default section heading text to make sure we don't end up with an empty section heading.
instancesectiontext = M.util.get_string('sectionnoname', 'quiz');
instancesection.addClass('sr-only');
} else {
// Show the section heading when a non-empty value is set.
instancesection.removeClass('sr-only');
}
instancesection.setContent(instancesectiontext);
var data = {
'class': 'section',
'field': 'updatesectiontitle',
@ -220,7 +231,21 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
};
this.send_request(data, spinner, function(response) {
if (response) {
activity.one(SELECTOR.INSTANCESECTION).setContent(response.instancesection);
// Set the content of the section heading if for some reason the response is different from the new text.
// e.g. filters were applied, the update failed, etc.
if (newtext !== response.instancesection) {
if (response.instancesection.trim() === '') {
// Add a sr-only default section heading text.
instancesectiontext = M.util.get_string('sectionnoname', 'quiz');
instancesection.addClass('sr-only');
} else {
instancesectiontext = response.instancesection;
// Show the section heading when a non-empty value is set.
instancesection.removeClass('sr-only');
}
instancesection.setContent(instancesectiontext);
}
activity.one(SELECTOR.EDITSECTIONICON).set('title',
M.util.get_string('sectionheadingedit', 'quiz', response.instancesection));
activity.one(SELECTOR.EDITSECTIONICON).set('alt',