From 44ecd4b27c1c8430784762352c424b8967f963e3 Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Tue, 15 Dec 2020 18:48:39 +0100 Subject: [PATCH] Apply changes from code review to form builder TypeScript code --- .../Form/Builder/Field/Dependency/Abstract.js | 6 +- .../Field/Dependency/Container/Abstract.js | 6 +- .../Field/Dependency/Container/Default.js | 8 +- .../Builder/Field/Dependency/Container/Tab.js | 8 +- .../Field/Dependency/Container/TabMenu.js | 8 +- .../Builder/Field/Dependency/IsNotClicked.js | 13 +- .../Form/Builder/Field/Dependency/Manager.js | 426 ++++++++-------- .../WoltLabSuite/Core/Form/Builder/Manager.js | 6 +- .../Form/Builder/Field/Controller/Label.ts | 2 +- .../Form/Builder/Field/Controller/Rating.ts | 12 +- .../Form/Builder/Field/Dependency/Abstract.ts | 4 +- .../Field/Dependency/Container/Abstract.ts | 4 +- .../Field/Dependency/Container/Default.ts | 2 +- .../Builder/Field/Dependency/Container/Tab.ts | 2 +- .../Field/Dependency/Container/TabMenu.ts | 2 +- .../Builder/Field/Dependency/IsNotClicked.ts | 11 +- .../Form/Builder/Field/Dependency/Manager.ts | 456 +++++++++--------- .../WoltLabSuite/Core/Form/Builder/Manager.ts | 2 +- 18 files changed, 486 insertions(+), 492 deletions(-) diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract.js index a510097ffc..06302e73ba 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract.js @@ -7,9 +7,9 @@ * @module WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract * @since 5.2 */ -define(["require", "exports", "tslib", "./Manager", "../../../../Core"], function (require, exports, tslib_1, Manager_1, Core) { +define(["require", "exports", "tslib", "./Manager", "../../../../Core"], function (require, exports, tslib_1, DependencyManager, Core) { "use strict"; - Manager_1 = tslib_1.__importDefault(Manager_1); + DependencyManager = tslib_1.__importStar(DependencyManager); Core = tslib_1.__importStar(Core); class FormBuilderFormFieldDependency { constructor(dependentElementId, fieldId) { @@ -77,7 +77,7 @@ define(["require", "exports", "tslib", "./Manager", "../../../../Core"], functio this._fields.push(this._noField); } } - Manager_1.default.addDependency(this); + DependencyManager.addDependency(this); } } Core.enableLegacyInheritance(FormBuilderFormFieldDependency); diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Abstract.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Abstract.js index 8bcbe8a5e0..a879f9c4fb 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Abstract.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Abstract.js @@ -8,9 +8,9 @@ * @module WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Abstract * @since 5.2 */ -define(["require", "exports", "tslib", "../Manager", "../../../../../Core"], function (require, exports, tslib_1, Manager_1, Core) { +define(["require", "exports", "tslib", "../Manager", "../../../../../Core"], function (require, exports, tslib_1, DependencyManager, Core) { "use strict"; - Manager_1 = tslib_1.__importDefault(Manager_1); + DependencyManager = tslib_1.__importStar(DependencyManager); Core = tslib_1.__importStar(Core); class Abstract { constructor(containerId) { @@ -33,7 +33,7 @@ define(["require", "exports", "tslib", "../Manager", "../../../../../Core"], fun if (this._container === null) { throw new Error("Unknown container with id '" + containerId + "'."); } - Manager_1.default.addContainerCheckCallback(() => this.checkContainer()); + DependencyManager.addContainerCheckCallback(() => this.checkContainer()); } } Core.enableLegacyInheritance(Abstract); 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 036d564490..567afbdfca 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 @@ -9,18 +9,18 @@ * @see module:WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract * @since 5.2 */ -define(["require", "exports", "tslib", "./Abstract", "../../../../../Core", "../Manager"], function (require, exports, tslib_1, Abstract_1, Core, Manager_1) { +define(["require", "exports", "tslib", "./Abstract", "../../../../../Core", "../Manager"], function (require, exports, tslib_1, Abstract_1, Core, DependencyManager) { "use strict"; Abstract_1 = tslib_1.__importDefault(Abstract_1); Core = tslib_1.__importStar(Core); - Manager_1 = tslib_1.__importDefault(Manager_1); + DependencyManager = tslib_1.__importStar(DependencyManager); class Default extends Abstract_1.default { checkContainer() { if (Core.stringToBool(this._container.dataset.ignoreDependencies || "")) { return; } // only consider containers that have not been hidden by their own dependencies - if (Manager_1.default.isHiddenByDependencies(this._container)) { + if (DependencyManager.isHiddenByDependencies(this._container)) { return; } const containerIsVisible = this._container.style.display !== "none"; @@ -40,7 +40,7 @@ define(["require", "exports", "tslib", "./Abstract", "../../../../../Core", "../ } // check containers again to make sure parent containers can react to // changing the visibility of this container - Manager_1.default.checkContainers(); + DependencyManager.checkContainers(); } } } 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 d4a2898a66..048f5ac311 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 @@ -9,17 +9,17 @@ * @see module:WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract * @since 5.2 */ -define(["require", "exports", "tslib", "./Abstract", "../Manager", "../../../../../Dom/Util", "../../../../../Ui/TabMenu", "../../../../../Core"], function (require, exports, tslib_1, Abstract_1, Manager_1, DomUtil, UiTabMenu, Core) { +define(["require", "exports", "tslib", "./Abstract", "../Manager", "../../../../../Dom/Util", "../../../../../Ui/TabMenu", "../../../../../Core"], function (require, exports, tslib_1, Abstract_1, DependencyManager, DomUtil, UiTabMenu, Core) { "use strict"; Abstract_1 = tslib_1.__importDefault(Abstract_1); - Manager_1 = tslib_1.__importDefault(Manager_1); + DependencyManager = tslib_1.__importStar(DependencyManager); DomUtil = tslib_1.__importStar(DomUtil); UiTabMenu = tslib_1.__importStar(UiTabMenu); Core = tslib_1.__importStar(Core); class Tab extends Abstract_1.default { checkContainer() { // only consider containers that have not been hidden by their own dependencies - if (Manager_1.default.isHiddenByDependencies(this._container)) { + if (DependencyManager.isHiddenByDependencies(this._container)) { return; } const containerIsVisible = this._container.style.display !== "none"; @@ -50,7 +50,7 @@ define(["require", "exports", "tslib", "./Abstract", "../Manager", "../../../../ } // Check containers again to make sure parent containers can react to changing the visibility // of this container. - Manager_1.default.checkContainers(); + DependencyManager.checkContainers(); } } } 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 b6dafd9c82..8b98bd216e 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 @@ -9,17 +9,17 @@ * @see module:WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract * @since 5.2 */ -define(["require", "exports", "tslib", "./Abstract", "../Manager", "../../../../../Dom/Util", "../../../../../Ui/TabMenu", "../../../../../Core"], function (require, exports, tslib_1, Abstract_1, Manager_1, DomUtil, UiTabMenu, Core) { +define(["require", "exports", "tslib", "./Abstract", "../Manager", "../../../../../Dom/Util", "../../../../../Ui/TabMenu", "../../../../../Core"], function (require, exports, tslib_1, Abstract_1, DependencyManager, DomUtil, UiTabMenu, Core) { "use strict"; Abstract_1 = tslib_1.__importDefault(Abstract_1); - Manager_1 = tslib_1.__importDefault(Manager_1); + DependencyManager = tslib_1.__importStar(DependencyManager); DomUtil = tslib_1.__importStar(DomUtil); UiTabMenu = tslib_1.__importStar(UiTabMenu); Core = tslib_1.__importStar(Core); class TabMenu extends Abstract_1.default { checkContainer() { // only consider containers that have not been hidden by their own dependencies - if (Manager_1.default.isHiddenByDependencies(this._container)) { + if (DependencyManager.isHiddenByDependencies(this._container)) { return; } const containerIsVisible = this._container.style.display !== "none"; @@ -37,7 +37,7 @@ define(["require", "exports", "tslib", "./Abstract", "../Manager", "../../../../ } // check containers again to make sure parent containers can react to // changing the visibility of this container - Manager_1.default.checkContainers(); + DependencyManager.checkContainers(); } } } diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/IsNotClicked.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/IsNotClicked.js index c13fc9aeac..1496492b96 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/IsNotClicked.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Field/Dependency/IsNotClicked.js @@ -8,11 +8,12 @@ * @see module:WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract * @since 5.4 */ -define(["require", "exports", "tslib", "./Abstract", "./Manager", "../../../../Core"], function (require, exports, tslib_1, Abstract_1, Manager_1, Core) { +define(["require", "exports", "tslib", "./Abstract", "./Manager"], function (require, exports, tslib_1, Abstract_1, DependencyManager) { "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.IsNotClicked = void 0; Abstract_1 = tslib_1.__importDefault(Abstract_1); - Manager_1 = tslib_1.__importDefault(Manager_1); - Core = tslib_1.__importStar(Core); + DependencyManager = tslib_1.__importStar(DependencyManager); class IsNotClicked extends Abstract_1.default { constructor(dependentElementId, fieldId) { super(dependentElementId, fieldId); @@ -21,13 +22,13 @@ define(["require", "exports", "tslib", "./Abstract", "./Manager", "../../../../C // events. this._field.addEventListener("click", () => { this._field.dataset.isClicked = "1"; - Manager_1.default.checkDependencies(); + DependencyManager.checkDependencies(); }); } checkDependency() { return this._field.dataset.isClicked !== "1"; } } - Core.enableLegacyInheritance(IsNotClicked); - return IsNotClicked; + exports.IsNotClicked = IsNotClicked; + exports.default = IsNotClicked; }); 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 67192de4e2..ce506f334f 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,245 +7,249 @@ * @module WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager * @since 5.2 */ -define(["require", "exports", "tslib", "../../../../Dom/Util", "../../../../Event/Handler", "../../../../Core"], function (require, exports, tslib_1, Util_1, EventHandler, Core) { +define(["require", "exports", "tslib", "../../../../Dom/Util", "../../../../Event/Handler"], function (require, exports, tslib_1, Util_1, EventHandler) { "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.unregister = exports.register = exports.isHiddenByDependencies = exports.checkDependencies = exports.checkContainers = exports.addDependency = exports.addContainerCheckCallback = void 0; Util_1 = tslib_1.__importDefault(Util_1); EventHandler = tslib_1.__importStar(EventHandler); - Core = tslib_1.__importStar(Core); const _dependencyHiddenNodes = new Set(); const _fields = new Map(); - const _forms = new Set(); + const _forms = new WeakSet(); const _nodeDependencies = new Map(); const _validatedFieldProperties = new WeakMap(); let _checkingContainers = false; let _checkContainersAgain = true; - const Manager = { - /** - * Hides the given node because of its own dependencies. - */ - _hide(node) { - node.style.display = "none"; - _dependencyHiddenNodes.add(node); - // also hide tab menu entry - if (node.classList.contains("tabMenuContent")) { - node - .parentNode.querySelector(".tabMenu") - .querySelectorAll("li") - .forEach((tabLink) => { - if (tabLink.dataset.name === node.dataset.name) { - tabLink.style.display = "none"; - } - }); - } - node.querySelectorAll("[max], [maxlength], [min], [required]").forEach((validatedField) => { - const properties = new Map(); - const max = validatedField.getAttribute("max"); - if (max) { - properties.set("max", max); - validatedField.removeAttribute("max"); - } - const maxlength = validatedField.getAttribute("maxlength"); - if (maxlength) { - properties.set("maxlength", maxlength); - validatedField.removeAttribute("maxlength"); + /** + * Hides the given node because of its own dependencies. + */ + function _hide(node) { + node.style.display = "none"; + _dependencyHiddenNodes.add(node); + // also hide tab menu entry + if (node.classList.contains("tabMenuContent")) { + node + .parentNode.querySelector(".tabMenu") + .querySelectorAll("li") + .forEach((tabLink) => { + if (tabLink.dataset.name === node.dataset.name) { + tabLink.style.display = "none"; } - const min = validatedField.getAttribute("min"); - if (min) { - properties.set("min", min); - validatedField.removeAttribute("min"); - } - if (validatedField.required) { - properties.set("required", "true"); - validatedField.removeAttribute("required"); - } - _validatedFieldProperties.set(validatedField, properties); }); - }, - /** - * Shows the given node because of its own dependencies. - */ - _show(node) { - node.style.display = "block"; - _dependencyHiddenNodes.delete(node); - // also show tab menu entry - if (node.classList.contains("tabMenuContent")) { - node - .parentNode.querySelector(".tabMenu") - .querySelectorAll("li") - .forEach((tabLink) => { - if (tabLink.dataset.name === node.dataset.name) { - tabLink.style.display = "block"; - } - }); + } + node.querySelectorAll("[max], [maxlength], [min], [required]").forEach((validatedField) => { + const properties = new Map(); + const max = validatedField.getAttribute("max"); + if (max) { + properties.set("max", max); + validatedField.removeAttribute("max"); } - node.querySelectorAll("input, select").forEach((validatedField) => { - // if a container is shown, ignore all fields that - // have a hidden parent element within the container - let parentNode = validatedField.parentNode; - while (parentNode !== node && parentNode.style.getPropertyValue("display") !== "none") { - parentNode = parentNode.parentNode; - } - if (parentNode === node && _validatedFieldProperties.has(validatedField)) { - const properties = _validatedFieldProperties.get(validatedField); - if (properties.has("max")) { - validatedField.setAttribute("max", properties.get("max")); - } - if (properties.has("maxlength")) { - validatedField.setAttribute("maxlength", properties.get("maxlength")); - } - if (properties.has("min")) { - validatedField.setAttribute("min", properties.get("min")); - } - if (properties.has("required")) { - validatedField.setAttribute("required", ""); - } - _validatedFieldProperties.delete(validatedField); - } - }); - }, - /** - * Adds the given callback to the list of callbacks called when checking containers. - */ - addContainerCheckCallback(callback) { - if (typeof callback !== "function") { - throw new TypeError("Expected a valid callback for parameter 'callback'."); + const maxlength = validatedField.getAttribute("maxlength"); + if (maxlength) { + properties.set("maxlength", maxlength); + validatedField.removeAttribute("maxlength"); } - EventHandler.add("com.woltlab.wcf.form.builder.dependency", "checkContainers", callback); - }, - /** - * Registers a new form field dependency. - */ - addDependency(dependency) { - const dependentNode = dependency.getDependentNode(); - if (!_nodeDependencies.has(dependentNode.id)) { - _nodeDependencies.set(dependentNode.id, [dependency]); + const min = validatedField.getAttribute("min"); + if (min) { + properties.set("min", min); + validatedField.removeAttribute("min"); } - else { - _nodeDependencies.get(dependentNode.id).push(dependency); + if (validatedField.required) { + properties.set("required", "true"); + validatedField.removeAttribute("required"); } - dependency.getFields().forEach((field) => { - const id = Util_1.default.identify(field); - if (!_fields.has(id)) { - _fields.set(id, field); - if (field.tagName === "INPUT" && - (field.type === "checkbox" || - field.type === "radio" || - field.type === "hidden")) { - field.addEventListener("change", () => this.checkDependencies()); - } - else { - field.addEventListener("input", () => this.checkDependencies()); - } + _validatedFieldProperties.set(validatedField, properties); + }); + } + /** + * Shows the given node because of its own dependencies. + */ + function _show(node) { + node.style.display = "block"; + _dependencyHiddenNodes.delete(node); + // also show tab menu entry + if (node.classList.contains("tabMenuContent")) { + node + .parentNode.querySelector(".tabMenu") + .querySelectorAll("li") + .forEach((tabLink) => { + if (tabLink.dataset.name === node.dataset.name) { + tabLink.style.display = "block"; } }); - }, - /** - * Checks the containers for their availability. - * - * If this function is called while containers are currently checked, the containers - * will be checked after the current check has been finished completely. - */ - checkContainers() { - // check if containers are currently being checked - if (_checkingContainers === true) { - // and if that is the case, calling this method indicates, that after the current round, - // containters should be checked to properly propagate changes in children to their parents - _checkContainersAgain = true; - return; + } + node.querySelectorAll("input, select").forEach((validatedField) => { + // if a container is shown, ignore all fields that + // have a hidden parent element within the container + let parentNode = validatedField.parentNode; + while (parentNode !== node && parentNode.style.getPropertyValue("display") !== "none") { + parentNode = parentNode.parentNode; } - // starting to check containers also resets the flag to check containers again after the current check - _checkingContainers = true; - _checkContainersAgain = false; - EventHandler.fire("com.woltlab.wcf.form.builder.dependency", "checkContainers"); - // finish checking containers and check if containters should be checked again - _checkingContainers = false; - if (_checkContainersAgain) { - this.checkContainers(); + if (parentNode === node && _validatedFieldProperties.has(validatedField)) { + const properties = _validatedFieldProperties.get(validatedField); + if (properties.has("max")) { + validatedField.setAttribute("max", properties.get("max")); + } + if (properties.has("maxlength")) { + validatedField.setAttribute("maxlength", properties.get("maxlength")); + } + if (properties.has("min")) { + validatedField.setAttribute("min", properties.get("min")); + } + if (properties.has("required")) { + validatedField.setAttribute("required", ""); + } + _validatedFieldProperties.delete(validatedField); } - }, - /** - * Checks if all dependencies are met. - */ - checkDependencies() { - const obsoleteNodeIds = []; - _nodeDependencies.forEach((nodeDependencies, nodeId) => { - const dependentNode = document.getElementById(nodeId); - if (dependentNode === null) { - obsoleteNodeIds.push(nodeId); - return; + }); + } + /** + * Adds the given callback to the list of callbacks called when checking containers. + */ + function addContainerCheckCallback(callback) { + if (typeof callback !== "function") { + throw new TypeError("Expected a valid callback for parameter 'callback'."); + } + EventHandler.add("com.woltlab.wcf.form.builder.dependency", "checkContainers", callback); + } + exports.addContainerCheckCallback = addContainerCheckCallback; + /** + * Registers a new form field dependency. + */ + function addDependency(dependency) { + const dependentNode = dependency.getDependentNode(); + if (!_nodeDependencies.has(dependentNode.id)) { + _nodeDependencies.set(dependentNode.id, [dependency]); + } + else { + _nodeDependencies.get(dependentNode.id).push(dependency); + } + dependency.getFields().forEach((field) => { + const id = Util_1.default.identify(field); + if (!_fields.has(id)) { + _fields.set(id, field); + if (field.tagName === "INPUT" && + (field.type === "checkbox" || + field.type === "radio" || + field.type === "hidden")) { + field.addEventListener("change", () => checkDependencies()); } - let dependenciesMet = true; - nodeDependencies.forEach((dependency) => { - if (!dependency.checkDependency()) { - this._hide(dependentNode); - dependenciesMet = false; - } - }); - if (dependenciesMet) { - this._show(dependentNode); + else { + field.addEventListener("input", () => checkDependencies()); } - }); - obsoleteNodeIds.forEach((id) => _nodeDependencies.delete(id)); - this.checkContainers(); - }, - /** - * Returns `true` if the given node has been hidden because of its own dependencies. - */ - isHiddenByDependencies(node) { - if (_dependencyHiddenNodes.has(node)) { - return true; } - let returnValue = false; - _dependencyHiddenNodes.forEach((hiddenNode) => { - if (node.contains(hiddenNode)) { - returnValue = true; + }); + } + exports.addDependency = addDependency; + /** + * Checks the containers for their availability. + * + * If this function is called while containers are currently checked, the containers + * will be checked after the current check has been finished completely. + */ + function checkContainers() { + // check if containers are currently being checked + if (_checkingContainers === true) { + // and if that is the case, calling this method indicates, that after the current round, + // containters should be checked to properly propagate changes in children to their parents + _checkContainersAgain = true; + return; + } + // starting to check containers also resets the flag to check containers again after the current check + _checkingContainers = true; + _checkContainersAgain = false; + EventHandler.fire("com.woltlab.wcf.form.builder.dependency", "checkContainers"); + // finish checking containers and check if containters should be checked again + _checkingContainers = false; + if (_checkContainersAgain) { + checkContainers(); + } + } + exports.checkContainers = checkContainers; + /** + * Checks if all dependencies are met. + */ + function checkDependencies() { + const obsoleteNodeIds = []; + _nodeDependencies.forEach((nodeDependencies, nodeId) => { + const dependentNode = document.getElementById(nodeId); + if (dependentNode === null) { + obsoleteNodeIds.push(nodeId); + return; + } + let dependenciesMet = true; + nodeDependencies.forEach((dependency) => { + if (!dependency.checkDependency()) { + _hide(dependentNode); + dependenciesMet = false; } }); - return returnValue; - }, - /** - * Registers the form with the given id with the dependency manager. - */ - register(formId) { - const form = document.getElementById(formId); - if (form === null) { - throw new Error("Unknown element with id '" + formId + "'"); + if (dependenciesMet) { + _show(dependentNode); } - if (_forms.has(form)) { - throw new Error("Form with id '" + formId + "' has already been registered."); + }); + obsoleteNodeIds.forEach((id) => _nodeDependencies.delete(id)); + checkContainers(); + } + exports.checkDependencies = checkDependencies; + /** + * Returns `true` if the given node has been hidden because of its own dependencies. + */ + function isHiddenByDependencies(node) { + if (_dependencyHiddenNodes.has(node)) { + return true; + } + let returnValue = false; + _dependencyHiddenNodes.forEach((hiddenNode) => { + if (node.contains(hiddenNode)) { + returnValue = true; } - _forms.add(form); - }, - /** - * Unregisters the form with the given id and all of its dependencies. - */ - unregister(formId) { - const form = document.getElementById(formId); - if (form === null) { - throw new Error("Unknown element with id '" + formId + "'"); + }); + return returnValue; + } + exports.isHiddenByDependencies = isHiddenByDependencies; + /** + * Registers the form with the given id with the dependency manager. + */ + function register(formId) { + const form = document.getElementById(formId); + if (form === null) { + throw new Error("Unknown element with id '" + formId + "'"); + } + if (_forms.has(form)) { + throw new Error("Form with id '" + formId + "' has already been registered."); + } + _forms.add(form); + } + exports.register = register; + /** + * Unregisters the form with the given id and all of its dependencies. + */ + function unregister(formId) { + const form = document.getElementById(formId); + if (form === null) { + throw new Error("Unknown element with id '" + formId + "'"); + } + if (!_forms.has(form)) { + throw new Error("Form with id '" + formId + "' has not been registered."); + } + _forms.delete(form); + _dependencyHiddenNodes.forEach((hiddenNode) => { + if (form.contains(hiddenNode)) { + _dependencyHiddenNodes.delete(hiddenNode); } - if (!_forms.has(form)) { - throw new Error("Form with id '" + formId + "' has not been registered."); + }); + _nodeDependencies.forEach((dependencies, nodeId) => { + if (form.contains(document.getElementById(nodeId))) { + _nodeDependencies.delete(nodeId); } - _forms.delete(form); - _dependencyHiddenNodes.forEach((hiddenNode) => { - if (form.contains(hiddenNode)) { - _dependencyHiddenNodes.delete(hiddenNode); - } - }); - _nodeDependencies.forEach((dependencies, nodeId) => { - if (form.contains(document.getElementById(nodeId))) { - _nodeDependencies.delete(nodeId); - } - dependencies.forEach((dependency) => { - dependency.getFields().forEach((field) => { - _fields.delete(field.id); - _validatedFieldProperties.delete(field); - }); + dependencies.forEach((dependency) => { + dependency.getFields().forEach((field) => { + _fields.delete(field.id); + _validatedFieldProperties.delete(field); }); }); - }, - }; - Core.enableLegacyInheritance(Manager); - return Manager; + }); + } + exports.unregister = unregister; }); diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Manager.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Manager.js index 927c9ff8be..a120e7d1cb 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Manager.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Manager.js @@ -8,14 +8,14 @@ * @module WoltLabSuite/Core/Form/Builder/Manager * @since 5.2 */ -define(["require", "exports", "tslib", "../../Core", "../../Event/Handler", "./Field/Field", "./Field/Dependency/Manager"], function (require, exports, tslib_1, Core, EventHandler, Field_1, Manager_1) { +define(["require", "exports", "tslib", "../../Core", "../../Event/Handler", "./Field/Field", "./Field/Dependency/Manager"], function (require, exports, tslib_1, Core, EventHandler, Field_1, DependencyManager) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.unregisterForm = exports.registerForm = exports.registerField = exports.hasForm = exports.hasField = exports.getForm = exports.getField = exports.getData = void 0; Core = tslib_1.__importStar(Core); EventHandler = tslib_1.__importStar(EventHandler); Field_1 = tslib_1.__importDefault(Field_1); - Manager_1 = tslib_1.__importDefault(Manager_1); + DependencyManager = tslib_1.__importStar(DependencyManager); const _fields = new Map(); const _forms = new Map(); /** @@ -132,7 +132,7 @@ define(["require", "exports", "tslib", "../../Core", "../../Event/Handler", "./F field.destroy(); }); _fields.delete(formId); - Manager_1.default.unregister(formId); + DependencyManager.unregister(formId); EventHandler.fire("WoltLabSuite/Core/Form/Builder/Manager", "afterUnregisterForm", { formId: formId, }); diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/Label.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/Label.ts index 01ce705e3e..91096faa8b 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/Label.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/Label.ts @@ -20,7 +20,7 @@ class Label { protected readonly _labelChooser: HTMLElement; protected readonly _options: LabelFormFieldOptions; - constructor(fieldId: string, labelId: string, options: LabelFormFieldOptions) { + constructor(fieldId: string, labelId: string, options: Partial) { this._formFieldContainer = document.getElementById(fieldId + "Container")!; this._labelChooser = this._formFieldContainer.getElementsByClassName("labelChooser")[0] as HTMLElement; this._options = Core.extend( diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/Rating.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/Rating.ts index 38d2009ca4..ec5e8da63a 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/Rating.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Controller/Rating.ts @@ -56,7 +56,7 @@ class Rating { /** * Saves the rating associated with the clicked rating element. */ - _listItemClick(event: Event): void { + protected _listItemClick(event: Event): void { const target = event.currentTarget as HTMLElement; this._input.value = target.dataset.rating!; @@ -68,7 +68,7 @@ class Rating { /** * Updates the rating UI when hovering over a rating element. */ - _listItemMouseEnter(event: Event): void { + protected _listItemMouseEnter(event: Event): void { const target = event.currentTarget as HTMLElement; const currentRating = target.dataset.rating!; @@ -83,7 +83,7 @@ class Rating { * Updates the rating UI when leaving a rating element by changing all rating elements * to their default state. */ - _listItemMouseLeave(): void { + protected _listItemMouseLeave(): void { this._ratingElements.forEach((ratingElement) => { const icon = ratingElement.getElementsByClassName("icon")[0]! as HTMLElement; @@ -94,7 +94,7 @@ class Rating { /** * Handles clicks on meta buttons. */ - _metaButtonClick(event: Event): void { + protected _metaButtonClick(event: Event): void { const target = event.currentTarget as HTMLElement; if (target.dataset.action === "removeRating") { this._input.value = ""; @@ -106,7 +106,7 @@ class Rating { /** * Updates the rating UI by changing the rating elements to the stored rating state. */ - _restoreRating(): void { + protected _restoreRating(): void { this._ratingElements.forEach((ratingElement, rating) => { const icon = ratingElement.getElementsByClassName("icon")[0]! as HTMLElement; @@ -117,7 +117,7 @@ class Rating { /** * Toggles the state of the given icon based on the given state parameter. */ - _toggleIcon(icon: HTMLElement, active = false): void { + protected _toggleIcon(icon: HTMLElement, active = false): void { if (active) { icon.classList.remove(...this._defaultCssClasses); icon.classList.add(...this._activeCssClasses); diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract.ts index b6d6b708c2..a47318ef3b 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Abstract.ts @@ -8,7 +8,7 @@ * @since 5.2 */ -import Manager from "./Manager"; +import * as DependencyManager from "./Manager"; import * as Core from "../../../../Core"; abstract class FormBuilderFormFieldDependency { @@ -96,7 +96,7 @@ abstract class FormBuilderFormFieldDependency { } } - Manager.addDependency(this); + DependencyManager.addDependency(this); } } diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Abstract.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Abstract.ts index e706d363e6..e829f75e88 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Abstract.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Abstract.ts @@ -9,10 +9,10 @@ * @since 5.2 */ -import DependencyManager from "../Manager"; +import * as DependencyManager from "../Manager"; import * as Core from "../../../../../Core"; -class Abstract { +abstract class Abstract { protected _container: HTMLElement; constructor(containerId: string) { diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default.ts index a3e7dd82e8..befff2e201 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Default.ts @@ -12,7 +12,7 @@ import Abstract from "./Abstract"; import * as Core from "../../../../../Core"; -import DependencyManager from "../Manager"; +import * as DependencyManager from "../Manager"; class Default extends Abstract { public checkContainer(): void { diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Tab.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Tab.ts index 85e067a264..480b9c211a 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Tab.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/Tab.ts @@ -11,7 +11,7 @@ */ import Abstract from "./Abstract"; -import DependencyManager from "../Manager"; +import * as DependencyManager from "../Manager"; import * as DomUtil from "../../../../../Dom/Util"; import * as UiTabMenu from "../../../../../Ui/TabMenu"; import * as Core from "../../../../../Core"; diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/TabMenu.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/TabMenu.ts index cf132631bd..b28b32e1ee 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/TabMenu.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Container/TabMenu.ts @@ -11,7 +11,7 @@ */ import Abstract from "./Abstract"; -import DependencyManager from "../Manager"; +import * as DependencyManager from "../Manager"; import * as DomUtil from "../../../../../Dom/Util"; import * as UiTabMenu from "../../../../../Ui/TabMenu"; import * as Core from "../../../../../Core"; diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/IsNotClicked.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/IsNotClicked.ts index 08d5e2b475..f7bb415b44 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/IsNotClicked.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/IsNotClicked.ts @@ -10,10 +10,9 @@ */ import Abstract from "./Abstract"; -import Manager from "./Manager"; -import * as Core from "../../../../Core"; +import * as DependencyManager from "./Manager"; -class IsNotClicked extends Abstract { +export class IsNotClicked extends Abstract { constructor(dependentElementId: string, fieldId: string) { super(dependentElementId, fieldId); @@ -23,7 +22,7 @@ class IsNotClicked extends Abstract { this._field.addEventListener("click", () => { this._field.dataset.isClicked = "1"; - Manager.checkDependencies(); + DependencyManager.checkDependencies(); }); } @@ -32,6 +31,4 @@ class IsNotClicked extends Abstract { } } -Core.enableLegacyInheritance(IsNotClicked); - -export = IsNotClicked; +export default IsNotClicked; diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager.ts index 521957365a..8c807cc59d 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager.ts @@ -11,8 +11,6 @@ import DomUtil from "../../../../Dom/Util"; import * as EventHandler from "../../../../Event/Handler"; import FormBuilderFormFieldDependency from "./Abstract"; -import * as DomTraverse from "../../../../Dom/Traverse"; -import * as Core from "../../../../Core"; type PropertiesMap = Map; @@ -27,279 +25,273 @@ let _checkContainersAgain = true; type Callback = (...args: any[]) => void; -const Manager = { - /** - * Hides the given node because of its own dependencies. - */ - _hide(node: HTMLElement): void { - node.style.display = "none"; - _dependencyHiddenNodes.add(node); - - // also hide tab menu entry - if (node.classList.contains("tabMenuContent")) { - node - .parentNode!.querySelector(".tabMenu")! - .querySelectorAll("li") - .forEach((tabLink) => { - if (tabLink.dataset.name === node.dataset.name) { - tabLink.style.display = "none"; - } - }); - } - - node.querySelectorAll("[max], [maxlength], [min], [required]").forEach((validatedField: HTMLInputElement) => { - const properties = new Map(); - - const max = validatedField.getAttribute("max"); - if (max) { - properties.set("max", max); - validatedField.removeAttribute("max"); - } +/** + * Hides the given node because of its own dependencies. + */ +function _hide(node: HTMLElement): void { + node.style.display = "none"; + _dependencyHiddenNodes.add(node); + + // also hide tab menu entry + if (node.classList.contains("tabMenuContent")) { + node + .parentNode!.querySelector(".tabMenu")! + .querySelectorAll("li") + .forEach((tabLink) => { + if (tabLink.dataset.name === node.dataset.name) { + tabLink.style.display = "none"; + } + }); + } - const maxlength = validatedField.getAttribute("maxlength"); - if (maxlength) { - properties.set("maxlength", maxlength); - validatedField.removeAttribute("maxlength"); - } + node.querySelectorAll("[max], [maxlength], [min], [required]").forEach((validatedField: HTMLInputElement) => { + const properties = new Map(); - const min = validatedField.getAttribute("min"); - if (min) { - properties.set("min", min); - validatedField.removeAttribute("min"); - } + const max = validatedField.getAttribute("max"); + if (max) { + properties.set("max", max); + validatedField.removeAttribute("max"); + } - if (validatedField.required) { - properties.set("required", "true"); - validatedField.removeAttribute("required"); - } + const maxlength = validatedField.getAttribute("maxlength"); + if (maxlength) { + properties.set("maxlength", maxlength); + validatedField.removeAttribute("maxlength"); + } - _validatedFieldProperties.set(validatedField, properties); - }); - }, - - /** - * Shows the given node because of its own dependencies. - */ - _show(node: HTMLElement): void { - node.style.display = "block"; - _dependencyHiddenNodes.delete(node); - - // also show tab menu entry - if (node.classList.contains("tabMenuContent")) { - node - .parentNode!.querySelector(".tabMenu")! - .querySelectorAll("li") - .forEach((tabLink) => { - if (tabLink.dataset.name === node.dataset.name) { - tabLink.style.display = "block"; - } - }); + const min = validatedField.getAttribute("min"); + if (min) { + properties.set("min", min); + validatedField.removeAttribute("min"); } - node.querySelectorAll("input, select").forEach((validatedField: HTMLInputElement | HTMLSelectElement) => { - // if a container is shown, ignore all fields that - // have a hidden parent element within the container - let parentNode = validatedField.parentNode! as HTMLElement; - while (parentNode !== node && parentNode.style.getPropertyValue("display") !== "none") { - parentNode = parentNode.parentNode! as HTMLElement; - } + if (validatedField.required) { + properties.set("required", "true"); + validatedField.removeAttribute("required"); + } - if (parentNode === node && _validatedFieldProperties.has(validatedField)) { - const properties = _validatedFieldProperties.get(validatedField)!; + _validatedFieldProperties.set(validatedField, properties); + }); +} - if (properties.has("max")) { - validatedField.setAttribute("max", properties.get("max")!); - } - if (properties.has("maxlength")) { - validatedField.setAttribute("maxlength", properties.get("maxlength")!); - } - if (properties.has("min")) { - validatedField.setAttribute("min", properties.get("min")!); - } - if (properties.has("required")) { - validatedField.setAttribute("required", ""); +/** + * Shows the given node because of its own dependencies. + */ +function _show(node: HTMLElement): void { + node.style.display = "block"; + _dependencyHiddenNodes.delete(node); + + // also show tab menu entry + if (node.classList.contains("tabMenuContent")) { + node + .parentNode!.querySelector(".tabMenu")! + .querySelectorAll("li") + .forEach((tabLink) => { + if (tabLink.dataset.name === node.dataset.name) { + tabLink.style.display = "block"; } - - _validatedFieldProperties.delete(validatedField); - } - }); - }, - - /** - * Adds the given callback to the list of callbacks called when checking containers. - */ - addContainerCheckCallback(callback: Callback): void { - if (typeof callback !== "function") { - throw new TypeError("Expected a valid callback for parameter 'callback'."); + }); + } + + node.querySelectorAll("input, select").forEach((validatedField: HTMLInputElement | HTMLSelectElement) => { + // if a container is shown, ignore all fields that + // have a hidden parent element within the container + let parentNode = validatedField.parentNode! as HTMLElement; + while (parentNode !== node && parentNode.style.getPropertyValue("display") !== "none") { + parentNode = parentNode.parentNode! as HTMLElement; } - EventHandler.add("com.woltlab.wcf.form.builder.dependency", "checkContainers", callback); - }, - - /** - * Registers a new form field dependency. - */ - addDependency(dependency: FormBuilderFormFieldDependency): void { - const dependentNode = dependency.getDependentNode(); - if (!_nodeDependencies.has(dependentNode.id)) { - _nodeDependencies.set(dependentNode.id, [dependency]); - } else { - _nodeDependencies.get(dependentNode.id)!.push(dependency); - } + if (parentNode === node && _validatedFieldProperties.has(validatedField)) { + const properties = _validatedFieldProperties.get(validatedField)!; - dependency.getFields().forEach((field) => { - const id = DomUtil.identify(field); - - if (!_fields.has(id)) { - _fields.set(id, field); - - if ( - field.tagName === "INPUT" && - ((field as HTMLInputElement).type === "checkbox" || - (field as HTMLInputElement).type === "radio" || - (field as HTMLInputElement).type === "hidden") - ) { - field.addEventListener("change", () => this.checkDependencies()); - } else { - field.addEventListener("input", () => this.checkDependencies()); - } + if (properties.has("max")) { + validatedField.setAttribute("max", properties.get("max")!); + } + if (properties.has("maxlength")) { + validatedField.setAttribute("maxlength", properties.get("maxlength")!); + } + if (properties.has("min")) { + validatedField.setAttribute("min", properties.get("min")!); + } + if (properties.has("required")) { + validatedField.setAttribute("required", ""); } - }); - }, - - /** - * Checks the containers for their availability. - * - * If this function is called while containers are currently checked, the containers - * will be checked after the current check has been finished completely. - */ - checkContainers(): void { - // check if containers are currently being checked - if (_checkingContainers === true) { - // and if that is the case, calling this method indicates, that after the current round, - // containters should be checked to properly propagate changes in children to their parents - _checkContainersAgain = true; - return; + _validatedFieldProperties.delete(validatedField); } + }); +} - // starting to check containers also resets the flag to check containers again after the current check - _checkingContainers = true; - _checkContainersAgain = false; +/** + * Adds the given callback to the list of callbacks called when checking containers. + */ +export function addContainerCheckCallback(callback: Callback): void { + if (typeof callback !== "function") { + throw new TypeError("Expected a valid callback for parameter 'callback'."); + } - EventHandler.fire("com.woltlab.wcf.form.builder.dependency", "checkContainers"); + EventHandler.add("com.woltlab.wcf.form.builder.dependency", "checkContainers", callback); +} - // finish checking containers and check if containters should be checked again - _checkingContainers = false; - if (_checkContainersAgain) { - this.checkContainers(); +/** + * Registers a new form field dependency. + */ +export function addDependency(dependency: FormBuilderFormFieldDependency): void { + const dependentNode = dependency.getDependentNode(); + if (!_nodeDependencies.has(dependentNode.id)) { + _nodeDependencies.set(dependentNode.id, [dependency]); + } else { + _nodeDependencies.get(dependentNode.id)!.push(dependency); + } + + dependency.getFields().forEach((field) => { + const id = DomUtil.identify(field); + + if (!_fields.has(id)) { + _fields.set(id, field); + + if ( + field.tagName === "INPUT" && + ((field as HTMLInputElement).type === "checkbox" || + (field as HTMLInputElement).type === "radio" || + (field as HTMLInputElement).type === "hidden") + ) { + field.addEventListener("change", () => checkDependencies()); + } else { + field.addEventListener("input", () => checkDependencies()); + } } - }, + }); +} - /** - * Checks if all dependencies are met. - */ - checkDependencies(): void { - const obsoleteNodeIds: string[] = []; +/** + * Checks the containers for their availability. + * + * If this function is called while containers are currently checked, the containers + * will be checked after the current check has been finished completely. + */ +export function checkContainers(): void { + // check if containers are currently being checked + if (_checkingContainers === true) { + // and if that is the case, calling this method indicates, that after the current round, + // containters should be checked to properly propagate changes in children to their parents + _checkContainersAgain = true; - _nodeDependencies.forEach((nodeDependencies, nodeId) => { - const dependentNode = document.getElementById(nodeId); - if (dependentNode === null) { - obsoleteNodeIds.push(nodeId); + return; + } - return; - } + // starting to check containers also resets the flag to check containers again after the current check + _checkingContainers = true; + _checkContainersAgain = false; - let dependenciesMet = true; - nodeDependencies.forEach((dependency) => { - if (!dependency.checkDependency()) { - this._hide(dependentNode); - dependenciesMet = false; - } - }); + EventHandler.fire("com.woltlab.wcf.form.builder.dependency", "checkContainers"); - if (dependenciesMet) { - this._show(dependentNode); - } - }); + // finish checking containers and check if containters should be checked again + _checkingContainers = false; + if (_checkContainersAgain) { + checkContainers(); + } +} - obsoleteNodeIds.forEach((id) => _nodeDependencies.delete(id)); +/** + * Checks if all dependencies are met. + */ +export function checkDependencies(): void { + const obsoleteNodeIds: string[] = []; - this.checkContainers(); - }, + _nodeDependencies.forEach((nodeDependencies, nodeId) => { + const dependentNode = document.getElementById(nodeId); + if (dependentNode === null) { + obsoleteNodeIds.push(nodeId); - /** - * Returns `true` if the given node has been hidden because of its own dependencies. - */ - isHiddenByDependencies(node: HTMLElement): boolean { - if (_dependencyHiddenNodes.has(node)) { - return true; + return; } - let returnValue = false; - _dependencyHiddenNodes.forEach((hiddenNode) => { - if (node.contains(hiddenNode)) { - returnValue = true; + let dependenciesMet = true; + nodeDependencies.forEach((dependency) => { + if (!dependency.checkDependency()) { + _hide(dependentNode); + dependenciesMet = false; } }); - return returnValue; - }, + if (dependenciesMet) { + _show(dependentNode); + } + }); - /** - * Registers the form with the given id with the dependency manager. - */ - register(formId: string): void { - const form = document.getElementById(formId); + obsoleteNodeIds.forEach((id) => _nodeDependencies.delete(id)); - if (form === null) { - throw new Error("Unknown element with id '" + formId + "'"); - } + checkContainers(); +} - if (_forms.has(form)) { - throw new Error("Form with id '" + formId + "' has already been registered."); +/** + * Returns `true` if the given node has been hidden because of its own dependencies. + */ +export function isHiddenByDependencies(node: HTMLElement): boolean { + if (_dependencyHiddenNodes.has(node)) { + return true; + } + + let returnValue = false; + _dependencyHiddenNodes.forEach((hiddenNode) => { + if (node.contains(hiddenNode)) { + returnValue = true; } + }); - _forms.add(form); - }, + return returnValue; +} - /** - * Unregisters the form with the given id and all of its dependencies. - */ - unregister(formId: string): void { - const form = document.getElementById(formId); +/** + * Registers the form with the given id with the dependency manager. + */ +export function register(formId: string): void { + const form = document.getElementById(formId); - if (form === null) { - throw new Error("Unknown element with id '" + formId + "'"); - } + if (form === null) { + throw new Error("Unknown element with id '" + formId + "'"); + } - if (!_forms.has(form)) { - throw new Error("Form with id '" + formId + "' has not been registered."); - } + if (_forms.has(form)) { + throw new Error("Form with id '" + formId + "' has already been registered."); + } - _forms.delete(form); + _forms.add(form); +} - _dependencyHiddenNodes.forEach((hiddenNode) => { - if (form.contains(hiddenNode)) { - _dependencyHiddenNodes.delete(hiddenNode); - } - }); - _nodeDependencies.forEach((dependencies, nodeId) => { - if (form.contains(document.getElementById(nodeId))) { - _nodeDependencies.delete(nodeId); - } +/** + * Unregisters the form with the given id and all of its dependencies. + */ +export function unregister(formId: string): void { + const form = document.getElementById(formId); - dependencies.forEach((dependency) => { - dependency.getFields().forEach((field) => { - _fields.delete(field.id); + if (form === null) { + throw new Error("Unknown element with id '" + formId + "'"); + } - _validatedFieldProperties.delete(field); - }); - }); - }); - }, -}; + if (!_forms.has(form)) { + throw new Error("Form with id '" + formId + "' has not been registered."); + } + + _forms.delete(form); + + _dependencyHiddenNodes.forEach((hiddenNode) => { + if (form.contains(hiddenNode)) { + _dependencyHiddenNodes.delete(hiddenNode); + } + }); + _nodeDependencies.forEach((dependencies, nodeId) => { + if (form.contains(document.getElementById(nodeId))) { + _nodeDependencies.delete(nodeId); + } -Core.enableLegacyInheritance(Manager); + dependencies.forEach((dependency) => { + dependency.getFields().forEach((field) => { + _fields.delete(field.id); -export = Manager; + _validatedFieldProperties.delete(field); + }); + }); + }); +} diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Manager.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Manager.ts index e498cf9a87..3feafe7b2c 100644 --- a/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Manager.ts +++ b/wcfsetup/install/files/ts/WoltLabSuite/Core/Form/Builder/Manager.ts @@ -12,7 +12,7 @@ import * as Core from "../../Core"; import * as EventHandler from "../../Event/Handler"; import Field from "./Field/Field"; -import DependencyManager from "./Field/Dependency/Manager"; +import * as DependencyManager from "./Field/Dependency/Manager"; import { FormBuilderData } from "./Data"; type FormId = string; -- 2.20.1