5
* @author Jonah Turnquist <poppitypop@gmail.com>
6
* @author Qiang Xue <qiang.xue@gmail.com>
7
* @link http://www.yiiframework.com/
8
* @copyright Copyright © 2008-2010 Yii Software LLC
9
* @license http://www.yiiframework.com/license/
13
* CMenu displays a multi-level menu using nested HTML lists.
15
* The main property of CMenu is {@link items}, which specifies the possible items in the menu.
16
* A menu item has three main properties: visible, active and items. The "visible" property
17
* specifies whether the menu item is currently visible. The "active" property specifies whether
18
* the menu item is currently selected. And the "items" property specifies the child menu items.
20
* The following example shows how to use CMenu:
22
* $this->widget('zii.widgets.CMenu', array(
24
* array('label'=>'Home', 'url'=>array('site/index')),
25
* array('label'=>'Products', 'url'=>array('product/index'), 'items=>array(
26
* array('label'=>'New Arrivals', 'url'=>array('product/new', 'tag'=>'new')),
27
* array('label'=>'Most Popular', 'url'=>array('product/index', 'tag'=>'popular')),
29
* array('label'=>'Login', 'url'=>array('site/login'), 'visible'=>Yii::app()->user->isGuest),
34
* @author Jonah Turnquist <poppitypop@gmail.com>
35
* @author Qiang Xue <qiang.xue@gmail.com>
36
* @version $Id: CMenu.php 102 2010-01-09 20:38:42Z qiang.xue $
37
* @package zii.widgets
40
class CMenu extends CWidget
43
* @var array list of menu items. Each menu item is specified as an array of name-value pairs.
44
* Possible option names include the following:
46
* <li>label: string, optional, specifies the menu item label. When {@link encodeLabel} is true, the label
47
* will be HTML-encoded.</li>
48
* <li>url: string or array, optional, specifies the URL of the menu item. It is passed to {@link CHtml::normalizeUrl}
49
* to generate a valid URL. If this is not set, the menu item will be rendered as a span text.</li>
50
* <li>visible: boolean, optional, whether this menu item is visible. Defaults to true.
51
* This can be used to control the visibility of menu items based on user permissions.</li>
52
* <li>items: array, optional, specifies the sub-menu items. Its format is the same as the parent items.</li>
53
* <li>active: boolean, optional, whether this menu item is in active state (currently selected).
54
* If a menu item is active and {@link activeClass} is not empty, its CSS class will be appended with {@link activeClass}.
55
* If this option is not set, the menu item will be set active automatically when the current request
56
* is triggered by {@link url}.</li>
57
* <li>linkOptions: array, optional, additional HTML attributes to be rendered for the link or span tag of the menu item.</li>
58
* <li>itemOptions: array, optional, additional HTML attributes to be rendered for the container tag of the menu item.</li>
61
public $items=array();
63
* @var boolean whether the labels for menu items should be HTML-encoded. Defaults to true.
65
public $encodeLabel=true;
67
* @var string the CSS class to be appended to the active menu item. Defaults to 'active'.
68
* If empty, the CSS class of menu items will not be changed.
70
public $activeCssClass='active';
72
* @var boolean whether to activate parent menu items when one of the corresponding child menu items is active.
73
* The activated parent menu items will also have its CSS classes appended with {@link activeCssClass}.
76
public $activateParents=false;
78
* @var boolean whether to hide empty menu items. An empty menu item is one whose 'url' option is not
79
* set and which doesn't contain visible child menu items. Defaults to true.
81
public $hideEmptyItems=true;
83
* @var array HTML attributes for the menu's root container tag
85
public $htmlOptions=array();
87
* @var array HTML attributes for the submenu's container tag.
89
public $submenuHtmlOptions=array();
92
* Initializes the menu widget.
93
* This method mainly normalizes the {@link items} property.
94
* If this method is overridden, make sure the parent implementation is invoked.
96
public function init()
98
$this->htmlOptions['id']=$this->getId();
99
$route=$this->getController()->getRoute();
100
$this->items=$this->normalizeItems($this->items,$route,$hasActiveChild);
104
* Calls {@link renderMenu} to render the menu.
106
public function run()
108
$this->renderMenu($this->items);
112
* Renders the menu items.
113
* @param array menu items. Each menu item will be an array with at least two elements: 'label' and 'active'.
114
* It may have three other optional elements: 'items', 'linkOptions' and 'itemOptions'.
116
protected function renderMenu($items)
120
echo CHtml::openTag('ul',$this->htmlOptions)."\n";
121
$this->renderMenuRecursive($items);
122
echo CHtml::closeTag('ul');
127
* Recursively renders the menu items.
128
* @param array the menu items to be rendered recursively
130
protected function renderMenuRecursive($items)
132
foreach($items as $item)
134
echo CHtml::openTag('li', isset($item['itemOptions']) ? $item['itemOptions'] : array());
135
if(isset($item['url']))
136
echo CHtml::link($item['label'],$item['url'],isset($item['linkOptions']) ? $item['linkOptions'] : array());
138
echo CHtml::tag('span',isset($item['linkOptions']) ? $item['linkOptions'] : array(), $item['label']);
139
if(isset($item['items']) && count($item['items']))
141
echo "\n".CHtml::openTag('ul',$this->submenuHtmlOptions)."\n";
142
$this->renderMenuRecursive($item['items']);
143
echo CHtml::closeTag('ul')."\n";
145
echo CHtml::closeTag('li')."\n";
150
* Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item.
151
* @param array the items to be normalized.
152
* @param string the route of the current request.
153
* @param boolean whether there is an active child menu item.
154
* @return array the normalized menu items
156
protected function normalizeItems($items,$route,&$active)
158
foreach($items as $i=>$item)
160
if(isset($item['visible']) && !$item['visible'])
165
if($this->encodeLabel)
166
$items[$i]['label']=CHtml::encode($item['label']);
167
$hasActiveChild=false;
168
if(isset($item['items']))
170
$items[$i]['items']=$this->normalizeItems($item['items'],$route,$hasActiveChild);
171
if(empty($items[$i]['items']) && $this->hideEmptyItems)
172
unset($items[$i]['items']);
174
if(!isset($item['active']))
176
if($this->activateParents && $hasActiveChild || $this->isItemActive($item,$route))
177
$active=$items[$i]['active']=true;
179
$items[$i]['active']=false;
181
else if($item['active'])
183
if($items[$i]['active'] && $this->activeCssClass!='')
185
if(isset($item['linkOptions']['class']))
186
$items[$i]['linkOptions']['class'].=' '.$this->activeCssClass;
188
$items[$i]['linkOptions']['class']=$this->activeCssClass;
191
return array_values($items);
195
* Checks whether a menu item is active.
196
* This is done by checking if the currently requested URL is generated by the 'url' option
198
* @param array the menu item to be checked
199
* @param string the route of the current request
200
* @return boolean whether the menu item is active
202
protected function isItemActive($item,$route)
204
if(isset($item['url']) && is_array($item['url']) && !strcasecmp(trim($item['url'][0],'/'),$route))
206
if(count($item['url'])>1)
208
foreach(array_splice($item['url'],1) as $name=>$value)
210
if(!isset($_GET[$name]) || $_GET[$name]!=$value)
b'\\ No newline at end of file'