├── views ├── index.php └── creator │ ├── update.php │ ├── create.php │ ├── view.php │ ├── index.php │ ├── _menu.php │ └── _form.php ├── icons ├── IMenuIcons.php ├── AbstractMenuIcons.php └── Glyphicons.php ├── MenuAsset.php ├── MenuWidget.php ├── migrations ├── menu_create.sql ├── m170101_000000_create_menu_table.php └── m170101_000001_humanized_menu_name.php ├── composer.json ├── LICENSE ├── models ├── Search.php └── Model.php ├── Menu.php ├── README.md ├── controllers └── CreatorController.php └── assets └── js ├── menu.min.js ├── Sortable.min.js └── menu.js /views/index.php: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /icons/IMenuIcons.php: -------------------------------------------------------------------------------- 1 | message === null) { 12 | $this->message = 'Hello World'; 13 | } 14 | } 15 | 16 | public function run(){ 17 | return $this->render('index'); 18 | } 19 | 20 | public function generator(){ 21 | 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /views/creator/update.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('app', 'Update'); 5 | $this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Menu'), 'url' => ['index']]; 6 | $this->params['breadcrumbs'][] = $this->title; 7 | 8 | echo $this->render('_menu');?> 9 | 10 | 11 |
12 | render('_form');?> 13 |
14 | 15 | registerJs("var menu = new MyMENU.Menu({ 17 | config: { 18 | setMysql: true, 19 | getMysql: true 20 | } 21 | 22 | });", 4); 23 | ?> 24 | -------------------------------------------------------------------------------- /migrations/menu_create.sql: -------------------------------------------------------------------------------- 1 | -- #Copyright (c) 2017 Rafal Marguzewicz pceuropa.net 2 | -- PHP Version: 7.0.8-0ubuntu0.16.04.2 3 | 4 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 5 | SET time_zone = "+00:00"; 6 | 7 | CREATE TABLE IF NOT EXISTS `menu` ( 8 | `menu_id` int(11) NOT NULL, 9 | `menu` text NOT NULL, 10 | `menu_name` char(255) DEFAULT NULL 11 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 12 | 13 | ALTER TABLE `menu` ADD PRIMARY KEY (`menu_id`); 14 | ALTER TABLE `menu` MODIFY `menu_id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1; 15 | ALTER TABLE `menu` ADD PRIMARY KEY (`menu_id`), ADD KEY `unique-index-menu-menu_name` (`menu_name`); 16 | -------------------------------------------------------------------------------- /icons/AbstractMenuIcons.php: -------------------------------------------------------------------------------- 1 | getAll() as $glyphName => $glyphCode) 21 | { 22 | $result[$glyphName] = $this->getDropDownOption($glyphName); 23 | } 24 | 25 | return $result; 26 | } 27 | } -------------------------------------------------------------------------------- /views/creator/create.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('app', 'Create'); 9 | $this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Menu'), 'url' => ['index']]; 10 | $this->params['breadcrumbs'][] = $this->title; 11 | ?> 12 | 13 |
14 |
15 | 16 | field($model, 'menu_name'); ?> 17 | 'btn btn-success pull-right col-xs-12']); ?> 18 | 19 |
20 |
21 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pceuropa/yii2-menu", 3 | "description": "Menu bootstrap builder. Sort by drag and drop", 4 | "keywords": [ 5 | "yii2", 6 | "extension", 7 | "creator", 8 | "menu builder", 9 | "drag end drop", 10 | "bootstrap menu" 11 | ], 12 | "version": "2.1.4", 13 | "homepage": "https://pceuropa.net/yii2-extensions/yii2-menu", 14 | "type": "yii2-extension", 15 | "license": "MIT", 16 | "minimum-stability": "beta", 17 | "authors": [ 18 | { 19 | "name": "Rafal Marguzewicz", 20 | "email": "info@pceuropa.net", 21 | "homepage": "https://pceuropa.net/" 22 | } 23 | ], 24 | "require" : { 25 | "kartik-v/yii2-widget-select2": "@dev" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "pceuropa\\menu\\": "" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /views/creator/view.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('app', 'View'); 8 | $this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Menu'), 'url' => ['index']]; 9 | $this->params['breadcrumbs'][] = $this->title; 10 | 11 | echo \yii\bootstrap\Html::tag('h1', $model->menu_name); 12 | 13 | NavBar::begin(); 14 | echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-left'], 15 | 'items' => Menu::NavbarLeft($model->menu_id) ]); 16 | 17 | echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], 18 | 'items' => Menu::NavbarRight($model->menu_id)]); 19 | NavBar::end(); 20 | 21 | ?> 22 | 23 | 24 | -------------------------------------------------------------------------------- /views/creator/index.php: -------------------------------------------------------------------------------- 1 | title = Yii::t('app', 'Menu'); 8 | $this->params['breadcrumbs'][] = $this->title; 9 | 10 | echo GridView::widget([ 11 | 'dataProvider' => $dataProvider, 12 | 'filterModel' => $searchModel, 13 | 'columns' => [ 14 | ['class' => 'yii\grid\SerialColumn'], 15 | [ 16 | 'attribute' => 'menu_name', 17 | 'value' => function($model) { 18 | return sprintf("(#%s) %s", $model->menu_id, $model->menu_name); 19 | } 20 | ], 21 | ['class' => 'yii\grid\ActionColumn',], 22 | ], 23 | ]); 24 | 25 | echo Html::a(Yii::t('app', 'Add'), ['create'], ['class' => 'btn btn-success']); 26 | ?> 27 | -------------------------------------------------------------------------------- /migrations/m170101_000000_create_menu_table.php: -------------------------------------------------------------------------------- 1 | db->driverName === 'mysql'){ 14 | 15 | $options = 'ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1'; 16 | } 17 | 18 | $this->createTable($this->table, [ 19 | 'menu_id' => $this->primaryKey(), 20 | 'menu' => $this->text()->notNull(), 21 | ], $options); 22 | } 23 | 24 | public function down(){ 25 | 26 | $this->dropTable($this->table); 27 | } 28 | 29 | /* 30 | // Use safeUp/safeDown to run migration code within a transaction 31 | public function safeUp() 32 | { 33 | } 34 | 35 | public function safeDown() 36 | { 37 | } 38 | */ 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Rafal Marguzewicz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /migrations/m170101_000001_humanized_menu_name.php: -------------------------------------------------------------------------------- 1 | addColumn($table, $this->newColumnName, $this->char('255')); 14 | $this->createIndex($this->getIndexName(), $table, $this->newColumnName); 15 | } 16 | 17 | public function down() 18 | { 19 | $table = \pceuropa\menu\models\Model::tableName(); 20 | $this->dropIndex($this->getIndexName(), $table); 21 | $this->dropColumn($table, $this->newColumnName); 22 | } 23 | 24 | protected function getIndexName() 25 | { 26 | $table = \pceuropa\menu\models\Model::tableName(); 27 | return "unique-index-{$table}-{$this->newColumnName}"; 28 | } 29 | 30 | /* 31 | // Use safeUp/safeDown to run migration code within a transaction 32 | public function safeUp() 33 | { 34 | } 35 | 36 | public function safeDown() 37 | { 38 | } 39 | */ 40 | } 41 | -------------------------------------------------------------------------------- /models/Search.php: -------------------------------------------------------------------------------- 1 | $query, 34 | ]); 35 | 36 | if (!($this->load($params) && $this->validate())) { 37 | return $dataProvider; 38 | } 39 | 40 | $query->andFilterWhere([ 41 | 'menu_id' => $this->menuId, 42 | ]); 43 | 44 | $query->andFilterWhere(['like', 'menu', $this->menu]); 45 | 46 | return $dataProvider; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /models/Model.php: -------------------------------------------------------------------------------- 1 | 'Link', 11 | 'dropmenu' => 'Dropdown menu', 12 | 'line' => 'Line (devider)' 13 | ]; 14 | 15 | public static function tableName() { 16 | return 'menu'; 17 | } 18 | 19 | 20 | public function rules(){ 21 | return [ 22 | [['menu_id'], 'integer'], 23 | [['menu', 'menu_name'], 'string'], 24 | ['menu', 'default', 'value' => json_encode([ 'left' => [], 'right' => [] ]), 'on' => 'insert'], 25 | ]; 26 | } 27 | 28 | public function attributeLabels(){ 29 | return [ 30 | 'menu_id' => Yii::t('app', 'Id'), 31 | 'menu_name' => Yii::t('app', 'Menu name'), 32 | 'menu' => Yii::t('app', 'Menu'), 33 | ]; 34 | } 35 | 36 | public static function findModel($id){ 37 | 38 | $where = (preg_match('#\d+#', $id)) ? ['menu_id' => $id] : ['like', 'lower(menu_name)', $id]; 39 | $model = Model::find()->where($where)->one(); 40 | 41 | if ($model !== null) { 42 | return $model; 43 | } else { 44 | return (object) [ 'menu' => '{"left" : [{"label": "wrong id of menu"}], "right": []}', ]; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Menu.php: -------------------------------------------------------------------------------- 1 | menu); 30 | 31 | //$data = self::checkIcon($m[$pos]); 32 | 33 | return $m[$pos]; 34 | } 35 | 36 | protected static function checkIcon($array){ 37 | $result = []; 38 | foreach ($array as $item){ 39 | 40 | if (array_key_exists('icon', $item)){ 41 | 42 | $glyph = Html::tag('i', '', 43 | ['class' => sprintf("glyphicon glyphicon-%s", $item['icon'])] 44 | ); 45 | 46 | $item['label'] = sprintf('%s %s', $glyph, $item['label']); 47 | } 48 | 49 | if (array_key_exists('items', $item)){ 50 | 51 | $item['items'] = self::checkIcon($item['items']); 52 | } 53 | 54 | $result[] = $item; 55 | } 56 | 57 | return $result; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /views/creator/_menu.php: -------------------------------------------------------------------------------- 1 | registerCss(' 4 | #type, #location {width: 200px} 5 | #left, #right {min-width:20px; min-height:50px;border: solid 1px #DCD8D8} 6 | .navbar-nav > li > .dropdown-menu { min-height: 30px;} 7 | .ghost { opacity: 0.3;outline: 0;background: #C8EBFB;} 8 | a { outline: 0;} 9 | #trash, #edit { min-height:120px; margin-top: 85px; margin-left:40px} 10 | 11 | #trash i, #edit i { font-size:33px; margin-top:10px; color:#ccc} 12 | #trash li, #edit li { text-align:center; list-style-type: none; font-size:200%;} 13 | 14 | #trash li a {color:red; opacity: 1;} 15 | #edit li a {color:#1D9841;opacity: 1;} 16 | 17 | .dropdown-menu .divider { 18 | height: 5px; 19 | }' 20 | ); ?> 21 | 22 |
23 | 42 | 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Latest Stable Version](https://poser.pugx.org/pceuropa/yii2-menu/v/stable)](https://packagist.org/packages/pceuropa/yii2-menu) [![Total Downloads](https://poser.pugx.org/pceuropa/yii2-menu/downloads)](https://packagist.org/packages/pceuropa/yii2-menu) [![Latest Unstable Version](https://poser.pugx.org/pceuropa/yii2-menu/v/unstable)](https://packagist.org/packages/pceuropa/yii2-menu) [![License](https://poser.pugx.org/pceuropa/yii2-menu/license)](https://packagist.org/packages/pceuropa/yii2-menu) 2 | 3 | Bootstrap Menu Builder for Yii2 4 | ============================ 5 | 6 | 7 | ![preview](http://pceuropa.net/images/yii2-menu.png) 8 | 9 | [DEMO](https://pceuropa.net/menu/creator) 10 | 11 | ## Features 12 | 13 | * Creating links, drop menus, line (diver) in the navbar-left and/or navbar-right 14 | * Sorting, editing, and deleting using drag and drop 15 | * No jQuery for drag and drop ([RubaXa/Sortable](https://github.com/RubaXa/Sortable)) 16 | * CRUD operations by jQuery Ajax) 17 | 18 | ## Installation 19 | ``` 20 | composer require pceuropa/yii2-menu dev-master 21 | ``` 22 | 23 | Add the following code to config file Yii2 24 | ```php 25 | 'modules' => [ 26 | 'menu' => [ 27 | 'class' => '\pceuropa\menu\Menu', 28 | ], 29 | ] 30 | ``` 31 | 32 | ## Configuration 33 | 34 | ### 1. Create database schema 35 | 36 | Make sure that you have properly configured `db` application component and run the following command: 37 | 38 | ```bash 39 | $ php yii migrate/up --migrationPath=@vendor/pceuropa/yii2-menu/migrations 40 | 41 | ``` 42 | 43 | 44 | ### 2. Add the following code to view layout file Yii2 45 | ```php 46 | 47 | use pceuropa\menu\Menu; 48 | 49 | NavBar::begin(['brandLabel' => 'Brand','brandUrl' => Url::home(),]); 50 | 51 | echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-left'], 52 | 'items' => Menu::NavbarLeft(1) // argument is id of menu 53 | ]); 54 | 55 | echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], 56 | 'items' => Menu::NavbarRight(1) 57 | ]); 58 | NavBar::end(); 59 | 60 | ``` 61 | ### 3. Getting started 62 | /menu/creator 63 | 64 | -------------------------------------------------------------------------------- /controllers/CreatorController.php: -------------------------------------------------------------------------------- 1 | enableCsrfValidation = false; 15 | return parent::beforeAction($action); 16 | } 17 | 18 | public function actionIndex(){ 19 | 20 | $searchModel = new Search(); 21 | $dataProvider = $searchModel->search(Yii::$app->request->queryParams); 22 | 23 | return $this->render('index', [ 24 | 'searchModel' => $searchModel, 25 | 'dataProvider' => $dataProvider, 26 | ]); 27 | } 28 | 29 | public function actionCreate(){ 30 | $m = new Model(); 31 | 32 | if ( $m->load(Yii::$app->request->post())){ 33 | 34 | $m->scenario = 'insert'; 35 | $m->save(); 36 | return $this->redirect(['update', 'id' => $m->menu_id]); 37 | } 38 | return $this->render('create', ['model' => $m]); 39 | } 40 | 41 | public function actionView($id){ 42 | $m = Model::findModel($id); 43 | $r = Yii::$app->request; 44 | 45 | if ($r->isAjax) { 46 | \Yii::$app->response->format = Response::FORMAT_JSON; 47 | 48 | switch (true) { 49 | case $r->post('get'): 50 | return ['success' => true, 'menu' => $m->menu]; 51 | default: 52 | return ['success' => false]; 53 | } 54 | } 55 | 56 | return $this->render('view', ['model' => $m]); 57 | } 58 | 59 | public function actionUpdate($id){ 60 | $m = $this->findModel($id); 61 | $r = Yii::$app->request; 62 | 63 | if ($r->isAjax) { 64 | \Yii::$app->response->format = Response::FORMAT_JSON; 65 | 66 | switch (true) { 67 | case $r->isGet: 68 | return ['success' => true, 'menu' => $m->menu]; 69 | case $r->post('update'): 70 | $m->menu = $r->post('menu'); 71 | return ['success' => $m->save()]; 72 | 73 | default: return ['success' => false]; 74 | } 75 | } 76 | 77 | return $this->render('update'); 78 | } 79 | 80 | public function actionDelete($id){ 81 | $this->findModel($id)->delete(); 82 | return $this->redirect(Yii::$app->request->referrer); 83 | } 84 | 85 | protected function findModel($id){ 86 | if (($model = Model::findOne($id)) !== null) { 87 | return $model; 88 | } else { 89 | throw new NotFoundHttpException('The requested menu does not exist.'); 90 | } 91 | } 92 | 93 | 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /views/creator/_form.php: -------------------------------------------------------------------------------- 1 | registerJsFile('@web/js/menu/menu.js', ['depends' => 'yii\web\YiiAsset']); 4 | 5 | use yii\bootstrap\BaseHtml; 6 | use pceuropa\menu\models\Model; 7 | //$glyphicons = \pceuropa\menu\icons\Glyphicons::forge()->getAll(); 8 | //$glyphicons = json_encode($glyphicons); 9 | //$this->registerJs( " window.glyphicons = {$glyphicons}; ", \yii\web\View::POS_HEAD); 10 | ?> 11 | 12 | 13 |
14 |

Add element

15 | 16 |
17 | 18 |
19 | 'type', 'class' => 'form-control input-sm'] 24 | ); ?> 25 |
26 |
27 | 28 |
29 | 30 |
31 | 'label', 'class' => 'form-control input-sm']); ?> 32 |
33 |
34 | 35 |
36 | 37 |
38 | 'url', 'class' => 'form-control input-sm']); ?> 39 |
40 |
41 | 42 | 43 |
44 | 45 |
46 | 'Navbar Left', 'right' => 'Navbar Right'], 50 | ['id' => 'location', 'class' => 'form-control input-sm'] 51 | ); ?> 52 |
53 |
54 | 70 | 71 |
72 | 73 |
74 | 'glyphicon glyphicon-ok', 'aria-hidden' => 'true']) . ' Add', 76 | ['id' => 'add', 'class' => 'btn btn-success'] 77 | ); ?> 78 |
79 |
80 | 81 | 82 |
83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /assets/js/menu.min.js: -------------------------------------------------------------------------------- 1 | //Copyright (c) MIT 2016-2017 Rafal Marguzewicz pceuropa.net 2 | "use strict";var MyMENU=MyMENU||{};MyMENU=function(){function a(a){a.config=a.config||{},this.config={prefixDelete:"prefixDelete"},this.config.getMysql=a.config.getMysql||!1,this.config.setMysql=a.config.setMysql||!1,this.navbar={left:[],right:[]},this.navbar=this.mysql("get")||this.navbar,this.init()}return a.prototype={version:"2.1.3",operations:0,location_selector:$("#location"),init:function(){var a=this;$("#type").on("change",function(){var b=$("#url-box, #anchor-box, #icon-box");switch(a.location_selector.empty().append(a.locations()),b.show(),!0){case"dropmenu"==$(this).val():$("#url-box").hide();break;case"line"==$(this).val():b.hide();break;default:b.show()}}),a.location_selector.on("change",function(){var a="#"+$(this).val();$(a).css({border:"0 solid #f37736"}).animate({borderWidth:1},3e3,"swing",function(){$(a).animate({borderWidth:0},1e3)})}),$("#menu-create").click(function(){a.mysql("set")}),$("#add").click(function(){var b=a.sourceElement();a.addToMenu(b)})},addToMenu:function(a){var a=a||{type:"link",location:"left",label:"error",url:"/menu/index",icon:""},b={};switch(a.side=this.sideNav(a.location),a.type){case"link":b={label:a.label,url:a.url,icon:a.icon,type:"link"},"left"==a.location||"right"==a.location?this.navbar[a.location].push(b):this.navbar[a.side][a.location[1]].items.push(b);break;case"dropmenu":this.navbar[a.location].push({label:a.label,items:[],icon:a.icon,type:"dropmenu"});break;case"line":this.navbar[a.side][a.location[1]].items.push({type:"line",label:""});break;default:window.console&&console.log("error side")}this.render()},mysql:function(a){var b=this,a=a||"get";if("get"==a){if(!this.config.getMysql)return!1;window.console&&console.log(a),$.getJSON(document.URL,function(a){b.navbar=JSON.parse(a.menu),b.render()})}else{if(0==this.operations)return b.operations++,!1;$.ajax({url:document.URL,type:"post",dataType:"JSON",data:{update:!0,_csrf:b.csrfToken,menu:JSON.stringify(b.navbar,null,4)},success:function(a){a.success===!1&&window.console&&console.log(a.message),a.success===!0&&(window.console&&console.log(b.operations+". save correct"),b.afterSuccessSave(),b.operations++)},error:function(a,b,c){alert(b)}})}},afterSuccessSave:function(){var a=$("#add"),b=a.html();window.setTimeout(function(){a.prop("disabled",!0).text("Menu saved correctly")},111),window.setTimeout(function(){a.prop("disabled",!1).html(b)},1111)},filter:function(){function b(b){return b!==a.config.prefixDelete}function c(a){return"line"!==a.type}function d(a){return void 0!==a.label||"string"==typeof a}var a=this;this.navbar.left=this.navbar.left.filter(b).filter(c).filter(d),this.navbar.right=this.navbar.right.filter(b).filter(c).filter(d);for(var e=this.navbar.left.length;e--;)this.navbar.left[e].hasOwnProperty("items")&&(this.navbar.left[e].items=this.navbar.left[e].items.filter(b).filter(d));for(var e=this.navbar.right.length;e--;)this.navbar.right[e].hasOwnProperty("items")&&(this.navbar.right[e].items=this.navbar.right[e].items.filter(b).filter(d))},render:function(){window.console&&console.log("render"),this.filter(),$("#left").empty().append(this.renderNavbar("left")),$("#right").empty().append(this.renderNavbar("right")),console.log(this.locations()),this.location_selector.empty().append(this.locations()),this.sort(),this.config.setMysql&&this.mysql("set")},jsonPreview:function(){$("#code code").text(JSON.stringify(this.navbar,null,4))},locations:function(){var a=$("#type").val(),b='';if("dropmenu"!=a){"line"==a&&(b="");for(var c=0;cDropmenu: '+this.navbar.left[c].label+"");for(var c=0;cDropmenu: '+this.navbar.right[c].label+"")}return b},renderNavbar:function(a){var b=$("#"+a),c=this.navbar[a],d=this;return $.map(c,function(c,e){switch(c.type){case"dropmenu":b.append(d.dropmenu(c,a[0]+e));break;case"link":b.append(d.link(c));break;case"line":b.append(d.divider(c));break;default:window.console&&console.log("Element type error")}}),b},icon:function(a){var b="";return a&&(b=$("").addClass("glyphicon").addClass("glyphicon-"+a)),b},divider:function(a){var b=$("
  • ");return b.addClass("divider"),b},link:function(a){var b=$("",{href:a.url}).text(a.label);b.prepend(this.icon(a.icon));var c=$("
  • ").append(b);return c},dropmenu:function(a,b){var c,d=$("