mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
MDL-53848 form: add hideIf functionality
This commit is contained in:
parent
27466d7548
commit
d20498625c
@ -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
|
||||
};
|
||||
}
|
||||
}, {
|
||||
|
52
lib/form/tests/behat/hideif.feature
Normal file
52
lib/form/tests/behat/hideif.feature
Normal file
@ -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 | <a href="lib/form/tests/fixtures/formhideiftestpage.php">HideIfLink</a> | 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
|
83
lib/form/tests/fixtures/formhideiftestpage.php
vendored
Normal file
83
lib/form/tests/fixtures/formhideiftestpage.php
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* 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();
|
@ -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
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user