├── 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 |
23 |
42 |
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://packagist.org/packages/pceuropa/yii2-menu) [](https://packagist.org/packages/pceuropa/yii2-menu) [](https://packagist.org/packages/pceuropa/yii2-menu) [](https://packagist.org/packages/pceuropa/yii2-menu)
2 |
3 | Bootstrap Menu Builder for Yii2
4 | ============================
5 |
6 |
7 | 
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 |
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;c
Dropmenu: '+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=$("",{id:b}).addClass("dropdown-menu"),e=this;return $.map(a.items,function(a){d.append(e.link(a))}),c=$("").addClass("pceuropa-dropmenu").attr("data-dropmenu","true"),c.append($("").addClass("dropdown-toggle").attr("data-toggle","dropdown").attr("draggable","false").attr("aria-expanded","false").text(a.label).prepend(this.icon(a.icon)).append($("").addClass("caret"))),c.append(d),c},previewTest:function(){return["normal","json","yii2"]},arrayGroups:function(){var a=[],b=0;for(b=this.navbar.left.length;b--;)this.navbar.left[b].hasOwnProperty("items")&&a.push("l"+b);for(b=this.navbar.right.length;b--;)this.navbar.right[b].hasOwnProperty("items")&&a.push("r"+b);return a||[]},sourceElement:function(){var a={};return $("#inputsData input, #inputsData select").filter(function(){return 0!==this.value.length}).each(function(){a[this.id]=$(this).val()}),a},sideNav:function(a){return"r"==a[0]?"right":"left"},sort:function(){var a=this,b={group:"nav",animation:0,ghostClass:"ghost",onMove:function(a){a.from.id,a.target.id,a.oldIndex,a.newIndex;"true"!=a.dragged.dataset.dropmenu&&$(".pceuropa-dropmenu").addClass("open")},onUpdate:function(b){var c=b.from.id,d=b.oldIndex,e=b.newIndex,f="left";"left"==c||"right"==c?a.navbar[c].move(d,e):(f=a.sideNav(c),a.navbar[f][c[1]].items.move(d,e)),setTimeout(a.render(),300)},onAdd:function(b){var c=b.from.id,d=b.target.id,e=b.oldIndex,f=b.newIndex,g={},h={},i=function(a){var b={};if("string"==typeof a||a instanceof String)return b=a;for(var c in a)b[c]=a[c];return b};if("left"==c||"right"==c)g=i(a.navbar[c][e]),a.navbar[c][e]=a.config.prefixDelete;else{var j=a.sideNav(c);g=i(a.navbar[j][c[1]].items[e]),a.navbar[j][c[1]].items[e]=a.config.prefixDelete}if("left"==d||"right"==d)h=a.navbar[d];else{var j=a.sideNav(d);h=a.navbar[j][d[1]].items}h.splice(f,0,g),setTimeout(a.render(),300)}},c={group:"nav",onAdd:function(b){var c={},d=b.from.id,e=a.sideNav(d),f=b.oldIndex,g=$("#edit"),h=$("#inputsData, #trash"),i=function(a){return a?a:""},j=function(a,b,c){var d=$("",{id:b+"-box-update"}).addClass("form-group"),e=$("").addClass("col-sm-3 control-label").text(c),f=$("").addClass("col-sm-8");return d.append(e).append(f.append(a))};$(".pceuropa-dropmenu").click(),c="left"==d||"right"==d?a.navbar[d][f]:a.navbar[e][d[1]].items[f],"line"!=c.type&&(g.attr("class","col-md-8 form-horizontal well"),g.append(j($("",{id:"label-update",type:"text"}).val(i(c.label)).addClass("form-control input-sm"),"anchor","Text")),c.hasOwnProperty("items")||"line"==c.type||g.append(j($("",{id:"url-update",type:"text"}).val(i(c.url)).addClass("form-control input-sm"),"url","URL")),window.console&&console.log(c),g.append(j($("",{id:"btnUpdate"}).addClass("btn btn-warning").text("Update"),"save","")),h.hide(),$("#btnUpdate").click(function(){"line"!=c.type&&(c.label=$("#label-update").val(),$("#url-update").val()?c.url=$("#url-update").val():null),h.show(),g.attr("class","col-md-2 well").html("Drop here to edit"),a.render()}))}},d={group:"nav",animation:0,ghostClass:"ghost",onAdd:function(b){var c=b.from.id,d=b.oldIndex,e=$("#trash");$(".pceuropa-dropmenu").click(),e.append($("",{type:"button",id:"cancel"}).addClass("btn btn-success").text("Cancel")).append($("",{type:"button",id:"delete"}).addClass("btn btn-danger").text("Delete")),$("#cancel").click(function(){e.html("Drop here to trash"),a.render()}),$("#delete").click(function(){if("left"==c||"right"==c)a.navbar[c][d]=a.config.prefixDelete;else{var b=a.sideNav(c);a.navbar[b][c[1]].items[d]=a.config.prefixDelete}e.html("Drop here to trash"),a.render()})}};Sortable.create(left,b),Sortable.create(right,b),Sortable.create(trash,d),Sortable.create(edit,c),function(){var d,c=0,e=a.arrayGroups();for(c=e.length;c--;)d=document.getElementById(e[c]),Sortable.create(d,b)}()},test:function(){for(var a=0;a<4;a++)this.addToMenu({type:"link",location:"left",label:"link"+a,url:"/menu/index"}),this.addToMenu({type:"dropmenu",location:"right",label:"DropMenu"+a,items:[]});this.addToMenu({type:"link",location:"r0",label:"link1",url:"/menu/index"}),this.addToMenu({type:"link",location:"r0",label:"link2",url:"/menu/index"}),this.addToMenu({type:"link",location:"r0",label:"link3",url:"/menu/index"}),this.navbar.left.move(0,3),this.navbar.right[0].items.move(0,1),this.navbar.right.move(3,1),this.render()}},{Menu:a}}(),Array.prototype.move=function(a,b){if(b>=this.length)for(var c=b-this.length;c--+1;)this.push(void 0);return this.splice(b,0,this.splice(a,1)[0]),this};
3 |
--------------------------------------------------------------------------------
/icons/Glyphicons.php:
--------------------------------------------------------------------------------
1 | $this->getGlyphClass($name)]
15 | );
16 |
17 | return sprintf("%s %s", $glyph, $text);
18 | }
19 |
20 | public function getAll()
21 | {
22 | return $this->glyphs;
23 | }
24 |
25 | private function getGlyphClass($name)
26 | {
27 | return sprintf('glyphicon glyphicon-%s', $name);
28 | }
29 |
30 | private $glyphs = [
31 | 'asterisk' => '\002a',
32 | 'plus' => '\002b',
33 | 'euro' => '\20ac',
34 | 'eur' => '\20ac',
35 | 'minus' => '\2212',
36 | 'cloud' => '\2601',
37 | 'envelope' => '\2709',
38 | 'pencil' => '\270f',
39 | 'glass' => '\e001',
40 | 'music' => '\e002',
41 | 'search' => '\e003',
42 | 'heart' => '\e005',
43 | 'star' => '\e006',
44 | 'star-empty' => '\e007',
45 | 'user' => '\e008',
46 | 'film' => '\e009',
47 | 'th-large' => '\e010',
48 | 'th' => '\e011',
49 | 'th-list' => '\e012',
50 | 'ok' => '\e013',
51 | 'remove' => '\e014',
52 | 'zoom-in' => '\e015',
53 | 'zoom-out' => '\e016',
54 | 'off' => '\e017',
55 | 'signal' => '\e018',
56 | 'cog' => '\e019',
57 | 'trash' => '\e020',
58 | 'home' => '\e021',
59 | 'file' => '\e022',
60 | 'time' => '\e023',
61 | 'road' => '\e024',
62 | 'download-alt' => '\e025',
63 | 'download' => '\e026',
64 | 'upload' => '\e027',
65 | 'inbox' => '\e028',
66 | 'play-circle' => '\e029',
67 | 'repeat' => '\e030',
68 | 'refresh' => '\e031',
69 | 'list-alt' => '\e032',
70 | 'lock' => '\e033',
71 | 'flag' => '\e034',
72 | 'headphones' => '\e035',
73 | 'volume-off' => '\e036',
74 | 'volume-down' => '\e037',
75 | 'volume-up' => '\e038',
76 | 'qrcode' => '\e039',
77 | 'barcode' => '\e040',
78 | 'tag' => '\e041',
79 | 'tags' => '\e042',
80 | 'book' => '\e043',
81 | 'bookmark' => '\e044',
82 | 'print' => '\e045',
83 | 'camera' => '\e046',
84 | 'font' => '\e047',
85 | 'bold' => '\e048',
86 | 'italic' => '\e049',
87 | 'text-height' => '\e050',
88 | 'text-width' => '\e051',
89 | 'align-left' => '\e052',
90 | 'align-center' => '\e053',
91 | 'align-right' => '\e054',
92 | 'align-justify' => '\e055',
93 | 'list' => '\e056',
94 | 'indent-left' => '\e057',
95 | 'indent-right' => '\e058',
96 | 'facetime-video' => '\e059',
97 | 'picture' => '\e060',
98 | 'map-marker' => '\e062',
99 | 'adjust' => '\e063',
100 | 'tint' => '\e064',
101 | 'edit' => '\e065',
102 | 'share' => '\e066',
103 | 'check' => '\e067',
104 | 'move' => '\e068',
105 | 'step-backward' => '\e069',
106 | 'fast-backward' => '\e070',
107 | 'backward' => '\e071',
108 | 'play' => '\e072',
109 | 'pause' => '\e073',
110 | 'stop' => '\e074',
111 | 'forward' => '\e075',
112 | 'fast-forward' => '\e076',
113 | 'step-forward' => '\e077',
114 | 'eject' => '\e078',
115 | 'chevron-left' => '\e079',
116 | 'chevron-right' => '\e080',
117 | 'plus-sign' => '\e081',
118 | 'minus-sign' => '\e082',
119 | 'remove-sign' => '\e083',
120 | 'ok-sign' => '\e084',
121 | 'question-sign' => '\e085',
122 | 'info-sign' => '\e086',
123 | 'screenshot' => '\e087',
124 | 'remove-circle' => '\e088',
125 | 'ok-circle' => '\e089',
126 | 'ban-circle' => '\e090',
127 | 'arrow-left' => '\e091',
128 | 'arrow-right' => '\e092',
129 | 'arrow-up' => '\e093',
130 | 'arrow-down' => '\e094',
131 | 'share-alt' => '\e095',
132 | 'resize-full' => '\e096',
133 | 'resize-small' => '\e097',
134 | 'exclamation-sign' => '\e101',
135 | 'gift' => '\e102',
136 | 'leaf' => '\e103',
137 | 'fire' => '\e104',
138 | 'eye-open' => '\e105',
139 | 'eye-close' => '\e106',
140 | 'warning-sign' => '\e107',
141 | 'plane' => '\e108',
142 | 'calendar' => '\e109',
143 | 'random' => '\e110',
144 | 'comment' => '\e111',
145 | 'magnet' => '\e112',
146 | 'chevron-up' => '\e113',
147 | 'chevron-down' => '\e114',
148 | 'retweet' => '\e115',
149 | 'shopping-cart' => '\e116',
150 | 'folder-close' => '\e117',
151 | 'folder-open' => '\e118',
152 | 'resize-vertical' => '\e119',
153 | 'resize-horizontal' => '\e120',
154 | 'hdd' => '\e121',
155 | 'bullhorn' => '\e122',
156 | 'bell' => '\e123',
157 | 'certificate' => '\e124',
158 | 'thumbs-up' => '\e125',
159 | 'thumbs-down' => '\e126',
160 | 'hand-right' => '\e127',
161 | 'hand-left' => '\e128',
162 | 'hand-up' => '\e129',
163 | 'hand-down' => '\e130',
164 | 'circle-arrow-right' => '\e131',
165 | 'circle-arrow-left' => '\e132',
166 | 'circle-arrow-up' => '\e133',
167 | 'circle-arrow-down' => '\e134',
168 | 'globe' => '\e135',
169 | 'wrench' => '\e136',
170 | 'tasks' => '\e137',
171 | 'filter' => '\e138',
172 | 'briefcase' => '\e139',
173 | 'fullscreen' => '\e140',
174 | 'dashboard' => '\e141',
175 | 'paperclip' => '\e142',
176 | 'heart-empty' => '\e143',
177 | 'link' => '\e144',
178 | 'phone' => '\e145',
179 | 'pushpin' => '\e146',
180 | 'usd' => '\e148',
181 | 'gbp' => '\e149',
182 | 'sort' => '\e150',
183 | 'sort-by-alphabet' => '\e151',
184 | 'sort-by-alphabet-alt' => '\e152',
185 | 'sort-by-order' => '\e153',
186 | 'sort-by-order-alt' => '\e154',
187 | 'sort-by-attributes' => '\e155',
188 | 'sort-by-attributes-alt' => '\e156',
189 | 'unchecked' => '\e157',
190 | 'expand' => '\e158',
191 | 'collapse-down' => '\e159',
192 | 'collapse-up' => '\e160',
193 | 'log-in' => '\e161',
194 | 'flash' => '\e162',
195 | 'log-out' => '\e163',
196 | 'new-window' => '\e164',
197 | 'record' => '\e165',
198 | 'save' => '\e166',
199 | 'open' => '\e167',
200 | 'saved' => '\e168',
201 | 'import' => '\e169',
202 | 'export' => '\e170',
203 | 'send' => '\e171',
204 | 'floppy-disk' => '\e172',
205 | 'floppy-saved' => '\e173',
206 | 'floppy-remove' => '\e174',
207 | 'floppy-save' => '\e175',
208 | 'floppy-open' => '\e176',
209 | 'credit-card' => '\e177',
210 | 'transfer' => '\e178',
211 | 'cutlery' => '\e179',
212 | 'header' => '\e180',
213 | 'compressed' => '\e181',
214 | 'earphone' => '\e182',
215 | 'phone-alt' => '\e183',
216 | 'tower' => '\e184',
217 | 'stats' => '\e185',
218 | 'sd-video' => '\e186',
219 | 'hd-video' => '\e187',
220 | 'subtitles' => '\e188',
221 | 'sound-stereo' => '\e189',
222 | 'sound-dolby' => '\e190',
223 | 'sound-5-1' => '\e191',
224 | 'sound-6-1' => '\e192',
225 | 'sound-7-1' => '\e193',
226 | 'copyright-mark' => '\e194',
227 | 'registration-mark' => '\e195',
228 | 'cloud-download' => '\e197',
229 | 'cloud-upload' => '\e198',
230 | 'tree-conifer' => '\e199',
231 | 'tree-deciduous' => '\e200',
232 | 'cd' => '\e201',
233 | 'save-file' => '\e202',
234 | 'open-file' => '\e203',
235 | 'level-up' => '\e204',
236 | 'copy' => '\e205',
237 | 'paste' => '\e206',
238 | 'alert' => '\e209',
239 | 'equalizer' => '\e210',
240 | 'king' => '\e211',
241 | 'queen' => '\e212',
242 | 'pawn' => '\e213',
243 | 'bishop' => '\e214',
244 | 'knight' => '\e215',
245 | 'baby-formula' => '\e216',
246 | 'tent' => '\26fa',
247 | 'blackboard' => '\e218',
248 | 'bed' => '\e219',
249 | 'apple' => '\f8ff',
250 | 'erase' => '\e221',
251 | 'hourglass' => '\231b',
252 | 'lamp' => '\e223',
253 | 'duplicate' => '\e224',
254 | 'piggy-bank' => '\e225',
255 | 'scissors' => '\e226',
256 | 'bitcoin' => '\e227',
257 | 'btc' => '\e227',
258 | 'xbt' => '\e227',
259 | 'yen' => '\00a5',
260 | 'jpy' => '\00a5',
261 | 'ruble' => '\20bd',
262 | 'rub' => '\20bd',
263 | 'scale' => '\e230',
264 | 'ice-lolly' => '\e231',
265 | 'ice-lolly-tasted' => '\e232',
266 | 'education' => '\e233',
267 | 'option-horizontal' => '\e234',
268 | 'option-vertical' => '\e235',
269 | 'menu-hamburger' => '\e236',
270 | 'modal-window' => '\e237',
271 | 'oil' => '\e238',
272 | 'grain' => '\e239',
273 | 'sunglasses' => '\e240',
274 | 'text-size' => '\e241',
275 | 'text-color' => '\e242',
276 | 'text-background' => '\e243',
277 | 'object-align-top' => '\e244',
278 | 'object-align-bottom' => '\e245',
279 | 'object-align-horizontal' => '\e246',
280 | 'object-align-left' => '\e247',
281 | 'object-align-vertical' => '\e248',
282 | 'object-align-right' => '\e249',
283 | 'triangle-right' => '\e250',
284 | 'triangle-left' => '\e251',
285 | 'triangle-bottom' => '\e252',
286 | 'triangle-top' => '\e253',
287 | 'console' => '\e254',
288 | 'superscript' => '\e255',
289 | 'subscript' => '\e256',
290 | 'menu-left' => '\e257',
291 | 'menu-right' => '\e258',
292 | 'menu-down' => '\e259',
293 | 'menu-up' => '\e260'
294 | ];
295 | }
--------------------------------------------------------------------------------
/assets/js/Sortable.min.js:
--------------------------------------------------------------------------------
1 | /*! Sortable 1.4.2 - MIT | git://github.com/rubaxa/Sortable.git */
2 | !function(a){"use strict";"function"==typeof define&&define.amd?define(a):"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=a():"undefined"!=typeof Package?Sortable=a():window.Sortable=a()}(function(){"use strict";function a(a,b){if(!a||!a.nodeType||1!==a.nodeType)throw"Sortable: `el` must be HTMLElement, and not "+{}.toString.call(a);this.el=a,this.options=b=r({},b),a[L]=this;var c={group:Math.random(),sort:!0,disabled:!1,store:null,handle:null,scroll:!0,scrollSensitivity:30,scrollSpeed:10,draggable:/[uo]l/i.test(a.nodeName)?"li":">*",ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",ignore:"a, img",filter:null,animation:0,setData:function(a,b){a.setData("Text",b.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1};for(var d in c)!(d in b)&&(b[d]=c[d]);V(b);for(var f in this)"_"===f.charAt(0)&&(this[f]=this[f].bind(this));this.nativeDraggable=b.forceFallback?!1:P,e(a,"mousedown",this._onTapStart),e(a,"touchstart",this._onTapStart),this.nativeDraggable&&(e(a,"dragover",this),e(a,"dragenter",this)),T.push(this._onDragOver),b.store&&this.sort(b.store.get(this))}function b(a){v&&v.state!==a&&(h(v,"display",a?"none":""),!a&&v.state&&w.insertBefore(v,s),v.state=a)}function c(a,b,c){if(a){c=c||N,b=b.split(".");var d=b.shift().toUpperCase(),e=new RegExp("\\s("+b.join("|")+")(?=\\s)","g");do if(">*"===d&&a.parentNode===c||(""===d||a.nodeName.toUpperCase()==d)&&(!b.length||((" "+a.className+" ").match(e)||[]).length==b.length))return a;while(a!==c&&(a=a.parentNode))}return null}function d(a){a.dataTransfer&&(a.dataTransfer.dropEffect="move"),a.preventDefault()}function e(a,b,c){a.addEventListener(b,c,!1)}function f(a,b,c){a.removeEventListener(b,c,!1)}function g(a,b,c){if(a)if(a.classList)a.classList[c?"add":"remove"](b);else{var d=(" "+a.className+" ").replace(K," ").replace(" "+b+" "," ");a.className=(d+(c?" "+b:"")).replace(K," ")}}function h(a,b,c){var d=a&&a.style;if(d){if(void 0===c)return N.defaultView&&N.defaultView.getComputedStyle?c=N.defaultView.getComputedStyle(a,""):a.currentStyle&&(c=a.currentStyle),void 0===b?c:c[b];b in d||(b="-webkit-"+b),d[b]=c+("string"==typeof c?"":"px")}}function i(a,b,c){if(a){var d=a.getElementsByTagName(b),e=0,f=d.length;if(c)for(;f>e;e++)c(d[e],e);return d}return[]}function j(a,b,c,d,e,f,g){var h=N.createEvent("Event"),i=(a||b[L]).options,j="on"+c.charAt(0).toUpperCase()+c.substr(1);h.initEvent(c,!0,!0),h.to=b,h.from=e||b,h.item=d||b,h.clone=v,h.oldIndex=f,h.newIndex=g,b.dispatchEvent(h),i[j]&&i[j].call(a,h)}function k(a,b,c,d,e,f){var g,h,i=a[L],j=i.options.onMove;return g=N.createEvent("Event"),g.initEvent("move",!0,!0),g.to=b,g.from=a,g.dragged=c,g.draggedRect=d,g.related=e||b,g.relatedRect=f||b.getBoundingClientRect(),a.dispatchEvent(g),j&&(h=j.call(i,g)),h}function l(a){a.draggable=!1}function m(){R=!1}function n(a,b){var c=a.lastElementChild,d=c.getBoundingClientRect();return(b.clientY-(d.top+d.height)>5||b.clientX-(d.right+d.width)>5)&&c}function o(a){for(var b=a.tagName+a.className+a.src+a.href+a.textContent,c=b.length,d=0;c--;)d+=b.charCodeAt(c);return d.toString(36)}function p(a){var b=0;if(!a||!a.parentNode)return-1;for(;a&&(a=a.previousElementSibling);)"TEMPLATE"!==a.nodeName.toUpperCase()&&b++;return b}function q(a,b){var c,d;return function(){void 0===c&&(c=arguments,d=this,setTimeout(function(){1===c.length?a.call(d,c[0]):a.apply(d,c),c=void 0},b))}}function r(a,b){if(a&&b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}var s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J={},K=/\s+/g,L="Sortable"+(new Date).getTime(),M=window,N=M.document,O=M.parseInt,P=!!("draggable"in N.createElement("div")),Q=function(a){return a=N.createElement("x"),a.style.cssText="pointer-events:auto","auto"===a.style.pointerEvents}(),R=!1,S=Math.abs,T=([].slice,[]),U=q(function(a,b,c){if(c&&b.scroll){var d,e,f,g,h=b.scrollSensitivity,i=b.scrollSpeed,j=a.clientX,k=a.clientY,l=window.innerWidth,m=window.innerHeight;if(z!==c&&(y=b.scroll,z=c,y===!0)){y=c;do if(y.offsetWidth=l-j)-(h>=j),g=(h>=m-k)-(h>=k),(f||g)&&(d=M)),(J.vx!==f||J.vy!==g||J.el!==d)&&(J.el=d,J.vx=f,J.vy=g,clearInterval(J.pid),d&&(J.pid=setInterval(function(){d===M?M.scrollTo(M.pageXOffset+f*i,M.pageYOffset+g*i):(g&&(d.scrollTop+=g*i),f&&(d.scrollLeft+=f*i))},24)))}},30),V=function(a){var b=a.group;b&&"object"==typeof b||(b=a.group={name:b}),["pull","put"].forEach(function(a){a in b||(b[a]=!0)}),a.groups=" "+b.name+(b.put.join?" "+b.put.join(" "):"")+" "};return a.prototype={constructor:a,_onTapStart:function(a){var b=this,d=this.el,e=this.options,f=a.type,g=a.touches&&a.touches[0],h=(g||a).target,i=h,k=e.filter;if(!("mousedown"===f&&0!==a.button||e.disabled)&&(h=c(h,e.draggable,d))){if(D=p(h),"function"==typeof k){if(k.call(this,a,h,this))return j(b,i,"filter",h,d,D),void a.preventDefault()}else if(k&&(k=k.split(",").some(function(a){return a=c(i,a.trim(),d),a?(j(b,a,"filter",h,d,D),!0):void 0})))return void a.preventDefault();(!e.handle||c(i,e.handle,d))&&this._prepareDragStart(a,g,h)}},_prepareDragStart:function(a,b,c){var d,f=this,h=f.el,j=f.options,k=h.ownerDocument;c&&!s&&c.parentNode===h&&(G=a,w=h,s=c,t=s.parentNode,x=s.nextSibling,F=j.group,d=function(){f._disableDelayedDrag(),s.draggable=!0,g(s,f.options.chosenClass,!0),f._triggerDragStart(b)},j.ignore.split(",").forEach(function(a){i(s,a.trim(),l)}),e(k,"mouseup",f._onDrop),e(k,"touchend",f._onDrop),e(k,"touchcancel",f._onDrop),j.delay?(e(k,"mouseup",f._disableDelayedDrag),e(k,"touchend",f._disableDelayedDrag),e(k,"touchcancel",f._disableDelayedDrag),e(k,"mousemove",f._disableDelayedDrag),e(k,"touchmove",f._disableDelayedDrag),f._dragStartTimer=setTimeout(d,j.delay)):d())},_disableDelayedDrag:function(){var a=this.el.ownerDocument;clearTimeout(this._dragStartTimer),f(a,"mouseup",this._disableDelayedDrag),f(a,"touchend",this._disableDelayedDrag),f(a,"touchcancel",this._disableDelayedDrag),f(a,"mousemove",this._disableDelayedDrag),f(a,"touchmove",this._disableDelayedDrag)},_triggerDragStart:function(a){a?(G={target:s,clientX:a.clientX,clientY:a.clientY},this._onDragStart(G,"touch")):this.nativeDraggable?(e(s,"dragend",this),e(w,"dragstart",this._onDragStart)):this._onDragStart(G,!0);try{N.selection?N.selection.empty():window.getSelection().removeAllRanges()}catch(b){}},_dragStarted:function(){w&&s&&(g(s,this.options.ghostClass,!0),a.active=this,j(this,w,"start",s,w,D))},_emulateDragOver:function(){if(H){if(this._lastX===H.clientX&&this._lastY===H.clientY)return;this._lastX=H.clientX,this._lastY=H.clientY,Q||h(u,"display","none");var a=N.elementFromPoint(H.clientX,H.clientY),b=a,c=" "+this.options.group.name,d=T.length;if(b)do{if(b[L]&&b[L].options.groups.indexOf(c)>-1){for(;d--;)T[d]({clientX:H.clientX,clientY:H.clientY,target:a,rootEl:b});break}a=b}while(b=b.parentNode);Q||h(u,"display","")}},_onTouchMove:function(b){if(G){a.active||this._dragStarted(),this._appendGhost();var c=b.touches?b.touches[0]:b,d=c.clientX-G.clientX,e=c.clientY-G.clientY,f=b.touches?"translate3d("+d+"px,"+e+"px,0)":"translate("+d+"px,"+e+"px)";I=!0,H=c,h(u,"webkitTransform",f),h(u,"mozTransform",f),h(u,"msTransform",f),h(u,"transform",f),b.preventDefault()}},_appendGhost:function(){if(!u){var a,b=s.getBoundingClientRect(),c=h(s),d=this.options;u=s.cloneNode(!0),g(u,d.ghostClass,!1),g(u,d.fallbackClass,!0),h(u,"top",b.top-O(c.marginTop,10)),h(u,"left",b.left-O(c.marginLeft,10)),h(u,"width",b.width),h(u,"height",b.height),h(u,"opacity","0.8"),h(u,"position","fixed"),h(u,"zIndex","100000"),h(u,"pointerEvents","none"),d.fallbackOnBody&&N.body.appendChild(u)||w.appendChild(u),a=u.getBoundingClientRect(),h(u,"width",2*b.width-a.width),h(u,"height",2*b.height-a.height)}},_onDragStart:function(a,b){var c=a.dataTransfer,d=this.options;this._offUpEvents(),"clone"==F.pull&&(v=s.cloneNode(!0),h(v,"display","none"),w.insertBefore(v,s)),b?("touch"===b?(e(N,"touchmove",this._onTouchMove),e(N,"touchend",this._onDrop),e(N,"touchcancel",this._onDrop)):(e(N,"mousemove",this._onTouchMove),e(N,"mouseup",this._onDrop)),this._loopId=setInterval(this._emulateDragOver,50)):(c&&(c.effectAllowed="move",d.setData&&d.setData.call(this,c,s)),e(N,"drop",this),setTimeout(this._dragStarted,0))},_onDragOver:function(a){var d,e,f,g=this.el,i=this.options,j=i.group,l=j.put,o=F===j,p=i.sort;if(void 0!==a.preventDefault&&(a.preventDefault(),!i.dragoverBubble&&a.stopPropagation()),I=!0,F&&!i.disabled&&(o?p||(f=!w.contains(s)):F.pull&&l&&(F.name===j.name||l.indexOf&&~l.indexOf(F.name)))&&(void 0===a.rootEl||a.rootEl===this.el)){if(U(a,i,this.el),R)return;if(d=c(a.target,i.draggable,g),e=s.getBoundingClientRect(),f)return b(!0),void(v||x?w.insertBefore(s,v||x):p||w.appendChild(s));if(0===g.children.length||g.children[0]===u||g===a.target&&(d=n(g,a))){if(d){if(d.animated)return;r=d.getBoundingClientRect()}b(o),k(w,g,s,e,d,r)!==!1&&(s.contains(g)||(g.appendChild(s),t=g),this._animate(e,s),d&&this._animate(r,d))}else if(d&&!d.animated&&d!==s&&void 0!==d.parentNode[L]){A!==d&&(A=d,B=h(d),C=h(d.parentNode));var q,r=d.getBoundingClientRect(),y=r.right-r.left,z=r.bottom-r.top,D=/left|right|inline/.test(B.cssFloat+B.display)||"flex"==C.display&&0===C["flex-direction"].indexOf("row"),E=d.offsetWidth>s.offsetWidth,G=d.offsetHeight>s.offsetHeight,H=(D?(a.clientX-r.left)/y:(a.clientY-r.top)/z)>.5,J=d.nextElementSibling,K=k(w,g,s,e,d,r);if(K!==!1){if(R=!0,setTimeout(m,30),b(o),1===K||-1===K)q=1===K;else if(D){var M=s.offsetTop,N=d.offsetTop;q=M===N?d.previousElementSibling===s&&!E||H&&E:N>M}else q=J!==s&&!G||H&&G;s.contains(g)||(q&&!J?g.appendChild(s):d.parentNode.insertBefore(s,q?J:d)),t=s.parentNode,this._animate(e,s),this._animate(r,d)}}}},_animate:function(a,b){var c=this.options.animation;if(c){var d=b.getBoundingClientRect();h(b,"transition","none"),h(b,"transform","translate3d("+(a.left-d.left)+"px,"+(a.top-d.top)+"px,0)"),b.offsetWidth,h(b,"transition","all "+c+"ms"),h(b,"transform","translate3d(0,0,0)"),clearTimeout(b.animated),b.animated=setTimeout(function(){h(b,"transition",""),h(b,"transform",""),b.animated=!1},c)}},_offUpEvents:function(){var a=this.el.ownerDocument;f(N,"touchmove",this._onTouchMove),f(a,"mouseup",this._onDrop),f(a,"touchend",this._onDrop),f(a,"touchcancel",this._onDrop)},_onDrop:function(b){var c=this.el,d=this.options;clearInterval(this._loopId),clearInterval(J.pid),clearTimeout(this._dragStartTimer),f(N,"mousemove",this._onTouchMove),this.nativeDraggable&&(f(N,"drop",this),f(c,"dragstart",this._onDragStart)),this._offUpEvents(),b&&(I&&(b.preventDefault(),!d.dropBubble&&b.stopPropagation()),u&&u.parentNode.removeChild(u),s&&(this.nativeDraggable&&f(s,"dragend",this),l(s),g(s,this.options.ghostClass,!1),g(s,this.options.chosenClass,!1),w!==t?(E=p(s),E>=0&&(j(null,t,"sort",s,w,D,E),j(this,w,"sort",s,w,D,E),j(null,t,"add",s,w,D,E),j(this,w,"remove",s,w,D,E))):(v&&v.parentNode.removeChild(v),s.nextSibling!==x&&(E=p(s),E>=0&&(j(this,w,"update",s,w,D,E),j(this,w,"sort",s,w,D,E)))),a.active&&((null===E||-1===E)&&(E=D),j(this,w,"end",s,w,D,E),this.save())),w=s=t=u=x=v=y=z=G=H=I=E=A=B=F=a.active=null)},handleEvent:function(a){var b=a.type;"dragover"===b||"dragenter"===b?s&&(this._onDragOver(a),d(a)):("drop"===b||"dragend"===b)&&this._onDrop(a)},toArray:function(){for(var a,b=[],d=this.el.children,e=0,f=d.length,g=this.options;f>e;e++)a=d[e],c(a,g.draggable,this.el)&&b.push(a.getAttribute(g.dataIdAttr)||o(a));return b},sort:function(a){var b={},d=this.el;this.toArray().forEach(function(a,e){var f=d.children[e];c(f,this.options.draggable,d)&&(b[a]=f)},this),a.forEach(function(a){b[a]&&(d.removeChild(b[a]),d.appendChild(b[a]))})},save:function(){var a=this.options.store;a&&a.set(this)},closest:function(a,b){return c(a,b||this.options.draggable,this.el)},option:function(a,b){var c=this.options;return void 0===b?c[a]:(c[a]=b,void("group"===a&&V(c)))},destroy:function(){var a=this.el;a[L]=null,f(a,"mousedown",this._onTapStart),f(a,"touchstart",this._onTapStart),this.nativeDraggable&&(f(a,"dragover",this),f(a,"dragenter",this)),Array.prototype.forEach.call(a.querySelectorAll("[draggable]"),function(a){a.removeAttribute("draggable")}),T.splice(T.indexOf(this._onDragOver),1),this._onDrop(),this.el=a=null}},a.utils={on:e,off:f,css:h,find:i,is:function(a,b){return!!c(a,b,a)},extend:r,throttle:q,closest:c,toggleClass:g,index:p},a.create=function(b,c){return new a(b,c)},a.version="1.4.2",a});
--------------------------------------------------------------------------------
/assets/js/menu.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | //Copyright (c) 2016-2017 Rafal Marguzewicz pceuropa.net
4 |
5 | var MyMENU = MyMENU || {};
6 | MyMENU = (function(){
7 |
8 | function Menu(o) {
9 | o.config = o.config || {};
10 | this.config = {
11 | prefixDelete: 'prefixDelete'
12 | };
13 | this.config.getMysql = o.config.getMysql || false;
14 | this.config.setMysql = o.config.setMysql || false;
15 | this.navbar = {
16 | left: [],
17 | right: []
18 | };
19 | this.navbar = this.mysql('get') || this.navbar;
20 | this.init();
21 | // this.test(); // uncomment to use function test example, with only this.config.getMysql false
22 | };
23 |
24 | Menu.prototype = {
25 | version: '2.1.3',
26 | operations: 0,
27 | location_selector: $("#location"),
28 | init: function () {
29 | var menu = this;
30 |
31 | $('#type').on( 'change', function (){
32 | var divs = $('#url-box, #anchor-box, #icon-box')
33 | menu.location_selector.empty().append(menu.locations());
34 | divs.show();
35 |
36 | switch(true) {
37 | case ($(this).val() == 'dropmenu'):
38 | $('#url-box').hide();
39 | break;
40 | case ($(this).val() == 'line'):
41 | divs.hide();
42 | break;
43 | default:
44 | divs.show();
45 | }
46 | });
47 |
48 | menu.location_selector.on( 'change', function (){
49 | var selector = '#' + $(this).val();
50 | $(selector).css({border: '0 solid #f37736'})
51 | .animate({ borderWidth: 1,}, 3000, 'swing', function () {
52 | $(selector).animate({ borderWidth: 0 }, 1000);
53 | });
54 | });
55 |
56 | $("#menu-create").click(function(){
57 | menu.mysql('set');
58 | });
59 |
60 | $("#add").click(function(){
61 | var o = menu.sourceElement();
62 |
63 | menu.addToMenu(o);
64 | });
65 | },
66 | addToMenu: function (o) {
67 | var o = o || {type: 'link', location: 'left', label: 'error', url: '/menu/index', icon: ''}, data = {};
68 | o.side = this.sideNav(o.location);
69 |
70 | switch(o.type) {
71 | case 'link':
72 | data = {'label': o.label, 'url': o.url, 'icon': o.icon, 'type' : 'link'}
73 | if(o.location == 'left' || o.location == 'right'){
74 | this.navbar[o.location].push(data);
75 | } else {
76 | this.navbar[o.side][o.location[1]].items.push(data);
77 | }
78 | break;
79 | case 'dropmenu': this.navbar[o.location].push({'label': o.label, 'items': [], 'icon': o.icon, type : 'dropmenu'}); break;
80 | case 'line': this.navbar[o.side][o.location[1]].items.push({type : 'line', 'label' : ''}); break;
81 | default: window.console && console.log('error side');
82 | }
83 |
84 | this.render();
85 | },
86 | mysql: function(action) {
87 |
88 | var menu = this, action = action || 'get', data = {}, fn;
89 |
90 | if(action == 'get' ){
91 | if(!this.config.getMysql){return false;}
92 |
93 | window.console && console.log(action);
94 |
95 | $.getJSON( document.URL, function( data ) {
96 | menu.navbar = JSON.parse(data.menu);
97 | menu.render();
98 | });
99 |
100 | } else {
101 |
102 | if(this.operations == 0){
103 | menu.operations++;
104 | return false;
105 | }
106 |
107 | $.ajax({
108 | url: document.URL,
109 | type: 'post',
110 | dataType:'JSON',
111 | data: { update: true, _csrf : menu.csrfToken, menu: JSON.stringify(menu.navbar, null, 4) },
112 | success: function (r) {
113 | if (r.success === false) {window.console && console.log(r.message);}
114 | if (r.success === true) {
115 |
116 | window.console && console.log(menu.operations +'. save correct');
117 | menu.afterSuccessSave();
118 | menu.operations++;
119 |
120 | }
121 | },
122 | error: function (XMLHttpRequest, textStatus, errorThrown) {
123 | alert(textStatus);
124 | }
125 | });
126 | }
127 |
128 |
129 | },
130 |
131 | afterSuccessSave: function () {
132 | var add = $("#add"), html = add.html();
133 |
134 | window.setTimeout(function() {
135 | add.prop('disabled', true ).text('Menu saved correctly');
136 | }, 111)
137 |
138 | window.setTimeout(function() {
139 | add.prop('disabled', false ).html(html);
140 | }, 1111)
141 | },
142 |
143 | filter: function () {
144 | var menu = this;
145 |
146 | function del(el) {
147 | return el !== menu.config.prefixDelete;
148 | }
149 |
150 | function line(el) {
151 | return el.type !== "line";
152 | }
153 |
154 | function label(el) {
155 | return el.label !== undefined || typeof el === "string" ;
156 | }
157 |
158 | this.navbar.left = this.navbar.left.filter(del).filter(line).filter(label);
159 | this.navbar.right = this.navbar.right.filter(del).filter(line).filter(label);
160 |
161 | for (var i = this.navbar.left.length; i--;) {
162 | if (this.navbar.left[i].hasOwnProperty('items')){
163 | this.navbar.left[i].items = this.navbar.left[i].items.filter(del).filter(label)
164 | }
165 | }
166 |
167 | for (var i = this.navbar.right.length; i--;) {
168 | if (this.navbar.right[i].hasOwnProperty('items')){
169 | this.navbar.right[i].items = this.navbar.right[i].items.filter(del).filter(label);
170 | }
171 | }
172 |
173 | },
174 |
175 | render: function () {
176 | window.console && console.log('render');
177 | this.filter();
178 |
179 | $("#left").empty().append(this.renderNavbar('left'));
180 | $("#right").empty().append(this.renderNavbar('right'));
181 | console.log(this.locations());
182 |
183 | this.location_selector.empty().append(this.locations());
184 | this.sort();
185 |
186 | if(this.config.setMysql){
187 | this.mysql('set');
188 | }
189 |
190 | },
191 |
192 | jsonPreview: function () {
193 | $("#code code").text(JSON.stringify(this.navbar, null, 4))
194 | },
195 |
196 | locations: function () {
197 | var type = $("#type").val(),
198 | locations = ''+
199 | '';
200 |
201 | if(type != 'dropmenu'){
202 |
203 | if(type == 'line'){
204 | locations = '';
205 | }
206 |
207 | for (var i = 0; i < this.navbar.left.length; i++) {
208 | if (this.navbar.left[i].hasOwnProperty('items')){
209 | locations += '';
210 | }
211 | }
212 |
213 | for (var i = 0; i < this.navbar.right.length; i++) {
214 | if (this.navbar.right[i].hasOwnProperty('items')){
215 | locations += '';
216 | }
217 | }
218 | }
219 |
220 | return locations;
221 | },
222 | renderNavbar : function (side) {
223 | var navbar = $('#' + side), o = this.navbar[side], self = this;
224 |
225 | $.map(o, function(el, indx){
226 | switch (el.type) {
227 | case 'dropmenu' :
228 | navbar.append(self.dropmenu(el, side[0] + indx));
229 | break;
230 | case 'link' :
231 | navbar.append(self.link(el));
232 | break;
233 | case 'line' :
234 | navbar.append(self.divider(el));
235 | break;
236 | default:
237 | window.console && console.log('Element type error');
238 | }
239 | });
240 |
241 | return navbar;
242 | },
243 |
244 | icon: function(name)
245 | {
246 | var el = '';
247 | if (name) {
248 | el = $('').addClass('glyphicon').addClass('glyphicon-' + name);
249 | }
250 | return el;
251 | },
252 | divider: function(o) {
253 | var el = $('');
254 | el.addClass('divider');
255 | return el;
256 | },
257 | link: function (o) {
258 | var lnk = $('', {'href' : o.url}).text(o.label);
259 |
260 | lnk.prepend(this.icon(o.icon));
261 |
262 | var el = $('')
263 | .append(lnk);
264 |
265 | return el;
266 | },
267 | dropmenu: function (o, key) {
268 | var el,
269 | links = $('', {id: key})
270 | .addClass('dropdown-menu'),
271 | self = this;
272 |
273 | $.map(o.items, function(el){
274 | links.append(
275 | self.link(el)
276 | );
277 | });
278 |
279 | el = $('')
280 | .addClass('pceuropa-dropmenu')
281 | .attr('data-dropmenu', 'true');
282 |
283 | el.append(
284 | $('')
285 | .addClass('dropdown-toggle')
286 | .attr('data-toggle', 'dropdown')
287 | .attr('draggable', 'false')
288 | .attr('aria-expanded', 'false')
289 | .text(o.label)
290 | .prepend(this.icon(o.icon))
291 | .append($('').addClass('caret'))
292 | );
293 |
294 | el.append(links);
295 | return el;
296 | },
297 |
298 | previewTest: function (){
299 | return ['normal', 'json', 'yii2'];
300 | },
301 | arrayGroups: function () { // join array navbar.left[] nad navbar.right[]
302 | var array = [], i = 0;
303 |
304 | for (i = this.navbar.left.length; i--;) {
305 | if (this.navbar.left[i].hasOwnProperty('items')){
306 | array.push('l' + i);
307 | }
308 | }
309 |
310 | for (i = this.navbar.right.length; i--;) {
311 | if (this.navbar.right[i].hasOwnProperty('items')){
312 | array.push('r' + i);
313 | }
314 | }
315 | return array || [];
316 | },
317 | sourceElement: function(){
318 | var o = {};
319 |
320 | $('#inputsData input, #inputsData select').filter(function() {
321 | return this.value.length !== 0;
322 | }).each(function() {
323 | o[this.id] = $(this).val();
324 | });
325 |
326 | return o;
327 | },
328 | sideNav: function (e){
329 | return e[0] == 'r' ? 'right' : 'left';
330 | },
331 |
332 |
333 | sort: function(){
334 | var menu = this,
335 | config = {
336 | group: "nav",
337 | animation: 0,
338 | ghostClass: "ghost",
339 | onMove: function (/**Event*/evt) {
340 | var gr = evt.from.id , newGr = evt.target.id, index = evt.oldIndex, newIndex = evt.newIndex;
341 |
342 | if(evt.dragged.dataset.dropmenu != 'true'){
343 | $('.pceuropa-dropmenu').addClass('open');
344 | }
345 |
346 |
347 | // return false; — for cancel
348 | },
349 |
350 | onUpdate: function (evt) {
351 | var gr = evt.from.id, index = evt.oldIndex, newIndex = evt.newIndex, side = 'left';
352 |
353 | if(gr == 'left' || gr == 'right'){
354 | menu.navbar[gr].move(index, newIndex);
355 | } else {
356 | side = menu.sideNav(gr);
357 | menu.navbar[side][gr[1]].items.move(index, newIndex);
358 | }
359 | setTimeout(menu.render(), 300);
360 | },
361 |
362 | onAdd: function (evt) {
363 | var gr = evt.from.id , newGr = evt.target.id, index = evt.oldIndex, newIndex = evt.newIndex, objToMove = {}, o = {},
364 | clone = function(o) { // this clone() not need deepclone
365 |
366 | var clone = {};
367 |
368 | if(typeof o === 'string' || o instanceof String){
369 | clone = o;
370 | return clone;
371 | }
372 |
373 |
374 | for (var prop in o){
375 | clone[prop] = o[prop];
376 | }
377 | return clone
378 | };
379 |
380 | if(gr == 'left' || gr == 'right'){
381 | objToMove = clone(menu.navbar[gr][index]);
382 | menu.navbar[gr][index] = menu.config.prefixDelete; // marking the item to Deleted
383 | } else {
384 | var side = menu.sideNav(gr);
385 | objToMove = clone(menu.navbar[side][gr[1]].items[index]);
386 | menu.navbar[side][gr[1]].items[index] = menu.config.prefixDelete; // marking the item to Deleted for filter method
387 | }
388 |
389 | if(newGr == 'left' || newGr == 'right'){
390 | o = menu.navbar[newGr];
391 | } else {
392 | var side = menu.sideNav(newGr);
393 | o = menu.navbar[side][newGr[1]].items;
394 | }
395 | o.splice(newIndex, 0, objToMove); // move object of menu to new location
396 | setTimeout(menu.render(), 300);
397 | }
398 | }, // end config
399 | configEdit = {
400 | group: "nav",
401 | onAdd: function (evt) {
402 | var o = {},
403 | gr = evt.from.id,
404 | side = menu.sideNav(gr),
405 | index = evt.oldIndex,
406 | editDiv = $("#edit"),
407 | formAndTrashDiv = $("#inputsData, #trash"),
408 | valueAttr = function (val) {
409 | return val ? val : '';
410 | },
411 | wrapItem = function(item, id, labelText){
412 | var wrap = $('', {'id' : id + '-box-update'}).addClass('form-group'),
413 | label = $('').addClass('col-sm-3 control-label').text(labelText),
414 | div = $('').addClass('col-sm-8');
415 |
416 | return wrap.append(label).append(div.append(item));
417 |
418 | };
419 | // window.console && console.log({gr: evt.from.id, index: evt.oldIndex}); // preview data do test
420 |
421 | $('.pceuropa-dropmenu').click();
422 | o = (gr == 'left' || gr == 'right') ? menu.navbar[gr][index] : menu.navbar[side][gr[1]].items[index];
423 |
424 | if (o.type == 'line')
425 | {
426 | return;
427 | }
428 |
429 | editDiv.attr('class', 'col-md-8 form-horizontal well');
430 |
431 | editDiv.append(
432 | wrapItem(
433 | $('', {'id' : 'label-update', 'type' : 'text'})
434 | .val(valueAttr(o.label))
435 | .addClass('form-control input-sm'),
436 | 'anchor',
437 | 'Text'
438 | )
439 | );
440 |
441 | if (!o.hasOwnProperty('items') && o.type != 'line')
442 | {
443 | editDiv.append(
444 | wrapItem(
445 | $('', {id : 'url-update', type : 'text'})
446 | .val(valueAttr(o.url))
447 | .addClass('form-control input-sm'),
448 | 'url',
449 | 'URL'
450 | )
451 | );
452 | }
453 |
454 | window.console && console.log(o);
455 |
456 | editDiv.append(
457 | wrapItem(
458 | $('', {id : 'btnUpdate'})
459 | .addClass('btn btn-warning')
460 | .text('Update'),
461 | 'save',
462 | ''
463 | )
464 | );
465 |
466 | formAndTrashDiv.hide();
467 |
468 | $("#btnUpdate").click(function(){
469 | if (o.type != 'line')
470 | {
471 | o.label = $("#label-update").val();
472 | $("#url-update").val() ? o.url = $("#url-update").val() : null;
473 | }
474 |
475 | formAndTrashDiv.show();
476 | editDiv.attr('class', 'col-md-2 well').html('Drop here to edit');
477 | menu.render();
478 |
479 | });
480 | } // end onAdd()
481 |
482 | }, // end config edit
483 | configTrash = {
484 | group: "nav",
485 | animation: 0,
486 | ghostClass: "ghost",
487 |
488 | onAdd: function (/**Event*/evt) {
489 | var gr = evt.from.id, index = evt.oldIndex, trash = $("#trash");
490 | $('.pceuropa-dropmenu').click();
491 | trash
492 | .append($('', {type: 'button', 'id': 'cancel'}).addClass('btn btn-success').text('Cancel'))
493 | .append($('', {type: 'button', 'id': 'delete'}).addClass('btn btn-danger').text('Delete'));
494 |
495 | $("#cancel").click(function(){
496 | trash.html('Drop here to trash');
497 | menu.render();
498 | });
499 |
500 | $("#delete").click(function(){
501 |
502 | if(gr == 'left' || gr == 'right'){
503 | menu.navbar[gr][index] = menu.config.prefixDelete; // marking the item to Deleted
504 | } else {
505 | var side = menu.sideNav(gr);
506 | menu.navbar[side][gr[1]].items[index] = menu.config.prefixDelete; // marking the item to Deleted
507 | };
508 | trash.html('Drop here to trash');
509 | menu.render();
510 | });
511 | },
512 | }; // end config trash
513 |
514 |
515 | Sortable.create(left, config);
516 | Sortable.create(right, config);
517 | Sortable.create(trash, configTrash);
518 | Sortable.create(edit, configEdit);
519 | (function() {
520 | var i = 0, id, array = menu.arrayGroups();
521 | for (i = array.length; i--;) {
522 | id = document.getElementById(array[i]);
523 | Sortable.create(id, config);
524 | }
525 | })();
526 |
527 | },
528 | test: function () {
529 | for (var i = 0; i < 4; i++) {
530 | this.addToMenu({type: 'link', location: 'left', label: 'link'+i, url: '/menu/index'});
531 | this.addToMenu({type: 'dropmenu', location: 'right', label: 'DropMenu'+i, items: []});
532 | }
533 | this.addToMenu({type: 'link', location: 'r0', label: 'link1', url: '/menu/index'});
534 | this.addToMenu({type: 'link', location: 'r0', label: 'link2', url: '/menu/index'});
535 | this.addToMenu({type: 'link', location: 'r0', label: 'link3', url: '/menu/index'});
536 |
537 | this.navbar.left.move(0, 3);
538 | this.navbar['right'][0].items.move(0, 1);
539 | this.navbar.right.move(3, 1);
540 | this.render();
541 | }
542 |
543 | };// end menu.prototype
544 |
545 | return {
546 | Menu: Menu,
547 | }
548 |
549 | })();
550 |
551 | Array.prototype.move = function (oldIndex, newIndex) {
552 | if (newIndex >= this.length) {
553 | var k = newIndex - this.length;
554 | while ((k--) + 1) {
555 | this.push(undefined);
556 | }
557 | }
558 | this.splice(newIndex, 0, this.splice(oldIndex, 1)[0]);
559 | return this; // for testing purposes
560 | };
561 |
--------------------------------------------------------------------------------