Skip to content

Commit 065cfdd

Browse files
authored
Fix #109: Add class for tag Datalist and method Html::datalist(), add specialized class for input tag with type Range and methods Html::range(), Input::range()
1 parent 5c59331 commit 065cfdd

10 files changed

Lines changed: 474 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
## 2.4.0 under development
44

55
- New #103: Add class for tag `Form` and method `Html::form()` (vjik)
6+
- New #109: Add class for tag `Datalist` and method `Html::datalist()` (vjik)
7+
- New #109: Add specialized class for input tag with type `Range` and methods `Html::range()`, `Input::range()` (vjik)
68
- Enh #106: Add option groups support to method `Select::optionsData()` (vjik)
79
- Enh #108: Add individual attributes of options and option groups support to method `Select::optionsData()` (vjik)
810
- Enh #102: Remove psalm type `HtmlAttributes`, too obsessive for package users (vjik)

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717

1818
The package provides various tools to help with dynamic server-side generation of HTML:
1919

20-
- Tag classes `A`, `Audio`, `B`, `Br`, `Button`, `Caption`, `Col`, `Colgroup`, `Div`, `Em`, `Form`, `H1`, `H2`, `H3`,
21-
`H4`, `H5`, `H6` `I`, `Img`, `Input` (and specialized `Checkbox`, `Radio`), `Label`, `Li`, `Link`, `Meta`, `Noscript`,
22-
`Ol`, `Optgroup`, `Option`, `P`, `Picture`, `Script`, `Select`, `Source`, `Span`, `Strong`, `Style`, `Table`, `Tbody`,
23-
`Td`, `Textarea`, `Tfoot`, `Th`, `Thead`, `Title`, `Tr`, `Track`, `Ul`, `Video`.
20+
- Tag classes `A`, `Audio`, `B`, `Br`, `Button`, `Caption`, `Col`, `Colgroup`, `Datalist`, `Div`, `Em`, `Form`, `H1`,
21+
`H2`, `H3`, `H4`, `H5`, `H6` `I`, `Img`, `Input` (and specialized `Checkbox`, `Radio`, `Range`), `Label`, `Li`, `Link`,
22+
`Meta`, `Noscript`, `Ol`, `Optgroup`, `Option`, `P`, `Picture`, `Script`, `Select`, `Source`, `Span`, `Strong`,
23+
`Style`, `Table`, `Tbody`, `Td`, `Textarea`, `Tfoot`, `Th`, `Thead`, `Title`, `Tr`, `Track`, `Ul`, `Video`.
2424
- `CustomTag` class that helps to generate custom tag with any attributes.
2525
- HTML widgets `CheckboxList` and `RadioList`.
2626
- All tags content is automatically HTML-encoded. There is `NoEncode` class designed to wrap content that should not be encoded.
@@ -277,6 +277,7 @@ Overall the helper has the following method groups.
277277
- button
278278
- buttonInput
279279
- checkbox
280+
- datalist
280281
- fileInput
281282
- form
282283
- hiddenInput

src/Html.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Yiisoft\Html\Tag\Col;
1717
use Yiisoft\Html\Tag\Colgroup;
1818
use Yiisoft\Html\Tag\CustomTag;
19+
use Yiisoft\Html\Tag\Datalist;
1920
use Yiisoft\Html\Tag\Div;
2021
use Yiisoft\Html\Tag\Em;
2122
use Yiisoft\Html\Tag\Form;
@@ -30,6 +31,7 @@
3031
use Yiisoft\Html\Tag\Input;
3132
use Yiisoft\Html\Tag\Input\Checkbox;
3233
use Yiisoft\Html\Tag\Input\Radio;
34+
use Yiisoft\Html\Tag\Input\Range;
3335
use Yiisoft\Html\Tag\Label;
3436
use Yiisoft\Html\Tag\Li;
3537
use Yiisoft\Html\Tag\Link;
@@ -756,6 +758,21 @@ public static function radio(?string $name = null, $value = null, array $attribu
756758
return $attributes === [] ? $tag : $tag->attributes($attributes);
757759
}
758760

