From d20498625cdac659f96a8373e1cdd1fc7aecd7bc Mon Sep 17 00:00:00 2001 From: Davo Smith Date: Mon, 19 Dec 2016 11:36:54 +0000 Subject: [PATCH 1/7] MDL-53848 form: add hideIf functionality --- lib/form/form.js | 68 ++++++++------- lib/form/tests/behat/hideif.feature | 52 ++++++++++++ .../tests/fixtures/formhideiftestpage.php | 83 +++++++++++++++++++ lib/formslib.php | 72 +++++++++++++++- 4 files changed, 240 insertions(+), 35 deletions(-) create mode 100644 lib/form/tests/behat/hideif.feature create mode 100644 lib/form/tests/fixtures/formhideiftestpage.php diff --git a/lib/form/form.js b/lib/form/form.js index 38e518bef44..13464fbaf31 100644 --- a/lib/form/form.js +++ b/lib/form/form.js @@ -69,8 +69,10 @@ if (typeof M.form.dependencyManager === 'undefined') { names[i] = new Y.NodeList(); for (var condition in conditions) { for (var value in conditions[condition]) { - for (var ei in conditions[condition][value]) { - names[conditions[condition][value][ei]] = new Y.NodeList(); + for (var hide in conditions[condition][value]) { + for (var ei in conditions[condition][value][hide]) { + names[conditions[condition][value][hide][ei]] = new Y.NodeList(); + } } } } @@ -118,7 +120,7 @@ if (typeof M.form.dependencyManager === 'undefined') { var dependencies = this.get('dependencies'), tohide = {}, tolock = {}, - condition, value, lock, hide, + condition, value, isHide, lock, hide, checkfunction, result, elements; if (!({}).hasOwnProperty.call(dependencies, dependon)) { return true; @@ -126,26 +128,28 @@ if (typeof M.form.dependencyManager === 'undefined') { elements = this.elementsByName(dependon); for (condition in dependencies[dependon]) { for (value in dependencies[dependon][condition]) { - checkfunction = '_dependency' + condition[0].toUpperCase() + condition.slice(1); - if (Y.Lang.isFunction(this[checkfunction])) { - result = this[checkfunction].apply(this, [elements, value, e]); - } else { - result = this._dependencyDefault(elements, value, e); - } - lock = result.lock || false; - hide = result.hide || false; - for (var ei in dependencies[dependon][condition][value]) { - var eltolock = dependencies[dependon][condition][value][ei]; - if (({}).hasOwnProperty.call(tohide, eltolock)) { - tohide[eltolock] = tohide[eltolock] || hide; + for (isHide in dependencies[dependon][condition][value]) { + checkfunction = '_dependency' + condition[0].toUpperCase() + condition.slice(1); + if (Y.Lang.isFunction(this[checkfunction])) { + result = this[checkfunction].apply(this, [elements, value, !!isHide, e]); } else { - tohide[eltolock] = hide; + result = this._dependencyDefault(elements, value, !!isHide, e); } + lock = result.lock || false; + hide = result.hide || false; + for (var ei in dependencies[dependon][condition][value][isHide]) { + var eltolock = dependencies[dependon][condition][value][isHide][ei]; + if (({}).hasOwnProperty.call(tohide, eltolock)) { + tohide[eltolock] = tohide[eltolock] || hide; + } else { + tohide[eltolock] = hide; + } - if (({}).hasOwnProperty.call(tolock, eltolock)) { - tolock[eltolock] = tolock[eltolock] || lock; - } else { - tolock[eltolock] = lock; + if (({}).hasOwnProperty.call(tolock, eltolock)) { + tolock[eltolock] = tolock[eltolock] || lock; + } else { + tolock[eltolock] = lock; + } } } } @@ -291,7 +295,7 @@ if (typeof M.form.dependencyManager === 'undefined') { return false; }, - _dependencyNotchecked: function(elements, value) { + _dependencyNotchecked: function(elements, value, isHide) { var lock = false; elements.each(function() { if (this.getAttribute('type').toLowerCase() == 'hidden' && @@ -306,10 +310,10 @@ if (typeof M.form.dependencyManager === 'undefined') { }); return { lock: lock, - hide: false + hide: isHide ? lock : false }; }, - _dependencyChecked: function(elements, value) { + _dependencyChecked: function(elements, value, isHide) { var lock = false; elements.each(function() { if (this.getAttribute('type').toLowerCase() == 'hidden' && @@ -324,20 +328,20 @@ if (typeof M.form.dependencyManager === 'undefined') { }); return { lock: lock, - hide: false + hide: isHide ? lock : false }; }, - _dependencyNoitemselected: function(elements, value) { + _dependencyNoitemselected: function(elements, value, isHide) { var lock = false; elements.each(function() { lock = lock || this.get('selectedIndex') == -1; }); return { lock: lock, - hide: false + hide: isHide ? lock : false }; }, - _dependencyEq: function(elements, value) { + _dependencyEq: function(elements, value, isHide) { var lock = false; var hiddenVal = false; var options, v, selected, values; @@ -391,7 +395,7 @@ if (typeof M.form.dependencyManager === 'undefined') { }); return { lock: lock, - hide: false + hide: isHide ? lock : false }; }, /** @@ -402,7 +406,7 @@ if (typeof M.form.dependencyManager === 'undefined') { * @returns {{lock: boolean, hide: boolean}} * @private */ - _dependencyIn: function(elements, values) { + _dependencyIn: function(elements, values, isHide) { // A pipe (|) is used as a value separator // when multiple values have to be passed on at the same time. values = values.split('|'); @@ -458,7 +462,7 @@ if (typeof M.form.dependencyManager === 'undefined') { }); return { lock: lock, - hide: false + hide: isHide ? lock : false }; }, _dependencyHide: function(elements, value) { @@ -467,7 +471,7 @@ if (typeof M.form.dependencyManager === 'undefined') { hide: true }; }, - _dependencyDefault: function(elements, value, ev) { + _dependencyDefault: function(elements, value, isHide) { var lock = false, hiddenVal = false, values @@ -521,7 +525,7 @@ if (typeof M.form.dependencyManager === 'undefined') { }); return { lock: lock, - hide: false + hide: isHide ? lock : false }; } }, { diff --git a/lib/form/tests/behat/hideif.feature b/lib/form/tests/behat/hideif.feature new file mode 100644 index 00000000000..864216a8fa7 --- /dev/null +++ b/lib/form/tests/behat/hideif.feature @@ -0,0 +1,52 @@ +@core @javascript +Feature: hideIf functionality in forms + For forms including hideIf functions + As a user + If I trigger the hideIf condition then the form elements will be hidden + + Background: + Given the following "activities" exist: + | activity | name | intro | course | section | idnumber | + | label | L1 | HideIfLink | Acceptance test site | 1 | L1 | + And I am on site homepage + And I follow "HideIfLink" + + Scenario: When 'eq' hideIf conditions are not met, the relevant elements are shown + When I set the field "Select yesno example" to "Yes" + Then I should see "Test eq hideif" + And "#id_testeqhideif" "css_element" should be visible + + Scenario: When 'eq' hideIf conditions are met, the relevant elements are hidden + When I set the field "Select yesno example" to "No" + Then I should not see "Test eq hideif" + And "#id_testeqhideif" "css_element" should not be visible + + Scenario: When 'checked' hideIf conditions are not met, the relevant elements are shown + When I set the field "Checkbox example" to "0" + Then I should see "Test checked hideif" + And "#id_testcheckedhideif" "css_element" should be visible + + Scenario: When 'checked' hideIf conditions are met, the relevant elements are hidden + When I set the field "Checkbox example" to "1" + Then I should not see "Test checked hideif" + And "#id_testcheckedhideif" "css_element" should not be visible + + Scenario: When 'notchecked' hideIf conditions are not met, the relevant elements are shown + When I set the field "Checkbox example" to "1" + Then I should see "Test not checked hideif" + And "#id_testnotcheckedhideif" "css_element" should be visible + + Scenario: When 'notchecked' hideIf conditions are met, the relevant elements are hidden + When I set the field "Checkbox example" to "0" + Then I should not see "Test not checked hideif" + And "#id_testnotcheckedhideif" "css_element" should not be visible + + Scenario: When 'in' hideIf conditions are not met, the relevant elements are shown + When I set the field "Select example" to "3" + Then I should see "Test in hideif" + And "#id_testinhideif" "css_element" should be visible + + Scenario: When 'in' hideIf conditions are met, the relevant elements are hidden + When I set the field "Select example" to "2" + Then I should not see "Test in hideif" + And "#id_testinhideif" "css_element" should not be visible diff --git a/lib/form/tests/fixtures/formhideiftestpage.php b/lib/form/tests/fixtures/formhideiftestpage.php new file mode 100644 index 00000000000..86a856ed0f7 --- /dev/null +++ b/lib/form/tests/fixtures/formhideiftestpage.php @@ -0,0 +1,83 @@ +. + +/** + * To support behat tests for hideif functionality (which is not yet used by any core forms). + * + * @package core + * @copyright 2016 Davo Smith, Synergy Learning + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(dirname(__FILE__).'/../../../../config.php'); +global $CFG, $PAGE, $OUTPUT; +require_once($CFG->libdir.'/formslib.php'); + +// Behat test fixture only. +defined('BEHAT_SITE_RUNNING') || die('Only available on Behat test server'); + +/** + * Class hideif_form + * @copyright 2016 Davo Smith, Synergy Learning + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class hideif_form extends moodleform { + + /** + * Form definition. + */ + protected function definition() { + $mform = $this->_form; + + // Use 'selectyesno' to show/hide element. + $mform->addElement('selectyesno', 'selectyesnoexample', 'Select yesno example'); + $mform->setDefault('selectyesnoexample', 0); + + $mform->addElement('text', 'testeqhideif', 'Test eq hideif'); + $mform->setType('testeqhideif', PARAM_TEXT); + $mform->hideIf('testeqhideif', 'selectyesnoexample', 'eq', 0); + + // Use 'checkbox' to show/hide element. + $mform->addElement('advcheckbox', 'checkboxexample', 'Checkbox example'); + $mform->setDefault('checkboxexample', 0); + + $mform->addElement('text', 'testcheckedhideif', 'Test checked hideif'); + $mform->setType('testcheckedhideif', PARAM_TEXT); + $mform->hideIf('testcheckedhideif', 'checkboxexample', 'checked'); + + $mform->addElement('text', 'testnotcheckedhideif', 'Test not checked hideif'); + $mform->setType('testnotcheckedhideif', PARAM_TEXT); + $mform->hideIf('testnotcheckedhideif', 'checkboxexample', 'notchecked'); + + // Use 'select' to show/hide element. + $opts = [1, 2, 3, 4, 5]; + $opts = array_combine($opts, $opts); + $mform->addElement('select', 'selectexample', 'Select example', $opts); + $mform->setDefault('selectexample', 1); + + $mform->addElement('text', 'testinhideif', 'Test in hideif'); + $mform->setType('testinhideif', PARAM_TEXT); + $mform->hideIf('testinhideif', 'selectexample', 'in', [1, 2, 5]); + } +} + +$PAGE->set_url('/lib/tests/fixtures/form_hideif.php'); +$PAGE->set_context(context_system::instance()); +$form = new hideif_form(); + +echo $OUTPUT->header(); +$form->display(); +echo $OUTPUT->footer(); diff --git a/lib/formslib.php b/lib/formslib.php index 965b0a4f51a..5c41ad2d9d9 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -1412,6 +1412,11 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { /** @var array dependent state for the element/'s */ var $_dependencies = array(); + /** + * @var array elements that will become hidden based on another element + */ + protected $_hideifs = array(); + /** @var array Array of buttons that if pressed do not result in the processing of the form. */ var $_noSubmitButtons=array(); @@ -1460,6 +1465,12 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { */ protected $clientvalidation = false; + /** + * Is this a 'disableIf' dependency of a 'hideIf' dependency? + */ + const DEP_DISABLE = 0; + const DEP_HIDE = 1; + /** * Class constructor - same parameters as HTML_QuickForm_DHTMLRulesTableless * @@ -2426,8 +2437,7 @@ require(["core/event", "jquery"], function(Event, $) { foreach ($conditions as $condition=>$values) { $result[$dependentOn][$condition] = array(); foreach ($values as $value=>$dependents) { - $result[$dependentOn][$condition][$value] = array(); - $i = 0; + $result[$dependentOn][$condition][$value][self::DEP_DISABLE] = array(); foreach ($dependents as $dependent) { $elements = $this->_getElNamesRecursive($dependent); if (empty($elements)) { @@ -2438,7 +2448,29 @@ require(["core/event", "jquery"], function(Event, $) { if ($element == $dependentOn) { continue; } - $result[$dependentOn][$condition][$value][] = $element; + $result[$dependentOn][$condition][$value][0][] = $element; + } + } + } + } + } + foreach ($this->_hideifs as $dependenton => $conditions){ + $result[$dependenton] = array(); + foreach ($conditions as $condition => $values) { + $result[$dependenton][$condition] = array(); + foreach ($values as $value => $dependents) { + $result[$dependenton][$condition][$value][self::DEP_HIDE] = array(); + foreach ($dependents as $dependent) { + $elements = $this->_getElNamesRecursive($dependent); + if (empty($elements)) { + // Probably element inside of some group. + $elements = array($dependent); + } + foreach ($elements as $element) { + if ($element == $dependenton) { + continue; + } + $result[$dependenton][$condition][$value][1][] = $element; } } } @@ -2533,6 +2565,40 @@ require(["core/event", "jquery"], function(Event, $) { $this->_dependencies[$dependentOn][$condition][$value][] = $elementName; } + /** + * Adds a dependency for $elementName which will be hidden if $condition is met. + * If $condition = 'notchecked' (default) then the condition is that the $dependentOn element + * is not checked. If $condition = 'checked' then the condition is that the $dependentOn element + * is checked. If $condition is something else (like "eq" for equals) then it is checked to see if the value + * of the $dependentOn element is $condition (such as equal) to $value. + * + * When working with multiple selects, the dependentOn has to be the real name of the select, meaning that + * it will most likely end up with '[]'. Also, the value should be an array of required values, or a string + * containing the values separated by pipes: array('red', 'blue') or 'red|blue'. + * + * @param string $elementname the name of the element which will be hidden + * @param string $dependenton the name of the element whose state will be checked for condition + * @param string $condition the condition to check + * @param mixed $value used in conjunction with condition. + */ + public function hideIf($elementname, $dependenton, $condition = 'notchecked', $value = '1') { + // Multiple selects allow for a multiple selection, we transform the array to string here as + // an array cannot be used as a key in an associative array. + if (is_array($value)) { + $value = implode('|', $value); + } + if (!array_key_exists($dependenton, $this->_hideifs)) { + $this->_hideifs[$dependenton] = array(); + } + if (!array_key_exists($condition, $this->_hideifs[$dependenton])) { + $this->_hideifs[$dependenton][$condition] = array(); + } + if (!array_key_exists($value, $this->_hideifs[$dependenton][$condition])) { + $this->_hideifs[$dependenton][$condition][$value] = array(); + } + $this->_hideifs[$dependenton][$condition][$value][] = $elementname; + } + /** * Registers button as no submit button * From f3da329da4b0923a8d030a0109749b5e30fd8306 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Fri, 27 Jan 2017 10:11:25 +0800 Subject: [PATCH 2/7] MDL-53848 forms: additions to the behat test --- lib/form/tests/behat/hideif.feature | 32 +++++++++++++------ .../tests/fixtures/formhideiftestpage.php | 10 ++++-- lib/formslib.php | 4 +-- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/lib/form/tests/behat/hideif.feature b/lib/form/tests/behat/hideif.feature index 864216a8fa7..26314cf5932 100644 --- a/lib/form/tests/behat/hideif.feature +++ b/lib/form/tests/behat/hideif.feature @@ -15,38 +15,52 @@ Feature: hideIf functionality in forms When I set the field "Select yesno example" to "Yes" Then I should see "Test eq hideif" And "#id_testeqhideif" "css_element" should be visible + And I press "Submit" + And I should see "Number of submitted form elements: 6" + And I should see "[testeqhideif] =>" Scenario: When 'eq' hideIf conditions are met, the relevant elements are hidden When I set the field "Select yesno example" to "No" Then I should not see "Test eq hideif" And "#id_testeqhideif" "css_element" should not be visible + And I press "Submit" + And I should see "Number of submitted form elements: 5" + And I should not see "[testeqhideif] =>" Scenario: When 'checked' hideIf conditions are not met, the relevant elements are shown When I set the field "Checkbox example" to "0" Then I should see "Test checked hideif" + And I should not see "Test not checked hideif" And "#id_testcheckedhideif" "css_element" should be visible + And "#id_testnotcheckedhideif" "css_element" should not be visible + And I press "Submit" + And I should see "Number of submitted form elements: 5" + And I should see "[testcheckedhideif] =>" + And I should not see "[testnotcheckedhideif] =>" Scenario: When 'checked' hideIf conditions are met, the relevant elements are hidden When I set the field "Checkbox example" to "1" Then I should not see "Test checked hideif" + And I should see "Test not checked hideif" And "#id_testcheckedhideif" "css_element" should not be visible - - Scenario: When 'notchecked' hideIf conditions are not met, the relevant elements are shown - When I set the field "Checkbox example" to "1" - Then I should see "Test not checked hideif" And "#id_testnotcheckedhideif" "css_element" should be visible - - Scenario: When 'notchecked' hideIf conditions are met, the relevant elements are hidden - When I set the field "Checkbox example" to "0" - Then I should not see "Test not checked hideif" - And "#id_testnotcheckedhideif" "css_element" should not be visible + And I press "Submit" + And I should see "Number of submitted form elements: 5" + And I should not see "[testcheckedhideif] =>" + And I should see "[testnotcheckedhideif] =>" Scenario: When 'in' hideIf conditions are not met, the relevant elements are shown When I set the field "Select example" to "3" Then I should see "Test in hideif" And "#id_testinhideif" "css_element" should be visible + And I press "Submit" + And I should see "Number of submitted form elements: 6" + And I should see "[testinhideif] =>" Scenario: When 'in' hideIf conditions are met, the relevant elements are hidden When I set the field "Select example" to "2" Then I should not see "Test in hideif" And "#id_testinhideif" "css_element" should not be visible + And I press "Submit" + And I should see "Number of submitted form elements: 5" + And I should not see "[testinhideif] =>" diff --git a/lib/form/tests/fixtures/formhideiftestpage.php b/lib/form/tests/fixtures/formhideiftestpage.php index 86a856ed0f7..722d1b09833 100644 --- a/lib/form/tests/fixtures/formhideiftestpage.php +++ b/lib/form/tests/fixtures/formhideiftestpage.php @@ -22,7 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once(dirname(__FILE__).'/../../../../config.php'); +require_once(__DIR__.'/../../../../config.php'); global $CFG, $PAGE, $OUTPUT; require_once($CFG->libdir.'/formslib.php'); @@ -71,13 +71,19 @@ class hideif_form extends moodleform { $mform->addElement('text', 'testinhideif', 'Test in hideif'); $mform->setType('testinhideif', PARAM_TEXT); $mform->hideIf('testinhideif', 'selectexample', 'in', [1, 2, 5]); + + $mform->addElement('submit', 'submitform', 'Submit'); } } -$PAGE->set_url('/lib/tests/fixtures/form_hideif.php'); +$PAGE->set_url('/lib/form/tests/fixtures/formhideiftestpage.php'); $PAGE->set_context(context_system::instance()); $form = new hideif_form(); echo $OUTPUT->header(); +if ($data = $form->get_data()) { + echo "

Number of submitted form elements: " . count((array)$data) . "

"; + print_object($data); +} $form->display(); echo $OUTPUT->footer(); diff --git a/lib/formslib.php b/lib/formslib.php index 5c41ad2d9d9..146a389cf84 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -2448,7 +2448,7 @@ require(["core/event", "jquery"], function(Event, $) { if ($element == $dependentOn) { continue; } - $result[$dependentOn][$condition][$value][0][] = $element; + $result[$dependentOn][$condition][$value][self::DEP_DISABLE][] = $element; } } } @@ -2470,7 +2470,7 @@ require(["core/event", "jquery"], function(Event, $) { if ($element == $dependenton) { continue; } - $result[$dependenton][$condition][$value][1][] = $element; + $result[$dependenton][$condition][$value][self::DEP_HIDE][] = $element; } } } From 988879655bfa5e93a6855073a9b7468208db1d32 Mon Sep 17 00:00:00 2001 From: Ankit Agarwal Date: Mon, 6 Mar 2017 10:20:12 +0530 Subject: [PATCH 3/7] MDL-53848 formslib: make conditional hidden elements properly accessible --- lib/form/form.js | 1 + lib/form/tests/behat/hideif.feature | 10 ++++++++-- lib/form/tests/fixtures/formhideiftestpage.php | 4 ++++ lib/formslib.php | 8 ++++++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/form/form.js b/lib/form/form.js index 13464fbaf31..3ed59b1afe3 100644 --- a/lib/form/form.js +++ b/lib/form/form.js @@ -266,6 +266,7 @@ if (typeof M.form.dependencyManager === 'undefined') { els.each(function(node) { var e = node.ancestor('.fitem'); if (e) { + (hidden) ? e.setAttribute('hidden', 'hidden') : e.removeAttribute('hidden'); e.setStyles({ display: (hidden) ? 'none' : '' }); diff --git a/lib/form/tests/behat/hideif.feature b/lib/form/tests/behat/hideif.feature index 26314cf5932..4856767e992 100644 --- a/lib/form/tests/behat/hideif.feature +++ b/lib/form/tests/behat/hideif.feature @@ -1,4 +1,4 @@ -@core @javascript +@core @javascript @core_form Feature: hideIf functionality in forms For forms including hideIf functions As a user @@ -8,7 +8,9 @@ Feature: hideIf functionality in forms Given the following "activities" exist: | activity | name | intro | course | section | idnumber | | label | L1 | HideIfLink | Acceptance test site | 1 | L1 | + And I log in as "admin" And I am on site homepage + And I wait "5" seconds And I follow "HideIfLink" Scenario: When 'eq' hideIf conditions are not met, the relevant elements are shown @@ -52,14 +54,18 @@ Feature: hideIf functionality in forms Scenario: When 'in' hideIf conditions are not met, the relevant elements are shown When I set the field "Select example" to "3" Then I should see "Test in hideif" + And I should see "Date time example" + And I should see "Files" And "#id_testinhideif" "css_element" should be visible And I press "Submit" - And I should see "Number of submitted form elements: 6" + And I should see "Number of submitted form elements: 8" And I should see "[testinhideif] =>" Scenario: When 'in' hideIf conditions are met, the relevant elements are hidden When I set the field "Select example" to "2" Then I should not see "Test in hideif" + And I should not see "Date time example" + And I should not see "Files" And "#id_testinhideif" "css_element" should not be visible And I press "Submit" And I should see "Number of submitted form elements: 5" diff --git a/lib/form/tests/fixtures/formhideiftestpage.php b/lib/form/tests/fixtures/formhideiftestpage.php index 722d1b09833..d6240c28d12 100644 --- a/lib/form/tests/fixtures/formhideiftestpage.php +++ b/lib/form/tests/fixtures/formhideiftestpage.php @@ -71,6 +71,10 @@ class hideif_form extends moodleform { $mform->addElement('text', 'testinhideif', 'Test in hideif'); $mform->setType('testinhideif', PARAM_TEXT); $mform->hideIf('testinhideif', 'selectexample', 'in', [1, 2, 5]); + $mform->addElement('date_time_selector', 'testdatetime', 'Date time example', array('optional' => true)); + $mform->hideIf('testdatetime', 'selectexample', 'in', [1, 2, 5]); + $mform->addElement('filemanager', 'files_filemanager', 'Files', null, array()); + $mform->hideIf('files_filemanager', 'selectexample', 'in', [1, 2, 5]); $mform->addElement('submit', 'submitform', 'Submit'); } diff --git a/lib/formslib.php b/lib/formslib.php index 146a389cf84..b8a50a51d38 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -1466,9 +1466,13 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { protected $clientvalidation = false; /** - * Is this a 'disableIf' dependency of a 'hideIf' dependency? + * Is this a 'disableIf' dependency ? */ const DEP_DISABLE = 0; + + /** + * Is this a 'hideIf' dependency? + */ const DEP_HIDE = 1; /** @@ -2454,7 +2458,7 @@ require(["core/event", "jquery"], function(Event, $) { } } } - foreach ($this->_hideifs as $dependenton => $conditions){ + foreach ($this->_hideifs as $dependenton => $conditions) { $result[$dependenton] = array(); foreach ($conditions as $condition => $values) { $result[$dependenton][$condition] = array(); From 766d6f9a618eda634d3fef0b5a3c735471fc7b9a Mon Sep 17 00:00:00 2001 From: Davo Smith Date: Fri, 14 Jul 2017 12:02:13 +0100 Subject: [PATCH 4/7] MDL-53848 form: hide entire group if hideIf test is applied to the group --- lib/form/form.js | 9 ++++++++- lib/form/group.php | 1 + lib/form/templates/element-template.mustache | 2 +- lib/formslib.php | 6 +++--- .../templates/core_form/element-template-inline.mustache | 2 +- .../boost/templates/core_form/element-template.mustache | 2 +- 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/form/form.js b/lib/form/form.js index 3ed59b1afe3..79a3844df48 100644 --- a/lib/form/form.js +++ b/lib/form/form.js @@ -85,6 +85,13 @@ if (typeof M.form.dependencyManager === 'undefined') { names[name].push(node); } }); + // Locate any groups with the given name. + this.get('form').all('.fitem').each(function(node) { + var name = node.getData('groupname'); + if (name && ({}).hasOwnProperty.call(names, name)) { + names[name].push(node); + } + }); this._nameCollections = names; }, @@ -264,7 +271,7 @@ if (typeof M.form.dependencyManager === 'undefined') { _hideElement: function(name, hidden) { var els = this.elementsByName(name); els.each(function(node) { - var e = node.ancestor('.fitem'); + var e = node.ancestor('.fitem', true); if (e) { (hidden) ? e.setAttribute('hidden', 'hidden') : e.removeAttribute('hidden'); e.setStyles({ diff --git a/lib/form/group.php b/lib/form/group.php index da9359ddbea..f4f241fd045 100644 --- a/lib/form/group.php +++ b/lib/form/group.php @@ -213,6 +213,7 @@ class MoodleQuickForm_group extends HTML_QuickForm_group implements templatable $i++; } + $context['groupname'] = $name; $context['elements'] = $elements; return $context; } diff --git a/lib/form/templates/element-template.mustache b/lib/form/templates/element-template.mustache index 9463064f2e9..cc1195ad53c 100644 --- a/lib/form/templates/element-template.mustache +++ b/lib/form/templates/element-template.mustache @@ -46,7 +46,7 @@ } }} -
+
{{{ helpbutton }}} diff --git a/lib/formslib.php b/lib/formslib.php index b8a50a51d38..66527b655b3 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -2466,9 +2466,9 @@ require(["core/event", "jquery"], function(Event, $) { $result[$dependenton][$condition][$value][self::DEP_HIDE] = array(); foreach ($dependents as $dependent) { $elements = $this->_getElNamesRecursive($dependent); - if (empty($elements)) { - // Probably element inside of some group. - $elements = array($dependent); + if (!in_array($dependent, $elements)) { + // Always want to hide the main element, even if it contains sub-elements as well. + $elements[] = $dependent; } foreach ($elements as $element) { if ($element == $dependenton) { diff --git a/theme/boost/templates/core_form/element-template-inline.mustache b/theme/boost/templates/core_form/element-template-inline.mustache index 88593fccdcb..95f1fa79c87 100644 --- a/theme/boost/templates/core_form/element-template-inline.mustache +++ b/theme/boost/templates/core_form/element-template-inline.mustache @@ -1,4 +1,4 @@ -
+