diff --git a/lib/form/form.js b/lib/form/form.js index 0ef899f64f3..c9cde31c890 100644 --- a/lib/form/form.js +++ b/lib/form/form.js @@ -16,6 +16,7 @@ if (typeof M.form.dependencyManager === 'undefined') { _dirty: null, _nameCollections: null, _fileinputs: null, + _staticElements: null, _editors: null, _editorNameSuffix: '[text]', @@ -105,6 +106,14 @@ if (typeof M.form.dependencyManager === 'undefined') { allnames[name].push(node); } }); + // Locate any static elements for each name. + this.get('form').all('.form-control-static').each(function(node) { + var name = node.getData('name'); + if (({}).hasOwnProperty.call(allnames, name)) { + names[name].push(node); + allnames[name].push(node); + } + }); this._nameCollections = {names: names, allnames: allnames}; }, @@ -259,20 +268,47 @@ if (typeof M.form.dependencyManager === 'undefined') { * @param {Boolean} disabled True to disable, false to enable. */ _disableElement: function(name, disabled) { - var els = this.elementsByName(name), + const els = this.elementsByName(name), filepicker = this.isFilePicker(name), - editors = this.get('form').all('.fitem [data-fieldtype="editor"] textarea[name="' + name + '[text]"]'); + editors = this.get('form').all('.fitem [data-fieldtype="editor"] textarea[name="' + name + '[text]"]'), + staticElement = this.isStaticElement(name); els.each(function(node) { + const fitem = node.ancestor('.fitem'); if (disabled) { node.setAttribute('disabled', 'disabled'); } else { node.removeAttribute('disabled'); } - + // Enable/Disable static elements if exist. + if (staticElement) { + const disabledNonTextElements = 'INPUT,SELECT,TEXTAREA,BUTTON,A'; + if (disabled) { + // Mute the text inside the current static element. + fitem.addClass('text-muted'); + // Disabled non-text elements in the static if exist. + fitem.all(disabledNonTextElements).each(function(disabledElement) { + if (disabledElement.get('tagName').toUpperCase() === "A") { + disabledElement.addClass('disabled'); + } else { + disabledElement.setAttribute('disabled', 'disabled'); + } + }); + } else { + // Unmute the text inside the current static element. + fitem.removeClass('text-muted'); + // Enabled non-text elements in the static if exist. + fitem.all(disabledNonTextElements).each(function(disabledElement) { + if (disabledElement.get('tagName').toUpperCase() === "A") { + disabledElement.removeClass('disabled'); + } else { + disabledElement.removeAttribute('disabled', 'disabled'); + } + }); + } + } // Extra code to disable filepicker or filemanager form elements if (filepicker) { - var fitem = node.ancestor('.fitem'); if (fitem) { if (disabled) { fitem.addClass('disabled'); @@ -363,6 +399,28 @@ if (typeof M.form.dependencyManager === 'undefined') { return false; }, + /** + * Checks if a form element with the given name is static. + * + * @param {string} el - The name of the form element to check. + * @returns {boolean} - Returns true if the form element is static, otherwise false. + */ + isStaticElement: function(el) { + if (!this._staticElements) { + const staticElements = {}; + const els = this.get('form').all('.fitem [data-fieldtype="static"] .form-control-static'); + els.each(function(node) { + if (node.getData('name') === el) { + staticElements[node.getData('name')] = true; + } + }); + this._staticElements = staticElements; + } + if (({}).hasOwnProperty.call(this._staticElements, el)) { + return this._staticElements[el] || false; + } + return false; + }, _dependencyNotchecked: function(elements, value, isHide) { var lock = false; elements.each(function() { diff --git a/lib/form/templates/element-static.mustache b/lib/form/templates/element-static.mustache index 409cd95ea4c..e8fa064d9dd 100644 --- a/lib/form/templates/element-static.mustache +++ b/lib/form/templates/element-static.mustache @@ -32,12 +32,20 @@ Example context (json): { "label": "Example label", - "element": { "html": "Example HTML", "staticlabel": true } + "element": { + "html": "Example HTML", + "staticlabel": true, + "extraclasses": null, + "name": "static_name", + "id": "id_static", + "wrapperid": "fitem_id_static", + "iderror": "id_error_static" + } } }} {{< core_form/element-template }} {{$element}} -
+
{{{element.html}}}
{{/element}} diff --git a/lib/form/tests/behat/disabledif.feature b/lib/form/tests/behat/disabledif.feature index 1cf4bcee4c6..97bcdabde4c 100644 --- a/lib/form/tests/behat/disabledif.feature +++ b/lib/form/tests/behat/disabledif.feature @@ -14,3 +14,15 @@ Feature: disabledIf functionality in forms Then the "disabled" attribute of "input#id_some_filemanager" "css_element" should contain "true" # Test file manager in a group. And the "disabled" attribute of "input#id_filemanager_group_some_filemanager_group" "css_element" should contain "true" + + Scenario: The static element is disabled when 'eq' disabledIf conditions are met + Given I am on fixture page "/lib/form/tests/behat/fixtures/static_hideif_disabledif_form.php" + And I should see "Static with form elements" + When I click on "Disable" "radio" + And the "class" attribute of "#fitem_id_some_static" "css_element" should contain "text-muted" + And the "disabled" attribute of "input#id_some_static_username" "css_element" should contain "true" + And the "disabled" attribute of "Check" "button" should contain "true" + Then I click on "Enable" "radio" + And the "class" attribute of "#fitem_id_some_static" "css_element" should not contain "text-muted" + And the "#id_some_static_username" "css_element" should be enabled + And the "class" attribute of "Check" "button" should not contain "disabled" diff --git a/lib/form/tests/behat/fixtures/static_hideif_disabledif_form.php b/lib/form/tests/behat/fixtures/static_hideif_disabledif_form.php new file mode 100644 index 00000000000..28a2f8ad58f --- /dev/null +++ b/lib/form/tests/behat/fixtures/static_hideif_disabledif_form.php @@ -0,0 +1,73 @@ +. + +require_once(__DIR__ . '/../../../../../config.php'); + +defined('BEHAT_SITE_RUNNING') || die(); + +global $CFG, $PAGE, $OUTPUT; +require_once($CFG->libdir . '/formslib.php'); +$PAGE->set_url('/lib/form/tests/behat/fixtures/static_hideif_disabledif_form.php'); +$PAGE->add_body_class('limitedwidth'); +require_login(); +$PAGE->set_context(core\context\system::instance()); + +/** + * Test class for hiding and disabling static elements. + * + * @package core_form + * @copyright Meirza + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class test_static_hideif_disabledif_form extends moodleform { + + /** + * Form definition. + */ + public function definition(): void { + $mform = $this->_form; + + // Radio buttons. + $radiogroup = [ + $mform->createElement('radio', 'some_radios', '', 'Enable', '1'), + $mform->createElement('radio', 'some_radios', '', 'Disable', '2'), + $mform->createElement('radio', 'some_radios', '', 'Hide', '3'), + ]; + + $mform->addGroup($radiogroup, 'some_radios_group', 'Enable/Disable/Hide', ' ', false); + $mform->setDefault('some_radios', 1); + + // Static element with conditions. + $mform->addElement( + 'static', + 'some_static', + 'Static element', + 'Static with form elements + + ', + ); + $mform->disabledIf('some_static', 'some_radios', 'eq', '2'); + $mform->hideIf('some_static', 'some_radios', 'eq', '3'); + + $this->add_action_buttons(); + } +} + +$form = new test_static_hideif_disabledif_form(); + +echo $OUTPUT->header(); +$form->display(); +echo $OUTPUT->footer(); diff --git a/lib/form/tests/behat/hideif.feature b/lib/form/tests/behat/hideif.feature index 4fd4c5772f0..768c116248b 100644 --- a/lib/form/tests/behat/hideif.feature +++ b/lib/form/tests/behat/hideif.feature @@ -31,3 +31,11 @@ Feature: hideIf functionality in forms And I should see "My test editor" When I click on "Hide" "radio" Then I should not see "My test editor" + + Scenario: The static element is hidden when 'eq' hideIf conditions are met + Given I am on fixture page "/lib/form/tests/behat/fixtures/static_hideif_disabledif_form.php" + And I should see "Static with form elements" + When I click on "Hide" "radio" + Then I should not see "Static with form elements" + And I click on "Enable" "radio" + And I should see "Static with form elements"