+<script data-relocate="true">
+ {* register form with dependency manager before any form field-related JavaScript code is executed below *}
+ require(['WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager'], function(FormBuilderFieldDependencyManager) {
+ FormBuilderFieldDependencyManager.register('{@$form->getId()}');
+ });
+</script>
+
<form method="{@$form->getMethod()}" action="{@$form->getAction()}" id="{@$form->getId()}"{if !$form->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()}
{@SECURITY_TOKEN_INPUT_TAG}
</div>
</form>
+
+<script data-relocate="true">
+ {* after all dependencies have been added, check them *}
+ require(['WoltLabSuite/Core/Form/Builder/Field/Dependency/Manager'], function(FormBuilderFieldDependencyManager) {
+ FormBuilderFieldDependencyManager.checkDependencies();
+ });
+</script>
* @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";
/**
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}
*/
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.
*
*/
_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);
},
/**
* @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));
}
};
});