| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- <?php
- namespace Dcat\Admin\Widgets;
- use Dcat\Admin\Admin;
- use Illuminate\Contracts\Support\Arrayable;
- use Illuminate\Contracts\Support\Renderable;
- use Illuminate\Support\Arr;
- use Illuminate\Support\Str;
- class Dropdown extends Widget
- {
- const DIVIDER = '_divider';
- /**
- * @var string
- */
- protected static $dividerHtml = '<li class="dropdown-divider"></li>';
- /**
- * @var string
- */
- protected $template = '<span class="dropdown" style="display:inline-block">%s<ul class="dropdown-menu">%s</ul></span>';
- /**
- * @var array
- */
- protected $button = [
- 'text' => null,
- 'class' => 'btn btn-sm btn-white waves-effect',
- 'style' => null,
- ];
- /**
- * @var string
- */
- protected $buttonId;
- /**
- * @var \Closure
- */
- protected $builder;
- /**
- * @var bool
- */
- protected $divider;
- /**
- * @var bool
- */
- protected $click = false;
- /**
- * @var array
- */
- protected $firstOptions = [];
- public function __construct(array $options = [])
- {
- $this->options($options);
- }
- /**
- * Set the options of dropdown menus.
- *
- * @param array $options
- * @param string|null $title
- *
- * @return $this
- */
- public function options($options = [], string $title = null)
- {
- if (! $options) {
- return $this;
- }
- if ($options instanceof Arrayable) {
- $options = $options->toArray();
- }
- $options = (array) $options;
- if (! $this->options) {
- $this->firstOptions = &$options;
- }
- $this->options[] = [$title, &$options];
- return $this;
- }
- /**
- * Set the button text.
- *
- * @param string|null $text
- *
- * @return $this
- */
- public function button(?string $text)
- {
- $this->button['text'] = $text;
- return $this;
- }
- /**
- * Without text of button.
- *
- * @return $this
- */
- public function withoutTextButton()
- {
- return $this->button('');
- }
- /**
- * Set the button class.
- *
- * @param string $class
- *
- * @return $this
- */
- public function buttonClass(string $class)
- {
- $this->button['class'] = $class;
- return $this;
- }
- /**
- * Set the button style.
- *
- * @param string $class
- *
- * @return $this
- */
- public function buttonStyle(string $style)
- {
- $this->button['style'] = $style;
- return $this;
- }
- /**
- * Show divider.
- *
- * @param string $class
- *
- * @return $this
- */
- public function divider()
- {
- $this->divider = true;
- return $this;
- }
- /**
- * Applies the callback to the elements of the options.
- *
- * @param string $class
- *
- * @return $this
- */
- public function map(\Closure $builder)
- {
- $this->builder = $builder;
- return $this;
- }
- /**
- * Add click event listener.
- *
- * @param string|null $defaultLabel
- *
- * @return $this
- */
- public function click(?string $defaultLabel = null)
- {
- $this->click = true;
- $this->buttonId = 'dropd_'.Str::random(8);
- if ($defaultLabel !== null) {
- $this->button($defaultLabel);
- }
- return $this;
- }
- /**
- * Set the template of dropdown menu.
- *
- * @param string|\Closure|Renderable $template
- *
- * @return $this
- */
- public function template($template)
- {
- $this->template = $this->toString($template);
- return $this;
- }
- /**
- * @return string
- */
- protected function renderButton()
- {
- if (is_null($this->button['text']) && ! $this->click) {
- return;
- }
- $text = $this->button['text'];
- $class = $this->button['class'];
- $style = $this->button['style'];
- if ($this->click && ! $text) {
- if (Arr::isAssoc($this->firstOptions)) {
- $text = array_keys($this->firstOptions)[0];
- } else {
- $text = $this->firstOptions[0] ?? '';
- }
- if (is_array($text)) {
- $text = $text['label'] ?? current($text);
- }
- }
- return str_replace(
- ['{id}', '{class}', '{style}', '{text}'],
- [
- $this->buttonId,
- $class,
- $style ? "style='$style'" : '',
- $text ? " $text " : '',
- ],
- <<<'HTML'
- <a id="{id}" class="{class} dropdown-toggle " data-toggle="dropdown" href="javascript:void(0)" {style}>
- <stub>{text}</stub>
- <span class="caret"></span>
- </a>
- HTML
- );
- }
- /**
- * @return string
- */
- public function getButtonId()
- {
- return $this->buttonId;
- }
- /**
- * @return string
- */
- protected function renderOptions()
- {
- $opt = '';
- foreach ($this->options as &$items) {
- [$title, $options] = $items;
- if ($title) {
- $opt .= "<li class='dropdown-header'>$title</li>";
- }
- foreach ($options as $key => $val) {
- $opt .= $this->renderOption($key, $val);
- }
- }
- return $opt;
- }
- /**
- * @param mixed $k
- * @param mixed $v
- *
- * @return mixed|string
- */
- protected function renderOption($k, $v)
- {
- if ($v === static::DIVIDER) {
- return static::$dividerHtml;
- }
- if ($builder = $this->builder) {
- $v = $builder->call($this, $v, $k);
- }
- $v = mb_strpos($v, '</a>') ? $v : "<a href='javascript:void(0)'>$v</a>";
- $v = "<li class='dropdown-item'>$v</li>";
- if ($this->divider) {
- $v .= static::$dividerHtml;
- $this->divider = null;
- }
- return $v;
- }
- /**
- * @return string
- */
- public function render()
- {
- if (is_null($this->button['text']) && ! $this->options) {
- return '';
- }
- $button = $this->renderButton();
- if (! $this->options) {
- return $button;
- }
- $opt = $this->renderOptions();
- if (! $button) {
- return sprintf('<ul class="dropdown-menu">%s</ul>', $opt);
- }
- $label = $this->button['text'];
- if ($this->click) {
- Admin::script(
- <<<JS
- (function () {
- var btn = $('#{$this->buttonId}'), _a = btn.parent().find('ul li a'), text = '$label';
- _a.on('click', function () {
- btn.find('stub').html($(this).html() + ' ');
- });
- if (text) {
- btn.find('stub').html(text + ' ');
- } else {
- (!_a.length) || btn.find('stub').html($(_a[0]).html() + ' ');
- }
- })();
- JS
- );
- }
- return sprintf(
- $this->template,
- $button,
- $opt
- );
- }
- }
|