diff --git a/site/app/Form/TrainingApplicationAdminFormFactory.php b/site/app/Form/TrainingApplicationAdminFormFactory.php index 5a6e6d973..902395bc0 100644 --- a/site/app/Form/TrainingApplicationAdminFormFactory.php +++ b/site/app/Form/TrainingApplicationAdminFormFactory.php @@ -77,12 +77,11 @@ public function create(callable $onSuccess, callable $onStatusHistoryDeleteSucce $this->addDeletableFieldCheckbox($companyInputs->getCompanyTaxId(), $form->addCheckbox('companyTaxIdSet'), $application->getCompanyTaxId()); $this->addDeletableFieldCheckbox($noteInput, $form->addCheckbox('noteSet'), $application->getNote()); - $containerName = 'statusHistoryDelete'; - $historyContainer = $form->addContainer($containerName); + $historyContainer = $form->addContainer('statusHistoryDelete'); foreach ($this->trainingApplicationStatusHistory->getStatusHistory($application->getId()) as $history) { $historyContainer ->addSubmit((string)$history->getId()) - ->setValidationScope([$form[$containerName]]) + ->setValidationScope([$historyContainer]) ->onClick[] = function (SubmitButton $button) use ($application, $onStatusHistoryDeleteSuccess): void { $this->trainingApplicationStatusHistory->deleteHistoryRecord($application->getId(), (int)$button->getName()); $onStatusHistoryDeleteSuccess(); diff --git a/site/composer.lock b/site/composer.lock index df4f944c6..992a6a312 100644 --- a/site/composer.lock +++ b/site/composer.lock @@ -697,16 +697,16 @@ }, { "name": "nette/forms", - "version": "v3.2.2", + "version": "v3.2.3", "source": { "type": "git", "url": "https://github.com/nette/forms.git", - "reference": "a20fdb1f81f5b406cdc99a450e0a327d5790f9b5" + "reference": "441926313d3f7ef78e9bc6996661310ae6f1c2f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/forms/zipball/a20fdb1f81f5b406cdc99a450e0a327d5790f9b5", - "reference": "a20fdb1f81f5b406cdc99a450e0a327d5790f9b5", + "url": "https://api.github.com/repos/nette/forms/zipball/441926313d3f7ef78e9bc6996661310ae6f1c2f7", + "reference": "441926313d3f7ef78e9bc6996661310ae6f1c2f7", "shasum": "" }, "require": { @@ -768,9 +768,9 @@ ], "support": { "issues": "https://github.com/nette/forms/issues", - "source": "https://github.com/nette/forms/tree/v3.2.2" + "source": "https://github.com/nette/forms/tree/v3.2.3" }, - "time": "2024-04-01T01:05:00+00:00" + "time": "2024-05-05T15:02:00+00:00" }, { "name": "nette/http", diff --git a/site/vendor/composer/installed.json b/site/vendor/composer/installed.json index 093207655..1f4987dbf 100644 --- a/site/vendor/composer/installed.json +++ b/site/vendor/composer/installed.json @@ -883,17 +883,17 @@ }, { "name": "nette/forms", - "version": "v3.2.2", - "version_normalized": "3.2.2.0", + "version": "v3.2.3", + "version_normalized": "3.2.3.0", "source": { "type": "git", "url": "https://github.com/nette/forms.git", - "reference": "a20fdb1f81f5b406cdc99a450e0a327d5790f9b5" + "reference": "441926313d3f7ef78e9bc6996661310ae6f1c2f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/forms/zipball/a20fdb1f81f5b406cdc99a450e0a327d5790f9b5", - "reference": "a20fdb1f81f5b406cdc99a450e0a327d5790f9b5", + "url": "https://api.github.com/repos/nette/forms/zipball/441926313d3f7ef78e9bc6996661310ae6f1c2f7", + "reference": "441926313d3f7ef78e9bc6996661310ae6f1c2f7", "shasum": "" }, "require": { @@ -916,7 +916,7 @@ "suggest": { "ext-intl": "to use date/time controls" }, - "time": "2024-04-01T01:05:00+00:00", + "time": "2024-05-05T15:02:00+00:00", "type": "library", "extra": { "branch-alias": { @@ -957,7 +957,7 @@ ], "support": { "issues": "https://github.com/nette/forms/issues", - "source": "https://github.com/nette/forms/tree/v3.2.2" + "source": "https://github.com/nette/forms/tree/v3.2.3" }, "install-path": "../nette/forms" }, diff --git a/site/vendor/composer/installed.php b/site/vendor/composer/installed.php index 6d36ada7a..218fa8e53 100644 --- a/site/vendor/composer/installed.php +++ b/site/vendor/composer/installed.php @@ -161,9 +161,9 @@ ), ), 'nette/forms' => array( - 'pretty_version' => 'v3.2.2', - 'version' => '3.2.2.0', - 'reference' => 'a20fdb1f81f5b406cdc99a450e0a327d5790f9b5', + 'pretty_version' => 'v3.2.3', + 'version' => '3.2.3.0', + 'reference' => '441926313d3f7ef78e9bc6996661310ae6f1c2f7', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/forms', 'aliases' => array(), diff --git a/site/vendor/nette/forms/.eslintrc.js b/site/vendor/nette/forms/.eslintrc.js deleted file mode 100644 index c078dec61..000000000 --- a/site/vendor/nette/forms/.eslintrc.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - 'env': { - 'browser': true, - 'amd': true, - 'commonjs': true - }, - 'globals': { - 'Tracy': true - }, - 'extends': 'eslint:recommended', - 'rules': { - 'indent': ['error', 'tab'], - 'quotes': ['error', 'single'], - 'semi': ['error', 'always'], - 'func-style': ['error', 'expression'] - } -}; diff --git a/site/vendor/nette/forms/eslint.config.mjs b/site/vendor/nette/forms/eslint.config.mjs new file mode 100644 index 000000000..3e78d371e --- /dev/null +++ b/site/vendor/nette/forms/eslint.config.mjs @@ -0,0 +1,30 @@ +import globals from 'globals'; +import pluginJs from '@eslint/js'; + +export default [ + pluginJs.configs.recommended, + { + ignores: ['**/*.min.js'], + }, + { + languageOptions: { + ecmaVersion: 2021, + globals: { + ...globals.browser, + 'Tracy': 'writeable', + 'define': 'readable', + 'module': 'readable', + }, + }, + rules: { + indent: ['error', 'tab'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + 'func-style': ['error', 'declaration', {'allowArrowFunctions': true}], + 'prefer-arrow-callback': ['error'], + 'arrow-parens': ['error'], + 'arrow-spacing': ['error'], + 'no-var': ['error'], + }, + }, +]; diff --git a/site/vendor/nette/forms/examples/html5.php b/site/vendor/nette/forms/examples/html5.php index 77f0600a9..fab0beccb 100644 --- a/site/vendor/nette/forms/examples/html5.php +++ b/site/vendor/nette/forms/examples/html5.php @@ -26,16 +26,13 @@ ->setHtmlType('search') ->setHtmlAttribute('autofocus'); -$form->addText('count', 'Number of results:') - ->setHtmlType('number') +$form->addInteger('count', 'Number of results:') ->setDefaultValue(10) - ->addRule($form::Integer, 'Must be numeric value') ->addRule($form::Range, 'Must be in range from %d to %d', [1, 100]); -$form->addText('precision', 'Precision:') +$form->addFloat('precision', 'Precision:') ->setHtmlType('range') ->setDefaultValue(50) - ->addRule($form::Integer, 'Precision must be numeric value') ->addRule($form::Range, 'Precision must be in range from %d to %d', [0, 100]); $form->addEmail('email', 'Send to email:') diff --git a/site/vendor/nette/forms/package.json b/site/vendor/nette/forms/package.json index cbd649a3d..8f240ea27 100644 --- a/site/vendor/nette/forms/package.json +++ b/site/vendor/nette/forms/package.json @@ -1,21 +1,26 @@ { - "name": "nette-forms", - "version": "3.3.6", - "description": "Client side script for Nette Forms Component", - "keywords": [ - "nette", - "validation", - "forms" - ], - "homepage": "https://nette.org", - "author": "David Grudl (https://davidgrudl.com)", - "license": "BSD-3-Clause", - "main": "src/assets/netteForms.js", - "files": [ - "src/assets" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/nette/forms.git" - } + "name": "nette-forms", + "version": "3.4.0", + "description": "Client side script for Nette Forms Component", + "keywords": [ + "nette", + "validation", + "forms" + ], + "homepage": "https://nette.org", + "author": "David Grudl (https://davidgrudl.com)", + "license": "BSD-3-Clause", + "main": "src/assets/netteForms.js", + "files": [ + "src/assets" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/nette/forms.git" + }, + "devDependencies": { + "@eslint/js": "^9.1.1", + "eslint": "^9.1.1", + "globals": "^15.1.0" + } } diff --git a/site/vendor/nette/forms/src/Bridges/FormsDI/FormsExtension.php b/site/vendor/nette/forms/src/Bridges/FormsDI/FormsExtension.php index 5b4989f89..b06ca6775 100644 --- a/site/vendor/nette/forms/src/Bridges/FormsDI/FormsExtension.php +++ b/site/vendor/nette/forms/src/Bridges/FormsDI/FormsExtension.php @@ -26,7 +26,7 @@ public function __construct() } - public function afterCompile(Nette\PhpGenerator\ClassType $class) + public function afterCompile(Nette\PhpGenerator\ClassType $class): void { $initialize = $this->initialization ?? $class->getMethod('initialize'); diff --git a/site/vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FieldNNameNode.php b/site/vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FieldNNameNode.php index a3dbb858e..46bb7a1c6 100644 --- a/site/vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FieldNNameNode.php +++ b/site/vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FieldNNameNode.php @@ -57,7 +57,7 @@ public function print(PrintContext $context): string } - private function init(Tag $tag) + private function init(Tag $tag): void { $el = $tag->htmlElement; $usedAttributes = self::findUsedAttributes($el); diff --git a/site/vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FormNNameNode.php b/site/vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FormNNameNode.php index fe569b71d..3c1213f03 100644 --- a/site/vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FormNNameNode.php +++ b/site/vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FormNNameNode.php @@ -57,7 +57,7 @@ public function print(PrintContext $context): string } - private function init(Tag $tag) + private function init(Tag $tag): void { $el = $tag->htmlElement; diff --git a/site/vendor/nette/forms/src/Forms/Blueprint.php b/site/vendor/nette/forms/src/Forms/Blueprint.php index 42aec6e49..e926a9cc0 100644 --- a/site/vendor/nette/forms/src/Forms/Blueprint.php +++ b/site/vendor/nette/forms/src/Forms/Blueprint.php @@ -199,7 +199,7 @@ public function generateDataClass( } } - if (!$input->isRequired()) { + if (!$input->isRequired() && $input->isNullable()) { $type = '?' . $type; } } elseif ($input instanceof Controls\UploadControl) { diff --git a/site/vendor/nette/forms/src/Forms/Container.php b/site/vendor/nette/forms/src/Forms/Container.php index e412c1b41..05782623b 100644 --- a/site/vendor/nette/forms/src/Forms/Container.php +++ b/site/vendor/nette/forms/src/Forms/Container.php @@ -49,10 +49,7 @@ class Container extends Nette\ComponentModel\Container implements \ArrayAccess public function setDefaults(array|object $data, bool $erase = false): static { $form = $this->getForm(false); - if (!$form || !$form->isAnchored() || !$form->isSubmitted()) { - $this->setValues($data, $erase); - } - + $this->setValues($data, $erase, $form?->isAnchored() && $form->isSubmitted()); return $this; } @@ -61,29 +58,20 @@ public function setDefaults(array|object $data, bool $erase = false): static * Fill-in with values. * @internal */ - public function setValues(array|object $data, bool $erase = false): static + public function setValues(array|object $values, bool $erase = false, bool $onlyDisabled = false): static { - if ($data instanceof \Traversable) { - $values = iterator_to_array($data); - - } elseif (is_object($data) || is_array($data) || $data === null) { - $values = (array) $data; - } + $values = $values instanceof \Traversable + ? iterator_to_array($values) + : (array) $values; foreach ($this->getComponents() as $name => $control) { if ($control instanceof Control) { - if (array_key_exists($name, $values)) { - $control->setValue($values[$name]); - - } elseif ($erase) { - $control->setValue(null); + if ((array_key_exists($name, $values) && (!$onlyDisabled || $control->isDisabled())) || $erase) { + $control->setValue($values[$name] ?? null); } } elseif ($control instanceof self) { - if (isset($values[$name])) { - $control->setValues($values[$name], $erase); - - } elseif ($erase) { - $control->setValues([], $erase); + if (isset($values[$name]) || $erase) { + $control->setValues($values[$name] ?? [], $erase, $onlyDisabled); } } } @@ -186,7 +174,6 @@ public function getUnsafeValues($returnType, ?array $controls = null) } - /** @return static */ public function setMappedType(string $type): static { $this->mappedType = $type; @@ -287,10 +274,7 @@ public function addComponent( ): static { parent::addComponent($component, $name, $insertBefore); - if ($this->currentGroup !== null) { - $this->currentGroup->add($component); - } - + $this->currentGroup?->add($component); return $this; } @@ -577,10 +561,7 @@ public function addContainer(string|int $name): self { $control = new self; $control->currentGroup = $this->currentGroup; - if ($this->currentGroup !== null) { - $this->currentGroup->add($control); - } - + $this->currentGroup?->add($control); return $this[$name] = $control; } diff --git a/site/vendor/nette/forms/src/Forms/Controls/BaseControl.php b/site/vendor/nette/forms/src/Forms/Controls/BaseControl.php index bac909dff..641102755 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/BaseControl.php +++ b/site/vendor/nette/forms/src/Forms/Controls/BaseControl.php @@ -169,7 +169,7 @@ public function isFilled(): bool */ public function setDefaultValue($value) { - $form = $this->getForm(false); + $form = $this->getForm(throw: false); if ($this->isDisabled() || !$form || !$form->isAnchored() || !$form->isSubmitted()) { $this->setValue($value); } @@ -182,11 +182,12 @@ public function setDefaultValue($value) * Disables or enables control. * @return static */ - public function setDisabled(bool $value = true) + public function setDisabled(bool $state = true) { - if ($this->disabled = (bool) $value) { + $this->disabled = $state; + if ($state) { $this->setValue(null); - } elseif (($form = $this->getForm(false)) && $form->isAnchored() && $form->isSubmitted()) { + } elseif (($form = $this->getForm(throw: false)) && $form->isAnchored() && $form->isSubmitted()) { $this->loadHttpData(); } @@ -206,9 +207,9 @@ public function isDisabled(): bool /** * Sets whether control value is excluded from $form->getValues() result. */ - public function setOmitted(bool $value = true): static + public function setOmitted(bool $state = true): static { - $this->omitted = $value; + $this->omitted = $state; return $this; } diff --git a/site/vendor/nette/forms/src/Forms/Controls/Checkbox.php b/site/vendor/nette/forms/src/Forms/Controls/Checkbox.php index 1b4cac23f..1c8ec02dc 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/Checkbox.php +++ b/site/vendor/nette/forms/src/Forms/Controls/Checkbox.php @@ -39,7 +39,7 @@ public function __construct(string|Stringable|null $label = null) public function setValue($value) { if (!is_scalar($value) && $value !== null) { - throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or null, %s given in field '%s'.", get_debug_type($value), $this->name)); + throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or null, %s given in field '%s'.", get_debug_type($value), $this->getName())); } $this->value = (bool) $value; diff --git a/site/vendor/nette/forms/src/Forms/Controls/CheckboxList.php b/site/vendor/nette/forms/src/Forms/Controls/CheckboxList.php index a04207a2e..8b2bcc41d 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/CheckboxList.php +++ b/site/vendor/nette/forms/src/Forms/Controls/CheckboxList.php @@ -56,8 +56,6 @@ public function getControl(): Html { $input = parent::getControl(); $items = $this->getItems(); - reset($items); - return $this->container->setHtml( Nette\Forms\Helpers::createInputList( $this->translate($items), @@ -66,7 +64,7 @@ public function getControl(): Html 'checked?' => $this->value, 'disabled:' => $this->disabled, 'required' => null, - 'data-nette-rules:' => [key($items) => $input->attrs['data-nette-rules']], + 'data-nette-rules:' => [array_key_first($items) => $input->attrs['data-nette-rules']], ]), $this->itemLabel->attrs, $this->separator, @@ -98,7 +96,7 @@ public function getLabelPart($key = null): Html { $itemLabel = clone $this->itemLabel; return func_num_args() - ? $itemLabel->setText($this->translate($this->items[$key]))->for($this->getHtmlId() . '-' . $key) + ? $itemLabel->setText($this->translate($this->getItems()[$key]))->for($this->getHtmlId() . '-' . $key) : $this->getLabel(); } diff --git a/site/vendor/nette/forms/src/Forms/Controls/ChoiceControl.php b/site/vendor/nette/forms/src/Forms/Controls/ChoiceControl.php index 3d36d4de1..382290318 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/ChoiceControl.php +++ b/site/vendor/nette/forms/src/Forms/Controls/ChoiceControl.php @@ -62,7 +62,7 @@ public function setValue($value) 70, '...', ); - throw new Nette\InvalidArgumentException("Value '$value' is out of allowed set [$set] in field '{$this->name}'."); + throw new Nette\InvalidArgumentException("Value '$value' is out of allowed set [$set] in field '{$this->getName()}'."); } $this->value = $value === null ? null : key([(string) $value => null]); diff --git a/site/vendor/nette/forms/src/Forms/Controls/ColorPicker.php b/site/vendor/nette/forms/src/Forms/Controls/ColorPicker.php index 0b82a9bd1..22e8f0c28 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/ColorPicker.php +++ b/site/vendor/nette/forms/src/Forms/Controls/ColorPicker.php @@ -31,7 +31,7 @@ public function setValue($value): static { if ($value === null) { $this->value = '#000000'; - } elseif (is_string($value) && preg_match('~#?[0-9a-f]{6}~DAi', $value)) { + } elseif (is_string($value) && preg_match('~#?[0-9a-f]{6}~Ai', $value)) { $this->value = '#' . strtolower(ltrim($value, '#')); } else { throw new Nette\InvalidArgumentException('Color must have #rrggbb format.'); @@ -44,7 +44,7 @@ public function loadHttpData(): void { try { parent::loadHttpData(); - } catch (Nette\InvalidArgumentException $e) { + } catch (Nette\InvalidArgumentException) { $this->setValue(null); } } diff --git a/site/vendor/nette/forms/src/Forms/Controls/HiddenField.php b/site/vendor/nette/forms/src/Forms/Controls/HiddenField.php index 2f5dd8120..547c426e5 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/HiddenField.php +++ b/site/vendor/nette/forms/src/Forms/Controls/HiddenField.php @@ -49,7 +49,7 @@ public function setValue($value) } elseif ($value instanceof \BackedEnum) { $value = $value->value; } elseif (!is_scalar($value) && !$value instanceof Stringable) { - throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or null, %s given in field '%s'.", get_debug_type($value), $this->name)); + throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or null, %s given in field '%s'.", get_debug_type($value), $this->getName())); } if (!$this->persistValue) { @@ -76,6 +76,12 @@ public function setNullable(bool $value = true): static } + public function isNullable(): bool + { + return $this->nullable; + } + + public function getControl(): Html { $this->setOption('rendered', true); diff --git a/site/vendor/nette/forms/src/Forms/Controls/ImageButton.php b/site/vendor/nette/forms/src/Forms/Controls/ImageButton.php index 035fcbe0b..c9eedcd7b 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/ImageButton.php +++ b/site/vendor/nette/forms/src/Forms/Controls/ImageButton.php @@ -16,8 +16,8 @@ class ImageButton extends SubmitButton { /** - * @param string $src URI of the image - * @param string $alt alternate text for the image + * @param ?string $src URI of the image + * @param ?string $alt alternate text for the image */ public function __construct(?string $src = null, ?string $alt = null) { diff --git a/site/vendor/nette/forms/src/Forms/Controls/MultiChoiceControl.php b/site/vendor/nette/forms/src/Forms/Controls/MultiChoiceControl.php index 5ab4cb555..a1aade76e 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/MultiChoiceControl.php +++ b/site/vendor/nette/forms/src/Forms/Controls/MultiChoiceControl.php @@ -52,7 +52,7 @@ public function setValue($values) if (is_scalar($values) || $values === null) { $values = (array) $values; } elseif (!is_array($values)) { - throw new Nette\InvalidArgumentException(sprintf("Value must be array or null, %s given in field '%s'.", get_debug_type($values), $this->name)); + throw new Nette\InvalidArgumentException(sprintf("Value must be array or null, %s given in field '%s'.", get_debug_type($values), $this->getName())); } $flip = []; @@ -60,7 +60,7 @@ public function setValue($values) if ($value instanceof \BackedEnum) { $value = $value->value; } elseif (!is_scalar($value) && !$value instanceof \Stringable) { - throw new Nette\InvalidArgumentException(sprintf("Values must be scalar, %s given in field '%s'.", get_debug_type($value), $this->name)); + throw new Nette\InvalidArgumentException(sprintf("Values must be scalar, %s given in field '%s'.", get_debug_type($value), $this->getName())); } $flip[(string) $value] = true; @@ -74,7 +74,7 @@ public function setValue($values) '...', ); $vals = (count($diff) > 1 ? 's' : '') . " '" . implode("', '", $diff) . "'"; - throw new Nette\InvalidArgumentException("Value$vals are out of allowed set [$set] in field '{$this->name}'."); + throw new Nette\InvalidArgumentException("Value$vals are out of allowed set [$set] in field '{$this->getName()}'."); } $this->value = $values; diff --git a/site/vendor/nette/forms/src/Forms/Controls/RadioList.php b/site/vendor/nette/forms/src/Forms/Controls/RadioList.php index 4a243e5f3..e50f955a5 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/RadioList.php +++ b/site/vendor/nette/forms/src/Forms/Controls/RadioList.php @@ -89,7 +89,7 @@ public function getLabelPart($key = null): Html { $itemLabel = clone $this->itemLabel; return func_num_args() - ? $itemLabel->setText($this->translate($this->items[$key]))->for($this->getHtmlId() . '-' . $key) + ? $itemLabel->setText($this->translate($this->getItems()[$key]))->for($this->getHtmlId() . '-' . $key) : $this->getLabel(); } diff --git a/site/vendor/nette/forms/src/Forms/Controls/SubmitButton.php b/site/vendor/nette/forms/src/Forms/Controls/SubmitButton.php index fd7cdc2f7..470486ad8 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/SubmitButton.php +++ b/site/vendor/nette/forms/src/Forms/Controls/SubmitButton.php @@ -35,7 +35,7 @@ public function __construct(string|Stringable|null $caption = null) { parent::__construct($caption); $this->control->type = 'submit'; - $this->setOmitted(true); + $this->setOmitted(); } @@ -59,7 +59,7 @@ public function isSubmittedBy(): bool /** * Sets the validation scope. Clicking the button validates only the controls within the specified scope. - * @param ?iterable + * @param ?iterable $scope */ public function setValidationScope(?iterable $scope): static { diff --git a/site/vendor/nette/forms/src/Forms/Controls/TextBase.php b/site/vendor/nette/forms/src/Forms/Controls/TextBase.php index e3473b146..57099a280 100644 --- a/site/vendor/nette/forms/src/Forms/Controls/TextBase.php +++ b/site/vendor/nette/forms/src/Forms/Controls/TextBase.php @@ -35,7 +35,7 @@ public function setValue($value) if ($value === null) { $value = ''; } elseif (!is_scalar($value) && !$value instanceof Stringable) { - throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or null, %s given in field '%s'.", get_debug_type($value), $this->name)); + throw new Nette\InvalidArgumentException(sprintf("Value must be scalar or null, %s given in field '%s'.", get_debug_type($value), $this->getName())); } $this->value = $value; @@ -67,6 +67,12 @@ public function setNullable(bool $value = true): static } + public function isNullable(): bool + { + return $this->nullable; + } + + /** * Sets the special value which is treated as empty string. */ diff --git a/site/vendor/nette/forms/src/Forms/Form.php b/site/vendor/nette/forms/src/Forms/Form.php index 81abcd0c3..db0ea94ff 100644 --- a/site/vendor/nette/forms/src/Forms/Form.php +++ b/site/vendor/nette/forms/src/Forms/Form.php @@ -256,7 +256,7 @@ public function setAction(string|Stringable $url): static /** * Returns form's action. */ - public function getAction(): mixed + public function getAction(): string|Stringable { return $this->getElementPrototype()->action; } @@ -358,7 +358,7 @@ public function removeGroup(string|ControlGroup $name): void $name = array_search($group, $this->groups, strict: true); } else { - throw new Nette\InvalidArgumentException("Group not found in form '$this->name'"); + throw new Nette\InvalidArgumentException("Group not found in form '{$this->getName()}'"); } foreach ($group->getControls() as $control) { @@ -458,7 +458,7 @@ public function setSubmittedBy(?SubmitterControl $by): static /** * Returns submitted HTTP data. */ - public function getHttpData(?int $type = null, ?string $htmlName = null): mixed + public function getHttpData(?int $type = null, ?string $htmlName = null): string|array|Nette\Http\FileUpload|null { if (!isset($this->httpData)) { if (!$this->isAnchored()) { @@ -470,11 +470,10 @@ public function getHttpData(?int $type = null, ?string $htmlName = null): mixed $this->submittedBy = is_array($data); } - if ($htmlName === null) { - return $this->httpData; - } + return $htmlName === null + ? $this->httpData + : Helpers::extractHttpData($this->httpData, $htmlName, $type); - return Helpers::extractHttpData($this->httpData, $htmlName, $type); } @@ -490,7 +489,7 @@ public function fireEvents(): void $this->validate(); } - $handled = count($this->onSuccess ?? []) || count($this->onSubmit ?? []); + $handled = count($this->onSuccess ?? []) || count($this->onSubmit ?? []) || $this->submittedBy === true; if ($this->submittedBy instanceof Controls\SubmitButton) { $handled = $handled || count($this->submittedBy->onClick ?? []); diff --git a/site/vendor/nette/forms/src/Forms/Helpers.php b/site/vendor/nette/forms/src/Forms/Helpers.php index 3a2fdb480..5d4eb1e50 100644 --- a/site/vendor/nette/forms/src/Forms/Helpers.php +++ b/site/vendor/nette/forms/src/Forms/Helpers.php @@ -66,7 +66,7 @@ public static function extractHttpData( } - private static function sanitize(int $type, $value) + private static function sanitize(int $type, $value): string|array|Nette\Http\FileUpload|null { if ($type === Form::DataText) { return is_scalar($value) diff --git a/site/vendor/nette/forms/src/Forms/Rendering/DefaultFormRenderer.php b/site/vendor/nette/forms/src/Forms/Rendering/DefaultFormRenderer.php index 34ebcb936..d0fc673a8 100644 --- a/site/vendor/nette/forms/src/Forms/Rendering/DefaultFormRenderer.php +++ b/site/vendor/nette/forms/src/Forms/Rendering/DefaultFormRenderer.php @@ -122,7 +122,7 @@ class DefaultFormRenderer implements Nette\Forms\FormRenderer /** * Provides complete form rendering. - * @param string $mode 'begin', 'errors', 'ownerrors', 'body', 'end' or empty to render all + * @param ?string $mode 'begin', 'errors', 'ownerrors', 'body', 'end' or empty to render all */ public function render(Nette\Forms\Form $form, ?string $mode = null): string { @@ -522,7 +522,6 @@ public function getWrapper(string $name): Html protected function getValue(string $name): mixed { $name = explode(' ', $name); - $data = &$this->wrappers[$name[0]][$name[1]]; - return $data; + return $this->wrappers[$name[0]][$name[1]] ?? null; } } diff --git a/site/vendor/nette/forms/src/Forms/Validator.php b/site/vendor/nette/forms/src/Forms/Validator.php index 3a9645f21..fa953e791 100644 --- a/site/vendor/nette/forms/src/Forms/Validator.php +++ b/site/vendor/nette/forms/src/Forms/Validator.php @@ -372,7 +372,7 @@ public static function validateFileSize(Controls\UploadControl $control, $limit) * Has file specified mime type? * @param string|string[] $mimeType */ - public static function validateMimeType(Controls\UploadControl $control, $mimeType): bool + public static function validateMimeType(Controls\UploadControl $control, string|array $mimeType): bool { $mimeTypes = is_array($mimeType) ? $mimeType : explode(',', $mimeType); foreach (static::toArray($control->getValue()) as $file) { diff --git a/site/vendor/nette/forms/src/assets/netteForms.js b/site/vendor/nette/forms/src/assets/netteForms.js index 56ed96035..dc7397e47 100644 --- a/site/vendor/nette/forms/src/assets/netteForms.js +++ b/site/vendor/nette/forms/src/assets/netteForms.js @@ -5,44 +5,66 @@ * Copyright (c) 2004 David Grudl (https://davidgrudl.com) */ -(function(global, factory) { +/** + * @typedef {HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement|HTMLButtonElement} FormElement + * @typedef {{op: string, neg: boolean, msg: string, arg: *, rules: ?Array, control: string, toggle: ?Array}} Rule + */ + +(function (global, factory) { if (!global.JSON) { return; } if (typeof define === 'function' && define.amd) { - define(function() { - return factory(global); - }); + define(() => factory(global)); } else if (typeof module === 'object' && typeof module.exports === 'object') { module.exports = factory(global); } else { - var init = !global.Nette || !global.Nette.noInit; + let init = !global.Nette?.noInit; global.Nette = factory(global); if (init) { global.Nette.initOnLoad(); } } -}(typeof window !== 'undefined' ? window : this, function(window) { - +}(typeof window !== 'undefined' ? window : this, (window) => { 'use strict'; - var Nette = {}; - var preventFiltering = {}; - var formToggles = {}; - var toggleListeners = new window.WeakMap(); + const Nette = {}; + let preventFiltering = {}; + let formToggles = {}; + let toggleListeners = new window.WeakMap(); Nette.formErrors = []; Nette.version = '3.3.0'; - Nette.invalidNumberMessage = 'Please enter a valid value.'; + + + /** + * @param {HTMLFormElement} form + * @param {string} name + * @return {?FormElement} + */ + function getFormElement(form, name) { + let res = form.elements.namedItem(name); + return res instanceof RadioNodeList ? res[0] : res; + } + + + /** + * @param {FormElement} elem + * @return {Array} + */ + function expandRadioElement(elem) { + let res = elem.form.elements.namedItem(elem.name); + return res instanceof RadioNodeList ? Array.from(res) : [res]; + } /** * Function to execute when the DOM is fully loaded. * @private */ - Nette.onDocumentReady = function(callback) { + Nette.onDocumentReady = function (callback) { if (document.readyState !== 'loading') { callback.call(this); } else { @@ -53,79 +75,61 @@ /** * Returns the value of form element. + * @param {FormElement|RadioNodeList} elem + * @return {*} */ - Nette.getValue = function(elem) { - var i; - if (!elem) { - return null; - - } else if (!elem.tagName) { // RadioNodeList, HTMLCollection, array - return elem[0] ? Nette.getValue(elem[0]) : null; - - } else if (elem.type === 'radio') { - var elements = elem.form.elements; // prevents problem with name 'item' or 'namedItem' - for (i = 0; i < elements.length; i++) { - if (elements[i].name === elem.name && elements[i].checked) { - return elements[i].value; - } - } - return null; - - } else if (elem.type === 'file') { - return elem.files || elem.value; - - } else if (elem.tagName.toLowerCase() === 'select') { - var index = elem.selectedIndex, - options = elem.options, - values = []; + Nette.getValue = function (elem) { + if (elem instanceof HTMLInputElement) { + if (elem.type === 'radio') { + return expandRadioElement(elem) + .find((input) => input.checked) + ?.value ?? null; + + } else if (elem.type === 'file') { + return elem.files; + + } else if (elem.type === 'checkbox') { + return elem.name.endsWith('[]') // checkbox list + ? expandRadioElement(elem) + .filter((input) => input.checked) + .map((input) => input.value) + : elem.checked; - if (elem.type === 'select-one') { - return index < 0 ? null : options[index].value; - } - - for (i = 0; i < options.length; i++) { - if (options[i].selected) { - values.push(options[i].value); - } + } else { + return elem.value.trim(); } - return values; - } else if (elem.name && elem.name.substr(-2) === '[]') { // multiple elements [] - elements = elem.form.elements[elem.name].tagName ? [elem] : elem.form.elements[elem.name]; - values = []; + } else if (elem instanceof HTMLSelectElement) { + return elem.multiple + ? Array.from(elem.selectedOptions, (option) => option.value) + : elem.selectedOptions[0]?.value ?? null; - for (i = 0; i < elements.length; i++) { - if (elements[i].type !== 'checkbox' || elements[i].checked) { - values.push(elements[i].value); - } - } - return values; + } else if (elem instanceof HTMLTextAreaElement) { + return elem.value; - } else if (elem.type === 'checkbox') { - return elem.checked; - - } else if (elem.tagName.toLowerCase() === 'textarea') { - return elem.value.replace('\r', ''); + } else if (elem instanceof RadioNodeList) { + return Nette.getValue(elem[0]); } else { - return elem.value.replace('\r', '').replace(/^\s+|\s+$/g, ''); + return null; } }; /** * Returns the effective value of form element. + * @param {FormElement} elem + * @param {boolean} filter + * @return {*} */ - Nette.getEffectiveValue = function(elem, filter) { - var val = Nette.getValue(elem); - if (elem.getAttribute) { - if (val === elem.getAttribute('data-nette-empty-value')) { - val = ''; - } + Nette.getEffectiveValue = function (elem, filter = false) { + let val = Nette.getValue(elem); + if (val === elem.getAttribute('data-nette-empty-value')) { + val = ''; } if (filter && preventFiltering[elem.name] === undefined) { preventFiltering[elem.name] = true; - var ref = {value: val}; + let ref = {value: val}; Nette.validateControl(elem, null, true, ref); val = ref.value; delete preventFiltering[elem.name]; @@ -136,17 +140,21 @@ /** * Validates form element against given rules. + * @param {FormElement} elem + * @param {?Array} rules + * @param {boolean} onlyCheck + * @param {?{value: *}} value + * @param {?boolean} emptyOptional + * @return {boolean} */ - Nette.validateControl = function(elem, rules, onlyCheck, value, emptyOptional) { - elem = elem.tagName ? elem : elem[0]; // RadioNodeList - rules = rules || JSON.parse(elem.getAttribute('data-nette-rules') || '[]'); - value = value === undefined ? {value: Nette.getEffectiveValue(elem)} : value; - emptyOptional = emptyOptional === undefined ? !Nette.validateRule(elem, ':filled', null, value) : emptyOptional; + Nette.validateControl = function (elem, rules, onlyCheck = false, value = null, emptyOptional = null) { + rules ??= JSON.parse(elem.getAttribute('data-nette-rules') ?? '[]'); + value ??= {value: Nette.getEffectiveValue(elem)}; + emptyOptional ??= !Nette.validateRule(elem, ':filled', null, value); - for (var id = 0, len = rules.length; id < len; id++) { - var rule = rules[id], - op = rule.op.match(/(~)?([^?]+)/), - curElem = rule.control ? elem.form.elements.namedItem(rule.control) : elem; + for (let rule of rules) { + let op = rule.op.match(/(~)?([^?]+)/), + curElem = rule.control ? getFormElement(elem.form, rule.control) : elem; rule.neg = op[1]; rule.op = op[2]; @@ -158,9 +166,7 @@ continue; } - curElem = curElem.tagName ? curElem : curElem[0]; // RadioNodeList - var success = Nette.validateRule(curElem, rule.op, rule.arg, elem === curElem ? value : undefined); - + let success = Nette.validateRule(curElem, rule.op, rule.arg, elem === curElem ? value : undefined); if (success === null) { continue; } else if (rule.neg) { @@ -176,10 +182,11 @@ continue; } if (!onlyCheck) { - var arr = Array.isArray(rule.arg) ? rule.arg : [rule.arg], - message = rule.msg.replace(/%(value|\d+)/g, function(foo, m) { - return Nette.getValue(m === 'value' ? curElem : elem.form.elements.namedItem(arr[m].control)); - }); + let arr = Array.isArray(rule.arg) ? rule.arg : [rule.arg], + message = rule.msg.replace( + /%(value|\d+)/g, + (foo, m) => Nette.getValue(m === 'value' ? curElem : elem.form.elements.namedItem(arr[m].control)) + ); Nette.addError(curElem, message); } return false; @@ -192,15 +199,18 @@ /** * Validates whole form. + * @param {HTMLFormElement} sender + * @param {boolean} onlyCheck + * @return {boolean} */ - Nette.validateForm = function(sender, onlyCheck) { - var form = sender.form || sender, - scope = false; + Nette.validateForm = function (sender, onlyCheck = false) { + let form = sender.form ?? sender, + scope; Nette.formErrors = []; if (form['nette-submittedBy'] && form['nette-submittedBy'].getAttribute('formnovalidate') !== null) { - var scopeArr = JSON.parse(form['nette-submittedBy'].getAttribute('data-nette-validation-scope') || '[]'); + let scopeArr = JSON.parse(form['nette-submittedBy'].getAttribute('data-nette-validation-scope') ?? '[]'); if (scopeArr.length) { scope = new RegExp('^(' + scopeArr.join('-|') + '-)'); } else { @@ -209,38 +219,25 @@ } } - var radios = {}, i, elem; - - for (i = 0; i < form.elements.length; i++) { - elem = form.elements[i]; - - if (elem.tagName && !(elem.tagName.toLowerCase() in {input: 1, select: 1, textarea: 1, button: 1})) { - continue; - - } else if (elem.type === 'radio') { - if (radios[elem.name]) { - continue; - } - radios[elem.name] = true; - - } else if (elem.type === 'number' && elem.validity.badInput && !Nette.isDisabled(elem)) { - if (onlyCheck) { - return false; - } - Nette.addError(elem, Nette.invalidNumberMessage); - continue; - } - - if ((scope && !elem.name.replace(/]\[|\[|]|$/g, '-').match(scope)) || Nette.isDisabled(elem)) { - continue; + for (let elem of form.elements) { + if (elem.willValidate && elem.validity.badInput) { + elem.reportValidity(); + return false; } + } - if (!Nette.validateControl(elem, null, onlyCheck) && !Nette.formErrors.length) { + for (let elem of Array.from(form.elements)) { + if (elem.getAttribute('data-nette-rules') + && (!scope || elem.name.replace(/]\[|\[|]|$/g, '-').match(scope)) + && !Nette.isDisabled(elem) + && !Nette.validateControl(elem, null, onlyCheck) + && !Nette.formErrors.length + ) { return false; } } - var success = !Nette.formErrors.length; + let success = !Nette.formErrors.length; Nette.showFormErrors(form, Nette.formErrors); return success; }; @@ -248,15 +245,13 @@ /** * Check if input is disabled. + * @param {FormElement} elem + * @return {boolean} */ - Nette.isDisabled = function(elem) { + Nette.isDisabled = function (elem) { if (elem.type === 'radio') { - for (var i = 0, elements = elem.form.elements; i < elements.length; i++) { - if (elements[i].name === elem.name && !elements[i].disabled) { - return false; - } - } - return true; + return expandRadioElement(elem) + .every((input) => input.disabled); } return elem.disabled; }; @@ -264,8 +259,10 @@ /** * Adds error message to the queue. + * @param {FormElement} elem + * @param {string} message */ - Nette.addError = function(elem, message) { + Nette.addError = function (elem, message) { Nette.formErrors.push({ element: elem, message: message @@ -275,26 +272,25 @@ /** * Display error messages. + * @param {HTMLFormElement} form + * @param {Array<{element: FormElement, message: string}>} errors */ - Nette.showFormErrors = function(form, errors) { - var messages = [], + Nette.showFormErrors = function (form, errors) { + let messages = [], focusElem; - for (var i = 0; i < errors.length; i++) { - var elem = errors[i].element, - message = errors[i].message; + for (let error of errors) { + if (messages.indexOf(error.message) < 0) { + messages.push(error.message); - if (messages.indexOf(message) < 0) { - messages.push(message); - - if (!focusElem && elem.focus) { - focusElem = elem; + if (!focusElem && error.element.focus) { + focusElem = error.element; } } } if (messages.length) { - Nette.showModal(messages.join('\n'), function () { + Nette.showModal(messages.join('\n'), () => { if (focusElem) { focusElem.focus(); } @@ -305,9 +301,11 @@ /** * Display modal window. + * @param {string} message + * @param {function} onclose */ - Nette.showModal = function(message, onclose) { - var dialog = document.createElement('dialog'); + Nette.showModal = function (message, onclose) { + let dialog = document.createElement('dialog'); if (!dialog.showModal) { alert(message); @@ -315,12 +313,12 @@ return; } - var style = document.createElement('style'); + let style = document.createElement('style'); style.innerText = '.netteFormsModal { text-align: center; margin: auto; border: 2px solid black; padding: 1rem } .netteFormsModal button { padding: .1em 2em }'; - var button = document.createElement('button'); + let button = document.createElement('button'); button.innerText = 'OK'; - button.onclick = function () { + button.onclick = () => { dialog.remove(); onclose(); }; @@ -335,55 +333,57 @@ /** * Validates single rule. + * @param {FormElement} elem + * @param {string} op + * @param {*} arg + * @param {?{value: *}} value */ - Nette.validateRule = function(elem, op, arg, value) { - if (elem.type === 'number' && elem.validity.badInput) { - return op === 'filled'; + Nette.validateRule = function (elem, op, arg, value) { + if (elem.validity.badInput) { + return op === ':filled'; } - value = value === undefined ? {value: Nette.getEffectiveValue(elem, true)} : value; + value ??= {value: Nette.getEffectiveValue(elem, true)}; - if (op.charAt(0) === ':') { - op = op.substr(1); - } - op = op.replace('::', '_'); - op = op.replace(/\\/g, ''); - - var arr = Array.isArray(arg) ? arg.slice(0) : [arg]; - for (var i = 0, len = arr.length; i < len; i++) { - if (arr[i] && arr[i].control) { - var control = elem.form.elements.namedItem(arr[i].control); - arr[i] = control === elem ? value.value : Nette.getEffectiveValue(control, true); + let method = op.charAt(0) === ':' ? op.substring(1) : op; + method = method.replace('::', '_').replaceAll('\\', ''); + + let args = Array.isArray(arg) ? arg : [arg]; + args = args.map((arg) => { + if (arg?.control) { + let control = getFormElement(elem.form, arg.control); + return control === elem ? value.value : Nette.getEffectiveValue(control, true); } - } + return arg; + }); - return Nette.validators[op] - ? Nette.validators[op](elem, Array.isArray(arg) ? arr : arr[0], value.value, value) + return Nette.validators[method] + ? Nette.validators[method](elem, Array.isArray(arg) ? args : args[0], value.value, value) : null; }; Nette.validators = { - filled: function(elem, arg, val) { + filled: function (elem, arg, val) { return val !== '' && val !== false && val !== null && (!Array.isArray(val) || !!val.length) && (!(val instanceof FileList) || val.length); }, - blank: function(elem, arg, val) { + blank: function (elem, arg, val) { return !Nette.validators.filled(elem, arg, val); }, - valid: function(elem) { + valid: function (elem) { return Nette.validateControl(elem, null, true); }, - equal: function(elem, arg, val) { + equal: function (elem, arg, val) { if (arg === undefined) { return null; } - var toString = function(val) { + let toString = (val) => { if (typeof val === 'number' || typeof val === 'string') { return '' + val; } else { @@ -394,9 +394,9 @@ val = Array.isArray(val) ? val : [val]; arg = Array.isArray(arg) ? arg : [arg]; loop: - for (var i1 = 0, len1 = val.length; i1 < len1; i1++) { - for (var i2 = 0, len2 = arg.length; i2 < len2; i2++) { - if (toString(val[i1]) === toString(arg[i2])) { + for (let a of val) { + for (let b of arg) { + if (toString(a) === toString(b)) { continue loop; } } @@ -405,111 +405,107 @@ return val.length > 0; }, - notEqual: function(elem, arg, val) { + notEqual: function (elem, arg, val) { return arg === undefined ? null : !Nette.validators.equal(elem, arg, val); }, - minLength: function(elem, arg, val) { + minLength: function (elem, arg, val) { + val = typeof val === 'number' ? val.toString() : val; return val.length >= arg; }, - maxLength: function(elem, arg, val) { + maxLength: function (elem, arg, val) { + val = typeof val === 'number' ? val.toString() : val; return val.length <= arg; }, - length: function(elem, arg, val) { + length: function (elem, arg, val) { + val = typeof val === 'number' ? val.toString() : val; arg = Array.isArray(arg) ? arg : [arg, arg]; return (arg[0] === null || val.length >= arg[0]) && (arg[1] === null || val.length <= arg[1]); }, - email: function(elem, arg, val) { + email: function (elem, arg, val) { return (/^("([ !#-[\]-~]|\\[ -~])+"|[-a-z0-9!#$%&'*+/=?^_`{|}~]+(\.[-a-z0-9!#$%&'*+/=?^_`{|}~]+)*)@([0-9a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,61}[0-9a-z\u00C0-\u02FF\u0370-\u1EFF])?\.)+[a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,17}[a-z\u00C0-\u02FF\u0370-\u1EFF])?$/i).test(val); }, - url: function(elem, arg, val, value) { + url: function (elem, arg, val, newValue) { if (!(/^[a-z\d+.-]+:/).test(val)) { val = 'https://' + val; } if ((/^https?:\/\/((([-_0-9a-z\u00C0-\u02FF\u0370-\u1EFF]+\.)*[0-9a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,61}[0-9a-z\u00C0-\u02FF\u0370-\u1EFF])?\.)?[a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,17}[a-z\u00C0-\u02FF\u0370-\u1EFF])?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[[0-9a-f:]{3,39}\])(:\d{1,5})?(\/\S*)?$/i).test(val)) { - value.value = val; + newValue.value = val; return true; } return false; }, - regexp: function(elem, arg, val) { - var parts = typeof arg === 'string' ? arg.match(/^\/(.*)\/([imu]*)$/) : false; + regexp: function (elem, arg, val) { + let parts = typeof arg === 'string' ? arg.match(/^\/(.*)\/([imu]*)$/) : false; try { return parts && (new RegExp(parts[1], parts[2].replace('u', ''))).test(val); - } catch (e) {} // eslint-disable-line no-empty + } catch {} // eslint-disable-line no-empty }, - pattern: function(elem, arg, val, value, caseInsensitive) { + pattern: function (elem, arg, val, newValue, caseInsensitive) { if (typeof arg !== 'string') { return null; } try { + let regExp; try { - var regExp = new RegExp('^(?:' + arg + ')$', caseInsensitive ? 'ui' : 'u'); - } catch (e) { + regExp = new RegExp('^(?:' + arg + ')$', caseInsensitive ? 'ui' : 'u'); + } catch { regExp = new RegExp('^(?:' + arg + ')$', caseInsensitive ? 'i' : ''); } - if (val instanceof FileList) { - for (var i = 0; i < val.length; i++) { - if (!regExp.test(val[i].name)) { - return false; - } - } - - return true; - } - - return regExp.test(val); - } catch (e) {} // eslint-disable-line no-empty + return val instanceof FileList + ? Array.from(val).every((file) => regExp.test(file.name)) + : regExp.test(val); + } catch {} // eslint-disable-line no-empty }, - patternCaseInsensitive: function(elem, arg, val) { + patternCaseInsensitive: function (elem, arg, val) { return Nette.validators.pattern(elem, arg, val, null, true); }, - numeric: function(elem, arg, val) { + numeric: function (elem, arg, val) { return (/^[0-9]+$/).test(val); }, - integer: function(elem, arg, val, value) { + integer: function (elem, arg, val, newValue) { if ((/^-?[0-9]+$/).test(val)) { - value.value = parseFloat(val); + newValue.value = parseFloat(val); return true; } return false; }, - 'float': function(elem, arg, val, value) { + 'float': function (elem, arg, val, newValue) { val = val.replace(/ +/g, '').replace(/,/g, '.'); if ((/^-?[0-9]*\.?[0-9]+$/).test(val)) { - value.value = parseFloat(val); + newValue.value = parseFloat(val); return true; } return false; }, - min: function(elem, arg, val) { + min: function (elem, arg, val) { if (Number.isFinite(arg)) { val = parseFloat(val); } return val >= arg; }, - max: function(elem, arg, val) { + max: function (elem, arg, val) { if (Number.isFinite(arg)) { val = parseFloat(val); } return val <= arg; }, - range: function(elem, arg, val) { + range: function (elem, arg, val) { if (!Array.isArray(arg)) { return null; } else if (elem.type === 'time' && arg[0] > arg[1]) { @@ -519,40 +515,24 @@ && (arg[1] === null || Nette.validators.max(elem, arg[1], val)); }, - submitted: function(elem) { + submitted: function (elem) { return elem.form['nette-submittedBy'] === elem; }, - fileSize: function(elem, arg, val) { - for (var i = 0; i < val.length; i++) { - if (val[i].size > arg) { - return false; - } - } - return true; + fileSize: function (elem, arg, val) { + return Array.from(val).every((file) => file.size <= arg); }, - mimeType: function (elem, arg, val) { - arg = Array.isArray(arg) ? arg : [arg]; - for (var i = 0, len = arg.length, re = []; i < len; i++) { - re.push('^' + arg[i].replace(/([^\w])/g, '\\$1').replace('\\*', '.*') + '$'); - } + mimeType: function (elem, args, val) { + let re = []; + args = Array.isArray(args) ? args : [args]; + args.forEach((arg) => re.push('^' + arg.replace(/([^\w])/g, '\\$1').replace('\\*', '.*') + '$')); re = new RegExp(re.join('|')); - - if (val instanceof FileList) { - for (i = 0; i < val.length; i++) { - if (val[i].type && !re.test(val[i].type)) { - return false; - } else if (elem.validity.badInput) { - return null; - } - } - } - return true; + return Array.from(val).every((file) => !file.type || re.test(file.type)); }, image: function (elem, arg, val) { - return Nette.validators.mimeType(elem, arg || ['image/gif', 'image/png', 'image/jpeg', 'image/webp'], val); + return Nette.validators.mimeType(elem, arg ?? ['image/gif', 'image/png', 'image/jpeg', 'image/webp'], val); }, 'static': function (elem, arg) { @@ -563,17 +543,18 @@ /** * Process all toggles in form. + * @param {HTMLFormElement} form + * @param {?Event} event */ - Nette.toggleForm = function(form, event) { - var i; + Nette.toggleForm = function (form, event = null) { formToggles = {}; - for (i = 0; i < form.elements.length; i++) { - if (form.elements[i].tagName.toLowerCase() in {input: 1, select: 1, textarea: 1, button: 1}) { - Nette.toggleControl(form.elements[i], null, null, !event); + for (let elem of Array.from(form.elements)) { + if (elem.getAttribute('data-nette-rules')) { + Nette.toggleControl(elem, null, null, !event); } } - for (i in formToggles) { + for (let i in formToggles) { Nette.toggle(i, formToggles[i].state, formToggles[i].elem, event); } }; @@ -581,22 +562,25 @@ /** * Process toggles on form element. + * @param {FormElement} elem + * @param {?Array} rules + * @param {?boolean} success + * @param {boolean} firsttime + * @param {?{value: *}} value + * @param {?boolean} emptyOptional + * @return {boolean} */ - Nette.toggleControl = function(elem, rules, success, firsttime, value, emptyOptional) { - rules = rules || JSON.parse(elem.getAttribute('data-nette-rules') || '[]'); - value = value === undefined ? {value: Nette.getEffectiveValue(elem)} : value; - emptyOptional = emptyOptional === undefined ? !Nette.validateRule(elem, ':filled', null, value) : emptyOptional; - - var has = false, - handler = function (e) { - Nette.toggleForm(elem.form, e); - }, + Nette.toggleControl = function (elem, rules, success, firsttime, value = null, emptyOptional = null) { + rules ??= JSON.parse(elem.getAttribute('data-nette-rules') ?? '[]'); + value ??= {value: Nette.getEffectiveValue(elem)}; + emptyOptional ??= !Nette.validateRule(elem, ':filled', null, value); + + let has = false, curSuccess; - for (var id = 0, len = rules.length; id < len; id++) { - var rule = rules[id], - op = rule.op.match(/(~)?([^?]+)/), - curElem = rule.control ? elem.form.elements.namedItem(rule.control) : elem; + for (let rule of rules) { + let op = rule.op.match(/(~)?([^?]+)/), + curElem = rule.control ? getFormElement(elem.form, rule.control) : elem; rule.neg = op[1]; rule.op = op[2]; @@ -625,19 +609,15 @@ if ((rule.condition && Nette.toggleControl(elem, rule.rules, curSuccess, firsttime, value, rule.op === ':blank' ? false : emptyOptional)) || rule.toggle) { has = true; if (firsttime) { - var name = curElem.tagName ? curElem.name : curElem[0].name, - els = curElem.tagName ? curElem.form.elements : curElem; - - for (var i = 0; i < els.length; i++) { - if (els[i].name === name && !toggleListeners.has(els[i])) { - els[i].addEventListener('change', handler); - toggleListeners.set(els[i], null); - } - } + expandRadioElement(curElem) + .filter((el) => !toggleListeners.has(el)) + .forEach((el) => { + el.addEventListener('change', (e) => Nette.toggleForm(elem.form, e)); + toggleListeners.set(el, null); + }); } - for (var toggleId in rule.toggle || []) { - formToggles[toggleId] = formToggles[toggleId] || {elem: elem}; - formToggles[toggleId].state = formToggles[toggleId].state || (rule.toggle[toggleId] ? curSuccess : !curSuccess); + for (let id in rule.toggle ?? []) { + formToggles[id] ??= {elem: elem, state: rule.toggle[id] ? curSuccess : !curSuccess}; } } } @@ -647,76 +627,52 @@ /** * Displays or hides HTML element. + * @param {string} selector + * @param {boolean} visible + * @param {FormElement} srcElement + * @param {Event} event */ - Nette.toggle = function(selector, visible, srcElement, event) { // eslint-disable-line no-unused-vars + Nette.toggle = function (selector, visible, srcElement, event) { // eslint-disable-line no-unused-vars if (/^\w[\w.:-]*$/.test(selector)) { // id selector = '#' + selector; } - var elems = document.querySelectorAll(selector); - for (var i = 0; i < elems.length; i++) { - elems[i].hidden = !visible; - } + Array.from(document.querySelectorAll(selector)) + .forEach((elem) => elem.hidden = !visible); }; /** * Compact checkboxes + * @param {HTMLFormElement} form + * @param {FormData} formData */ - Nette.compactCheckboxes = function(form) { - var name, i, elem, values = {}; - - for (i = 0; i < form.elements.length; i++) { - elem = form.elements[i]; - if (elem.tagName - && elem.tagName.toLowerCase() === 'input' - && elem.type === 'checkbox' - ) { - if (elem.name - && elem.name.substr(-2) === '[]' - ) { - name = elem.name.substr(0, elem.name.length - 2); - elem.removeAttribute('name'); - elem.setAttribute('data-nette-name', name); - } + Nette.compactCheckboxes = function (form, formData) { + let values = {}; - if (name = elem.getAttribute('data-nette-name')) { // eslint-disable-line no-cond-assign - values[name] = values[name] || []; - if (elem.checked && !elem.disabled) { - values[name].push(elem.value); - } - } + for (let elem of form.elements) { + if (elem instanceof HTMLInputElement && elem.type === 'checkbox' && elem.name.endsWith('[]') && elem.checked && !elem.disabled) { + formData.delete(elem.name); + values[elem.name] ??= []; + values[elem.name].push(elem.value); } } - for (name in values) { - if (form.elements[name] === undefined) { - elem = document.createElement('input'); - elem.setAttribute('name', name); - elem.setAttribute('type', 'hidden'); - form.append(elem); - } - form.elements[name].value = values[name].join(','); - form.elements[name].disabled = values[name].length === 0; + for (let name in values) { + formData.set(name.substring(0, name.length - 2), values[name].join(',')); } }; /** * Setup handlers. + * @param {HTMLFormElement} form */ - Nette.initForm = function(form) { + Nette.initForm = function (form) { if (form.method === 'get' && form.hasAttribute('data-nette-compact')) { - form.addEventListener('submit', function() { - Nette.compactCheckboxes(form); - }); + form.addEventListener('formdata', (e) => Nette.compactCheckboxes(form, e.formData)); } - check: { - for (var i = 0; i < form.elements.length; i++) { - if (form.elements[i].getAttribute('data-nette-rules')) { - break check; - } - } + if (!Array.from(form.elements).some((elem) => elem.getAttribute('data-nette-rules'))) { return; } @@ -727,17 +683,15 @@ } form.noValidate = true; - form.addEventListener('submit', function(e) { + form.addEventListener('submit', (e) => { if (!Nette.validateForm(form)) { e.stopPropagation(); e.preventDefault(); } }); - form.addEventListener('reset', function() { - setTimeout(function() { - Nette.toggleForm(form); - }); + form.addEventListener('reset', () => { + setTimeout(() => Nette.toggleForm(form)); }); }; @@ -745,14 +699,13 @@ /** * @private */ - Nette.initOnLoad = function() { - Nette.onDocumentReady(function() { - for (var i = 0; i < document.forms.length; i++) { - Nette.initForm(document.forms[i]); - } + Nette.initOnLoad = function () { + Nette.onDocumentReady(() => { + Array.from(document.forms) + .forEach((form) => Nette.initForm(form)); - document.body.addEventListener('click', function(e) { - var target = e.target; + document.body.addEventListener('click', (e) => { + let target = e.target; while (target) { if (target.form && target.type in {submit: 1, image: 1}) { target.form['nette-submittedBy'] = target; @@ -767,11 +720,13 @@ /** * Converts string to web safe characters [a-z0-9-] text. + * @param {string} s + * @return {string} */ - Nette.webalize = function(s) { + Nette.webalize = function (s) { s = s.toLowerCase(); - var res = '', i, ch; - for (i = 0; i < s.length; i++) { + let res = '', ch; + for (let i = 0; i < s.length; i++) { ch = Nette.webalizeTable[s.charAt(i)]; res += ch ? ch : s.charAt(i); } diff --git a/site/vendor/nette/forms/src/assets/netteForms.min.js b/site/vendor/nette/forms/src/assets/netteForms.min.js index 17f189a18..272db1f96 100644 --- a/site/vendor/nette/forms/src/assets/netteForms.min.js +++ b/site/vendor/nette/forms/src/assets/netteForms.min.js @@ -1,22 +1,7 @@ -(function(p,e){if(p.JSON)if("function"===typeof define&&define.amd)define(function(){return e(p)});else if("object"===typeof module&&"object"===typeof module.exports)module.exports=e(p);else{var u=!p.Nette||!p.Nette.noInit;p.Nette=e(p);u&&p.Nette.initOnLoad()}})("undefined"!==typeof window?window:this,function(p){var e={},u={},r={},x=new p.WeakMap;e.formErrors=[];e.version="3.3.0";e.invalidNumberMessage="Please enter a valid value.";e.onDocumentReady=function(a){"loading"!==document.readyState?a.call(this): -document.addEventListener("DOMContentLoaded",a)};e.getValue=function(a){var b;if(a){if(a.tagName){if("radio"===a.type){var c=a.form.elements;for(b=0;bb?null:c[b].value;for(b=0;ba.indexOf(g)&&(a.push(g),!c&&f.focus&&(c=f))}a.length&&e.showModal(a.join("\n"),function(){c&&c.focus()})};e.showModal=function(a,b){var c=document.createElement("dialog");if(c.showModal){var d=document.createElement("style");d.innerText=".netteFormsModal { text-align: center; margin: auto; border: 2px solid black; padding: 1rem } .netteFormsModal button { padding: .1em 2em }";var f=document.createElement("button");f.innerText= -"OK";f.onclick=function(){c.remove();b()};c.setAttribute("class","netteFormsModal");c.innerText=a+"\n\n";c.append(d,f);document.body.append(c);c.showModal()}else alert(a),b()};e.validateRule=function(a,b,c,d){if("number"===a.type&&a.validity.badInput)return"filled"===b;d=void 0===d?{value:e.getEffectiveValue(a,!0)}:d;":"===b.charAt(0)&&(b=b.substr(1));b=b.replace("::","_");b=b.replace(/\\/g,"");for(var f=Array.isArray(c)?c.slice(0):[c],g=0,q=f.length;g=b},maxLength:function(a,b,c){return c.length<=b},length:function(a,b,c){b=Array.isArray(b)?b:[b,b];return(null===b[0]||c.length>=b[0])&&(null===b[1]||c.length<=b[1])},email:function(a,b,c){return/^("([ !#-[\]-~]|\\[ -~])+"|[-a-z0-9!#$%&'*+/=?^_`{|}~]+(\.[-a-z0-9!#$%&'*+/=?^_`{|}~]+)*)@([0-9a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,61}[0-9a-z\u00C0-\u02FF\u0370-\u1EFF])?\.)+[a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,17}[a-z\u00C0-\u02FF\u0370-\u1EFF])?$/i.test(c)}, -url:function(a,b,c,d){/^[a-z\d+.-]+:/.test(c)||(c="https://"+c);return/^https?:\/\/((([-_0-9a-z\u00C0-\u02FF\u0370-\u1EFF]+\.)*[0-9a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,61}[0-9a-z\u00C0-\u02FF\u0370-\u1EFF])?\.)?[a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,17}[a-z\u00C0-\u02FF\u0370-\u1EFF])?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[[0-9a-f:]{3,39}\])(:\d{1,5})?(\/\S*)?$/i.test(c)?(d.value=c,!0):!1},regexp:function(a,b,c){a="string"===typeof b?b.match(/^\/(.*)\/([imu]*)$/): -!1;try{return a&&(new RegExp(a[1],a[2].replace("u",""))).test(c)}catch(d){}},pattern:function(a,b,c,d,f){if("string"!==typeof b)return null;try{try{var g=new RegExp("^(?:"+b+")$",f?"ui":"u")}catch(q){g=new RegExp("^(?:"+b+")$",f?"i":"")}if(c instanceof FileList){for(a=0;a=b},max:function(a,b,c){Number.isFinite(b)&&(c=parseFloat(c));return c<=b},range:function(a,b,c){return Array.isArray(b)?"time"===a.type&&b[0]>b[1]?c>=b[0]||c<=b[1]:(null===b[0]||e.validators.min(a,b[0],c))&&(null===b[1]||e.validators.max(a, -b[1],c)):null},submitted:function(a){return a.form["nette-submittedBy"]===a},fileSize:function(a,b,c){for(a=0;ab)return!1;return!0},mimeType:function(a,b,c){b=Array.isArray(b)?b:[b];for(var d=0,f=b.length,g=[];dt(e)));else if("object"==typeof module&&"object"==typeof module.exports)module.exports=t(e);else{var n;let r=!(null!==(n=e.Nette)&&void 0!==n&&n.noInit);e.Nette=t(e),r&&e.Nette.initOnLoad()}}("undefined"!=typeof window?window:void 0,(e=>{const t={};let n={},r={},o=new e.WeakMap;function l(e,t){let n=e.elements.namedItem(t);return n instanceof RadioNodeList?n[0]:n}function a(e){let t=e.form.elements.namedItem(e.name);return t instanceof RadioNodeList?Array.from(t):[t]}return t.formErrors=[],t.version="3.3.0",t.onDocumentReady=function(e){"loading"!==document.readyState?e.call(this):document.addEventListener("DOMContentLoaded",e)},t.getValue=function(e){var n,r;return e instanceof HTMLInputElement?"radio"===e.type?(null===(n=a(e).find((e=>e.checked)))||void 0===n?void 0:n.value)??null:"file"===e.type?e.files:"checkbox"===e.type?e.name.endsWith("[]")?a(e).filter((e=>e.checked)).map((e=>e.value)):e.checked:e.value.trim():e instanceof HTMLSelectElement?e.multiple?Array.from(e.selectedOptions,(e=>e.value)):(null===(r=e.selectedOptions[0])||void 0===r?void 0:r.value)??null:e instanceof HTMLTextAreaElement?e.value:e instanceof RadioNodeList?t.getValue(e[0]):null},t.getEffectiveValue=function(e,r=!1){let o=t.getValue(e);if(o===e.getAttribute("data-nette-empty-value")&&(o=""),r&&void 0===n[e.name]){n[e.name]=!0;let r={value:o};t.validateControl(e,null,!0,r),o=r.value,delete n[e.name]}return o},t.validateControl=function(e,n,r=!1,o=null,a=null){n??=JSON.parse(e.getAttribute("data-nette-rules")??"[]"),o??={value:t.getEffectiveValue(e)},a??=!t.validateRule(e,":filled",null,o);for(let i of n){let n=i.op.match(/(~)?([^?]+)/),u=i.control?l(e.form,i.control):e;if(i.neg=n[1],i.op=n[2],i.condition=!!i.rules,!u)continue;if(a&&!i.condition&&":filled"!==i.op)continue;let f=t.validateRule(u,i.op,i.arg,e===u?o:void 0);if(null!==f)if(i.neg&&(f=!f),i.condition&&f){if(!t.validateControl(e,i.rules,r,o,":blank"!==i.op&&a))return!1}else if(!i.condition&&!f){if(t.isDisabled(u))continue;if(!r){let n=Array.isArray(i.arg)?i.arg:[i.arg],r=i.msg.replace(/%(value|\d+)/g,((r,o)=>t.getValue("value"===o?u:e.form.elements.namedItem(n[o].control))));t.addError(u,r)}return!1}}return!0},t.validateForm=function(e,n=!1){let r,o=e.form??e;if(t.formErrors=[],o["nette-submittedBy"]&&null!==o["nette-submittedBy"].getAttribute("formnovalidate")){let e=JSON.parse(o["nette-submittedBy"].getAttribute("data-nette-validation-scope")??"[]");if(!e.length)return t.showFormErrors(o,[]),!0;r=new RegExp("^("+e.join("-|")+"-)")}for(let e of o.elements)if(e.willValidate&&e.validity.badInput)return e.reportValidity(),!1;for(let e of Array.from(o.elements))if(e.getAttribute("data-nette-rules")&&(!r||e.name.replace(/]\[|\[|]|$/g,"-").match(r))&&!t.isDisabled(e)&&!t.validateControl(e,null,n)&&!t.formErrors.length)return!1;let l=!t.formErrors.length;return t.showFormErrors(o,t.formErrors),l},t.isDisabled=function(e){return"radio"===e.type?a(e).every((e=>e.disabled)):e.disabled},t.addError=function(e,n){t.formErrors.push({element:e,message:n})},t.showFormErrors=function(e,n){let r,o=[];for(let e of n)o.indexOf(e.message)<0&&(o.push(e.message),!r&&e.element.focus&&(r=e.element));o.length&&t.showModal(o.join("\n"),(()=>{r&&r.focus()}))},t.showModal=function(e,t){let n=document.createElement("dialog");if(!n.showModal)return alert(e),void t();let r=document.createElement("style");r.innerText=".netteFormsModal { text-align: center; margin: auto; border: 2px solid black; padding: 1rem } .netteFormsModal button { padding: .1em 2em }";let o=document.createElement("button");o.innerText="OK",o.onclick=()=>{n.remove(),t()},n.setAttribute("class","netteFormsModal"),n.innerText=e+"\n\n",n.append(r,o),document.body.append(n),n.showModal()},t.validateRule=function(e,n,r,o){if(e.validity.badInput)return":filled"===n;o??={value:t.getEffectiveValue(e,!0)};let a=":"===n.charAt(0)?n.substring(1):n;a=a.replace("::","_").replaceAll("\\","");let i=Array.isArray(r)?r:[r];return i=i.map((n=>{if(null!=n&&n.control){let r=l(e.form,n.control);return r===e?o.value:t.getEffectiveValue(r,!0)}return n})),t.validators[a]?t.validators[a](e,Array.isArray(r)?i:i[0],o.value,o):null},t.validators={filled:function(e,t,n){return""!==n&&!1!==n&&null!==n&&(!Array.isArray(n)||!!n.length)&&(!(n instanceof FileList)||n.length)},blank:function(e,n,r){return!t.validators.filled(e,n,r)},valid:function(e){return t.validateControl(e,null,!0)},equal:function(e,t,n){if(void 0===t)return null;let r=e=>"number"==typeof e||"string"==typeof e?""+e:!0===e?"1":"";n=Array.isArray(n)?n:[n],t=Array.isArray(t)?t:[t];e:for(let e of n){for(let n of t)if(r(e)===r(n))continue e;return!1}return n.length>0},notEqual:function(e,n,r){return void 0===n?null:!t.validators.equal(e,n,r)},minLength:function(e,t,n){return(n="number"==typeof n?n.toString():n).length>=t},maxLength:function(e,t,n){return(n="number"==typeof n?n.toString():n).length<=t},length:function(e,t,n){return n="number"==typeof n?n.toString():n,(null===(t=Array.isArray(t)?t:[t,t])[0]||n.length>=t[0])&&(null===t[1]||n.length<=t[1])},email:function(e,t,n){return/^("([ !#-[\]-~]|\\[ -~])+"|[-a-z0-9!#$%&'*+/=?^_`{|}~]+(\.[-a-z0-9!#$%&'*+/=?^_`{|}~]+)*)@([0-9a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,61}[0-9a-z\u00C0-\u02FF\u0370-\u1EFF])?\.)+[a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,17}[a-z\u00C0-\u02FF\u0370-\u1EFF])?$/i.test(n)},url:function(e,t,n,r){return/^[a-z\d+.-]+:/.test(n)||(n="https://"+n),!!/^https?:\/\/((([-_0-9a-z\u00C0-\u02FF\u0370-\u1EFF]+\.)*[0-9a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,61}[0-9a-z\u00C0-\u02FF\u0370-\u1EFF])?\.)?[a-z\u00C0-\u02FF\u0370-\u1EFF]([-0-9a-z\u00C0-\u02FF\u0370-\u1EFF]{0,17}[a-z\u00C0-\u02FF\u0370-\u1EFF])?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[[0-9a-f:]{3,39}\])(:\d{1,5})?(\/\S*)?$/i.test(n)&&(r.value=n,!0)},regexp:function(e,t,n){let r="string"==typeof t&&t.match(/^\/(.*)\/([imu]*)$/);try{return r&&new RegExp(r[1],r[2].replace("u","")).test(n)}catch{}},pattern:function(e,t,n,r,o){if("string"!=typeof t)return null;try{let e;try{e=new RegExp("^(?:"+t+")$",o?"ui":"u")}catch{e=new RegExp("^(?:"+t+")$",o?"i":"")}return n instanceof FileList?Array.from(n).every((t=>e.test(t.name))):e.test(n)}catch{}},patternCaseInsensitive:function(e,n,r){return t.validators.pattern(e,n,r,null,!0)},numeric:function(e,t,n){return/^[0-9]+$/.test(n)},integer:function(e,t,n,r){return!!/^-?[0-9]+$/.test(n)&&(r.value=parseFloat(n),!0)},float:function(e,t,n,r){return n=n.replace(/ +/g,"").replace(/,/g,"."),!!/^-?[0-9]*\.?[0-9]+$/.test(n)&&(r.value=parseFloat(n),!0)},min:function(e,t,n){return Number.isFinite(t)&&(n=parseFloat(n)),n>=t},max:function(e,t,n){return Number.isFinite(t)&&(n=parseFloat(n)),n<=t},range:function(e,n,r){return Array.isArray(n)?"time"===e.type&&n[0]>n[1]?r>=n[0]||r<=n[1]:(null===n[0]||t.validators.min(e,n[0],r))&&(null===n[1]||t.validators.max(e,n[1],r)):null},submitted:function(e){return e.form["nette-submittedBy"]===e},fileSize:function(e,t,n){return Array.from(n).every((e=>e.size<=t))},mimeType:function(e,t,n){let r=[];return(t=Array.isArray(t)?t:[t]).forEach((e=>r.push("^"+e.replace(/([^\w])/g,"\\$1").replace("\\*",".*")+"$"))),r=new RegExp(r.join("|")),Array.from(n).every((e=>!e.type||r.test(e.type)))},image:function(e,n,r){return t.validators.mimeType(e,n??["image/gif","image/png","image/jpeg","image/webp"],r)},static:function(e,t){return t}},t.toggleForm=function(e,n=null){r={};for(let r of Array.from(e.elements))r.getAttribute("data-nette-rules")&&t.toggleControl(r,null,null,!n);for(let e in r)t.toggle(e,r[e].state,r[e].elem,n)},t.toggleControl=function(e,n,i,u,f=null,d=null){n??=JSON.parse(e.getAttribute("data-nette-rules")??"[]"),f??={value:t.getEffectiveValue(e)},d??=!t.validateRule(e,":filled",null,f);let s,c=!1;for(let m of n){let n=m.op.match(/(~)?([^?]+)/),g=m.control?l(e.form,m.control):e;if(m.neg=n[1],m.op=n[2],m.condition=!!m.rules,g&&(!d||m.condition||":filled"===m.op)){if(s=i,!1!==i){if(s=t.validateRule(g,m.op,m.arg,e===g?f:void 0),null===s)continue;m.neg&&(s=!s),m.condition||(i=s)}if(m.condition&&t.toggleControl(e,m.rules,s,u,f,":blank"!==m.op&&d)||m.toggle){c=!0,u&&a(g).filter((e=>!o.has(e))).forEach((n=>{n.addEventListener("change",(n=>t.toggleForm(e.form,n))),o.set(n,null)}));for(let t in m.toggle??[])r[t]??={elem:e,state:m.toggle[t]?s:!s}}}}return c},t.toggle=function(e,t,n,r){/^\w[\w.:-]*$/.test(e)&&(e="#"+e),Array.from(document.querySelectorAll(e)).forEach((e=>e.hidden=!t))},t.compactCheckboxes=function(e,t){let n={};for(let r of e.elements)r instanceof HTMLInputElement&&"checkbox"===r.type&&r.name.endsWith("[]")&&r.checked&&!r.disabled&&(t.delete(r.name),n[r.name]??=[],n[r.name].push(r.value));for(let e in n)t.set(e.substring(0,e.length-2),n[e].join(","))},t.initForm=function(e){"get"===e.method&&e.hasAttribute("data-nette-compact")&&e.addEventListener("formdata",(n=>t.compactCheckboxes(e,n.formData))),Array.from(e.elements).some((e=>e.getAttribute("data-nette-rules")))&&(t.toggleForm(e),e.noValidate||(e.noValidate=!0,e.addEventListener("submit",(n=>{t.validateForm(e)||(n.stopPropagation(),n.preventDefault())})),e.addEventListener("reset",(()=>{setTimeout((()=>t.toggleForm(e)))}))))},t.initOnLoad=function(){t.onDocumentReady((()=>{Array.from(document.forms).forEach((e=>t.initForm(e))),document.body.addEventListener("click",(e=>{let t=e.target;for(;t;){if(t.form&&t.type in{submit:1,image:1}){t.form["nette-submittedBy"]=t;break}t=t.parentNode}}))}))},t.webalize=function(e){e=e.toLowerCase();let n,r="";for(let o=0;o