Skip to content

Commit

Permalink
Initial release
Browse files Browse the repository at this point in the history
  • Loading branch information
kartik-v committed Nov 9, 2014
1 parent 06a2681 commit 02ee4f1
Show file tree
Hide file tree
Showing 10 changed files with 484 additions and 1 deletion.
7 changes: 7 additions & 0 deletions CHANGE.md
@@ -0,0 +1,7 @@
version 1.0.0
=============

**Date:** 08-Nov-2014

- Initial release
- Sub repo split from [yii2-widgets](https://github.com/kartik-v/yii2-widgets)
28 changes: 28 additions & 0 deletions LICENSE.md
@@ -0,0 +1,28 @@
Copyright (c) 2014, Kartik Visweswaran
Krajee.com
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

* Neither the names of Kartik Visweswaran or Krajee nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 changes: 59 additions & 1 deletion README.md
@@ -1,4 +1,62 @@
yii2-widget-sidenav
===================

An enhanced side navigation menu styled for bootstrap (sub repo split from yii2-widgets)
This widget is a collapsible side navigation menu built to seamlessly work with Bootstrap framework. It is built over Bootstrap [stacked nav](http://getbootstrap.com/components/#nav-pills) component. This widget class extends the [Yii Menu widget](https://github.com/yiisoft/yii2/blob/master/framework/widgets/Menu.php). Upto 3 levels of submenus are by default supported by the CSS styles to balance performance and useability. You can choose to extend it to more or less levels by customizing the [CSS](https://github.com/kartik-v/yii2-widgets/blob/master/assets/css/sidenav.css).

> NOTE: This extension is a sub repo split of [yii2-widgets](https://github.com/kartik-v/yii2-widgets). The split has been done since 08-Nov-2014 to allow developers to install this specific widget in isolation if needed. One can also use the extension the previous way with the whole suite of [yii2-widgets](http://demos.krajee.com/widgets).
## Installation

The preferred way to install this extension is through [composer](http://getcomposer.org/download/). Check the [composer.json](https://github.com/kartik-v/yii2-widget-sidenav/blob/master/composer.json) for this extension's requirements and dependencies. Read this [web tip /wiki](http://webtips.krajee.com/setting-composer-minimum-stability-application/) on setting the `minimum-stability` settings for your application's composer.json.

To install, either run

```
$ php composer.phar require kartik-v/yii2-widget-sidenav "*"
```

or add

```
"kartik-v/yii2-widget-sidenav": "*"
```

to the ```require``` section of your `composer.json` file.

## Latest Release

> NOTE: The latest version of the module is v1.0.0 released on 08-Nov-2014. Refer the [CHANGE LOG](https://github.com/kartik-v/yii2-widget-sidenav/blob/master/CHANGE.md) for details.
## Demo

You can refer detailed [documentation and demos](http://demos.krajee.com/widget-details/sidenav) on usage of the extension.

## Usage

```php
use kartik\sidenav\SideNav;

echo SideNav::widget([
'type' => SideNav::TYPE_DEFAULT,
'heading' => 'Options',
'items' => [
[
'url' => '#',
'label' => 'Home',
'icon' => 'home'
],
[
'label' => 'Help',
'icon' => 'question-sign',
'items' => [
['label' => 'About', 'icon'=>'info-sign', 'url'=>'#'],
['label' => 'Contact', 'icon'=>'phone', 'url'=>'#'],
],
],
],
]);
```

## License

**yii2-widget-sidenav** is released under the BSD 3-Clause License. See the bundled `LICENSE.md` for details.
244 changes: 244 additions & 0 deletions SideNav.php
@@ -0,0 +1,244 @@
<?php

/**
* @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2014
* @package yii2-widgets
* @subpackage yii2-widget-sidenav
* @version 1.0.0
*/

namespace kartik\sidenav;

use Yii;
use yii\base\InvalidConfigException;
use yii\helpers\Html;
use yii\helpers\Url;
use yii\helpers\ArrayHelper;

/**
* A custom extended side navigation menu extending Yii Menu
*
* For example:
*
* ```php
* echo SideNav::widget([
* 'items' => [
* [
* 'url' => ['/site/index'],
* 'label' => 'Home',
* 'icon' => 'home'
* ],
* [
* 'url' => ['/site/about'],
* 'label' => 'About',
* 'icon' => 'info-sign',
* 'items' => [
* ['url' => '#', 'label' => 'Item 1'],
* ['url' => '#', 'label' => 'Item 2'],
* ],
* ],
* ],
* ]);
* ```
*
* @author Kartik Visweswaran <kartikv2@gmail.com>
*/
class SideNav extends \yii\widgets\Menu
{

/**
* Panel contextual states
*/
const TYPE_DEFAULT = 'default';
const TYPE_PRIMARY = 'primary';
const TYPE_INFO = 'info';
const TYPE_SUCCESS = 'success';
const TYPE_DANGER = 'danger';
const TYPE_WARNING = 'warning';

/**
* @var string the menu container style. This is one of the bootstrap panel
* contextual state classes. Defaults to `default`.
* @see http://getbootstrap.com/components/#panels
*/
public $type = self::TYPE_DEFAULT;

/**
* @var string prefix for the icon in [[items]]. This string will be prepended
* before the icon name to get the icon CSS class. This defaults to `glyphicon glyphicon-`
* for usage with glyphicons available with Bootstrap.
*/
public $iconPrefix = 'glyphicon glyphicon-';

/**
* @var array string/boolean the sidenav heading. This is not HTML encoded
* When set to false or null, no heading container will be displayed.
*/
public $heading = false;

/**
* @var array options for the sidenav heading
*/
public $headingOptions = [];

/**
* @var array options for the sidenav container
*/
public $containerOptions = [];

/**
* @var string indicator for a menu sub-item
*/
public $indItem = '&raquo; ';

/**
* @var string indicator for a opened sub-menu
*/
public $indMenuOpen = '<i class="indicator glyphicon glyphicon-chevron-down"></i>';

/**
* @var string indicator for a closed sub-menu
*/
public $indMenuClose = '<i class="indicator glyphicon glyphicon-chevron-right"></i>';

/**
* @var array list of sidenav menu items. Each menu item should be an array of the following structure:
*
* - label: string, optional, specifies the menu item label. When [[encodeLabels]] is true, the label
* will be HTML-encoded. If the label is not specified, an empty string will be used.
* - icon: string, optional, specifies the glyphicon name to be placed before label.
* - url: string or array, optional, specifies the URL of the menu item. It will be processed by [[Url::to]].
* When this is set, the actual menu item content will be generated using [[linkTemplate]];
* - visible: boolean, optional, whether this menu item is visible. Defaults to true.
* - items: array, optional, specifies the sub-menu items. Its format is the same as the parent items.
* - active: boolean, optional, whether this menu item is in active state (currently selected).
* If a menu item is active, its CSS class will be appended with [[activeCssClass]].
* If this option is not set, the menu item will be set active automatically when the current request
* is triggered by [[url]]. For more details, please refer to [[isItemActive()]].
* - template: string, optional, the template used to render the content of this menu item.
* The token `{url}` will be replaced by the URL associated with this menu item,
* and the token `{label}` will be replaced by the label of the menu item.
* If this option is not set, [[linkTemplate]] will be used instead.
* - options: array, optional, the HTML attributes for the menu item tag.
*
*/
public $items;

/**
* Allowed panel stypes
*/
private static $_validTypes = [
self::TYPE_DEFAULT,
self::TYPE_PRIMARY,
self::TYPE_INFO,
self::TYPE_SUCCESS,
self::TYPE_DANGER,
self::TYPE_WARNING,
];

public function init()
{
parent::init();
SideNavAsset::register($this->getView());
$this->activateParents = true;
$this->submenuTemplate = "\n<ul class='nav nav-pills nav-stacked'>\n{items}\n</ul>\n";
$this->linkTemplate = '<a href="{url}">{icon}{label}</a>';
$this->labelTemplate = '{icon}{label}';
$this->markTopItems();
Html::addCssClass($this->options, 'nav nav-pills nav-stacked kv-sidenav');
}

/**
* Renders the side navigation menu.
* with the heading and panel containers
*/
public function run()
{
$heading = '';
if (isset($this->heading) && $this->heading != '') {
Html::addCssClass($this->headingOptions, 'panel-heading');
$heading = Html::tag('div', '<h3 class="panel-title">' . $this->heading . '</h3>', $this->headingOptions);
}
$body = Html::tag('div', $this->renderMenu(), ['class' => 'table']);
$type = in_array($this->type, self::$_validTypes) ? $this->type : self::TYPE_DEFAULT;
Html::addCssClass($this->containerOptions, "panel panel-{$type}");
echo Html::tag('div', $heading . $body, $this->containerOptions);
}

/**
* Renders the main menu
*/
protected function renderMenu()
{
if ($this->route === null && Yii::$app->controller !== null) {
$this->route = Yii::$app->controller->getRoute();
}
if ($this->params === null) {
$this->params = $_GET;
}
$items = $this->normalizeItems($this->items, $hasActiveChild);
$options = $this->options;
$tag = ArrayHelper::remove($options, 'tag', 'ul');

return Html::tag($tag, $this->renderItems($items), $options);
}

/**
* Marks each topmost level item which is not a submenu
*/
protected function markTopItems()
{
$items = [];
foreach ($this->items as $item) {
if (empty($item['items'])) {
$item['top'] = true;
}
$items[] = $item;
}
$this->items = $items;
}

/**
* Renders the content of a side navigation menu item.
*
* @param array $item the menu item to be rendered. Please refer to [[items]] to see what data might be in the item.
* @return string the rendering result
* @throws InvalidConfigException
*/
protected function renderItem($item)
{
$this->validateItems($item);
$template = ArrayHelper::getValue($item, 'template', $this->linkTemplate);
$url = Url::to(ArrayHelper::getValue($item, 'url', '#'));
if (empty($item['top'])) {
if (empty($item['items'])) {
$template = str_replace('{icon}', $this->indItem . '{icon}', $template);
} else {
$template = isset($item['template']) ? $item['template'] :'<a href="{url}" class="kv-toggle">{icon}{label}</a>';
$openOptions = ($item['active']) ? ['class' => 'opened'] : ['class' => 'opened', 'style' => 'display:none'];
$closeOptions = ($item['active']) ? ['class' => 'closed', 'style' => 'display:none'] : ['class' => 'closed'];
$indicator = Html::tag('span', $this->indMenuOpen, $openOptions) . Html::tag('span', $this->indMenuClose, $closeOptions);
$template = str_replace('{icon}', $indicator . '{icon}', $template);
}
}
$icon = empty($item['icon']) ? '' : '<span class="' . $this->iconPrefix . $item['icon'] . '"></span> &nbsp;';
unset($item['icon'], $item['top']);
return strtr($template, [
'{url}' => $url,
'{label}' => $item['label'],
'{icon}' => $icon
]);
}

/**
* Validates each item for a valid label and url.
*
* @throws InvalidConfigException
*/
protected function validateItems($item)
{
if (!isset($item['label'])) {
throw new InvalidConfigException("The 'label' option is required.");
}
}
}
27 changes: 27 additions & 0 deletions SideNavAsset.php
@@ -0,0 +1,27 @@
<?php

/**
* @copyright Copyright &copy; Kartik Visweswaran, Krajee.com, 2014
* @package yii2-widgets
* @subpackage yii2-widget-sidenav
* @version 1.0.0
*/

namespace kartik\sidenav;

/**
* Asset bundle for SideNav Widget
*
* @author Kartik Visweswaran <kartikv2@gmail.com>
* @since 1.0
*/
class SideNavAsset extends \kartik\base\AssetBundle
{
public function init()
{
$this->setSourcePath(__DIR__ . '/assets');
$this->setupAssets('css', ['css/sidenav']);
$this->setupAssets('js', ['js/sidenav']);
parent::init();
}
}

0 comments on commit 02ee4f1

Please sign in to comment.