├── .gitignore
├── ColorBlueAsset.php
├── ColorBrownAsset.php
├── ColorDefaultAsset.php
├── ColorGrayAsset.php
├── ColorLightAsset.php
├── ColorPurpleAsset.php
├── CoreAsset.php
├── FontAsset.php
├── LICENSE.md
├── Metronic.php
├── README.md
├── assets
└── .empty
├── composer.json
├── helpers
├── Html.php
└── Layout.php
├── layouts
└── main.php
└── widgets
├── Accordion.php
├── ActiveField.php
├── ActiveForm.php
├── Alert.php
├── Badge.php
├── Breadcrumbs.php
├── Button.php
├── ButtonDropdown.php
├── ButtonGroup.php
├── CheckboxList.php
├── DatePicker.php
├── DatePickerAsset.php
├── DateRangePicker.php
├── DateRangePickerAsset.php
├── Decorator.php
├── DetailView.php
├── Dropdown.php
├── DropdownContent.php
├── GridView.php
├── HorizontalMenu.php
├── InputWidget.php
├── IonRangeSlider.php
├── IonRangeSliderAsset.php
├── Link.php
├── Menu.php
├── Modal.php
├── ModalAsset.php
├── MultiSelect.php
├── MultiSelectAsset.php
├── Nav.php
├── NavBar.php
├── Note.php
├── Notification.php
├── NotificationAsset.php
├── Portlet.php
├── Select2.php
├── Select2Asset.php
├── Spinner.php
├── SpinnerAsset.php
├── Tabs.php
├── TextInputWidget.php
└── Widget.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
--------------------------------------------------------------------------------
/ColorBlueAsset.php:
--------------------------------------------------------------------------------
1 | [
16 | 'plugins/respond.min.js' => 'if lt IE 9',
17 | 'plugins/excanvas.min.js' => 'if lt IE 9',
18 | ],
19 | ];
20 | public $js = [
21 | 'plugins/respond.min.js',
22 | 'plugins/excanvas.min.js',
23 | 'plugins/jquery-migrate-1.2.1.min.js',
24 | 'plugins/bootstrap-hover-dropdown/bootstrap-hover-dropdown.min.js',
25 | 'plugins/jquery-slimscroll/jquery.slimscroll.min.js',
26 | 'plugins/jquery.blockui.min.js',
27 | 'plugins/jquery.cokie.min.js',
28 | 'plugins/uniform/jquery.uniform.min.js',
29 | 'scripts/core/metronic.js',
30 | 'scripts/core/app.js',
31 | 'scripts/custom/custom.js',
32 | ];
33 |
34 | public $css = [
35 | 'plugins/uniform/css/uniform.default.css',
36 | 'css/style-metronic.css',
37 | 'css/style.css',
38 | 'css/style-responsive.css',
39 | 'css/custom.css',
40 | ];
41 | public $depends = [
42 | 'icron\metronic\FontAsset',
43 | 'yii\bootstrap\BootstrapPluginAsset',
44 | 'yii\web\JqueryAsset',
45 | ];
46 | }
47 |
--------------------------------------------------------------------------------
/FontAsset.php:
--------------------------------------------------------------------------------
1 | {static::$componentName};
90 | }
91 |
92 | /**
93 | * Get base url to metronic assets
94 | * @param $view View
95 | * @return string
96 | */
97 | public static function getAssetsUrl($view)
98 | {
99 | if(static::$assetsBundle === null){
100 | static::$assetsBundle = static::registerThemeAsset($view);
101 | }
102 |
103 | return (static::$assetsBundle instanceof AssetBundle) ? static::$assetsBundle->baseUrl : '';
104 | }
105 |
106 | /**
107 | * Register Theme Asset
108 | * @param $view View
109 | * @return AssetBundle
110 | */
111 | public static function registerThemeAsset($view)
112 | {
113 | /** @var AssetBundle $themeAsset */
114 | $themeAsset = 'icron\metronic\Color' . ucfirst(static::getComponent()->color) . 'Asset';
115 | static::$assetsBundle = $themeAsset::register($view);
116 |
117 | return static::$assetsBundle;
118 | }
119 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Yii2Metronic
2 | ======================
3 | Yii2Metronic is a collection of Yii2 components(widgets) based on responsive and multipurpose admin theme
4 | called Metronic (v2.0). Powered with Twitter Bootstrap 3.1.0 Framework.
5 |
6 | Metronic can be used for any type of web applications: custom admin panels, admin dashboards, CMS, CRM, SAAS and websites: business, corporate, portfolio, blog.
7 | Metronic has a sleek, clean and intuitive metro style design which makes your next project look awesome and yet user
8 | friendly. Metronic has a huge collection of plugins and UI components and works seamlessly on all major web browsers,
9 | tablets and phones.
10 |
11 | More than 30 widgets for Yii2 Metronic.
12 |
13 | Basic configuration:
14 | ```
15 | 'components' => [
16 | 'metronic' => [
17 | 'class' => 'icron\metronic\Metronic',
18 | 'color' => 'default',
19 | 'layoutOption' => \icron\metronic\Metronic::LAYOUT_FLUID,
20 | 'headerOption' => 'fixed',
21 | ],
22 | ],
23 | 'preload' => ['metronic'],
24 | ```
25 |
26 | Some examples:
27 | #### Menu
28 | Metronic menu displays a multi-level menu using nested HTML lists.
29 |
30 | The main property of Menu is [[items]], which specifies the possible items in the menu.
31 | A menu item can contain sub-items which specify the sub-menu under that menu item.
32 | Menu checks the current route and request parameters to toggle certain menu items
33 | with active state.
34 | Note that Menu only renders the HTML tags about the menu. It does do any styling.
35 | You are responsible to provide CSS styles to make it look like a real menu.
36 |
37 | The following example shows how to use Menu:
38 |
39 | ```php
40 | echo Menu::widget([
41 | 'items' => [
42 | // Important: you need to specify url as 'controller/action',
43 | // not just as 'controller' even if default action is used.
44 | [
45 | 'icon' => '',
46 | 'label' => 'Home',
47 | 'url' => ['site/index']
48 | ],
49 | // 'Products' menu item will be selected as long as the route is 'product/index'
50 | ['label' => 'Products', 'url' => ['product/index'], 'items' => [
51 | ['label' => 'New Arrivals', 'url' => ['product/index', 'tag' => 'new']],
52 | ['label' => 'Most Popular', 'url' => ['product/index', 'tag' => 'popular']],
53 | ]],
54 | ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
55 | ],
56 | 'search' => [
57 | // required, whether search box is visible. Defaults to 'true'.
58 | 'visible' => true,
59 | // optional, the configuration array for [[ActiveForm]].
60 | 'form' => [],
61 | // optional, input options with default values
62 | 'input' => [
63 | 'name' => 'search',
64 | 'value' => '',
65 | 'options' => [
66 | 'placeholder' => 'Search...',
67 | ]
68 | ],
69 | ]
70 | ]);
71 | ```
72 | #### Horizontal Menu
73 | Horizontal Menu displays a multi-level menu using nested HTML lists.
74 |
75 | The main property of Menu is [[items]], which specifies the possible items in the menu.
76 | A menu item can contain sub-items which specify the sub-menu under that menu item.
77 | Menu checks the current route and request parameters to toggle certain menu items
78 | with active state.
79 | Note that Menu only renders the HTML tags about the menu. It does do any styling.
80 | You are responsible to provide CSS styles to make it look like a real menu.
81 | Supports multiple operating modes: classic, mega, and full mega(see [[HorizontalMenu::type]]).
82 |
83 | The following example shows how to use Menu:
84 |
85 | ```php
86 | // Classic menu with search box
87 | echo HorizontalMenu::widget([
88 | 'items' => [
89 | // Important: you need to specify url as 'controller/action',
90 | // not just as 'controller' even if default action is used.
91 | ['label' => 'Home', 'url' => ['site/index']],
92 | // 'Products' menu item will be selected as long as the route is 'product/index'
93 | ['label' => 'Products', 'url' => ['product/index'], 'items' => [
94 | ['label' => 'New Arrivals', 'url' => ['product/index', 'tag' => 'new']],
95 | ['label' => 'Most Popular', 'url' => ['product/index', 'tag' => 'popular']],
96 | ]],
97 | ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
98 | ],
99 | 'search' => [
100 | // required, whether search box is visible. Defaults to 'true'.
101 | 'visible' => true,
102 | // optional, the configuration array for [[ActiveForm]].
103 | 'form' => [],
104 | // optional, input options with default values
105 | 'input' => [
106 | 'name' => 'search',
107 | 'value' => '',
108 | 'options' => [
109 | 'placeholder' => 'Search...',
110 | ]
111 | ],
112 | ]);
113 |
114 | // Mega Menu without search box
115 | echo HorizontalMenu::widget([
116 | 'items' => [
117 | ['label' => 'Home', 'url' => ['site/index']],
118 | [
119 | 'label' => 'Mega Menu',
120 | 'type' => HorizontalMenu::ITEM_TYPE_FULL_MEGA,
121 | //optional, HTML text for last column
122 | 'text' => 'Other HTML text',
123 | 'items' => [
124 | [
125 | 'label' => 'Column 1', // First column title
126 | 'items' => [
127 | ['label' => 'Column 1 Item 1'],
128 | ['label' => 'Column 1 Item 2'],
129 | ]
130 | ],
131 | [
132 | 'label' => 'Column 2', // Second column title
133 | 'items' => [
134 | ['label' => 'Column 2 Item 1'],
135 | ['label' => 'Column 2 Item 2'],
136 | ]
137 | ],
138 | ]
139 | ],
140 | ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
141 | ],
142 | ]);
143 | ```
144 | #### Nav
145 |
146 | Nav renders a nav HTML component.
147 | For example:
148 |
149 | ```php
150 | echo Nav::widget([
151 | 'items' => [
152 | [
153 | 'icon' => 'fa fa-warning',
154 | 'badge' => Badge::widget(['label' => 'New', 'round' => false]),
155 | 'label' => 'Home',
156 | 'url' => ['site/index'],
157 | 'linkOptions' => [...],
158 | ],
159 | [
160 | 'label' => 'Dropdown',
161 | 'items' => [
162 | ['label' => 'Level 1 - Dropdown A', 'url' => '#'],
163 | '
',
164 | '',
165 | ['label' => 'Level 1 - Dropdown B', 'url' => '#'],
166 | ],
167 | ],
168 | ],
169 | ]);
170 | ```
171 |
172 | **Note**: *Multilevel dropdowns beyond Level 1 are not supported in Bootstrap 3.*
173 |
174 | #### DateRangePicker
175 | DateRangePicker renders dateRangePicker widget.
176 |
177 | There are two modes of operation of the widget are 'input' and 'advance'.
178 | Mode 'input' renders input HTML element and mode 'advance' renders span HTML element.
179 | Widget renders a hidden field with the model name that this widget is associated with
180 | and the current value of the selected date.
181 |
182 | For example, if [[model]] and [[attribute]] are not set:
183 | ```php
184 | DateRangePicker::widget([
185 | 'mode' => DateRangePicker::MODE_ADVANCE,
186 | 'labelDateFormat' => 'MMMM D, YYYY',
187 | 'type' => DateRangePicker::TYPE_BLUE,
188 | 'clientOptions' => [
189 | 'format' => 'YYYY-MM-DD',
190 | 'ranges' => new \yii\web\JsExpression("{
191 | 'Today': [moment(), moment()],
192 | 'Yesterday': [moment().subtract('days', 1), moment().subtract('days', 1)],
193 | 'Last 7 Days': [moment().subtract('days', 6), moment()],
194 | 'Last 30 Days': [moment().subtract('days', 29), moment()],
195 | 'This Month': [moment().startOf('month'), moment().endOf('month')],
196 | 'Last Month': [moment().subtract('month', 1).startOf('month'), moment().subtract('month', 1).endOf('month')]
197 | }"),
198 | ],
199 | 'name' => 'date',
200 | 'icon' => 'fa fa-calendar',
201 | 'value' => '2014-02-15 - 2014-02-18',
202 | ]);
203 | ```
204 | #### Portlet
205 |
206 | Portlet renders a metronic portlet.
207 | Any content enclosed between the [[begin()]] and [[end()]] calls of Portlet
208 | is treated as the content of the portlet.
209 | For example,
210 |
211 | ```php
212 | // Simple portlet
213 | Portlet::begin([
214 | 'icon' => 'fa fa-bell-o',
215 | 'title' => 'Title Portlet',
216 | ]);
217 | echo 'Body portlet';
218 | Portlet::end();
219 |
220 | // Portlet with tools, actions, scroller, events and remote content
221 | Portlet::begin([
222 | 'title' => 'Extended Portlet',
223 | 'scroller' => [
224 | 'height' => 150,
225 | 'footer' => ['label' => 'Show all', 'url' => '#'],
226 | ],
227 | 'clientOptions' => [
228 | 'loadSuccess' => new \yii\web\JsExpression('function(){ console.log("load success"); }'),
229 | 'remote' => '/?r=site/about',
230 | ],
231 | 'clientEvents' => [
232 | 'close.mr.portlet' => 'function(e) { console.log("portlet closed"); e.preventDefault(); }'
233 | ],
234 | 'tools' => [
235 | Portlet::TOOL_RELOAD,
236 | Portlet::TOOL_MINIMIZE,
237 | Portlet::TOOL_CLOSE,
238 | ],
239 | ]);
240 | ```
241 | #### Select2
242 |
243 | Select2 renders Select2 component.
244 | For example:
245 | ```php
246 | echo Select2::widget([
247 | 'name' => 'select',
248 | 'data' => ['1' => 'Item 1', '2' => 'Item 2'],
249 | 'multiple' => true,
250 | ]);
251 | ```
252 |
253 | #### Badge
254 |
255 | Badge widget. For example,
256 | ```
257 | Badge::widget([
258 | 'label' => 'NEW',
259 | 'type' => Badge::TYPE_SUCCESS,
260 | 'round'
261 | ]);
262 | ```
263 | #### IonRangeSlider
264 | IonRangeSlider renders ionRangeSlider widget.
265 | For example, if [[model]] and [[attribute]] are not set:
266 | ```php
267 | echo IonRangeSlider::widget([
268 | 'name' => 'ionRangeSlider',
269 | 'clientOptions' => [
270 | 'min' => 0,
271 | 'max' => 5000,
272 | 'from' => 1000, // default value
273 | 'to' => 4000, // default value
274 | 'type' => 'double',
275 | 'step' => 1,
276 | 'prefix' => "$",
277 | 'prettify' => false,
278 | 'hasGrid' => true
279 | ],
280 | ]);
281 | ```
282 | #### Spinner
283 |
284 | Spinner renders an spinner Fuel UX widget.
285 | For example:
286 |
287 | ```php
288 | echo Spinner::widget([
289 | 'model' => $model,
290 | 'attribute' => 'country',
291 | 'size' => Spinner::SIZE_SMALL,
292 | 'buttonsLocation' => Spinner::BUTTONS_LOCATION_VERTICAL,
293 | 'clientOptions' => ['step' => 2],
294 | 'clientEvents' => ['changed' => 'function(event, value){ console.log(value);}'],
295 | ]);
296 | ```
297 |
298 | The following example will use the name property instead:
299 |
300 | ```php
301 | echo Spinner::widget([
302 | 'name' => 'country',
303 | 'clientOptions' => ['step' => 2],
304 | ]);
305 | ```
306 | #### Accordion
307 | Accordion renders an accordion Metronic component.
308 | For example:
309 |
310 | ```php
311 | echo Accordion::widget([
312 | 'items' => [
313 | [
314 | 'header' => 'Item 1',
315 | 'content' => 'Content 1...',
316 | // open its content by default
317 | 'contentOptions' => ['class' => 'in'],
318 | 'type' => Accordion::ITEM_TYPE_SUCCESS,
319 | ],
320 | [
321 | 'header' => 'Item 2',
322 | 'content' => 'Content 2...',
323 | ],
324 | ],
325 | 'itemConfig' => ['showIcon' => true],
326 | ]);
327 | ```
328 | #### Note
329 |
330 | Note renders a metronic button.
331 | For example,
332 | ```php
333 | Note::widget([
334 | 'title' => 'Success! Some Header Goes Here',
335 | 'body' => 'Duis mollis, est non commodo luctus',
336 | 'type' => Note::TYPE_INFO,
337 | ]);
338 | ```
339 |
340 | The following example will show the content enclosed between the [[begin()]]
341 | and [[end()]] calls within the alert box:
342 | ```php
343 | Note::begin(['type' => Note::TYPE_DANGER]);
344 | echo 'Some title and body';
345 | Note::end();
346 | ```
347 |
348 | ##### For more details see code documentation ...
349 |
--------------------------------------------------------------------------------
/assets/.empty:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icron/yii2-metronic/ad21d4ad996167dbc77d24c6c0f8bba98578975b/assets/.empty
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "icron/yii2-metronic",
3 | "description": "Metronic Template for Yii2",
4 | "keywords": ["yii", "metronic", "template"],
5 | "type": "yii2-extension",
6 | "license": "BSD",
7 | "support": {
8 | "forum": "",
9 | "wiki": ""
10 | },
11 |
12 | "require": {
13 | "yiisoft/yii2": "*"
14 | },
15 | "autoload": {
16 | "psr-4": { "icron\\metronic\\": "" }
17 | }
18 | }
--------------------------------------------------------------------------------
/helpers/Html.php:
--------------------------------------------------------------------------------
1 | $condition) {
32 | if (strpos($url, $file) !== false) {
33 | unset($options['conditions']);
34 | return static::conditionalComment(static::tag('link', '', $options), $condition);
35 | }
36 | }
37 | }
38 | unset($options['conditions']);
39 |
40 | return static::tag('link', '', $options);
41 | }
42 |
43 | /**
44 | * Generates a script tag that refers to an external JavaScript file.
45 | * @param string $url the URL of the external JavaScript file. This parameter will be processed by [[\yii\helpers\Url::to()]].
46 | * @param array $options the tag options in terms of name-value pairs. These will be rendered as
47 | * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
48 | * If a value is null, the corresponding attribute will not be rendered.
49 | * See [[renderTagAttributes()]] for details on how attributes are being rendered.
50 | * @return string the generated script tag
51 | * @see \yii\helpers\Url::to()
52 | */
53 | public static function jsFile($url, $options = [])
54 | {
55 | $options['src'] = Url::to($url);
56 | if (!empty($options['conditions'])) {
57 | foreach ($options['conditions'] as $file => $condition) {
58 | if (strpos($url, $file) !== false) {
59 | unset($options['conditions']);
60 | return static::conditionalComment(static::tag('script', '', $options), $condition);
61 | }
62 | }
63 | }
64 | unset($options['conditions']);
65 |
66 | return static::tag('script', '', $options);
67 | }
68 |
69 | /**
70 | * Generates conditional comments such as ''.
71 | * @param $content string the commented content
72 | * @param $condition string condition. Can contain 'if...' or ''
73 | * @return string the generated result
74 | */
75 | public static function conditionalComment($content, $condition)
76 | {
77 | $condition = strpos($condition, '') !== false ? '';
82 |
83 | return implode("\n", $lines);
84 | }
85 | }
--------------------------------------------------------------------------------
/helpers/Layout.php:
--------------------------------------------------------------------------------
1 | headerOption, 'fixed') === 0) {
24 | Html::addCssClass($options, 'page-header-fixed');
25 | }
26 |
27 | switch(Metronic::getComponent()->layoutOption)
28 | {
29 | case Metronic::LAYOUT_FULL_WIDTH :
30 | Html::addCssClass($options, Metronic::LAYOUT_FULL_WIDTH);
31 | break;
32 | case Metronic::LAYOUT_BOXED:
33 | Html::addCssClass($options, Metronic::LAYOUT_BOXED);
34 | break;
35 | }
36 |
37 | break;
38 | case 'header':
39 | Html::addCssClass($options, 'header navbar');
40 | if (strcasecmp(Metronic::getComponent()->headerOption, 'fixed') === 0) {
41 | Html::addCssClass($options, 'navbar-fixed-top');
42 | } else {
43 | Html::addCssClass($options, 'navbar-static-top');
44 | }
45 | break;
46 | }
47 |
48 | return $asString ? Html::renderTagAttributes($options) : $options;
49 | }
50 | }
--------------------------------------------------------------------------------
/layouts/main.php:
--------------------------------------------------------------------------------
1 |
2 | /** @var $this \yii\web\View */
3 |
4 | use icron\metronic\helpers\Layout;
5 | use icron\metronic\widgets\Menu;
6 | use icron\metronic\widgets\NavBar;
7 | use icron\metronic\widgets\Nav;
8 | use icron\metronic\widgets\Breadcrumbs;
9 | use yii\helpers\Html;
10 | use icron\metronic\widgets\Button;
11 | use icron\metronic\widgets\HorizontalMenu;
12 | use icron\metronic\Metronic;
13 | use icron\metronic\widgets\Badge;
14 |
15 | $this->beginPage();
16 | Metronic::registerThemeAsset($this);
17 | ?>
18 |
19 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | = Html::encode($this->title) ?>
31 | head() ?>
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | >
40 | beginBody() ?>
41 |
42 | NavBar::begin(
43 | [
44 | 'brandLabel' => 'My Company',
45 | 'brandLogoUrl' => Metronic::getAssetsUrl($this) . '/img/logo.png',
46 | 'brandUrl' => Yii::$app->homeUrl,
47 | 'options' => Layout::getHtmlOptions('header', false),
48 | ]
49 | );
50 | echo HorizontalMenu::widget(
51 | [
52 | 'items' => [
53 | [
54 | 'label' => 'Mega menu',
55 | 'type' => HorizontalMenu::ITEM_TYPE_MEGA,
56 | 'items' => [
57 | [
58 | //'options' => '',
59 | 'label' => 'Layouts',
60 | 'items' => [
61 | ['label' => 'Promo Page', 'url' => ['/site/index']],
62 | ['label' => 'Email Templates'],
63 | ]
64 | ],
65 | [
66 | //'options' => '',
67 | 'label' => 'Layouts 2',
68 | 'items' => [
69 | ['label' => 'Promo Page 2'],
70 | ['label' => 'Email Templates 2'],
71 | ]
72 | ],
73 | ]
74 | ],
75 | [
76 | 'label' => 'Full Mega menu',
77 | 'type' => HorizontalMenu::ITEM_TYPE_FULL_MEGA,
78 | 'text' => \icron\metronic\widgets\Accordion::widget(
79 | [
80 | 'items' => [
81 | [
82 | 'header' => 'Item 1',
83 | 'content' => 'Content 1...',
84 | // open its content by default
85 | 'contentOptions' => ['class' => 'in'],
86 | 'type' => \icron\metronic\widgets\Accordion::ITEM_TYPE_SUCCESS,
87 | ],
88 | [
89 | 'header' => 'Item 2',
90 | 'content' => 'Content 2...',
91 | ],
92 | ],
93 | 'itemConfig' => ['showIcon' => true],
94 | ]
95 | ),
96 | 'items' => [
97 | [
98 | //'options' => '',
99 | 'label' => 'Layouts',
100 | 'items' => [
101 | ['label' => 'Promo Page', 'url' => ['/site/index']],
102 | ['label' => 'Email Templates'],
103 | ]
104 | ],
105 | [
106 | //'options' => '',
107 | 'label' => 'Layouts 2',
108 | 'items' => [
109 | ['label' => 'Promo Page 2'],
110 | ['label' => 'Email Templates 2'],
111 | ]
112 | ],
113 | ]
114 | ],
115 | [
116 |
117 | 'label' => 'Home',
118 | 'items' => [
119 | ['label' => 'About', 'url' => ['/site/about']],
120 | ['label' => 'About', 'url' => ['/site/about']],
121 | ['label' => 'About', 'url' => ['/site/about']],
122 | ['label' => 'About', 'url' => ['/site/about']],
123 | ['label' => 'About', 'url' => ['/site/about']],
124 | ['label' => 'About', 'url' => ['/site/about']],
125 | ]
126 | ],
127 | [
128 | 'label' => 'Home 2',
129 | 'url' => ['/site/index'],
130 | 'items' => [
131 | [
132 | 'badge' => Badge::widget(['label' => 'Новинка', 'round' => false]),
133 | 'label' => 'About',
134 | 'url' => ['/site/about']
135 | ],
136 | ['label' => 'About', 'url' => ['/site/about']],
137 | [
138 | 'label' => 'About',
139 | 'url' => ['/site/about'],
140 | 'items' => [
141 | ['label' => 'About', 'url' => ['/site/about']],
142 | ['label' => 'About', 'url' => ['/site/about']],
143 | ['label' => 'Index', 'url' => ['/site/index']],
144 | ]
145 | ],
146 | ['label' => 'About', 'url' => ['/site/about']],
147 | ]
148 | ],
149 |
150 | ],
151 | ]
152 | );
153 | echo Nav::widget(
154 | [
155 | 'items' => [
156 | [
157 | 'icon' => 'fa fa-warning',
158 | 'badge' => Badge::widget(['label' => 'xxx']),
159 | 'label' => 'Home',
160 | 'url' => ['/site/index'],
161 | // dropdown title
162 | 'title' => 'xx',
163 | 'more' => ['label' => 'xxx', 'url' => '/', 'icon' => 'm-icon-swapright'],
164 | // scroller
165 | 'scroller' => ['height' => 200],
166 | // end dropdown
167 | 'items' => [
168 | ['label' => 'About', 'url' => ['/site/aboutz']],
169 | ['label' => 'About', 'url' => ['/site/aboutz']],
170 | ['label' => 'About', 'url' => ['/site/aboutz']],
171 | ['label' => 'About', 'url' => ['/site/aboutz']],
172 | ['label' => 'About', 'url' => ['/site/aboutz']],
173 | ['label' => 'About', 'url' => ['/site/aboutz']],
174 | ]
175 | ],
176 | [
177 | 'label' => Nav::userItem('Bob Nilson', Metronic::getAssetsUrl($this) . '/img/avatar1_small.jpg'),
178 | 'url' => '#',
179 | 'type' => 'user',
180 | 'items' => [
181 | [
182 | 'icon' => 'fa fa-calendar',
183 | 'label' => 'About',
184 | 'url' => ['/site/about'],
185 | 'badge' => Badge::widget(['label' => 'xxx']),
186 | ],
187 | ['label' => 'About', 'url' => ['/site/about']],
188 | ['label' => 'About', 'url' => ['/site/about']],
189 | ['label' => 'About', 'url' => ['/site/about']],
190 | ['divider'],
191 | ['label' => 'About', 'url' => ['/site/about']],
192 | ['label' => 'About', 'url' => ['/site/about']],
193 | ]
194 | ],
195 | // [ 'label' => 'Contact', 'url' => ['/site/contact']],
196 | ],
197 | ]
198 | );
199 | NavBar::end();
200 | ?>
201 | =
202 | (Metronic::getComponent()->layoutOption == Metronic::LAYOUT_BOXED) ?
203 | Html::beginTag('div', ['class' => 'container']) : ''; ?>
204 |
205 |
206 |
207 | =
208 | Menu::widget(
209 | [
210 | 'visible' => true,
211 | 'items' => [
212 | // Important: you need to specify url as 'controller/action',
213 | // not just as 'controller' even if default action is used.
214 | ['icon' => 'fa fa-home', 'label' => 'Home', 'url' => ['site/indea']],
215 | // 'Products' menu item will be selected as long as the route is 'product/index'
216 | [
217 | 'icon' => 'fa fa-cogs',
218 | 'badge' => Badge::widget(['label' => 'New', 'round' => false, 'type' => Badge::TYPE_SUCCESS]),
219 | 'label' => 'Products',
220 | 'url' => '#',
221 | 'items' => [
222 | ['label' => 'New Arrivals', 'url' => ['product/index', 'tag' => 'new']],
223 | [
224 | 'label' => 'Home',
225 | 'url' => '#',
226 | 'items' => [
227 | [
228 | 'icon' => 'fa fa-cogs',
229 | 'label' => 'Products',
230 | 'url' => ['site/index'],
231 | 'badge' => Badge::widget(
232 | ['label' => 'New', 'round' => false, 'type' => Badge::TYPE_SUCCESS]
233 | ),
234 | ],
235 | ]
236 | ],
237 | ]
238 | ],
239 | [
240 | 'icon' => 'fa fa-bookmark-o',
241 | 'label' => 'UI Features',
242 | 'url' => '#',
243 | 'items' => [
244 | [
245 | 'label' => 'Buttons & Icons',
246 | 'url' => ['site/'],
247 | ],
248 | ],
249 | ],
250 | [
251 | 'icon' => 'fa fa-user',
252 | 'label' => 'Login',
253 | 'url' => ['site/login'],
254 | 'visible' => Yii::$app->user->isGuest
255 | ],
256 | [
257 | 'icon' => 'fa fa-user',
258 | 'label' => 'Login',
259 | 'url' => ['site/login'],
260 | 'visible' => Yii::$app->user->isGuest
261 | ],
262 | ],
263 | ]
264 | ); ?>
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 | = Html::encode($this->title) ?>
275 | = Html::encode($this->title) ?>
276 |
277 | =
278 | Breadcrumbs::widget(
279 | [
280 | 'actions' => [
281 | 'label' => 'Action',
282 | 'button' => [
283 | 'type' => Button::TYPE_M_BLUE,
284 | 'options' => ['data-hover' => 'dropdown', 'delay' => '1000'],
285 | ],
286 | 'dropdown' => [
287 | 'items' => [
288 | ['label' => 'DropdownA', 'url' => '/'],
289 | ['divider'],
290 | ['label' => 'DropdownB', 'url' => '#'],
291 | ],
292 | ],
293 | ],
294 | 'homeLink' => [
295 | 'label' => 'Home',
296 | 'icon' => 'fa fa-home',
297 | 'url' => ['/']
298 | ],
299 | 'links' => [
300 | [
301 | 'icon' => 'fa fa-cogs',
302 | 'label' => 'Sample Post',
303 | 'url' => ['post/edit', 'id' => 1]
304 | ],
305 | 'Edit',
306 | ],
307 | ]
308 | );
309 | ?>
310 |
311 |
312 |
313 |
314 |
315 |
316 | = $content ?>
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
336 | = (Metronic::getComponent()->layoutOption == Metronic::LAYOUT_BOXED) ? Html::endTag('div') : ''; ?>
337 | endBody() ?>
338 |
339 |
340 |
341 | endPage() ?>
--------------------------------------------------------------------------------
/widgets/Accordion.php:
--------------------------------------------------------------------------------
1 | [
21 | * [
22 | * 'header' => 'Item 1',
23 | * 'content' => 'Content 1...',
24 | * // open its content by default
25 | * 'contentOptions' => ['class' => 'in'],
26 | * 'type' => Accordion::ITEM_TYPE_SUCCESS,
27 | * ],
28 | * [
29 | * 'header' => 'Item 2',
30 | * 'content' => 'Content 2...',
31 | * ],
32 | * ],
33 | * 'itemConfig' => ['showIcon' => true],
34 | *]);
35 | * ```
36 | *
37 | * @see http://getbootstrap.com/javascript/#collapse
38 | */
39 | class Accordion extends Widget
40 | {
41 | // Item types
42 | const ITEM_TYPE_DEFAULT = 'default';
43 | const ITEM_TYPE_SUCCESS = 'success';
44 | const ITEM_TYPE_DANGER = 'danger';
45 | const ITEM_TYPE_WARNING = 'warning';
46 | const ITEM_TYPE_INFO = 'info';
47 |
48 | /**
49 | * @var array list of groups in the collapse widget. Each array element represents a single
50 | * group with the following structure:
51 | *
52 | * ```php
53 | * [
54 | * // required, the header (HTML) of the group
55 | * 'header' => 'Item 1',
56 | * // required, the content (HTML) of the group
57 | * 'content' => '',
58 | * // optional the HTML attributes of the content group
59 | * 'contentOptions' => [],
60 | * // optional, the HTML attributes of the group
61 | * 'options' => [],
62 | * // optional, the item type. Valid values are 'default', 'success', 'danger', 'warning', 'info'
63 | * // Determines color of the item.
64 | * 'type' => '',
65 | * ]
66 | * ```
67 | */
68 | public $items = [];
69 | /**
70 | * @var array the default configuration used by item.
71 | */
72 | public $itemConfig = [];
73 |
74 | /**
75 | * Initializes the widget.
76 | */
77 | public function init()
78 | {
79 | parent::init();
80 | Html::addCssClass($this->options, 'panel-group accordion');
81 | }
82 |
83 | /**
84 | * Renders the widget.
85 | */
86 | public function run()
87 | {
88 | echo Html::beginTag('div', $this->options) . "\n";
89 | echo $this->renderItems() . "\n";
90 | echo Html::endTag('div') . "\n";
91 | $this->registerPlugin('collapse');
92 | }
93 |
94 | /**
95 | * Renders collapsible items as specified on [[items]].
96 | * @return string the rendering result
97 | * @throws InvalidConfigException.
98 | */
99 | public function renderItems()
100 | {
101 | $items = [];
102 | $index = 0;
103 | foreach ($this->items as $item) {
104 | if (!isset($item['header'])) {
105 | throw new InvalidConfigException("The 'header' option is required.");
106 | }
107 | if (!isset($item['content'])) {
108 | throw new InvalidConfigException("The 'content' option is required.");
109 | }
110 |
111 | $options = ArrayHelper::getValue($item, 'options', []);
112 | $type = ArrayHelper::getValue($item, 'type', self::ITEM_TYPE_DEFAULT);
113 | Html::addCssClass($options, 'panel panel-' . $type);
114 | $items[] = Html::tag('div', $this->renderItem(array_merge($this->itemConfig, $item), ++$index), $options);
115 | }
116 |
117 | return implode("\n", $items);
118 | }
119 |
120 | /**
121 | * Renders a single collapsible item group
122 | * @param array $item a single item from [[items]]
123 | * @param integer $index the item index as each item group content must have an id
124 | * @return string the rendering result
125 | * @throws InvalidConfigException
126 | */
127 | protected function renderItem($item, $index)
128 | {
129 | $options = ArrayHelper::getValue($item, 'options', []);
130 | $type = ArrayHelper::getValue($item, 'type', self::ITEM_TYPE_DEFAULT);
131 | Html::addCssClass($options, 'panel panel-' . $type);
132 | $id = $this->options['id'] . '-collapse' . $index;
133 | $options = ArrayHelper::getValue($item, 'contentOptions', []);
134 | $options['id'] = $id;
135 | Html::addCssClass($options, 'panel-collapse collapse');
136 | $styled = '';
137 | if (ArrayHelper::getValue($item, 'showIcon', false)) {
138 | if (preg_match('/[^\w]*in[^\w]*/', $options['class'])) {
139 | $styled = 'accordion-toggle-styled';
140 | } else {
141 | $styled = 'accordion-toggle-styled collapsed';
142 | }
143 | }
144 | $headerToggle = Html::a(
145 | $item['header'],
146 | '#' . $id,
147 | [
148 | 'class' => 'accordion-toggle ' . $styled,
149 | 'data-toggle' => 'collapse',
150 | 'data-parent' => '#' . $this->options['id']
151 | ]
152 | ) . "\n";
153 |
154 | $header = Html::tag('h4', $headerToggle, ['class' => 'panel-title']);
155 | $content = Html::tag('div', $item['content'], ['class' => 'panel-body']) . "\n";
156 |
157 | $group = [];
158 | $group[] = Html::tag('div', $header, ['class' => 'panel-heading']);
159 | $group[] = Html::tag('div', $content, $options);
160 |
161 | return implode("\n", $group);
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/widgets/ActiveField.php:
--------------------------------------------------------------------------------
1 | options['tag']) ? $this->options['tag'] : 'div') . "\n";
29 | }
30 | /**
31 | * Generates a icon for input.
32 | * @param array $options icon options.
33 | * The options have following structure:
34 | * ```php
35 | * [
36 | * 'icon' => 'fa fa-bookmark-o',
37 | * 'position' => ActiveField::ICON_POSITION_LEFT,
38 | * ]
39 | * ```
40 | * @return static the field object itself
41 | */
42 | public function icon($options = [])
43 | {
44 | $icon = ArrayHelper::remove($options, 'icon', null);
45 | if($icon) {
46 | $position = ArrayHelper::remove($options, 'position', self::ICON_POSITION_LEFT);
47 | if ($position != self::ICON_POSITION_RIGHT) {
48 | $position = '';
49 | }
50 | $this->parts['{input}'] = Html::tag('i', '', ['class' => $icon]) . "\n" . $this->parts['{input}'];
51 | $this->parts['{input}'] = Html::tag('div', $this->parts['{input}'], ['class' => 'input-icon ' . $position]);
52 | }
53 |
54 | return $this;
55 | }
56 | /**
57 | * Generates a groupAddon for input.
58 | * GroupAddon similar to [[icon()]].
59 | * @param array $options icon options.
60 | * The options have following structure:
61 | * ```php
62 | * [
63 | * 'icon' => 'fa fa-bookmark-o',
64 | * 'position' => ActiveField::ICON_POSITION_LEFT,
65 | * ]
66 | * ```
67 | * @return static the field object itself
68 | */
69 | public function groupAddon($options = [])
70 | {
71 | $icon = ArrayHelper::remove($options, 'icon', null);
72 | if($icon) {
73 | $addon = Html::tag('span', Html::tag('i', '', ['class' => $icon]), ['class' => 'input-group-addon']);
74 | $position = ArrayHelper::remove($options, 'position', self::ICON_POSITION_LEFT);
75 | if ($position == self::ICON_POSITION_RIGHT) {
76 | $this->parts['{input}'] .= "\n" . $addon;
77 | } else {
78 | $this->parts['{input}'] = $addon . "\n" . $this->parts['{input}'];
79 | }
80 | $this->parts['{input}'] = Html::tag('div', $this->parts['{input}'], ['class' => 'input-group']);
81 | }
82 |
83 | return $this;
84 | }
85 |
86 | /**
87 | * Generates a tag that contains error.
88 | * @param $error string the error to use.
89 | * @param array $options the tag options in terms of name-value pairs. It will be merged with [[errorOptions]].
90 | * @return static the field object itself
91 | */
92 | public function staticError($error, $options = [])
93 | {
94 | $options = array_merge($this->errorOptions, $options);
95 | $tag = isset($options['tag']) ? $options['tag'] : 'div';
96 | unset($options['tag']);
97 | $this->parts['{error}'] = Html::tag($tag, $error, $options);
98 |
99 | return $this;
100 | }
101 |
102 | /**
103 | * Generates spinner component.
104 | * @param array $options spinner options
105 | * @return $this
106 | */
107 | public function spinner($options = [])
108 | {
109 | $this->parts['{input}'] = Spinner::widget(array_merge($options, ['model' => $this->model, 'attribute' => $this->attribute]));
110 |
111 | return $this;
112 | }
113 |
114 | /**
115 | * Generates dateRangePicker component [[DateRangePicker]].
116 | * @param array $options dateRangePicker options
117 | * @return $this
118 | */
119 | public function dateRangePicker($options = [])
120 | {
121 | if ($this->form->type == ActiveForm::TYPE_VERTICAL) {
122 | //$options = array_merge($options, ['options' => ['style' => 'display:table-cell;']]);
123 | $options = array_merge($options, ['options' => ['class' => 'show']]);
124 | }
125 | $this->parts['{input}'] = DateRangePicker::widget(array_merge($options, ['model' => $this->model, 'attribute' => $this->attribute]));
126 |
127 | return $this;
128 | }
129 |
130 | /**
131 | * Generates dateRangePicker component [[DateRangePicker]].
132 | * @param array $options dateRangePicker options
133 | * @return $this
134 | */
135 | public function datePicker($options = [])
136 | {
137 | /*if ($this->form->type == ActiveForm::TYPE_VERTICAL) {
138 | //$options = array_merge($options, ['options' => ['style' => 'display:table-cell;']]);
139 | $options = array_merge($options, ['options' => ['class' => 'show']]);
140 | }*/
141 | $this->parts['{input}'] = DatePicker::widget(array_merge($options, ['model' => $this->model, 'attribute' => $this->attribute]));
142 |
143 | return $this;
144 | }
145 |
146 | /**
147 | * Generates select2 component [[Select2]].
148 | * @param array $options select2 options
149 | * @return $this
150 | */
151 | public function select2($options = [])
152 | {
153 | $this->parts['{input}'] = Select2::widget(array_merge($options, ['model' => $this->model, 'attribute' => $this->attribute]));
154 |
155 | return $this;
156 | }
157 |
158 | /**
159 | * Generates multiSelect component [[MultiSelect]].
160 | * @param array $options multiSelect options
161 | * @return $this
162 | */
163 | public function multiSelect($options = [])
164 | {
165 | $this->parts['{input}'] = MultiSelect::widget(array_merge($options, ['model' => $this->model, 'attribute' => $this->attribute]));
166 |
167 | return $this;
168 | }
169 |
170 | public function range($options = [])
171 | {
172 | $this->parts['{input}'] = IonRangeSlider::widget(array_merge($options, ['model' => $this->model, 'attribute' => $this->attribute]));
173 |
174 | return $this;
175 | }
176 | }
--------------------------------------------------------------------------------
/widgets/ActiveForm.php:
--------------------------------------------------------------------------------
1 | ActiveForm::BUTTONS_POSITION_LEFT,
53 | * //optional, vertical position
54 | * 'position' => ActiveForm::BUTTONS_POSITION_BOTTOM,
55 | * //optional, array of buttons
56 | * 'items' => [
57 | * Button::widget('label' => 'Save', 'options' => ['type' => 'submit']),
58 | * Button::widget('label' => 'Back'),
59 | * ],
60 | * // optional, the HTML attributes (name-value pairs) for the form actions tag.
61 | * 'options' => ['class' => 'fluid']
62 | * ]
63 | * ```
64 | */
65 | public $buttons = [];
66 | /**
67 | * @var array the default configuration used by [[field()]] when creating a new field object.
68 | */
69 | public $fieldConfig = [];
70 |
71 | /**
72 | * @var bool indicates whether the tag 'form' is rendered.
73 | * In case 'true' widget renders 'div' instead 'form'.
74 | */
75 | public $fake = false;
76 | /**
77 | * Initializes the widget.
78 | * This renders the form open tag.
79 | */
80 | public function init()
81 | {
82 | if (!isset($this->options['id'])) {
83 | $this->options['id'] = $this->getId();
84 | }
85 |
86 | switch ($this->type) {
87 | case self::TYPE_HORIZONTAL:
88 | if ($this->stripped) {
89 | Html::addCssClass($this->options, 'form-row-stripped');
90 | }
91 | if ($this->separated) {
92 | Html::addCssClass($this->options, 'form-row-seperated');
93 | }
94 | if ($this->bordered) {
95 | Html::addCssClass($this->options, 'form-bordered');
96 | }
97 | Html::addCssClass($this->options, 'form-horizontal');
98 | $this->fieldConfig = ArrayHelper::merge([
99 | 'labelOptions' => ['class' => 'col-md-3 control-label'],
100 | 'template' => "{label}\n" . Html::tag('div', "{input}\n{error}\n{hint}", ['class' => 'col-md-9']),
101 | ], $this->fieldConfig);
102 | break;
103 | case self::TYPE_INLINE:
104 | Html::addCssClass($this->options, 'form-inline');
105 | $this->fieldConfig = ArrayHelper::merge([
106 | 'labelOptions' => ['class' => 'sr-only'],
107 | ], $this->fieldConfig);
108 | break;
109 | }
110 | if (!isset($this->fieldConfig['class'])) {
111 | $this->fieldConfig['class'] = ActiveField::className();
112 | }
113 | if ($this->fake) {
114 | echo Html::beginTag('div', $this->options);
115 | } else {
116 | echo Html::beginForm($this->action, $this->method, $this->options);
117 | }
118 | echo $this->renderActions(self::BUTTONS_POSITION_TOP);
119 | echo Html::beginTag('div', ['class' => 'form-body']);
120 | }
121 | /**
122 | * Runs the widget.
123 | * This registers the necessary javascript code and renders the form close tag.
124 | */
125 | public function run()
126 | {
127 | echo Html::endTag('div');
128 | echo $this->renderActions(self::BUTTONS_POSITION_BOTTOM);
129 | if (!empty($this->attributes)) {
130 | $id = $this->options['id'];
131 | $options = Json::encode($this->getClientOptions());
132 | $attributes = Json::encode($this->attributes);
133 | $view = $this->getView();
134 | ActiveFormAsset::register($view);
135 | $view->registerJs("jQuery('#$id').yiiActiveForm($attributes, $options);");
136 | }
137 | if ($this->fake) {
138 | echo Html::endTag('div');
139 | } else {
140 | echo Html::endForm();
141 | }
142 | }
143 |
144 | /**
145 | * Generates a form field.
146 | * A form field is associated with a model and an attribute. It contains a label, an input and an error message
147 | * and use them to interact with end users to collect their inputs for the attribute.
148 | * @param Model $model the data model
149 | * @param string $attribute the attribute name or expression. See [[Html::getAttributeName()]] for the format
150 | * about attribute expression.
151 | * @param array $options the additional configurations for the field object
152 | * @return ActiveField the created ActiveField object
153 | * @see fieldConfig
154 | */
155 | public function field($model, $attribute, $options = []) {
156 | return parent::field($model, $attribute, $options);
157 | }
158 |
159 | protected function renderActions($currentPosition)
160 | {
161 | $position = ArrayHelper::getValue($this->buttons, 'position', self::BUTTONS_POSITION_BOTTOM);
162 | if (!empty($this->buttons['items']) && $position == $currentPosition) {
163 | $actionsOptions = ArrayHelper::getValue($this->buttons, 'options', []);
164 | Html::addCssClass($actionsOptions, 'form-actions');
165 | if ($position == self::BUTTONS_POSITION_TOP) {
166 | Html::addCssClass($actionsOptions, 'top');
167 | }
168 | if (isset($this->buttons['align']) && $this->buttons['align'] == self::BUTTONS_ALIGN_RIGHT) {
169 | Html::addCssClass($actionsOptions, 'right');
170 | }
171 | $rowOptions = [];
172 | $buttons = implode("\n", $this->buttons['items']);
173 | switch ($this->type) {
174 | case self::TYPE_HORIZONTAL:
175 | Html::addCssClass($actionsOptions, 'fluid');
176 | preg_match('#col-md-(\d+)#', $this->fieldConfig['labelOptions']['class'], $matches);
177 | if (isset($matches[1])) {
178 | $offset = $matches[1];
179 | Html::addCssClass($rowOptions, 'col-md-offset-' . $offset);
180 | Html::addCssClass($rowOptions, 'col-md-' . 12 - $offset);
181 | $buttons = Html::tag('div', $buttons, $rowOptions);
182 | }
183 | break;
184 | }
185 |
186 | return Html::tag('div', $buttons, $actionsOptions);
187 | }
188 |
189 | return '';
190 | }
191 | }
--------------------------------------------------------------------------------
/widgets/Alert.php:
--------------------------------------------------------------------------------
1 | 'Say hello...',
21 | * 'closeButton' => [
22 | * 'label' => '×',
23 | * 'tag' => 'a',
24 | * 'type' => Alert::TYPE_DANGER,
25 | * ],
26 | * ]);
27 | * ```
28 | *
29 | * The following example will show the content enclosed between the [[begin()]]
30 | * and [[end()]] calls within the alert box:
31 | *
32 | * ```php
33 | * Alert::begin([
34 | * 'type' => Alert::TYPE_DANGER,
35 | * 'closeButton' => ['label' => '×'],
36 | * ]);
37 | *
38 | * echo 'Say hello...';
39 | *
40 | * Alert::end();
41 | * ```
42 | */
43 | class Alert extends \yii\bootstrap\Alert
44 | {
45 | // type
46 | const TYPE_SUCCESS = 'success';
47 | const TYPE_INFO = 'info';
48 | const TYPE_WARNING = 'warning';
49 | const TYPE_DANGER = 'danger';
50 | /**
51 | * @var string the note type.
52 | * Valid values are 'success', 'info', 'warning', 'danger'.
53 | */
54 | public $type = self::TYPE_SUCCESS;
55 | /**
56 | * @var boolean when set, alert has a larger block size.
57 | */
58 | public $block = true;
59 | /**
60 | * @var boolean when set, alert will fade out using transitions when closed.
61 | */
62 | public $fade = true;
63 |
64 | /**
65 | * Initializes the widget.
66 | */
67 | public function init()
68 | {
69 | Html::addCssClass($this->options, 'alert-'.$this->type);
70 | if ($this->block) {
71 | Html::addCssClass($this->options, 'alert-block');
72 | }
73 | if ($this->fade) {
74 | Html::addCssClass($this->options, 'fade in');
75 | }
76 | parent::init();
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/widgets/Badge.php:
--------------------------------------------------------------------------------
1 | 'NEW',
18 | * 'type' => Badge::TYPE_SUCCESS,
19 | * 'round'
20 | * ]);
21 | *
22 | * @package icron\metronic\widgets
23 | */
24 | class Badge extends \yii\base\Widget
25 | {
26 | // type
27 | const TYPE_DEFAULT = '';
28 | const TYPE_GRAY = 'default';
29 | const TYPE_SUCCESS = 'success';
30 | const TYPE_WARNING = 'warning';
31 | const TYPE_DANGER = 'danger';
32 | const TYPE_INFO = 'info';
33 | /**
34 | * @var string the badge label
35 | */
36 | public $label;
37 | /**
38 | * @var string the badge type
39 | * Valid values '', 'default', 'success', 'warning', 'danger', 'info'
40 | */
41 | public $type = self::TYPE_DEFAULT;
42 | /**
43 | * @var bool Indicates whether badge is rounded or not.
44 | */
45 | public $round = true;
46 |
47 | /**
48 | * Executes the widget.
49 | */
50 | public function run()
51 | {
52 | $options = [];
53 | Html::addCssClass($options, 'badge');
54 | if (!$this->round) {
55 | Html::addCssClass($options, 'badge-roundless');
56 | }
57 | Html::addCssClass($options, 'badge-' . $this->type);
58 |
59 | echo Html::tag('span', $this->label, $options);
60 | }
61 | }
--------------------------------------------------------------------------------
/widgets/Breadcrumbs.php:
--------------------------------------------------------------------------------
1 | [
27 | * ['label' => 'Sample Post', 'url' => ['post/edit', 'id' => 1]],
28 | * 'Edit',
29 | * ],
30 | * ]);
31 | * ```
32 | *
33 | * Because breadcrumbs usually appears in nearly every page of a website, you may consider placing it in a layout view.
34 | * You can use a view parameter (e.g. `$this->params['breadcrumbs']`) to configure the links in different
35 | * views. In the layout view, you assign this view parameter to the [[links]] property like the following:
36 | *
37 | * ```php
38 | * // $this is the view object currently being used
39 | * echo Breadcrumbs::widget([
40 | * 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
41 | * ]);
42 | * ```
43 | */
44 | class Breadcrumbs extends \yii\widgets\Breadcrumbs
45 | {
46 | /**
47 | * @var string the template used to render each inactive item in the breadcrumbs. The token `{link}`
48 | * will be replaced with the actual HTML link for each inactive item.
49 | */
50 | public $itemTemplate = "{link} \n";
51 | /**
52 | * @var string the template used to render each active item in the breadcrumbs. The token `{link}`
53 | * will be replaced with the actual HTML link for each active item.
54 | */
55 | public $activeItemTemplate = "{link} \n";
56 | /**
57 | * @var array|string
58 | */
59 | public $actions;
60 |
61 | public function init()
62 | {
63 | parent::init();
64 | Html::addCssClass($this->options, 'page-breadcrumb breadcrumb');
65 | }
66 |
67 |
68 | public function run()
69 | {
70 | if (empty($this->links)) {
71 | return;
72 | }
73 | $links = [];
74 |
75 | if ($this->actions !== null) {
76 | Html::addCssClass($this->actions['dropdown']['options'], 'pull-right');
77 | if (is_string($this->actions)) {
78 | $links[] = $this->actions;
79 | } else if (is_array($this->actions)) {
80 | $links[] = ButtonDropdown::widget($this->actions);
81 | } else {
82 | throw new InvalidConfigException('Actions must be of type "string" or "array".');
83 | }
84 | }
85 |
86 | if ($this->homeLink === null) {
87 | $links[] = $this->renderItem([
88 | 'label' => Yii::t('yii', 'Home'),
89 | 'url' => Yii::$app->homeUrl,
90 | ], $this->itemTemplate);
91 | } elseif ($this->homeLink !== false) {
92 | $links[] = $this->renderItem($this->homeLink, $this->itemTemplate);
93 | }
94 | foreach ($this->links as $link) {
95 | if (!is_array($link)) {
96 | $link = ['label' => $link];
97 | }
98 | $links[] = $this->renderItem($link, isset($link['url']) ? $this->itemTemplate : $this->activeItemTemplate);
99 | }
100 | echo Html::tag($this->tag, implode('', $links), $this->options);
101 | }
102 |
103 | /**
104 | * Renders a single breadcrumb item.
105 | * @param array $link the link to be rendered. It must contain the "label" element. The "url" element is optional.
106 | * @param string $template the template to be used to rendered the link. The token "{link}" will be replaced by the link.
107 | * @return string the rendering result
108 | * @throws InvalidConfigException if `$link` does not have "label" element.
109 | */
110 | protected function renderItem($link, $template)
111 | {
112 | if (isset($link['label'])) {
113 | $label = $this->encodeLabels ? Html::encode($link['label']) : $link['label'];
114 | } else {
115 | throw new InvalidConfigException('The "label" element is required for each link.');
116 | }
117 |
118 | $icon = ArrayHelper::getValue($link, 'icon', '');
119 | if ($icon) {
120 | $icon = Html::tag('i', '', ['class' => 'fa ' . $icon]) . ' ';
121 | }
122 | if (isset($link['url'])) {
123 | return strtr($template, ['{link}' => $icon . Html::a($label, $link['url'])]);
124 | } else {
125 | return strtr($template, ['{link}' => $icon . $label]);
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/widgets/Button.php:
--------------------------------------------------------------------------------
1 | 'Action',
21 | * 'icon' => 'fa fa-bookmark-o',
22 | * 'iconPosition' => Button::ICON_POSITION_LEFT,
23 | * 'size' => Button::SIZE_SMALL,
24 | * 'disabled' => false,
25 | * 'block' => false,
26 | * 'type' => Button::TYPE_M_BLUE,
27 | * ]);
28 | * ```
29 | */
30 | class Button extends \yii\bootstrap\Button
31 | {
32 | // Button bootstrap types.
33 | const TYPE_PRIMARY = 'primary';
34 | const TYPE_INFO = 'info';
35 | const TYPE_SUCCESS = 'success';
36 | const TYPE_WARNING = 'warning';
37 | const TYPE_DANGER = 'danger';
38 | const TYPE_INVERSE = 'inverse';
39 | const TYPE_LINK = 'link';
40 |
41 | // Button metronic types.
42 | const TYPE_M_DEFAULT = 'default';
43 | const TYPE_M_RED = 'red';
44 | const TYPE_M_BLUE = 'blue';
45 | const TYPE_M_GREEN = 'green';
46 | const TYPE_M_YELLOW = 'yellow';
47 | const TYPE_M_PURPLE = 'purple';
48 | const TYPE_M_DARK = 'dark';
49 |
50 | // Button sizes.
51 | const SIZE_MINI = 'xs';
52 | const SIZE_SMALL = 'sm';
53 | const SIZE_LARGE = 'lg';
54 |
55 | // Позиция иконки
56 | const ICON_POSITION_LEFT = 'left';
57 | const ICON_POSITION_RIGHT = 'right';
58 |
59 | /**
60 | * @var string The button size.
61 | * Valid values are 'xs', 'sm', 'lg'.
62 | */
63 | public $size;
64 | /**
65 | * @var string The button type.
66 | * Valid values for metronic styles are 'default', 'red', 'blue', 'green', 'yellow', 'purple', 'dark'.
67 | * Valid values for bootstrap styles are 'primary', 'info', 'success', 'warning', 'danger', 'inverse', 'link'.
68 | */
69 | public $type = self::TYPE_M_DEFAULT;
70 | /**
71 | * @var string The button icon.
72 | */
73 | public $icon;
74 | /**
75 | * @var string Icon position.
76 | * Valid values are 'left', 'right'.
77 | */
78 | public $iconPosition = self::ICON_POSITION_LEFT;
79 | /**
80 | * @var bool Indicates whether button is disabled or not.
81 | */
82 | public $disabled = false;
83 | /**
84 | * @var bool Indicates whether the button should span the full width of the a parent.
85 | */
86 | public $block = false;
87 |
88 | /**
89 | * Initializes the widget.
90 | */
91 | public function init()
92 | {
93 | parent::init();
94 | $bootstrapTypes = [
95 | self::TYPE_PRIMARY,
96 | self::TYPE_INFO,
97 | self::TYPE_SUCCESS,
98 | self::TYPE_WARNING,
99 | self::TYPE_DANGER,
100 | self::TYPE_INVERSE,
101 | self::TYPE_LINK,
102 | ];
103 |
104 | $metronicTypes = [
105 | self::TYPE_M_DEFAULT,
106 | self::TYPE_M_RED,
107 | self::TYPE_M_BLUE,
108 | self::TYPE_M_GREEN,
109 | self::TYPE_M_YELLOW,
110 | self::TYPE_M_PURPLE,
111 | self::TYPE_M_DARK,
112 | ];
113 |
114 | if (in_array($this->type, $bootstrapTypes)) {
115 | Html::addCssClass($this->options, 'btn-' . $this->type);
116 | } elseif (in_array($this->type, $metronicTypes)) {
117 | Html::addCssClass($this->options, $this->type);
118 | } else {
119 | throw new InvalidConfigException("The button type is invalid.");
120 | }
121 |
122 | $sizes = [
123 | self::SIZE_MINI,
124 | self::SIZE_SMALL,
125 | self::SIZE_LARGE,
126 | ];
127 |
128 | if (in_array($this->size, $sizes)) {
129 | Html::addCssClass($this->options, 'btn-' . $this->size);
130 | }
131 |
132 | if ($this->disabled === true) {
133 | Html::addCssClass($this->options, 'disabled');
134 | }
135 |
136 | if ($this->block === true) {
137 | Html::addCssClass($this->options, 'btn-block');
138 | }
139 | }
140 |
141 | /**
142 | * Renders the widget.
143 | */
144 | public function run()
145 | {
146 | $label = $this->encodeLabel ? Html::encode($this->label) : $this->label;
147 | if ($this->icon !== null) {
148 | $icon = Html::tag('i', '', ['class' => $this->icon]);
149 | $label = strcasecmp($this->iconPosition, self::ICON_POSITION_LEFT) === 0 ? ($icon . ' ' . $label) : $label . ' ' . $icon;
150 | }
151 | echo Html::tag($this->tagName, $label, $this->options);
152 | $this->registerPlugin('button');
153 | }
154 | }
--------------------------------------------------------------------------------
/widgets/ButtonDropdown.php:
--------------------------------------------------------------------------------
1 | 'Action',
22 | * 'button' => [
23 | * 'icon' => 'fa fa-bookmark-o',
24 | * 'iconPosition' => Button::ICON_POSITION_LEFT,
25 | * 'size' => Button::SIZE_SMALL,
26 | * 'disabled' => false,
27 | * 'block' => false,
28 | * 'type' => Button::TYPE_M_BLUE,
29 | * ],
30 | * 'dropdown' => [
31 | * 'items' => [
32 | * ['label' => 'DropdownA', 'url' => '/'],
33 | * ['label' => 'DropdownB', 'url' => '#'],
34 | * ],
35 | * ],
36 | * ]);
37 | * ```
38 | *
39 | **/
40 | class ButtonDropdown extends \yii\bootstrap\ButtonDropdown
41 | {
42 | /**
43 | * @var array The configuration array for [[Button]].
44 | */
45 | public $button = [];
46 | /**
47 | * Renders the widget.
48 | */
49 | public function run()
50 | {
51 | echo Html::tag('li', $this->renderButton() . "\n" . $this->renderDropdown(), ['class' => 'btn-group']);
52 | }
53 |
54 | /**
55 | * Renders the button.
56 | * @return string the rendering result
57 | */
58 | protected function renderButton()
59 | {
60 | Html::addCssClass($this->options, 'btn');
61 | $label = $this->label;
62 | if ($this->encodeLabel) {
63 | $label = Html::encode($label);
64 | }
65 | if ($this->split) {
66 | $options = $this->options;
67 | $this->options['data-toggle'] = 'dropdown';
68 | Html::addCssClass($this->options, 'dropdown-toggle');
69 | $splitButton = Button::widget([
70 | 'label' => ' ',
71 | 'encodeLabel' => false,
72 | 'options' => $this->button,
73 | ]);
74 | } else {
75 | $label .= ' ';
76 | $options = $this->options;
77 | if (!isset($options['href'])) {
78 | $options['href'] = '#';
79 | }
80 | Html::addCssClass($options, 'dropdown-toggle');
81 | $options['data-toggle'] = 'dropdown';
82 | $splitButton = '';
83 | }
84 |
85 | return Button::widget(ArrayHelper::merge($this->button, [
86 | 'tagName' => $this->tagName,
87 | 'label' => $label,
88 | 'options' => $options,
89 | 'encodeLabel' => false,
90 | ])) . "\n" . $splitButton;
91 | }
92 |
93 | /**
94 | * Renders the dropdown
95 | * @return string the rendering result
96 | */
97 | protected function renderDropdown()
98 | {
99 | $config = $this->dropdown;
100 | $config['clientOptions'] = false;
101 | return Dropdown::widget($config);
102 | }
103 | }
--------------------------------------------------------------------------------
/widgets/ButtonGroup.php:
--------------------------------------------------------------------------------
1 | true,
21 | * 'buttons' => [
22 | * ['label' => 'A'],
23 | * ['label' => 'B'],
24 | * ]
25 | * ]);
26 | *
27 | * // a button group with an item as a string
28 | * echo ButtonGroup::widget([
29 | * 'buttons' => [
30 | * Button::widget(['label' => 'A']),
31 | * ['label' => 'B'],
32 | * ]
33 | * ]);
34 | * ```
35 | */
36 | class ButtonGroup extends \yii\bootstrap\ButtonGroup
37 | {
38 | /**
39 | * @var bool Indicates whether the button group appears vertically stacked.
40 | */
41 | public $stacked = false;
42 |
43 | /**
44 | * Initializes the widget.
45 | */
46 | public function init()
47 | {
48 | if ($this->stacked === true) {
49 | Html::addCssClass($this->options, 'btn-group-vertical');
50 | } else {
51 | Html::addCssClass($this->options, 'btn-group');
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/widgets/CheckboxList.php:
--------------------------------------------------------------------------------
1 | [
22 | * 'full_name',
23 | * [
24 | * 'name' => 'city',
25 | * 'label' => 'Location',
26 | * ]
27 | * ],
28 | * 'model' => $filterModel,
29 | * 'attribute' => 'columns',
30 | * ]);
31 | * ```
32 | */
33 | class CheckboxList extends InputWidget
34 | {
35 | /**
36 | * @var array list of checkbox items.
37 | * Each item must be either as string like the name checkbox
38 | * or as array with following special options:
39 | * - name, required, item name
40 | * - label, optional, item label
41 | * Item can not belong to the model.
42 | */
43 | public $items = [];
44 | /**
45 | * @var string the model attribute that this widget is associated with.
46 | * This model attribute contains list of checkboxes name, separated $separator value.
47 | */
48 | public $attribute;
49 | /**
50 | * @var string separator values
51 | */
52 | public $separator = ',';
53 | /**
54 | * @var array the HTML attributes for items.
55 | */
56 | public $itemOptions = [];
57 | /**
58 | * @var array items name, that will be checked.
59 | */
60 | private $_checked = [];
61 |
62 | /**
63 | * Initializes the widget.
64 | */
65 | public function init()
66 | {
67 | parent::init();
68 | $items = [];
69 | if ($this->hasModel()) {
70 | $this->_checked = array_map('trim', explode(',', $this->model->{$this->attribute}));
71 | foreach ($this->items as $item) {
72 | $input = [];
73 | if (is_string($item)) {
74 | $input['name'] = $item;
75 | $input['label'] = $this->model->getAttributeLabel($item);
76 | } else {
77 | if (!isset($item['name'])) {
78 | throw new InvalidConfigException('Option "name" is required.');
79 | }
80 | $input['name'] = $item['name'];
81 | $input['label'] = isset($item['label']) ? $item['label'] : $this->model->getAttributeLabel(
82 | $item['name']
83 | );
84 | }
85 | $items[] = $input;
86 | }
87 | } else {
88 | $this->_checked = array_map('trim', explode(',', $this->value));
89 | foreach ($this->items as $item) {
90 | $input = [];
91 | if (is_string($item)) {
92 | $input['name'] = $item;
93 | $input['label'] = Inflector::camel2words($item);
94 | } else {
95 | if (!isset($item['name'])) {
96 | throw new InvalidConfigException('Option "name" is required.');
97 | }
98 | $input['name'] = $item['name'];
99 | $input['label'] = isset($item['label']) ? $item['label'] : Inflector::camel2words($item['name']);
100 | }
101 | $items[] = $input;
102 | }
103 | }
104 |
105 | $this->items = $items;
106 | }
107 |
108 | /**
109 | * Executes the widget.
110 | */
111 | public function run()
112 | {
113 | if ($this->hasModel()) {
114 | $hiddenInput = Html::activeHiddenInput($this->model, $this->attribute);
115 | $inputId = Html::getInputId($this->model, $this->attribute);
116 | } else {
117 | $hiddenInput = Html::textInput($this->name, $this->name);
118 | $inputId = $this->name;
119 | }
120 |
121 | $items = [];
122 | usort($this->items, function($a, $b){
123 | $aKey = array_search($a['name'], $this->_checked);
124 | $bKey = array_search($b['name'], $this->_checked);
125 | if ($aKey == $bKey) {
126 | return 0;
127 | }
128 |
129 | return ($aKey > $bKey) ? 1 : -1;
130 | });
131 | Html::addCssClass($this->itemOptions, 'btn btn-xs default');
132 | foreach ($this->items as $item) {
133 | $checkbox = Html::checkbox($item['name'], in_array($item['name'], $this->_checked));
134 | $items[] = Html::tag('span', $checkbox . ' ' . $item['label'], $this->itemOptions);
135 | }
136 |
137 | echo Html::beginTag('div', $this->options);
138 | echo Sortable::widget([
139 | 'items' => $items,
140 | 'options' => ['tag' => 'div'],
141 | 'itemOptions' => ['tag' => 'span'],
142 | 'clientOptions' => ['cursor' => 'move',
143 | 'start' => new JsExpression('function(e, ui){
144 | ui.placeholder.height(ui.item.height());
145 | ui.placeholder.width(ui.item.width());
146 | }'),
147 | 'update' => new JsExpression("function(e, ui){
148 | var values = $.map($('#{$this->options['id']} input:checkbox:checked'),
149 | function(item){ return $(item).attr('name')});
150 | $('#{$inputId}').val(values.join('{$this->separator}'));
151 | }"),
152 | ],
153 | ]);
154 | echo $hiddenInput;
155 | echo Html::endTag('div');
156 | $this->registerJs($inputId);
157 | }
158 |
159 | protected function registerJs($inputId)
160 | {
161 | $this->view->registerJs("
162 | ;(function($){
163 | $('#{$this->options['id']}').on('change', 'input:checkbox', function(){
164 | var values = $.map($('#{$this->options['id']} input:checkbox:checked'),
165 | function(item){ return $(item).attr('name')});
166 | $('#{$inputId}').val(values.join('{$this->separator}'));
167 | });
168 | })(jQuery);
169 | ", View::POS_READY);
170 | }
171 | }
--------------------------------------------------------------------------------
/widgets/DatePicker.php:
--------------------------------------------------------------------------------
1 | 'ru',
22 | * 'model' => $model,
23 | * 'attribute' => 'country',
24 | * 'clientOptions' => [
25 | * 'dateFormat' => 'yy-mm-dd',
26 | * ],
27 | * ]);
28 | * ```
29 | *
30 | * The following example will use the name property instead:
31 | *
32 | * ```php
33 | * echo DatePicker::widget([
34 | * 'language' => 'ru',
35 | * 'name' => 'country',
36 | * 'clientOptions' => [
37 | * 'dateFormat' => 'yy-mm-dd',
38 | * ],
39 | * ]);
40 | *```
41 | *
42 | * @see http://api.jqueryui.com/datepicker/
43 | * @author Alexander Kochetov
44 | * @since 2.0
45 | */
46 | class DatePicker extends InputWidget
47 | {
48 | /**
49 | * @var string the locale ID (eg 'fr', 'de') for the language to be used by the date picker.
50 | * If this property set to false, I18N will not be involved. That is, the date picker will show in English.
51 | */
52 | public $language = false;
53 | /**
54 | * @var boolean If true, shows the widget as an inline calendar and the input as a hidden field.
55 | */
56 | public $inline = false;
57 | /**
58 | * @var array the HTML attributes for the container tag. This is only used when [[inline]] is true.
59 | */
60 | public $containerOptions = [];
61 |
62 | /**
63 | * Initializes the widget.
64 | */
65 | public function init()
66 | {
67 | parent::init();
68 | if ($this->inline && !isset($this->containerOptions['id'])) {
69 | $this->containerOptions['id'] = $this->options['id'] . '-container';
70 | } else {
71 | Html::addCssClass($this->options, 'form-control form-control-inline');
72 | }
73 | }
74 |
75 | /**
76 | * Renders the widget.
77 | */
78 | public function run()
79 | {
80 | $contents = [];
81 | if($this->inline) {
82 | if ($this->hasModel()) {
83 | $contents[] = Html::activeHiddenInput($this->model, $this->attribute, $this->options);
84 |
85 | } else {
86 | $contents[] = Html::hiddenInput($this->name, $this->value, $this->options);
87 | }
88 | $contents[] = Html::tag('div', '', $this->containerOptions);
89 | } else {
90 | if ($this->hasModel()) {
91 | $contents[] = Html::activeTextInput($this->model, $this->attribute, $this->options);
92 | } else {
93 | $contents[] = Html::textInput($this->name, $this->value, $this->options);
94 | }
95 | }
96 | echo implode("\n", $contents);
97 | if($this->language) {
98 | DatePickerAsset::$extraJs[] = 'plugins/bootstrap-datepicker-extended/js/locales/bootstrap-datepicker.' . $this->language . '.js';
99 | $this->clientOptions['language'] = $this->language;
100 | }
101 | DatePickerAsset::register($this->view);
102 | $this->registerPlugin('datepicker');
103 | if ($this->inline) {
104 | $this->view->registerJs("
105 | !(function($){
106 | var el = $('#{$this->options['id']}'),
107 | val = el.val(),
108 | container = $('#{$this->containerOptions['id']}');
109 | container.on('changeDate', function(e){
110 | el.val(e.format());
111 | });
112 | if(val) {
113 | container.datepicker('update', new Date(Date.parse(val)));
114 | }
115 | })(jQuery);
116 | ", View::POS_READY);
117 | }
118 | }
119 |
120 | /**
121 | * Registers a specific Bootstrap plugin and the related events
122 | * @param string $name the name of the Bootstrap plugin
123 | */
124 | protected function registerPlugin($name)
125 | {
126 | $view = $this->getView();
127 | $id = $this->inline ? $this->containerOptions['id'] : $this->options['id'];
128 | if ($this->clientOptions !== false) {
129 | $options = empty($this->clientOptions) ? '' : Json::encode($this->clientOptions);
130 | $js = "jQuery('#$id').$name($options);";
131 | $view->registerJs($js);
132 | }
133 | if (!empty($this->clientEvents)) {
134 | $js = [];
135 | foreach ($this->clientEvents as $event => $handler) {
136 | $js[] = "jQuery('#$id').on('$event', $handler);";
137 | }
138 | $view->registerJs(implode("\n", $js));
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/widgets/DatePickerAsset.php:
--------------------------------------------------------------------------------
1 | js = array_merge($this->js, static::$extraJs);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/widgets/DateRangePicker.php:
--------------------------------------------------------------------------------
1 | DateRangePicker::MODE_ADVANCE,
26 | * 'labelDateFormat' => 'MMMM D, YYYY',
27 | * 'type' => DateRangePicker::TYPE_BLUE,
28 | * 'clientOptions' => [
29 | * 'format' => 'YYYY-MM-DD',
30 | * 'ranges' => new \yii\web\JsExpression("{
31 | * 'Today': [moment(), moment()],
32 | * 'Yesterday': [moment().subtract('days', 1), moment().subtract('days', 1)],
33 | * 'Last 7 Days': [moment().subtract('days', 6), moment()],
34 | * 'Last 30 Days': [moment().subtract('days', 29), moment()],
35 | * 'This Month': [moment().startOf('month'), moment().endOf('month')],
36 | * 'Last Month': [moment().subtract('month', 1).startOf('month'), moment().subtract('month', 1).endOf('month')]
37 | * }"),
38 | * ],
39 | * 'name' => 'date',
40 | * 'icon' => 'fa fa-calendar',
41 | * 'value' => '2014-02-15 - 2014-02-18',
42 | * ]);
43 | * ```
44 | * @see https://github.com/dangrossman/bootstrap-daterangepicker
45 | */
46 | class DateRangePicker extends InputWidget
47 | {
48 | // mode
49 | const MODE_INPUT = 'input';
50 | const MODE_ADVANCE = 'advance';
51 | // type
52 | const TYPE_DEFAULT = 'default';
53 | const TYPE_RED = 'red';
54 | const TYPE_BLUE = 'blue';
55 | const TYPE_GREEN = 'green';
56 | const TYPE_YELLOW = 'yellow';
57 | const TYPE_PURPLE = 'purple';
58 | const TYPE_DARK = 'dark';
59 | /**
60 | * @var string dateRangePicker icon.
61 | */
62 | public $icon;
63 | /**
64 | * @var string date separator.
65 | */
66 | public $separator = ' - ';
67 | /**
68 | * @var string dateRangePicker format is displayed on the span HTML element in case mode 'advance'.
69 | * Using the format from JS dateRangePicker formats.
70 | */
71 | public $labelDateFormat;
72 | /**
73 | * @var string dateRangePicker mode.
74 | * Valid values are 'input', 'advance'.
75 | * When it is set 'input' then it will be shown input element.
76 | */
77 | public $mode = self::MODE_ADVANCE;
78 | /**
79 | * @var string dateRangePicker type.
80 | * Valid values are 'default', 'red', 'blue', 'green', 'yellow', 'purple', 'dark'
81 | * Type determines what color will have widget.
82 | */
83 | public $type = self::TYPE_DEFAULT;
84 | /**
85 | * Executes the widget.
86 | */
87 | public function run()
88 | {
89 | if (empty($this->clientOptions['format'])) {
90 | $this->clientOptions['format'] = 'MM/DD/YYYY';
91 | }
92 |
93 | if (empty($this->labelDateFormat)) {
94 | $this->labelDateFormat = $this->clientOptions['format'];
95 | }
96 |
97 | if ($this->hasModel()) {
98 | $hiddenInput = Html::activeHiddenInput($this->model, $this->attribute);
99 | $input = Html::activeTextInput($this->model, $this->attribute);
100 | $name = Html::getInputName($this->model, $this->attribute);
101 | $value = $this->model->{$this->attribute};
102 | $this->options['id'] .= '-picker';
103 | } else {
104 | $hiddenInput = Html::hiddenInput($this->name, $this->value);
105 | $input = Html::textInput($this->name, $this->value, ['class' => 'form-control']);
106 | $name = $this->name;
107 | $value = $this->value;
108 | }
109 | $arrValue = array_map('trim', ($value = explode($this->separator, $value)) ? $value : []);
110 | $callback = '';
111 | $initJS = '';
112 | $lines = [];
113 | switch ($this->mode) {
114 | case self::MODE_ADVANCE:
115 | Html::addCssClass($this->options, 'btn ' . $this->type);
116 | $lines[] = $hiddenInput;
117 | $lines[] = Html::beginTag('div', $this->options);
118 | if (!empty($this->icon)) {
119 | $lines[] = Html::tag('i', '', ['class' => $this->icon]) . ' ';
120 | }
121 | $lines[] = Html::tag('span', ' ');
122 | $lines[] = Html::tag('b', '', ['class' => 'fa fa-angle-down']);
123 | $lines[] = Html::endTag('div');
124 | $callback = "function (start, end) {
125 | $('#{$this->options['id']} span')
126 | .html(start.format('{$this->labelDateFormat}')
127 | + '{$this->separator}' + end.format('{$this->labelDateFormat} '));
128 | // set value to hidden input
129 | $('input[name=\"{$name}\"]').val(start.format('{$this->clientOptions['format']}')
130 | + '{$this->separator}' + end.format('{$this->clientOptions['format']}'));
131 | }";
132 | if(count($arrValue) == 2) {
133 | $initJS = ("
134 | !(function($){
135 | var el = $('#{$this->options['id']}');
136 | el.data('daterangepicker')
137 | .setStartDate(moment('{$arrValue[0]}', '{$this->clientOptions['format']}'));
138 | el.data('daterangepicker')
139 | .setEndDate(moment('{$arrValue[1]}', '{$this->clientOptions['format']}'));
140 | el.find('span')
141 | .html(moment('{$arrValue[0]}', '{$this->clientOptions['format']}').format('{$this->labelDateFormat}')
142 | + '{$this->separator}'
143 | + moment('{$arrValue[1]}', '{$this->clientOptions['format']}').format('{$this->labelDateFormat} '));
144 | })(jQuery);
145 | ");
146 | }
147 | break;
148 | case self::MODE_INPUT:
149 | Html::addCssClass($this->options, 'input-group');
150 | $lines[] = Html::beginTag('div', $this->options);
151 | $lines[] = $input;
152 | $lines[] = Html::beginTag('span', ['class' => 'input-group-btn']);
153 | $lines[] = Button::widget(
154 | [
155 | 'label' => ' ',
156 | 'icon' => $this->icon,
157 | 'type' => $this->type,
158 | 'iconPosition' => Button::ICON_POSITION_RIGHT
159 | ]
160 | );
161 | $lines[] = Html::endTag('span');
162 | $lines[] = Html::endTag('div');
163 | $callback = "function (start, end) {
164 | $('#{$this->options['id']} input')
165 | .val(start.format('{$this->clientOptions['format']}')
166 | + '{$this->separator}' + end.format('{$this->clientOptions['format']} '));
167 | // set value to hidden input
168 | $('input[name=\"{$name}\"]').val(start.format('{$this->clientOptions['format']}')
169 | + '{$this->separator}' + end.format('{$this->clientOptions['format']}'));
170 | }";
171 | if(count($arrValue) == 2) {
172 | $initJS = ("
173 | !(function($){
174 | var el = $('#{$this->options['id']}');
175 | el.data('daterangepicker')
176 | .setStartDate(moment('{$arrValue[0]}', '{$this->clientOptions['format']}'));
177 | el.data('daterangepicker')
178 | .setEndDate(moment('{$arrValue[1]}', '{$this->clientOptions['format']}'));
179 | el.find('input')
180 | .val(moment('{$arrValue[0]}', '{$this->clientOptions['format']}').format('{$this->clientOptions['format']}')
181 | + '{$this->separator}'
182 | + moment('{$arrValue[1]}', '{$this->clientOptions['format']}').format('{$this->clientOptions['format']} '));
183 | })(jQuery);
184 | ");
185 | }
186 | break;
187 | }
188 | echo implode("\n", $lines);
189 | DateRangePickerAsset::register($this->view);
190 | $this->registerPlugin('daterangepicker', $callback);
191 | if (!empty($initJS)) {
192 | $this->view->registerJs($initJS, View::POS_READY);
193 | }
194 | }
195 |
196 | /**
197 | * Registers a specific Bootstrap plugin and the related events
198 | * @param string $name the name of the Bootstrap plugin
199 | * @param string $callback second parameter option of the Bootstrap plugin
200 | */
201 | protected function registerPlugin($name, $callback) {
202 | $view = $this->getView();
203 | $id = $this->options['id'];
204 | if ($this->clientOptions !== false) {
205 | $options = empty($this->clientOptions) ? '' : Json::encode($this->clientOptions);
206 | if (!empty($callback)) {
207 | $js = "jQuery('#$id').$name($options, $callback);";
208 | } else {
209 | $js = "jQuery('#$id').$name($options);";
210 | }
211 | $view->registerJs($js);
212 | }
213 | if (!empty($this->clientEvents)) {
214 | $js = [];
215 | foreach ($this->clientEvents as $event => $handler) {
216 | $js[] = "jQuery('#$id').on('$event', $handler);";
217 | }
218 | $view->registerJs(implode("\n", $js));
219 | }
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/widgets/DateRangePickerAsset.php:
--------------------------------------------------------------------------------
1 | $model,
26 | * 'attributes' => [
27 | * 'title', // title attribute (in plain text)
28 | * 'description:html', // description attribute in HTML
29 | * [ // the owner name of the model
30 | * 'label' => 'Owner',
31 | * 'value' => $model->owner->name,
32 | * ],
33 | * ],
34 | * ]);
35 | * ~~~
36 | */
37 | class DetailView extends \yii\widgets\DetailView
38 | {
39 | /**
40 | * @var string|callback the template used to render a single attribute. If a string, the token `{label}`
41 | * and `{value}` will be replaced with the label and the value of the corresponding attribute.
42 | * If a callback (e.g. an anonymous function), the signature must be as follows:
43 | *
44 | * ~~~
45 | * function ($attribute, $index, $widget)
46 | * ~~~
47 | *
48 | * where `$attribute` refer to the specification of the attribute being rendered, `$index` is the zero-based
49 | * index of the attribute in the [[attributes]] array, and `$widget` refers to this widget instance.
50 | */
51 | public $template = '
52 |
{label}
53 |
{value}
54 |
';
55 | }
56 |
--------------------------------------------------------------------------------
/widgets/Dropdown.php:
--------------------------------------------------------------------------------
1 | 'Dropdown title',
21 | * 'more' => ['label' => 'xxx', 'url' => '/', 'icon' => 'm-icon-swapright'],
22 | * 'scroller' => ['height' => 200],
23 | * 'items' => [
24 | * ['label' => 'Level 1 - Dropdown A', 'url' => '#'],
25 | * ' ',
26 | * '',
27 | * ['label' => 'Level 1 - Dropdown B', 'url' => '#'],
28 | * ],
29 | * ]);
30 | *
31 | */
32 | class Dropdown extends \yii\bootstrap\Dropdown
33 | {
34 | /**
35 | * @var string the dropdown title
36 | */
37 | public $title;
38 | /**
39 | * @var array the dropdown last item options
40 | * with the following structure:
41 | * ```php
42 | * [
43 | * // optional, item label
44 | * 'label' => 'Show all messages',
45 | * // optional, item icon
46 | * 'icon' => 'm-icon-swapright',
47 | * // optional, item url
48 | * 'url' => '/',
49 | * ]
50 | * ```
51 | */
52 | public $more = [];
53 | /**
54 | * @var array the dropdown item options
55 | * is an array of the following structure:
56 | * ```php
57 | * [
58 | * // required, height of the body portlet as a px
59 | * 'height' => 150,
60 | * // optional, HTML attributes of the scroller
61 | * 'options' => [],
62 | * // optional, footer of the scroller. May contain string or array(the options of Link component)
63 | * 'footer' => [
64 | * 'label' => 'Show all',
65 | * ],
66 | * ]
67 | * ```
68 | */
69 | public $scroller = [];
70 |
71 | /**
72 | * Executes the widget.
73 | */
74 | public function run()
75 | {
76 | echo $this->renderItems($this->items);
77 | }
78 |
79 | /**
80 | * Renders menu items.
81 | * @param array $items the menu items to be rendered
82 | * @return string the rendering result.
83 | * @throws InvalidConfigException if the label option is not specified in one of the items.
84 | */
85 | protected function renderItems($items, $options = [])
86 | {
87 | $lines = [];
88 | if ($this->title) {
89 | $lines[] = Html::tag('li', Html::tag('p', $this->title));
90 | }
91 |
92 | if (!empty($this->scroller)) {
93 | if (!isset($this->scroller['height'])) {
94 | throw new InvalidConfigException("The 'height' option of Scroller is required.");
95 | }
96 | $lines[] = Html::beginTag('li');
97 | $lines[] = Html::beginTag(
98 | 'ul',
99 | [
100 | 'style' => 'height: ' . $this->scroller['height'] . 'px;',
101 | 'class' => 'dropdown-menu-list scroller'
102 | ]
103 | );
104 | }
105 |
106 | foreach ($items as $i => $item) {
107 | if (isset($item['visible']) && !$item['visible']) {
108 | unset($items[$i]);
109 | continue;
110 | }
111 | if (is_string($item)) {
112 | $lines[] = $item;
113 | continue;
114 | }
115 |
116 | if (in_array('divider', $item)) {
117 | $lines[] = Html::tag('li', '', ['class' => 'divider']);
118 | continue;
119 | }
120 |
121 | if (!isset($item['label'])) {
122 | throw new InvalidConfigException("The 'label' option is required.");
123 | }
124 | $label = $this->encodeLabels ? Html::encode($item['label']) : $item['label'];
125 |
126 | $icon = ArrayHelper::getValue($item, 'icon', null);
127 | if ($icon) {
128 | $label = Html::tag('i', '', ['alt' => $label, 'class' => $icon]) . ' ' . $label;
129 | }
130 | $label .= ArrayHelper::getValue($item, 'badge', '');
131 | $options = ArrayHelper::getValue($item, 'options', []);
132 | $linkOptions = ArrayHelper::getValue($item, 'linkOptions', []);
133 | $linkOptions['tabindex'] = '-1';
134 | $content = Html::a($label, ArrayHelper::getValue($item, 'url', '#'), $linkOptions);
135 | $lines[] = Html::tag('li', $content, $options);
136 | }
137 |
138 | if (!empty($this->scroller)) {
139 | $lines[] = Html::endTag('ul');
140 | $lines[] = Html::endTag('li');
141 | }
142 |
143 | if (!empty($this->more)) {
144 | $url = ArrayHelper::getValue($this->more, 'url', '#');
145 | $text = ArrayHelper::getValue($this->more, 'label', '');
146 | $icon = ArrayHelper::getValue($this->more, 'icon', '');
147 | if ($icon) {
148 | $icon = Html::tag('i', '', ['class' => $icon]);
149 | }
150 | $lines[] = Html::tag('li', Html::tag('a', $text . $icon, ['href' => $url]), ['class' => 'external']);
151 | }
152 |
153 | return Html::tag('ul', implode("\n", $lines), $this->options);
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/widgets/DropdownContent.php:
--------------------------------------------------------------------------------
1 | 'Action',
21 | * 'dropdown' => 'Content',
22 | * ]);
23 | * ```
24 | */
25 | class DropdownContent extends ButtonDropdown
26 | {
27 | /**
28 | * @var string the button label
29 | */
30 | public $label = 'Button';
31 | /**
32 | * @var array the HTML attributes of the button.
33 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
34 | */
35 | public $options = [];
36 | /**
37 | * @var string the dropdown content.
38 | */
39 | public $dropdown = '';
40 |
41 | /**
42 | * Executes the widget.
43 | */
44 | public function run()
45 | {
46 | echo Html::beginTag('div', ['class' => 'btn-group']);
47 | echo $this->renderButton() . "\n" . $this->renderDropdown();
48 | echo Html::endTag('div');
49 |
50 | $this->registerPlugin('button');
51 |
52 | }
53 |
54 | /**
55 | * Generates the button dropdown.
56 | * @return string the rendering result.
57 | */
58 | protected function renderButton()
59 | {
60 | Html::addCssClass($this->options, 'btn');
61 | $label = $this->label;
62 | if ($this->encodeLabel) {
63 | $label = Html::encode($label);
64 | }
65 | if ($this->split) {
66 | $options = $this->options;
67 | $this->options['data-toggle'] = 'dropdown';
68 | Html::addCssClass($this->options, 'dropdown-toggle');
69 | $splitButton = BButton::widget([
70 | 'label' => ' ',
71 | 'encodeLabel' => false,
72 | 'options' => $this->options,
73 | 'view' => $this->getView(),
74 | ]);
75 | } else {
76 | $label .= ' ';
77 | $options = $this->options;
78 | if (!isset($options['href'])) {
79 | $options['href'] = '#';
80 | }
81 | Html::addCssClass($options, 'dropdown-toggle');
82 | $options['data-toggle'] = 'dropdown';
83 | $splitButton = '';
84 | }
85 |
86 | return BButton::widget([
87 | 'tagName' => $this->tagName,
88 | 'label' => $label,
89 | 'options' => $options,
90 | 'encodeLabel' => false,
91 | 'view' => $this->getView(),
92 | ]) . "\n" . $splitButton;
93 | }
94 |
95 | /**
96 | * Gets dropdown content.
97 | * @return string the rendering result.
98 | */
99 | protected function renderDropdown()
100 | {
101 | return Html::tag('div', $this->dropdown, ['class' => 'dropdown-menu']);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/widgets/GridView.php:
--------------------------------------------------------------------------------
1 | 'table table-striped table-bordered table-hover dataTable'];
26 | /**
27 | * @var array the HTML attributes for the table header row
28 | */
29 | public $headerRowOptions = ['class' => 'heading'];
30 |
31 | public function init()
32 | {
33 | parent::init();
34 | $this->initVisible();
35 | $this->initSortable();
36 | }
37 |
38 | /**
39 | * Renders the data models for the grid view.
40 | */
41 | public function renderItems()
42 | {
43 | $content = array_filter([
44 | $this->renderCaption(),
45 | $this->renderColumnGroup(),
46 | $this->showHeader ? $this->renderTableHeader() : false,
47 | $this->showFooter ? $this->renderTableFooter() : false,
48 | $this->renderTableBody(),
49 | ]);
50 | $table = Html::tag('table', implode("\n", $content), $this->tableOptions);
51 | if ($this->responsive) {
52 | $table = Html::tag('div', $table, ['class' => 'table-responsive']);
53 | }
54 |
55 | return $table;
56 | }
57 |
58 | protected function initVisible()
59 | {
60 | $columns = $this->getStorageColumns();
61 | if (empty($columns)) {
62 | return;
63 | }
64 | foreach ($this->columns as $i => $column) {
65 | if (array_search($i, $columns) === false) {
66 | unset($this->columns[$i]);
67 | }
68 | }
69 | }
70 |
71 | protected function initSortable()
72 | {
73 | $positions = $this->getStorageColumns();
74 | if (empty($positions)) {
75 | return;
76 | }
77 | uksort(
78 | $this->columns,
79 | function ($a, $b) use ($positions) {
80 | $aIndex = array_search($a, $positions);
81 | $bIndex = array_search($b, $positions);
82 | if ($aIndex == $bIndex) {
83 | return 0;
84 | }
85 |
86 | return ($aIndex < $bIndex) ? -1 : 1;
87 | }
88 | );
89 | }
90 |
91 | protected function getStorageColumns()
92 | {
93 | return [];
94 | }
95 | }
--------------------------------------------------------------------------------
/widgets/HorizontalMenu.php:
--------------------------------------------------------------------------------
1 | [
38 | * // Important: you need to specify url as 'controller/action',
39 | * // not just as 'controller' even if default action is used.
40 | * ['label' => 'Home', 'url' => ['site/index']],
41 | * // 'Products' menu item will be selected as long as the route is 'product/index'
42 | * ['label' => 'Products', 'url' => ['product/index'], 'items' => [
43 | * ['label' => 'New Arrivals', 'url' => ['product/index', 'tag' => 'new']],
44 | * ['label' => 'Most Popular', 'url' => ['product/index', 'tag' => 'popular']],
45 | * ]],
46 | * ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
47 | * ],
48 | * 'search' => [
49 | * // required, whether search box is visible. Defaults to 'true'.
50 | * 'visible' => true,
51 | * // optional, the configuration array for [[ActiveForm]].
52 | * 'form' => [],
53 | * // optional, input options with default values
54 | * 'input' => [
55 | * 'name' => 'search',
56 | * 'value' => '',
57 | * 'options' => [
58 | * 'placeholder' => 'Search...',
59 | * ]
60 | * ],
61 | * ]);
62 | *
63 | * // Mega Menu without search box
64 | * echo HorizontalMenu::widget([
65 | * 'items' => [
66 | * ['label' => 'Home', 'url' => ['site/index']],
67 | * [
68 | * 'label' => 'Mega Menu',
69 | * 'type' => HorizontalMenu::ITEM_TYPE_FULL_MEGA,
70 | * //optional, HTML text for last column
71 | * 'text' => 'Other HTML text',
72 | * 'items' => [
73 | * [
74 | * 'label' => 'Column 1', // First column title
75 | * 'items' => [
76 | * ['label' => 'Column 1 Item 1'],
77 | * ['label' => 'Column 1 Item 2'],
78 | * ]
79 | * ],
80 | * [
81 | * 'label' => 'Column 2', // Second column title
82 | * 'items' => [
83 | * ['label' => 'Column 2 Item 1'],
84 | * ['label' => 'Column 2 Item 2'],
85 | * ]
86 | * ],
87 | * ]
88 | * ],
89 | * ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
90 | * ],
91 | * ]);
92 | * ```
93 | *
94 | */
95 | class HorizontalMenu extends Menu
96 | {
97 | const ITEM_TYPE_CLASSIC = 'classic-menu-dropdown';
98 | const ITEM_TYPE_MEGA = 'mega-menu-dropdown';
99 | const ITEM_TYPE_FULL_MEGA = 'mega-menu-dropdown mega-menu-full';
100 | /**
101 | * @var string the template used to render the body of a menu which is a link.
102 | * In this template, the token `{url}` will be replaced with the corresponding link URL;
103 | * while `{label}` will be replaced with the link text.
104 | * This property will be overridden by the `template` option set in individual menu items via [[items]].
105 | */
106 | public $linkTemplate = '{icon}{label} ';
107 | /**
108 | * @var boolean whether to activate parent menu items when one of the corresponding child menu items is active.
109 | * The activated parent menu items will also have its CSS classes appended with [[activeCssClass]].
110 | */
111 | public $activateParents = true;
112 | /**
113 | * @var array Search options
114 | * is an array of the following structure:
115 | * ```php
116 | * [
117 | * // required, whether search box is visible
118 | * 'visible' => true,
119 | * // optional, ActiveForm options
120 | * 'form' => [],
121 | * // optional, input options with default values
122 | * 'input' => [
123 | * 'name' => 'search',
124 | * 'value' => '',
125 | * 'options' => [
126 | * 'placeholder' => 'Search...',
127 | * ]
128 | * ],
129 | * ]
130 | * ```
131 | */
132 | public $search = ['visible' => true];
133 | /**
134 | * @var string the template used to render a list of sub-menus.
135 | * In this template, the token `{items}` will be replaced with the renderer sub-menu items.
136 | */
137 | public $submenuTemplate = "\n\n";
138 | /**
139 | * @var string the template used to render the body of a dropdown which is a link.
140 | * In this template, the token `{label}` will be replaced with the link text;
141 | * the token `{url}` will be replaced with the corresponding link URL;
142 | */
143 | public $dropdownLinkTemplate = '{label} ';
144 | /**
145 | * @var string the template used to render the body of a dropdown which is a link for the Mega Menu.
146 | * In this template, the token `{label}` will be replaced with the link text;
147 | * the token `{url}` will be replaced with the corresponding link URL;
148 | */
149 | public $dropdownLinkMegaTemplate = '{label} ';
150 |
151 | /**
152 | * Renders the menu.
153 | */
154 | public function run()
155 | {
156 | Html::addCssClass($this->options, 'nav navbar-nav');
157 | echo Html::beginTag('div', ['class' => 'hor-menu hidden-sm hidden-xs']);
158 | if ($this->route === null && Yii::$app->controller !== null) {
159 | $this->route = Yii::$app->controller->getRoute();
160 | }
161 | if ($this->params === null) {
162 | $this->params = $_GET;
163 | }
164 | $items = $this->normalizeItems($this->items, $hasActiveChild);
165 | $options = $this->options;
166 | $tag = ArrayHelper::remove($options, 'tag', 'ul');
167 | $data = [$this->renderItems($items)];
168 | if (!isset($this->search['visible'])) {
169 | throw new InvalidConfigException("The 'visible' option of search is required.");
170 | }
171 | $data[] = Html::tag('li', $this->renderSearch());
172 | echo Html::tag($tag, implode("\n", $data), $options);
173 | echo Html::endTag('div');
174 | }
175 |
176 | /**
177 | * Recursively renders the menu items (without the container tag).
178 | * @param array $items the menu items to be rendered recursively
179 | * @param integer $level Indicates the level of the menu items
180 | * @param integer $type Item type. Valid values are:
181 | * HorizontalMenu::ITEM_TYPE_CLASSIC,
182 | * HorizontalMenu::ITEM_TYPE_MEGA,
183 | * HorizontalMenu::ITEM_TYPE_FULL_MEGA
184 | * @return string the rendering result
185 | */
186 | protected function renderItems($items, $level = 1, $type = null)
187 | {
188 | $n = count($items);
189 | $lines = [];
190 | foreach ($items as $i => $item) {
191 | $options = array_merge($this->itemOptions, ArrayHelper::getValue($item, 'options', []));
192 | $tag = ArrayHelper::remove($options, 'tag', 'li');
193 | $itemType = ($type === null) ? ArrayHelper::getValue($item, 'type', self::ITEM_TYPE_CLASSIC) : $type;
194 | $class = [];
195 | if ($item['active']) {
196 | $class[] = $this->activeCssClass;
197 | }
198 | if ($i === 0 && $this->firstItemCssClass !== null) {
199 | $class[] = $this->firstItemCssClass;
200 | }
201 | if ($i === $n - 1 && $this->lastItemCssClass !== null) {
202 | $class[] = $this->lastItemCssClass;
203 | }
204 | if (!empty($class)) {
205 | if (empty($options['class'])) {
206 | $options['class'] = implode(' ', $class);
207 | } else {
208 | $options['class'] .= ' ' . implode(' ', $class);
209 | }
210 | }
211 | if ($level == 1) {
212 | Html::addCssClass($options, $itemType);
213 | $item['template'] = ($itemType == self::ITEM_TYPE_CLASSIC)
214 | ? $this->dropdownLinkTemplate : $this->dropdownLinkMegaTemplate;
215 | if ($item['active']) {
216 | $item['label'] = Html::tag('span', '', ['class' => 'selected']) . $item['label'];
217 | }
218 | if (!empty($item['items'])) {
219 | $item['label'] .= ' ' . Html::tag('i', '',['class' => 'fa fa-angle-down']);
220 | }
221 | } else {
222 | if (!empty($item['items'])) {
223 | Html::addCssClass($options, 'dropdown-submenu');
224 | }
225 | }
226 | if ($itemType == self::ITEM_TYPE_CLASSIC) {
227 | $menu = $this->renderItem($item);
228 | if (!empty($item['items'])) {
229 | $menu .= strtr($this->submenuTemplate, [
230 | '{items}' => $this->renderItems($item['items'], $level + 1, $itemType),
231 | '{class}' => 'dropdown-menu',
232 | ]);
233 | }
234 | } else {
235 | if ($level == 1) {
236 | $menu = $this->renderItem($item);
237 | if (!empty($item['items'])) {
238 | $submenu = $this->renderItems($item['items'], $level + 1, $itemType);
239 | if ($itemType == self::ITEM_TYPE_FULL_MEGA) {
240 | $text = ArrayHelper::getValue($item, 'text', '');
241 | $submenu = Html::tag('div', $submenu, ['class' => 'col-md-7']);
242 | $submenu .= Html::tag('div', $text, ['class' => 'col-md-5']);
243 | }
244 | $submenu = Html::tag('div', $submenu, ['class' => 'row']);
245 | $submenu = Html::tag('div', $submenu, ['class' => 'mega-menu-content']);
246 | $submenu = Html::tag('li', $submenu);
247 | $menu .= strtr($this->submenuTemplate, [
248 | '{items}' => $submenu,
249 | '{class}' => 'dropdown-menu',
250 | ]);
251 | }
252 | } else {
253 | if (!empty($item['items'])) {
254 | $headerItem = $item;
255 | unset($headerItem['items']);
256 | $headerItem['template'] = '{label} ';
257 | array_unshift($item['items'], $headerItem);
258 | $lines[] = strtr($this->submenuTemplate, [
259 | '{items}' => $this->renderItems($item['items'], $level + 1, $itemType),
260 | '{class}' => 'col-md-4 mega-menu-submenu',
261 | ]);
262 | continue;
263 | } else {
264 | $item['icon'] = 'fa fa-angle-right';
265 | $menu = $this->renderItem($item);
266 | }
267 | }
268 | }
269 | $lines[] = Html::tag($tag, $menu, $options);
270 | }
271 |
272 | return implode("\n", $lines);
273 | }
274 |
275 | /**
276 | * Renders the content of a menu item.
277 | * Note that the container and the sub-menus are not rendered here.
278 | * @param array $item the menu item to be rendered. Please refer to [[items]] to see what data might be in the item.
279 | * @return string the rendering result
280 | */
281 | protected function renderItem($item)
282 | {
283 | $item['url'] = ArrayHelper::getValue($item, 'url', '#');
284 | $item['label'] = ArrayHelper::getValue($item, 'badge', '') . $item['label'];
285 | $item['icon'] = ArrayHelper::getValue($item, 'icon', '');
286 | if ($item['icon']) {
287 | $item['icon'] = Html::tag('i', '', ['class' => $item['icon']]);
288 | }
289 | $template = ArrayHelper::getValue($item, 'template', $this->linkTemplate);
290 |
291 | return strtr($template, [
292 | '{url}' => Url::toRoute($item['url']),
293 | '{label}' => $item['label'],
294 | '{icon}' => $item['icon'],
295 | ]);
296 | }
297 |
298 | /**
299 | * Renders search box
300 | * @return string the rendering result
301 | */
302 | protected function renderSearch()
303 | {
304 | $defaultFormOptions = ['options' => ['class' => 'sidebar-search']];
305 | $defaultInputOptions = [
306 | 'name' => 'search',
307 | 'value' => '',
308 | 'options' => [
309 | 'placeholder' => 'Search...',
310 | 'class' => 'form-control',
311 | ]
312 | ];
313 | $formOptions = ArrayHelper::merge(ArrayHelper::getValue($this->search, 'form', []), $defaultFormOptions);
314 | $inputOptions = ArrayHelper::merge(ArrayHelper::getValue($this->search, 'input', []), $defaultInputOptions);
315 | ob_start();
316 | ob_implicit_flush(false);
317 | echo Html::tag('span', ' ', ['class' => 'hor-menu-search-form-toggler']);
318 | echo ''; // end .search-form
327 | CoreActiveForm::end();
328 |
329 | return ob_get_clean();
330 | }
331 | }
--------------------------------------------------------------------------------
/widgets/InputWidget.php:
--------------------------------------------------------------------------------
1 | hasModel() && $this->name === null) {
42 | throw new InvalidConfigException("Either 'name', or 'model' and 'attribute' properties must be specified.");
43 | }
44 | if (!isset($this->options['id'])) {
45 | $this->options['id'] = $this->hasModel() ? Html::getInputId($this->model, $this->attribute) : $this->getId();
46 | }
47 | parent::init();
48 | }
49 |
50 | /**
51 | * @return boolean whether this widget is associated with a data model.
52 | */
53 | protected function hasModel()
54 | {
55 | return $this->model instanceof Model && $this->attribute !== null;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/widgets/IonRangeSlider.php:
--------------------------------------------------------------------------------
1 | 'ionRangeSlider',
21 | * 'clientOptions' => [
22 | * 'min' => 0,
23 | * 'max' => 5000,
24 | * 'from' => 1000, // default value
25 | * 'to' => 4000, // default value
26 | * 'type' => 'double',
27 | * 'step' => 1,
28 | * 'prefix' => "$",
29 | * 'prettify' => false,
30 | * 'hasGrid' => true
31 | * ],
32 | * ]);
33 | * ```
34 | * @see https://github.com/IonDen/ion.rangeSlider
35 | */
36 | class IonRangeSlider extends InputWidget
37 | {
38 | /**
39 | * @var string separator values
40 | */
41 | public $separator = ';';
42 |
43 | /**
44 | * Executes the widget.
45 | */
46 | public function run()
47 | {
48 | if ($this->hasModel()) {
49 | $values = explode($this->separator, $this->model->{$this->attribute});
50 | if (count($values) == 2) {
51 | $this->clientOptions['from'] = (int)$values[0];
52 | $this->clientOptions['to'] = (int)$values[1];
53 | }
54 | echo Html::activeTextInput($this->model, $this->attribute, $this->options);
55 | } else {
56 | $values = explode($this->separator, $this->value);
57 | if (count($values) == 2) {
58 | $this->clientOptions['from'] = (int)$values[0];
59 | $this->clientOptions['to'] = (int)$values[1];
60 | }
61 | echo Html::textInput($this->name, $this->value, $this->options);
62 | }
63 | IonRangeSliderAsset::register($this->view);
64 | $this->registerPlugin('ionRangeSlider');
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/widgets/IonRangeSliderAsset.php:
--------------------------------------------------------------------------------
1 | 'Link',
20 | * 'url' => 'http://yii2metronic.icron.org/',
21 | * 'icon' => 'm-icon-swapright m-icon-gray',
22 | * 'iconPosition' => Link::ICON_POSITION_LEFT,
23 | * ]);
24 | * ```
25 | */
26 | class Link extends Widget
27 | {
28 | // Icon position
29 | const ICON_POSITION_LEFT = 'left';
30 | const ICON_POSITION_RIGHT = 'right';
31 |
32 | /**
33 | * @var string The button label
34 | */
35 | public $label;
36 | /**
37 | * @var bool Whether the label should be HTML-encoded
38 | */
39 | public $encodeLabel = true;
40 | /**
41 | * @var string The link url
42 | */
43 | public $url = '#';
44 | /**
45 | * @var string The button icon
46 | */
47 | public $icon = 'm-icon-swapright m-icon-gray';
48 | /**
49 | * @var string Icon position
50 | * Valid values are 'left', 'right'
51 | */
52 | public $iconPosition = self::ICON_POSITION_RIGHT;
53 |
54 | /**
55 | * Initializes the widget.
56 | * @throws InvalidConfigException
57 | */
58 | public function init()
59 | {
60 | if ($this->label === null) {
61 | throw new InvalidConfigException("The 'label' option is required.");
62 | }
63 |
64 | if ($this->url === null) {
65 | $this->url = '#';
66 | }
67 | }
68 |
69 | /**
70 | * Renders the widget.
71 | */
72 | public function run()
73 | {
74 | $icon = ($this->icon === null) ? '' : Html::tag('i', '', ['class' => $this->icon]);
75 | if (strcasecmp($this->iconPosition, self::ICON_POSITION_LEFT) === 0) {
76 | $label = $icon . ' ' . Html::encode($this->label);
77 | } else {
78 | $label = Html::encode($this->label) . ' ' . $icon;
79 | }
80 | echo Html::a($label, $this->url, $this->options);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/widgets/Menu.php:
--------------------------------------------------------------------------------
1 | [
34 | * // Important: you need to specify url as 'controller/action',
35 | * // not just as 'controller' even if default action is used.
36 | * [
37 | * 'icon' => '',
38 | * 'label' => 'Home',
39 | * 'url' => ['site/index']
40 | * ],
41 | * // 'Products' menu item will be selected as long as the route is 'product/index'
42 | * ['label' => 'Products', 'url' => ['product/index'], 'items' => [
43 | * ['label' => 'New Arrivals', 'url' => ['product/index', 'tag' => 'new']],
44 | * ['label' => 'Most Popular', 'url' => ['product/index', 'tag' => 'popular']],
45 | * ]],
46 | * ['label' => 'Login', 'url' => ['site/login'], 'visible' => Yii::$app->user->isGuest],
47 | * ],
48 | * 'search' => [
49 | * // required, whether search box is visible. Defaults to 'true'.
50 | * 'visible' => true,
51 | * // optional, the configuration array for [[ActiveForm]].
52 | * 'form' => [],
53 | * // optional, input options with default values
54 | * 'input' => [
55 | * 'name' => 'search',
56 | * 'value' => '',
57 | * 'options' => [
58 | * 'placeholder' => 'Search...',
59 | * ]
60 | * ],
61 | * ]
62 | * ]);
63 | * ```
64 | *
65 | */
66 | class Menu extends \yii\widgets\Menu
67 | {
68 | /**
69 | * @var boolean whether to activate parent menu items when one of the corresponding child menu items is active.
70 | * The activated parent menu items will also have its CSS classes appended with [[activeCssClass]].
71 | */
72 | public $activateParents = true;
73 | /**
74 | * @var string the CSS class that will be assigned to the first item in the main menu or each submenu.
75 | */
76 | public $firstItemCssClass = 'start';
77 | /**
78 | * @var string the CSS class that will be assigned to the last item in the main menu or each submenu.
79 | */
80 | public $lastItemCssClass = 'last';
81 | /**
82 | * @var string the template used to render a list of sub-menus.
83 | * In this template, the token `{items}` will be replaced with the renderer sub-menu items.
84 | */
85 | public $submenuTemplate = "\n\n";
86 | /**
87 | * @var string the template used to render the body of a menu which is a link.
88 | * In this template, the token `{url}` will be replaced with the corresponding link URL;
89 | * while `{label}` will be replaced with the link text.
90 | * The token `{icon}` will be replaced with the corresponding link icon.
91 | * The token `{arrow}` will be replaced with the corresponding link arrow.
92 | * This property will be overridden by the `template` option set in individual menu items via [[items]].
93 | */
94 | public $linkTemplate = '{icon}{label}{arrow}{badge} ';
95 | /**
96 | * @var array Search options
97 | * is an array of the following structure:
98 | * ```php
99 | * [
100 | * // required, whether search box is visible
101 | * 'visible' => true,
102 | * // optional, ActiveForm options
103 | * 'form' => [],
104 | * // optional, input options with default values
105 | * 'input' => [
106 | * 'name' => 'search',
107 | * 'value' => '',
108 | * 'options' => [
109 | * 'placeholder' => 'Search...',
110 | * ]
111 | * ],
112 | * ]
113 | * ```
114 | */
115 | public $search = ['visible' => true];
116 | /**
117 | * @var bool Indicates whether menu is visible.
118 | */
119 | public $visible = true;
120 |
121 | /**
122 | * Initializes the widget.
123 | */
124 | public function init()
125 | {
126 | Metronic::registerThemeAsset($this->getView());
127 | Html::addCssClass($this->options, 'page-sidebar-menu');
128 | if (!$this->visible || Metronic::getComponent()->layoutOption == Metronic::LAYOUT_FULL_WIDTH) {
129 | Html::addCssClass($this->options, 'visible-sm visible-xs');
130 | }
131 | }
132 |
133 | /**
134 | * Renders the widget.
135 | */
136 | public function run()
137 | {
138 | echo Html::beginTag('div', ['class' => 'page-sidebar navbar-collapse collapse']);
139 | if ($this->route === null && Yii::$app->controller !== null) {
140 | $this->route = Yii::$app->controller->getRoute();
141 | }
142 | if ($this->params === null) {
143 | $this->params = $_GET;
144 | }
145 | $items = $this->normalizeItems($this->items, $hasActiveChild);
146 | $options = $this->options;
147 | $tag = ArrayHelper::remove($options, 'tag', 'ul');
148 | $data = [Html::tag('li', Html::tag('div', '', ['class' => 'sidebar-toggler hidden-phone']))];
149 |
150 | if (!isset($this->search['visible'])) {
151 | throw new InvalidConfigException("The 'visible' option of search is required.");
152 | }
153 | $data[] = Html::tag('li', $this->renderSearch());
154 | $data[] = $this->renderItems($items);
155 | echo Html::tag($tag, implode("\n", $data), $options);
156 | echo Html::endTag('div');
157 | }
158 |
159 | /**
160 | * Renders search box
161 | * @return string the rendering result
162 | */
163 | public function renderSearch()
164 | {
165 | $defaultFormOptions = ['options' => ['class' => 'sidebar-search']];
166 | $defaultInputOptions = ['name' => 'search', 'value' => '', 'options' => ['placeholder' => 'Search...']];
167 | $formOptions = ArrayHelper::merge(ArrayHelper::getValue($this->search, 'form', []), $defaultFormOptions);
168 | $inputOptions = ArrayHelper::merge(ArrayHelper::getValue($this->search, 'input', []), $defaultInputOptions);
169 | ob_start();
170 | ob_implicit_flush(false);
171 | CoreActiveForm::begin($formOptions);
172 | echo '';
179 | CoreActiveForm::end();
180 |
181 | return ob_get_clean();
182 | }
183 |
184 | /**
185 | * Recursively renders the menu items (without the container tag).
186 | * @param array $items the menu items to be rendered recursively
187 | * @param integer $level the item level, starting with 1
188 | * @return string the rendering result
189 | */
190 | protected function renderItems($items, $level = 1)
191 | {
192 | $n = count($items);
193 | $lines = [];
194 | foreach ($items as $i => $item) {
195 | $options = array_merge($this->itemOptions, ArrayHelper::getValue($item, 'options', []));
196 | $tag = ArrayHelper::remove($options, 'tag', 'li');
197 | $class = [];
198 | if ($item['active']) {
199 | $class[] = $this->activeCssClass;
200 | }
201 | if ($i === 0 && $this->firstItemCssClass !== null) {
202 | $class[] = $this->firstItemCssClass;
203 | }
204 | if ($i === $n - 1 && $this->lastItemCssClass !== null) {
205 | $class[] = $this->lastItemCssClass;
206 | }
207 | if (!empty($class)) {
208 | if (empty($options['class'])) {
209 | $options['class'] = implode(' ', $class);
210 | } else {
211 | $options['class'] .= ' ' . implode(' ', $class);
212 | }
213 | }
214 |
215 | // set parent flag
216 | $item['level'] = $level;
217 | $menu = $this->renderItem($item);
218 | if (!empty($item['items'])) {
219 | $menu .= strtr($this->submenuTemplate, [
220 | '{items}' => $this->renderItems($item['items'], $level + 1),
221 | ]);
222 | }
223 | $lines[] = Html::tag($tag, $menu, $options);
224 | }
225 | return implode("\n", $lines);
226 | }
227 |
228 | /**
229 | * Renders the content of a menu item.
230 | * Note that the container and the sub-menus are not rendered here.
231 | * @param array $item the menu item to be rendered. Please refer to [[items]] to see what data might be in the item.
232 | * @return string the rendering result
233 | */
234 | protected function renderItem($item)
235 | {
236 | $icon = isset($item['icon']) ? Html::tag('i', '', ['class' => $item['icon']]) : '';
237 | $label = ($item['level'] == 1) ?
238 | Html::tag('span', $item['label'], ['class' => 'title']) : (' ' . $item['label']);
239 | $arrow = !empty($item['items']) ?
240 | Html::tag('span', '', ['class' => 'arrow' . ($item['active'] ? ' open' : '')]) : '';
241 |
242 | if ($item['active'] && $item['level'] == 1) {
243 | $arrow = Html::tag('div', '', ['class' => 'selected']) . $arrow;
244 | }
245 | $badge = ArrayHelper::getValue($item, 'badge', '');
246 | if (isset($item['url'])) {
247 | $template = ArrayHelper::getValue($item, 'template', $this->linkTemplate);
248 | return strtr($template, [
249 | '{url}' => Url::toRoute($item['url']),
250 | '{label}' => $label,
251 | '{icon}' => $icon,
252 | '{arrow}' => $arrow,
253 | '{badge}' => $badge,
254 | ]);
255 | } else {
256 | $template = ArrayHelper::getValue($item, 'template', $this->labelTemplate);
257 | return strtr($template, [
258 | '{label}' => $label,
259 | '{icon}' => $icon,
260 | '{arrow}' => $arrow,
261 | '{badge}' => $badge,
262 | ]);
263 | }
264 | }
265 | }
--------------------------------------------------------------------------------
/widgets/Modal.php:
--------------------------------------------------------------------------------
1 | 'Configuration',
22 | * 'toggleButton' => [
23 | * 'type' => Button::TYPE_M_GREEN,
24 | * 'label' => 'Modal',
25 | * 'icon' => 'fa fa-bell-o',
26 | * 'fullWidth' => true,
27 | * 'stackable' => true,
28 | * ],
29 | * ]);
30 | *
31 | * echo 'Say hello...';
32 | *
33 | * Modal::end();
34 | * ~~~
35 | *
36 | * @see http://twitter.github.io/bootstrap/javascript.html#modals
37 | */
38 | class Modal extends Widget
39 | {
40 | /**
41 | * @var string the title in the modal window.
42 | */
43 | public $title;
44 | /**
45 | * @var string the footer content in the modal window.
46 | */
47 | public $footer;
48 | /**
49 | * @var array the options for rendering the close button tag.
50 | * The close button is displayed in the header of the modal window. Clicking
51 | * on the button will hide the modal window. If this is null, no close button will be rendered.
52 | *
53 | * The following special options are supported:
54 | *
55 | * - tag: string, the tag name of the button. Defaults to 'button'.
56 | * - label: string, the label of the button. Defaults to '×'.
57 | *
58 | * The rest of the options will be rendered as the HTML attributes of the button tag.
59 | * Please refer to the [Modal plugin help](http://twitter.github.com/bootstrap/javascript.html#modals)
60 | * for the supported HTML attributes.
61 | */
62 | public $closeButton = [];
63 | /**
64 | * @var array the configuration array for [[Button]].
65 | */
66 | public $toggleButton = [];
67 | /**
68 | * @var bool indicates whether the modal in full screen width.
69 | */
70 | public $fullWidth = false;
71 | /**
72 | * @var bool indicates whether the modal is stacked.
73 | */
74 | public $stackable = false;
75 |
76 | /**
77 | * Initializes the widget.
78 | */
79 | public function init()
80 | {
81 | parent::init();
82 |
83 | $this->initOptions();
84 |
85 | echo $this->renderToggleButton() . "\n";
86 | echo Html::beginTag('div', $this->options) . "\n";
87 | echo $this->renderHeader() . "\n";
88 | echo $this->renderBodyBegin() . "\n";
89 | }
90 |
91 | /**
92 | * Renders the widget.
93 | */
94 | public function run()
95 | {
96 | echo "\n" . $this->renderBodyEnd();
97 | echo "\n" . $this->renderFooter();
98 | echo "\n" . Html::endTag('div');
99 |
100 | ModalAsset::register($this->view);
101 | $this->registerPlugin('spinner');
102 | }
103 |
104 | /**
105 | * Renders the header HTML markup of the modal
106 | * @return string the rendering result
107 | */
108 | protected function renderHeader()
109 | {
110 | $button = $this->renderCloseButton();
111 | if ($button !== null) {
112 | $this->title = $button . "\n" . Html::tag('h4', $this->title, ['class' => 'modal-title']);
113 | }
114 | if ($this->title !== null) {
115 | return Html::tag('div', "\n" . $this->title . "\n", ['class' => 'modal-header']);
116 | } else {
117 | return null;
118 | }
119 | }
120 |
121 | /**
122 | * Renders the opening tag of the modal body.
123 | * @return string the rendering result
124 | */
125 | protected function renderBodyBegin()
126 | {
127 | return Html::beginTag('div', ['class' => 'modal-body']);
128 | }
129 |
130 | /**
131 | * Renders the closing tag of the modal body.
132 | * @return string the rendering result
133 | */
134 | protected function renderBodyEnd()
135 | {
136 | return Html::endTag('div');
137 | }
138 |
139 | /**
140 | * Renders the HTML markup for the footer of the modal
141 | * @return string the rendering result
142 | */
143 | protected function renderFooter()
144 | {
145 | if ($this->footer !== null) {
146 | return Html::tag('div', "\n" . $this->footer . "\n", ['class' => 'modal-footer']);
147 | } else {
148 | return null;
149 | }
150 | }
151 |
152 | /**
153 | * Renders the toggle button.
154 | * @return string the rendering result
155 | */
156 | protected function renderToggleButton()
157 | {
158 | if (!empty($this->toggleButton)) {
159 | return Button::widget($this->toggleButton);
160 | } else {
161 | return null;
162 | }
163 | }
164 |
165 | /**
166 | * Renders the close button.
167 | * @return string the rendering result
168 | */
169 | protected function renderCloseButton()
170 | {
171 | if ($this->closeButton !== null) {
172 | $tag = ArrayHelper::remove($this->closeButton, 'tag', 'button');
173 | $label = ArrayHelper::remove($this->closeButton, 'label', '×');
174 | if ($tag === 'button' && !isset($this->closeButton['type'])) {
175 | $this->closeButton['type'] = 'button';
176 | }
177 | return Html::tag($tag, $label, $this->closeButton);
178 | } else {
179 | return null;
180 | }
181 | }
182 |
183 | /**
184 | * Initializes the widget options.
185 | * This method sets the default values for various options.
186 | */
187 | protected function initOptions()
188 | {
189 | $this->options = array_merge([
190 | 'class' => 'fade',
191 | 'tabindex' => -1,
192 | ], $this->options);
193 | Html::addCssClass($this->options, 'modal');
194 | if ($this->fullWidth) {
195 | Html::addCssClass($this->options, 'container');
196 | }
197 | if ($this->stackable) {
198 | $this->options = array_merge($this->options, ['data-focus-on' => 'input:first']);
199 | }
200 | if ($this->clientOptions !== false) {
201 | $this->clientOptions = array_merge(['show' => false], $this->clientOptions);
202 | }
203 |
204 | if ($this->closeButton !== null) {
205 | $this->closeButton = array_merge([
206 | 'data-dismiss' => 'modal',
207 | 'aria-hidden' => 'true',
208 | 'class' => 'close',
209 | ], $this->closeButton);
210 | }
211 |
212 | if (!empty($this->toggleButton)) {
213 | $this->toggleButton = array_merge([
214 | 'options' => ['data-toggle' => 'modal'],
215 | ], $this->toggleButton);
216 | if (!isset($this->toggleButton['options']['data-target']) && !isset($this->toggleButton['options']['href'])) {
217 | $this->toggleButton['options']['data-target'] = '#' . $this->options['id'];
218 | }
219 | }
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/widgets/ModalAsset.php:
--------------------------------------------------------------------------------
1 | 'select1',
19 | * 'data' => ['1' => 'Item 1', '2' => 'Item 2'],
20 | * ]);
21 | * ```
22 | *
23 | * @see http://loudev.com/
24 | */
25 | class MultiSelect extends InputWidget
26 | {
27 | /**
28 | * @var bool indicates whether the multiSelect is disabled or not.
29 | */
30 | public $disabled;
31 | /**
32 | * @var array the option data items. The array keys are option values, and the array values
33 | * are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
34 | * For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
35 | * If you have a list of data models, you may convert them into the format described above using
36 | * [[\yii\helpers\ArrayHelper::map()]].
37 | */
38 | public $data = [];
39 |
40 | /**
41 | * Initializes the widget.
42 | */
43 | public function init()
44 | {
45 | parent::init();
46 | $this->options['multiple'] = true;
47 | if ($this->disabled) {
48 | $this->options['disabled'] = true;
49 | }
50 | Html::addCssClass($this->options, 'multi-select');
51 | }
52 | /**
53 | * Executes the widget.
54 | */
55 | public function run()
56 | {
57 | if ($this->hasModel()) {
58 | echo Html::activeDropDownList($this->model, $this->attribute, $this->data, $this->options);
59 | } else {
60 | echo Html::dropDownList($this->name, $this->value, $this->data, $this->options);
61 | }
62 | MultiSelectAsset::register($this->view);
63 | $this->registerPlugin('multiSelect');
64 | }
65 |
66 |
67 | }
--------------------------------------------------------------------------------
/widgets/MultiSelectAsset.php:
--------------------------------------------------------------------------------
1 | [
23 | * [
24 | * 'icon' => 'fa fa-warning',
25 | * 'badge' => Badge::widget(['label' => 'New', 'round' => false]),
26 | * 'label' => 'Home',
27 | * 'url' => ['site/index'],
28 | * 'linkOptions' => [...],
29 | * ],
30 | * [
31 | * 'label' => 'Dropdown',
32 | * 'items' => [
33 | * ['label' => 'Level 1 - Dropdown A', 'url' => '#'],
34 | * ' ',
35 | * '',
36 | * ['label' => 'Level 1 - Dropdown B', 'url' => '#'],
37 | * ],
38 | * ],
39 | * ],
40 | * ]);
41 | * ```
42 | *
43 | * Note: Multilevel dropdowns beyond Level 1 are not supported in Bootstrap 3.
44 | */
45 | class Nav extends \yii\bootstrap\Nav
46 | {
47 | // position
48 | const POS_LEFT = '';
49 | const POS_RIGHT = 'pull-right';
50 |
51 | /**
52 | * @var array list of items in the nav widget. Each array element represents a single
53 | * menu item which can be either a string or an array with the following structure:
54 | *
55 | * - label: string, required, the nav item label.
56 | * - icon: string, optional, the nav item icon.
57 | * - badge: array, optional
58 | * - url: optional, the item's URL. Defaults to "#".
59 | * - visible: boolean, optional, whether this menu item is visible. Defaults to true.
60 | * - linkOptions: array, optional, the HTML attributes of the item's link.
61 | * - options: array, optional, the HTML attributes of the item container (LI).
62 | * - active: boolean, optional, whether the item should be on active state or not.
63 | * - items: array|string, optional, the configuration array for creating a [[Dropdown]] widget,
64 | * or a string representing the dropdown menu. Note that Bootstrap does not support sub-dropdown menus.
65 | *
66 | * If a menu item is a string, it will be rendered directly without HTML encoding.
67 | */
68 | public $items = [];
69 | /**
70 | * @var string the nav position
71 | */
72 | public $position = self::POS_RIGHT;
73 |
74 | /**
75 | * Initializes the widget.
76 | */
77 | public function init()
78 | {
79 | Html::addCssClass($this->options, 'navbar-nav');
80 | Html::addCssClass($this->options, $this->position);
81 | parent::init();
82 | }
83 |
84 | /**
85 | * Renders a widget's item.
86 | * @param string|array $item the item to render.
87 | * @return string the rendering result.
88 | * @throws InvalidConfigException
89 | */
90 | public function renderItem($item)
91 | {
92 | if (is_string($item)) {
93 | return $item;
94 | }
95 | if (!isset($item['label']) && !isset($item['icon'])) {
96 | throw new InvalidConfigException("The 'label' option is required.");
97 | }
98 | $type = ArrayHelper::getValue($item, 'type', '');
99 | $options = ArrayHelper::getValue($item, 'options', []);
100 | if ($type === 'user') {
101 | $label = $item['label'];
102 | Html::addCssClass($options, 'user');
103 | } else {
104 | $label = $this->encodeLabels ? Html::encode($item['label']) : $item['label'];
105 | }
106 | $icon = ArrayHelper::getValue($item, 'icon', null);
107 | if ($icon) {
108 | $label = Html::tag('i', '', ['alt' => $label, 'class' => $icon]);
109 | }
110 | $label .= ArrayHelper::getValue($item, 'badge', '');
111 | $items = ArrayHelper::getValue($item, 'items');
112 | $url = Url::toRoute(ArrayHelper::getValue($item, 'url', '#'));
113 | $linkOptions = ArrayHelper::getValue($item, 'linkOptions', []);
114 |
115 | if (isset($item['active'])) {
116 | $active = ArrayHelper::remove($item, 'active', false);
117 | } else {
118 | $active = $this->isItemActive($item);
119 | }
120 |
121 | if ($active) {
122 | Html::addCssClass($options, 'active');
123 | }
124 |
125 | if ($items !== null) {
126 | $linkOptions['data-toggle'] = 'dropdown';
127 | $linkOptions['data-hover'] = 'dropdown';
128 | $linkOptions['data-close-others'] = 'true';
129 | Html::addCssClass($options, 'dropdown');
130 | Html::addCssClass($linkOptions, 'dropdown-toggle');
131 |
132 | if (is_array($items)) {
133 | $items = Dropdown::widget([
134 | 'title' => ArrayHelper::getValue($item, 'title', ''),
135 | 'more' => ArrayHelper::getValue($item, 'more', []),
136 | 'scroller' => ArrayHelper::getValue($item, 'scroller', []),
137 | 'items' => $items,
138 | 'encodeLabels' => $this->encodeLabels,
139 | 'clientOptions' => false,
140 | 'options' => $type !== 'user' ? ['class' => 'extended'] : [],
141 | ]);
142 | }
143 | }
144 |
145 | return Html::tag('li', Html::a($label, $url, $linkOptions) . $items, $options);
146 | }
147 |
148 | /**
149 | * Renders user item.
150 | * @param $label string User label
151 | * @param $photo string User photo url
152 | * @return string the rendering result
153 | */
154 | public static function userItem($label, $photo)
155 | {
156 | $lines = [];
157 | $lines[] = Html::img($photo, ['alt' => $label]);
158 | $lines[] = Html::tag('span', $label, ['class' => 'username']);
159 | $lines[] = Html::tag('i', '', ['class' => 'fa fa-angle-down']);
160 | return implode("\n", $lines);
161 | }
162 | }
--------------------------------------------------------------------------------
/widgets/NavBar.php:
--------------------------------------------------------------------------------
1 | 'NavBar Test',
26 | * 'brandLogoUrl' => '/img/logo.png',
27 | * ]);
28 | * echo Nav::widget([
29 | * 'items' => [
30 | * ['label' => 'Home', 'url' => ['/site/index']],
31 | * ['label' => 'About', 'url' => ['/site/about']],
32 | * ],
33 | * ]);
34 | * NavBar::end();
35 | * ```
36 | *
37 | * @see http://twitter.github.io/bootstrap/components.html#navbar
38 | */
39 | class NavBar extends \yii\bootstrap\NavBar
40 | {
41 | /**
42 | * @var string the url to logo of the brand.
43 | */
44 | public $brandLogoUrl;
45 |
46 | /**
47 | * Renders toggle button
48 | * @return string the rendering result
49 | */
50 | protected function renderToggleButton()
51 | {
52 | return Html::tag(
53 | 'a',
54 | Html::img(Metronic::getAssetsUrl($this->view) . '/img/menu-toggler.png'),
55 | [
56 | 'href' => '#',
57 | 'class' => 'navbar-toggle',
58 | 'data-toggle' => 'collapse',
59 | 'data-target' => '.navbar-collapse'
60 | ]
61 | );
62 | }
63 |
64 | /**
65 | * Renders Brand
66 | * @return string the rendering result
67 | */
68 | protected function renderBrand()
69 | {
70 | if ($this->brandLogoUrl) {
71 | $content = Html::img($this->brandLogoUrl, ['class' => 'img-responsive','alt' => $this->brandLabel]);
72 | } else {
73 | $content = $this->brandLabel;
74 | }
75 | Html::addCssClass($this->brandOptions, 'navbar-brand');
76 | $this->brandOptions['href'] = $this->brandUrl;
77 | return Html::tag('a', $content, $this->brandOptions);
78 | }
79 |
80 | /**
81 | * Initializes the widget.
82 | */
83 | public function init()
84 | {
85 | if (!isset($this->options['id'])) {
86 | $this->options['id'] = $this->getId();
87 | }
88 | Html::addCssClass($this->options, 'mega-menu');
89 | echo Html::beginTag('div', $this->options);
90 | echo Html::beginTag('div', ['class' => 'header-inner']);
91 | echo $this->renderBrand();
92 | echo $this->renderToggleButton();
93 | }
94 |
95 | /**
96 | * Executes the widget.
97 | */
98 | public function run()
99 | {
100 | echo Html::endTag('div');
101 | echo Html::endTag('div');
102 | echo Html::tag('div', '', ['class' => 'clearfix']);
103 | }
104 | }
--------------------------------------------------------------------------------
/widgets/Note.php:
--------------------------------------------------------------------------------
1 | 'Success! Some Header Goes Here',
18 | * 'body' => 'Duis mollis, est non commodo luctus',
19 | * 'type' => Note::TYPE_INFO,
20 | * ]);
21 | * ```
22 | *
23 | * The following example will show the content enclosed between the [[begin()]]
24 | * and [[end()]] calls within the alert box:
25 | * ```php
26 | * Note::begin(['type' => Note::TYPE_DANGER]);
27 | * echo 'Some title and body';
28 | * Note::end();
29 | * ```
30 | */
31 | class Note extends Widget
32 | {
33 | const TYPE_DANGER = 'danger';
34 | const TYPE_INFO = 'info';
35 | const TYPE_SUCCESS = 'success';
36 | const TYPE_WARNING = 'warning';
37 |
38 | /**
39 | * @var string the note title
40 | */
41 | public $title;
42 | /**
43 | * @var string the note body
44 | */
45 | public $body;
46 | /**
47 | * @var string the note type.
48 | * Valid values are 'danger', 'info', 'success', 'warning'.
49 | */
50 | public $type = self::TYPE_SUCCESS;
51 |
52 | /**
53 | * Initializes the widget.
54 | */
55 | public function init()
56 | {
57 | parent::init();
58 | Html::addCssClass($this->options, 'note note-' . $this->type);
59 | echo Html::beginTag('div', $this->options);
60 | echo $this->renderTitle();
61 | }
62 |
63 | /**
64 | * Executes the widget.
65 | */
66 | public function run()
67 | {
68 | echo $this->renderBody();
69 | echo Html::endTag('div');
70 | }
71 |
72 | /**
73 | * Renders title
74 | * @return string the rendering result
75 | */
76 | public function renderTitle()
77 | {
78 | return !empty($this->title) ? Html::tag('h4', $this->title, ['class' => 'block']) : '';
79 | }
80 |
81 | /**
82 | * Renders body
83 | * @return string the rendering result
84 | */
85 | public function renderBody()
86 | {
87 | return !empty($this->body) ? Html::tag('p', $this->body) : '';
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/widgets/Notification.php:
--------------------------------------------------------------------------------
1 | 'Success! Some Header Goes Here',
22 | * 'body' => 'Duis mollis, est non commodo luctus',
23 | * 'type' => Notification::TYPE_INFO,
24 | * 'openButton' => [
25 | * 'type' => Button::TYPE_M_GREEN,
26 | * 'label' => 'Notification',
27 | * 'icon' => 'fa fa-bell-o',
28 | * ]
29 | * ]);
30 | * ```
31 | *
32 | * The following example will show the content enclosed between the [[begin()]]
33 | * and [[end()]] calls within the alert box:
34 | * ```php
35 | * Notification::begin(['type' => Notification::TYPE_DANGER]);
36 | * echo 'Some title and body';
37 | * Notification::end();
38 | * ```
39 | * @see https://github.com/CodeSeven/toastr
40 | */
41 | class Notification extends Widget
42 | {
43 | // type
44 | const TYPE_ERROR = 'error';
45 | const TYPE_INFO = 'info';
46 | const TYPE_SUCCESS = 'success';
47 | const TYPE_WARNING = 'warning';
48 | // position
49 | const POSITION_TOP_RIGHT = 'toast-top-right';
50 | const POSITION_BOTTOM_RIGHT = 'toast-bottom-right';
51 | const POSITION_BOTTOM_LEFT = 'toast-bottom-left';
52 | const POSITION_TOP_LEFT = 'toast-top-left';
53 | const POSITION_TOP_CENTER = 'toast-top-center';
54 | const POSITION_BOTTOM_CENTER = 'toast-bottom-center';
55 | const POSITION_FULL_WIDTH = 'toast-top-full-width';
56 | // easing
57 | const EASING_LINEAR = 'linear';
58 | const EASING_SWING = 'swing';
59 |
60 | /**
61 | * @var string the notification title
62 | */
63 | public $title = '';
64 | /**
65 | * @var string the notification body
66 | */
67 | public $body = '';
68 | /**
69 | * @var string the notification type.
70 | * Valid values are 'danger', 'info', 'success', 'warning'.
71 | */
72 | public $type = self::TYPE_SUCCESS;
73 | /**
74 | * @var array the configuration array for [[Button]].
75 | */
76 | public $openButton = [];
77 |
78 | /**
79 | * Executes the widget.
80 | */
81 | public function init()
82 | {
83 | parent::init();
84 | $this->initOptions();
85 | ob_start();
86 | ob_implicit_flush(false);
87 | }
88 |
89 | public function run()
90 | {
91 | $this->body .= ob_get_clean();
92 | if (!empty($this->openButton)) {
93 | /** @var Button $widget */
94 | $js = 'toastr.options = ' . Json::encode($this->clientOptions) . ';';
95 | $this->view->registerJs($js, View::POS_READY);
96 | $this->initOpenButton();
97 | } else {
98 | return null;
99 | }
100 | NotificationAsset::register($this->view);
101 | }
102 |
103 | /**
104 | * Initializes the widget options.
105 | * This method sets the default values for various options.
106 | */
107 | public function initOptions()
108 | {
109 | $defaultOptions = [
110 | 'closeButton'=> true,
111 | 'debug'=> false,
112 | 'positionClass'=> 'toast-top-right',
113 | 'onclick'=> null,
114 | 'showDuration'=> '1000',
115 | 'hideDuration'=> '1000',
116 | 'timeOut'=> '5000',
117 | 'extendedTimeOut'=> '1000',
118 | 'showEasing'=> 'swing',
119 | 'hideEasing'=> 'linear',
120 | 'showMethod'=> 'fadeIn',
121 | 'hideMethod'=> 'fadeOut'
122 | ];
123 |
124 | $this->clientOptions = array_merge($defaultOptions, $this->clientOptions);
125 | }
126 |
127 | /**
128 | * Initializes the widget Button options.
129 | * This method sets the default values for various options.
130 | */
131 | public function initOpenButton()
132 | {
133 | $widget = Button::begin($this->openButton);
134 | $msg = "'{$this->body}', '{$this->title}'";
135 | $jsOpen = 'toastr.' . $this->type . '(' . $msg . ')';
136 | if(!isset($widget->clientEvents['click'])) {
137 | $widget->clientEvents['click'] = "function(){{$jsOpen};}";
138 | }
139 | $widget->run();
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/widgets/NotificationAsset.php:
--------------------------------------------------------------------------------
1 | 'fa fa-bell-o',
24 | * 'title' => 'Title Portlet',
25 | * ]);
26 | * echo 'Body portlet';
27 | * Portlet::end();
28 | *
29 | * // Portlet with tools, actions, scroller, events and remote content
30 | * Portlet::begin([
31 | * 'title' => 'Extended Portlet',
32 | * 'scroller' => [
33 | * 'height' => 150,
34 | * 'footer' => ['label' => 'Show all', 'url' => '#'],
35 | * ],
36 | * 'clientOptions' => [
37 | * 'loadSuccess' => new \yii\web\JsExpression('function(){ console.log("load success"); }'),
38 | * 'remote' => '/?r=site/about',
39 | * ],
40 | * 'clientEvents' => [
41 | * 'close.mr.portlet' => 'function(e) { console.log("portlet closed"); e.preventDefault(); }'
42 | * ],
43 | * 'tools' => [
44 | * Portlet::TOOL_RELOAD,
45 | * Portlet::TOOL_MINIMIZE,
46 | * Portlet::TOOL_CLOSE,
47 | * ],
48 | * ]);
49 | * ```
50 | *
51 | * @see http://yii2metronic.icron.org/components.html#portlet
52 | * @author icron.org
53 | * @since 1.0
54 | */
55 | class Portlet extends Widget
56 | {
57 | //types of the portlet
58 | const TYPE_BOX = 'box';
59 | const TYPE_SOLID = 'solid';
60 | const TYPE_NONE = '';
61 | // color scheme
62 | const COLOR_LIGHT_BLUE = 'light-blue';
63 | const COLOR_BLUE = 'blue';
64 | const COLOR_RED = 'red';
65 | const COLOR_YELLOW = 'yellow';
66 | const COLOR_GREEN = 'green';
67 | const COLOR_PURPLE = 'purple';
68 | const COLOR_LIGHT_GRAY = 'light-grey';
69 | const COLOR_GRAY = 'grey';
70 | //tools
71 | const TOOL_MINIMIZE = 'collapse';
72 | const TOOL_MODAL = 'modal';
73 | const TOOL_RELOAD = 'reload';
74 | const TOOL_CLOSE = 'remove';
75 | /**
76 | * @var string The portlet title
77 | */
78 | public $title;
79 | /**
80 | * @var string The portlet icon
81 | */
82 | public $icon;
83 | /**
84 | * @var string The portlet type
85 | * Valid values are 'box', 'solid', ''
86 | */
87 | public $type = self::TYPE_BOX;
88 | /**
89 | * @var string The portlet color
90 | * Valid values are 'light-blue', 'blue', 'red', 'yellow', 'green', 'purple', 'light-grey', 'grey'
91 | */
92 | public $color = self::COLOR_BLUE;
93 | /**
94 | * @var array List of actions, where each element must be specified as a string.
95 | */
96 | public $actions = [];
97 | /**
98 | * @var array The portlet tools
99 | * Valid values are 'collapse', 'modal', 'reload', 'remove'
100 | */
101 | public $tools = [];
102 | /**
103 | * @var array Scroller options
104 | * is an array of the following structure:
105 | * ```php
106 | * [
107 | * // required, height of the body portlet as a px
108 | * 'height' => 150,
109 | * // optional, HTML attributes of the scroller
110 | * 'options' => [],
111 | * // optional, footer of the scroller. May contain string or array(the options of Link component)
112 | * 'footer' => [
113 | * 'label' => 'Show all',
114 | * ],
115 | * ]
116 | * ```
117 | */
118 | public $scroller = [];
119 | /**
120 | * @var bool Whether the portlet should be bordered
121 | */
122 | public $bordered = false;
123 | /**
124 | * @var array The HTML attributes for the widget container
125 | */
126 | public $options = [];
127 | /**
128 | * @var array The HTML attributes for the widget body container
129 | */
130 | public $bodyOptions = [];
131 | /**
132 | * @var array The HTML attributes for the widget body container
133 | */
134 | public $headerOptions = [];
135 |
136 | /**
137 | * Initializes the widget.
138 | */
139 | public function init()
140 | {
141 | parent::init();
142 | Html::addCssClass($this->options, 'portlet ' . $this->color . ' ' . $this->type);
143 | echo Html::beginTag('div', $this->options);
144 | Html::addCssClass($this->headerOptions, 'portlet-title');
145 | echo Html::beginTag('div', $this->headerOptions);
146 | $icon = ($this->icon) ? Html::tag('i', '', ['class' => 'fa ' . $this->icon]) : '';
147 | echo Html::tag('div', $icon . ' ' . $this->title, ['class' => 'caption']);
148 |
149 | if (!empty($this->tools)) {
150 | $tools = [];
151 | foreach ($this->tools as $tool) {
152 | $class = '';
153 | switch ($tool) {
154 | case self::TOOL_CLOSE :
155 | $class = 'remove';
156 | break;
157 |
158 | case self::TOOL_MINIMIZE :
159 | $class = 'collapse';
160 | break;
161 |
162 | case self::TOOL_RELOAD :
163 | $class = 'reload';
164 | break;
165 | }
166 | $tools[] = Html::tag('a', '', ['class' => $class, 'href' => '']);
167 | }
168 | echo Html::tag('div', implode("\n", $tools), ['class' => 'tools']);
169 | }
170 |
171 | if (!empty($this->actions)) {
172 | echo Html::tag('div', implode("\n", $this->actions), ['class' => 'actions']);
173 | }
174 | echo Html::endTag('div');
175 | Html::addCssClass($this->bodyOptions, 'portlet-body');
176 | echo Html::beginTag('div', $this->bodyOptions);
177 | if (!empty($this->scroller)) {
178 | if (!isset($this->scroller['height'])) {
179 | throw new InvalidConfigException("The 'height' option of the scroller is required.");
180 | }
181 | $options = ArrayHelper::getValue($this->scroller, 'options', []);
182 | echo Html::beginTag(
183 | 'div',
184 | ArrayHelper::merge(
185 | ['class' => 'scroller', 'data-always-visible' => '1', 'data-rail-visible' => '0'],
186 | $options,
187 | ['style' => 'height:' . $this->scroller['height'] . 'px;']
188 | )
189 | );
190 | }
191 | }
192 |
193 | /**
194 | * Renders the widget.
195 | */
196 | public function run()
197 | {
198 | if (!empty($this->scroller)) {
199 | echo Html::endTag('div');
200 | $footer = ArrayHelper::getValue($this->scroller, 'footer', '');
201 | if (!empty($footer)) {
202 | echo Html::beginTag('div', ['class' => 'scroller-footer']);
203 | if (is_array($footer)) {
204 | echo Html::tag('div', Link::widget($footer), ['class' => 'pull-right']);
205 | } elseif (is_string($footer)) {
206 | echo $footer;
207 | }
208 | echo Html::endTag('div');
209 | }
210 | }
211 | echo Html::endTag('div'); // End portlet body
212 | echo Html::endTag('div'); // End portlet div
213 | $loader = Html::img(Metronic::getAssetsUrl($this->view) . '/img/loading-spinner-grey.gif');
214 | $this->clientOptions['loader'] = ArrayHelper::getValue($this->clientOptions, 'loader', $loader);
215 | $this->registerPlugin('portlet');
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/widgets/Select2.php:
--------------------------------------------------------------------------------
1 | 'select',
19 | * 'data' => ['1' => 'Item 1', '2' => 'Item 2'],
20 | * 'multiple' => true,
21 | * ]);
22 | * ```
23 | *
24 | * @see http://ivaynberg.github.io/select2/
25 | */
26 | class Select2 extends InputWidget
27 | {
28 | /**
29 | * @var bool indicates whether to display a dropdown select box or use it for tagging
30 | */
31 | public $asDropdownList = true;
32 | /**
33 | * @var bool indicates whether the select2 is disabled or not.
34 | */
35 | public $disabled = false;
36 | /**
37 | * @var array the option data items. The array keys are option values, and the array values
38 | * are the corresponding option labels. The array can also be nested (i.e. some array values are arrays too).
39 | * For each sub-array, an option group will be generated whose label is the key associated with the sub-array.
40 | * If you have a list of data models, you may convert them into the format described above using
41 | * [[\yii\helpers\ArrayHelper::map()]].
42 | */
43 | public $data = [];
44 | /**
45 | * @var bool indicates whether the select2 is multiple or not.
46 | */
47 | public $multiple = false;
48 |
49 | /**
50 | * Initializes the widget.
51 | */
52 | public function init()
53 | {
54 | parent::init();
55 | Html::addCssClass($this->options, 'form-control');
56 | if ($this->multiple) {
57 | $this->options['multiple'] = 'multiple';
58 | }
59 | if ($this->disabled) {
60 | $this->options['disabled'] = true;
61 | }
62 | }
63 |
64 | /**
65 | * Executes the widget.
66 | */
67 | public function run()
68 | {
69 | if ($this->hasModel()) {
70 | if ($this->asDropdownList) {
71 | echo Html::activeDropDownList($this->model, $this->attribute, $this->data, $this->options);
72 | } else {
73 | if (!isset($this->clientOptions['query']) && !isset($this->clientOptions['ajax']) && !isset($this->clientOptions['data'])) {
74 | throw new InvalidConfigException('Must be set at least one of the client options: query, data, ajax.');
75 | }
76 | echo Html::activeHiddenInput($this->model, $this->attribute, $this->options);
77 | }
78 | } else {
79 | if ($this->asDropdownList) {
80 | echo Html::dropDownList($this->name, $this->value, $this->data, $this->options);
81 | } else {
82 | if (!isset($this->clientOptions['query']) && !isset($this->clientOptions['ajax']) && !isset($this->clientOptions['data'])) {
83 | throw new InvalidConfigException('Must be set at least one of the options Select2: query, data, ajax.');
84 | }
85 | echo Html::hiddenInput($this->name, $this->value, $this->options);
86 | }
87 | }
88 | Select2Asset::register($this->view);
89 | $this->registerPlugin('select2');
90 | }
91 | }
--------------------------------------------------------------------------------
/widgets/Select2Asset.php:
--------------------------------------------------------------------------------
1 | $model,
19 | * 'attribute' => 'country',
20 | * 'size' => Spinner::SIZE_SMALL,
21 | * 'buttonsLocation' => Spinner::BUTTONS_LOCATION_VERTICAL,
22 | * 'clientOptions' => ['step' => 2],
23 | * 'clientEvents' => ['changed' => 'function(event, value){ console.log(value);}'],
24 | * ]);
25 | * ```
26 | *
27 | * The following example will use the name property instead:
28 | *
29 | * ```php
30 | * echo Spinner::widget([
31 | * 'name' => 'country',
32 | * 'clientOptions' => ['step' => 2],
33 | * ]);
34 | *```
35 | *
36 | * @see http://exacttarget.github.io/fuelux/#spinner
37 | * @author
38 | */
39 | class Spinner extends InputWidget
40 | {
41 | // position
42 | const BUTTONS_LOCATION_VERTICAL = 'vertical';
43 | const BUTTONS_LOCATION_SIDES = 'sides';
44 | // size
45 | const SIZE_XSMALL = 'xsmall';
46 | const SIZE_SMALL = 'small';
47 | const SIZE_MEDIUM = 'medium';
48 | const SIZE_LARGE = 'large';
49 | /**
50 | * @var string Spinner size
51 | */
52 | public $size = self::SIZE_SMALL;
53 | /**
54 | * @var array the configuration array for [[Button]].
55 | */
56 | public $buttonsConfig = ['type' => Button::TYPE_M_BLUE];
57 | /**
58 | * @var array the HTML attributes for the input element.
59 | */
60 | public $inputOptions = [];
61 | /**
62 | * @var string The buttons location.
63 | * Valid values are 'vertical', 'sides'
64 | */
65 | public $buttonsLocation = self::BUTTONS_LOCATION_VERTICAL;
66 | /**
67 | * Executes the widget.
68 | */
69 | public function run()
70 | {
71 | Html::addCssClass($this->inputOptions, 'spinner-input form-control');
72 | $this->buttonsConfig = array_merge(['label' => ''], $this->buttonsConfig);
73 | if ($this->hasModel()) {
74 | $input = Html::activeTextInput($this->model, $this->attribute, $this->inputOptions);
75 | } else {
76 | $input = Html::textInput($this->name, $this->value, $this->inputOptions);
77 | }
78 | if ($this->buttonsLocation == self::BUTTONS_LOCATION_VERTICAL) {
79 | $this->buttonsConfig = array_merge($this->buttonsConfig, ['size' => Button::SIZE_MINI]);
80 | }
81 | $btnUp = Button::widget(
82 | array_merge($this->buttonsConfig, [
83 | 'icon' => 'fa fa-angle-up',
84 | 'options' => ['class' => 'spinner-up']
85 | ])
86 | );
87 | $btnDown = Button::widget(
88 | array_merge($this->buttonsConfig, [
89 | 'icon' => 'fa fa-angle-down',
90 | 'options' => ['class' => 'spinner-down']
91 | ])
92 | );
93 |
94 | if ($this->buttonsLocation == self::BUTTONS_LOCATION_VERTICAL) {
95 | $spinner = $input . Html::tag('div', $btnUp . $btnDown, ['class' => 'spinner-buttons input-group-btn btn-group-vertical']);
96 | } else {
97 | $spinner = Html::tag('div', $btnUp . $input . $btnDown, ['class' => 'spinner-buttons input-group-btn']);
98 | }
99 | echo Html::tag('div' , Html::tag('div', $spinner, ['class' => 'input-group input-' . $this->size]), $this->options);
100 | SpinnerAsset::register($this->view);
101 | $this->registerPlugin('spinner');
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/widgets/SpinnerAsset.php:
--------------------------------------------------------------------------------
1 | [
21 | * [
22 | * 'label' => 'One',
23 | * 'content' => 'Anim pariatur cliche...',
24 | * 'active' => true
25 | * ],
26 | * [
27 | * 'label' => 'Two',
28 | * 'content' => 'Anim pariatur cliche...',
29 | * 'headerOptions' => [...],
30 | * 'options' => ['id' => 'myveryownID'],
31 | * ],
32 | * [
33 | * 'label' => 'Dropdown',
34 | * 'items' => [
35 | * [
36 | * 'label' => 'DropdownA',
37 | * 'content' => 'DropdownA, Anim pariatur cliche...',
38 | * ],
39 | * [
40 | * 'label' => 'DropdownB',
41 | * 'content' => 'DropdownB, Anim pariatur cliche...',
42 | * ],
43 | * ],
44 | * ],
45 | * ],
46 | * ]);
47 | * ```
48 | *
49 | */
50 | class Tabs extends \yii\bootstrap\Tabs
51 | {
52 |
53 | // Tab placements.
54 | const PLACEMENT_ABOVE = 'above';
55 | const PLACEMENT_BELOW = 'below';
56 | const PLACEMENT_LEFT = 'left';
57 | const PLACEMENT_RIGHT = 'right';
58 |
59 | // Tab type
60 | const NAV_TYPE_TABS = 'nav-tabs';
61 | const NAV_TYPE_PILLS = 'nav-pills';
62 |
63 | /**
64 | * @var string, specifies the Bootstrap tab styling.
65 | * Valid values 'nav-tabs', 'nav-pills'
66 | */
67 | public $navType = self::NAV_TYPE_TABS;
68 |
69 | /**
70 | * @var string the placement of the tabs.
71 | * Valid values are 'above', 'below', 'left' and 'right'.
72 | */
73 | public $placement = self::PLACEMENT_BELOW;
74 |
75 | /**
76 | * @var bool Indicates whether tabs is styled for Metronic.
77 | */
78 | public $styled = true;
79 | /**
80 | * @var bool Indicates whether tabs is justified.
81 | */
82 | public $justified = false;
83 |
84 | /**
85 | * Initializes the widget.
86 | */
87 | public function init()
88 | {
89 | if ($this->justified) {
90 | Html::addCssClass($this->options, 'nav-justified');
91 | }
92 |
93 | Html::addCssClass($this->options, 'nav ' . $this->navType);
94 | parent::init();
95 | }
96 |
97 | /**
98 | * Renders the widget.
99 | */
100 | public function run()
101 | {
102 | $classWrap = ['tabs-' . $this->placement];
103 | if ($this->styled) {
104 | $classWrap[] = 'tabbable-custom';
105 | if ($this->justified) {
106 | $classWrap[] = 'nav-justified';
107 | }
108 | } else {
109 | $classWrap[]= 'tabbable';
110 | }
111 | echo Html::beginTag('div', ['class' => implode(' ', $classWrap)]);
112 | parent::run();
113 | echo Html::endTag('div');
114 | }
115 |
116 | /**
117 | * Renders tab items as specified on [[items]].
118 | * @return string the rendering result.
119 | * @throws InvalidConfigException.
120 | */
121 | protected function renderItems()
122 | {
123 | $headers = [];
124 | $panes = [];
125 | foreach ($this->items as $n => $item) {
126 | if (!isset($item['label'])) {
127 | throw new InvalidConfigException("The 'label' option is required.");
128 | }
129 | $label = $this->encodeLabels ? Html::encode($item['label']) : $item['label'];
130 | $headerOptions = array_merge($this->headerOptions, ArrayHelper::getValue($item, 'headerOptions', []));
131 |
132 | if (isset($item['items'])) {
133 | if ($this->styled) {
134 | throw new InvalidConfigException("The 'styled' not support dropdown items. Please, set 'styled' to false.");
135 | }
136 | $label .= ' ';
137 | Html::addCssClass($headerOptions, 'dropdown');
138 |
139 | if ($this->renderDropdown($item['items'], $panes)) {
140 | Html::addCssClass($headerOptions, 'active');
141 | }
142 |
143 | $header = Html::a($label, "#", ['class' => 'dropdown-toggle', 'data-toggle' => 'dropdown']) . "\n"
144 | . Dropdown::widget(['items' => $item['items'], 'clientOptions' => false]);
145 | } elseif (isset($item['content'])) {
146 | $options = array_merge($this->itemOptions, ArrayHelper::getValue($item, 'options', []));
147 | $options['id'] = ArrayHelper::getValue($options, 'id', $this->options['id'] . '-tab' . $n);
148 |
149 | Html::addCssClass($options, 'tab-pane');
150 | if (ArrayHelper::remove($item, 'active')) {
151 | Html::addCssClass($options, 'active');
152 | Html::addCssClass($headerOptions, 'active');
153 | }
154 | $header = Html::a($label, '#' . $options['id'], ['data-toggle' => 'tab']);
155 | $panes[] = Html::tag('div', $item['content'], $options);
156 | } else {
157 | throw new InvalidConfigException("Either the 'content' or 'items' option must be set.");
158 | }
159 |
160 | $headers[] = Html::tag('li', $header, $headerOptions);
161 | }
162 |
163 | $headers = Html::tag('ul', implode("\n", $headers), $this->options);
164 | $panes = Html::tag('div', implode("\n", $panes), ['class' => 'tab-content']);
165 |
166 | return ($this->placement == self::PLACEMENT_BELOW) ? ($panes . "\n" . $headers) : ($headers . "\n" . $panes);
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/widgets/TextInputWidget.php:
--------------------------------------------------------------------------------
1 | hasModel()) {
28 | echo Html::activeTextInput($this->model, $this->attribute, $this->options);
29 | } else {
30 | echo Html::textInput($this->name, $this->value, $this->options);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/widgets/Widget.php:
--------------------------------------------------------------------------------
1 |
16 | * @since 1.0
17 | */
18 | class Widget extends \yii\bootstrap\Widget
19 | {
20 | /**
21 | * @var array the HTML attributes for the widget container tag.
22 | */
23 | public $options = [];
24 | /**
25 | * @var array the options for the underlying Metronic JS plugin.
26 | * Please refer to the corresponding Metronic plugin Web page for possible options.
27 | * For example, [this page](http://yii2metronic.icron.org/javascript.html#portlet) shows
28 | * how to use the "Portlet" plugin and the supported options (e.g. "loadSuccess").
29 | */
30 | public $clientOptions = [];
31 | /**
32 | * @var array the event handlers for the underlying Metronic JS plugin.
33 | * Please refer to the corresponding Metronic plugin Web page for possible events.
34 | * For example, [this page](http://yii2metronic.icron.org/javascript.html#portlet) shows
35 | * how to use the "Portlet" plugin and the supported events (e.g. "close.mr.portlet").
36 | */
37 | public $clientEvents = [];
38 |
39 | /**
40 | * Registers a specific Bootstrap plugin and the related events
41 | * @param string $name the name of the Bootstrap plugin
42 | */
43 | protected function registerPlugin($name)
44 | {
45 | $view = $this->getView();
46 | $id = $this->options['id'];
47 | if ($this->clientOptions !== false) {
48 | $options = empty($this->clientOptions) ? '' : Json::encode($this->clientOptions);
49 | $js = "jQuery('#$id').$name($options);";
50 | $view->registerJs($js);
51 | }
52 | if (!empty($this->clientEvents)) {
53 | $js = [];
54 | foreach ($this->clientEvents as $event => $handler) {
55 | $js[] = "jQuery('#$id').on('$event', $handler);";
56 | }
57 | $view->registerJs(implode("\n", $js));
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------