From 9c33aaa0fed33ed2ee524a1e5308f6d115cf7f26 Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Sat, 13 Jan 2018 17:58:46 +0100 Subject: [PATCH] Fix form field dependency-related issues See #2509 --- .../templates/__formContainerDependencies.tpl | 2 +- .../Field/Dependency/Container/Default.js | 5 ++ .../Builder/Field/Dependency/Container/Tab.js | 5 ++ .../Field/Dependency/Container/TabMenu.js | 5 ++ .../Form/Builder/Field/Dependency/Manager.js | 47 +++++++++++++++++-- .../system/form/builder/TFormNode.class.php | 23 +++++---- .../ValueFormFieldDependency.class.php | 2 +- 7 files changed, 73 insertions(+), 16 deletions(-) diff --git a/wcfsetup/install/files/acp/templates/__formContainerDependencies.tpl b/wcfsetup/install/files/acp/templates/__formContainerDependencies.tpl index e9daa97fde..20b7a7477e 100644 --- a/wcfsetup/install/files/acp/templates/__formContainerDependencies.tpl +++ b/wcfsetup/install/files/acp/templates/__formContainerDependencies.tpl @@ -1,6 +1,6 @@ {if !$container->getDependencies()|empty} diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default.js index 6432c3de53..67b4129db6 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default.js @@ -23,6 +23,11 @@ define(['./Abstract', 'Core', '../Manager'], function(Abstract, Core, Dependency * @see WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default#checkContainer */ checkContainer: function() { + // only consider containers that have not been hidden by their own dependencies + if (DependencyManager.isHiddenByDependencies(this._container)) { + return; + } + var containerIsVisible = !elIsHidden(this._container); var containerShouldBeVisible = false; diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Tab.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Tab.js index a561b89697..0a8c38b0b4 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Tab.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Tab.js @@ -23,6 +23,11 @@ define(['./Abstract', 'Core', 'Dom/Util', '../Manager'], function(Abstract, Core * @see WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default#checkContainer */ checkContainer: function() { + // only consider containers that have not been hidden by their own dependencies + if (DependencyManager.isHiddenByDependencies(this._container)) { + return; + } + var containerIsVisible = !elIsHidden(this._container); var containerShouldBeVisible = false; diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/TabMenu.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/TabMenu.js index e957a4275c..8f9b039d0a 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/TabMenu.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/TabMenu.js @@ -23,6 +23,11 @@ define(['./Abstract', 'Core', 'Dom/Util', '../Manager'], function(Abstract, Core * @see WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default#checkContainer */ checkContainer: function() { + // only consider containers that have not been hidden by their own dependencies + if (DependencyManager.isHiddenByDependencies(this._container)) { + return; + } + var containerIsVisible = !elIsHidden(this._container); var containerShouldBeVisible = false; diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager.js index 70e656a48c..fe8807ebe6 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager.js @@ -7,7 +7,7 @@ * @module WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager * @since 3.2 */ -define(['Dictionary', 'EventHandler'], function(Dictionary, EventHandler) { +define(['Dictionary', 'EventHandler', 'List'], function(Dictionary, EventHandler, List) { "use strict"; /** @@ -25,6 +25,13 @@ define(['Dictionary', 'EventHandler'], function(Dictionary, EventHandler) { */ var _checkContainersAgain = true; + /** + * list of containers hidden due to their own dependencies + * @type {List} + * @private + */ + var _dependencyHiddenNodes = new List(); + /** * list if fields for which event listeners have been registered * @type {Dictionary} @@ -40,6 +47,28 @@ define(['Dictionary', 'EventHandler'], function(Dictionary, EventHandler) { var _nodeDependencies = new Dictionary(); return { + /** + * Hides the given node because of its own dependencies. + * + * @param {HTMLElement} node hidden node + * @protected + */ + _hide: function(node) { + elHide(node); + _dependencyHiddenNodes.add(node.id); + }, + + /** + * Shows the given node because of its own dependencies. + * + * @param {HTMLElement} node shown node + * @protected + */ + _show: function(node) { + elShow(node); + _dependencyHiddenNodes.delete(node.id); + }, + /** * Registers a new form field dependency. * @@ -88,14 +117,14 @@ define(['Dictionary', 'EventHandler'], function(Dictionary, EventHandler) { for (var i = 0, length = nodeDependencies.length; i < length; i++) { // if any dependency is met, the element is visible if (nodeDependencies[i].checkDependency()) { - elShow(dependentNode); + this._show(dependentNode); return; } } // no node dependencies is met - elHide(dependentNode); - }); + this._hide(dependentNode); + }.bind(this)); // delete dependencies for removed elements for (var i = 0, length = obsoleteNodes.length; i < length; i++) { @@ -146,5 +175,15 @@ define(['Dictionary', 'EventHandler'], function(Dictionary, EventHandler) { this.checkContainers(); } }, + + /** + * Returns `true` if the given node has been hidden because of its own dependencies. + * + * @param {HTMLElement} node checked node + * @return {boolean} + */ + isHiddenByDependencies: function(node) { + return _dependencyHiddenNodes.has(container.id); + } }; }); diff --git a/wcfsetup/install/files/lib/system/form/builder/TFormNode.class.php b/wcfsetup/install/files/lib/system/form/builder/TFormNode.class.php index 26310dd5a3..2b92600a02 100644 --- a/wcfsetup/install/files/lib/system/form/builder/TFormNode.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/TFormNode.class.php @@ -114,6 +114,19 @@ trait TFormNode { * @return bool */ public function checkDependencies() { + if (!empty($this->dependencies)) { + $hasMetDependency = false; + foreach ($this->dependencies as $dependency) { + if ($dependency->checkDependency()) { + $hasMetDependency = true; + } + } + + if (!$hasMetDependency) { + return false; + } + } + if ($this instanceof IFormParentNode) { if (count($this) > 0) { /** @var IFormChildNode $child */ @@ -130,16 +143,6 @@ trait TFormNode { return false; } - if (!empty($this->dependencies)) { - foreach ($this->dependencies as $dependency) { - if ($dependency->checkDependency()) { - return true; - } - } - - return false; - } - return true; } diff --git a/wcfsetup/install/files/lib/system/form/builder/field/dependency/ValueFormFieldDependency.class.php b/wcfsetup/install/files/lib/system/form/builder/field/dependency/ValueFormFieldDependency.class.php index 0b06f0ea68..6340a9f158 100644 --- a/wcfsetup/install/files/lib/system/form/builder/field/dependency/ValueFormFieldDependency.class.php +++ b/wcfsetup/install/files/lib/system/form/builder/field/dependency/ValueFormFieldDependency.class.php @@ -26,7 +26,7 @@ class ValueFormFieldDependency extends AbstractFormFieldDependency { * @inheritDoc */ public function checkDependency() { - return !empty($this->getField()->getValue()); + return in_array($this->getField()->getValue(), $this->getValues()); } /** -- 2.20.1