updated rendering of widgets

This commit is contained in:
Simon Karlen 2021-07-12 17:22:29 +02:00
parent 96f471a0bb
commit ee1415b6c3
No known key found for this signature in database
GPG Key ID: 0630C27D666EBCC3
33 changed files with 419 additions and 443 deletions

View File

@ -150,7 +150,7 @@ class Accordion extends Widget
} }
$header = ArrayHelper::remove($item, 'label'); $header = ArrayHelper::remove($item, 'label');
$options = ArrayHelper::getValue($item, 'options', []); $options = ArrayHelper::getValue($item, 'options', []);
Html::addCssClass($options, ['panel' => 'card']); Html::addCssClass($options, ['panel' => 'accordion-item']);
$items[] = Html::tag('div', $this->renderItem($header, $item, $index++), $options); $items[] = Html::tag('div', $this->renderItem($header, $item, $index++), $options);
} }
@ -192,18 +192,22 @@ class Accordion extends Widget
$itemToggleOptions = array_merge([ $itemToggleOptions = array_merge([
'tag' => 'button', 'tag' => 'button',
'type' => 'button', 'type' => 'button',
'data-toggle' => 'collapse', 'data' => [
'data-target' => '#' . $options['id'], 'bs-toggle' => 'collapse',
'aria-expanded' => $expand ? 'true' : 'false', 'bs-target' => '#' . $options['id']
'aria-controls' => $options['id'], ],
'aria' => [
'expanded' => $expand ? 'true' : 'false',
'controls' => $options['id']
]
], $this->itemToggleOptions); ], $this->itemToggleOptions);
$itemToggleTag = ArrayHelper::remove($itemToggleOptions, 'tag', 'button'); $itemToggleTag = ArrayHelper::remove($itemToggleOptions, 'tag', 'button');
if ($itemToggleTag === 'a') { if ($itemToggleTag === 'a') {
ArrayHelper::remove($itemToggleOptions, 'data-target'); ArrayHelper::remove($itemToggleOptions, 'data.bs-target');
$headerToggle = Html::a($header, '#' . $id, $itemToggleOptions) . "\n"; $headerToggle = Html::a($header, '#' . $id, $itemToggleOptions) . "\n";
} else { } else {
Html::addCssClass($itemToggleOptions, ['feature' => 'btn-link']); Html::addCssClass($itemToggleOptions, ['widget' => 'accordion-button']);
$headerToggle = Button::widget([ $headerToggle = Button::widget([
'label' => $header, 'label' => $header,
'encodeLabel' => false, 'encodeLabel' => false,
@ -214,7 +218,7 @@ class Accordion extends Widget
$header = Html::tag('h5', $headerToggle, ['class' => 'mb-0']); $header = Html::tag('h5', $headerToggle, ['class' => 'mb-0']);
if (is_string($item['content']) || is_numeric($item['content']) || is_object($item['content'])) { if (is_string($item['content']) || is_numeric($item['content']) || is_object($item['content'])) {
$content = Html::tag('div', $item['content'], ['class' => 'card-body']) . "\n"; $content = Html::tag('div', $item['content'], ['class' => 'accordion-body']) . "\n";
} elseif (is_array($item['content'])) { } elseif (is_array($item['content'])) {
$content = Html::ul($item['content'], [ $content = Html::ul($item['content'], [
'class' => 'list-group', 'class' => 'list-group',
@ -232,14 +236,14 @@ class Accordion extends Widget
$group = []; $group = [];
if ($this->autoCloseItems) { if ($this->autoCloseItems) {
$options['data-parent'] = '#' . $this->options['id']; $options['data']['bs-parent'] = '#' . $this->options['id'];
} }
$group[] = Html::tag('div', $header, ['class' => 'card-header', 'id' => $options['id'] . '-heading']); $group[] = Html::tag('div', $header, ['class' => 'accordion-header', 'id' => $options['id'] . '-heading']);
$group[] = Html::beginTag('div', $options); $group[] = Html::beginTag('div', $options);
$group[] = $content; $group[] = $content;
if (isset($item['footer'])) { if (isset($item['footer'])) {
$group[] = Html::tag('div', $item['footer'], ['class' => 'card-footer']); $group[] = Html::tag('div', $item['footer'], ['class' => 'accordion-footer']);
} }
$group[] = Html::endTag('div'); $group[] = Html::endTag('div');

View File

@ -105,7 +105,7 @@ class ActiveField extends \yii\widgets\ActiveField
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public $options = ['class' => ['widget' => 'form-group']]; public $options = ['class' => ['widget' => 'mb-3']];
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -120,9 +120,9 @@ class ActiveField extends \yii\widgets\ActiveField
* @since 2.0.7 * @since 2.0.7
*/ */
public array $checkOptions = [ public array $checkOptions = [
'class' => ['widget' => 'custom-control-input'], 'class' => ['widget' => 'form-check-input'],
'labelOptions' => [ 'labelOptions' => [
'class' => ['widget' => 'custom-control-label'], 'class' => ['widget' => 'form-check-label'],
], ],
]; ];
/** /**
@ -135,9 +135,9 @@ class ActiveField extends \yii\widgets\ActiveField
* @since 2.0.7 * @since 2.0.7
*/ */
public array $radioOptions = [ public array $radioOptions = [
'class' => ['widget' => 'custom-control-input'], 'class' => ['widget' => 'form-check-input'],
'labelOptions' => [ 'labelOptions' => [
'class' => ['widget' => 'custom-control-label'], 'class' => ['widget' => 'form-check-label'],
], ],
]; ];
/** /**
@ -147,7 +147,7 @@ class ActiveField extends \yii\widgets\ActiveField
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public $labelOptions = []; public $labelOptions = ['class' => ['widget' => 'form-label']];
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -164,21 +164,21 @@ class ActiveField extends \yii\widgets\ActiveField
/** /**
* @var string the template for checkboxes in default layout * @var string the template for checkboxes in default layout
*/ */
public string $checkTemplate = "<div class=\"custom-control custom-checkbox\">\n{input}\n{label}\n{error}\n{hint}\n</div>"; public string $checkTemplate = "<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>";
/** /**
* @var string the template for radios in default layout * @var string the template for radios in default layout
* @since 2.0.5 * @since 2.0.5
*/ */
public string $radioTemplate = "<div class=\"custom-control custom-radio\">\n{input}\n{label}\n{error}\n{hint}\n</div>"; public string $radioTemplate = "<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>";
/** /**
* @var string the template for checkboxes and radios in horizontal layout * @var string the template for checkboxes and radios in horizontal layout
*/ */
public string $checkHorizontalTemplate = "{beginWrapper}\n<div class=\"custom-control custom-checkbox\">\n{input}\n{label}\n{error}\n{hint}\n</div>\n{endWrapper}"; public string $checkHorizontalTemplate = "{beginWrapper}\n<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>\n{endWrapper}";
/** /**
* @var string the template for checkboxes and radios in horizontal layout * @var string the template for checkboxes and radios in horizontal layout
* @since 2.0.5 * @since 2.0.5
*/ */
public string $radioHorizontalTemplate = "{beginWrapper}\n<div class=\"custom-control custom-radio\">\n{input}\n{label}\n{error}\n{hint}\n</div>\n{endWrapper}"; public string $radioHorizontalTemplate = "{beginWrapper}\n<div class=\"form-check\">\n{input}\n{label}\n{error}\n{hint}\n</div>\n{endWrapper}";
/** /**
* @var string the `enclosed by label` template for checkboxes and radios in default layout * @var string the `enclosed by label` template for checkboxes and radios in default layout
*/ */
@ -248,9 +248,9 @@ class ActiveField extends \yii\widgets\ActiveField
{ {
$checkOptions = $this->checkOptions; $checkOptions = $this->checkOptions;
$options = ArrayHelper::merge($checkOptions, $options); $options = ArrayHelper::merge($checkOptions, $options);
Html::removeCssClass($options, 'form-control');
$labelOptions = ArrayHelper::remove($options, 'labelOptions', []); $labelOptions = ArrayHelper::remove($options, 'labelOptions', []);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', []); $wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', []);
Html::removeCssClass($options, 'form-control');
$this->labelOptions = ArrayHelper::merge($this->labelOptions, $labelOptions); $this->labelOptions = ArrayHelper::merge($this->labelOptions, $labelOptions);
$this->wrapperOptions = ArrayHelper::merge($this->wrapperOptions, $wrapperOptions); $this->wrapperOptions = ArrayHelper::merge($this->wrapperOptions, $wrapperOptions);
@ -266,6 +266,7 @@ class ActiveField extends \yii\widgets\ActiveField
Html::removeCssClass($this->labelOptions, $this->horizontalCssClasses['label']); Html::removeCssClass($this->labelOptions, $this->horizontalCssClasses['label']);
Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']); Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']);
} }
Html::removeCssClass($this->labelOptions, 'form-label');
unset($options['template']); unset($options['template']);
if ($enclosedByLabel) { if ($enclosedByLabel) {
@ -284,9 +285,9 @@ class ActiveField extends \yii\widgets\ActiveField
{ {
$checkOptions = $this->radioOptions; $checkOptions = $this->radioOptions;
$options = ArrayHelper::merge($checkOptions, $options); $options = ArrayHelper::merge($checkOptions, $options);
Html::removeCssClass($options, 'form-control');
$labelOptions = ArrayHelper::remove($options, 'labelOptions', []); $labelOptions = ArrayHelper::remove($options, 'labelOptions', []);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', []); $wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', []);
Html::removeCssClass($options, 'form-control');
$this->labelOptions = ArrayHelper::merge($this->labelOptions, $labelOptions); $this->labelOptions = ArrayHelper::merge($this->labelOptions, $labelOptions);
$this->wrapperOptions = ArrayHelper::merge($this->wrapperOptions, $wrapperOptions); $this->wrapperOptions = ArrayHelper::merge($this->wrapperOptions, $wrapperOptions);
@ -302,6 +303,7 @@ class ActiveField extends \yii\widgets\ActiveField
Html::removeCssClass($this->labelOptions, $this->horizontalCssClasses['label']); Html::removeCssClass($this->labelOptions, $this->horizontalCssClasses['label']);
Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']); Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']);
} }
Html::removeCssClass($this->labelOptions, 'form-label');
unset($options['template']); unset($options['template']);
if ($enclosedByLabel && isset($options['label'])) { if ($enclosedByLabel && isset($options['label'])) {
@ -332,10 +334,10 @@ class ActiveField extends \yii\widgets\ActiveField
'label' => $encode ? Html::encode($label) : $label, 'label' => $encode ? Html::encode($label) : $label,
'value' => $value, 'value' => $value,
], $itemOptions); ], $itemOptions);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', ['class' => ['custom-control', 'custom-checkbox']]); $wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', ['class' => ['form-check']]);
if ($this->inline) { // if ($this->inline) {
Html::addCssClass($wrapperOptions, 'custom-control-inline'); // Html::addCssClass($wrapperOptions, 'custom-control-inline');
} // }
$html = Html::beginTag('div', $wrapperOptions) . "\n" . $html = Html::beginTag('div', $wrapperOptions) . "\n" .
Html::checkbox($name, $checked, $options) . "\n"; Html::checkbox($name, $checked, $options) . "\n";
@ -373,10 +375,10 @@ class ActiveField extends \yii\widgets\ActiveField
'label' => $encode ? Html::encode($label) : $label, 'label' => $encode ? Html::encode($label) : $label,
'value' => $value, 'value' => $value,
], $itemOptions); ], $itemOptions);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', ['class' => ['custom-control', 'custom-radio']]); $wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', ['class' => ['form-check']]);
if ($this->inline) { // if ($this->inline) {
Html::addCssClass($wrapperOptions, 'custom-control-inline'); // Html::addCssClass($wrapperOptions, 'custom-control-inline');
} // }
$html = Html::beginTag('div', $wrapperOptions) . "\n" . $html = Html::beginTag('div', $wrapperOptions) . "\n" .
Html::radio($name, $checked, $options) . "\n"; Html::radio($name, $checked, $options) . "\n";
@ -399,7 +401,7 @@ class ActiveField extends \yii\widgets\ActiveField
public function listBox($items, $options = []) public function listBox($items, $options = [])
{ {
if ($this->form->layout === ActiveForm::LAYOUT_INLINE) { if ($this->form->layout === ActiveForm::LAYOUT_INLINE) {
Html::removeCssClass($this->labelOptions, 'sr-only'); Html::removeCssClass($this->labelOptions, 'visually-hidden');
} }
return parent::listBox($items, $options); return parent::listBox($items, $options);
@ -411,7 +413,7 @@ class ActiveField extends \yii\widgets\ActiveField
public function dropdownList($items, $options = []) public function dropdownList($items, $options = [])
{ {
if ($this->form->layout === ActiveForm::LAYOUT_INLINE) { if ($this->form->layout === ActiveForm::LAYOUT_INLINE) {
Html::removeCssClass($this->labelOptions, 'sr-only'); Html::removeCssClass($this->labelOptions, 'visually-hidden');
} }
return parent::dropdownList($items, $options); return parent::dropdownList($items, $options);
@ -482,7 +484,7 @@ class ActiveField extends \yii\widgets\ActiveField
'class' => 'form-control', 'class' => 'form-control',
], ],
'labelOptions' => [ 'labelOptions' => [
'class' => [], 'class' => ['form-label'],
], ],
]; ];
@ -499,7 +501,7 @@ class ActiveField extends \yii\widgets\ActiveField
'wrapper' => 'col-sm-10', 'wrapper' => 'col-sm-10',
'error' => '', 'error' => '',
'hint' => '', 'hint' => '',
'field' => 'form-group row', 'field' => 'mb-3 row',
]; ];
if (isset($instanceConfig['horizontalCssClasses'])) { if (isset($instanceConfig['horizontalCssClasses'])) {
$cssClasses = ArrayHelper::merge($cssClasses, $instanceConfig['horizontalCssClasses']); $cssClasses = ArrayHelper::merge($cssClasses, $instanceConfig['horizontalCssClasses']);
@ -515,7 +517,7 @@ class ActiveField extends \yii\widgets\ActiveField
$config['inputOptions']['placeholder'] = true; $config['inputOptions']['placeholder'] = true;
$config['enableError'] = false; $config['enableError'] = false;
Html::addCssClass($config['labelOptions'], ['screenreader' => 'sr-only']); Html::addCssClass($config['labelOptions'], ['screenreader' => 'visually-hidden']);
} }
return $config; return $config;
@ -526,7 +528,7 @@ class ActiveField extends \yii\widgets\ActiveField
*/ */
public function fileInput($options = []) public function fileInput($options = [])
{ {
Html::addCssClass($options, ['widget' => 'form-control-file']); Html::addCssClass($options, ['widget' => 'form-control']);
return parent::fileInput($options); return parent::fileInput($options);
} }