761+
/**
762+
* Generates a range {@see Range}.
763+
*
764+
* @see Input::range()
765+
*
766+
* @param string|null $name The name attribute.
767+
* @param float|int|string|Stringable|null $value The value attribute.
768+
* @param array $attributes The tag attributes in terms of name-value pairs.
769+
*/
770+
public static function range(?string $name = null, $value = null, array $attributes = []): Range
771+
{
772+
$tag = Input::range($name, $value);
773+
return $attributes === [] ? $tag : $tag->attributes($attributes);
774+
}
775+
759776
/**
760777
* Generates a checkbox {@see Input}.
761778
*
@@ -1072,6 +1089,21 @@ public static function li($content = ''): Li
10721089
return $content === '' ? $tag : $tag->content($content);
10731090
}
10741091

1092+
/**
1093+
* Generates a {@see Datalist} tag.
1094+
*
1095+
* @param string|Stringable $content Tag content.
1096+
* @param array $attributes The tag attributes in terms of name-value pairs.
1097+
*/
1098+
public static function datalist(array $attributes = []): Datalist
1099+
{
1100+
$tag = Datalist::tag();
1101+
if (!empty($attributes)) {
1102+
$tag = $tag->attributes($attributes);
1103+
}
1104+
return $tag;
1105+
}
1106+
10751107
/**
10761108
* Generates a {@see Caption} tag.
10771109
*

src/Tag/Datalist.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yiisoft\Html\Tag;
6+
7+
use Yiisoft\Html\Tag\Base\NormalTag;
8+
use Yiisoft\Html\Tag\Base\TagContentTrait;
9+
10+
/**
11+
* @link https://html.spec.whatwg.org/#the-datalist-element
12+
*/
13+
final class Datalist extends NormalTag
14+
{
15+
use TagContentTrait;
16+
17+
protected function getName(): string
18+
{
19+
return 'datalist';
20+
}
21+
}

src/Tag/Input.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Yiisoft\Html\Tag\Base\InputTag;
88
use Yiisoft\Html\Tag\Input\Checkbox;
99
use Yiisoft\Html\Tag\Input\Radio;
10+
use Yiisoft\Html\Tag\Input\Range;
1011

1112
/**
1213
* HTML input.
@@ -135,6 +136,26 @@ public static function radio(?string $name = null, $value = null): Radio
135136
return $input;
136137
}
137138

139+
/**
140+
* Range.
141+
*
142+
* @link https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)
143+
*
144+
* @param string|null $name Name of the input.
145+
* @param float|int|string|\Stringable|null $value Value of the input.
146+
*/
147+
public static function range(?string $name = null, $value = null): Range
148+
{
149+
$input = Range::tag();
150+
if ($name !== null) {
151+
$input = $input->name($name);
152+
}
153+
if ($value !== null) {
154+
$input = $input->value($value);
155+
}
156+
return $input;
157+
}
158+
138159
/**
139160
* Button.
140161
*

src/Tag/Input/Range.php

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yiisoft\Html\Tag\Input;
6+
7+
use InvalidArgumentException;
8+
use Yiisoft\Html\Html;
9+
use Yiisoft\Html\Tag\Base\InputTag;
10+
use Yiisoft\Html\Tag\CustomTag;
11+
12+
/**
13+
* An imprecise control for setting the element’s value to a string representing a number.
14+
*
15+
* @link https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)
16+
*/
17+
final class Range extends InputTag
18+
{
19+
private bool $showOutput = false;
20+
21+
/**
22+
* @psalm-var non-empty-string
23+
*/
24+
private string $outputTagName = 'span';
25+
private array $outputTagAttributes = [];
26+
private ?string $outputTagId = null;
27+
28+
/**
29+
* Maximum value.
30+
*
31+
* @param float|int|string|\Stringable|null $value
32+
*
33+
* @link https://html.spec.whatwg.org/multipage/input.html#attr-input-max
34+
*/
35+
public function max($value): self
36+
{
37+
$new = clone $this;
38+
$new->attributes['max'] = $value;
39+
return $new;
40+
}
41+
42+
/**
43+
* Minimum value.
44+
*
45+
* @param float|int|string|\Stringable|null $value
46+
*
47+
* @link https://html.spec.whatwg.org/multipage/input.html#attr-input-min
48+
*/
49+
public function min($value): self
50+
{
51+
$new = clone $this;
52+
$new->attributes['min'] = $value;
53+
return $new;
54+
}
55+
56+
/**
57+
* Granularity to be matched by the form control's value.
58+
*
59+
* @param float|int|string|\Stringable|null $value
60+
*
61+
* @link https://html.spec.whatwg.org/multipage/input.html#attr-input-step
62+
*/
63+
public function step($value): self
64+
{
65+
$new = clone $this;
66+
$new->attributes['step'] = $value;
67+
return $new;
68+
}
69+
70+
/**
71+
* ID of element that lists predefined options suggested to the user.
72+
*
73+
* @link https://html.spec.whatwg.org/multipage/input.html#the-list-attribute
74+
*/
75+
public function list(?string $id): self
76+
{
77+
$new = clone $this;
78+
$new->attributes['list'] = $id;
79+
return $new;
80+
}
81+
82+
public function showOutput(bool $show = true): self
83+
{
84+
$new = clone $this;
85+
$new->showOutput = $show;
86+
return $new;
87+
}
88+
89+
public function outputTagName(string $tagName): self
90+
{
91+
if ($tagName === '') {
92+
throw new InvalidArgumentException('The output tag name it cannot be empty value.');
93+
}
94+
95+
$new = clone $this;
96+
$new->outputTagName = $tagName;
97+
return $new;
98+
}
99+
100+
public function outputTagAttributes(array $attributes): self
101+
{
102+
$new = clone $this;
103+
$new->outputTagAttributes = $attributes;
104+
return $new;
105+
}
106+
107+
protected function prepareAttributes(): void
108+
{
109+
$this->attributes['type'] = 'range';
110+
111+
if ($this->showOutput) {
112+
$this->outputTagId = (string) ($this->outputTagAttributes['id'] ?? Html::generateId('rangeOutput'));
113+
$this->attributes['oninput'] = 'document.getElementById("' . $this->outputTagId . '").innerHTML=this.value';
114+
}
115+
}
116+
117+
protected function after(): string
118+
{
119+
if (!$this->showOutput) {
120+
return '';
121+
}
122+
123+
return "\n" . CustomTag::name($this->outputTagName)
124+
->attributes($this->outputTagAttributes)
125+
->content((string) ($this->attributes['value'] ?? '-'))
126+
->id($this->outputTagId)
127+
->render();
128+
}
129+
}

