From cae7de5e3c66feb3142301767ac0ab0a6a2391b7 Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Sun, 25 Mar 2018 16:35:33 +0200 Subject: [PATCH] Discard `invalid` events for hidden form builder form fields See #2509 --- .../install/files/acp/templates/__form.tpl | 14 +++ .../Form/Builder/Field/Dependency/Manager.js | 87 +++++++++++++++++-- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/wcfsetup/install/files/acp/templates/__form.tpl b/wcfsetup/install/files/acp/templates/__form.tpl index a8ad558bb9..5f50ac22b6 100644 --- a/wcfsetup/install/files/acp/templates/__form.tpl +++ b/wcfsetup/install/files/acp/templates/__form.tpl @@ -1,3 +1,10 @@ + +
getClasses()|empty} class="{implode from=$form->getClasses() item='class'}{$class}{/implode}"{/if}{foreach from=$form->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}> {foreach from=$form item='child'} {if $child->isAvailable()} @@ -10,3 +17,10 @@ {@SECURITY_TOKEN_INPUT_TAG}
+ + 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 6084f4a6e7..95c86f64be 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', 'List'], function(Dictionary, EventHandler, List) { +define(['Dictionary', 'Dom/ChangeListener', 'EventHandler', 'List', 'Dom/Util'], function(Dictionary, DomChangeListener, EventHandler, List, DomUtil) { "use strict"; /** @@ -33,12 +33,19 @@ define(['Dictionary', 'EventHandler', 'List'], function(Dictionary, EventHandler var _dependencyHiddenNodes = new List(); /** - * list if fields for which event listeners have been registered + * list of fields for which event listeners have been registered * @type {Dictionary} * @private */ var _fields = new Dictionary(); + /** + * list of registered forms + * @type {List} + * @private + */ + var _forms = new List(); + /** * list of dependencies grouped by the dependent node they belong to * @type {Dictionary} @@ -46,7 +53,48 @@ define(['Dictionary', 'EventHandler', 'List'], function(Dictionary, EventHandler */ var _nodeDependencies = new Dictionary(); + /** + * list of required fields + * @type {List} + * @private + */ + var _validatedFields = new List(); + return { + /** + * Check if for an invalid form field if it has been hidden due to dependencies + * and discards any validation error message if that is the case. + * + * @param {Event} event `invalid` form field event + * @protected + */ + _checkRequiredField: function(event) { + _dependencyHiddenNodes.forEach(function(hiddenNode) { + if (DomUtil.contains(hiddenNode, event.currentTarget)) { + event.preventDefault(); + event.stopPropagation(); + }; + }); + }, + + /** + * Registers the (new) required fields of all registered forms. + * + * @protected + */ + _registerValidatedFields: function() { + _forms.forEach(function(form) { + // `minlength` does not trigger `invalid` events + elBySelAll('[max], [maxlength], [min], [required]', form, function(validatedField) { + if (!_validatedFields.has(validatedField)) { + _validatedFields.add(validatedField); + + validatedField.addEventListener('invalid', this._checkRequiredField.bind(this)); + } + }.bind(this)) + }.bind(this)); + }, + /** * Hides the given node because of its own dependencies. * @@ -55,18 +103,18 @@ define(['Dictionary', 'EventHandler', 'List'], function(Dictionary, EventHandler */ _hide: function(node) { elHide(node); - _dependencyHiddenNodes.add(node.id); + _dependencyHiddenNodes.add(node); }, /** * Shows the given node because of its own dependencies. - * + * * @param {HTMLElement} node shown node * @protected */ _show: function(node) { elShow(node); - _dependencyHiddenNodes.delete(node.id); + _dependencyHiddenNodes.delete(node); }, /** @@ -183,7 +231,34 @@ define(['Dictionary', 'EventHandler', 'List'], function(Dictionary, EventHandler * @return {boolean} */ isHiddenByDependencies: function(node) { - return _dependencyHiddenNodes.has(node.id); + return _dependencyHiddenNodes.has(node); + }, + + /** + * Registers the form with the given id with the dependency manager. + * + * @param {string} formId id of register form + * @throws {Error} if given form id is invalid or has already been registered + */ + register: function(formId) { + var form = elById(formId); + + if (form === null) { + throw new Error("Unknown element with id '" + formId + "'"); + } + if (form.tagName !== 'FORM') { + throw new Error("Element with id '" + formId + "' is no form."); + } + + if (_forms.has(form)) { + throw new Error("Form with id '" + formId + "' has already been registered."); + } + + _forms.add(form); + + this._registerValidatedFields(); + + DomChangeListener.add('WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager', this._registerValidatedFields.bind(this)); } }; }); -- 2.20.1