Dropdown.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. namespace Dcat\Admin\Widgets;
  3. use Dcat\Admin\Support\Helper;
  4. use Illuminate\Support\Str;
  5. class Dropdown extends Widget
  6. {
  7. const DIVIDER = '_divider';
  8. /**
  9. * @var string
  10. */
  11. protected static $dividerHtml = '<li class="dropdown-divider"></li>';
  12. protected $view = 'admin::widgets.dropdown';
  13. /**
  14. * @var array
  15. */
  16. protected $button = [
  17. 'text' => null,
  18. 'class' => 'btn btn-sm btn-white waves-effect',
  19. 'style' => null,
  20. ];
  21. /**
  22. * @var string
  23. */
  24. protected $buttonId;
  25. /**
  26. * @var \Closure
  27. */
  28. protected $builder;
  29. /**
  30. * @var bool
  31. */
  32. protected $divider;
  33. /**
  34. * @var bool
  35. */
  36. protected $click = false;
  37. public function __construct(array $options = [])
  38. {
  39. $this->options($options);
  40. }
  41. /**
  42. * Set the options of dropdown menus.
  43. *
  44. * @param array $options
  45. * @param string|null $title
  46. *
  47. * @return $this
  48. */
  49. public function options($options = [], ?string $title = null)
  50. {
  51. if (! $options) {
  52. return $this;
  53. }
  54. $this->options[] = [$title, Helper::array($options)];
  55. return $this;
  56. }
  57. /**
  58. * Set the button text.
  59. *
  60. * @param string|null $text
  61. *
  62. * @return $this
  63. */
  64. public function button(?string $text)
  65. {
  66. $this->button['text'] = $text;
  67. return $this;
  68. }
  69. /**
  70. * Set the button class.
  71. *
  72. * @param string $class
  73. *
  74. * @return $this
  75. */
  76. public function buttonClass(?string $class)
  77. {
  78. $this->button['class'] = $class;
  79. return $this;
  80. }
  81. /**
  82. * Set the button style.
  83. *
  84. * @param string $class
  85. *
  86. * @return $this
  87. */
  88. public function buttonStyle(?string $style)
  89. {
  90. $this->button['style'] = $style;
  91. return $this;
  92. }
  93. /**
  94. * Show divider.
  95. *
  96. * @param string $class
  97. *
  98. * @return $this
  99. */
  100. public function divider()
  101. {
  102. $this->divider = true;
  103. return $this;
  104. }
  105. /**
  106. * Applies the callback to the elements of the options.
  107. *
  108. * @param string $class
  109. *
  110. * @return $this
  111. */
  112. public function map(\Closure $builder)
  113. {
  114. $this->builder = $builder;
  115. return $this;
  116. }
  117. /**
  118. * Add click event listener.
  119. *
  120. * @param string|null $defaultLabel
  121. *
  122. * @return $this
  123. */
  124. public function click(?string $defaultLabel = null)
  125. {
  126. $this->click = true;
  127. $this->buttonId = 'dropd-'.Str::random(8);
  128. if ($defaultLabel !== null) {
  129. $this->button($defaultLabel);
  130. }
  131. return $this;
  132. }
  133. /**
  134. * @return string
  135. */
  136. public function getButtonId()
  137. {
  138. return $this->buttonId;
  139. }
  140. /**
  141. * @return string
  142. */
  143. protected function renderOptions()
  144. {
  145. $html = '';
  146. foreach ($this->options as &$items) {
  147. [$title, $options] = $items;
  148. if ($title) {
  149. $html .= "<li class='dropdown-header'>$title</li>";
  150. }
  151. foreach ($options as $key => $val) {
  152. $html .= $this->renderOption($key, $val);
  153. }
  154. }
  155. return $html;
  156. }
  157. /**
  158. * @param mixed $k
  159. * @param mixed $v
  160. *
  161. * @return mixed|string
  162. */
  163. protected function renderOption($k, $v)
  164. {
  165. if ($v === static::DIVIDER) {
  166. return static::$dividerHtml;
  167. }
  168. if ($builder = $this->builder) {
  169. $v = $builder->call($this, $v, $k);
  170. }
  171. $v = mb_strpos($v, '</a>') ? $v : "<a href='javascript:void(0)'>$v</a>";
  172. $v = "<li class='dropdown-item'>$v</li>";
  173. if ($this->divider) {
  174. $v .= static::$dividerHtml;
  175. $this->divider = null;
  176. }
  177. return $v;
  178. }
  179. /**
  180. * @return string
  181. */
  182. public function render()
  183. {
  184. $this->addVariables([
  185. 'options' => $this->renderOptions(),
  186. 'button' => $this->button,
  187. 'buttonId' => $this->buttonId,
  188. 'click' => $this->click,
  189. ]);
  190. return parent::render();
  191. }
  192. }