tests/common/HtmlTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,22 @@ public function testCheckbox(): void
419419
);
420420
}
421421

422+
public function testRange(): void
423+
{
424+
$this->assertSame('<input type="range">', Html::range()->render());
425+
$this->assertSame('<input type="range" name>', Html::range('')->render());
426+
$this->assertSame('<input type="range" value>', Html::range(null, '')->render());
427+
$this->assertSame('<input type="range" name="test">', Html::range('test')->render());
428+
$this->assertSame(
429+
'<input type="range" name="test" value="43">',
430+
Html::range('test', '43')->render(),
431+
);
432+
$this->assertSame(
433+
'<input type="range" name="test" value="43" readonly>',
434+
Html::range('test', '43', ['readonly' => true])->render(),
435+
);
436+
}
437+
422438
public function testSelect(): void
423439
{
424440
$this->assertSame('<select></select>', Html::select()->render());
@@ -609,6 +625,12 @@ public function testLi(): void
609625
$this->assertSame('<li><span>Hello</span></li>', Html::li(Html::span('Hello'))->render());
610626
}
611627

628+
public function testDatalist(): void
629+
{
630+
$this->assertSame('<datalist></datalist>', Html::datalist()->render());
631+
$this->assertSame('<datalist id="numbers"></datalist>', Html::datalist(['id' => 'numbers'])->render());
632+
}
633+
612634
public function testCaption(): void
613635
{
614636
$this->assertSame('<caption></caption>', Html::caption()->render());

tests/common/Tag/DatalistTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yiisoft\Html\Tests\Tag;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Yiisoft\Html\Tag\Datalist;
9+
use Yiisoft\Html\Tag\Option;
10+
use Yiisoft\Html\Tests\Support\AssertTrait;
11+
12+
final class DatalistTest extends TestCase
13+
{
14+
use AssertTrait;
15+
16+
public function testBase(): void
17+
{
18+
$tag = Datalist::tag()
19+
->id('numbers')
20+
->content(
21+
Option::tag()->value('One'),
22+
Option::tag()->value('Two'),
23+
);
24+
25+
$this->assertSame(
26+
'<datalist id="numbers"><option value="One"></option><option value="Two"></option></datalist>',
27+
$tag->render()
28+
);
29+
}
30+
}

0 commit comments

Comments
 (0)