├── Elements.php ├── InputWidget.php ├── LICENSE ├── Widget.php ├── assets ├── SemanticUICSSAsset.php └── SemanticUIJSAsset.php ├── collections ├── Breadcrumb.php ├── Menu.php └── Message.php ├── composer.json ├── helpers ├── Color.php └── Size.php ├── modules ├── Accordion.php ├── Checkbox.php ├── CheckboxList.php ├── Dropdown.php ├── Embed.php ├── Modal.php ├── Progress.php ├── Radio.php ├── RadioList.php ├── Rating.php ├── Search.php ├── Select.php ├── Shape.php ├── Sidebar.php ├── Sticky.php └── Tab.php ├── readme.md └── widgets ├── ActionColumn.php ├── ActiveField.php ├── ActiveForm.php ├── CheckboxColumn.php ├── DataColumn.php ├── DetailView.php ├── GridView.php ├── LinkPager.php └── Pjax.php /Elements.php: -------------------------------------------------------------------------------- 1 | options['id']) 23 | ? $this->setId($this->options['id']) 24 | : $this->options['id'] = $this->getId(); 25 | } 26 | 27 | public function registerJsAsset() 28 | { 29 | SemanticUIJSAsset::register($this->getView()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Aleksandr Zelenin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Widget.php: -------------------------------------------------------------------------------- 1 | options['id']) 23 | ? $this->setId($this->options['id']) 24 | : $this->options['id'] = $this->getId(); 25 | } 26 | 27 | public function registerJsAsset() 28 | { 29 | SemanticUIJSAsset::register($this->getView()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /assets/SemanticUICSSAsset.php: -------------------------------------------------------------------------------- 1 | css[] = 'semantic' . $postfix . '.css'; 19 | 20 | parent::init(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /assets/SemanticUIJSAsset.php: -------------------------------------------------------------------------------- 1 | js[] = 'semantic' . $postfix . '.js'; 27 | 28 | parent::init(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /collections/Breadcrumb.php: -------------------------------------------------------------------------------- 1 | / '; 37 | const DIVIDER_CHEVRON = ' '; 38 | 39 | /** 40 | * @var string 41 | */ 42 | public $size; 43 | 44 | public function run() 45 | { 46 | Html::addCssClass($this->options, 'ui breadcrumb'); 47 | if ($this->size) { 48 | Html::addCssClass($this->options, $this->size); 49 | } 50 | 51 | echo Html::tag('div', $this->renderItems(), $this->options); 52 | } 53 | 54 | /** 55 | * @return string 56 | */ 57 | public function renderItems() 58 | { 59 | $items = []; 60 | if ($homelink = $this->getHomeLink()) { 61 | $items[] = $homelink; 62 | } 63 | 64 | foreach ($this->links as $item) { 65 | if (!is_array($item)) { 66 | $item = [ 67 | 'label' => $item 68 | ]; 69 | } 70 | $items[] = $this->renderItem($item); 71 | } 72 | return implode($this->divider, $items); 73 | } 74 | 75 | /** 76 | * @return bool|string 77 | */ 78 | private function getHomeLink() 79 | { 80 | if ($this->homeLink === null) { 81 | $this->homeLink = [ 82 | 'label' => Yii::t('yii', 'Home'), 83 | 'url' => Yii::$app->getHomeUrl(), 84 | ]; 85 | } 86 | return $this->homeLink !== false 87 | ? $this->renderItem($this->homeLink) 88 | : false; 89 | } 90 | 91 | /** 92 | * @param array $item 93 | * 94 | * @return string 95 | */ 96 | protected function renderItem($item) 97 | { 98 | $item['label'] = $this->encodeLabels ? Html::encode($item['label']) : $item['label']; 99 | 100 | $options = ArrayHelper::getValue($item, 'options', $this->itemOptions); 101 | Html::addCssClass($options, 'section'); 102 | 103 | if (isset($item['url'])) { 104 | $link = Html::a($item['label'], $item['url'], $options); 105 | } else { 106 | Html::addCssClass($options, 'active'); 107 | $link = Html::tag('div', $item['label'], $options); 108 | } 109 | return $link; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /collections/Menu.php: -------------------------------------------------------------------------------- 1 | route === null && Yii::$app->controller !== null) { 152 | $this->route = Yii::$app->controller->getRoute(); 153 | } 154 | if ($this->params === null) { 155 | $this->params = Yii::$app->getRequest()->getQueryParams(); 156 | } 157 | } 158 | 159 | public function run() 160 | { 161 | Html::addCssClass($this->options, 'ui menu'); 162 | if ($this->vertical) { 163 | Html::addCssClass($this->options, self::TYPE_VERTICAL); 164 | } 165 | if ($this->tabular) { 166 | Html::addCssClass($this->options, self::TYPE_TABULAR); 167 | } 168 | if ($this->topAttached) { 169 | Html::addCssClass($this->options, self::TYPE_TOP_ATTACHED); 170 | } 171 | if ($this->tiered) { 172 | Html::addCssClass($this->options, self::TYPE_TIERED); 173 | } 174 | if ($this->secondary) { 175 | Html::addCssClass($this->options, self::TYPE_SECONDARY); 176 | } 177 | if ($this->pointing) { 178 | Html::addCssClass($this->options, self::TYPE_POINTING); 179 | } 180 | if ($this->text) { 181 | Html::addCssClass($this->options, self::TYPE_TEXT); 182 | } 183 | if ($this->fluid) { 184 | Html::addCssClass($this->options, self::TYPE_FLUID); 185 | } 186 | if ($this->inverted) { 187 | Html::addCssClass($this->options, self::TYPE_INVERTED); 188 | } 189 | if ($this->color) { 190 | Html::addCssClass($this->options, $this->color); 191 | } 192 | if ($this->size) { 193 | Html::addCssClass($this->options, $this->size); 194 | } 195 | if ($this->borderless) { 196 | Html::addCssClass($this->options, self::TYPE_BORDERLESS); 197 | } 198 | 199 | $tag = ArrayHelper::remove($this->options, 'tag', 'div'); 200 | echo Html::tag($tag, $this->renderItems(), $this->options); 201 | } 202 | 203 | /** 204 | * @return string 205 | */ 206 | public function renderItems() 207 | { 208 | Html::addCssClass($this->rightMenuOptions, 'right menu'); 209 | Html::addCssClass($this->subMenuOptions, 'ui sub menu'); 210 | 211 | $leftMenuPart = $this->items ? $this->renderMenuPart($this->items) : ''; 212 | $rightMenuPart = $this->rightMenuItems ? Html::tag('div', $this->renderMenuPart($this->rightMenuItems), $this->rightMenuOptions) : ''; 213 | return 214 | ( 215 | $this->tiered 216 | ? 217 | Html::tag('div', $leftMenuPart . $rightMenuPart, ['class' => 'menu']) 218 | : $leftMenuPart . $rightMenuPart 219 | ) . 220 | ($this->subMenuItems ? Html::tag('div', $this->renderMenuPart($this->subMenuItems), $this->subMenuOptions) : ''); 221 | } 222 | 223 | /** 224 | * @param $items 225 | * 226 | * @return string 227 | */ 228 | public function renderMenuPart($items) 229 | { 230 | $items = $this->normalizeItems($items, $hasActiveChild); 231 | 232 | $lines = ''; 233 | foreach ($items as $i => $item) { 234 | Html::addCssClass($item['options'], 'item'); 235 | if ($item['active']) { 236 | Html::addCssClass($item['options'], 'active'); 237 | } 238 | 239 | if (isset($item['items'])) { 240 | Html::addCssClass($item['options'], 'ui simple dropdown'); 241 | $item['label'] = 242 | $item['label'] . 243 | Elements::icon('dropdown') . 244 | Html::tag('div', $this->renderMenuPart($item['items']), ['class' => 'menu']); 245 | 246 | $menu = $this->renderItem($item); 247 | } else { 248 | $menu = $this->renderItem($item); 249 | } 250 | $lines .= $menu; 251 | } 252 | return $lines; 253 | } 254 | 255 | /** 256 | * @param $item 257 | * 258 | * @return string 259 | */ 260 | public function renderItem($item) 261 | { 262 | if (isset($item['header'])) { 263 | Html::addCssClass($item['options'], 'header'); 264 | return Html::tag('div', $item['header'], $item['options']); 265 | } else { 266 | if (isset($item['url'])) { 267 | return Html::a($item['label'], Url::to($item['url']), $item['options']); 268 | } else { 269 | return Html::tag('div', $item['label'], $item['options']); 270 | } 271 | } 272 | } 273 | 274 | /** 275 | * @param array $items 276 | * @param bool $active 277 | * 278 | * @return array 279 | */ 280 | protected function normalizeItems($items, &$active) 281 | { 282 | foreach ($items as $i => $item) { 283 | 284 | if (!ArrayHelper::getValue($item, 'visible', true)) { 285 | unset($items[$i]); 286 | continue; 287 | } 288 | 289 | $item['label'] = ArrayHelper::getValue($item, 'label', ''); 290 | $encodeLabel = ArrayHelper::getValue($item, 'encode', $this->encodeLabels); 291 | $items[$i]['label'] = $encodeLabel ? Html::encode($item['label']) : $item['label']; 292 | if (isset($items[$i]['header'])) { 293 | $items[$i]['header'] = $encodeLabel ? Html::encode($item['header']) : $item['header']; 294 | } 295 | 296 | $hasActiveChild = false; 297 | if (isset($item['items'])) { 298 | $items[$i]['items'] = $this->normalizeItems($item['items'], $hasActiveChild); 299 | if (empty($items[$i]['items']) && $this->hideEmptyItems) { 300 | unset($items[$i]['items']); 301 | if (!isset($item['url'])) { 302 | unset($items[$i]); 303 | continue; 304 | } 305 | } 306 | } 307 | 308 | if (!isset($item['active'])) { 309 | $items[$i]['active'] = ($this->activateParents && $hasActiveChild) || ($this->activateItems && $this->isItemActive($item)); 310 | } elseif ($item['active']) { 311 | $active = true; 312 | } 313 | $item['options'] = ArrayHelper::getValue($items, 'options', $this->itemOptions); 314 | } 315 | 316 | return array_values($items); 317 | } 318 | 319 | /** 320 | * @param array $item 321 | * 322 | * @return bool 323 | */ 324 | protected function isItemActive($item) 325 | { 326 | if (isset($item['url']) && is_array($item['url']) && isset($item['url'][0])) { 327 | $route = $item['url'][0]; 328 | if ($route[0] !== '/' && Yii::$app->controller) { 329 | $route = Yii::$app->controller->module->getUniqueId() . '/' . $route; 330 | } 331 | if (ltrim($route, '/') !== $this->route) { 332 | return false; 333 | } 334 | unset($item['url']['#']); 335 | 336 | if (count($item['url']) > 1) { 337 | foreach (array_splice($item['url'], 1) as $name => $value) { 338 | if ($value !== null && (!isset($this->params[$name]) || $this->params[$name] != $value)) { 339 | return false; 340 | } 341 | } 342 | } 343 | return true; 344 | } 345 | return false; 346 | } 347 | } 348 | -------------------------------------------------------------------------------- /collections/Message.php: -------------------------------------------------------------------------------- 1 | options, 'ui message'); 74 | if ($this->icon) { 75 | Html::addCssClass($this->options, self::TYPE_ICON); 76 | } 77 | if ($this->hidden) { 78 | Html::addCssClass($this->options, self::TYPE_HIDDEN); 79 | } 80 | if ($this->visible) { 81 | Html::addCssClass($this->options, self::TYPE_VISIBLE); 82 | } 83 | if ($this->floating) { 84 | Html::addCssClass($this->options, self::TYPE_FLOATING); 85 | } 86 | if ($this->compact) { 87 | Html::addCssClass($this->options, self::TYPE_COMPACT); 88 | } 89 | if ($this->attached) { 90 | Html::addCssClass($this->options, self::TYPE_ATTACHED); 91 | } 92 | if ($this->size) { 93 | Html::addCssClass($this->options, $this->size); 94 | } 95 | if ($this->color) { 96 | Html::addCssClass($this->options, $this->color); 97 | } 98 | if ($this->type) { 99 | Html::addCssClass($this->options, $this->type); 100 | } 101 | 102 | echo Html::beginTag('div', $this->options); 103 | } 104 | 105 | public function run() 106 | { 107 | echo Html::endTag('div'); 108 | } 109 | 110 | /** 111 | * @param array $options 112 | * 113 | * @return string 114 | */ 115 | public function renderCloseButton($options = []) 116 | { 117 | if (!isset($options['id'])) { 118 | $options['id'] = $this->getId() . '-close-button'; 119 | } 120 | 121 | $this->getView()->registerJs(' 122 | jQuery("#' . $options['id'] . '").on("click", function(event) { 123 | jQuery("#' . $this->getId() . '").fadeOut(); 124 | }); 125 | '); 126 | 127 | return Elements::icon('close', $options); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zelenin/yii2-semantic-ui", 3 | "description": "Semantic UI extension for Yii2", 4 | "type": "yii2-extension", 5 | "keywords": [ 6 | "yii2", 7 | "widgets", 8 | "semantic", 9 | "semantic ui" 10 | ], 11 | "homepage": "https://github.com/zelenin/yii2-semantic-ui", 12 | "license": "MIT", 13 | "authors": [ 14 | { 15 | "name": "Aleksandr Zelenin", 16 | "email": "aleksandr@zelenin.me", 17 | "homepage": "http://zelenin.me", 18 | "role": "Developer" 19 | } 20 | ], 21 | "support": { 22 | "issues": "https://github.com/zelenin/yii2-semantic-ui/issues", 23 | "source": "https://github.com/zelenin/yii2-semantic-ui" 24 | }, 25 | "require": { 26 | "yiisoft/yii2": "~2", 27 | "bower-asset/semantic-ui": "~2" 28 | }, 29 | "autoload": { 30 | "psr-4": { 31 | "Zelenin\\yii\\SemanticUI\\": "" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /helpers/Color.php: -------------------------------------------------------------------------------- 1 | registerJs(); 56 | 57 | Html::addCssClass($this->options, 'ui accordion'); 58 | if ($this->styled) { 59 | Html::addCssClass($this->options, self::TYPE_STYLED); 60 | } 61 | if ($this->fluid) { 62 | Html::addCssClass($this->options, self::TYPE_FLUID); 63 | } 64 | if ($this->vertical) { 65 | Html::addCssClass($this->options, self::TYPE_VERTICAL); 66 | } 67 | if ($this->inverted) { 68 | Html::addCssClass($this->options, self::TYPE_INVERTED); 69 | echo Elements::segment(Html::tag('div', $this->renderItems(), $this->options), ['class' => self::TYPE_INVERTED]); 70 | } else { 71 | echo Html::tag('div', $this->renderItems(), $this->options); 72 | } 73 | } 74 | 75 | /** 76 | * @return string 77 | */ 78 | public function renderItems() 79 | { 80 | $items = ''; 81 | foreach ($this->items as $item) { 82 | $items .= $this->renderItem($this->normalizeItem($item)); 83 | } 84 | return $items; 85 | } 86 | 87 | /** 88 | * @param array $item 89 | * 90 | * @return string 91 | */ 92 | public function renderItem($item) 93 | { 94 | return $this->renderTitle($item) . $this->renderContent($item); 95 | } 96 | 97 | /** 98 | * @param array $item 99 | * 100 | * @return string 101 | */ 102 | public function renderTitle($item) 103 | { 104 | $options = ArrayHelper::merge($this->titleOptions, ArrayHelper::getValue($item, 'titleOptions', [])); 105 | 106 | $encode = ArrayHelper::getValue($options, 'encode', true); 107 | $title = Elements::icon('dropdown') . ($encode ? Html::encode($item['title']) : $item['title']); 108 | 109 | Html::addCssClass($options, 'title'); 110 | if ($item['active']) { 111 | Html::addCssClass($options, 'active'); 112 | } 113 | return Html::tag('div', $title, $options); 114 | } 115 | 116 | /** 117 | * @param array $item 118 | * 119 | * @return string 120 | */ 121 | public function renderContent($item) 122 | { 123 | $options = ArrayHelper::merge($this->contentOptions, ArrayHelper::getValue($item, 'contentOptions', [])); 124 | 125 | $encode = ArrayHelper::getValue($options, 'encode', true); 126 | $content = $encode ? Html::encode($item['content']) : $item['content']; 127 | 128 | Html::addCssClass($options, 'content'); 129 | if ($item['active']) { 130 | Html::addCssClass($options, 'active'); 131 | } 132 | return Html::tag('div', $content, $options); 133 | } 134 | 135 | /** 136 | * @param array $item 137 | * 138 | * @return array 139 | */ 140 | public function normalizeItem($item) 141 | { 142 | $item['active'] = ArrayHelper::remove($item, 'active', false); 143 | return $item; 144 | } 145 | 146 | public function registerJs() 147 | { 148 | $this->registerJsAsset(); 149 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 150 | $this->getView()->registerJs('jQuery("#' . $this->options['id'] . '").accordion(' . $clientOptions . ');'); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /modules/Checkbox.php: -------------------------------------------------------------------------------- 1 | registerJs(); 60 | $this->prepareInputId(); 61 | 62 | Html::addCssClass($this->options, 'ui ' . $this->type . ' checkbox'); 63 | if ($this->readOnly) { 64 | Html::addCssClass($this->options, self::TYPE_READONLY); 65 | } 66 | if ($this->disabled) { 67 | Html::addCssClass($this->options, self::TYPE_DISABLED); 68 | } 69 | if ($this->fitted) { 70 | Html::addCssClass($this->options, self::TYPE_FITTED); 71 | } 72 | 73 | echo Html::tag('div', $this->renderInput() . $this->renderLabel(), $this->options); 74 | } 75 | 76 | /** 77 | * @return string 78 | */ 79 | public function renderInput() 80 | { 81 | $this->inputOptions['label'] = null; 82 | return $this->hasModel() 83 | ? Html::activeCheckbox($this->model, $this->attribute, $this->inputOptions) 84 | : Html::checkbox($this->name, $this->checked, $this->inputOptions); 85 | } 86 | 87 | public function prepareInputId() 88 | { 89 | if (!isset($this->inputOptions['id'])) { 90 | $id = $this->getId() . '-' . ($this->hasModel() ? $this->attribute : $this->name); 91 | $this->inputOptions['id'] = $id; 92 | } 93 | } 94 | 95 | /** 96 | * @return string 97 | */ 98 | public function renderLabel() 99 | { 100 | if (!isset($this->labelOptions['for'])) { 101 | $this->labelOptions['for'] = ($this->hasModel() ? $this->attribute : $this->name); 102 | } 103 | return $this->hasModel() 104 | ? Html::activeLabel($this->model, $this->attribute, $this->labelOptions) 105 | : Html::label($this->label, $this->labelOptions['for'], $this->labelOptions); 106 | } 107 | 108 | public function registerJs() 109 | { 110 | $this->registerJsAsset(); 111 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 112 | $this->getView()->registerJs('jQuery("#' . $this->options['id'] . '").checkbox(' . $clientOptions . ');'); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /modules/CheckboxList.php: -------------------------------------------------------------------------------- 1 | prepareOptions(); 40 | echo $this->renderInput(); 41 | } 42 | 43 | /** 44 | * @return string 45 | */ 46 | public function renderInput() 47 | { 48 | return $this->hasModel() 49 | ? Html::activeCheckboxList($this->model, $this->attribute, $this->items, $this->options) 50 | : Html::checkboxList($this->name, $this->selection, $this->items, $this->options); 51 | } 52 | 53 | /** 54 | * @return callable 55 | */ 56 | public function getDefaultItem() 57 | { 58 | return function ($index, $label, $name, $checked, $value) { 59 | $inputOptions = $this->inputOptions; 60 | $inputOptions['value'] = ArrayHelper::getValue($inputOptions, 'value', $value); 61 | return Html::tag( 62 | 'div', 63 | Checkbox::widget([ 64 | 'name' => $name, 65 | 'label' => $label, 66 | 'checked' => $checked, 67 | 'inputOptions' => $inputOptions, 68 | 'labelOptions' => $this->labelOptions 69 | ]), 70 | ['class' => 'field'] 71 | ); 72 | }; 73 | } 74 | 75 | public function prepareOptions() 76 | { 77 | $defaultItem = $this->getDefaultItem(); 78 | $this->options['item'] = ArrayHelper::getValue($this->options, 'item', $defaultItem); 79 | $this->options['itemOptions'] = $this->listOptions; 80 | Html::addCssClass($this->options, 'grouped inline fields'); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /modules/Dropdown.php: -------------------------------------------------------------------------------- 1 | '; 75 | 76 | public function run() 77 | { 78 | $this->registerJs(); 79 | 80 | Html::addCssClass($this->options, 'ui ' . $this->type . ' dropdown'); 81 | 82 | if ($this->search) { 83 | Html::addCssClass($this->options, self::TYPE_SEARCH); 84 | } 85 | if ($this->fluid) { 86 | Html::addCssClass($this->options, self::TYPE_FLUID); 87 | } 88 | if ($this->disabled) { 89 | Html::addCssClass($this->options, self::TYPE_DISABLED); 90 | } 91 | if ($this->compact) { 92 | Html::addCssClass($this->options, self::TYPE_COMPACT); 93 | } 94 | if ($this->upward) { 95 | Html::addCssClass($this->options, self::TYPE_UPWARD); 96 | } 97 | if ($this->multiple) { 98 | Html::addCssClass($this->options, self::TYPE_MULTIPLE); 99 | } 100 | 101 | echo Html::tag( 102 | 'div', 103 | $this->renderHiddenInput() . $this->renderText() . $this->renderDropdown(), 104 | $this->options 105 | ); 106 | } 107 | 108 | /** 109 | * @return string 110 | */ 111 | public function renderHiddenInput() 112 | { 113 | return $this->hasModel() 114 | ? Html::activeHiddenInput($this->model, $this->attribute, []) 115 | : Html::hiddenInput($this->name, $this->selection, []); 116 | } 117 | 118 | /** 119 | * @return string 120 | */ 121 | public function renderText() 122 | { 123 | return Html::tag('div', $this->defaultText, ['class' => 'default text']); 124 | } 125 | 126 | /** 127 | * @return string 128 | */ 129 | public function renderDropdown() 130 | { 131 | return 132 | $this->icon . 133 | Html::tag('div', $this->renderItems(), ['class' => 'menu']); 134 | } 135 | 136 | /** 137 | * @return string 138 | */ 139 | public function renderItems() 140 | { 141 | $items = ''; 142 | foreach ($this->items as $key => $item) { 143 | if (is_array($item)) { 144 | $items .= $this->renderHeader($key); 145 | $rawItems = $item; 146 | foreach ($rawItems as $key => $item) { 147 | $items .= $this->renderItem($key, $item); 148 | } 149 | } elseif (empty($item)) { 150 | $items .= $this->renderDivider(); 151 | } else { 152 | $items .= $this->renderItem($key, $item); 153 | } 154 | } 155 | return $items; 156 | } 157 | 158 | /** 159 | * @param string $item 160 | * 161 | * @return string 162 | */ 163 | public function renderHeader($item) 164 | { 165 | return Html::tag('div', $item, ['class' => 'header']); 166 | } 167 | 168 | /** 169 | * @return string 170 | */ 171 | public function renderDivider() 172 | { 173 | return Html::tag('div', '', ['class' => 'divider']); 174 | } 175 | 176 | /** 177 | * @param string $key 178 | * @param string $item 179 | * 180 | * @return string 181 | */ 182 | public function renderItem($key, $item) 183 | { 184 | return Html::tag('div', $item, [ 185 | 'data' => ['value' => $key], 186 | 'class' => 'item' 187 | ]); 188 | } 189 | 190 | public function registerJs() 191 | { 192 | $this->registerJsAsset(); 193 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 194 | $this->getView()->registerJs('jQuery("#' . $this->getId() . '").dropdown(' . $clientOptions . ');', View::POS_END); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /modules/Embed.php: -------------------------------------------------------------------------------- 1 | registerJs(); 42 | 43 | Html::addCssClass($this->options, 'ui embed'); 44 | 45 | $this->options['data']['source'] = $this->source; 46 | $this->options['data']['id'] = $this->id; 47 | 48 | if ($this->placeholder) { 49 | $this->options['data']['placeholder'] = $this->placeholder; 50 | } 51 | if ($this->url) { 52 | $this->options['data']['url'] = $this->url; 53 | } 54 | if ($this->icon) { 55 | $this->options['data']['icon'] = $this->icon; 56 | } 57 | 58 | echo Html::tag('div', '', $this->options); 59 | } 60 | 61 | public function registerJs() 62 | { 63 | $this->registerJsAsset(); 64 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 65 | $this->getView()->registerJs('jQuery("#' . $this->getId() . '").embed(' . $clientOptions . ');', View::POS_END); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /modules/Modal.php: -------------------------------------------------------------------------------- 1 | '; 17 | 18 | /** 19 | * @var string 20 | */ 21 | public $header; 22 | /** 23 | * @var array 24 | */ 25 | public $headerOptions = []; 26 | 27 | /** 28 | * @var string 29 | */ 30 | public $content; 31 | /** 32 | * @var array 33 | */ 34 | public $contentOptions = []; 35 | 36 | /** 37 | * @var string 38 | */ 39 | public $actions; 40 | /** 41 | * @var array 42 | */ 43 | public $actionsOptions = []; 44 | 45 | /** 46 | * @var string 47 | */ 48 | public $type = self::TYPE_STANDARD; 49 | const TYPE_BASIC = 'basic'; 50 | const TYPE_STANDARD = 'standard'; 51 | 52 | /** 53 | * @var bool 54 | */ 55 | public $fullscreen = false; 56 | const TYPE_FULLSCREEN = 'fullscreen'; 57 | 58 | /** 59 | * @var string 60 | */ 61 | public $size; 62 | 63 | public function init() 64 | { 65 | parent::init(); 66 | 67 | $this->registerJs(); 68 | 69 | Html::addCssClass($this->options, 'ui ' . $this->type . ' modal'); 70 | if ($this->fullscreen) { 71 | Html::addCssClass($this->options, self::TYPE_FULLSCREEN); 72 | } 73 | if ($this->size) { 74 | Html::addCssClass($this->options, $this->size); 75 | } 76 | 77 | echo Html::beginTag('div', $this->options); 78 | echo $this->renderCloseButton(); 79 | echo $this->renderHeader(); 80 | Html::addCssClass($this->contentOptions, 'content'); 81 | echo Html::beginTag('div', $this->contentOptions); 82 | } 83 | 84 | public function run() 85 | { 86 | echo Html::endTag('div'); 87 | echo $this->renderActions(); 88 | echo Html::endTag('div'); 89 | } 90 | 91 | /** 92 | * @return string 93 | */ 94 | public function renderCloseButton() 95 | { 96 | return $this->closeButton; 97 | } 98 | 99 | /** 100 | * @return null|string 101 | */ 102 | public function renderHeader() 103 | { 104 | Html::addCssClass($this->headerOptions, 'header'); 105 | return $this->header ? Html::tag('div', $this->header, $this->headerOptions) : null; 106 | } 107 | 108 | /** 109 | * @return null|string 110 | */ 111 | public function renderActions() 112 | { 113 | Html::addCssClass($this->actionsOptions, 'actions'); 114 | return $this->actions ? Html::tag('div', $this->actions, $this->actionsOptions) : null; 115 | } 116 | 117 | /** 118 | * @param string $content 119 | * @param array $options 120 | * 121 | * @return string 122 | */ 123 | public function renderToggleButton($content, $options = []) 124 | { 125 | if (!isset($options['id'])) { 126 | $options['id'] = $this->getId() . '-button'; 127 | } 128 | 129 | $this->getView()->registerJs(' 130 | jQuery("#' . $options['id'] . '").on("click", function(event) { 131 | event.preventDefault(); 132 | jQuery("#' . $this->getId() . '").modal("show"); 133 | }); 134 | '); 135 | 136 | return Elements::button($content, $options); 137 | } 138 | 139 | public function registerJs() 140 | { 141 | $this->registerJsAsset(); 142 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 143 | $this->getView()->registerJs('jQuery("#' . $this->options['id'] . '").modal(' . $clientOptions . ');'); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /modules/Progress.php: -------------------------------------------------------------------------------- 1 | registerJs(); 64 | 65 | Html::addCssClass($this->options, 'ui progress'); 66 | 67 | if ($this->indicating) { 68 | Html::addCssClass($this->options, self::TYPE_INDICATING); 69 | } 70 | if ($this->inverted) { 71 | Html::addCssClass($this->options, self::TYPE_INVERTED); 72 | } 73 | if ($this->attached) { 74 | Html::addCssClass($this->options, $this->attached); 75 | } 76 | if ($this->size) { 77 | Html::addCssClass($this->options, $this->size); 78 | } 79 | if ($this->state) { 80 | Html::addCssClass($this->options, $this->state); 81 | } 82 | if ($this->color) { 83 | Html::addCssClass($this->options, $this->color); 84 | } 85 | 86 | echo Html::tag('div', $this->renderBar() . $this->renderLabel(), $this->options); 87 | } 88 | 89 | /** 90 | * @return string 91 | */ 92 | public function renderBar() 93 | { 94 | return Html::tag('div', $this->renderProgress(), ['class' => 'bar']);; 95 | } 96 | 97 | /** 98 | * @return string 99 | */ 100 | public function renderLabel() 101 | { 102 | if ($this->label) { 103 | return Html::tag('div', $this->label, ['class' => 'label']); 104 | } else { 105 | return ''; 106 | } 107 | } 108 | 109 | /** 110 | * @return string 111 | */ 112 | public function renderProgress() 113 | { 114 | if ($this->progress) { 115 | return Html::tag('div', $this->progress, ['class' => 'progress']); 116 | } else { 117 | return ''; 118 | } 119 | } 120 | 121 | public function registerJs() 122 | { 123 | $this->registerJsAsset(); 124 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 125 | $this->getView()->registerJs('jQuery("#' . $this->options['id'] . '").progress(' . $clientOptions . ');'); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /modules/Radio.php: -------------------------------------------------------------------------------- 1 | hasModel() 19 | ? Html::activeRadio($this->model, $this->attribute, $this->inputOptions) 20 | : Html::radio($this->name, $this->checked, $this->inputOptions); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /modules/RadioList.php: -------------------------------------------------------------------------------- 1 | hasModel() 17 | ? Html::activeRadioList($this->model, $this->attribute, $this->items, $this->options) 18 | : Html::radioList($this->name, $this->selection, $this->items, $this->options); 19 | } 20 | 21 | /** 22 | * @return callable 23 | */ 24 | public function getDefaultItem() 25 | { 26 | return function ($index, $label, $name, $checked, $value) { 27 | $inputOptions = $this->inputOptions; 28 | $inputOptions['value'] = ArrayHelper::getValue($inputOptions, 'value', $value); 29 | return Html::tag( 30 | 'div', 31 | Radio::widget([ 32 | 'name' => $name, 33 | 'label' => $label, 34 | 'checked' => $checked, 35 | 'inputOptions' => $inputOptions, 36 | 'labelOptions' => $this->labelOptions 37 | ]), 38 | ['class' => 'field'] 39 | ); 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /modules/Rating.php: -------------------------------------------------------------------------------- 1 | registerJs(); 27 | 28 | Html::addCssClass($this->options, 'ui rating'); 29 | 30 | if ($this->type) { 31 | Html::addCssClass($this->options, $this->type); 32 | } 33 | if ($this->size) { 34 | Html::addCssClass($this->options, $this->size); 35 | } 36 | 37 | echo Html::tag('div', '', $this->options); 38 | } 39 | 40 | public function registerJs() 41 | { 42 | $this->registerJsAsset(); 43 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 44 | $this->getView()->registerJs('jQuery("#' . $this->getId() . '").rating(' . $clientOptions . ');'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /modules/Search.php: -------------------------------------------------------------------------------- 1 | registerJs(); 45 | 46 | Html::addCssClass($this->options, 'ui search'); 47 | if ($this->loading) { 48 | Html::addCssClass($this->options, self::TYPE_LOADING); 49 | } 50 | if ($this->fluid) { 51 | Html::addCssClass($this->options, self::TYPE_FLUID); 52 | } 53 | if ($this->category) { 54 | Html::addCssClass($this->options, self::TYPE_CATEGORY); 55 | } 56 | if ($this->rightAligned) { 57 | Html::addCssClass($this->options, self::TYPE_RIGHT_ALIGNED); 58 | } 59 | 60 | echo Html::tag('div', $this->renderInput() . $this->renderResults(), $this->options); 61 | } 62 | 63 | /** 64 | * @return string 65 | */ 66 | public function renderInput() 67 | { 68 | return $this->input ?: Elements::input(Html::input('text', null, null, ['class' => 'prompt'])); 69 | } 70 | 71 | /** 72 | * @return string 73 | */ 74 | public function renderResults() 75 | { 76 | return Html::tag('div', null, ['class' => 'results']); 77 | } 78 | 79 | public function registerJs() 80 | { 81 | $this->registerJsAsset(); 82 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 83 | $this->getView()->registerJs('jQuery("#' . $this->options['id'] . '").search(' . $clientOptions . ');'); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /modules/Select.php: -------------------------------------------------------------------------------- 1 | registerJs(); 61 | 62 | Html::addCssClass($this->options, 'ui dropdown'); 63 | 64 | if ($this->search) { 65 | Html::addCssClass($this->options, self::TYPE_SEARCH); 66 | } 67 | if ($this->fluid) { 68 | Html::addCssClass($this->options, self::TYPE_FLUID); 69 | } 70 | if ($this->disabled) { 71 | Html::addCssClass($this->options, self::TYPE_DISABLED); 72 | } 73 | if ($this->compact) { 74 | Html::addCssClass($this->options, self::TYPE_COMPACT); 75 | } 76 | if ($this->upward) { 77 | Html::addCssClass($this->options, self::TYPE_UPWARD); 78 | } 79 | if ($this->multiple) { 80 | $this->options['multiple'] = true; 81 | } 82 | 83 | echo $this->hasModel() 84 | ? Html::activeDropDownList($this->model, $this->attribute, $this->items, $this->options) 85 | : Html::dropDownList($this->name, $this->selection, $this->items, $this->options); 86 | } 87 | 88 | public function registerJs() 89 | { 90 | $this->registerJsAsset(); 91 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 92 | $this->getView()->registerJs('jQuery("#' . $this->options['id'] . '").dropdown(' . $clientOptions . ');', View::POS_END); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /modules/Shape.php: -------------------------------------------------------------------------------- 1 | registerJs(); 51 | 52 | Html::addCssClass($this->options, 'ui shape'); 53 | 54 | if ($this->type) { 55 | Html::addCssClass($this->options, $this->type); 56 | } 57 | 58 | echo Html::tag('div', Html::tag('div', $this->renderSides(), ['class' => 'sides']), $this->options); 59 | } 60 | 61 | /** 62 | * @return string 63 | */ 64 | public function renderSides() 65 | { 66 | $sides = ''; 67 | foreach ($this->normalizeSides($this->sides) as $side) { 68 | $sides .= $this->renderSide($side); 69 | } 70 | return $sides; 71 | } 72 | 73 | /** 74 | * @param array $side 75 | * @return string 76 | */ 77 | public function renderSide($side) 78 | { 79 | $sideOptions = ['class' => 'side']; 80 | if ($side['active']) { 81 | Html::addCssClass($sideOptions, 'active'); 82 | } 83 | return Html::tag('div', $side['content'], $sideOptions); 84 | } 85 | 86 | /** 87 | * @param array $sides 88 | * @return array 89 | */ 90 | public function normalizeSides($sides) 91 | { 92 | $items = []; 93 | $isActive = false; 94 | foreach ($sides as $side) { 95 | if (isset($side['active'])) { 96 | if ($side['active'] && !$isActive) { 97 | $isActive = true; 98 | } 99 | } else { 100 | $side['active'] = false; 101 | } 102 | $items[] = $side; 103 | } 104 | if (!$isActive && isset($items[0])) { 105 | $items[0]['active'] = true; 106 | } 107 | return $items; 108 | } 109 | 110 | public function registerJs() 111 | { 112 | $this->registerJsAsset(); 113 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 114 | $this->getView()->registerJs('jQuery("#' . $this->getId() . '").shape(' . $clientOptions . ');'); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /modules/Sidebar.php: -------------------------------------------------------------------------------- 1 | registerJs(); 35 | 36 | Html::addCssClass($this->options, 'ui sidebar'); 37 | 38 | if ($this->visible) { 39 | Html::addCssClass($this->options, self::TYPE_VISIBLE); 40 | } 41 | if ($this->width) { 42 | Html::addCssClass($this->options, $this->width); 43 | } 44 | 45 | echo Html::tag('div', $this->content, $this->options); 46 | } 47 | 48 | public function registerJs() 49 | { 50 | $this->registerJsAsset(); 51 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 52 | $this->getView()->registerJs('jQuery("#' . $this->getId() . '").sidebar(' . $clientOptions . ');'); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /modules/Sticky.php: -------------------------------------------------------------------------------- 1 | registerJs(); 17 | 18 | Html::addCssClass($this->options, 'ui sticky'); 19 | echo Html::beginTag('div', $this->options); 20 | } 21 | 22 | public function run() 23 | { 24 | echo Html::endTag('div'); 25 | } 26 | 27 | public function registerJs() 28 | { 29 | $this->registerJsAsset(); 30 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 31 | $this->getView()->registerJs('jQuery("#' . $this->options['id'] . '").sticky(' . $clientOptions . ');'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /modules/Tab.php: -------------------------------------------------------------------------------- 1 | 'bottom attached segment' 28 | ]; 29 | 30 | /** 31 | * @var array 32 | */ 33 | public $options = [ 34 | 'class' => 'ui top attached tabular menu' 35 | ]; 36 | 37 | const STATE_ACTIVE = 'active'; 38 | 39 | public function run() 40 | { 41 | $this->registerJs(); 42 | $this->normalizeItems(); 43 | 44 | echo $this->renderMenu() . $this->renderTabs(); 45 | } 46 | 47 | /** 48 | * @return string 49 | */ 50 | public function renderMenu() 51 | { 52 | $items = ''; 53 | foreach ($this->items as $item) { 54 | Html::addCssClass($item['labelOptions'], 'item'); 55 | $item['labelOptions']['data-tab'] = $item['uniqueId']; 56 | if ($item[self::STATE_ACTIVE]) { 57 | Html::addCssClass($item['labelOptions'], self::STATE_ACTIVE); 58 | } 59 | $items .= Html::a($item['label'], null, $item['labelOptions']); 60 | } 61 | return Html::tag('div', $items, $this->options); 62 | } 63 | 64 | /** 65 | * @return string 66 | */ 67 | public function renderTabs() 68 | { 69 | $items = ''; 70 | foreach ($this->items as $item) { 71 | Html::addCssClass($item['contentOptions'], 'ui tab'); 72 | $item['contentOptions']['data-tab'] = $item['uniqueId']; 73 | if ($item[self::STATE_ACTIVE]) { 74 | Html::addCssClass($item['contentOptions'], self::STATE_ACTIVE); 75 | } 76 | $items .= Html::tag('div', $item['content'], $item['contentOptions']); 77 | } 78 | return $items; 79 | } 80 | 81 | public function normalizeItems() 82 | { 83 | $items = []; 84 | $i = 1; 85 | $isActive = false; 86 | foreach ($this->items as $item) { 87 | $item['labelOptions'] = array_merge($this->labelOptions, ArrayHelper::getValue($item, 'labelOptions', [])); 88 | $item['contentOptions'] = array_merge($this->contentOptions, ArrayHelper::getValue($item, 'contentOptions', [])); 89 | if (!array_key_exists('uniqueId', $item)) { 90 | $item['uniqueId'] = $this->getId() . '-tab-' . $i; 91 | } 92 | 93 | if (isset($item[self::STATE_ACTIVE])) { 94 | if ($item[self::STATE_ACTIVE] && !$isActive) { 95 | $isActive = true; 96 | } 97 | } else { 98 | $item[self::STATE_ACTIVE] = false; 99 | } 100 | 101 | $items[] = $item; 102 | $i++; 103 | } 104 | if (!$isActive && isset($items[0])) { 105 | $items[0][self::STATE_ACTIVE] = true; 106 | } 107 | $this->items = $items; 108 | } 109 | 110 | public function registerJs() 111 | { 112 | $this->registerJsAsset(); 113 | $clientOptions = $this->clientOptions ? Json::encode($this->clientOptions) : null; 114 | $this->getView()->registerJs('jQuery("#' . $this->getId() . ' .item").tab(' . $clientOptions . ');'); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Yii2 Semantic UI extension 2 | 3 | [Semantic UI](http://semantic-ui.com) extension for [Yii2](http://www.yiiframework.com) 4 | 5 | ## Installation 6 | 7 | yii2-semantic-ui 2.* works with Semantic UI 2.* 8 | 9 | ### Composer 10 | 11 | The preferred way to install this extension is through [Composer](http://getcomposer.org/). 12 | 13 | Either run 14 | 15 | ``` 16 | php composer.phar require zelenin/yii2-semantic-ui "~2" 17 | ``` 18 | 19 | or add 20 | 21 | ``` 22 | "zelenin/yii2-semantic-ui": "~2" 23 | ``` 24 | 25 | to the require section of your ```composer.json``` 26 | 27 | ## Usage 28 | 29 | Add SemanticUICSSAsset to AppAsset: 30 | 31 | ```php 32 | set(\yii\grid\GridView::className(), \Zelenin\yii\SemanticUI\widgets\GridView::className()); 58 | Yii::$container->set(\yii\widgets\ActiveForm::className(), \Zelenin\yii\SemanticUI\widgets\ActiveForm::className()); 59 | Yii::$container->set(\yii\bootstrap\ActiveForm::className(), \Zelenin\yii\SemanticUI\widgets\ActiveForm::className()); 60 | Yii::$container->set(\yii\widgets\Breadcrumbs::className(), \Zelenin\yii\SemanticUI\collections\Breadcrumb::className()); 61 | Yii::$container->set(\yii\grid\CheckboxColumn::className(), \Zelenin\yii\SemanticUI\widgets\CheckboxColumn::className()); 62 | ``` 63 | 64 | Be very careful with it. 65 | 66 | ## Author 67 | 68 | [Aleksandr Zelenin](https://github.com/zelenin/), e-mail: [aleksandr@zelenin.me](mailto:aleksandr@zelenin.me) 69 | -------------------------------------------------------------------------------- /widgets/ActionColumn.php: -------------------------------------------------------------------------------- 1 | {view}{update}{delete}'; 15 | 16 | protected function initDefaultButtons() 17 | { 18 | if (!isset($this->buttons['view'])) { 19 | $this->buttons['view'] = function ($url, $model, $key) { 20 | return Html::a(Elements::icon('eye'), $url, [ 21 | 'class' => 'ui button', 22 | 'title' => Yii::t('yii', 'View'), 23 | 'data-pjax' => '0', 24 | ]); 25 | }; 26 | } 27 | if (!isset($this->buttons['update'])) { 28 | $this->buttons['update'] = function ($url, $model, $key) { 29 | return Html::a(Elements::icon('pencil'), $url, [ 30 | 'class' => 'ui button', 31 | 'title' => Yii::t('yii', 'Update'), 32 | 'data-pjax' => '0', 33 | ]); 34 | }; 35 | } 36 | if (!isset($this->buttons['delete'])) { 37 | $this->buttons['delete'] = function ($url, $model, $key) { 38 | return Html::a(Elements::icon('trash'), $url, [ 39 | 'class' => 'ui button', 40 | 'title' => Yii::t('yii', 'Delete'), 41 | 'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'), 42 | 'data-method' => 'post', 43 | 'data-pjax' => '0', 44 | ]); 45 | }; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /widgets/ActiveField.php: -------------------------------------------------------------------------------- 1 | 'field']; 18 | public $inputOptions = []; 19 | 20 | public $errorOptions = ['class' => 'ui red pointing label']; 21 | public $hintOptions = ['class' => 'ui pointing label']; 22 | 23 | public $template = "{label}\n{input}\n{hint}\n{error}"; 24 | public $checkboxTemplate = '