From cc9b175c5f9637e194b86f831857f1181a502d8f Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Tue, 28 May 2013 16:24:37 +0200 Subject: [PATCH 1/5] Added Nav widget closes #367 --- framework/yii/bootstrap/Nav.php | 137 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 framework/yii/bootstrap/Nav.php diff --git a/framework/yii/bootstrap/Nav.php b/framework/yii/bootstrap/Nav.php new file mode 100644 index 0000000..f373961 --- /dev/null +++ b/framework/yii/bootstrap/Nav.php @@ -0,0 +1,137 @@ + array( + * array( + * 'label' => 'Home', + * 'url' => '/', + * 'options' => array(...), + * 'active' => true, + * ), + * array( + * 'label' => 'Dropdown', + * 'dropdown' => array( + * array( + * 'label' => 'DropdownA', + * 'url' => '#', + * ), + * array( + * 'label' => 'DropdownB', + * 'url' => '#', + * ), + * ), + * ), + * ), + * )); + * ``` + * + * @see http://twitter.github.io/bootstrap/components.html#nav + * @author Antonio Ramirez + * @since 2.0 + */ +class Nav extends Widget +{ + /** + * @var array list of items in the nav widget. Each array element represents a single + * menu item with the following structure: + * + * ```php + * array( + * // required, the menu item label. + * 'label' => 'Nav item label', + * // optional, the URL of the menu item. Defaults to "#" + * 'url'=> '#', + * // optional, the HTML options of the URL. + * 'urlOptions' => array(...), + * // optional the HTML attributes of the item container (LI). + * 'options' => array(...), + * // optional, an array of [[Dropdown]] widget items so to display a dropdown menu on the tab header. + * // important: there is an issue with sub-dropdown menus, and as of 3.0, bootstrap won't support sub-dropdown + * // @see https://github.com/twitter/bootstrap/issues/5050#issuecomment-11741727 + * 'dropdown'=> array(...) + * ) + * ``` + * + * Optionally, you can also use a plain string instead of an array element. + */ + public $items = array(); + + + /** + * Initializes the widget. + */ + public function init() + { + $this->addCssClass($this->options, 'nav'); + } + + /** + * Renders the widget. + */ + public function run() + { + echo $this->renderItems(); + } + + /** + * Renders widget items. + */ + public function renderItems() + { + $items = array(); + foreach ($this->items as $item) { + $items[] = $this->renderItem($item); + } + + return Html::tag('ul', implode("\n", $items), $this->options); + } + + /** + * Renders a widget's item. + * @param mixed $item the item to render. + * @return string the rendering result. + * @throws InvalidConfigException + */ + public function renderItem($item) + { + if (is_string($item)) { + return $item; + } + if (!isset($item['label'])) { + throw new InvalidConfigException("The 'label' option is required."); + } + $label = $item['label']; + $url = ArrayHelper::getValue($item, 'url', '#'); + $options = ArrayHelper::getValue($item, 'options', array()); + $urlOptions = ArrayHelper::getValue($item, 'urlOptions', array()); + $dropdown = null; + + // does it has a dropdown widget? + if (isset($item['dropdown'])) { + $urlOptions['data-toggle'] = 'dropdown'; + $this->addCssClass($options, 'dropdown'); + $this->addCssClass($urlOptions, 'dropdown-toggle'); + $label .= ' ' . Html::tag('b', '', array('class' => 'caret')); + $dropdown = Dropdown::widget(array('items' => $item['dropdown'], 'clientOptions' => false)); + } + + return Html::tag('li', Html::a($label, $url, $urlOptions) . $dropdown, $options); + } +} \ No newline at end of file From 70f1d4169996c1259bfa02d8627c2f5dd0d34c0f Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Tue, 28 May 2013 16:27:33 +0200 Subject: [PATCH 2/5] Added NavBar widget closes #437 --- framework/yii/bootstrap/NavBar.php | 169 +++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 framework/yii/bootstrap/NavBar.php diff --git a/framework/yii/bootstrap/NavBar.php b/framework/yii/bootstrap/NavBar.php new file mode 100644 index 0000000..1ed5a9a --- /dev/null +++ b/framework/yii/bootstrap/NavBar.php @@ -0,0 +1,169 @@ + array( + * // a Nav widget + * array( + * // defaults to Nav anyway. + * 'class' => 'yii\bootstrap\Nav', + * // widget configuration + * 'options' => array( + * 'items' => array( + * array( + * 'label' => 'Home', + * 'url' => '/', + * 'options' => array('class' => 'active'), + * ), + * array( + * 'label' => 'Dropdown', + * // configure a dropdown menu + * 'dropdown' => array( + * array( + * 'label' => 'DropdownA', + * 'url' => '#', + * ), + * array( + * 'label' => 'DropdownB', + * 'url' => '#' + * ), + * ) + * ), + * ) + * ), + * ), + * // you can also use strings + * '', + * ), + * )); + * ``` + * + * @see http://twitter.github.io/bootstrap/components.html#navbar + * @author Antonio Ramirez + * @since 2.0 + */ +class NavBar extends Widget +{ + public $brand; + /** + * @var array list of menu items in the navbar widget. Each array element represents a single + * menu item with the following structure: + * + * ```php + * array( + * // optional, the menu item class type of the widget to render. Defaults to "Nav" widget. + * 'class' => 'Menu item class type', + * // required, the configuration options of the widget. + * 'options'=> array(...), + * ), + * // optionally, you can pass a string + * '', + * ``` + * + * Optionally, you can also use a plain string instead of an array element. + */ + public $items = array(); + + + /** + * Initializes the widget. + */ + public function init() + { + parent::init(); + $this->addCssClass($this->options, 'navbar'); + } + + /** + * Renders the widget. + */ + public function run() + { + echo Html::beginTag('div', $this->options); + echo $this->renderItems(); + echo Html::endTag('div'); + } + + /** + * @return string the rendering items. + */ + protected function renderItems() + { + $items = array(); + + foreach ($this->items as $item) { + $items[] = $this->renderItem($item); + } + $contents =implode("\n", $items); + if (self::$responsive === true) { + $this->getView()->registerAssetBundle('yii/bootstrap/collapse'); + $contents = + Html::tag('div', + $this->renderToggleButton() . + $this->brand . "\n" . + Html::tag('div', $contents, array('class' => 'nav-collapse collapse navbar-collapse')), + array('class' => 'container')); + + } else { + $contents = $this->brand . "\n" . $contents; + } + return Html::tag('div', $contents, array('class' => 'navbar-inner')); + } + + /** + * Renders a item. The item can be a string, a custom class or a Nav widget (defaults if no class specified. + * @param mixed $item the item to render. If array, it is assumed the configuration of a widget being `class` + * required and if not specified, then defaults to `yii\bootstrap\Nav`. + * @return string the rendering result. + * @throws InvalidConfigException + */ + protected function renderItem($item) + { + if (is_string($item)) { + return $item; + } + $config = ArrayHelper::getValue($item, 'options', array()); + $config['class'] = ArrayHelper::getValue($item, 'class', 'yii\bootstrap\Nav'); + $widget = \Yii::createObject($config); + ob_start(); + $widget->run(); + return ob_get_clean(); + } + + /** + * Renders collapsible toggle button. + * @return string the rendering toggle button. + */ + protected function renderToggleButton() + { + $items = array(); + for ($i = 0; $i < 3; $i++) { + $items[] = Html::tag('span', '', array('class' => 'icon-bar')); + } + return Html::tag('a', implode("\n", $items), array( + 'class' => 'btn btn-navbar', + 'data-toggle' => 'collapse', + 'data-target' => 'div.navbar-collapse', + )) . "\n"; + } +} \ No newline at end of file From cbb33bd164b21f504ceb461ec547604061627da3 Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Wed, 29 May 2013 10:54:01 +0200 Subject: [PATCH 3/5] refactored based on comments (2nd round) --- framework/yii/bootstrap/Nav.php | 64 +++++++++++++++++++---------------- framework/yii/bootstrap/NavBar.php | 68 ++++++++++++++++++++++++++------------ 2 files changed, 81 insertions(+), 51 deletions(-) diff --git a/framework/yii/bootstrap/Nav.php b/framework/yii/bootstrap/Nav.php index f373961..c247433 100644 --- a/framework/yii/bootstrap/Nav.php +++ b/framework/yii/bootstrap/Nav.php @@ -8,7 +8,7 @@ namespace yii\bootstrap; use yii\base\InvalidConfigException; -use yii\helpers\base\ArrayHelper; +use yii\helpers\ArrayHelper; use yii\helpers\Html; /** @@ -22,12 +22,12 @@ use yii\helpers\Html; * array( * 'label' => 'Home', * 'url' => '/', - * 'options' => array(...), + * 'linkOptions' => array(...), * 'active' => true, * ), * array( * 'label' => 'Dropdown', - * 'dropdown' => array( + * 'items' => array( * array( * 'label' => 'DropdownA', * 'url' => '#', @@ -52,26 +52,25 @@ class Nav extends Widget * @var array list of items in the nav widget. Each array element represents a single * menu item with the following structure: * - * ```php - * array( - * // required, the menu item label. - * 'label' => 'Nav item label', - * // optional, the URL of the menu item. Defaults to "#" - * 'url'=> '#', - * // optional, the HTML options of the URL. - * 'urlOptions' => array(...), - * // optional the HTML attributes of the item container (LI). - * 'options' => array(...), - * // optional, an array of [[Dropdown]] widget items so to display a dropdown menu on the tab header. - * // important: there is an issue with sub-dropdown menus, and as of 3.0, bootstrap won't support sub-dropdown - * // @see https://github.com/twitter/bootstrap/issues/5050#issuecomment-11741727 - * 'dropdown'=> array(...) - * ) - * ``` + * - label: string, required, the nav item label. + * - url: optional, the item's URL. Defaults to "#". + * - linkOptions: array, optional, the HTML attributes of the item's link. + * - options: array, optional, the HTML attributes of the item container (LI). + * - active: boolean, optional, whether the item should be on active state or not. + * - items: array, optional, the configuration of specify the item's dropdown menu. You can optionally set this as + * a string (ie. `'items'=> Dropdown::widget(array(...))` + * - important: there is an issue with sub-dropdown menus, and as of 3.0, bootstrap won't support sub-dropdown. * - * Optionally, you can also use a plain string instead of an array element. + * **Note:** Optionally, you can also use a plain string instead of an array element. + * + * @see https://github.com/twitter/bootstrap/issues/5050#issuecomment-11741727 + * @see [[Dropdown]] */ public $items = array(); + /** + * @var boolean whether the nav items labels should be HTML-encoded. + */ + public $encodeLabels = true; /** @@ -79,6 +78,7 @@ class Nav extends Widget */ public function init() { + parent::init(); $this->addCssClass($this->options, 'nav'); } @@ -88,6 +88,7 @@ class Nav extends Widget public function run() { echo $this->renderItems(); + $this->registerPlugin('dropdown'); } /** @@ -117,21 +118,26 @@ class Nav extends Widget if (!isset($item['label'])) { throw new InvalidConfigException("The 'label' option is required."); } - $label = $item['label']; - $url = ArrayHelper::getValue($item, 'url', '#'); + $label = $this->encodeLabels ? Html::encode($item['label']) : $item['label']; $options = ArrayHelper::getValue($item, 'options', array()); - $urlOptions = ArrayHelper::getValue($item, 'urlOptions', array()); - $dropdown = null; + $dropdown = ArrayHelper::getValue($item, 'items'); + $url = Html::url(ArrayHelper::getValue($item, 'url', '#')); + $linkOptions = ArrayHelper::getValue($item, 'linkOptions', array()); + + if(ArrayHelper::getValue($item, 'active')) { + $this->addCssClass($options, 'active'); + } - // does it has a dropdown widget? - if (isset($item['dropdown'])) { - $urlOptions['data-toggle'] = 'dropdown'; + if ($dropdown !== null) { + $linkOptions['data-toggle'] = 'dropdown'; $this->addCssClass($options, 'dropdown'); $this->addCssClass($urlOptions, 'dropdown-toggle'); $label .= ' ' . Html::tag('b', '', array('class' => 'caret')); - $dropdown = Dropdown::widget(array('items' => $item['dropdown'], 'clientOptions' => false)); + $dropdown = is_string($dropdown) + ? $dropdown + : Dropdown::widget(array('items' => $item['items'], 'clientOptions' => false)); } - return Html::tag('li', Html::a($label, $url, $urlOptions) . $dropdown, $options); + return Html::tag('li', Html::a($label, $url, $linkOptions) . $dropdown, $options); } } \ No newline at end of file diff --git a/framework/yii/bootstrap/NavBar.php b/framework/yii/bootstrap/NavBar.php index 1ed5a9a..cbcd2d3 100644 --- a/framework/yii/bootstrap/NavBar.php +++ b/framework/yii/bootstrap/NavBar.php @@ -8,7 +8,7 @@ namespace yii\bootstrap; use yii\base\InvalidConfigException; -use yii\helpers\base\ArrayHelper; +use yii\helpers\ArrayHelper; use yii\helpers\Html; /** @@ -18,6 +18,7 @@ use yii\helpers\Html; * * ```php * echo NavBar::widget(array( + * 'brandLabel' => 'NavBar Test', * 'items' => array( * // a Nav widget * array( @@ -33,17 +34,18 @@ use yii\helpers\Html; * ), * array( * 'label' => 'Dropdown', - * // configure a dropdown menu - * 'dropdown' => array( - * array( - * 'label' => 'DropdownA', - * 'url' => '#', - * ), - * array( - * 'label' => 'DropdownB', - * 'url' => '#' - * ), - * ) + * 'content' => new Dropdown(array( + * 'items' => array( + * array( + * 'label' => 'DropdownA', + * 'url' => '#', + * ), + * array( + * 'label' => 'DropdownB', + * 'url' => '#' + * ), + * ) + * ), * ), * ) * ), @@ -62,7 +64,20 @@ use yii\helpers\Html; */ class NavBar extends Widget { - public $brand; + /** + * @var string the text of the brand. + * @see http://twitter.github.io/bootstrap/components.html#navbar + */ + public $brandLabel; + /** + * @param array|string $url the URL for the brand's hyperlink tag. This parameter will be processed by [[Html::url()]] + * and will be used for the "href" attribute of the brand link. Defaults to site root. + */ + public $brandRoute = '/'; + /** + * @var array the HTML attributes of the brand link. + */ + public $brandOptions = array(); /** * @var array list of menu items in the navbar widget. Each array element represents a single * menu item with the following structure: @@ -83,6 +98,10 @@ class NavBar extends Widget * Optionally, you can also use a plain string instead of an array element. */ public $items = array(); + /** + * @var string the generated brand url if specified by [[brandLabel]] + */ + protected $brand; /** @@ -91,7 +110,10 @@ class NavBar extends Widget public function init() { parent::init(); + $this->clientOptions = false; $this->addCssClass($this->options, 'navbar'); + $this->addCssClass($this->brandOptions, 'brand'); + $this->brand = Html::a($this->brandLabel, $this->brandRoute, $this->brandOptions); } /** @@ -102,19 +124,20 @@ class NavBar extends Widget echo Html::beginTag('div', $this->options); echo $this->renderItems(); echo Html::endTag('div'); + $this->getView()->registerAssetBundle('yii/bootstrap'); } /** + * Renders the items. * @return string the rendering items. */ protected function renderItems() { $items = array(); - foreach ($this->items as $item) { $items[] = $this->renderItem($item); } - $contents =implode("\n", $items); + $contents = implode("\n", $items); if (self::$responsive === true) { $this->getView()->registerAssetBundle('yii/bootstrap/collapse'); $contents = @@ -127,6 +150,7 @@ class NavBar extends Widget } else { $contents = $this->brand . "\n" . $contents; } + return Html::tag('div', $contents, array('class' => 'navbar-inner')); } @@ -143,11 +167,11 @@ class NavBar extends Widget return $item; } $config = ArrayHelper::getValue($item, 'options', array()); - $config['class'] = ArrayHelper::getValue($item, 'class', 'yii\bootstrap\Nav'); - $widget = \Yii::createObject($config); - ob_start(); - $widget->run(); - return ob_get_clean(); + $config['clientOptions'] = false; + + $class = ArrayHelper::getValue($item, 'class', 'yii\bootstrap\Nav'); + + return $class::widget($config); } /** @@ -160,10 +184,10 @@ class NavBar extends Widget for ($i = 0; $i < 3; $i++) { $items[] = Html::tag('span', '', array('class' => 'icon-bar')); } - return Html::tag('a', implode("\n", $items), array( + return Html::a(implode("\n", $items), null, array( 'class' => 'btn btn-navbar', 'data-toggle' => 'collapse', 'data-target' => 'div.navbar-collapse', - )) . "\n"; + )); } } \ No newline at end of file From 1e9cc35fd8ce005033668b0eee77d1edbfdccaf8 Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Wed, 29 May 2013 10:54:53 +0200 Subject: [PATCH 4/5] fix namespaces --- framework/yii/bootstrap/Carousel.php | 2 +- framework/yii/bootstrap/Collapse.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/yii/bootstrap/Carousel.php b/framework/yii/bootstrap/Carousel.php index 3d38b54..f8904fa 100644 --- a/framework/yii/bootstrap/Carousel.php +++ b/framework/yii/bootstrap/Carousel.php @@ -8,7 +8,7 @@ namespace yii\bootstrap; use yii\base\InvalidConfigException; -use yii\helpers\base\ArrayHelper; +use yii\helpers\ArrayHelper; use yii\helpers\Html; /** diff --git a/framework/yii/bootstrap/Collapse.php b/framework/yii/bootstrap/Collapse.php index d83df3c..a7929e3 100644 --- a/framework/yii/bootstrap/Collapse.php +++ b/framework/yii/bootstrap/Collapse.php @@ -8,7 +8,7 @@ namespace yii\bootstrap; use yii\base\InvalidConfigException; -use yii\helpers\base\ArrayHelper; +use yii\helpers\ArrayHelper; use yii\helpers\Html; /** From e8d3a7ff9287b683b2248d95f1affd3c45610a34 Mon Sep 17 00:00:00 2001 From: Antonio Ramirez Date: Wed, 29 May 2013 10:58:21 +0200 Subject: [PATCH 5/5] register asset bundle instead --- framework/yii/bootstrap/Nav.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/yii/bootstrap/Nav.php b/framework/yii/bootstrap/Nav.php index c247433..7a29ecd 100644 --- a/framework/yii/bootstrap/Nav.php +++ b/framework/yii/bootstrap/Nav.php @@ -88,7 +88,7 @@ class Nav extends Widget public function run() { echo $this->renderItems(); - $this->registerPlugin('dropdown'); + $this->getView()->registerAssetBundle('yii/bootstrap'); } /**