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 #39: Add inline mode to `BaseHtml::checkboxList()` and `BaseHtml::radioList()` (WinterSilence)
- Enh #40: Breadcrumbs refactoring (WinterSilence) - Enh #40: Breadcrumbs refactoring (WinterSilence)
- Bug #46: Fix data-attribute usage for Dropdown toggle (machour) - 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 2.0.3 April 22, 2022

View File

@ -13,7 +13,7 @@ use yii\base\InvalidConfigException;
use yii\helpers\Json; 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: * 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 trait BootstrapWidgetTrait
{ {
/** /**
* @var array|bool the options for the underlying Bootstrap JS plugin. * @var array|false the options for the underlying Bootstrap JS plugin/component.
* Please refer to the corresponding Bootstrap plugin Web page for possible options. * Please refer to the corresponding Bootstrap plugin/component Web page for possible options.
* For example, [this page](http://getbootstrap.com/javascript/#modals) shows * For example, [this page](https://getbootstrap.com/docs/5.1/components/modal/#options) shows
* how to use the "Modal" plugin and the supported options (e.g. "remote"). * 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. * If this property is false, `registerJs()` will not be called on the view to initialize the module.
*/ */
public $clientOptions = []; public $clientOptions = [];
/** /**
* @var array the event handlers for the underlying Bootstrap JS plugin. * @var array the event handlers for the underlying Bootstrap JS plugin.
* Please refer to the corresponding Bootstrap plugin Web page for possible events. * Please refer to the corresponding Bootstrap plugin Web page for possible events.
* For example, [this page](http://getbootstrap.com/javascript/#modals) shows * 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"). * how to use the "Modal" plugin and the supported events (e.g. "shown.bs.modal").
*/ */
public $clientEvents = []; public $clientEvents = [];
/** /**
* Initializes the widget. * Initializes the widget.
* This method will register the bootstrap asset bundle. If you override this method, * This method will register the bootstrap asset bundle. If you override this method,
@ -66,24 +65,46 @@ 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 * @param string $name the name of the Bootstrap plugin
*/ */
protected function registerPlugin(string $name) protected function registerPlugin(string $name)
{ {
$view = $this->getView(); /**
* @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'];
$options = empty($this->clientOptions) ? '{}' : Json::htmlEncode($this->clientOptions);
$view->registerJs("(new bootstrap.$name('#$id', $options));");
}
BootstrapPluginAsset::register($view); $this->registerClientEvents();
$id = $this->options['id'];
if ($this->clientOptions !== false) {
$options = empty($this->clientOptions) ? '' : Json::htmlEncode($this->clientOptions);
$js = "jQuery('#$id').$name($options);";
$view->registerJs($js);
} }
$this->registerClientEvents();
} }
/** /**
@ -95,7 +116,7 @@ trait BootstrapWidgetTrait
$id = $this->options['id']; $id = $this->options['id'];
$js = []; $js = [];
foreach ($this->clientEvents as $event => $handler) { 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)); $this->getView()->registerJs(implode("\n", $js));
} }

View File

@ -39,7 +39,7 @@ HTML;
$this->assertInternalType(IsType::TYPE_ARRAY, $js); $this->assertInternalType(IsType::TYPE_ARRAY, $js);
$options = array_shift($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("id=\u0022w0-popover\u0022", $options);
$this->assertContainsWithoutLE("class=\u0022test-header popover-header\u0022", $options); $this->assertContainsWithoutLE("class=\u0022test-header popover-header\u0022", $options);
$this->assertContainsWithoutLE('"placement":"bottom"', $options); $this->assertContainsWithoutLE('"placement":"bottom"', $options);

View File

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