172 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * TbNav class file.
 | |
|  * @author Christoffer Niska <christoffer.niska@gmail.com>
 | |
|  * @copyright Copyright © Christoffer Niska 2013-
 | |
|  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
 | |
|  * @package bootstrap.widgets
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Bootstrap navigation menu widget.
 | |
|  * @see http://twitter.github.com/bootstrap/components.html#navbar
 | |
|  */
 | |
| class TbNav extends CWidget
 | |
| {
 | |
|     /**
 | |
|      * @var string the menu type.
 | |
|      */
 | |
|     public $type;
 | |
|     /**
 | |
|      * @var boolean whether the menu items should be stacked on top of each other.
 | |
|      */
 | |
|     public $stacked = false;
 | |
|     /**
 | |
|      * @var string|array the scrollspy target or configuration.
 | |
|      */
 | |
|     public $scrollspy;
 | |
|     /**
 | |
|      * @var array list of menu items. Each menu item is specified as an array of name-value pairs.
 | |
|      */
 | |
|     public $items = array();
 | |
|     /**
 | |
|      * @var boolean whether the labels for menu items should be HTML-encoded. Defaults to true.
 | |
|      */
 | |
|     public $encodeLabel = true;
 | |
|     /**
 | |
|      * @var boolean whether to automatically activate items according to whether their route setting
 | |
|      * matches the currently requested route. Defaults to true.
 | |
|      */
 | |
|     public $activateItems = true;
 | |
|     /**
 | |
|      * @var boolean whether to activate parent menu items when one of the corresponding child menu items is active.
 | |
|      */
 | |
|     public $activateParents = false;
 | |
|     /**
 | |
|      * @var boolean whether to hide empty menu items.
 | |
|      */
 | |
|     public $hideEmptyItems = true;
 | |
|     /**
 | |
|      * @var array HTML attributes for the menu's root container tag.
 | |
|      */
 | |
|     public $htmlOptions = array();
 | |
| 
 | |
|     // todo: consider supporting these.
 | |
|     //public $submenuHtmlOptions = array();
 | |
|     //public $linkLabelWrapper;
 | |
|     //public $linkLabelWrapperHtmlOptions=array();
 | |
|     //public $itemCssClass;
 | |
| 
 | |
|     /**
 | |
|      * Initializes the widget.
 | |
|      */
 | |
|     public function init()
 | |
|     {
 | |
|         $this->attachBehavior('TbWidget', new TbWidget);
 | |
|         $this->copyId();
 | |
|         $route = $this->controller->getRoute();
 | |
|         if ($this->stacked) {
 | |
|             TbHtml::addCssClass('nav-stacked', $this->htmlOptions);
 | |
|         }
 | |
|         if (isset($this->scrollspy)) {
 | |
|             if (is_string($this->scrollspy)) {
 | |
|                 $this->scrollspy = array('target' => $this->scrollspy);
 | |
|             }
 | |
|             $this->widget('bootstrap.widgets.TbScrollspy', $this->scrollspy);
 | |
|         }
 | |
|         $this->items = $this->normalizeItems($this->items, $route, $hasActiveChild);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Runs the widget.
 | |
|      */
 | |
|     public function run()
 | |
|     {
 | |
|         if (!empty($this->items)) {
 | |
|             echo TbHtml::nav($this->type, $this->items, $this->htmlOptions);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Normalizes the menu items.
 | |
|      * @param array $items the items to be normalized.
 | |
|      * @param string $route the route of the current request.
 | |
|      * @param boolean $active whether there is an active child menu item.
 | |
|      * @return array the normalized menu items.
 | |
|      */
 | |
|     protected function normalizeItems($items, $route, &$active)
 | |
|     {
 | |
|         foreach ($items as $i => $item) {
 | |
|             // skip dividers
 | |
|             if (is_string($item)) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             if (isset($item['visible']) && !$item['visible']) {
 | |
|                 unset($items[$i]);
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             TbArray::defaultValue('label', '', $item);
 | |
| 
 | |
|             if ($this->encodeLabel) {
 | |
|                 $items[$i]['label'] = CHtml::encode($item['label']);
 | |
|             }
 | |
| 
 | |
|             $hasActiveChild = false;
 | |
| 
 | |
|             if (isset($item['items']) && !empty($item['items'])) {
 | |
|                 $items[$i]['items'] = $this->normalizeItems($item['items'], $route, $hasActiveChild);
 | |
| 
 | |
|                 if (empty($items[$i]['items']) && $this->hideEmptyItems) {
 | |
|                     unset($items[$i]['items']);
 | |
|                     if (!isset($item['url'])) {
 | |
|                         unset($items[$i]);
 | |
|                         continue;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (!isset($item['active'])) {
 | |
|                 if ($this->activateParents && $hasActiveChild || $this->activateItems && $this->isItemActive(
 | |
|                         $item,
 | |
|                         $route
 | |
|                     )
 | |
|                 ) {
 | |
|                     $active = $items[$i]['active'] = true;
 | |
|                 } else {
 | |
|                     $items[$i]['active'] = false;
 | |
|                 }
 | |
|             } else {
 | |
|                 if ($item['active']) {
 | |
|                     $active = true;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return array_values($items);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether a menu item is active.
 | |
|      * @param array $item the menu item to be checked.
 | |
|      * @param string $route the route of the current request.
 | |
|      * @return boolean whether the menu item is active.
 | |
|      */
 | |
|     protected function isItemActive($item, $route)
 | |
|     {
 | |
|         if (isset($item['url']) && is_array($item['url']) && !strcasecmp(trim($item['url'][0], '/'), $route)) {
 | |
|             unset($item['url']['#']);
 | |
|             if (count($item['url']) > 1) {
 | |
|                 foreach (array_splice($item['url'], 1) as $name => $value) {
 | |
|                     if (!isset($_GET[$name]) || $_GET[$name] != $value) {
 | |
|                         return false;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             return true;
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| }
 |