diff --git a/asset/css/primary-submit-btn-duplicate.less b/asset/css/primary-submit-btn-duplicate.less new file mode 100644 index 00000000..aae545f0 --- /dev/null +++ b/asset/css/primary-submit-btn-duplicate.less @@ -0,0 +1,16 @@ +/** + Automatically set CSS class for duplicated submit buttons + used for implicit form submission that should be invisible + and not take up any space. `display: none` is not an option, + because at least Safari will then ignore the element completely + when submitting a form. + */ +.primary-submit-btn-duplicate { + border: 0; + height: 0; + margin: 0; + padding: 0; + visibility: hidden; + width: 0; + position: absolute; +} diff --git a/src/Compat/CompatForm.php b/src/Compat/CompatForm.php index b759b8fa..ef973159 100644 --- a/src/Compat/CompatForm.php +++ b/src/Compat/CompatForm.php @@ -2,7 +2,11 @@ namespace ipl\Web\Compat; +use ipl\Html\Contract\FormSubmitElement; use ipl\Html\Form; +use ipl\Html\FormElement\SubmitElement; +use ipl\Html\HtmlDocument; +use ipl\Html\HtmlString; use ipl\I18n\Translation; use ipl\Web\FormDecorator\IcingaFormDecorator; @@ -12,6 +16,27 @@ class CompatForm extends Form protected $defaultAttributes = ['class' => 'icinga-form icinga-controls']; + /** + * Render the content of the element to HTML + * + * A duplicate of the primary submit button is being prepended if there is more than one present. + * + * @return string + */ + public function renderContent(): string + { + if (count($this->submitElements) > 1) { + return (new HtmlDocument()) + ->setHtmlContent( + $this->duplicateSubmitButton($this->submitButton), + new HtmlString(parent::renderContent()) + ) + ->render(); + } + + return parent::renderContent(); + } + public function hasDefaultElementDecorator() { if (parent::hasDefaultElementDecorator()) { @@ -22,4 +47,28 @@ public function hasDefaultElementDecorator() return true; } + + /** + * Return a duplicate of the given submit button with the `class` attribute fixed to `primary-submit-btn-duplicate` + * + * @param FormSubmitElement $originalSubmitButton + * + * @return SubmitElement + */ + public function duplicateSubmitButton(FormSubmitElement $originalSubmitButton): SubmitElement + { + $attributes = array_reduce( + $originalSubmitButton->getAttributes()->getIterator()->getArrayCopy(), + function ($accumulator, $attribute) { + $accumulator[$attribute->getName()] = $attribute->getValue(); + }, + [] + ); + $attributes['class'] = 'primary-submit-btn-duplicate'; + + $submit = (new SubmitElement($originalSubmitButton->getName(), $attributes)) + ->setValue($originalSubmitButton->getValue()); + + return $submit; + } } diff --git a/tests/Compat/CompatFormTest.php b/tests/Compat/CompatFormTest.php new file mode 100644 index 00000000..ec6845fb --- /dev/null +++ b/tests/Compat/CompatFormTest.php @@ -0,0 +1,92 @@ +form = new CompatForm(); + } + + public function testDuplicateSubmitButtonApplied(): void + { + $this->form->addElement('submit', 'submitCreate'); + $this->form->addElement('submit', 'submitDelete'); + + $expected = <<<'HTML' +
+HTML; + + $this->assertHtml($expected, $this->form); + } + + public function testDuplicateSubmitButtonOmitted(): void + { + $this->form->addElement('submit', 'submitCreate'); + + $expected = <<<'HTML' + +HTML; + + $this->assertHtml($expected, $this->form); + } + + public function testDuplicateSubmitButtonAddedOnlyOnce(): void + { + $this->form->addElement('submit', 'submitCreate'); + $this->form->addElement('submit', 'submitDelete'); + + $expected = <<<'HTML' + +HTML; + + $this->form->render(); + + $this->assertHtml($expected, $this->form); + } + + public function testCreatingDuplicateSubmitButton(): void + { + $submitButton = new SubmitElement('test_submit', [ + 'class' => 'autosubmit' + ]); + + $prefixButton = $this->form->duplicateSubmitButton($submitButton); + + // Name should stay the same + $this->assertSame($submitButton->getName(), 'test_submit'); + $this->assertSame($prefixButton->getName(), 'test_submit'); + + // Class attribute should change to `primary-submit-btn-duplicate` + $this->assertSame($submitButton->getAttributes()->get('class')->getValue(), 'autosubmit'); + $this->assertSame($prefixButton->getAttributes()->get('class')->getValue(), 'primary-submit-btn-duplicate'); + } +}