View File

@ -72,6 +72,10 @@ class ActiveForm extends \yii\widgets\ActiveForm
* Inline form layout * Inline form layout
*/ */
const LAYOUT_INLINE = 'inline'; const LAYOUT_INLINE = 'inline';
/**
* Floating labels form layout
*/
const LAYOUT_FLOATING = 'floating';
/** /**
* @var string the default field class name when calling [[field()]] to create a new field. * @var string the default field class name when calling [[field()]] to create a new field.
@ -114,7 +118,7 @@ class ActiveForm extends \yii\widgets\ActiveForm
*/ */
public function init() public function init()
{ {
if (!in_array($this->layout, [self::LAYOUT_DEFAULT, self::LAYOUT_HORIZONTAL, self::LAYOUT_INLINE])) { if (!in_array($this->layout, [self::LAYOUT_DEFAULT, self::LAYOUT_HORIZONTAL, self::LAYOUT_INLINE, self::LAYOUT_FLOATING])) {
throw new InvalidConfigException('Invalid layout type: ' . $this->layout); throw new InvalidConfigException('Invalid layout type: ' . $this->layout);
} }
@ -125,9 +129,10 @@ class ActiveForm extends \yii\widgets\ActiveForm
} }
/** /**
* @inheritdoc * {@inheritDoc}
* @return ActiveField|\yii\widgets\ActiveField
*/ */
public function field($model, $attribute, $options = []): \yii\widgets\ActiveField public function field($model, $attribute, $options = []): ActiveField
{ {
return parent::field($model, $attribute, $options); return parent::field($model, $attribute, $options);
} }

View File

@ -46,7 +46,7 @@ class Alert extends Widget
* the [[begin()]] and [[end()]] calls of the Alert widget will also be treated * the [[begin()]] and [[end()]] calls of the Alert widget will also be treated
* as the body content, and will be rendered before this. * as the body content, and will be rendered before this.
*/ */
public $body; public string $body;
/** /**
* @var array|false the options for rendering the close button tag. * @var array|false the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking * The close button is displayed in the header of the modal window. Clicking
@ -55,7 +55,6 @@ class Alert extends Widget
* The following special options are supported: * The following special options are supported:
* *
* - tag: string, the tag name of the button. Defaults to 'button'. * - tag: string, the tag name of the button. Defaults to 'button'.
* - label: string, the label of the button. Defaults to '&times;'.
* *
* The rest of the options will be rendered as the HTML attributes of the button tag. * The rest of the options will be rendered as the HTML attributes of the button tag.
* Please refer to the [Alert documentation](https://getbootstrap.com/docs/5.0/components/alerts/) * Please refer to the [Alert documentation](https://getbootstrap.com/docs/5.0/components/alerts/)
@ -91,7 +90,7 @@ class Alert extends Widget
* Renders the alert body and the close button (if any). * Renders the alert body and the close button (if any).
* @return string the rendering result * @return string the rendering result
*/ */
protected function renderBodyEnd() protected function renderBodyEnd(): string
{ {
return $this->body . "\n" . $this->renderCloseButton() . "\n"; return $this->body . "\n" . $this->renderCloseButton() . "\n";
} }
@ -104,14 +103,8 @@ class Alert extends Widget
{ {
if (($closeButton = $this->closeButton) !== false) { if (($closeButton = $this->closeButton) !== false) {
$tag = ArrayHelper::remove($closeButton, 'tag', 'button'); $tag = ArrayHelper::remove($closeButton, 'tag', 'button');
$label = ArrayHelper::remove($closeButton, 'label', Html::tag('span', '&times;', [
'aria-hidden' => 'true',
]));
if ($tag === 'button' && !isset($closeButton['type'])) {
$closeButton['type'] = 'button';
}
return Html::tag($tag, $label, $closeButton); return Html::tag($tag, '', $closeButton);
} else { } else {
return null; return null;
} }
@ -127,8 +120,10 @@ class Alert extends Widget
if ($this->closeButton !== false) { if ($this->closeButton !== false) {
$this->closeButton = array_merge([ $this->closeButton = array_merge([
'data-dismiss' => 'alert', 'type' => 'button',
'class' => ['widget' => 'close'], 'class' => ['widget' => 'btn-close'],
'data' => ['bs-dismiss' => 'alert'],
'aria' => ['label' => 'Close']
], $this->closeButton); ], $this->closeButton);
Html::addCssClass($this->options, ['toggle' => 'alert-dismissible']); Html::addCssClass($this->options, ['toggle' => 'alert-dismissible']);

View File

@ -14,7 +14,5 @@ class BootstrapAsset extends AssetBundle
'css/bootstrap.css', 'css/bootstrap.css',
]; ];
public $js = [ public $js = [];
'js/bootstrap.bundle.js',
];
} }

View File

@ -94,6 +94,4 @@ trait BootstrapWidgetTrait
$this->getView()->registerJs(implode("\n", $js)); $this->getView()->registerJs(implode("\n", $js));
} }
} }
abstract function getView();
} }

View File

