Update BootstrapWidgetTrait (#48)

* Update BootstrapWidgetTrait

Using pure JS instead Jquery
Optimize components activation : only 'popover', 'toast' and 'tooltip' not activates via data attributes
Fix outdated PHPDoc's
This commit is contained in:
Anton 2022-08-25 14:26:48 +03:00 committed by GitHub
parent fe254a7d1f
commit bd8ed65e7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 34 deletions

View File

@ -8,6 +8,7 @@ Yii Framework 2 bootstrap5 extension Change Log
- Enh #39: Add inline mode to `BaseHtml::checkboxList()` and `BaseHtml::radioList()` (WinterSilence)
- Enh #40: Breadcrumbs refactoring (WinterSilence)
- Bug #46: Fix data-attribute usage for Dropdown toggle (machour)
- Enh #48: Update `BootstrapWidgetTrait` to initialize JS plugins without jQuery (WinterSilence)
2.0.3 April 22, 2022

View File

@ -13,7 +13,7 @@ use yii\base\InvalidConfigException;
use yii\helpers\Json;
/**
* BootstrapWidgetTrait is the trait, which provides basic for all bootstrap widgets features.
* BootstrapWidgetTrait is the trait, which provides basic for all Bootstrap widgets features.
*
* Note: class, which uses this trait must declare public field named `options` with the array default value:
*
@ -35,22 +35,21 @@ use yii\helpers\Json;
trait BootstrapWidgetTrait
{
/**
* @var array|bool the options for the underlying Bootstrap JS plugin.
* Please refer to the corresponding Bootstrap plugin Web page for possible options.
* For example, [this page](http://getbootstrap.com/javascript/#modals) shows
* how to use the "Modal" plugin and the supported options (e.g. "remote").
* If this property is false, registerJs will not be called on the view to initialize the module.
* @var array|false the options for the underlying Bootstrap JS plugin/component.
* Please refer to the corresponding Bootstrap plugin/component Web page for possible options.
* For example, [this page](https://getbootstrap.com/docs/5.1/components/modal/#options) shows
* how to use the "Modal" component and the supported options (e.g. "backdrop").
* If this property is false, `registerJs()` will not be called on the view to initialize the module.
*/
public $clientOptions = [];
/**
* @var array the event handlers for the underlying Bootstrap JS plugin.
* Please refer to the corresponding Bootstrap plugin Web page for possible events.
* For example, [this page](http://getbootstrap.com/javascript/#modals) shows
* how to use the "Modal" plugin and the supported events (e.g. "shown").
* For example, [this page](https://getbootstrap.com/docs/5.1/components/modal/#events) shows
* how to use the "Modal" plugin and the supported events (e.g. "shown.bs.modal").
*/
public $clientEvents = [];
/**
* Initializes the widget.
* This method will register the bootstrap asset bundle. If you override this method,
@ -66,25 +65,47 @@ trait BootstrapWidgetTrait
}
/**
* Registers a specific Bootstrap plugin and the related events
* Registers a specific Bootstrap plugin/component and the related events.
*
* @param string $name the name of the Bootstrap plugin
*/
protected function registerPlugin(string $name)
{
/**
* @see https://github.com/twbs/bootstrap/blob/v5.2.0/js/index.esm.js
*/
$jsPlugins = [
'alert',
'button',
'carousel',
'collapse',
'dropdown',
'modal',
'offcanvas',
'popover',
'scrollspy',
'tab',
'toast',
'tooltip'
];
if (in_array($name, $jsPlugins, true)) {
$view = $this->getView();
BootstrapPluginAsset::register($view);
// 'popover', 'toast' and 'tooltip' plugins not activates via data attributes
if (
$this->clientOptions !== false
|| !empty($this->clientOptions)
|| in_array($name, ['popover', 'toast', 'tooltip'], true)
) {
$name = ucfirst($name);
$id = $this->options['id'];
if ($this->clientOptions !== false) {
$options = empty($this->clientOptions) ? '' : Json::htmlEncode($this->clientOptions);
$js = "jQuery('#$id').$name($options);";
$view->registerJs($js);
$options = empty($this->clientOptions) ? '{}' : Json::htmlEncode($this->clientOptions);
$view->registerJs("(new bootstrap.$name('#$id', $options));");
}
$this->registerClientEvents();
}
}
/**
* Registers JS event handlers that are listed in [[clientEvents]].
@ -95,7 +116,7 @@ trait BootstrapWidgetTrait
$id = $this->options['id'];
$js = [];
foreach ($this->clientEvents as $event => $handler) {
$js[] = "jQuery('#$id').on('$event', $handler);";
$js[] = "document.getElementById('$id').addEventListener('$event', $handler);";
}
$this->getView()->registerJs(implode("\n", $js));
}

View File

@ -39,7 +39,7 @@ HTML;
$this->assertInternalType(IsType::TYPE_ARRAY, $js);
$options = array_shift($js);
$this->assertContainsWithoutLE("jQuery('#w0').popover({", $options);
$this->assertContainsWithoutLE("(new bootstrap.Popover('#w0', {", $options);
$this->assertContainsWithoutLE("id=\u0022w0-popover\u0022", $options);
$this->assertContainsWithoutLE("class=\u0022test-header popover-header\u0022", $options);
$this->assertContainsWithoutLE('"placement":"bottom"', $options);

View File

@ -140,7 +140,7 @@ HTML;
$this->assertInternalType(IsType::TYPE_ARRAY, $js);
$options = array_shift($js);
$this->assertContainsWithoutLE("jQuery('#w0').toast();", $options);
$this->assertContainsWithoutLE("(new bootstrap.Toast('#w0', {}));", $options);
}
/**
@ -160,33 +160,29 @@ HTML;
$out = ob_get_clean();
$this->assertFalse($toast->clientOptions);
$this->assertArrayNotHasKey(View::POS_READY,Yii::$app->view->js);
$this->assertArrayHasKey(View::POS_READY, Yii::$app->view->js);
}
/**
*
* @see https://github.com/yiisoft/yii2-bootstrap5/issues/36
*/
public function testWidgetInitializationTrue()
public function testWidgetInitializationWithClientOptions()
{
Toast::$counter = 0;
ob_start();
$toast = Toast::begin([
'title' => 'Toast title',
'clientOptions' => true,
'clientOptions' => ['delay' => 1000],
'titleOptions' => ['tag' => 'h5', 'style' => ['text-align' => 'left']]
]);
echo 'test';
Toast::end();
$out = ob_get_clean();
$this->assertTrue($toast->clientOptions);
$this->assertArrayHasKey('delay', $toast->clientOptions);
$this->assertArrayHasKey(View::POS_READY, Yii::$app->view->js);
$js = Yii::$app->view->js[View::POS_READY];
$this->assertInternalType(IsType::TYPE_ARRAY, $js);
$options = array_shift($js);
$this->assertContainsWithoutLE("jQuery('#w0').toast(true);", $options);
$this->assertContainsWithoutLE("(new bootstrap.Toast('#w0', {\"delay\":1000}));", $options);
}
}