Skip to content

Commit c508a5d

Browse files
TAINCERTimm Ortloff
authored andcommitted
Create invisible duplicate submit button if more than one submitElements is present
1 parent 7208f1a commit c508a5d

3 files changed

Lines changed: 154 additions & 0 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
Automatically set CSS class for duplicated submit buttons
3+
used for implicit form submission that should be invisible
4+
and not take up any space. `display: none` is not an option,
5+
because at least Safari will then ignore the element completely
6+
when submitting a form.
7+
*/
8+
.primary-submit-btn-duplicate {
9+
border: 0;
10+
height: 0;
11+
margin: 0;
12+
padding: 0;
13+
visibility: hidden;
14+
width: 0;
15+
position: absolute;
16+
}

src/Compat/CompatForm.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
namespace ipl\Web\Compat;
44

5+
use ipl\Html\Contract\FormSubmitElement;
56
use ipl\Html\Form;
7+
use ipl\Html\FormElement\SubmitElement;
8+
use ipl\Html\HtmlDocument;
9+
use ipl\Html\HtmlString;
610
use ipl\I18n\Translation;
711
use ipl\Web\FormDecorator\IcingaFormDecorator;
812

@@ -12,6 +16,27 @@ class CompatForm extends Form
1216

1317
protected $defaultAttributes = ['class' => 'icinga-form icinga-controls'];
1418

19+
/**
20+
* Render the content of the element to HTML
21+
*
22+
* A duplicate of the primary submit button is being prepended if there is more than one present
23+
*
24+
* @return string
25+
*/
26+
public function renderContent(): string
27+
{
28+
if (count($this->submitElements) > 1) {
29+
return (new HtmlDocument())
30+
->setHtmlContent(
31+
$this->duplicateSubmitButton($this->submitButton),
32+
new HtmlString(parent::renderContent())
33+
)
34+
->render();
35+
}
36+
37+
return parent::renderContent();
38+
}
39+
1540
public function hasDefaultElementDecorator()
1641
{
1742
if (parent::hasDefaultElementDecorator()) {
@@ -22,4 +47,20 @@ public function hasDefaultElementDecorator()
2247

2348
return true;
2449
}
50+
51+
/**
52+
* Return a duplicate of the given submit button with the `class` attribute fixed to `primary-submit-btn-duplicate`
53+
*
54+
* @param FormSubmitElement $originalSubmitButton
55+
*
56+
* @return SubmitElement
57+
*/
58+
public function duplicateSubmitButton(FormSubmitElement $originalSubmitButton): SubmitElement
59+
{
60+
$attributes = (clone $originalSubmitButton->getAttributes())
61+
->set('class', 'primary-submit-btn-duplicate');
62+
$attributes->remove('id');
63+
64+
return new SubmitElement($originalSubmitButton->getName(), $attributes);
65+
}
2566
}

tests/Compat/CompatFormTest.php

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
namespace ipl\Tests\Web\Compat;
4+
5+
use ipl\Html\FormElement\SubmitElement;
6+
use ipl\Tests\Html\TestCase;
7+
use ipl\Web\Compat\CompatForm;
8+
9+
class CompatFormTest extends TestCase
10+
{
11+
/** @var CompatForm */
12+
private $form;
13+
14+
protected function setUp(): void
15+
{
16+
$this->form = new CompatForm();
17+
}
18+
19+
public function testDuplicateSubmitButtonApplied(): void
20+
{
21+
$this->form->addElement('submit', 'submitCreate');
22+
$this->form->addElement('submit', 'submitDelete');
23+
24+
$expected = <<<'HTML'
25+
<form class="icinga-form icinga-controls" method="POST">
26+
<input class="primary-submit-btn-duplicate" name="submitCreate" type="submit" value="submitCreate"/>
27+
<div class="control-group form-controls">
28+
<input class="btn-primary" name="submitCreate" type="submit" value="submitCreate"/>
29+
</div>
30+
<div class="control-group form-controls">
31+
<input class="btn-primary" name="submitDelete" type="submit" value="submitDelete"/>
32+
</div>
33+
</form>
34+
HTML;
35+
36+
$this->assertHtml($expected, $this->form);
37+
}
38+
39+
public function testDuplicateSubmitButtonOmitted(): void
40+
{
41+
$this->form->addElement('submit', 'submitCreate');
42+
43+
$expected = <<<'HTML'
44+
<form class="icinga-form icinga-controls" method="POST">
45+
<div class="control-group form-controls">
46+
<input class="btn-primary" name="submitCreate" type="submit" value="submitCreate"/>
47+
</div>
48+
</form>
49+
HTML;
50+
51+
$this->assertHtml($expected, $this->form);
52+
}
53+
54+
public function testDuplicateSubmitButtonAddedOnlyOnce(): void
55+
{
56+
$this->form->addElement('submit', 'submitCreate', ['id' => 'submit_id']);
57+
$this->form->addElement('submit', 'submitDelete');
58+
59+
$expected = <<<'HTML'
60+
<form class="icinga-form icinga-controls" method="POST">
61+
<input class="primary-submit-btn-duplicate" name="submitCreate" type="submit" value="submitCreate"/>
62+
<div class="control-group form-controls">
63+
<input id="submit_id" class="btn-primary" name="submitCreate" type="submit" value="submitCreate"/>
64+
</div>
65+
<div class="control-group form-controls">
66+
<input class="btn-primary" name="submitDelete" type="submit" value="submitDelete"/>
67+
</div>
68+
</form>
69+
HTML;
70+
71+
$this->form->render();
72+
73+
$this->assertHtml($expected, $this->form);
74+
}
75+
76+
public function testDuplicateSubmitButtonRespectsOriginalAttributes(): void
77+
{
78+
$submitButton = new SubmitElement('test_submit', [
79+
'class' => 'autosubmit',
80+
'formnovalidate' => true
81+
]);
82+
83+
$prefixButton = $this->form->duplicateSubmitButton($submitButton);
84+
85+
// Name should stay the same
86+
$this->assertSame($submitButton->getName(), 'test_submit');
87+
$this->assertSame($prefixButton->getName(), 'test_submit');
88+
89+
// Added attributes should stay the same
90+
$this->assertSame($submitButton->getAttributes()->get('formnovalidate')->getValue(), true);
91+
$this->assertSame($prefixButton->getAttributes()->get('formnovalidate')->getValue(), true);
92+
93+
// Class attribute should change to `primary-submit-btn-duplicate`
94+
$this->assertSame($submitButton->getAttributes()->get('class')->getValue(), 'autosubmit');
95+
$this->assertSame($prefixButton->getAttributes()->get('class')->getValue(), 'primary-submit-btn-duplicate');
96+
}
97+
}

0 commit comments

Comments
 (0)