Commits

vi...@vinay-Studio-1558  committed 472c16f Draft

Formatted alignments

  • Participants
  • Parent commits fbf30b7
  • Branches 1.0.0-wip

Comments (0)

Files changed (7)

File demo/yii/zii/widgets/CMenu.php

 <?php
+
 /**
  * CMenu class file.
  *
  * @package zii.widgets
  * @since 1.1
  */
-class CMenu extends CWidget
-{
-	/**
-	 * @var array list of menu items. Each menu item is specified as an array of name-value pairs.
-	 * Possible option names include the following:
-	 * <ul>
-	 * <li>label: string, optional, specifies the menu item label. When {@link encodeLabel} is true, the label
-	 * will be HTML-encoded. If the label is not specified, it defaults to an empty string.</li>
-	 * <li>url: string or array, optional, specifies the URL of the menu item. It is passed to {@link CHtml::normalizeUrl}
-	 * to generate a valid URL. If this is not set, the menu item will be rendered as a span text.</li>
-	 * <li>visible: boolean, optional, whether this menu item is visible. Defaults to true.
-	 * This can be used to control the visibility of menu items based on user permissions.</li>
-	 * <li>items: array, optional, specifies the sub-menu items. Its format is the same as the parent items.</li>
-	 * <li>active: boolean, optional, whether this menu item is in active state (currently selected).
-	 * If a menu item is active and {@link activeClass} is not empty, its CSS class will be appended with {@link activeClass}.
-	 * If this option is not set, the menu item will be set active automatically when the current request
-	 * is triggered by {@link url}. Note that the GET parameters not specified in the 'url' option will be ignored.</li>
-	 * <li>template: string, optional, the template used to render this menu item.
-	 * When this option is set, it will override the global setting {@link itemTemplate}.
-	 * Please see {@link itemTemplate} for more details. This option has been available since version 1.1.1.</li>
-	 * <li>linkOptions: array, optional, additional HTML attributes to be rendered for the link or span tag of the menu item.</li>
-	 * <li>itemOptions: array, optional, additional HTML attributes to be rendered for the container tag of the menu item.</li>
-	 * <li>submenuOptions: array, optional, additional HTML attributes to be rendered for the container of the submenu if this menu item has one.
-	 * When this option is set, the {@link submenuHtmlOptions} property will be ignored for this particular submenu.
-	 * This option has been available since version 1.1.6.</li>
-	 * </ul>
-	 */
-	public $items=array();
-	/**
-	 * @var string the template used to render an individual menu item. In this template,
-	 * the token "{menu}" will be replaced with the corresponding menu link or text.
-	 * If this property is not set, each menu will be rendered without any decoration.
-	 * This property will be overridden by the 'template' option set in individual menu items via {@items}.
-	 * @since 1.1.1
-	 */
-	public $itemTemplate;
-	/**
-	 * @var boolean whether the labels for menu items should be HTML-encoded. Defaults to true.
-	 */
-	public $encodeLabel=true;
-	/**
-	 * @var string the CSS class to be appended to the active menu item. Defaults to 'active'.
-	 * If empty, the CSS class of menu items will not be changed.
-	 */
-	public $activeCssClass='active';
-	/**
-	 * @var boolean whether to automatically activate items according to whether their route setting
-	 * matches the currently requested route. Defaults to true.
-	 * @since 1.1.3
-	 */
-	public $activateItems=true;
-	/**
-	 * @var boolean whether to activate parent menu items when one of the corresponding child menu items is active.
-	 * The activated parent menu items will also have its CSS classes appended with {@link activeCssClass}.
-	 * Defaults to false.
-	 */
-	public $activateParents=false;
-	/**
-	 * @var boolean whether to hide empty menu items. An empty menu item is one whose 'url' option is not
-	 * set and which doesn't contain visible child menu items. Defaults to true.
-	 */
-	public $hideEmptyItems=true;
-	/**
-	 * @var array HTML attributes for the menu's root container tag
-	 */
-	public $htmlOptions=array();
-	/**
-	 * @var array HTML attributes for the submenu's container tag.
-	 */
-	public $submenuHtmlOptions=array();
-	/**
-	 * @var string the HTML element name that will be used to wrap the label of all menu links.
-	 * For example, if this property is set as 'span', a menu item may be rendered as
-	 * &lt;li&gt;&lt;a href="url"&gt;&lt;span&gt;label&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
-	 * This is useful when implementing menu items using the sliding window technique.
-	 * Defaults to null, meaning no wrapper tag will be generated.
-	 * @since 1.1.4
-	 */
-	public $linkLabelWrapper;
-	/**
-	 * @var string the CSS class that will be assigned to the first item in the main menu or each submenu.
-	 * Defaults to null, meaning no such CSS class will be assigned.
-	 * @since 1.1.4
-	 */
-	public $firstItemCssClass;
-	/**
-	 * @var string the CSS class that will be assigned to the last item in the main menu or each submenu.
-	 * Defaults to null, meaning no such CSS class will be assigned.
-	 * @since 1.1.4
-	 */
-	public $lastItemCssClass;
-	/**
-	 * @var string the CSS class that will be assigned to every item.
-	 * Defaults to null, meaning no such CSS class will be assigned.
-	 * @since 1.1.9
-	 */
-	public $itemCssClass;
+class CMenu extends CWidget {
 
-	/**
-	 * Initializes the menu widget.
-	 * This method mainly normalizes the {@link items} property.
-	 * If this method is overridden, make sure the parent implementation is invoked.
-	 */
-	public function init()
-	{
-		$this->htmlOptions['id']=$this->getId();
-		$route=$this->getController()->getRoute();
-		$this->items=$this->normalizeItems($this->items,$route,$hasActiveChild);
-	}
+    /**
+     * @var array list of menu items. Each menu item is specified as an array of name-value pairs.
+     * Possible option names include the following:
+     * <ul>
+     * <li>label: string, optional, specifies the menu item label. When {@link encodeLabel} is true, the label
+     * will be HTML-encoded. If the label is not specified, it defaults to an empty string.</li>
+     * <li>url: string or array, optional, specifies the URL of the menu item. It is passed to {@link CHtml::normalizeUrl}
+     * to generate a valid URL. If this is not set, the menu item will be rendered as a span text.</li>
+     * <li>visible: boolean, optional, whether this menu item is visible. Defaults to true.
+     * This can be used to control the visibility of menu items based on user permissions.</li>
+     * <li>items: array, optional, specifies the sub-menu items. Its format is the same as the parent items.</li>
+     * <li>active: boolean, optional, whether this menu item is in active state (currently selected).
+     * If a menu item is active and {@link activeClass} is not empty, its CSS class will be appended with {@link activeClass}.
+     * If this option is not set, the menu item will be set active automatically when the current request
+     * is triggered by {@link url}. Note that the GET parameters not specified in the 'url' option will be ignored.</li>
+     * <li>template: string, optional, the template used to render this menu item.
+     * When this option is set, it will override the global setting {@link itemTemplate}.
+     * Please see {@link itemTemplate} for more details. This option has been available since version 1.1.1.</li>
+     * <li>linkOptions: array, optional, additional HTML attributes to be rendered for the link or span tag of the menu item.</li>
+     * <li>itemOptions: array, optional, additional HTML attributes to be rendered for the container tag of the menu item.</li>
+     * <li>submenuOptions: array, optional, additional HTML attributes to be rendered for the container of the submenu if this menu item has one.
+     * When this option is set, the {@link submenuHtmlOptions} property will be ignored for this particular submenu.
+     * This option has been available since version 1.1.6.</li>
+     * </ul>
+     */
+    public $items = array();
 
-	/**
-	 * Calls {@link renderMenu} to render the menu.
-	 */
-	public function run()
-	{
-		$this->renderMenu($this->items);
-	}
+    /**
+     * @var string the template used to render an individual menu item. In this template,
+     * the token "{menu}" will be replaced with the corresponding menu link or text.
+     * If this property is not set, each menu will be rendered without any decoration.
+     * This property will be overridden by the 'template' option set in individual menu items via {@items}.
+     * @since 1.1.1
+     */
+    public $itemTemplate;
 
-	/**
-	 * Renders the menu items.
-	 * @param array $items menu items. Each menu item will be an array with at least two elements: 'label' and 'active'.
-	 * It may have three other optional elements: 'items', 'linkOptions' and 'itemOptions'.
-	 */
-	protected function renderMenu($items)
-	{
-		if(count($items))
-		{
-			echo CHtml::openTag('ul',$this->htmlOptions)."\n";
-			$this->renderMenuRecursive($items);
-			echo CHtml::closeTag('ul');
-		}
-	}
+    /**
+     * @var boolean whether the labels for menu items should be HTML-encoded. Defaults to true.
+     */
+    public $encodeLabel = true;
 
-	/**
-	 * Recursively renders the menu items.
-	 * @param array $items the menu items to be rendered recursively
-	 */
-	protected function renderMenuRecursive($items)
-	{
-		$count=0;
-		$n=count($items);
-		foreach($items as $item)
-		{
-			$count++;
-			$options=isset($item['itemOptions']) ? $item['itemOptions'] : array();
-			$class=array();
-			if($item['active'] && $this->activeCssClass!='')
-				$class[]=$this->activeCssClass;
-			if($count===1 && $this->firstItemCssClass!==null)
-				$class[]=$this->firstItemCssClass;
-			if($count===$n && $this->lastItemCssClass!==null)
-				$class[]=$this->lastItemCssClass;
-			if($this->itemCssClass!==null)
-				$class[]=$this->itemCssClass;
-			if($class!==array())
-			{
-				if(empty($options['class']))
-					$options['class']=implode(' ',$class);
-				else
-					$options['class'].=' '.implode(' ',$class);
-			}
+    /**
+     * @var string the CSS class to be appended to the active menu item. Defaults to 'active'.
+     * If empty, the CSS class of menu items will not be changed.
+     */
+    public $activeCssClass = 'active';
 
-			echo CHtml::openTag('li', $options);
+    /**
+     * @var boolean whether to automatically activate items according to whether their route setting
+     * matches the currently requested route. Defaults to true.
+     * @since 1.1.3
+     */
+    public $activateItems = true;
 
-			$menu=$this->renderMenuItem($item);
-			if(isset($this->itemTemplate) || isset($item['template']))
-			{
-				$template=isset($item['template']) ? $item['template'] : $this->itemTemplate;
-				echo strtr($template,array('{menu}'=>$menu));
-			}
-			else
-				echo $menu;
+    /**
+     * @var boolean whether to activate parent menu items when one of the corresponding child menu items is active.
+     * The activated parent menu items will also have its CSS classes appended with {@link activeCssClass}.
+     * Defaults to false.
+     */
+    public $activateParents = false;
 
-			if(isset($item['items']) && count($item['items']))
-			{
-				echo "\n".CHtml::openTag('ul',isset($item['submenuOptions']) ? $item['submenuOptions'] : $this->submenuHtmlOptions)."\n";
-				$this->renderMenuRecursive($item['items']);
-				echo CHtml::closeTag('ul')."\n";
-			}
+    /**
+     * @var boolean whether to hide empty menu items. An empty menu item is one whose 'url' option is not
+     * set and which doesn't contain visible child menu items. Defaults to true.
+     */
+    public $hideEmptyItems = true;
 
-			echo CHtml::closeTag('li')."\n";
-		}
-	}
+    /**
+     * @var array HTML attributes for the menu's root container tag
+     */
+    public $htmlOptions = array();
 
-	/**
-	 * Renders the content of a menu item.
-	 * Note that the container and the sub-menus are not rendered here.
-	 * @param array $item the menu item to be rendered. Please see {@link items} on what data might be in the item.
-	 * @return string
-	 * @since 1.1.6
-	 */
-	protected function renderMenuItem($item)
-	{
-		if(isset($item['url']))
-		{
-			$label=$this->linkLabelWrapper===null ? $item['label'] : '<'.$this->linkLabelWrapper.'>'.$item['label'].'</'.$this->linkLabelWrapper.'>';
-			return CHtml::link($label,$item['url'],isset($item['linkOptions']) ? $item['linkOptions'] : array());
-		}
-		else
-			return CHtml::tag('span',isset($item['linkOptions']) ? $item['linkOptions'] : array(), $item['label']);
-	}
+    /**
+     * @var array HTML attributes for the submenu's container tag.
+     */
+    public $submenuHtmlOptions = array();
 
-	/**
-	 * Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item.
-	 * @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)
-		{
-			if(isset($item['visible']) && !$item['visible'])
-			{
-				unset($items[$i]);
-				continue;
-			}
-			if(!isset($item['label']))
-				$item['label']='';
-			if($this->encodeLabel)
-				$items[$i]['label']=CHtml::encode($item['label']);
-			$hasActiveChild=false;
-			if(isset($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);
-	}
+    /**
+     * @var string the HTML element name that will be used to wrap the label of all menu links.
+     * For example, if this property is set as 'span', a menu item may be rendered as
+     * &lt;li&gt;&lt;a href="url"&gt;&lt;span&gt;label&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
+     * This is useful when implementing menu items using the sliding window technique.
+     * Defaults to null, meaning no wrapper tag will be generated.
+     * @since 1.1.4
+     */
+    public $linkLabelWrapper;
 
-	/**
-	 * Checks whether a menu item is active.
-	 * This is done by checking if the currently requested URL is generated by the 'url' option
-	 * of the menu item. Note that the GET parameters not specified in the 'url' option will be ignored.
-	 * @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;
-	}
+    /**
+     * @var string the CSS class that will be assigned to the first item in the main menu or each submenu.
+     * Defaults to null, meaning no such CSS class will be assigned.
+     * @since 1.1.4
+     */
+    public $firstItemCssClass;
+
+    /**
+     * @var string the CSS class that will be assigned to the last item in the main menu or each submenu.
+     * Defaults to null, meaning no such CSS class will be assigned.
+     * @since 1.1.4
+     */
+    public $lastItemCssClass;
+
+    /**
+     * @var string the CSS class that will be assigned to every item.
+     * Defaults to null, meaning no such CSS class will be assigned.
+     * @since 1.1.9
+     */
+    public $itemCssClass;
+
+    /**
+     * Initializes the menu widget.
+     * This method mainly normalizes the {@link items} property.
+     * If this method is overridden, make sure the parent implementation is invoked.
+     */
+    public function init() {
+        $this->htmlOptions['id'] = $this->getId();
+        $route = $this->getController()->getRoute();
+        $this->items = $this->normalizeItems($this->items, $route, $hasActiveChild);
+    }
+
+    /**
+     * Calls {@link renderMenu} to render the menu.
+     */
+    public function run() {
+        $this->renderMenu($this->items);
+    }
+
+    /**
+     * Renders the menu items.
+     * @param array $items menu items. Each menu item will be an array with at least two elements: 'label' and 'active'.
+     * It may have three other optional elements: 'items', 'linkOptions' and 'itemOptions'.
+     */
+    protected function renderMenu($items) {
+        if (count($items)) {
+            echo CHtml::openTag('ul', $this->htmlOptions) . "\n";
+            $this->renderMenuRecursive($items);
+            echo CHtml::closeTag('ul');
+        }
+    }
+
+    /**
+     * Recursively renders the menu items.
+     * @param array $items the menu items to be rendered recursively
+     */
+    protected function renderMenuRecursive($items) {
+        $count = 0;
+        $n = count($items);
+        foreach ($items as $item) {
+            $count++;
+            $options = isset($item['itemOptions']) ? $item['itemOptions'] : array();
+            $class = array();
+            if ($item['active'] && $this->activeCssClass != '')
+                $class[] = $this->activeCssClass;
+            if ($count === 1 && $this->firstItemCssClass !== null)
+                $class[] = $this->firstItemCssClass;
+            if ($count === $n && $this->lastItemCssClass !== null)
+                $class[] = $this->lastItemCssClass;
+            if ($this->itemCssClass !== null)
+                $class[] = $this->itemCssClass;
+            if ($class !== array()) {
+                if (empty($options['class']))
+                    $options['class'] = implode(' ', $class);
+                else
+                    $options['class'].=' ' . implode(' ', $class);
+            }
+
+            echo CHtml::openTag('li', $options);
+
+            $menu = $this->renderMenuItem($item);
+            if (isset($this->itemTemplate) || isset($item['template'])) {
+                $template = isset($item['template']) ? $item['template'] : $this->itemTemplate;
+                echo strtr($template, array('{menu}' => $menu));
+            }
+            else
+                echo $menu;
+
+            if (isset($item['items']) && count($item['items'])) {
+                echo "\n" . CHtml::openTag('ul', isset($item['submenuOptions']) ? $item['submenuOptions'] : $this->submenuHtmlOptions) . "\n";
+                $this->renderMenuRecursive($item['items']);
+                echo CHtml::closeTag('ul') . "\n";
+            }
+
+            echo CHtml::closeTag('li') . "\n";
+        }
+    }
+
+    /**
+     * Renders the content of a menu item.
+     * Note that the container and the sub-menus are not rendered here.
+     * @param array $item the menu item to be rendered. Please see {@link items} on what data might be in the item.
+     * @return string
+     * @since 1.1.6
+     */
+    protected function renderMenuItem($item) {
+        if (isset($item['url'])) {
+            $label = $this->linkLabelWrapper === null ? $item['label'] : '<' . $this->linkLabelWrapper . '>' . $item['label'] . '</' . $this->linkLabelWrapper . '>';
+            return CHtml::link($label, $item['url'], isset($item['linkOptions']) ? $item['linkOptions'] : array());
+        }
+        else
+            return CHtml::tag('span', isset($item['linkOptions']) ? $item['linkOptions'] : array(), $item['label']);
+    }
+
+    /**
+     * Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item.
+     * @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) {
+            if (isset($item['visible']) && !$item['visible']) {
+                unset($items[$i]);
+                continue;
+            }
+            if (!isset($item['label']))
+                $item['label'] = '';
+            if ($this->encodeLabel)
+                $items[$i]['label'] = CHtml::encode($item['label']);
+            $hasActiveChild = false;
+            if (isset($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.
+     * This is done by checking if the currently requested URL is generated by the 'url' option
+     * of the menu item. Note that the GET parameters not specified in the 'url' option will be ignored.
+     * @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;
+    }
+
 }

File nbproject/project.properties

+include.path=${php.global.include.path}
+php.version=PHP_53
+source.encoding=UTF-8
+src.dir=.
+tags.asp=false
+tags.short=true
+web.root=.

File nbproject/project.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.php.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/php-project/1">
+            <name>Xtn yii-bootstrap</name>
+        </data>
+    </configuration>
+</project>

File widgets/TbBaseMenu.php

 <?php
+
 /**
  * TbBaseMenu class file.
  * @author Christoffer Niska <ChristofferNiska@gmail.com>
  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  * @package bootstrap.widgets
  */
-
 Yii::import('zii.widgets.CMenu');
 
-abstract class TbBaseMenu extends CMenu
-{
-	/**
-	 * Returns the divider css class.
-	 * @return string the class name
-	 */
-	abstract public function getDividerCssClass();
+abstract class TbBaseMenu extends CMenu {
 
-	/**
-	 * Returns the dropdown css class.
-	 * @return string the class name
-	 */
-	abstract public function getDropdownCssClass();
+    /**
+     * Returns the divider css class.
+     * @return string the class name
+     */
+    abstract public function getDividerCssClass();
 
-	/**
-	 * Returns whether this is a vertical menu.
-	 * @return boolean the result
-	 */
-	abstract public function isVertical();
+    /**
+     * Returns the dropdown css class.
+     * @return string the class name
+     */
+    abstract public function getDropdownCssClass();
 
-	/**
-	 * Renders the menu items.
-	 * @param array $items menu items. Each menu item will be an array with at least two elements: 'label' and 'active'.
-	 * It may have three other optional elements: 'items', 'linkOptions' and 'itemOptions'.
-	 */
-	protected function renderMenu($items)
-	{
-		$n = count($items);
+    /**
+     * Returns whether this is a vertical menu.
+     * @return boolean the result
+     */
+    abstract public function isVertical();
 
-		if($n > 0)
-		{
-			echo CHtml::openTag('ul', $this->htmlOptions);
+    /**
+     * Renders the menu items.
+     * @param array $items menu items. Each menu item will be an array with at least two elements: 'label' and 'active'.
+     * It may have three other optional elements: 'items', 'linkOptions' and 'itemOptions'.
+     */
+    protected function renderMenu($items) {
+        $n = count($items);
 
-			$count = 0;
-			foreach ($items as $item)
-			{
-				$count++;
+        if ($n > 0) {
+            echo CHtml::openTag('ul', $this->htmlOptions);
 
-				if (isset($item['divider']))
-					echo '<li class="'.$this->getDividerCssClass().'"></li>';
-				else
-				{
-					$options = isset($item['itemOptions']) ? $item['itemOptions'] : array();
-					$classes = array();
+            $count = 0;
+            foreach ($items as $item) {
+                $count++;
 
-					if ($item['active'] && $this->activeCssClass != '')
-						$classes[] = $this->activeCssClass;
+                if (isset($item['divider']))
+                    echo '<li class="' . $this->getDividerCssClass() . '"></li>';
+                else {
+                    $options = isset($item['itemOptions']) ? $item['itemOptions'] : array();
+                    $classes = array();
 
-					if ($count === 1 && $this->firstItemCssClass !== null)
-						$classes[] = $this->firstItemCssClass;
+                    if ($item['active'] && $this->activeCssClass != '')
+                        $classes[] = $this->activeCssClass;
 
-					if ($count === $n && $this->lastItemCssClass !== null)
-						$classes[] = $this->lastItemCssClass;
+                    if ($count === 1 && $this->firstItemCssClass !== null)
+                        $classes[] = $this->firstItemCssClass;
 
-					if ($this->itemCssClass !== null)
-						$classes[] = $this->itemCssClass;
+                    if ($count === $n && $this->lastItemCssClass !== null)
+                        $classes[] = $this->lastItemCssClass;
 
-					if (isset($item['items']))
-						$classes[] = $this->getDropdownCssClass();
+                    if ($this->itemCssClass !== null)
+                        $classes[] = $this->itemCssClass;
 
-					if (!empty($classes))
-					{
-						$classes = implode(' ', $classes);
-						if (!empty($options['class']))
-							$options['class'] .= ' '.$classes;
-						else
-							$options['class'] = $classes;
-					}
+                    if (isset($item['items']))
+                        $classes[] = $this->getDropdownCssClass();
 
-					echo CHtml::openTag('li', $options);
+                    if (!empty($classes)) {
+                        $classes = implode(' ', $classes);
+                        if (!empty($options['class']))
+                            $options['class'] .= ' ' . $classes;
+                        else
+                            $options['class'] = $classes;
+                    }
 
-					$menu = $this->renderMenuItem($item);
+                    echo CHtml::openTag('li', $options);
 
-					if (isset($this->itemTemplate) || isset($item['template']))
-					{
-						$template = isset($item['template']) ? $item['template'] : $this->itemTemplate;
-						echo strtr($template, array('{menu}' => $menu));
-					}
-					else
-						echo $menu;
+                    $menu = $this->renderMenuItem($item);
 
-					if (isset($item['items']) && !empty($item['items']))
-					{
-						$this->controller->widget('bootstrap.widgets.TbDropdown', array(
-							'encodeLabel'=>$this->encodeLabel,
-							'htmlOptions'=>isset($item['submenuOptions']) ? $item['submenuOptions'] : $this->submenuHtmlOptions,
-							'items'=>$item['items'],
-						));
-					}
+                    if (isset($this->itemTemplate) || isset($item['template'])) {
+                        $template = isset($item['template']) ? $item['template'] : $this->itemTemplate;
+                        echo strtr($template, array('{menu}' => $menu));
+                    }
+                    else
+                        echo $menu;
 
-					echo '</li>';
-				}
-			}
+                    if (isset($item['items']) && !empty($item['items'])) {
+                        $this->controller->widget('bootstrap.widgets.TbDropdown', array(
+                            'encodeLabel' => $this->encodeLabel,
+                            'htmlOptions' => isset($item['submenuOptions']) ? $item['submenuOptions'] : $this->submenuHtmlOptions,
+                            'items' => $item['items'],
+                        ));
+                    }
 
-			echo '</ul>';
-		}
-	}
+                    echo '</li>';
+                }
+            }
 
-	/**
-	 * Renders the content of a menu item.
-	 * Note that the container and the sub-menus are not rendered here.
-	 * @param array $item the menu item to be rendered. Please see {@link items} on what data might be in the item.
-	 * @return string the rendered item
-	 */
-	protected function renderMenuItem($item)
-	{
-		if (isset($item['icon']))
-		{
-			if (strpos($item['icon'], 'icon') === false)
-			{
-				$pieces = explode(' ', $item['icon']);
-				$item['icon'] = 'icon-'.implode(' icon-', $pieces);
-			}
+            echo '</ul>';
+        }
+    }
 
-			$item['label'] = '<i class="'.$item['icon'].'"></i> '.$item['label'];
-		}
+    /**
+     * Renders the content of a menu item.
+     * Note that the container and the sub-menus are not rendered here.
+     * @param array $item the menu item to be rendered. Please see {@link items} on what data might be in the item.
+     * @return string the rendered item
+     */
+    protected function renderMenuItem($item) {
+        if (isset($item['icon'])) {
+            if (strpos($item['icon'], 'icon') === false) {
+                $pieces = explode(' ', $item['icon']);
+                $item['icon'] = 'icon-' . implode(' icon-', $pieces);
+            }
 
-		if (!isset($item['linkOptions']))
-			$item['linkOptions'] = array();
+            $item['label'] = '<i class="' . $item['icon'] . '"></i> ' . $item['label'];
+        }
 
-		if (isset($item['items']) && !empty($item['items']))
-		{
-			$item['url'] = '#';
+        if (!isset($item['linkOptions']))
+            $item['linkOptions'] = array();
 
-			if (isset($item['linkOptions']['class']))
-				$item['linkOptions']['class'] .= ' dropdown-toggle';
-			else
-				$item['linkOptions']['class'] = 'dropdown-toggle';
+        if (isset($item['items']) && !empty($item['items'])) {
+            $item['url'] = '#';
 
-			$item['linkOptions']['data-toggle'] = 'dropdown';
-			$item['label'] .= ' <span class="caret"></span>';
-		}
+            if (isset($item['linkOptions']['class']))
+                $item['linkOptions']['class'] .= ' dropdown-toggle';
+            else
+                $item['linkOptions']['class'] = 'dropdown-toggle';
 
-		if (isset($item['url']))
-			return CHtml::link($item['label'], $item['url'], $item['linkOptions']);
-		else
-			return $item['label'];
-	}
+            $item['linkOptions']['data-toggle'] = 'dropdown';
+            $item['label'] .= ' <span class="caret"></span>';
+        }
 
-	/**
-	 * Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item.
-	 * @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)
-		{
-			if (!is_array($item))
-				$item = array('divider'=>true);
-			else
-			{
-				if (!isset($item['itemOptions']))
-					$item['itemOptions'] = array();
+        if (isset($item['url']))
+            return CHtml::link($item['label'], $item['url'], $item['linkOptions']);
+        else
+            return $item['label'];
+    }
 
-				$classes = array();
+    /**
+     * Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item.
+     * @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) {
+            if (!is_array($item))
+                $item = array('divider' => true);
+            else {
+                if (!isset($item['itemOptions']))
+                    $item['itemOptions'] = array();
 
-				if (!isset($item['url']) && !isset($item['items']) && $this->isVertical())
-				{
-					$item['header'] = true;
-					$classes[] = 'nav-header';
-				}
+                $classes = array();
 
-				if (!empty($classes))
-				{
-					$classes = implode($classes, ' ');
-					if (isset($item['itemOptions']['class']))
-						$item['itemOptions']['class'] .= ' '.$classes;
-					else
-						$item['itemOptions']['class'] = $classes;
-				}
-			}
+                if (!isset($item['url']) && !isset($item['items']) && $this->isVertical()) {
+                    $item['header'] = true;
+                    $classes[] = 'nav-header';
+                }
 
-			$items[$i] = $item;
-		}
+                if (!empty($classes)) {
+                    $classes = implode($classes, ' ');
+                    if (isset($item['itemOptions']['class']))
+                        $item['itemOptions']['class'] .= ' ' . $classes;
+                    else
+                        $item['itemOptions']['class'] = $classes;
+                }
+            }
 
-		return parent::normalizeItems($items, $route, $active);
-	}
+            $items[$i] = $item;
+        }
+
+        return parent::normalizeItems($items, $route, $active);
+    }
+
 }

File widgets/TbMenu.php

 <?php
+
 /**
  * TbMenu class file.
  * @author Christoffer Niska <ChristofferNiska@gmail.com>
  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  * @package bootstrap.widgets
  */
-
 Yii::import('bootstrap.widgets.TbBaseMenu');
 
 /**
  * Bootstrap menu.
  * @see http://twitter.github.com/bootstrap/components.html#navs
  */
-class TbMenu extends TbBaseMenu
-{
-	// Menu types.
-	const TYPE_TABS = 'tabs';
-	const TYPE_PILLS = 'pills';
-	const TYPE_LIST = 'list';
+class TbMenu extends TbBaseMenu {
+    // Menu types.
 
-	/**
-	 * @var string the menu type.
-	 * Valid values are 'tabs' and 'pills'.
-	 */
-	public $type;
-	/**
-	 * @var boolean indicates whether to stack navigation items.
-	 */
-	public $stacked = false;
-	/**
-	 * @var string|array the scrollspy configuration.
-	 */
-	public $scrollspy;
-	/**
-	 * @var boolean indicates whether dropdowns should be dropups instead.
-	 */
-	public $dropup = false;
+    const TYPE_TABS = 'tabs';
+    const TYPE_PILLS = 'pills';
+    const TYPE_LIST = 'list';
 
-	/**
-	 * Initializes the widget.
-	 */
-	public function init()
-	{
-		parent::init();
+    /**
+     * @var string the menu type.
+     * Valid values are 'tabs' and 'pills'.
+     */
+    public $type;
 
-		$classes = array('nav');
+    /**
+     * @var boolean indicates whether to stack navigation items.
+     */
+    public $stacked = false;
 
-		$validTypes = array(self::TYPE_TABS, self::TYPE_PILLS, self::TYPE_LIST);
+    /**
+     * @var string|array the scrollspy configuration.
+     */
+    public $scrollspy;
 
-		if (isset($this->type) && in_array($this->type, $validTypes))
-			$classes[] = 'nav-'.$this->type;
+    /**
+     * @var boolean indicates whether dropdowns should be dropups instead.
+     */
+    public $dropup = false;
 
-		if ($this->stacked && $this->type !== self::TYPE_LIST)
-			$classes[] = 'nav-stacked';
+    /**
+     * Initializes the widget.
+     */
+    public function init() {
+        parent::init();
 
-		if ($this->dropup === true)
-			$classes[] = 'dropup';
+        $classes = array('nav');
 
-		if (isset($this->scrollspy))
-		{
-			$scrollspy = is_string($this->scrollspy) ? array('target'=>$this->scrollspy) : $this->scrollspy;
-			$this->widget('bootstrap.widgets.TbScrollSpy', $scrollspy);
-		}
+        $validTypes = array(self::TYPE_TABS, self::TYPE_PILLS, self::TYPE_LIST);
 
-		if (!empty($classes))
-		{
-			$classes = implode(' ', $classes);
-			if (isset($this->htmlOptions['class']))
-				$this->htmlOptions['class'] .= ' '.$classes;
-			else
-				$this->htmlOptions['class'] = $classes;
-		}
-	}
+        if (isset($this->type) && in_array($this->type, $validTypes))
+            $classes[] = 'nav-' . $this->type;
 
-	/**
-	 * Returns the divider css class.
-	 * @return string the class name
-	 */
-	public function getDividerCssClass()
-	{
-		return (isset($this->type) && $this->type === self::TYPE_LIST) ? 'divider' : 'divider-vertical';
-	}
+        if ($this->stacked && $this->type !== self::TYPE_LIST)
+            $classes[] = 'nav-stacked';
 
-	/**
-	 * Returns the dropdown css class.
-	 * @return string the class name
-	 */
-	public function getDropdownCssClass()
-	{
-		return 'dropdown';
-	}
+        if ($this->dropup === true)
+            $classes[] = 'dropup';
 
-	/**
-	 * Returns whether this is a vertical menu.
-	 * @return boolean the result
-	 */
-	public function isVertical()
-	{
-		return isset($this->type) && $this->type === self::TYPE_LIST;
-	}
+        if (isset($this->scrollspy)) {
+            $scrollspy = is_string($this->scrollspy) ? array('target' => $this->scrollspy) : $this->scrollspy;
+            $this->widget('bootstrap.widgets.TbScrollSpy', $scrollspy);
+        }
+
+        if (!empty($classes)) {
+            $classes = implode(' ', $classes);
+            if (isset($this->htmlOptions['class']))
+                $this->htmlOptions['class'] .= ' ' . $classes;
+            else
+                $this->htmlOptions['class'] = $classes;
+        }
+    }
+
+    /**
+     * Returns the divider css class.
+     * @return string the class name
+     */
+    public function getDividerCssClass() {
+        return (isset($this->type) && $this->type === self::TYPE_LIST) ? 'divider' : 'divider-vertical';
+    }
+
+    /**
+     * Returns the dropdown css class.
+     * @return string the class name
+     */
+    public function getDropdownCssClass() {
+        return 'dropdown';
+    }
+
+    /**
+     * Returns whether this is a vertical menu.
+     * @return boolean the result
+     */
+    public function isVertical() {
+        return isset($this->type) && $this->type === self::TYPE_LIST;
+    }
+
 }

File widgets/TbNavbar.php

 <?php
+
 /**
  * TbNavbar class file.
  * @author Christoffer Niska <ChristofferNiska@gmail.com>
  * @package bootstrap.widgets
  * @since 0.9.7
  */
-
 Yii::import('bootstrap.widgets.TbCollapse');
 
 /**
  * Bootstrap navigation bar widget.
  */
-class TbNavbar extends CWidget
-{
-	// Navbar types.
-	const TYPE_INVERSE = 'inverse';
+class TbNavbar extends CWidget {
+    // Navbar types.
 
-	// Navbar fix locations.
-	const FIXED_TOP = 'top';
-	const FIXED_BOTTOM = 'bottom';
+    const TYPE_INVERSE = 'inverse';
 
-	/**
-	 * @var string the navbar type. Valid values are 'inverse'.
-	 * @since 1.0.0
-	 */
-	public $type;
-	/**
-	 * @var string the text for the brand.
-	 */
-	public $brand;
-	/**
-	 * @var string the URL for the brand link.
-	 */
-	public $brandUrl;
-	/**
-	 * @var array the HTML attributes for the brand link.
-	 */
-	public $brandOptions = array();
-	/**
-	 * @var array navigation items.
-	 * @since 0.9.8
-	 */
-	public $items = array();
-	/**
-	 * @var mixed fix location of the navbar if applicable.
-	 * Valid values are 'top' and 'bottom'. Defaults to 'top'.
-	 * Setting the value to false will make the navbar static.
-	 * @since 0.9.8
-	 */
-	public $fixed = self::FIXED_TOP;
-	/**
-	* @var boolean whether the nav span over the full width. Defaults to false.
-	* @since 0.9.8
-	*/
-	public $fluid = false;
-	/**
-	 * @var boolean whether to enable collapsing on narrow screens. Default to false.
-	 */
-	public $collapse = false;
-	/**
-	 * @var array the HTML attributes for the widget container.
-	 */
-	public $htmlOptions = array();
+    // Navbar fix locations.
+    const FIXED_TOP = 'top';
+    const FIXED_BOTTOM = 'bottom';
 
-	/**
-	 * Initializes the widget.
-	 */
-	public function init()
-	{
-		if ($this->brand !== false)
-		{
-			if (!isset($this->brand))
-				$this->brand = CHtml::encode(Yii::app()->name);
+    /**
+     * @var string the navbar type. Valid values are 'inverse'.
+     * @since 1.0.0
+     */
+    public $type;
 
-			if (!isset($this->brandUrl))
-				$this->brandUrl = Yii::app()->homeUrl;
+    /**
+     * @var string the text for the brand.
+     */
+    public $brand;
 
-			$this->brandOptions['href'] = CHtml::normalizeUrl($this->brandUrl);
+    /**
+     * @var string the URL for the brand link.
+     */
+    public $brandUrl;
 
-			if (isset($this->brandOptions['class']))
-				$this->brandOptions['class'] .= ' brand';
-			else
-				$this->brandOptions['class'] = 'brand';
-		}
+    /**
+     * @var array the HTML attributes for the brand link.
+     */
+    public $brandOptions = array();
 
-		$classes = array('navbar');
+    /**
+     * @var array navigation items.
+     * @since 0.9.8
+     */
+    public $items = array();
 
-		if (isset($this->type) && in_array($this->type, array(self::TYPE_INVERSE)))
-			$classes[] = 'navbar-'.$this->type;
+    /**
+     * @var mixed fix location of the navbar if applicable.
+     * Valid values are 'top' and 'bottom'. Defaults to 'top'.
+     * Setting the value to false will make the navbar static.
+     * @since 0.9.8
+     */
+    public $fixed = self::FIXED_TOP;
 
-		if ($this->fixed !== false && in_array($this->fixed, array(self::FIXED_TOP, self::FIXED_BOTTOM)))
-			$classes[] = 'navbar-fixed-'.$this->fixed;
+    /**
+     * @var boolean whether the nav span over the full width. Defaults to false.
+     * @since 0.9.8
+     */
+    public $fluid = false;
 
-		if (!empty($classes))
-		{
-			$classes = implode(' ', $classes);
-			if (isset($this->htmlOptions['class']))
-				$this->htmlOptions['class'] .= ' '.$classes;
-			else
-				$this->htmlOptions['class'] = $classes;
-		}
-	}
+    /**
+     * @var boolean whether to enable collapsing on narrow screens. Default to false.
+     */
+    public $collapse = false;
 
-	/**
-	 * Runs the widget.
-	 */
-	public function run()
-	{
-		echo CHtml::openTag('div', $this->htmlOptions);
-		echo '<div class="navbar-inner"><div class="'.$this->getContainerCssClass().'">';
+    /**
+     * @var array the HTML attributes for the widget container.
+     */
+    public $htmlOptions = array();
 
-		$collapseId = TbCollapse::getNextContainerId();
+    /**
+     * Initializes the widget.
+     */
+    public function init() {
+        if ($this->brand !== false) {
+            if (!isset($this->brand))
+                $this->brand = CHtml::encode(Yii::app()->name);
 
-		if ($this->collapse !== false)
-		{
-			echo '<a class="btn btn-navbar" data-toggle="collapse" data-target="#'.$collapseId.'">';
-			echo '<span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>';
-			echo '</a>';
-		}
+            if (!isset($this->brandUrl))
+                $this->brandUrl = Yii::app()->homeUrl;
 
-		if ($this->brand !== false)
-			echo CHtml::openTag('a', $this->brandOptions).$this->brand.'</a>';
+            $this->brandOptions['href'] = CHtml::normalizeUrl($this->brandUrl);
 
-		if ($this->collapse !== false)
-		{
-			$this->controller->beginWidget('bootstrap.widgets.TbCollapse', array(
-				'id'=>$collapseId,
-				'toggle'=>false, // navbars should be collapsed by default
-				'htmlOptions'=>array('class'=>'nav-collapse'),
-			));
-		}
+            if (isset($this->brandOptions['class']))
+                $this->brandOptions['class'] .= ' brand';
+            else
+                $this->brandOptions['class'] = 'brand';
+        }
 
-		foreach ($this->items as $item)
-		{
-			if (is_string($item))
-				echo $item;
-			else
-			{
-				if (isset($item['class']))
-				{
-					$className = $item['class'];
-					unset($item['class']);
+        $classes = array('navbar');
 
-					$this->controller->widget($className, $item);
-				}
-			}
-		}
+        if (isset($this->type) && in_array($this->type, array(self::TYPE_INVERSE)))
+            $classes[] = 'navbar-' . $this->type;
 
-		if ($this->collapse !== false)
-			$this->controller->endWidget();
+        if ($this->fixed !== false && in_array($this->fixed, array(self::FIXED_TOP, self::FIXED_BOTTOM)))
+            $classes[] = 'navbar-fixed-' . $this->fixed;
 
-		echo '</div></div></div>';
-	}
+        if (!empty($classes)) {
+            $classes = implode(' ', $classes);
+            if (isset($this->htmlOptions['class']))
+                $this->htmlOptions['class'] .= ' ' . $classes;
+            else
+                $this->htmlOptions['class'] = $classes;
+        }
+    }
 
-	/**
-	 * Returns the navbar container CSS class.
-	 * @return string the class
-	 */
-	protected function getContainerCssClass()
-	{
-		return $this->fluid ? 'container-fluid' : 'container';
-	}
+    /**
+     * Runs the widget.
+     */
+    public function run() {
+        echo CHtml::openTag('div', $this->htmlOptions);
+        echo '<div class="navbar-inner"><div class="' . $this->getContainerCssClass() . '">';
+
+        $collapseId = TbCollapse::getNextContainerId();
+
+        if ($this->collapse !== false) {
+            echo '<a class="btn btn-navbar" data-toggle="collapse" data-target="#' . $collapseId . '">';
+            echo '<span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>';
+            echo '</a>';
+        }
+
+        if ($this->brand !== false)
+            echo CHtml::openTag('a', $this->brandOptions) . $this->brand . '</a>';
+
+        if ($this->collapse !== false) {
+            $this->controller->beginWidget('bootstrap.widgets.TbCollapse', array(
+                'id' => $collapseId,
+                'toggle' => false, // navbars should be collapsed by default
+                'htmlOptions' => array('class' => 'nav-collapse'),
+            ));
+        }
+
+        foreach ($this->items as $item) {
+            if (is_string($item))
+                echo $item;
+            else {
+                if (isset($item['class'])) {
+                    $className = $item['class'];
+                    unset($item['class']);
+
+                    $this->controller->widget($className, $item);
+                }
+            }
+        }
+
+        if ($this->collapse !== false)
+            $this->controller->endWidget();
+
+        echo '</div></div></div>';
+    }
+
+    /**
+     * Returns the navbar container CSS class.
+     * @return string the class
+     */
+    protected function getContainerCssClass() {
+        return $this->fluid ? 'container-fluid' : 'container';
+    }
+
 }

File widgets/TbTabs.php

 <?php
+
 /**
  * TbTabs class file.
  * @author Christoffer Niska <ChristofferNiska@gmail.com>
  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  * @package bootstrap.widgets
  */
-
 Yii::import('bootstrap.widgets.TbMenu');
 
 /**
  * Bootstrap Javascript tabs widget.
  * @see http://twitter.github.com/bootstrap/javascript.html#tabs
  */
-class TbTabs extends CWidget
-{
-	// Tab placements.
-	const PLACEMENT_ABOVE = 'above';
-	const PLACEMENT_BELOW = 'below';
-	const PLACEMENT_LEFT = 'left';
-	const PLACEMENT_RIGHT = 'right';
+class TbTabs extends CWidget {
+    // Tab placements.
 
-	/**
-	 * @var string the type of tabs to display. Defaults to 'tabs'. Valid values are 'tabs' and 'pills'.
-	 * Please not that Javascript pills are not fully supported in Bootstrap yet!
-	 * @see TbMenu::$type
-	 */
-	public $type = TbMenu::TYPE_TABS;
-	/**
-	 * @var string the placement of the tabs.
-	 * Valid values are 'above', 'below', 'left' and 'right'.
-	 */
-	public $placement;
-	/**
-	 * @var array the tab configuration.
-	 */
-	public $tabs = array();
-	/**
-	 * @var boolean whether to encode item labels.
-	 */
-	public $encodeLabel = true;
-	/**
-	 * @var string[] the Javascript event handlers.
-	 */
-	public $events = array();
-	/**
-	 * @var array the HTML attributes for the widget container.
-	 */
-	public $htmlOptions = array();
+    const PLACEMENT_ABOVE = 'above';
+    const PLACEMENT_BELOW = 'below';
+    const PLACEMENT_LEFT = 'left';
+    const PLACEMENT_RIGHT = 'right';
 
-	/**
-	 * Initializes the widget.
-	 */
-	public function init()
-	{
-		if (!isset($this->htmlOptions['id']))
-			$this->htmlOptions['id'] = $this->getId();
+    /**
+     * @var string the type of tabs to display. Defaults to 'tabs'. Valid values are 'tabs' and 'pills'.
+     * Please not that Javascript pills are not fully supported in Bootstrap yet!
+     * @see TbMenu::$type
+     */
+    public $type = TbMenu::TYPE_TABS;
 
-		$classes = array();
+    /**
+     * @var string the placement of the tabs.
+     * Valid values are 'above', 'below', 'left' and 'right'.
+     */
+    public $placement;
 
-		$validPlacements = array(self::PLACEMENT_ABOVE, self::PLACEMENT_BELOW, self::PLACEMENT_LEFT, self::PLACEMENT_RIGHT);
+    /**
+     * @var array the tab configuration.
+     */
+    public $tabs = array();
 
-		if (isset($this->placement) && in_array($this->placement, $validPlacements))
-			$classes[] = 'tabs-'.$this->placement;
+    /**
+     * @var boolean whether to encode item labels.
+     */
+    public $encodeLabel = true;
 
-		if (!empty($classes))
-		{
-			$classes = implode(' ', $classes);
-			if (isset($this->htmlOptions['class']))
-				$this->htmlOptions['class'] .= ' '.$classes;
-			else
-				$this->htmlOptions['class'] = $classes;
-		}
-	}
+    /**
+     * @var string[] the Javascript event handlers.
+     */
+    public $events = array();
 
-	/**
-	 * Run this widget.
-	 */
-	public function run()
-	{
-		$id = $this->id;
-		$content = array();
-		$items = $this->normalizeTabs($this->tabs, $content);
+    /**
+     * @var array the HTML attributes for the widget container.
+     */
+    public $htmlOptions = array();
 
-		ob_start();
-		$this->controller->widget('bootstrap.widgets.TbMenu', array(
-			'type'=>$this->type,
-			'encodeLabel'=>$this->encodeLabel,
-			'items'=>$items,
-		));
-		$tabs = ob_get_clean();
+    /**
+     * Initializes the widget.
+     */
+    public function init() {
+        if (!isset($this->htmlOptions['id']))
+            $this->htmlOptions['id'] = $this->getId();
 
-		ob_start();
-		echo '<div class="tab-content">';
-		echo implode('', $content);
-		echo '</div>';
-		$content = ob_get_clean();
+        $classes = array();
 
-		echo CHtml::openTag('div', $this->htmlOptions);
-		echo $this->placement === self::PLACEMENT_BELOW ? $content.$tabs : $tabs.$content;
-		echo '</div>';
+        $validPlacements = array(self::PLACEMENT_ABOVE, self::PLACEMENT_BELOW, self::PLACEMENT_LEFT, self::PLACEMENT_RIGHT);
 
-		/** @var CClientScript $cs */
-		$cs = Yii::app()->getClientScript();
-		$cs->registerScript(__CLASS__.'#'.$id, "jQuery('#{$id}').tab('show');");
+        if (isset($this->placement) && in_array($this->placement, $validPlacements))
+            $classes[] = 'tabs-' . $this->placement;
 
-		foreach ($this->events as $name => $handler)
-		{
-			$handler = CJavaScript::encode($handler);
-			$cs->registerScript(__CLASS__.'#'.$id.'_'.$name, "jQuery('#{$id}').on('{$name}', {$handler});");
-		}
-	}
+        if (!empty($classes)) {
+            $classes = implode(' ', $classes);
+            if (isset($this->htmlOptions['class']))
+                $this->htmlOptions['class'] .= ' ' . $classes;
+            else
+                $this->htmlOptions['class'] = $classes;
+        }
+    }
 
-	/**
-	 * Normalizes the tab configuration.
-	 * @param array $tabs the tab configuration
-	 * @param array $panes a reference to the panes array
-	 * @param integer $i the current index
-	 * @return array the items
-	 */
-	protected function normalizeTabs($tabs, &$panes, &$i = 0)
-	{
-		$id = $this->getId();
-		$items = array();
+    /**
+     * Run this widget.
+     */
+    public function run() {
+        $id = $this->id;
+        $content = array();
+        $items = $this->normalizeTabs($this->tabs, $content);
 
-		foreach ($tabs as $tab)
-		{
-			$item = $tab;
+        ob_start();
+        $this->controller->widget('bootstrap.widgets.TbMenu', array(
+            'type' => $this->type,
+            'encodeLabel' => $this->encodeLabel,
+            'items' => $items,
+        ));
+        $tabs = ob_get_clean();
 
-			if (isset($item['visible']) && $item['visible'] === false)
-				continue;
+        ob_start();
+        echo '<div class="tab-content">';
+        echo implode('', $content);
+        echo '</div>';
+        $content = ob_get_clean();
 
-			if (!isset($item['itemOptions']))
-				$item['itemOptions'] = array();
+        echo CHtml::openTag('div', $this->htmlOptions);
+        echo $this->placement === self::PLACEMENT_BELOW ? $content . $tabs : $tabs . $content;
+        echo '</div>';
 
-			$item['linkOptions']['data-toggle'] = 'tab';
+        /** @var CClientScript $cs */
+        $cs = Yii::app()->getClientScript();
+        $cs->registerScript(__CLASS__ . '#' . $id, "jQuery('#{$id}').tab('show');");
 
-			if (isset($tab['items']))
-				$item['items'] = $this->normalizeTabs($item['items'], $panes, $i);
-			else
-			{
-				if (!isset($item['id']))
-					$item['id'] = $id.'_tab_'.($i + 1);
+        foreach ($this->events as $name => $handler) {
+            $handler = CJavaScript::encode($handler);
+            $cs->registerScript(__CLASS__ . '#' . $id . '_' . $name, "jQuery('#{$id}').on('{$name}', {$handler});");
+        }
+    }
 
-				$item['url'] = '#'.$item['id'];
+    /**
+     * Normalizes the tab configuration.
+     * @param array $tabs the tab configuration
+     * @param array $panes a reference to the panes array
+     * @param integer $i the current index
+     * @return array the items
+     */
+    protected function normalizeTabs($tabs, &$panes, &$i = 0) {
+        $id = $this->getId();
+        $items = array();
 
-				if (!isset($item['content']))
-					$item['content'] = '';
+        foreach ($tabs as $tab) {
+            $item = $tab;
 
-				$content = $item['content'];
-				unset($item['content']);
+            if (isset($item['visible']) && $item['visible'] === false)
+                continue;
 
-				if (!isset($item['paneOptions']))
-					$item['paneOptions'] = array();
+            if (!isset($item['itemOptions']))
+                $item['itemOptions'] = array();
 
-				$paneOptions = $item['paneOptions'];
-				unset($item['paneOptions']);
+            $item['linkOptions']['data-toggle'] = 'tab';
 
-				$paneOptions['id'] = $item['id'];
+            if (isset($tab['items']))
+                $item['items'] = $this->normalizeTabs($item['items'], $panes, $i);
+            else {
+                if (!isset($item['id']))
+                    $item['id'] = $id . '_tab_' . ($i + 1);
 
-				$classes = array('tab-pane fade');
+                $item['url'] = '#' . $item['id'];
 
-				if (isset($item['active']) && $item['active'])
-					$classes[] = 'active in';
+                if (!isset($item['content']))
+                    $item['content'] = '';
 
-				$classes = implode(' ', $classes);
-				if (isset($paneOptions['class']))
-					$paneOptions['class'] .= ' '.$classes;
-				else
-					$paneOptions['class'] = $classes;
+                $content = $item['content'];
+                unset($item['content']);
 
-				$panes[] = CHtml::tag('div', $paneOptions, $content);
+                if (!isset($item['paneOptions']))
+                    $item['paneOptions'] = array();
 
-				$i++; // increment the tab-index
-			}
+                $paneOptions = $item['paneOptions'];
+                unset($item['paneOptions']);
 
-			$items[] = $item;
-		}
+                $paneOptions['id'] = $item['id'];
 
-		return $items;
-	}
+                $classes = array('tab-pane');
+
+                if (isset($item['active']) && $item['active'])
+                    $classes[] = 'active in';
+
+                $classes = implode(' ', $classes);
+                if (isset($paneOptions['class']))
+                    $paneOptions['class'] .= ' ' . $classes;
+                else
+                    $paneOptions['class'] = $classes;
+
+                $panes[] = CHtml::tag('div', $paneOptions, $content);
+
+                $i++; // increment the tab-index
+            }
+
+            $items[] = $item;
+        }
+
+        return $items;
+    }
+
 }