From 03d6acbb578ff9cbc3b74b1cc8b7af055274ec01 Mon Sep 17 00:00:00 2001 From: Jun Pataleta Date: Thu, 10 Dec 2020 22:03:21 +0800 Subject: [PATCH 1/4] MDL-70288 theme_boost: Manage aria-describedby on form validation * The aria-describedby attribute can be a list of element IDs that describe the element. On form validation, the ID of the error message container is added to this attribute which may already be containing another ID. So we need to properly add/remove the error message ID so that we don't delete any existing ID(s) in the aria-describedby attribute during form validation. --- .../amd/build/form-display-errors.min.js | 2 +- .../amd/build/form-display-errors.min.js.map | 2 +- theme/boost/amd/src/form-display-errors.js | 35 +++++++++++++++++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/theme/boost/amd/build/form-display-errors.min.js b/theme/boost/amd/build/form-display-errors.min.js index e169aac1e44..fa6511c5681 100644 --- a/theme/boost/amd/build/form-display-errors.min.js +++ b/theme/boost/amd/build/form-display-errors.min.js @@ -1,2 +1,2 @@ -define ("theme_boost/form-display-errors",["jquery","core/event"],function(a,b){return{enhance:function enhance(c){var d=document.getElementById(c);if(!d){return}a(d).on(b.Events.FORM_FIELD_VALIDATION,function(b,c){b.preventDefault();var e=a(d).closest(".form-group"),f=e.find(".form-control-feedback");if("TEXTAREA"==a(d).prop("tagName")&&e.find("[contenteditable]")){d=e.find("[contenteditable]")}if(""!==c){e.addClass("has-danger");e.data("client-validation-error",!0);a(d).addClass("is-invalid");a(d).attr("aria-describedby",f.attr("id"));a(d).attr("aria-invalid",!0);f.attr("tabindex",0);f.html(c);if(!f.is(":visible")){f.show();f.focus()}}else{if(!0===e.data("client-validation-error")){e.removeClass("has-danger");e.data("client-validation-error",!1);a(d).removeClass("is-invalid");a(d).removeAttr("aria-describedby");a(d).attr("aria-invalid",!1);f.hide()}}});var e=d.closest("form");if(e&&!("boostFormErrorsEnhanced"in e.dataset)){e.addEventListener("submit",function(){var b=a(".form-control-feedback:visible");if(b.length){b[0].focus()}});e.dataset.boostFormErrorsEnhanced=1}}}}); +define ("theme_boost/form-display-errors",["jquery","core/event"],function(a,b){return{enhance:function enhance(c){var d=document.getElementById(c);if(!d){return}a(d).on(b.Events.FORM_FIELD_VALIDATION,function(b,c){b.preventDefault();var e=a(d).closest(".form-group"),f=e.find(".form-control-feedback"),g=f.attr("id"),h=a(d).attr("aria-describedby");if("undefined"==typeof h){h=""}var i=[];if(h.length){i=h.split(" ")}var j=i.indexOf(g);if("TEXTAREA"==a(d).prop("tagName")&&e.find("[contenteditable]")){d=e.find("[contenteditable]")}if(""!==c){e.addClass("has-danger");e.data("client-validation-error",!0);a(d).addClass("is-invalid");if(-1===j){i.push(g);a(d).attr("aria-describedby",i.join(" "))}a(d).attr("aria-invalid",!0);f.attr("tabindex",0);f.html(c);if(!f.is(":visible")){f.show();f.focus()}}else{if(!0===e.data("client-validation-error")){e.removeClass("has-danger");e.data("client-validation-error",!1);a(d).removeClass("is-invalid");if(-1.\n\n/**\n * Custom form error event handler to manipulate the bootstrap markup and show\n * nicely styled errors in an mform.\n *\n * @module theme_boost/form-display-errors\n * @copyright 2016 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/event'], function($, Event) {\n return {\n enhance: function(elementid) {\n var element = document.getElementById(elementid);\n if (!element) {\n // Some elements (e.g. static) don't have a form field.\n // Hence there is no validation. So, no setup required here.\n return;\n }\n\n $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {\n event.preventDefault();\n var parent = $(element).closest('.form-group');\n var feedback = parent.find('.form-control-feedback');\n\n // Sometimes (atto) we have a hidden textarea backed by a real contenteditable div.\n if (($(element).prop(\"tagName\") == 'TEXTAREA') && parent.find('[contenteditable]')) {\n element = parent.find('[contenteditable]');\n }\n if (msg !== '') {\n parent.addClass('has-danger');\n parent.data('client-validation-error', true);\n $(element).addClass('is-invalid');\n $(element).attr('aria-describedby', feedback.attr('id'));\n $(element).attr('aria-invalid', true);\n feedback.attr('tabindex', 0);\n feedback.html(msg);\n\n // Only display and focus when the error was not already visible.\n // This is so that, when tabbing around the form, you don't get stuck.\n if (!feedback.is(':visible')) {\n feedback.show();\n feedback.focus();\n }\n\n } else {\n if (parent.data('client-validation-error') === true) {\n parent.removeClass('has-danger');\n parent.data('client-validation-error', false);\n $(element).removeClass('is-invalid');\n $(element).removeAttr('aria-describedby');\n $(element).attr('aria-invalid', false);\n feedback.hide();\n }\n }\n });\n\n var form = element.closest('form');\n if (form && !('boostFormErrorsEnhanced' in form.dataset)) {\n form.addEventListener('submit', function() {\n var visibleError = $('.form-control-feedback:visible');\n if (visibleError.length) {\n visibleError[0].focus();\n }\n });\n form.dataset.boostFormErrorsEnhanced = 1;\n }\n }\n };\n});\n"],"file":"form-display-errors.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/form-display-errors.js"],"names":["define","$","Event","enhance","elementid","element","document","getElementById","on","Events","FORM_FIELD_VALIDATION","event","msg","preventDefault","parent","closest","feedback","find","feedbackId","attr","describedBy","describedByIds","length","split","feedbackIndex","indexOf","prop","addClass","data","push","join","html","is","show","focus","removeClass","splice","removeAttr","hide","form","dataset","addEventListener","visibleError","boostFormErrorsEnhanced"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Custom form error event handler to manipulate the bootstrap markup and show\n * nicely styled errors in an mform.\n *\n * @module theme_boost/form-display-errors\n * @copyright 2016 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/event'], function($, Event) {\n return {\n enhance: function(elementid) {\n var element = document.getElementById(elementid);\n if (!element) {\n // Some elements (e.g. static) don't have a form field.\n // Hence there is no validation. So, no setup required here.\n return;\n }\n\n $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {\n event.preventDefault();\n var parent = $(element).closest('.form-group');\n var feedback = parent.find('.form-control-feedback');\n const feedbackId = feedback.attr('id');\n\n // Get current aria-describedby value.\n let describedBy = $(element).attr('aria-describedby');\n if (typeof describedBy === \"undefined\") {\n describedBy = '';\n }\n // Split aria-describedby attribute into an array of IDs if necessary.\n let describedByIds = [];\n if (describedBy.length) {\n describedByIds = describedBy.split(\" \");\n }\n // Find the the feedback container in the aria-describedby attribute.\n const feedbackIndex = describedByIds.indexOf(feedbackId);\n\n // Sometimes (atto) we have a hidden textarea backed by a real contenteditable div.\n if (($(element).prop(\"tagName\") == 'TEXTAREA') && parent.find('[contenteditable]')) {\n element = parent.find('[contenteditable]');\n }\n if (msg !== '') {\n parent.addClass('has-danger');\n parent.data('client-validation-error', true);\n $(element).addClass('is-invalid');\n // Append the feedback ID to the aria-describedby attribute if it doesn't exist yet.\n if (feedbackIndex === -1) {\n describedByIds.push(feedbackId);\n $(element).attr('aria-describedby', describedByIds.join(\" \"));\n }\n $(element).attr('aria-invalid', true);\n feedback.attr('tabindex', 0);\n feedback.html(msg);\n\n // Only display and focus when the error was not already visible.\n // This is so that, when tabbing around the form, you don't get stuck.\n if (!feedback.is(':visible')) {\n feedback.show();\n feedback.focus();\n }\n\n } else {\n if (parent.data('client-validation-error') === true) {\n parent.removeClass('has-danger');\n parent.data('client-validation-error', false);\n $(element).removeClass('is-invalid');\n // If the aria-describedby attribute contains the error container's ID, remove it.\n if (feedbackIndex > -1) {\n describedByIds.splice(feedbackIndex, 1);\n }\n // Check the remaining element IDs in the aria-describedby attribute.\n if (describedByIds.length) {\n // If there's at least one, combine them with a blank space and update the aria-describedby attribute.\n describedBy = describedByIds.join(\" \");\n // Put back the new describedby attribute.\n $(element).attr('aria-describedby', describedBy);\n } else {\n // If there's none, remove the aria-describedby attribute.\n $(element).removeAttr('aria-describedby');\n }\n $(element).attr('aria-invalid', false);\n feedback.hide();\n }\n }\n });\n\n var form = element.closest('form');\n if (form && !('boostFormErrorsEnhanced' in form.dataset)) {\n form.addEventListener('submit', function() {\n var visibleError = $('.form-control-feedback:visible');\n if (visibleError.length) {\n visibleError[0].focus();\n }\n });\n form.dataset.boostFormErrorsEnhanced = 1;\n }\n }\n };\n});\n"],"file":"form-display-errors.min.js"} \ No newline at end of file diff --git a/theme/boost/amd/src/form-display-errors.js b/theme/boost/amd/src/form-display-errors.js index a8391847a5a..4820397e7f2 100644 --- a/theme/boost/amd/src/form-display-errors.js +++ b/theme/boost/amd/src/form-display-errors.js @@ -35,6 +35,20 @@ define(['jquery', 'core/event'], function($, Event) { event.preventDefault(); var parent = $(element).closest('.form-group'); var feedback = parent.find('.form-control-feedback'); + const feedbackId = feedback.attr('id'); + + // Get current aria-describedby value. + let describedBy = $(element).attr('aria-describedby'); + if (typeof describedBy === "undefined") { + describedBy = ''; + } + // Split aria-describedby attribute into an array of IDs if necessary. + let describedByIds = []; + if (describedBy.length) { + describedByIds = describedBy.split(" "); + } + // Find the the feedback container in the aria-describedby attribute. + const feedbackIndex = describedByIds.indexOf(feedbackId); // Sometimes (atto) we have a hidden textarea backed by a real contenteditable div. if (($(element).prop("tagName") == 'TEXTAREA') && parent.find('[contenteditable]')) { @@ -44,7 +58,11 @@ define(['jquery', 'core/event'], function($, Event) { parent.addClass('has-danger'); parent.data('client-validation-error', true); $(element).addClass('is-invalid'); - $(element).attr('aria-describedby', feedback.attr('id')); + // Append the feedback ID to the aria-describedby attribute if it doesn't exist yet. + if (feedbackIndex === -1) { + describedByIds.push(feedbackId); + $(element).attr('aria-describedby', describedByIds.join(" ")); + } $(element).attr('aria-invalid', true); feedback.attr('tabindex', 0); feedback.html(msg); @@ -61,7 +79,20 @@ define(['jquery', 'core/event'], function($, Event) { parent.removeClass('has-danger'); parent.data('client-validation-error', false); $(element).removeClass('is-invalid'); - $(element).removeAttr('aria-describedby'); + // If the aria-describedby attribute contains the error container's ID, remove it. + if (feedbackIndex > -1) { + describedByIds.splice(feedbackIndex, 1); + } + // Check the remaining element IDs in the aria-describedby attribute. + if (describedByIds.length) { + // If there's at least one, combine them with a blank space and update the aria-describedby attribute. + describedBy = describedByIds.join(" "); + // Put back the new describedby attribute. + $(element).attr('aria-describedby', describedBy); + } else { + // If there's none, remove the aria-describedby attribute. + $(element).removeAttr('aria-describedby'); + } $(element).attr('aria-invalid', false); feedback.hide(); } From 97303481634b6af25be4905e50fee774c8402d56 Mon Sep 17 00:00:00 2001 From: Jun Pataleta Date: Thu, 10 Dec 2020 14:09:04 +0800 Subject: [PATCH 2/4] MDL-70288 core: Remove duplicate labels for checkbox elements * If there's a label, the text will serve as the description of the element. --- .../templates/element-advcheckbox.mustache | 21 ++++++++++++------- lib/form/templates/element-checkbox.mustache | 21 ++++++++++++------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/lib/form/templates/element-advcheckbox.mustache b/lib/form/templates/element-advcheckbox.mustache index 7524c003eb2..0e927e088ad 100644 --- a/lib/form/templates/element-advcheckbox.mustache +++ b/lib/form/templates/element-advcheckbox.mustache @@ -8,7 +8,6 @@
- + {{/text}}
{{#required}}
diff --git a/lib/form/templates/element-checkbox.mustache b/lib/form/templates/element-checkbox.mustache index b3497a4d117..ce1cd2e7bba 100644 --- a/lib/form/templates/element-checkbox.mustache +++ b/lib/form/templates/element-checkbox.mustache @@ -8,7 +8,6 @@
- + {{/text}}
{{#required}}
From c7b0a60a3c874713493aa882545fd009944b74d8 Mon Sep 17 00:00:00 2001 From: Jun Pataleta Date: Thu, 10 Dec 2020 22:49:39 +0800 Subject: [PATCH 3/4] MDL-70288 mod_lti: Remove unnecessary empty label string * When a label is passed to an (advanced) checkbox and no text was provided, the label will be displayed on the right of the the checkbox element. So there's no point in passing an empty string for the label just to render the text to the right of the checkbox. --- admin/tool/capability/classes/settings_form.php | 8 ++++---- mod/lti/edit_form.php | 2 +- mod/lti/mod_form.php | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/admin/tool/capability/classes/settings_form.php b/admin/tool/capability/classes/settings_form.php index 1bdf548dd04..c0984d1e8a1 100644 --- a/admin/tool/capability/classes/settings_form.php +++ b/admin/tool/capability/classes/settings_form.php @@ -60,12 +60,12 @@ class tool_capability_settings_form extends moodleform { $form->addElement('select', 'roles', get_string('roleslabel', 'tool_capability'), $roles, $attributes); $form->setType('roles', PARAM_TEXT); - $form->addElement('checkbox', 'onlydiff', - get_string('filters', 'tool_capability'), - get_string('onlydiff', 'tool_capability')); + $filters = []; + $filters[] = $form->createElement('checkbox', 'onlydiff', get_string('onlydiff', 'tool_capability')); $form->setType('onlydiff', PARAM_BOOL); + $form->addGroup($filters, 'filters', get_string('filters', 'tool_capability'), array('
'), false); $form->addElement('submit', 'submitbutton', get_string('getreport', 'tool_capability')); } -} \ No newline at end of file +} diff --git a/mod/lti/edit_form.php b/mod/lti/edit_form.php index d0f06fd6905..fdbb03c3840 100644 --- a/mod/lti/edit_form.php +++ b/mod/lti/edit_form.php @@ -279,7 +279,7 @@ class mod_lti_edit_types_form extends moodleform { $mform->setDefault('lti_acceptgrades', '2'); $mform->addHelpButton('lti_acceptgrades', 'accept_grades_admin', 'lti'); - $mform->addElement('checkbox', 'lti_forcessl', ' ', ' ' . get_string('force_ssl', 'lti'), $options); + $mform->addElement('checkbox', 'lti_forcessl', get_string('force_ssl', 'lti'), '', $options); $mform->setType('lti_forcessl', PARAM_BOOL); if (!empty($CFG->mod_lti_forcessl)) { $mform->setDefault('lti_forcessl', '1'); diff --git a/mod/lti/mod_form.php b/mod/lti/mod_form.php index adc17baf771..27fee1a0afc 100644 --- a/mod/lti/mod_form.php +++ b/mod/lti/mod_form.php @@ -104,12 +104,12 @@ class mod_lti_mod_form extends moodleform_mod { $mform->setAdvanced('showdescription'); - $mform->addElement('checkbox', 'showtitlelaunch', ' ', ' ' . get_string('display_name', 'lti')); + $mform->addElement('checkbox', 'showtitlelaunch', get_string('display_name', 'lti')); $mform->setAdvanced('showtitlelaunch'); $mform->setDefault('showtitlelaunch', true); $mform->addHelpButton('showtitlelaunch', 'display_name', 'lti'); - $mform->addElement('checkbox', 'showdescriptionlaunch', ' ', ' ' . get_string('display_description', 'lti')); + $mform->addElement('checkbox', 'showdescriptionlaunch', get_string('display_description', 'lti')); $mform->setAdvanced('showdescriptionlaunch'); $mform->addHelpButton('showdescriptionlaunch', 'display_description', 'lti'); @@ -281,17 +281,17 @@ class mod_lti_mod_form extends moodleform_mod { // Add privacy preferences fieldset where users choose whether to send their data. $mform->addElement('header', 'privacy', get_string('privacy', 'lti')); - $mform->addElement('advcheckbox', 'instructorchoicesendname', ' ', ' ' . get_string('share_name', 'lti')); + $mform->addElement('advcheckbox', 'instructorchoicesendname', get_string('share_name', 'lti')); $mform->setDefault('instructorchoicesendname', '1'); $mform->addHelpButton('instructorchoicesendname', 'share_name', 'lti'); $mform->disabledIf('instructorchoicesendname', 'typeid', 'in', $toolproxy); - $mform->addElement('advcheckbox', 'instructorchoicesendemailaddr', ' ', ' ' . get_string('share_email', 'lti')); + $mform->addElement('advcheckbox', 'instructorchoicesendemailaddr', get_string('share_email', 'lti')); $mform->setDefault('instructorchoicesendemailaddr', '1'); $mform->addHelpButton('instructorchoicesendemailaddr', 'share_email', 'lti'); $mform->disabledIf('instructorchoicesendemailaddr', 'typeid', 'in', $toolproxy); - $mform->addElement('advcheckbox', 'instructorchoiceacceptgrades', ' ', ' ' . get_string('accept_grades', 'lti')); + $mform->addElement('advcheckbox', 'instructorchoiceacceptgrades', get_string('accept_grades', 'lti')); $mform->setDefault('instructorchoiceacceptgrades', '1'); $mform->addHelpButton('instructorchoiceacceptgrades', 'accept_grades', 'lti'); $mform->disabledIf('instructorchoiceacceptgrades', 'typeid', 'in', $toolproxy); From 868af1cb0b057e9ad81c2b5130f0bbe2b85c4803 Mon Sep 17 00:00:00 2001 From: Jun Pataleta Date: Tue, 24 Nov 2020 13:08:54 +0800 Subject: [PATCH 4/4] MDL-70288 qtype: Remove unnecessary empty label string * When a label is passed to an (advanced) checkbox and no text was provided, the label will be displayed on the right of the the checkbox element. So there's no point in passing an empty string for the label just to render the text to the right of the checkbox. --- question/type/ddimageortext/edit_ddimageortext_form.php | 6 ++---- question/type/ddmarker/edit_ddmarker_form.php | 6 ++---- question/type/ddwtos/edit_ddwtos_form.php | 3 +-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/question/type/ddimageortext/edit_ddimageortext_form.php b/question/type/ddimageortext/edit_ddimageortext_form.php index 9b9f1d831e7..7d499e7f5b9 100644 --- a/question/type/ddimageortext/edit_ddimageortext_form.php +++ b/question/type/ddimageortext/edit_ddimageortext_form.php @@ -116,8 +116,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { protected function definition_draggable_items($mform, $itemrepeatsatstart) { $mform->addElement('header', 'draggableitemheader', get_string('draggableitems', 'qtype_ddimageortext')); - $mform->addElement('advcheckbox', 'shuffleanswers', ' ', - get_string('shuffleimages', 'qtype_'.$this->qtype())); + $mform->addElement('advcheckbox', 'shuffleanswers', get_string('shuffleimages', 'qtype_'.$this->qtype())); $mform->setDefault('shuffleanswers', 0); $this->repeat_elements($this->draggable_item($mform), $itemrepeatsatstart, $this->draggable_items_repeated_options(), @@ -143,8 +142,7 @@ class qtype_ddimageortext_edit_form extends qtype_ddtoimage_edit_form_base { get_string('group', 'qtype_gapselect'), $options, array('class' => 'draggroup')); - $grouparray[] = $mform->createElement('advcheckbox', 'infinite', ' ', - get_string('infinite', 'qtype_ddimageortext')); + $grouparray[] = $mform->createElement('advcheckbox', 'infinite', get_string('infinite', 'qtype_ddimageortext')); $draggableimageitem[] = $mform->createElement('group', 'drags', get_string('draggableitemheader', 'qtype_ddimageortext', '{no}'), $grouparray); diff --git a/question/type/ddmarker/edit_ddmarker_form.php b/question/type/ddmarker/edit_ddmarker_form.php index 8242691a437..15ff5864e7c 100644 --- a/question/type/ddmarker/edit_ddmarker_form.php +++ b/question/type/ddmarker/edit_ddmarker_form.php @@ -44,8 +44,7 @@ class qtype_ddmarker_edit_form extends qtype_ddtoimage_edit_form_base { } protected function definition_inner($mform) { - $mform->addElement('advcheckbox', 'showmisplaced', ' ', - get_string('showmisplaced', 'qtype_ddmarker')); + $mform->addElement('advcheckbox', 'showmisplaced', get_string('showmisplaced', 'qtype_ddmarker')); parent::definition_inner($mform); $mform->addHelpButton('drops[0]', 'dropzones', 'qtype_ddmarker'); @@ -60,8 +59,7 @@ class qtype_ddmarker_edit_form extends qtype_ddtoimage_edit_form_base { protected function definition_draggable_items($mform, $itemrepeatsatstart) { $mform->addElement('header', 'draggableitemheader', get_string('markers', 'qtype_ddmarker')); - $mform->addElement('advcheckbox', 'shuffleanswers', ' ', - get_string('shuffleimages', 'qtype_'.$this->qtype())); + $mform->addElement('advcheckbox', 'shuffleanswers', get_string('shuffleimages', 'qtype_'.$this->qtype())); $mform->setDefault('shuffleanswers', 0); $this->repeat_elements($this->draggable_item($mform), $itemrepeatsatstart, $this->draggable_items_repeated_options(), diff --git a/question/type/ddwtos/edit_ddwtos_form.php b/question/type/ddwtos/edit_ddwtos_form.php index f42b439d0db..84479dd84f8 100644 --- a/question/type/ddwtos/edit_ddwtos_form.php +++ b/question/type/ddwtos/edit_ddwtos_form.php @@ -49,8 +49,7 @@ class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { protected function choice_group($mform) { $grouparray = parent::choice_group($mform); - $grouparray[] = $mform->createElement('checkbox', 'infinite', ' ', - get_string('infinite', 'qtype_ddwtos'), null, + $grouparray[] = $mform->createElement('checkbox', 'infinite', get_string('infinite', 'qtype_ddwtos'), '', null, array('size' => 1, 'class' => 'tweakcss')); return $grouparray; }