@ -89,6 +89,9 @@ class Breadcrumbs extends Widget
Html::addCssClass($this->options, ['widget' => 'breadcrumb']); Html::addCssClass($this->options, ['widget' => 'breadcrumb']);
} }
/**
* {@inheritDoc}
*/
public function run(): string public function run(): string
{ {
if (!isset($this->options['id'])) { if (!isset($this->options['id'])) {
@ -98,8 +101,6 @@ class Breadcrumbs extends Widget
/** @psalm-suppress InvalidArgument */ /** @psalm-suppress InvalidArgument */
Html::addCssClass($this->options, ['widget' => 'breadcrumb']); Html::addCssClass($this->options, ['widget' => 'breadcrumb']);
$this->registerPlugin('breadcrumb');
if (empty($this->links)) { if (empty($this->links)) {
return ''; return '';
} }
@ -133,7 +134,7 @@ class Breadcrumbs extends Widget
* @param string $template the template to be used to rendered the link. The token "{link}" will be replaced by the * @param string $template the template to be used to rendered the link. The token "{link}" will be replaced by the
* link. * link.
* *
* @throws JsonException|RuntimeException if `$link` does not have "label" element. * @throws RuntimeException if `$link` does not have "label" element.
* *
* @return string the rendering result * @return string the rendering result
*/ */

View File

@ -37,6 +37,7 @@ class Button extends Widget
/** /**
* Initializes the widget. * Initializes the widget.
* If you override this method, make sure you call the parent implementation first. * If you override this method, make sure you call the parent implementation first.
* @throws \yii\base\InvalidConfigException
*/ */
public function init() public function init()
{ {
@ -51,8 +52,10 @@ class Button extends Widget
*/ */
public function run(): string public function run(): string
{ {
$this->registerPlugin('button'); return Html::tag(
return Html::tag($this->tagName, $this->encodeLabel ? Html::encode($this->label) : $this->label, $this->tagName,
$this->options); $this->encodeLabel ? Html::encode($this->label) : $this->label,
$this->options
);
} }
} }

View File

@ -147,13 +147,12 @@ class ButtonDropdown extends Widget
if ($this->split) { if ($this->split) {
$buttonOptions = $this->buttonOptions; $buttonOptions = $this->buttonOptions;
$this->buttonOptions['data-toggle'] = 'dropdown'; $this->buttonOptions['data'] = ['bs-toggle' => 'dropdown'];
$this->buttonOptions['aria-haspopup'] = 'true'; $this->buttonOptions['aria'] = ['expanded' => 'false'];
$this->buttonOptions['aria-expanded'] = 'false';
Html::addCssClass($this->buttonOptions, ['toggle' => 'dropdown-toggle dropdown-toggle-split']); Html::addCssClass($this->buttonOptions, ['toggle' => 'dropdown-toggle dropdown-toggle-split']);
unset($buttonOptions['id']); unset($buttonOptions['id']);
$splitButton = Button::widget([ $splitButton = Button::widget([
'label' => '<span class="sr-only">Toggle Dropdown</span>', 'label' => '<span class="visually-hidden">Toggle Dropdown</span>',
'encodeLabel' => false, 'encodeLabel' => false,
'options' => $this->buttonOptions, 'options' => $this->buttonOptions,
'view' => $this->getView(), 'view' => $this->getView(),
@ -161,9 +160,8 @@ class ButtonDropdown extends Widget
} else { } else {
$buttonOptions = $this->buttonOptions; $buttonOptions = $this->buttonOptions;
Html::addCssClass($buttonOptions, ['toggle' => 'dropdown-toggle']); Html::addCssClass($buttonOptions, ['toggle' => 'dropdown-toggle']);
$buttonOptions['data-toggle'] = 'dropdown'; $buttonOptions['data'] = ['bs-toggle' => 'dropdown'];
$buttonOptions['aria-haspopup'] = 'true'; $buttonOptions['aria'] = ['expanded' => 'false'];
$buttonOptions['aria-expanded'] = 'false';
$splitButton = ''; $splitButton = '';
} }

View File

@ -76,7 +76,8 @@ class Carousel extends Widget
/** /**
* Initializes the widget. * {@inheritDoc}
* @throws InvalidConfigException
*/ */
public function init() public function init()
{ {
@ -91,9 +92,10 @@ class Carousel extends Widget
* {@inheritdoc} * {@inheritdoc}
* @throws InvalidConfigException * @throws InvalidConfigException
*/ */
public function run() public function run(): string
{ {
$this->registerPlugin('carousel'); $this->registerPlugin('carousel');
return implode("\n", [ return implode("\n", [
Html::beginTag('div', $this->options), Html::beginTag('div', $this->options),
$this->renderIndicators(), $this->renderIndicators(),
@ -107,21 +109,28 @@ class Carousel extends Widget
* Renders carousel indicators. * Renders carousel indicators.
* @return string the rendering result * @return string the rendering result
*/ */
public function renderIndicators() public function renderIndicators(): string
{ {
if ($this->showIndicators === false) { if ($this->showIndicators === false) {
return ''; return '';
} }
$indicators = []; $indicators = [];
for ($i = 0, $count = count($this->items); $i < $count; $i++) { for ($i = 0, $count = count($this->items); $i < $count; $i++) {
$options = ['data-target' => '#' . $this->options['id'], 'data-slide-to' => $i]; $options = [
'data' => [
'bs-target' => '#' . $this->options['id'],
'bs-slide-to' => $i
],
'type' => 'button'
];
if ($i === 0) { if ($i === 0) {
Html::addCssClass($options, ['activate' => 'active']); Html::addCssClass($options, ['activate' => 'active']);
$options['aria']['current'] = 'true';
} }
$indicators[] = Html::tag('li', '', $options); $indicators[] = Html::tag('button', '', $options);
} }
return Html::tag('ol', implode("\n", $indicators), ['class' => ['carousel-indicators']]); return Html::tag('div', implode("\n", $indicators), ['class' => ['carousel-indicators']]);
} }
/** /**
@ -129,7 +138,7 @@ class Carousel extends Widget
* @return string the rendering result * @return string the rendering result
* @throws InvalidConfigException * @throws InvalidConfigException
*/ */
public function renderItems() public function renderItems(): string
{ {
$items = []; $items = [];
for ($i = 0, $count = count($this->items); $i < $count; $i++) { for ($i = 0, $count = count($this->items); $i < $count; $i++) {
@ -145,8 +154,9 @@ class Carousel extends Widget
* @param int $index the item index as the first item should be set to `active` * @param int $index the item index as the first item should be set to `active`
* @return string the rendering result * @return string the rendering result
* @throws InvalidConfigException if the item is invalid * @throws InvalidConfigException if the item is invalid
* @throws \Exception
*/ */
public function renderItem($item, $index) public function renderItem($item, int $index): string
{ {
if (is_string($item)) { if (is_string($item)) {
$content = $item; $content = $item;
@ -181,15 +191,21 @@ class Carousel extends Widget
public function renderControls() public function renderControls()
{ {
if (isset($this->controls[0], $this->controls[1])) { if (isset($this->controls[0], $this->controls[1])) {
return Html::a($this->controls[0], '#' . $this->options['id'], [ return Html::button($this->controls[0], [
'class' => 'carousel-control-prev', 'class' => 'carousel-control-prev',
'data-slide' => 'prev', 'data' => [
'role' => 'button', 'bs-target' => '#' . $this->options['id'],
'bs-slide' => 'prev'
],
'type' => 'button',
]) . "\n" ]) . "\n"
. Html::a($this->controls[1], '#' . $this->options['id'], [ . Html::button($this->controls[1], [
'class' => 'carousel-control-next', 'class' => 'carousel-control-next',
'data-slide' => 'next', 'data' => [
'role' => 'button', 'bs-target' => '#' . $this->options['id'],
'bs-slide' => 'next'
],
'type' => 'button',
]); ]);
} elseif ($this->controls === false) { } elseif ($this->controls === false) {
return ''; return '';

View File

@ -97,7 +97,7 @@ class Dropdown extends Widget
foreach ($items as $item) { foreach ($items as $item) {
if (is_string($item)) { if (is_string($item)) {
$lines[] = ($item === '-') $lines[] = ($item === '-')
? Html::tag('div', '', ['class' => 'dropdown-divider']) ? Html::tag('hr', '', ['class' => 'dropdown-divider'])
: $item; : $item;
continue; continue;
} }
@ -120,6 +120,7 @@ class Dropdown extends Widget
ArrayHelper::setValue($linkOptions, 'aria-disabled', 'true'); ArrayHelper::setValue($linkOptions, 'aria-disabled', 'true');
Html::addCssClass($linkOptions, ['disable' => 'disabled']); Html::addCssClass($linkOptions, ['disable' => 'disabled']);
} elseif ($active) { } elseif ($active) {
ArrayHelper::setValue($linkOptions, 'aria-current', 'true');
Html::addCssClass($linkOptions, ['activate' => 'active']); Html::addCssClass($linkOptions, ['activate' => 'active']);
} }
@ -141,8 +142,7 @@ class Dropdown extends Widget
$lines[] = Html::beginTag('div', array_merge_recursive(['class' => ['dropdown'], 'aria-expanded' => 'false'], $itemOptions)); $lines[] = Html::beginTag('div', array_merge_recursive(['class' => ['dropdown'], 'aria-expanded' => 'false'], $itemOptions));
$lines[] = Html::a($label, $url, array_merge([ $lines[] = Html::a($label, $url, array_merge([
'data-toggle' => 'dropdown', 'data-bs-toggle' => 'dropdown',
'aria-haspopup' => 'true',
'aria-expanded' => 'false', 'aria-expanded' => 'false',
'role' => 'button', 'role' => 'button',
], $linkOptions)); ], $linkOptions));

View File

@ -102,12 +102,12 @@ class LinkPager extends Widget
* @var string|bool the label for the "next" page button. Note that this will NOT be HTML-encoded. * @var string|bool the label for the "next" page button. Note that this will NOT be HTML-encoded.
* If this property is false, the "next" page button will not be displayed. * If this property is false, the "next" page button will not be displayed.
*/ */
public $nextPageLabel = "<span aria-hidden=\"true\">&raquo;</span>\n<span class=\"sr-only\">Next</span>"; public $nextPageLabel = '<span aria-hidden="true">&raquo;</span';
/** /**
* @var string|bool the text label for the "previous" page button. Note that this will NOT be HTML-encoded. * @var string|bool the text label for the "previous" page button. Note that this will NOT be HTML-encoded.
* If this property is false, the "previous" page button will not be displayed. * If this property is false, the "previous" page button will not be displayed.
*/ */
public $prevPageLabel = "<span aria-hidden=\"true\">&laquo;</span>\n<span class=\"sr-only\">Previous</span>"; public $prevPageLabel = '<span aria-hidden="true">&laquo;</span>';
/** /**
* @var string|bool the text label for the "first" page button. Note that this will NOT be HTML-encoded. * @var string|bool the text label for the "first" page button. Note that this will NOT be HTML-encoded.
* If it's specified as true, page number will be used as label. * If it's specified as true, page number will be used as label.
@ -285,6 +285,7 @@ class LinkPager extends Widget
$linkOptions['data-page'] = $page; $linkOptions['data-page'] = $page;
if ($active) { if ($active) {
$options['aria'] = ['current' => 'true'];
Html::addCssClass($options, $this->activePageCssClass); Html::addCssClass($options, $this->activePageCssClass);
} }
if ($disabled) { if ($disabled) {

View File

@ -51,35 +51,35 @@ class Modal extends Widget
/** /**
* @var string the tile content in the modal window. * @var string the tile content in the modal window.
*/ */
public $title; public string $title;
/** /**
* @var array additional title options * @var array additional title options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/ */
public $titleOptions = []; public array $titleOptions = [];
/** /**
* @var array additional header options * @var array additional header options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/ */
public $headerOptions = []; public array $headerOptions = [];
/** /**
* @var array body options * @var array body options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/ */
public $bodyOptions = []; public array $bodyOptions = [];
/** /**
* @var string the footer content in the modal window. * @var string|null the footer content in the modal window.
*/ */
public $footer; public ?string $footer;
/** /**
* @var array additional footer options * @var array additional footer options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/ */
public $footerOptions = []; public array $footerOptions = [];
/** /**
* @var string the modal size. Can be [[SIZE_LARGE]] or [[SIZE_SMALL]], or empty for default. * @var string|null the modal size. Can be [[SIZE_LARGE]] or [[SIZE_SMALL]], or empty for default.
*/ */
public $size; public ?string $size;
/** /**
* @var array|false the options for rendering the close button tag. * @var array|false the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking * The close button is displayed in the header of the modal window. Clicking
@ -116,24 +116,25 @@ class Modal extends Widget
* When true the modal-dialog-centered class will be added to the modal-dialog * When true the modal-dialog-centered class will be added to the modal-dialog
* @since 2.0.9 * @since 2.0.9
*/ */
public $centerVertical = false; public bool $centerVertical = false;
/** /**
* @var boolean whether to make the modal body scrollable * @var boolean whether to make the modal body scrollable
* *
* When true the modal-dialog-scrollable class will be added to the modal-dialog * When true the modal-dialog-scrollable class will be added to the modal-dialog
* @since 2.0.9 * @since 2.0.9
*/ */
public $scrollable = false; public bool $scrollable = false;
/** /**
* @var array modal dialog options * @var array modal dialog options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
* @since 2.0.9 * @since 2.0.9
*/ */
public $dialogOptions = []; public array $dialogOptions = [];
/** /**
* Initializes the widget. * {@inheritDoc}
* @throws \yii\base\InvalidConfigException
*/ */
public function init() public function init()
{ {
@ -167,10 +168,10 @@ class Modal extends Widget
* Renders the header HTML markup of the modal * Renders the header HTML markup of the modal
* @return string the rendering result * @return string the rendering result
*/ */
protected function renderHeader() protected function renderHeader(): string
{ {
$button = $this->renderCloseButton(); $button = $this->renderCloseButton();
if ($this->title !== null) { if (isset($this->title)) {
Html::addCssClass($this->titleOptions, ['widget' => 'modal-title']); Html::addCssClass($this->titleOptions, ['widget' => 'modal-title']);
$header = Html::tag('h5', $this->title, $this->titleOptions); $header = Html::tag('h5', $this->title, $this->titleOptions);
} else { } else {
@ -190,7 +191,7 @@ class Modal extends Widget
* Renders the opening tag of the modal body. * Renders the opening tag of the modal body.
* @return string the rendering result * @return string the rendering result
*/ */
protected function renderBodyBegin() protected function renderBodyBegin(): string
{ {
Html::addCssClass($this->bodyOptions, ['widget' => 'modal-body']); Html::addCssClass($this->bodyOptions, ['widget' => 'modal-body']);
return Html::beginTag('div', $this->bodyOptions); return Html::beginTag('div', $this->bodyOptions);
@ -200,7 +201,7 @@ class Modal extends Widget
* Renders the closing tag of the modal body. * Renders the closing tag of the modal body.
* @return string the rendering result * @return string the rendering result
*/ */
protected function renderBodyEnd() protected function renderBodyEnd(): string
{ {
return Html::endTag('div'); return Html::endTag('div');
} }
@ -209,9 +210,9 @@ class Modal extends Widget
* Renders the HTML markup for the footer of the modal * Renders the HTML markup for the footer of the modal
* @return string the rendering result * @return string the rendering result
*/ */
protected function renderFooter() protected function renderFooter(): ?string
{ {
if ($this->footer !== null) { if (isset($this->footer)) {
Html::addCssClass($this->footerOptions, ['widget' => 'modal-footer']); Html::addCssClass($this->footerOptions, ['widget' => 'modal-footer']);
return Html::tag('div', "\n" . $this->footer . "\n", $this->footerOptions); return Html::tag('div', "\n" . $this->footer . "\n", $this->footerOptions);
} else { } else {
@ -223,7 +224,7 @@ class Modal extends Widget
* Renders the toggle button. * Renders the toggle button.
* @return string the rendering result * @return string the rendering result
*/ */
protected function renderToggleButton() protected function renderToggleButton(): ?string
{ {
if (($toggleButton = $this->toggleButton) !== false) { if (($toggleButton = $this->toggleButton) !== false) {
$tag = ArrayHelper::remove($toggleButton, 'tag', 'button'); $tag = ArrayHelper::remove($toggleButton, 'tag', 'button');
@ -239,15 +240,12 @@ class Modal extends Widget
* Renders the close button. * Renders the close button.
* @return string the rendering result * @return string the rendering result
*/ */
protected function renderCloseButton() protected function renderCloseButton(): ?string
{ {
if (($closeButton = $this->closeButton) !== false) { if (($closeButton = $this->closeButton) !== false) {
$tag = ArrayHelper::remove($closeButton, 'tag', 'button'); $tag = ArrayHelper::remove($closeButton, 'tag', 'button');
$label = ArrayHelper::remove($closeButton, 'label', Html::tag('span', '&times;', [
'aria-hidden' => 'true',
]));
return Html::tag($tag, $label, $closeButton); return Html::tag($tag, '', $closeButton);
} else { } else {
return null; return null;
} }
@ -260,47 +258,43 @@ class Modal extends Widget
protected function initOptions() protected function initOptions()
{ {
$this->options = array_merge([ $this->options = array_merge([
'class' => 'fade',
'role' => 'dialog',
'tabindex' => -1, 'tabindex' => -1,
'aria-hidden' => 'true', 'aria-hidden' => 'true',
], $this->options); ], $this->options);
Html::addCssClass($this->options, ['widget' => 'modal']); Html::addCssClass($this->options, ['widget' => 'modal fade']);
if ($this->clientOptions !== false) { if (!empty($this->clientOptions)) {
$this->clientOptions = array_merge(['show' => false], $this->clientOptions); $this->clientOptions = array_merge(['show' => false], $this->clientOptions);
} }
$this->titleOptions = array_merge([ $this->titleOptions = array_merge([
'id' => $this->options['id'] . '-label', 'id' => $this->options['id'] . '-label',
], $this->titleOptions); ], $this->titleOptions);
if (!isset($this->options['aria-label'], $this->options['aria-labelledby']) && $this->title !== null) { if (!isset($this->options['aria-label'], $this->options['aria-labelledby']) && isset($this->title)) {
$this->options['aria-labelledby'] = $this->titleOptions['id']; $this->options['aria-labelledby'] = $this->titleOptions['id'];
} }
if ($this->closeButton !== false) { if ($this->closeButton !== false) {
$this->closeButton = array_merge([ $this->closeButton = array_merge([
'data-dismiss' => 'modal', 'data-bs-dismiss' => 'modal',
'class' => 'close', 'class' => 'btn-close',
'type' => 'button', 'type' => 'button',
'aria-label' => 'Close'
], $this->closeButton); ], $this->closeButton);
} }
if ($this->toggleButton !== false) { if ($this->toggleButton !== false) {
$this->toggleButton = array_merge([ $this->toggleButton = array_merge([
'data-toggle' => 'modal', 'data-bs-toggle' => 'modal',
'type' => 'button', 'type' => 'button',
], $this->toggleButton); ], $this->toggleButton);
if (!isset($this->toggleButton['data-target']) && !isset($this->toggleButton['href'])) { if (!isset($this->toggleButton['data-bs-target']) && !isset($this->toggleButton['href'])) {
$this->toggleButton['data-target'] = '#' . $this->options['id']; $this->toggleButton['data-bs-target'] = '#' . $this->options['id'];
} }
} }
$this->dialogOptions = array_merge([
'role' => 'document',
], $this->dialogOptions);
Html::addCssClass($this->dialogOptions, ['widget' => 'modal-dialog']); Html::addCssClass($this->dialogOptions, ['widget' => 'modal-dialog']);
if ($this->size) { if (isset($this->size)) {
Html::addCssClass($this->dialogOptions, ['size' => $this->size]); Html::addCssClass($this->dialogOptions, ['size' => $this->size]);
} }
if ($this->centerVertical) { if ($this->centerVertical) {

View File

@ -103,7 +103,7 @@ class Nav extends Widget
/** /**
* Initializes the widget. * {@inheritDoc}
*/ */
public function init() public function init()
{ {
@ -120,7 +120,7 @@ class Nav extends Widget
/** /**
* Renders the widget. * Renders the widget.
* @return string * @return string
* @throws InvalidConfigException * @throws InvalidConfigException|\Throwable
*/ */
public function run(): string public function run(): string
{ {
@ -131,7 +131,7 @@ class Nav extends Widget
/** /**
* Renders widget items. * Renders widget items.
* @return string * @return string
* @throws InvalidConfigException * @throws InvalidConfigException|\Throwable
*/ */
public function renderItems(): string public function renderItems(): string
{ {
@ -175,7 +175,9 @@ class Nav extends Widget
Html::addCssClass($options, ['widget' => 'nav-item']); Html::addCssClass($options, ['widget' => 'nav-item']);
Html::addCssClass($linkOptions, ['widget' => 'nav-link']); Html::addCssClass($linkOptions, ['widget' => 'nav-link']);
} else { } else {
$linkOptions['data-toggle'] = 'dropdown'; $linkOptions['data-bs-toggle'] = 'dropdown';
$linkOptions['role'] = 'button';
$linkOptions['aria-expanded'] = 'false';
Html::addCssClass($options, ['widget' => 'dropdown nav-item']); Html::addCssClass($options, ['widget' => 'dropdown nav-item']);
Html::addCssClass($linkOptions, ['widget' => 'dropdown-toggle nav-link']); Html::addCssClass($linkOptions, ['widget' => 'dropdown-toggle nav-link']);
if (is_array($items)) { if (is_array($items)) {
@ -220,7 +222,9 @@ class Nav extends Widget
* Check to see if a child item is active optionally activating the parent. * Check to see if a child item is active optionally activating the parent.
* @param array $items @see items * @param array $items @see items
* @param bool $active should the parent be active too * @param bool $active should the parent be active too
* @return array @see items * @return array
* @see items
* @throws \Exception
*/ */
protected function isChildActive(array $items, bool &$active): array protected function isChildActive(array $items, bool &$active): array
{ {
@ -256,6 +260,7 @@ class Nav extends Widget
* be considered active. * be considered active.
* @param array $item the menu item to be checked * @param array $item the menu item to be checked
* @return bool whether the menu item is active * @return bool whether the menu item is active
* @throws \Exception
*/ */
protected function isItemActive(array $item): bool protected function isItemActive(array $item): bool
{ {

View File

@ -84,7 +84,7 @@ class NavBar extends Widget
*/ */
public string $screenReaderToggleText = 'Toggle navigation'; public string $screenReaderToggleText = 'Toggle navigation';
/** /**
* @var string the toggle button content. Defaults to bootstrap 4 default `<span class="navbar-toggler-icon"></span>` * @var string the toggle button content. Defaults to bootstrap 5 default `<span class="navbar-toggler-icon"></span>`
*/ */
public string $togglerContent = '<span class="navbar-toggler-icon"></span>'; public string $togglerContent = '<span class="navbar-toggler-icon"></span>';
/** /**
@ -109,7 +109,7 @@ class NavBar extends Widget
/** /**
* Initializes the widget. * {@inheritDoc}
*/ */
public function init() public function init()
{ {
@ -176,29 +176,6 @@ class NavBar extends Widget
BootstrapPluginAsset::register($this->getView()); BootstrapPluginAsset::register($this->getView());
} }
/**
* Renders collapsible toggle button.
* @return string the rendering toggle button.
*/
protected function renderToggleButton(): string
{
$options = $this->togglerOptions;
Html::addCssClass($options, ['widget' => 'navbar-toggler']);
return Html::button(
$this->togglerContent,
ArrayHelper::merge($options, [
'type' => 'button',
'data' => [
'toggle' => 'collapse',
'target' => '#' . $this->collapseOptions['id'],
],
'aria-controls' => $this->collapseOptions['id'],
'aria-expanded' => 'false',
'aria-label' => $this->screenReaderToggleText,
])
);
}
/** /**
* Container options setter for backwards compatibility * Container options setter for backwards compatibility
* @param array $collapseOptions * @param array $collapseOptions
@ -208,4 +185,30 @@ class NavBar extends Widget
{ {
$this->collapseOptions = $collapseOptions; $this->collapseOptions = $collapseOptions;
} }
/**
* Renders collapsible toggle button.
* @return string the rendering toggle button.
*/
protected function renderToggleButton(): string
{
$options = $this->togglerOptions;
Html::addCssClass($options, ['widget' => 'navbar-toggler']);
return Html::button(
$this->togglerContent,
ArrayHelper::merge($options, [
'type' => 'button',
'data' => [
'bs-toggle' => 'collapse',
'bs-target' => '#' . $this->collapseOptions['id'],
],
'aria' => [
'controls' => $this->collapseOptions['id'],
'expanded' => 'false',
'label' => $this->screenReaderToggleText,
]
])
);
}
} }

View File

@ -80,17 +80,17 @@ class Progress extends Widget
/** /**
* @var string the button label. This property will only be considered if [[bars]] is empty * @var string the button label. This property will only be considered if [[bars]] is empty
*/ */
public $label; public string $label;
/** /**
* @var int the amount of progress as a percentage. This property will only be considered if [[bars]] is empty * @var int the amount of progress as a percentage. This property will only be considered if [[bars]] is empty
*/ */
public $percent = 0; public int $percent = 0;
/** /**
* @var array the HTML attributes of the bar. This property will only be considered if [[bars]] is empty * @var array the HTML attributes of the bar. This property will only be considered if [[bars]] is empty
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
* @since 2.0.6 * @since 2.0.6
*/ */
public $barOptions = []; public array $barOptions = [];
/** /**
* @var array a set of bars that are stacked together to form a single progress bar. * @var array a set of bars that are stacked together to form a single progress bar.
* Each bar is an array of the following structure: * Each bar is an array of the following structure:
@ -106,7 +106,7 @@ class Progress extends Widget
* ] * ]
* ``` * ```
*/ */
public $bars; public array $bars;
/** /**
@ -123,7 +123,7 @@ class Progress extends Widget
* {@inheritdoc} * {@inheritdoc}
* @throws InvalidConfigException * @throws InvalidConfigException
*/ */
public function run() public function run(): string
{ {
BootstrapAsset::register($this->getView()); BootstrapAsset::register($this->getView());
return $this->renderProgress(); return $this->renderProgress();
@ -133,8 +133,9 @@ class Progress extends Widget
* Renders the progress. * Renders the progress.
* @return string the rendering result. * @return string the rendering result.
* @throws InvalidConfigException if the "percent" option is not set in a stacked progress bar. * @throws InvalidConfigException if the "percent" option is not set in a stacked progress bar.
* @throws \Exception
*/ */
protected function renderProgress() protected function renderProgress(): string
{ {
$out = Html::beginTag('div', $this->options) . "\n"; $out = Html::beginTag('div', $this->options) . "\n";
if (empty($this->bars)) { if (empty($this->bars)) {
@ -164,14 +165,16 @@ class Progress extends Widget
* @param array $options the HTML attributes of the bar * @param array $options the HTML attributes of the bar
* @return string the rendering result. * @return string the rendering result.
*/ */
protected function renderBar($percent, $label = '', $options = []) protected function renderBar(int $percent, string $label = '', array $options = []): string
{ {
$percent = (float)trim(rtrim((string)$percent, '%')); $percent = (float)trim(rtrim((string)$percent, '%'));
$options = array_merge($options, [ $options = array_merge($options, [
'role' => 'progressbar', 'role' => 'progressbar',
'aria-valuenow' => $percent, 'aria' => [
'aria-valuemin' => 0, 'valuenow' => $percent,
'aria-valuemax' => 100, 'valuemin' => 0,
'valuemax' => 100,
]
]); ]);
Html::addCssClass($options, ['widget' => 'progress-bar']); Html::addCssClass($options, ['widget' => 'progress-bar']);
Html::addCssStyle($options, ['width' => $percent . '%'], true); Html::addCssStyle($options, ['width' => $percent . '%'], true);

View File

@ -165,6 +165,7 @@ class Tabs extends Widget
* @param array $items * @param array $items
* @param string $prefix * @param string $prefix
* @throws InvalidConfigException * @throws InvalidConfigException
* @throws \Exception
*/ */
protected function prepareItems(array &$items, string $prefix = '') protected function prepareItems(array &$items, string $prefix = '')
{ {
@ -196,9 +197,9 @@ class Tabs extends Widget
ArrayHelper::setValue($items[$n], 'url', '#' . $options['id']); ArrayHelper::setValue($items[$n], 'url', '#' . $options['id']);
ArrayHelper::setValue($items[$n], 'linkOptions.data.toggle', 'tab'); ArrayHelper::setValue($items[$n], 'linkOptions.data.toggle', 'tab');
ArrayHelper::setValue($items[$n], 'linkOptions.role', 'tab'); ArrayHelper::setValue($items[$n], 'linkOptions.role', 'tab');
ArrayHelper::setValue($items[$n], 'linkOptions.aria-controls', $options['id']); ArrayHelper::setValue($items[$n], 'linkOptions.aria.controls', $options['id']);
if (!$disabled) { if (!$disabled) {
ArrayHelper::setValue($items[$n], 'linkOptions.aria-selected', $selected ? 'true' : 'false'); ArrayHelper::setValue($items[$n], 'linkOptions.aria.selected', $selected ? 'true' : 'false');
} }
} else { } else {
continue; continue;
@ -236,6 +237,7 @@ class Tabs extends Widget
* *
* This method activates the first tab that is visible and * This method activates the first tab that is visible and
* not explicitly set to inactive (`'active' => false`). * not explicitly set to inactive (`'active' => false`).
* @throws \Exception
*/ */
protected function activateFirstVisibleTab() protected function activateFirstVisibleTab()
{ {

View File

@ -134,7 +134,7 @@ class Toast extends Widget
{ {
$button = $this->renderCloseButton(); $button = $this->renderCloseButton();
$tag = ArrayHelper::remove($this->titleOptions, 'tag', 'strong'); $tag = ArrayHelper::remove($this->titleOptions, 'tag', 'strong');
Html::addCssClass($this->titleOptions, ['widget' => 'mr-auto']); Html::addCssClass($this->titleOptions, ['widget' => 'me-auto']);
$title = Html::tag($tag, $this->title === null ? '' : $this->title, $this->titleOptions); $title = Html::tag($tag, $this->title === null ? '' : $this->title, $this->titleOptions);
if ($this->dateTime !== false) { if ($this->dateTime !== false) {
@ -175,11 +175,8 @@ class Toast extends Widget
protected function renderCloseButton(): string protected function renderCloseButton(): string
{ {
$tag = ArrayHelper::remove($this->closeButton, 'tag', 'button'); $tag = ArrayHelper::remove($this->closeButton, 'tag', 'button');
$label = ArrayHelper::remove($this->closeButton, 'label', Html::tag('span', '&times;', [
'aria-hidden' => 'true',
]));
return Html::tag($tag, "\n" . $label . "\n", $this->closeButton); return Html::tag($tag, '', $this->closeButton);
} }
/** /**
@ -192,8 +189,8 @@ class Toast extends Widget
$this->closeButton = array_merge([ $this->closeButton = array_merge([
'aria' => ['label' => 'Close'], 'aria' => ['label' => 'Close'],
'data' => ['dismiss' => 'toast'], 'data' => ['bs-dismiss' => 'toast'],
'class' => ['widget' => 'ml-2 mb-1 close'], 'class' => ['widget' => 'btn-close'],
'type' => 'button', 'type' => 'button',
], $this->closeButton); ], $this->closeButton);

View File

@ -68,8 +68,8 @@ class ToggleButtonGroup extends InputWidget
{ {
parent::init(); parent::init();
$this->registerPlugin('button'); $this->registerPlugin('button');
Html::addCssClass($this->options, ['widget' => 'btn-group-toggle']); Html::addCssClass($this->options, ['widget' => 'btn-group']);
$this->options['data-toggle'] = 'buttons'; $this->options['role'] = 'group';
} }
/** /**

View File

@ -71,41 +71,41 @@ class AccordionTest extends TestCase
$this->assertEqualsWithoutLE(<<<HTML $this->assertEqualsWithoutLE(<<<HTML
<div id="w0" class="accordion"> <div id="w0" class="accordion">
<div class="card"><div id="w0-collapse0-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w1" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse0" aria-expanded="true" aria-controls="w0-collapse0">Collapsible Group Item #1</button> <div class="accordion-item"><div id="w0-collapse0-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w1" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse0" aria-expanded="true" aria-controls="w0-collapse0">Collapsible Group Item #1</button>
</h5></div> </h5></div>
<div id="w0-collapse0" class="collapse show" aria-labelledby="w0-collapse0-heading" data-parent="#w0"> <div id="w0-collapse0" class="collapse show" aria-labelledby="w0-collapse0-heading" data-bs-parent="#w0">
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item">test content1</li> <li class="list-group-item">test content1</li>
<li class="list-group-item">test content2</li> <li class="list-group-item">test content2</li>
</ul> </ul>
</div></div> </div></div>
<div id="testId" class="testClass card"><div id="w0-collapse1-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w2" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse1" aria-expanded="false" aria-controls="w0-collapse1">Collapsible Group Item #2</button> <div id="testId" class="testClass accordion-item"><div id="w0-collapse1-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w2" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse1" aria-expanded="false" aria-controls="w0-collapse1">Collapsible Group Item #2</button>
</h5></div> </h5></div>
<div id="w0-collapse1" class="testContentOptions collapse" aria-labelledby="w0-collapse1-heading" data-parent="#w0"> <div id="w0-collapse1" class="testContentOptions collapse" aria-labelledby="w0-collapse1-heading" data-bs-parent="#w0">
<div class="card-body">Das ist das Haus vom Nikolaus</div> <div class="accordion-body">Das ist das Haus vom Nikolaus</div>
<div class="card-footer">Footer</div> <div class="accordion-footer">Footer</div>
</div></div> </div></div>
<div id="testId2" class="testClass2 card"><div id="w0-collapse2-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w3" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse2" aria-expanded="false" aria-controls="w0-collapse2"><h1>Collapsible Group Item #3</h1></button> <div id="testId2" class="testClass2 accordion-item"><div id="w0-collapse2-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w3" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse2" aria-expanded="false" aria-controls="w0-collapse2"><h1>Collapsible Group Item #3</h1></button>
</h5></div> </h5></div>
<div id="w0-collapse2" class="testContentOptions2 collapse" aria-labelledby="w0-collapse2-heading" data-parent="#w0"> <div id="w0-collapse2" class="testContentOptions2 collapse" aria-labelledby="w0-collapse2-heading" data-bs-parent="#w0">
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item"><h2>test content1</h2></li> <li class="list-group-item"><h2>test content1</h2></li>
<li class="list-group-item"><h2>test content2</h2></li> <li class="list-group-item"><h2>test content2</h2></li>
</ul> </ul>
<div class="card-footer">Footer2</div> <div class="accordion-footer">Footer2</div>
</div></div> </div></div>
<div id="testId3" class="testClass3 card"><div id="w0-collapse3-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w4" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse3" aria-expanded="false" aria-controls="w0-collapse3">&lt;h1&gt;Collapsible Group Item #4&lt;/h1&gt;</button> <div id="testId3" class="testClass3 accordion-item"><div id="w0-collapse3-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w4" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse3" aria-expanded="false" aria-controls="w0-collapse3">&lt;h1&gt;Collapsible Group Item #4&lt;/h1&gt;</button>
</h5></div> </h5></div>
<div id="w0-collapse3" class="testContentOptions3 collapse" aria-labelledby="w0-collapse3-heading" data-parent="#w0"> <div id="w0-collapse3" class="testContentOptions3 collapse" aria-labelledby="w0-collapse3-heading" data-bs-parent="#w0">
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item"><h2>test content1</h2></li> <li class="list-group-item"><h2>test content1</h2></li>
<li class="list-group-item"><h2>test content2</h2></li> <li class="list-group-item"><h2>test content2</h2></li>
</ul> </ul>
<div class="card-footer">Footer3</div> <div class="accordion-footer">Footer3</div>
</div></div> </div></div>
</div> </div>
@ -137,28 +137,28 @@ HTML
$this->assertEqualsWithoutLE(<<<HTML $this->assertEqualsWithoutLE(<<<HTML
<div id="w0" class="accordion"> <div id="w0" class="accordion">
<div class="card"><div id="w0-collapse0-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w1" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse0" aria-expanded="true" aria-controls="w0-collapse0">Item1</button> <div class="accordion-item"><div id="w0-collapse0-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w1" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse0" aria-expanded="true" aria-controls="w0-collapse0">Item1</button>
</h5></div> </h5></div>
<div id="w0-collapse0" class="collapse show" aria-labelledby="w0-collapse0-heading" data-parent="#w0"> <div id="w0-collapse0" class="collapse show" aria-labelledby="w0-collapse0-heading" data-bs-parent="#w0">
<div class="card-body">Content1</div> <div class="accordion-body">Content1</div>
</div></div> </div></div>
<div class="card"><div id="w0-collapse1-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w2" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse1" aria-expanded="false" aria-controls="w0-collapse1">Item2</button> <div class="accordion-item"><div id="w0-collapse1-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w2" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse1" aria-expanded="false" aria-controls="w0-collapse1">Item2</button>
</h5></div> </h5></div>
<div id="w0-collapse1" class="collapse" aria-labelledby="w0-collapse1-heading" data-parent="#w0"> <div id="w0-collapse1" class="collapse" aria-labelledby="w0-collapse1-heading" data-bs-parent="#w0">
<div class="card-body">Content2</div> <div class="accordion-body">Content2</div>
</div></div> </div></div>
<div class="card"><div id="w0-collapse2-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w3" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse2" aria-expanded="false" aria-controls="w0-collapse2">Item3</button> <div class="accordion-item"><div id="w0-collapse2-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w3" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse2" aria-expanded="false" aria-controls="w0-collapse2">Item3</button>
</h5></div> </h5></div>
<div id="w0-collapse2" class="collapse" aria-labelledby="w0-collapse2-heading" data-parent="#w0"> <div id="w0-collapse2" class="collapse" aria-labelledby="w0-collapse2-heading" data-bs-parent="#w0">
<div class="card-body">Content3</div> <div class="accordion-body">Content3</div>
</div></div> </div></div>
<div class="card"><div id="w0-collapse3-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w4" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse3" aria-expanded="false" aria-controls="w0-collapse3">FormField</button> <div class="accordion-item"><div id="w0-collapse3-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w4" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse3" aria-expanded="false" aria-controls="w0-collapse3">FormField</button>
</h5></div> </h5></div>
<div id="w0-collapse3" class="collapse" aria-labelledby="w0-collapse3-heading" data-parent="#w0"> <div id="w0-collapse3" class="collapse" aria-labelledby="w0-collapse3-heading" data-bs-parent="#w0">
<div class="card-body"><div class="form-group field-dynamicmodel-test"> <div class="accordion-body"><div class="form-group field-dynamicmodel-test">
<input type="text" id="dynamicmodel-test" class="form-control" name="DynamicModel[test]"> <input type="text" id="dynamicmodel-test" class="form-control" name="DynamicModel[test]">
</div></div> </div></div>
@ -184,16 +184,16 @@ HTML
$this->assertEqualsWithoutLE(<<<HTML $this->assertEqualsWithoutLE(<<<HTML
<div id="w0" class="accordion"> <div id="w0" class="accordion">
<div class="card"><div id="w0-collapse0-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w1" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse0" aria-expanded="false" aria-controls="w0-collapse0">Item1</button> <div class="accordion-item"><div id="w0-collapse0-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w1" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse0" aria-expanded="false" aria-controls="w0-collapse0">Item1</button>
</h5></div> </h5></div>
<div id="w0-collapse0" class="collapse" aria-labelledby="w0-collapse0-heading" data-parent="#w0"> <div id="w0-collapse0" class="collapse" aria-labelledby="w0-collapse0-heading" data-bs-parent="#w0">
<div class="card-body">Content1</div> <div class="accordion-body">Content1</div>
</div></div> </div></div>
<div class="card"><div id="w0-collapse1-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w2" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse1" aria-expanded="true" aria-controls="w0-collapse1">Item2</button> <div class="accordion-item"><div id="w0-collapse1-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w2" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse1" aria-expanded="true" aria-controls="w0-collapse1">Item2</button>
</h5></div> </h5></div>
<div id="w0-collapse1" class="collapse show" aria-labelledby="w0-collapse1-heading" data-parent="#w0"> <div id="w0-collapse1" class="collapse show" aria-labelledby="w0-collapse1-heading" data-bs-parent="#w0">
<div class="card-body">Content2</div> <div class="accordion-body">Content2</div>
</div></div> </div></div>
</div> </div>
@ -246,10 +246,10 @@ HTML
$this->assertEqualsWithoutLE(<<<HTML $this->assertEqualsWithoutLE(<<<HTML
<div id="w0" class="accordion"> <div id="w0" class="accordion">
<div class="card"><div id="w0-collapse0-heading" class="card-header"><h5 class="mb-0"><button type="button" id="w1" class="btn-link btn" data-toggle="collapse" data-target="#w0-collapse0" aria-expanded="true" aria-controls="w0-collapse0">Collapsible Group Item #1</button> <div class="accordion-item"><div id="w0-collapse0-heading" class="accordion-header"><h5 class="mb-0"><button type="button" id="w1" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#w0-collapse0" aria-expanded="true" aria-controls="w0-collapse0">Collapsible Group Item #1</button>
</h5></div> </h5></div>
<div id="w0-collapse0" class="collapse show" aria-labelledby="w0-collapse0-heading" data-parent="#w0"> <div id="w0-collapse0" class="collapse show" aria-labelledby="w0-collapse0-heading" data-bs-parent="#w0">
<div class="card-body"><div class="form-group field-singer-firstname"> <div class="accordion-body"><div class="form-group field-singer-firstname">
<input type="text" id="singer-firstname" class="form-control" name="Singer[firstName]"> <input type="text" id="singer-firstname" class="form-control" name="Singer[firstName]">
</div></div> </div></div>
@ -276,12 +276,12 @@ HTML
$output = Accordion::widget([ $output = Accordion::widget([
'items' => $items 'items' => $items
]); ]);
$this->assertContains('data-parent="', $output); $this->assertContains('data-bs-parent="', $output);
$output = Accordion::widget([ $output = Accordion::widget([
'autoCloseItems' => false, 'autoCloseItems' => false,
'items' => $items 'items' => $items
]); ]);
$this->assertNotContains('data-parent="', $output); $this->assertNotContains('data-bs-parent="', $output);
} }
/** /**

View File

@ -85,7 +85,7 @@ class ActiveFieldDefaultFormCheckTest extends TestCase
$html = $this->_activeField->checkbox()->render(); $html = $this->_activeField->checkbox()->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<div class="form-check"> <div class="form-check">
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="checkbox" id="dynamicmodel-attributename" class="form-check-input" name="DynamicModel[attributeName]" value="1"> <input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="checkbox" id="dynamicmodel-attributename" class="form-check-input" name="DynamicModel[attributeName]" value="1">
<label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label> <label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label>
@ -104,7 +104,7 @@ HTML;
$html = $this->_activeField->radio()->render(); $html = $this->_activeField->radio()->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<div class="form-check"> <div class="form-check">
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="radio" id="dynamicmodel-attributename" class="form-check-input" name="DynamicModel[attributeName]" value="1"> <input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="radio" id="dynamicmodel-attributename" class="form-check-input" name="DynamicModel[attributeName]" value="1">
<label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label> <label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label>
@ -122,8 +122,8 @@ HTML;
$html = $this->_activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render(); $html = $this->_activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label>Attribute Name</label> <label class="form-label">Attribute Name</label>
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename"><div class="form-check"> <input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename"><div class="form-check">
<input type="checkbox" id="i0" class="form-check-input" name="DynamicModel[attributeName][]" value="1"> <input type="checkbox" id="i0" class="form-check-input" name="DynamicModel[attributeName][]" value="1">
<label class="form-check-label" for="i0">name1</label> <label class="form-check-label" for="i0">name1</label>
@ -147,8 +147,8 @@ HTML;
$html = $this->_activeField->radioList([1 => 'name1', 2 => 'name2'])->render(); $html = $this->_activeField->radioList([1 => 'name1', 2 => 'name2'])->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label>Attribute Name</label> <label class="form-label">Attribute Name</label>
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" role="radiogroup"><div class="form-check"> <input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" role="radiogroup"><div class="form-check">
<input type="radio" id="i0" class="form-check-input" name="DynamicModel[attributeName]" value="1"> <input type="radio" id="i0" class="form-check-input" name="DynamicModel[attributeName]" value="1">
<label class="form-check-label" for="i0">name1</label> <label class="form-check-label" for="i0">name1</label>
@ -187,7 +187,7 @@ HTML;
$out = ob_get_clean(); $out = ob_get_clean();
$expected = <<<HTML $expected = <<<HTML
<div class="form-group row field-dynamicmodel-attributename"> <div class="mb-3 row field-dynamicmodel-attributename">
<label class="col-sm-2 col-form-label" for="dynamicmodel-attributename">Attribute Name</label> <label class="col-sm-2 col-form-label" for="dynamicmodel-attributename">Attribute Name</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]"> <input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]">
@ -197,7 +197,7 @@ HTML;
</div> </div>
HTML; HTML;
$expected2 = <<<HTML $expected2 = <<<HTML
<div class="form-group row field-dynamicmodel-checkbox"> <div class="mb-3 row field-dynamicmodel-checkbox">
<div class="col-sm-10 offset-sm-2"> <div class="col-sm-10 offset-sm-2">
<div class="form-check"> <div class="form-check">
<input type="hidden" name="DynamicModel[checkbox]" value="0"><input type="checkbox" id="dynamicmodel-checkbox" class="form-check-input" name="DynamicModel[checkbox]" value="1"> <input type="hidden" name="DynamicModel[checkbox]" value="0"><input type="checkbox" id="dynamicmodel-checkbox" class="form-check-input" name="DynamicModel[checkbox]" value="1">
@ -209,7 +209,7 @@ HTML;
</div> </div>
HTML; HTML;
$expected3 = <<<HTML $expected3 = <<<HTML
<div class="form-group row field-dynamicmodel-gridradios"> <div class="mb-3 row field-dynamicmodel-gridradios">
<label class="col-sm-2 col-form-label">Grid Radios</label> <label class="col-sm-2 col-form-label">Grid Radios</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="hidden" name="DynamicModel[gridRadios]" value=""><div id="dynamicmodel-gridradios" role="radiogroup"><div class="form-check"> <input type="hidden" name="DynamicModel[gridRadios]" value=""><div id="dynamicmodel-gridradios" role="radiogroup"><div class="form-check">

View File

@ -51,9 +51,9 @@ class ActiveFieldTest extends TestCase
$html = $this->activeField->fileInput()->render(); $html = $this->activeField->fileInput()->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label for="dynamicmodel-attributename">Attribute Name</label> <label class="form-label" for="dynamicmodel-attributename">Attribute Name</label>
<input type="hidden" name="DynamicModel[attributeName]" value=""><input type="file" id="dynamicmodel-attributename" class="form-control-file" name="DynamicModel[attributeName]"> <input type="hidden" name="DynamicModel[attributeName]" value=""><input type="file" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]">
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
</div> </div>
@ -70,16 +70,16 @@ HTML;
$html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render(); $html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label>Attribute Name</label> <label class="form-label">Attribute Name</label>
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" role="radiogroup"><div class="custom-control custom-radio"> <input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" role="radiogroup"><div class="form-check">
<input type="radio" id="i0" class="custom-control-input" name="DynamicModel[attributeName]" value="1"> <input type="radio" id="i0" class="form-check-input" name="DynamicModel[attributeName]" value="1">
<label class="custom-control-label" for="i0">name1</label> <label class="form-check-label" for="i0">name1</label>
</div> </div>
<div class="custom-control custom-radio"> <div class="form-check">
<input type="radio" id="i1" class="custom-control-input" name="DynamicModel[attributeName]" value="2"> <input type="radio" id="i1" class="form-check-input" name="DynamicModel[attributeName]" value="2">
<label class="custom-control-label" for="i1">name2</label> <label class="form-check-label" for="i1">name2</label>
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
</div> </div>
</div> </div>
@ -96,10 +96,10 @@ HTML;
$html = $this->activeField->radio()->render(); $html = $this->activeField->radio()->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<div class="custom-control custom-radio"> <div class="form-check">
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="radio" id="dynamicmodel-attributename" class="custom-control-input is-invalid" name="DynamicModel[attributeName]" value="1" aria-invalid="true"> <input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="radio" id="dynamicmodel-attributename" class="form-check-input is-invalid" name="DynamicModel[attributeName]" value="1" aria-invalid="true">
<label class="custom-control-label" for="dynamicmodel-attributename">Attribute Name</label> <label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label>
<div class="invalid-feedback">Test print error message</div> <div class="invalid-feedback">Test print error message</div>
</div> </div>
@ -115,16 +115,16 @@ HTML;
$html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render(); $html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label>Attribute Name</label> <label class="form-label">Attribute Name</label>
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" class="is-invalid" role="radiogroup" aria-invalid="true"><div class="custom-control custom-radio"> <input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" class="is-invalid" role="radiogroup" aria-invalid="true"><div class="form-check">
<input type="radio" id="i0" class="custom-control-input" name="DynamicModel[attributeName]" value="1"> <input type="radio" id="i0" class="form-check-input" name="DynamicModel[attributeName]" value="1">
<label class="custom-control-label" for="i0">name1</label> <label class="form-check-label" for="i0">name1</label>
</div> </div>
<div class="custom-control custom-radio"> <div class="form-check">
<input type="radio" id="i1" class="custom-control-input" name="DynamicModel[attributeName]" value="2"> <input type="radio" id="i1" class="form-check-input" name="DynamicModel[attributeName]" value="2">
<label class="custom-control-label" for="i1">name2</label> <label class="form-check-label" for="i1">name2</label>
<div class="invalid-feedback">Test print error message</div> <div class="invalid-feedback">Test print error message</div>
</div> </div>
</div> </div>
@ -140,16 +140,16 @@ HTML;
$html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render(); $html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label>Attribute Name</label> <label class="form-label">Attribute Name</label>
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename"><div class="custom-control custom-checkbox"> <input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename"><div class="form-check">
<input type="checkbox" id="i0" class="custom-control-input" name="DynamicModel[attributeName][]" value="1"> <input type="checkbox" id="i0" class="form-check-input" name="DynamicModel[attributeName][]" value="1">
<label class="custom-control-label" for="i0">name1</label> <label class="form-check-label" for="i0">name1</label>
</div> </div>
<div class="custom-control custom-checkbox"> <div class="form-check">
<input type="checkbox" id="i1" class="custom-control-input" name="DynamicModel[attributeName][]" value="2"> <input type="checkbox" id="i1" class="form-check-input" name="DynamicModel[attributeName][]" value="2">
<label class="custom-control-label" for="i1">name2</label> <label class="form-check-label" for="i1">name2</label>
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
</div> </div>
</div> </div>
@ -166,10 +166,10 @@ HTML;
$html = $this->activeField->checkbox()->render(); $html = $this->activeField->checkbox()->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<div class="custom-control custom-checkbox"> <div class="form-check">
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="checkbox" id="dynamicmodel-attributename" class="custom-control-input is-invalid" name="DynamicModel[attributeName]" value="1" aria-invalid="true"> <input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="checkbox" id="dynamicmodel-attributename" class="form-check-input is-invalid" name="DynamicModel[attributeName]" value="1" aria-invalid="true">
<label class="custom-control-label" for="dynamicmodel-attributename">Attribute Name</label> <label class="form-check-label" for="dynamicmodel-attributename">Attribute Name</label>
<div class="invalid-feedback">Test print error message</div> <div class="invalid-feedback">Test print error message</div>
</div> </div>
@ -185,16 +185,16 @@ HTML;
$html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render(); $html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label>Attribute Name</label> <label class="form-label">Attribute Name</label>
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" class="is-invalid" aria-invalid="true"><div class="custom-control custom-checkbox"> <input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" class="is-invalid" aria-invalid="true"><div class="form-check">
<input type="checkbox" id="i0" class="custom-control-input" name="DynamicModel[attributeName][]" value="1"> <input type="checkbox" id="i0" class="form-check-input" name="DynamicModel[attributeName][]" value="1">
<label class="custom-control-label" for="i0">name1</label> <label class="form-check-label" for="i0">name1</label>
</div> </div>
<div class="custom-control custom-checkbox"> <div class="form-check">
<input type="checkbox" id="i1" class="custom-control-input" name="DynamicModel[attributeName][]" value="2"> <input type="checkbox" id="i1" class="form-check-input" name="DynamicModel[attributeName][]" value="2">
<label class="custom-control-label" for="i1">name2</label> <label class="form-check-label" for="i1">name2</label>
<div class="invalid-feedback">Test print error message</div> <div class="invalid-feedback">Test print error message</div>
</div> </div>
</div> </div>
@ -211,16 +211,16 @@ HTML;
$html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render(); $html = $this->activeField->radioList([1 => 'name1', 2 => 'name2'])->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label>Attribute Name</label> <label class="form-label">Attribute Name</label>
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" role="radiogroup"><div class="custom-control custom-radio custom-control-inline"> <input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename" role="radiogroup"><div class="form-check">
<input type="radio" id="i0" class="custom-control-input" name="DynamicModel[attributeName]" value="1"> <input type="radio" id="i0" class="form-check-input" name="DynamicModel[attributeName]" value="1">
<label class="custom-control-label" for="i0">name1</label> <label class="form-check-label" for="i0">name1</label>
</div> </div>
<div class="custom-control custom-radio custom-control-inline"> <div class="form-check">
<input type="radio" id="i1" class="custom-control-input" name="DynamicModel[attributeName]" value="2"> <input type="radio" id="i1" class="form-check-input" name="DynamicModel[attributeName]" value="2">
<label class="custom-control-label" for="i1">name2</label> <label class="form-check-label" for="i1">name2</label>
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
</div> </div>
</div> </div>
@ -237,16 +237,16 @@ HTML;
$html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render(); $html = $this->activeField->checkboxList([1 => 'name1', 2 => 'name2'])->render();
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label>Attribute Name</label> <label class="form-label">Attribute Name</label>
<input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename"><div class="custom-control custom-checkbox custom-control-inline"> <input type="hidden" name="DynamicModel[attributeName]" value=""><div id="dynamicmodel-attributename"><div class="form-check">
<input type="checkbox" id="i0" class="custom-control-input" name="DynamicModel[attributeName][]" value="1"> <input type="checkbox" id="i0" class="form-check-input" name="DynamicModel[attributeName][]" value="1">
<label class="custom-control-label" for="i0">name1</label> <label class="form-check-label" for="i0">name1</label>
</div> </div>
<div class="custom-control custom-checkbox custom-control-inline"> <div class="form-check">
<input type="checkbox" id="i1" class="custom-control-input" name="DynamicModel[attributeName][]" value="2"> <input type="checkbox" id="i1" class="form-check-input" name="DynamicModel[attributeName][]" value="2">
<label class="custom-control-label" for="i1">name2</label> <label class="form-check-label" for="i1">name2</label>
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
</div> </div>
</div> </div>
@ -289,48 +289,4 @@ HTML;
$this->assertContains('data-attribute="test"', $content); $this->assertContains('data-attribute="test"', $content);
} }
/**
*
*/
public function testCustomRadio()
{
Html::$counter = 0;
$this->activeField->inline = true;
$html = $this->activeField->radio()->render();
$expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename">
<div class="custom-control custom-radio">
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="radio" id="dynamicmodel-attributename" class="custom-control-input" name="DynamicModel[attributeName]" value="1">
<label class="custom-control-label" for="dynamicmodel-attributename">Attribute Name</label>
<div class="invalid-feedback"></div>
</div>
</div>
HTML;
$this->assertEqualsWithoutLE($expectedHtml, $html);
}
/**
*
*/
public function testCustomCheckbox()
{
Html::$counter = 0;
$this->activeField->inline = true;
$html = $this->activeField->checkbox()->render();
$expectedHtml = <<<HTML
<div class="form-group field-dynamicmodel-attributename">
<div class="custom-control custom-checkbox">
<input type="hidden" name="DynamicModel[attributeName]" value="0"><input type="checkbox" id="dynamicmodel-attributename" class="custom-control-input" name="DynamicModel[attributeName]" value="1">
<label class="custom-control-label" for="dynamicmodel-attributename">Attribute Name</label>
<div class="invalid-feedback"></div>
</div>
</div>
HTML;
$this->assertEqualsWithoutLE($expectedHtml, $html);
}
} }

View File

@ -38,8 +38,8 @@ class ActiveFormTest extends TestCase
$out = ob_get_clean(); $out = ob_get_clean();
$expected = <<<HTML $expected = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label for="dynamicmodel-attributename">Attribute Name</label> <label class="form-label" for="dynamicmodel-attributename">Attribute Name</label>
<input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]"> <input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]">
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
@ -71,7 +71,7 @@ HTML;
$out = ob_get_clean(); $out = ob_get_clean();
$expected = <<<HTML $expected = <<<HTML
<div class="form-group row field-dynamicmodel-attributename"> <div class="mb-3 row field-dynamicmodel-attributename">
<label class="col-sm-2 col-form-label" for="dynamicmodel-attributename">Attribute Name</label> <label class="col-sm-2 col-form-label" for="dynamicmodel-attributename">Attribute Name</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]"> <input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]">
@ -81,11 +81,11 @@ HTML;
</div> </div>
HTML; HTML;
$expected2 = <<<HTML $expected2 = <<<HTML
<div class="form-group row field-dynamicmodel-checkbox"> <div class="mb-3 row field-dynamicmodel-checkbox">
<div class="col-sm-10 offset-sm-2"> <div class="col-sm-10 offset-sm-2">
<div class="custom-control custom-checkbox"> <div class="form-check">
<input type="hidden" name="DynamicModel[checkbox]" value="0"><input type="checkbox" id="dynamicmodel-checkbox" class="custom-control-input" name="DynamicModel[checkbox]" value="1"> <input type="hidden" name="DynamicModel[checkbox]" value="0"><input type="checkbox" id="dynamicmodel-checkbox" class="form-check-input" name="DynamicModel[checkbox]" value="1">
<label class="custom-control-label" for="dynamicmodel-checkbox">Checkbox</label> <label class="form-check-label" for="dynamicmodel-checkbox">Checkbox</label>
<div class="invalid-feedback "></div> <div class="invalid-feedback "></div>
</div> </div>
@ -93,22 +93,22 @@ HTML;
</div> </div>
HTML; HTML;
$expected3 = <<<HTML $expected3 = <<<HTML
<div class="form-group row field-dynamicmodel-gridradios"> <div class="mb-3 row field-dynamicmodel-gridradios">
<label class="col-sm-2 col-form-label">Grid Radios</label> <label class="col-sm-2 col-form-label">Grid Radios</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="hidden" name="DynamicModel[gridRadios]" value=""><div id="dynamicmodel-gridradios" role="radiogroup"><div class="custom-control custom-radio"> <input type="hidden" name="DynamicModel[gridRadios]" value=""><div id="dynamicmodel-gridradios" role="radiogroup"><div class="form-check">
<input type="radio" id="i0" class="custom-control-input" name="DynamicModel[gridRadios]" value="option1"> <input type="radio" id="i0" class="form-check-input" name="DynamicModel[gridRadios]" value="option1">
<label class="custom-control-label" for="i0">First radio</label> <label class="form-check-label" for="i0">First radio</label>
</div> </div>
<div class="custom-control custom-radio"> <div class="form-check">
<input type="radio" id="i1" class="custom-control-input" name="DynamicModel[gridRadios]" value="option2"> <input type="radio" id="i1" class="form-check-input" name="DynamicModel[gridRadios]" value="option2">
<label class="custom-control-label" for="i1">Second radio</label> <label class="form-check-label" for="i1">Second radio</label>
</div> </div>
<div class="custom-control custom-radio"> <div class="form-check">
<input type="radio" id="i2" class="custom-control-input" name="DynamicModel[gridRadios]" value="option3"> <input type="radio" id="i2" class="form-check-input" name="DynamicModel[gridRadios]" value="option3">
<label class="custom-control-label" for="i2">Third radio</label> <label class="form-check-label" for="i2">Third radio</label>
<div class="invalid-feedback "></div> <div class="invalid-feedback "></div>
</div> </div>
</div> </div>
@ -135,14 +135,14 @@ HTML;
'action' => '/some-action', 'action' => '/some-action',
'layout' => ActiveForm::LAYOUT_HORIZONTAL 'layout' => ActiveForm::LAYOUT_HORIZONTAL
]); ]);
echo $form->field($model, 'checkboxName')->checkbox(['template' => "<div class=\"offset-lg-1 col-lg-3\">\n{input}\n{label}\n</div>\n<div class=\"col-lg-8\">{error}</div>"]); echo $form->field($model, 'checkboxName')->checkbox(['template' => "<div class=\"form-check offset-lg-1 col-lg-3\">\n{input}\n{label}\n</div>\n<div class=\"col-lg-8\">{error}</div>"]);
ActiveForm::end(); ActiveForm::end();
$out = ob_get_clean(); $out = ob_get_clean();
$expected = <<<HTML $expected = <<<HTML
<div class="offset-lg-1 col-lg-3"> <div class="form-check offset-lg-1 col-lg-3">
<input type="hidden" name="DynamicModel[checkboxName]" value="0"><input type="checkbox" id="dynamicmodel-checkboxname" class="custom-control-input" name="DynamicModel[checkboxName]" value="1"> <input type="hidden" name="DynamicModel[checkboxName]" value="0"><input type="checkbox" id="dynamicmodel-checkboxname" class="form-check-input" name="DynamicModel[checkboxName]" value="1">
<label class="custom-control-label" for="dynamicmodel-checkboxname">Checkbox Name</label> <label class="form-check-label" for="dynamicmodel-checkboxname">Checkbox Name</label>
</div> </div>
<div class="col-lg-8"><div class="invalid-feedback "></div></div> <div class="col-lg-8"><div class="invalid-feedback "></div></div>
HTML; HTML;
@ -171,16 +171,16 @@ HTML;
$out = ob_get_clean(); $out = ob_get_clean();
$expected = <<<HTML $expected = <<<HTML
<div class="form-group field-dynamicmodel-attributename"> <div class="mb-3 field-dynamicmodel-attributename">
<label class="sr-only" for="dynamicmodel-attributename">Attribute Name</label> <label class="form-label visually-hidden" for="dynamicmodel-attributename">Attribute Name</label>
<input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]" placeholder="Attribute Name"> <input type="text" id="dynamicmodel-attributename" class="form-control" name="DynamicModel[attributeName]" placeholder="Attribute Name">
</div> </div>
HTML; HTML;
$expected2 = <<<HTML $expected2 = <<<HTML
<div class="form-group field-dynamicmodel-selectname"> <div class="mb-3 field-dynamicmodel-selectname">
<label for="dynamicmodel-selectname">Select Name</label> <label class="form-label" for="dynamicmodel-selectname">Select Name</label>
<input type="hidden" name="DynamicModel[selectName]" value=""><select id="dynamicmodel-selectname" class="form-control" name="DynamicModel[selectName]" size="4" placeholder> <input type="hidden" name="DynamicModel[selectName]" value=""><select id="dynamicmodel-selectname" class="form-control" name="DynamicModel[selectName]" size="4" placeholder>
<option value="1">One</option> <option value="1">One</option>
<option value="2">Two</option> <option value="2">Two</option>
@ -191,10 +191,10 @@ HTML;
</div> </div>
HTML; HTML;
$expected3 = <<<HTML $expected3 = <<<HTML
<div class="form-group field-dynamicmodel-checkboxname"> <div class="mb-3 field-dynamicmodel-checkboxname">
<div class="custom-control custom-checkbox"> <div class="form-check">
<input type="hidden" name="DynamicModel[checkboxName]" value="0"><input type="checkbox" id="dynamicmodel-checkboxname" class="custom-control-input" name="DynamicModel[checkboxName]" value="1"> <input type="hidden" name="DynamicModel[checkboxName]" value="0"><input type="checkbox" id="dynamicmodel-checkboxname" class="form-check-input" name="DynamicModel[checkboxName]" value="1">
<label class="sr-only custom-control-label" for="dynamicmodel-checkboxname">Checkbox Name</label> <label class="visually-hidden form-check-label" for="dynamicmodel-checkboxname">Checkbox Name</label>
</div> </div>
@ -225,32 +225,32 @@ HTML;
$out = ob_get_clean(); $out = ob_get_clean();
$expected = <<<HTML $expected = <<<HTML
<div class="form-group field-user-firstname"> <div class="mb-3 field-user-firstname">
<label for="user-firstname">First Name</label> <label class="form-label" for="user-firstname">First Name</label>
<input type="text" id="user-firstname" class="form-control" name="User[firstName]"> <input type="text" id="user-firstname" class="form-control" name="User[firstName]">
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
</div> </div>
HTML; HTML;
$expected2 = <<<HTML $expected2 = <<<HTML
<div class="form-group field-user-lastname"> <div class="mb-3 field-user-lastname">
<label for="user-lastname">Last Name</label> <label class="form-label" for="user-lastname">Last Name</label>
<input type="text" id="user-lastname" class="form-control" name="User[lastName]"> <input type="text" id="user-lastname" class="form-control" name="User[lastName]">
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
</div> </div>
HTML; HTML;
$expected3 = <<<HTML $expected3 = <<<HTML
<div class="form-group field-user-username required"> <div class="mb-3 field-user-username required">
<label for="user-username">Username</label> <label class="form-label" for="user-username">Username</label>
<input type="text" id="user-username" class="form-control" name="User[username]" aria-required="true"> <input type="text" id="user-username" class="form-control" name="User[username]" aria-required="true">
<small class="form-text text-muted">Your username must be at least 4 characters long</small> <small class="form-text text-muted">Your username must be at least 4 characters long</small>
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
</div> </div>
HTML; HTML;
$expected4 = <<<HTML $expected4 = <<<HTML
<div class="form-group field-user-password required"> <div class="mb-3 field-user-password required">
<label for="user-password">Password</label> <label class="form-label" for="user-password">Password</label>
<input type="password" id="user-password" class="form-control" name="User[password]" aria-required="true"> <input type="password" id="user-password" class="form-control" name="User[password]" aria-required="true">
<small class="form-text text-muted">Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.</small> <small class="form-text text-muted">Your password must be 8-20 characters long, contain letters and numbers, and must not contain spaces, special characters, or emoji.</small>
<div class="invalid-feedback"></div> <div class="invalid-feedback"></div>
@ -280,8 +280,8 @@ HTML;
$out = ob_get_clean(); $out = ob_get_clean();
$expected = <<<HTML $expected = <<<HTML
<div class="form-group field-user-username required"> <div class="mb-3 field-user-username required">
<label for="user-username">Username</label> <label class="form-label" for="user-username">Username</label>
<input type="text" id="user-username" class="form-control is-invalid" name="User[username]" aria-required="true" aria-invalid="true"> <input type="text" id="user-username" class="form-control is-invalid" name="User[username]" aria-required="true" aria-invalid="true">
<small class="form-text text-muted">Your username must be at least 4 characters long</small> <small class="form-text text-muted">Your username must be at least 4 characters long</small>
<div class="invalid-feedback">Username cannot be blank.</div> <div class="invalid-feedback">Username cannot be blank.</div>

View File

@ -25,7 +25,7 @@ class AlertTest extends TestCase
<div id="w0" class="alert-warning alert alert-dismissible" role="alert"> <div id="w0" class="alert-warning alert alert-dismissible" role="alert">
<strong>Holy guacamole!</strong> You should check in on some of those fields below. <strong>Holy guacamole!</strong> You should check in on some of those fields below.
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span></button> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div> </div>
HTML; HTML;
@ -47,7 +47,7 @@ HTML;
<div id="w0" class="alert alert-dismissible" role="alert"> <div id="w0" class="alert alert-dismissible" role="alert">
Message1 Message1
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span></button> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div> </div>
HTML; HTML;

View File

@ -46,7 +46,7 @@ class ButtonDropdownTest extends TestCase
]); ]);
$expected = <<<EXPECTED $expected = <<<EXPECTED
<div id="w0" class="dropleft btn-group"><button id="w0-button" class="btn dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Action</button> <div id="w0" class="dropleft btn-group"><button id="w0-button" class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Action</button>
<div id="w1" class="dropdown-menu"><a class="dropdown-item" href="#">ItemA</a> <div id="w1" class="dropdown-menu"><a class="dropdown-item" href="#">ItemA</a>
<a class="dropdown-item" href="#">ItemB</a></div></div> <a class="dropdown-item" href="#">ItemB</a></div></div>
@ -72,7 +72,7 @@ EXPECTED;
$expected = <<<EXPECTED $expected = <<<EXPECTED
<div id="w0" class="dropdown btn-group"><button id="w1" class="btn">Split dropdown</button> <div id="w0" class="dropdown btn-group"><button id="w1" class="btn">Split dropdown</button>
<button id="w0-button" class="btn dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="sr-only">Toggle Dropdown</span></button> <button id="w0-button" class="btn dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"><span class="visually-hidden">Toggle Dropdown</span></button>
<div id="w2" class="dropdown-menu"><a class="dropdown-item" href="#">ItemA</a> <div id="w2" class="dropdown-menu"><a class="dropdown-item" href="#">ItemA</a>
<a class="dropdown-item" href="#">ItemB</a></div></div> <a class="dropdown-item" href="#">ItemB</a></div></div>
EXPECTED; EXPECTED;

View File

@ -40,17 +40,17 @@ class CarouselTest extends TestCase
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="carousel slide" data-bs-ride="carousel"> <div id="w0" class="carousel slide" data-bs-ride="carousel">
<ol class="carousel-indicators"><li class="active" data-target="#w0" data-slide-to="0"></li> <div class="carousel-indicators"><button type="button" class="active" data-bs-target="#w0" data-bs-slide-to="0" aria-current="true"></button>
<li data-target="#w0" data-slide-to="1"></li> <button type="button" data-bs-target="#w0" data-bs-slide-to="1"></button>
<li data-target="#w0" data-slide-to="2"></li></ol> <button type="button" data-bs-target="#w0" data-bs-slide-to="2"></button></div>
<div class="carousel-inner"><div class="carousel-item active"><img src="https://via.placeholder.com/800x400?text=First+slide" class="d-block w-100"> <div class="carousel-inner"><div class="carousel-item active"><img src="https://via.placeholder.com/800x400?text=First+slide" class="d-block w-100">
<div class="d-none d-md-block carousel-caption"><h5>First slide label</h5><p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p></div></div> <div class="d-none d-md-block carousel-caption"><h5>First slide label</h5><p>Nulla vitae elit libero, a pharetra augue mollis interdum.</p></div></div>
<div class="carousel-item"><img src="https://via.placeholder.com/800x400?text=Second+slide" class="d-block w-100"> <div class="carousel-item"><img src="https://via.placeholder.com/800x400?text=Second+slide" class="d-block w-100">
<div class="d-none d-md-block carousel-caption"><h5>Second slide label</h5><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p></div></div> <div class="d-none d-md-block carousel-caption"><h5>Second slide label</h5><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p></div></div>
<div class="carousel-item"><img src="https://via.placeholder.com/800x400?text=Third+slide" class="d-block w-100"> <div class="carousel-item"><img src="https://via.placeholder.com/800x400?text=Third+slide" class="d-block w-100">
<div class="d-none d-md-block carousel-caption"><h5>Third slide label</h5><p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p></div></div></div> <div class="d-none d-md-block carousel-caption"><h5>Third slide label</h5><p>Praesent commodo cursus magna, vel scelerisque nisl consectetur.</p></div></div></div>
<a class="carousel-control-prev" href="#w0" data-slide="prev" role="button"><span class="carousel-control-prev-icon" aria-hidden="true"></span><span class="visually-hidden">Previous</span></a> <button type="button" class="carousel-control-prev" data-bs-target="#w0" data-bs-slide="prev"><span class="carousel-control-prev-icon" aria-hidden="true"></span><span class="visually-hidden">Previous</span></button>
<a class="carousel-control-next" href="#w0" data-slide="next" role="button"><span class="carousel-control-next-icon" aria-hidden="true"></span><span class="visually-hidden">Next</span></a> <button type="button" class="carousel-control-next" data-bs-target="#w0" data-bs-slide="next"><span class="carousel-control-next-icon" aria-hidden="true"></span><span class="visually-hidden">Next</span></button>
</div> </div>
HTML; HTML;

View File

@ -42,7 +42,7 @@ class DropdownTest extends TestCase
$expected = <<<EXPECTED $expected = <<<EXPECTED
<div id="w0" class="dropdown-menu"><h6 class="dropdown-header">Page1</h6> <div id="w0" class="dropdown-menu"><h6 class="dropdown-header">Page1</h6>
<div class="dropdown" aria-expanded="false"> <div class="dropdown" aria-expanded="false">
<a class="dropdown-item dropdown-toggle" href="#test" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="button">Dropdown1</a> <a class="dropdown-item dropdown-toggle" href="#test" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown1</a>
<div id="w1" class="dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page2</h6> <div id="w1" class="dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page2</h6>
<h6 class="dropdown-header">Page3</h6></div> <h6 class="dropdown-header">Page3</h6></div>
</div></div> </div></div>
@ -84,13 +84,13 @@ EXPECTED;
$expected = <<<EXPECTED $expected = <<<EXPECTED
<div id="w0" class="dropdown-menu"><div class="dropdown" aria-expanded="false"> <div id="w0" class="dropdown-menu"><div class="dropdown" aria-expanded="false">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="button">Dropdown1</a> <a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown1</a>
<div id="w1" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page1</h6> <div id="w1" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page1</h6>
<h6 class="dropdown-header">Page2</h6></div> <h6 class="dropdown-header">Page2</h6></div>
</div> </div>
<div class="dropdown-divider"></div> <hr class="dropdown-divider">
<div class="dropdown" aria-expanded="false"> <div class="dropdown" aria-expanded="false">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="button">Dropdown2</a> <a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown2</a>
<div id="w2" class="submenu-override dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page3</h6> <div id="w2" class="submenu-override dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page3</h6>
<h6 class="dropdown-header">Page4</h6></div> <h6 class="dropdown-header">Page4</h6></div>
</div></div> </div></div>
@ -128,14 +128,14 @@ EXPECTED;
); );
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="dropdown-menu"><div class="dropdown" aria-expanded="false"> <div id="w0" class="dropdown-menu"><div class="dropdown" aria-expanded="false">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="button">Dropdown1</a> <a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown1</a>
<div id="w1" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page1</h6> <div id="w1" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page1</h6>
<h6 class="dropdown-header">Page2</h6></div> <h6 class="dropdown-header">Page2</h6></div>
</div> </div>
<div class="dropdown-divider"></div> <hr class="dropdown-divider">
<div class="dropdown" aria-expanded="false"> <div class="dropdown" aria-expanded="false">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="button">Dropdown2</a> <a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown2</a>
<div id="w2" class="submenu-list dropdown-submenu dropdown-menu"><a class="dropdown-item active" href="/">Page3</a> <div id="w2" class="submenu-list dropdown-submenu dropdown-menu"><a class="dropdown-item active" href="/" aria-current="true">Page3</a>
<h6 class="dropdown-header">Page4</h6></div> <h6 class="dropdown-header">Page4</h6></div>
</div></div> </div></div>
HTML; HTML;
@ -173,13 +173,13 @@ HTML;
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="dropdown-menu"><div class="dropdown" aria-expanded="false"> <div id="w0" class="dropdown-menu"><div class="dropdown" aria-expanded="false">
<a class="dropdown-item disabled dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="button" tabindex="-1" aria-disabled="true">Dropdown1</a> <a class="dropdown-item disabled dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button" tabindex="-1" aria-disabled="true">Dropdown1</a>
<div id="w1" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page1</h6> <div id="w1" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page1</h6>
<h6 class="dropdown-header">Page2</h6></div> <h6 class="dropdown-header">Page2</h6></div>
</div> </div>
<div class="dropdown-divider"></div> <hr class="dropdown-divider">
<div class="dropdown" aria-expanded="false"> <div class="dropdown" aria-expanded="false">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="button">Dropdown2</a> <a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Dropdown2</a>
<div id="w2" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page3</h6> <div id="w2" class="submenu-list dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page3</h6>
<h6 class="dropdown-header">Page4</h6></div> <h6 class="dropdown-header">Page4</h6></div>
</div></div> </div></div>
@ -193,12 +193,12 @@ HTML;
Dropdown::$counter = 0; Dropdown::$counter = 0;
$form = <<<HTML $form = <<<HTML
<form class="px-4 py-3"> <form class="px-4 py-3">
<div class="form-group"> <div class="mb-3">
<label for="exampleDropdownFormEmail1">Email address</label> <label class="form-label" for="exampleDropdownFormEmail1">Email address</label>
<input type="email" class="form-control" id="exampleDropdownFormEmail1" placeholder="email@example.com"> <input type="email" class="form-control" id="exampleDropdownFormEmail1" placeholder="email@example.com">
</div> </div>
<div class="form-group"> <div class="mb-3">
<label for="exampleDropdownFormPassword1">Password</label> <label class="form-label" for="exampleDropdownFormPassword1">Password</label>
<input type="password" class="form-control" id="exampleDropdownFormPassword1" placeholder="Password"> <input type="password" class="form-control" id="exampleDropdownFormPassword1" placeholder="Password">
</div> </div>
<div class="form-check"> <div class="form-check">
@ -222,12 +222,12 @@ HTML;
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="dropdown-menu"><form class="px-4 py-3"> <div id="w0" class="dropdown-menu"><form class="px-4 py-3">
<div class="form-group"> <div class="mb-3">
<label for="exampleDropdownFormEmail1">Email address</label> <label class="form-label" for="exampleDropdownFormEmail1">Email address</label>
<input type="email" class="form-control" id="exampleDropdownFormEmail1" placeholder="email@example.com"> <input type="email" class="form-control" id="exampleDropdownFormEmail1" placeholder="email@example.com">
</div> </div>
<div class="form-group"> <div class="mb-3">
<label for="exampleDropdownFormPassword1">Password</label> <label class="form-label" for="exampleDropdownFormPassword1">Password</label>
<input type="password" class="form-control" id="exampleDropdownFormPassword1" placeholder="Password"> <input type="password" class="form-control" id="exampleDropdownFormPassword1" placeholder="Password">
</div> </div>
<div class="form-check"> <div class="form-check">
@ -238,7 +238,7 @@ Remember me
</div> </div>
<button type="submit" class="btn btn-primary">Sign in</button> <button type="submit" class="btn btn-primary">Sign in</button>
</form> </form>
<div class="dropdown-divider"></div> <hr class="dropdown-divider">
<a class="dropdown-item" href="#">New around here? Sign up</a> <a class="dropdown-item" href="#">New around here? Sign up</a>
<a class="dropdown-item" href="#">Forgot password?</a></div> <a class="dropdown-item" href="#">Forgot password?</a></div>
HTML; HTML;

View File

@ -97,12 +97,12 @@ class LinkPagerTest extends TestCase
'pagination' => $pagination, 'pagination' => $pagination,
'disableCurrentPageButton' => false, 'disableCurrentPageButton' => false,
]); ]);
$this->assertContains('<li class="page-item active"><a class="page-link" href="/?r=test&amp;page=6" data-page="5">6</a></li>', $output); $this->assertContains('<li class="page-item active" aria-current="true"><a class="page-link" href="/?r=test&amp;page=6" data-page="5">6</a></li>', $output);
$output = LinkPager::widget([ $output = LinkPager::widget([
'pagination' => $pagination, 'pagination' => $pagination,
'disableCurrentPageButton' => true, 'disableCurrentPageButton' => true,
]); ]);
$this->assertContains('<li class="page-item active disabled"><a class="page-link" href="/?r=test&amp;page=6" data-page="5" tabindex="-1">6</a></li>', $output); $this->assertContains('<li class="page-item active disabled" aria-current="true"><a class="page-link" href="/?r=test&amp;page=6" data-page="5" tabindex="-1">6</a></li>', $output);
} }
public function testOptionsWithTagOption() public function testOptionsWithTagOption()
@ -132,7 +132,7 @@ class LinkPagerTest extends TestCase
$output $output
); );
$this->assertContains( $this->assertContains(
'<div class="my-class page-item active"><a class="page-link" href="/?r=test&amp;page=2" data-page="1">2</a></div>', '<div class="my-class page-item active" aria-current="true"><a class="page-link" href="/?r=test&amp;page=2" data-page="1">2</a></div>',
$output $output
); );
} }

View File

@ -21,8 +21,8 @@ class ModalTest extends TestCase
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="fade modal" role="dialog" tabindex="-1" aria-hidden="true"> <div id="w0" class="modal fade" tabindex="-1" aria-hidden="true">
<div class="modal-dialog" role="document"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body test" style="text-align:center;"> <div class="modal-body test" style="text-align:center;">
@ -64,12 +64,12 @@ HTML;
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="fade modal" role="dialog" tabindex="-1" aria-hidden="true" aria-labelledby="w0-label"> <div id="w0" class="modal fade" tabindex="-1" aria-hidden="true" aria-labelledby="w0-label">
<div class="modal-dialog" role="document"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 id="w0-label" class="modal-title">Modal title</h5> <h5 id="w0-label" class="modal-title">Modal title</h5>
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>Woohoo, you're reading this text in a modal!</p> <p>Woohoo, you're reading this text in a modal!</p>
@ -109,8 +109,10 @@ HTML;
Modal::end(); Modal::end();
$out = ob_get_clean(); $out = ob_get_clean();
$this->assertContains('<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#w0">Launch demo modal</button>', $this->assertContains(
$out); '<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#w0">Launch demo modal</button>',
$out
);
} }
public function testDialogOptions() public function testDialogOptions()
@ -124,8 +126,8 @@ HTML;
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="fade modal" role="dialog" tabindex="-1" aria-hidden="true"> <div id="w0" class="modal fade" tabindex="-1" aria-hidden="true">
<div class="test modal-dialog" role="document" style="text-align:center;"> <div class="test modal-dialog" style="text-align:center;">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-body">
@ -151,8 +153,8 @@ HTML;
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="fade modal" role="dialog" tabindex="-1" aria-hidden="true"> <div id="w0" class="modal fade" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-body">
@ -166,6 +168,7 @@ HTML;
$this->assertEqualsWithoutLE($expected, $out); $this->assertEqualsWithoutLE($expected, $out);
} }
public function testScrollable() public function testScrollable()
{ {
Modal::$counter = 0; Modal::$counter = 0;
@ -177,8 +180,8 @@ HTML;
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="fade modal" role="dialog" tabindex="-1" aria-hidden="true"> <div id="w0" class="modal fade" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable" role="document"> <div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-body">

View File

@ -27,7 +27,7 @@ class NavBarTest extends TestCase
<nav id="w0" class="navbar-inverse navbar-static-top navbar-frontend navbar"> <nav id="w0" class="navbar-inverse navbar-static-top navbar-frontend navbar">
<div class="container"> <div class="container">
<a class="navbar-brand" href="/">My Company</a> <a class="navbar-brand" href="/">My Company</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#w0-collapse" aria-controls="w0-collapse" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button> <button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#w0-collapse" aria-controls="w0-collapse" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
<div id="w0-collapse" class="collapse navbar-collapse"> <div id="w0-collapse" class="collapse navbar-collapse">
</div> </div>
</div> </div>
@ -109,13 +109,13 @@ HTML;
<nav id="w0" class="navbar navbar-expand-lg navbar-light bg-light"> <nav id="w0" class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container"> <div class="container">
<a class="navbar-brand" href="/">My Company</a> <a class="navbar-brand" href="/">My Company</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#w0-collapse" aria-controls="w0-collapse" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button> <button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#w0-collapse" aria-controls="w0-collapse" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
<div id="w0-collapse" class="collapse navbar-collapse"> <div id="w0-collapse" class="collapse navbar-collapse">
<ul id="w1" class="mr-auto nav"><li class="nav-item"><a class="nav-link" href="#">Home</a></li> <ul id="w1" class="mr-auto nav"><li class="nav-item"><a class="nav-link" href="#">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#">Link</a></li> <li class="nav-item"><a class="nav-link" href="#">Link</a></li>
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-toggle="dropdown">Dropdown</a><div id="w2" class="dropdown-menu"><a class="dropdown-item" href="#">Action</a> <li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown</a><div id="w2" class="dropdown-menu"><a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a> <a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div> <hr class="dropdown-divider">
<a class="dropdown-item" href="#">Something else here</a></div></li></ul><form class="form-inline my-2 my-lg-0"> <a class="dropdown-item" href="#">Something else here</a></div></li></ul><form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"> <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>

View File

@ -61,7 +61,7 @@ class NavTest extends TestCase
$expected = <<<EXPECTED $expected = <<<EXPECTED
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Page1</a></li> <ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Page1</a></li>
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-toggle="dropdown">Dropdown1</a><div id="w1" class="dropdown-menu"><h6 class="dropdown-header">Page2</h6> <li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown1</a><div id="w1" class="dropdown-menu"><h6 class="dropdown-header">Page2</h6>
<h6 class="dropdown-header">Page3</h6></div></li></ul> <h6 class="dropdown-header">Page3</h6></div></li></ul>
EXPECTED; EXPECTED;
@ -100,7 +100,7 @@ EXPECTED;
$expected = <<<EXPECTED $expected = <<<EXPECTED
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Page1</a></li> <ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Page1</a></li>
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-toggle="dropdown">Dropdown1</a><div id="test1" class="test dropdown-menu" data-id="t1"><h6 class="dropdown-header">Page2</h6> <li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown1</a><div id="test1" class="test dropdown-menu" data-id="t1"><h6 class="dropdown-header">Page2</h6>
<h6 class="dropdown-header">Page3</h6></div></li></ul> <h6 class="dropdown-header">Page3</h6></div></li></ul>
EXPECTED; EXPECTED;
@ -132,7 +132,7 @@ EXPECTED;
$expected = <<<EXPECTED $expected = <<<EXPECTED
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Page1</a></li> <ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Page1</a></li>
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-toggle="dropdown">Dropdown1</a><div id="w1" class="dropdown-menu"><h6 class="dropdown-header">Page2</h6> <li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown1</a><div id="w1" class="dropdown-menu"><h6 class="dropdown-header">Page2</h6>
<h6 class="dropdown-header">Page3</h6></div></li> <h6 class="dropdown-header">Page3</h6></div></li>
<li class="nav-item"><a class="nav-link" href="#">Page4</a></li></ul> <li class="nav-item"><a class="nav-link" href="#">Page4</a></li></ul>
EXPECTED; EXPECTED;
@ -164,7 +164,7 @@ EXPECTED;
$expected = <<<EXPECTED $expected = <<<EXPECTED
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="/base/index.php?r=site%2Findex">Main</a></li> <ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="/base/index.php?r=site%2Findex">Main</a></li>
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-toggle="dropdown">Admin</a><div id="w1" class="dropdown-menu"><a class="dropdown-item active" href="/base/index.php?r=site%2Fusers">Users</a> <li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Admin</a><div id="w1" class="dropdown-menu"><a class="dropdown-item active" href="/base/index.php?r=site%2Fusers" aria-current="true">Users</a>
<a class="dropdown-item" href="/base/index.php?r=site%2Froles">Roles</a> <a class="dropdown-item" href="/base/index.php?r=site%2Froles">Roles</a>
<a class="dropdown-item" href="/base/index.php?r=site%2Fstatuses">Statuses</a></div></li></ul> <a class="dropdown-item" href="/base/index.php?r=site%2Fstatuses">Statuses</a></div></li></ul>
EXPECTED; EXPECTED;
@ -260,7 +260,7 @@ EXPECTED;
$expected = <<<EXPECTED $expected = <<<EXPECTED
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Item1</a></li> <ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Item1</a></li>
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-toggle="dropdown">Item2</a><div id="w1" class="dropdown-menu"><a class="dropdown-item" href="/base/index.php?r=site%2Findex">Page2</a> <li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Item2</a><div id="w1" class="dropdown-menu"><a class="dropdown-item" href="/base/index.php?r=site%2Findex">Page2</a>
<h6 class="dropdown-header">Page3</h6></div></li></ul> <h6 class="dropdown-header">Page3</h6></div></li></ul>
EXPECTED; EXPECTED;
@ -293,7 +293,7 @@ EXPECTED;
$expected = <<<EXPECTED $expected = <<<EXPECTED
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Item1</a></li> <ul id="w0" class="nav"><li class="nav-item"><a class="nav-link" href="#">Item1</a></li>
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-toggle="dropdown">Item2</a><div id="w1" class="dropdown-menu"><a class="dropdown-item active" href="/base/index.php?r=site%2Findex">Page2</a> <li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Item2</a><div id="w1" class="dropdown-menu"><a class="dropdown-item active" href="/base/index.php?r=site%2Findex" aria-current="true">Page2</a>
<h6 class="dropdown-header">Page3</h6></div></li></ul> <h6 class="dropdown-header">Page3</h6></div></li></ul>
EXPECTED; EXPECTED;
@ -324,7 +324,7 @@ EXPECTED;
$expected = <<<EXPECTED $expected = <<<EXPECTED
<ul id="w0" class="nav"><li class="nav-item"><a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Item1</a></li> <ul id="w0" class="nav"><li class="nav-item"><a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Item1</a></li>
<li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-toggle="dropdown">Item2</a><div id="w1" class="dropdown-menu"><a class="dropdown-item disabled" href="/base/index.php?r=site%2Findex" tabindex="-1" aria-disabled="true">Page2</a> <li class="dropdown nav-item"><a class="dropdown-toggle nav-link" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Item2</a><div id="w1" class="dropdown-menu"><a class="dropdown-item disabled" href="/base/index.php?r=site%2Findex" tabindex="-1" aria-disabled="true">Page2</a>
<h6 class="dropdown-header">Page3</h6></div></li></ul> <h6 class="dropdown-header">Page3</h6></div></li></ul>
EXPECTED; EXPECTED;
@ -357,8 +357,8 @@ EXPECTED;
]); ]);
$expected = <<<EXPECTED $expected = <<<EXPECTED
<ul id="w0" class="nav"><li class="dropdown nav-item"><a class="dropdown-toggle nav-link active" href="#" data-toggle="dropdown">Dropdown</a><div id="w1" class="dropdown-menu"><div class="dropdown active" aria-expanded="false"> <ul id="w0" class="nav"><li class="dropdown nav-item"><a class="dropdown-toggle nav-link active" href="#" data-bs-toggle="dropdown" role="button" aria-expanded="false">Dropdown</a><div id="w1" class="dropdown-menu"><div class="dropdown active" aria-expanded="false">
<a class="dropdown-item dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" role="button">Sub-dropdown</a> <a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" role="button">Sub-dropdown</a>
<div id="w2" class="dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page</h6></div> <div id="w2" class="dropdown-submenu dropdown-menu"><h6 class="dropdown-header">Page</h6></div>
</div></div></li></ul> </div></div></li></ul>
EXPECTED; EXPECTED;

View File

@ -19,10 +19,8 @@ class ToastTest extends TestCase
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true"> <div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"> <div class="toast-header">
<strong class="mr-auto"></strong> <strong class="me-auto"></strong>
<button type="button" class="ml-2 mb-1 close" aria-label="Close" data-dismiss="toast"> <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="toast"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="toast-body test" style="text-align: center;"> <div class="toast-body test" style="text-align: center;">
@ -53,11 +51,9 @@ HTML;
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true"> <div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"> <div class="toast-header">
<strong class="mr-auto">Toast title</strong> <strong class="me-auto">Toast title</strong>
<small class="text-muted">a minute ago</small> <small class="text-muted">a minute ago</small>
<button type="button" class="ml-2 mb-1 close" aria-label="Close" data-dismiss="toast"> <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="toast"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="toast-body"> <div class="toast-body">
Woohoo, you're reading this text in a toast! Woohoo, you're reading this text in a toast!
@ -81,11 +77,9 @@ HTML;
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true"> <div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"> <div class="toast-header">
<strong class="mr-auto">Toast title</strong> <strong class="me-auto">Toast title</strong>
<small class="toast-date-time text-muted" style="text-align: right;">a minute ago</small> <small class="toast-date-time text-muted" style="text-align: right;">a minute ago</small>
<button type="button" class="ml-2 mb-1 close" aria-label="Close" data-dismiss="toast"> <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="toast"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="toast-body"> <div class="toast-body">
@ -108,10 +102,8 @@ HTML;
$expected = <<<HTML $expected = <<<HTML
<div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true"> <div id="w0" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"> <div class="toast-header">
<h5 class="mr-auto" style="text-align: left;">Toast title</h5> <h5 class="me-auto" style="text-align: left;">Toast title</h5>
<button type="button" class="ml-2 mb-1 close" aria-label="Close" data-dismiss="toast"> <button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="toast"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="toast-body"> <div class="toast-body">

View File

@ -25,7 +25,7 @@ class ToggleButtonGroupTest extends TestCase
]); ]);
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<input type="hidden" name="ToggleButtonGroupTestModel[value]" value=""><div id="togglebuttongrouptestmodel-value" class="btn-group-toggle" data-toggle="buttons"><label class="btn btn-secondary" for="i0"><input type="checkbox" id="i0" name="ToggleButtonGroupTestModel[value][]" value="1" autocomplete="off">item 1</label> <input type="hidden" name="ToggleButtonGroupTestModel[value]" value=""><div id="togglebuttongrouptestmodel-value" class="btn-group" role="group"><label class="btn btn-secondary" for="i0"><input type="checkbox" id="i0" name="ToggleButtonGroupTestModel[value][]" value="1" autocomplete="off">item 1</label>
<label class="btn btn-secondary" for="i1"><input type="checkbox" id="i1" name="ToggleButtonGroupTestModel[value][]" value="2" autocomplete="off">item 2</label></div> <label class="btn btn-secondary" for="i1"><input type="checkbox" id="i1" name="ToggleButtonGroupTestModel[value][]" value="2" autocomplete="off">item 2</label></div>
HTML; HTML;
$this->assertEqualsWithoutLE($expectedHtml, $html); $this->assertEqualsWithoutLE($expectedHtml, $html);
@ -63,7 +63,7 @@ HTML;
]); ]);
$expectedHtml = <<<HTML $expectedHtml = <<<HTML
<input type="hidden" name="ToggleButtonGroupTestModel[value]" value=""><div id="togglebuttongrouptestmodel-value" class="btn-group-toggle" data-toggle="buttons"><label class="btn btn-secondary" for="i0"><input type="radio" id="i0" name="ToggleButtonGroupTestModel[value]" value="1" autocomplete="off">item 1</label> <input type="hidden" name="ToggleButtonGroupTestModel[value]" value=""><div id="togglebuttongrouptestmodel-value" class="btn-group" role="group"><label class="btn btn-secondary" for="i0"><input type="radio" id="i0" name="ToggleButtonGroupTestModel[value]" value="1" autocomplete="off">item 1</label>
<label class="btn btn-secondary" for="i1"><input type="radio" id="i1" name="ToggleButtonGroupTestModel[value]" value="2" autocomplete="off">item 2</label></div> <label class="btn btn-secondary" for="i1"><input type="radio" id="i1" name="ToggleButtonGroupTestModel[value]" value="2" autocomplete="off">item 2</label></div>
HTML; HTML;
$this->assertEqualsWithoutLE($expectedHtml, $html); $this->assertEqualsWithoutLE($expectedHtml, $html);