1 <?php
2 /**
3 * @copyright Copyright © 2amigOS! Consulting Group 2013-
4 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
5 * @package foundation.components
6 * @version 1.0.0
7 */
8 namespace foundation\widgets;
9
10 use foundation\helpers\ArrayHelper;
11 use foundation\helpers\Html;
12 use foundation\helpers\Nav;
13 use foundation\enum\Enum;
14 use foundation\exception\InvalidConfigurationException;
15
16 /**
17 * TopBar widget renders a nav HTML component.
18 *
19 * For example:
20 *
21 * <pre>
22 * echo TopBar::widget(array(
23 * 'leftItems' => array(
24 * array(
25 * 'label' => 'Home',
26 * 'url' => '/',
27 * 'linkOptions' => array(...),
28 * 'active' => true,
29 * ),
30 * array(
31 * 'label' => 'Dropdown',
32 * 'items' => array(
33 * array(
34 * 'label' => 'Dropdown item A',
35 * 'url' => '#',
36 * ),
37 * array(
38 * 'label' => 'Dropdown item B',
39 * 'url' => '#',
40 * ),
41 * ),
42 * ),
43 * ),
44 * 'rightItems' => array(
45 * array(
46 * 'label' => 'I am at right',
47 * 'url' => '/',
48 * 'linkOptions' => array(...),
49 * 'active' => true,
50 * ),
51 * array(
52 * 'label' => 'Dropdown',
53 * 'items' => array(
54 * array(
55 * 'label' => 'Dropdown item A',
56 * 'url' => '#',
57 * ),
58 * array(
59 * 'label' => 'Dropdown item B',
60 * 'url' => '#',
61 * ),
62 * ),
63 * ),
64 * ),
65 * ));
66 * </pre>
67 *
68 * @author Antonio Ramirez <amigo.cobos@gmail.com>
69 * @package foundation\widgets
70 */
71 class TopBar extends base\Widget
72 {
73 /**
74 * @var string $title the menu title
75 */
76 public $title = '';
77 /**
78 * @var string $titleUrl the menu url
79 */
80 public $titleUrl = '#';
81 /**
82 * @var array $titleOptions the HTML-attributes of the title
83 */
84 public $titleOptions = array();
85 /**
86 * @var array list of left menu items in the topbar widget. Each array element represents a single
87 * menu item with the following structure:
88 *
89 * - label: string, required, the nav item label.
90 * - url: optional, the item's URL. Defaults to "#".
91 * - linkOptions: array, optional, the HTML attributes of the item's link.
92 * - options: array, optional, the HTML attributes of the item container (LI).
93 * - active: boolean, optional, whether the item should be on active state or not.
94 * - dropdown: array|string, optional, the items configuration array to render [[Nav::dropdown]],
95 * or a string representing the dropdown menu. Note that Bootstrap does not support sub-dropdown menus.
96 */
97 public $leftItems = array();
98 /**
99 * @var array list of right menu items in the topbar widget. Each array element represents a single
100 * menu item with the following structure:
101 *
102 * - label: string, required, the nav item label.
103 * - url: optional, the item's URL. Defaults to "#".
104 * - linkOptions: array, optional, the HTML attributes of the item's link.
105 * - options: array, optional, the HTML attributes of the item container (LI).
106 * - active: boolean, optional, whether the item should be on active state or not.
107 * - dropdown: array|string, optional, the items configuration array to render [[Nav::dropdown]],
108 * or a string representing the dropdown menu. Note that Bootstrap does not support sub-dropdown menus.
109 */
110 public $rightItems = array();
111 /**
112 * @var bool whether the left|right items should be HTML-encoded
113 */
114 public $encodeLabels = true;
115 /**
116 * @var bool whether to make the bar fixed or not
117 */
118 public $fixed = false;
119 /**
120 * @var bool whether to make the top bar contained to grid.
121 */
122 public $containToGrid = false;
123 /**
124 * @var bool whether to make the top bar sticky. Sticky means that when the navigation its the top of the browser, it
125 * will act like the fixed top bar and stick to the top as users continue to scroll.
126 */
127 public $sticky = false;
128 /**
129 * @var array the HTML-attributes of the layer wrapping the nav tag. If empty, the wrapper wont be displayed.
130 */
131 protected $wrapperOptions = array();
132
133
134 /**
135 * Initializes the widget
136 */
137 public function init()
138 {
139 $this->assets = array(
140 'js' => YII_DEBUG ? 'foundation/foundation.topbar.js' : 'foundation.min.js'
141 );
142
143 Html::addCssClass($this->htmlOptions, Enum::NAV_TOPBAR);
144 if ($this->fixed) {
145 Html::addCssClass($this->htmlOptions, Enum::NAV_FIXED);
146 }
147 if ($this->sticky) {
148 Html::addCssClass($this->htmlOptions, Enum::NAV_STICKY);
149 }
150 if ($this->containToGrid) {
151 Html::addCssClass($this->htmlOptions, Enum::NAV_CONTAINED);
152 }
153
154 parent::init();
155 }
156
157 /**
158 * Renders the widget
159 */
160 public function run()
161 {
162 echo $this->renderNavigation();
163 }
164
165 /**
166 * Renders the navigation
167 */
168 protected function renderNavigation()
169 {
170 $nav = array();
171 if (!empty($this->wrapperOptions)) {
172 $nav[] = \CHtml::openTag('div', $this->wrapperOptions);
173 }
174 $nav[] = \CHtml::openTag('nav', $this->htmlOptions);
175 $nav[] = $this->renderTitle();
176 $nav[] = $this->renderItems();
177 $nav[] = \CHtml::closeTag('nav');
178
179 if (!empty($this->wrapperOptions)) {
180 $nav[] = \CHtml::closeTag('div');
181 }
182 return implode("\n", $nav);
183 }
184
185 /**
186 * Renders the title of navigation
187 * @return string
188 */
189 protected function renderTitle()
190 {
191 $items = array();
192 $title = \CHtml::tag('h1', array(), \CHtml::link($this->title, $this->titleUrl, $this->titleOptions));
193 $items[] = \CHtml::tag('li', array('class' => 'name'), $title);
194 $items[] = \CHtml::tag(
195 'li',
196 array('class' => 'toggle-topbar menu-icon'),
197 \CHtml::link('<span>Menu</span>', '#')
198 );
199 return \CHtml::tag('ul', array('class' => 'title-area'), implode("\n", $items));
200 }
201
202 /**
203 * Renders widget's items.
204 * @return string
205 */
206 protected function renderItems()
207 {
208 $items = array();
209 if (!empty($this->leftItems)) {
210 $tItems = array();
211 foreach ($this->leftItems as $item) {
212 $tItems[] = $this->renderItem($item);
213 }
214 $items[] = \CHtml::openTag('ul', array('class' => Enum::POS_LEFT)) . implode(
215 "\n",
216 $tItems
217 ) . \CHtml::closeTag(
218 'ul'
219 );
220 }
221 if (!empty($this->rightItems)) {
222 $tItems = array();
223 foreach ($this->rightItems as $item) {
224 $tItems[] = $this->renderItem($item);
225 }
226 $items[] = \CHtml::openTag('ul', array('class' => Enum::POS_RIGHT)) . implode(
227 "\n",
228 $tItems
229 ) . \CHtml::closeTag(
230 'ul'
231 );
232 }
233
234 return \CHtml::tag('section', array('class' => 'top-bar-section'), implode("\n", $items), true);
235 }
236
237 /**
238 * Renders a widget's item
239 * @param mixed $item the item to render
240 * @return string the rendering result.
241 * @throws InvalidConfigException
242 */
243 protected function renderItem($item)
244 {
245 if (is_string($item)) {
246 return $item;
247 }
248 if (!isset($item['label'])) {
249 throw new InvalidConfigException("The 'label' option is required.");
250 }
251 $label = $this->encodeLabels ? \CHtml::encode($item['label']) : $item['label'];
252 $options = ArrayHelper::getValue($item, 'options', array());
253 $items = ArrayHelper::getValue($item, 'items');
254 $url = \CHtml::normalizeUrl(ArrayHelper::getValue($item, 'url', '#'));
255 $linkOptions = ArrayHelper::getValue($item, 'linkOptions', array());
256
257 if (ArrayHelper::getValue($item, Enum::STATE_ACTIVE)) {
258 ArrayHelper::addValue('class', Enum::STATE_ACTIVE, $options);
259 }
260
261 if ($items !== null) {
262 Html::addCssClass($options, Enum::DROPDOWN_HAS);
263 if (is_array($items)) {
264 $items = Nav::dropdown($items, $this->encodeLabels);
265 }
266 }
267
268 return \CHtml::tag('li', $options, \CHtml::link($label, $url, $linkOptions) . $items);
269 }
270 }