forked from yiisoft/yii2-bootstrap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDropdown.php
143 lines (134 loc) · 5.32 KB
/
Dropdown.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\bootstrap;
use yii\base\InvalidConfigException;
use yii\helpers\ArrayHelper;
/**
* Dropdown renders a Bootstrap dropdown menu component.
*
* For example,
*
* ```php
* <div class="dropdown">
* <a href="#" data-toggle="dropdown" class="dropdown-toggle">Label <b class="caret"></b></a>
* <?php
* echo Dropdown::widget([
* 'items' => [
* ['label' => 'DropdownA', 'url' => '/'],
* ['label' => 'DropdownB', 'url' => '#'],
* ],
* ]);
* ?>
* </div>
* ```
* @see http://getbootstrap.com/javascript/#dropdowns
* @author Antonio Ramirez <[email protected]>
* @since 2.0
*/
class Dropdown extends Widget
{
/**
* @var array list of menu items in the dropdown. Each array element can be either an HTML string,
* or an array representing a single menu with the following structure:
*
* - label: string, required, the label of the item link.
* - encode: boolean, optional, whether to HTML-ecnode item label.
* - url: string|array, optional, the url of the item link. This will be processed by [[Url::to()]].
* If not set, the item will be treated as a menu header when the item has no sub-menu.
* - visible: boolean, optional, whether this menu item is visible. Defaults to true.
* - linkOptions: array, optional, the HTML attributes of the item link.
* - options: array, optional, the HTML attributes of the item.
* - items: array, optional, the submenu items. The structure is the same as this property.
* Note that Bootstrap doesn't support dropdown submenu. You have to add your own CSS styles to support it.
* - submenuOptions: array, optional, the HTML attributes for sub-menu container tag. If specified it will be
* merged with [[submenuOptions]].
*
* To insert divider use `<li role="presentation" class="divider"></li>`.
*/
public $items = [];
/**
* @var boolean whether the labels for header items should be HTML-encoded.
*/
public $encodeLabels = true;
/**
* @var array|null the HTML attributes for sub-menu container tags.
* If not set - [[options]] value will be used for it.
* @since 2.0.5
*/
public $submenuOptions;
/**
* Initializes the widget.
* If you override this method, make sure you call the parent implementation first.
*/
public function init()
{
if ($this->submenuOptions === null) {
// copying of [[options]] kept for BC
// @todo separate [[submenuOptions]] from [[options]] completely before 2.1 release
$this->submenuOptions = $this->options;
unset($this->submenuOptions['id']);
}
parent::init();
Html::addCssClass($this->options, ['widget' => 'dropdown-menu']);
}
/**
* Renders the widget.
*/
public function run()
{
BootstrapPluginAsset::register($this->getView());
$this->registerClientEvents();
return $this->renderItems($this->items, $this->options);
}
/**
* Renders menu items.
* @param array $items the menu items to be rendered
* @param array $options the container HTML attributes
* @return string the rendering result.
* @throws InvalidConfigException if the label option is not specified in one of the items.
*/
protected function renderItems($items, $options = [])
{
$lines = [];
foreach ($items as $item) {
if (is_string($item)) {
$lines[] = $item;
continue;
}
if (isset($item['visible']) && !$item['visible']) {
continue;
}
if (!array_key_exists('label', $item)) {
throw new InvalidConfigException("The 'label' option is required.");
}
$encodeLabel = isset($item['encode']) ? $item['encode'] : $this->encodeLabels;
$label = $encodeLabel ? Html::encode($item['label']) : $item['label'];
$itemOptions = ArrayHelper::getValue($item, 'options', []);
$linkOptions = ArrayHelper::getValue($item, 'linkOptions', []);
$linkOptions['tabindex'] = '-1';
$url = array_key_exists('url', $item) ? $item['url'] : null;
if (empty($item['items'])) {
if ($url === null) {
$content = $label;
Html::addCssClass($itemOptions, ['widget' => 'dropdown-header']);
} else {
$content = Html::a($label, $url, $linkOptions);
}
} else {
$submenuOptions = $this->submenuOptions;
if (isset($item['submenuOptions'])) {
$submenuOptions = array_merge($submenuOptions, $item['submenuOptions']);
}
$content = Html::a($label, $url === null ? '#' : $url, $linkOptions)
. $this->renderItems($item['items'], $submenuOptions);
Html::addCssClass($itemOptions, ['widget' => 'dropdown-submenu']);
}
$lines[] = Html::tag('li', $content, $itemOptions);
}
return Html::tag('ul', implode("\n", $lines), $options);
}
}